diff --git a/.gitignore b/.gitignore
index 68136f8be070c507f06fc835f6b646660bdffdb7..156016aab9ca7cd1aabb380eb0ecd78ba2cda2c0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -58,6 +58,7 @@ Debug
 /deployment/win/create_archive.bat
 /install_manifest.txt
 /modules/gui/src/module_config.hh
+/modules/base/pymod/__init__.py
 /modules/gui/src/dngr.qrc.depends
 *_out.csv
 *_out.tab
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index af007259420189de595538d71a69c4e3aea0bde0..dbfdc8e3e7a6ef0e30130c38408616a0c2af468b 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,5 +1,43 @@
-Changes in Release 1.2.2
+Changes in Release 1.4
+--------------------------------------------------------------------------------
+
+  * Feasibility check set to off by default, atoms in compounds are now connected
+    by the Builder irrespective of the distance between them
+  * Speed improvement for bracketed within selections up to a factor of 20
+
+Changes In Release 1.3.1
+--------------------------------------------------------------------------------
+
+  * Export missing default argument for AligmentHandle.ToString
+  * Automatically attach entity view in SequenceFromChain
+  * Export GetMatchingBackboneViews to Python
+  * Fix compilation with boost 1.33.1
+  * Allow renumbering of single chain
+
+Changes In Release 1.3.0
+--------------------------------------------------------------------------------
+
+  * Scene background can now be set to a gradient or an image
+  * Better Handling of HSV colors
+  * Table: direct access to columns tab['x'] is also available as tab.x
+  * Table: Export to ConTeXt and HTML tables
+  * Table: Barplot interface
+  * The BLAST binding supports newer versions of BLAST
+  * Bindings for CAD score
+  * Update directory layout of OST to be more conformant with the site-package
+    system of Python: Instead of storing the modules in lib{64}/ost/ost, they
+    are now in lib{64}/python{{VERSION}}/site-packages/ost
+  * Added molck, the molecular checker. A small command-line tool to clean PDB 
+    files, e.g. remove atoms with zero occupancy, "virtual atoms", hydrogens 
+    etc.
+
+Changes In Release 1.2.3
+--------------------------------------------------------------------------------
 
+  * PDBWriter: Prevent writing of out-of-bounds atom coordinates.
+
+Changes in Release 1.2.2
+--------------------------------------------------------------------------------
   * Fixed loop indentation in the PDBize function for bio units, leading to
     exponential running time/ memory consumption. This problem only affected a
     fraction of PDB entries.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 08d517d1b6384426a4a4088a7f7a2aba23d92e15..3dfaa4b7ae39b6dd6118ad35aa299378e30ccfd4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,8 +5,8 @@
 cmake_minimum_required(VERSION 2.6.4 FATAL_ERROR)
 project(OpenStructure CXX C)
 set (OST_VERSION_MAJOR 1)
-set (OST_VERSION_MINOR 2)
-set (OST_VERSION_PATCH 2)
+set (OST_VERSION_MINOR 3)
+set (OST_VERSION_PATCH 1)
 set (OST_VERSION_STRING ${OST_VERSION_MAJOR}.${OST_VERSION_MINOR}.${OST_VERSION_PATCH} )
 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake_support)
 include(OST)
@@ -183,6 +183,9 @@ if (ENABLE_STATIC AND UNIX AND NOT APPLE)
 endif()
 
 setup_boost()
+if (WIN32)
+   ADD_DEFINITIONS("-DBOOST_ALL_NO_LIB")
+endif()
 
 if (ENABLE_INFO)        
   find_package(Qt4 4.5.0 REQUIRED)
diff --git a/cmake_support/CopyDependencies.cmake b/cmake_support/CopyDependencies.cmake
index ae48aaa8867e499c9cda736aaae59132496c0a87..60f399430c3936f7e503af33c278a3a61c045bc3 100644
--- a/cmake_support/CopyDependencies.cmake
+++ b/cmake_support/CopyDependencies.cmake
@@ -240,7 +240,9 @@ function(resolve_item context item exepath resolved_item_var)
     string(REPLACE "@loader_path" "${contextpath}" resolved_item "${resolved_item}")
   endif(resolved_item MATCHES "@loader_path")
   
-  get_filename_component(resolved_item "${resolved_item}" REALPATH)
+  if(NOT WIN32)
+    get_filename_component(resolved_item "${resolved_item}" REALPATH)
+  endif(NOT WIN32)
 
   if(IS_ABSOLUTE "${resolved_item}" AND EXISTS "${resolved_item}")
     set(${resolved_item_var} "${resolved_item}" PARENT_SCOPE)
@@ -248,12 +250,14 @@ function(resolve_item context item exepath resolved_item_var)
   endif(IS_ABSOLUTE "${resolved_item}" AND EXISTS "${resolved_item}")
 
   set(ri "ri-NOTFOUND")
-  find_file(ri "${item}" ${exepath}  NO_DEFAULT_PATH)
-  find_file(ri "${item}" ${exepath}  /usr/lib)
-  if(WIN32 AND NOT UNIX)
+  if(UNIX AND NOT WIN32)
+    find_file(ri "${item}" ${exepath}  NO_DEFAULT_PATH)
+    find_file(ri "${item}" ${exepath}  /usr/lib)
+  else(UNIX AND NOT WIN32)
     find_program(ri "${item}" PATHS "${exepath}" NO_DEFAULT_PATH)
+    find_program(ri "${item}" PATHS "${CMAKE_INSTALL_PREFIX}/bin" NO_DEFAULT_PATH)
     find_program(ri "${item}" PATHS "${exepath}")
-  endif(WIN32 AND NOT UNIX)
+  endif(UNIX AND NOT WIN32)
   if(ri)
     set(resolved_item "${ri}")
     set(ri "ri-NOTFOUND")
@@ -277,7 +281,11 @@ function(resolve_embedded_item item resolved_item_var)
   else(${item} MATCHES ${CMAKE_INSTALL_PREFIX})
     # only embed libraries, therefore put into lib dir
     get_filename_component(item_name "${item}" NAME)
-    set(${resolved_item_var} "${CMAKE_INSTALL_PREFIX}/${LIB_DIR}/${item_name}" PARENT_SCOPE)
+    if(WIN32 AND NOT UNIX)
+      set(${resolved_item_var} "${CMAKE_INSTALL_PREFIX}/bin/${item_name}" PARENT_SCOPE)
+    else(WIN32 AND NOT UNIX)
+      set(${resolved_item_var} "${CMAKE_INSTALL_PREFIX}/${LIB_DIR}/${item_name}" PARENT_SCOPE)
+    endif(WIN32 AND NOT UNIX)
   endif(${item} MATCHES ${CMAKE_INSTALL_PREFIX})
 endfunction(resolve_embedded_item)
 
@@ -333,17 +341,19 @@ endfunction(change_install_names_for_item)
 #=============================================================================
 function(verify keys_var)
   foreach(key ${${keys_var}})
-    get_dependencies_for_item("${${key}_RESOLVED_EMBEDDED_ITEM}" dependencies)
-    get_filename_component(exepath ${${key}_RESOLVED_EMBEDDED_ITEM} PATH)
-    foreach(dep ${dependencies})
-      resolve_item( ${${key}_RESOLVED_EMBEDDED_ITEM} ${dep} exepath resolved_dep)
-      is_system_lib(${resolved_dep} system_flag)
-      if(NOT ${system_flag})
-        if(NOT ${resolved_dep} MATCHES ${CMAKE_INSTALL_PREFIX})
-          MESSAGE("Warning: item:'${${key}_RESOLVED_EMBEDDED_ITEM}' contains external dependency:'${resolved_dep}'")
-        endif(NOT ${resolved_dep} MATCHES ${CMAKE_INSTALL_PREFIX})
-      endif(NOT ${system_flag})
-    endforeach(dep)
+    if(NOT ${${key}_SYSTEMFLAG})
+      get_dependencies_for_item("${${key}_RESOLVED_EMBEDDED_ITEM}" dependencies)
+      get_filename_component(exepath ${${key}_RESOLVED_EMBEDDED_ITEM} PATH)
+      foreach(dep ${dependencies})
+        resolve_item( ${${key}_RESOLVED_EMBEDDED_ITEM} ${dep} exepath resolved_dep)
+        is_system_lib(${resolved_dep} system_flag)
+        if(NOT ${system_flag})
+          if(NOT ${resolved_dep} MATCHES ${CMAKE_INSTALL_PREFIX})
+            MESSAGE("Warning: item:'${${key}_RESOLVED_EMBEDDED_ITEM}' contains external dependency:'${resolved_dep}'")
+          endif(NOT ${resolved_dep} MATCHES ${CMAKE_INSTALL_PREFIX})
+        endif(NOT ${system_flag})
+      endforeach(dep)
+    endif(NOT ${${key}_SYSTEMFLAG})
   endforeach(key)
 endfunction(verify)
 
@@ -649,6 +659,28 @@ function(copy_resolved_item resolved_item resolved_embedded_item)
 
 endfunction(copy_resolved_item)
 
+#=============================================================================
+# function copy_python (OSX)
+#=============================================================================
+function(copy_python include_path version new_binary_path)
+
+
+  get_filename_component(real_python_include_path ${include_path} REALPATH)
+  get_filename_component(python_root_dir ${real_python_include_path}/../.. REALPATH) 
+  file(COPY ${python_root_dir}/${LIB_DIR}/python${version}/ DESTINATION ${CMAKE_INSTALL_PREFIX}/${LIB_DIR}/python${version})
+  file(GLOB  py_config_files "${include_path}/pyconfig*.h")
+  file(COPY ${py_config_files} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/python${version})
+  file(GLOB_RECURSE python_so_files "${CMAKE_INSTALL_PREFIX}/${LIB_DIR}/python${version}/*.so")
+  foreach(so_file ${python_so_files})
+    file(RPATH_REMOVE FILE "${so_file}")
+  endforeach(so_file)
+  read_config(ost_config)
+  file(COPY ${python_root_dir}/Resources/Python.app/Contents/MacOS/Python DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
+  set(${new_binary_path} "${CMAKE_INSTALL_PREFIX}/bin/Python" PARENT_SCOPE)
+  string(REGEX REPLACE "pyexec=\"[^\n\$]*\"" "pyexec=\"\$DNG_BINDIR/Python\"\nexport PYTHONHOME=\$DNG_ROOT" ost_config "${ost_config}")
+  write_config("${ost_config}")
+endfunction(copy_python)
+
 
 elseif(WIN32 AND NOT UNIX)
 
@@ -675,8 +707,19 @@ function(get_dependencies_for_item  item list_var)
   endif(NOT dumpbin_cmd)
 
   set(ENV{VS_UNICODE_OUTPUT} "") # Block extra output from inside VS IDE.
-  execute_process( COMMAND ${dumpbin_cmd}  /dependents ${item} OUTPUT_VARIABLE dumpbin_cmd_ov RESULT_VARIABLE retcode)
+  execute_process( COMMAND ${dumpbin_cmd}  /dependents ${item} OUTPUT_VARIABLE dumpbin_cmd_ov  ERROR_VARIABLE dumpbin_cmd_ev RESULT_VARIABLE retcode)
+  if(retcode)
+    if(${item} MATCHES "System32")
+      # 32 bit cmake might run within WOW64, which automatically mangles the path to System32
+      # dumpbin, which is x86_64 in this case will run with the unmangled path and therefore has to look for
+      # the 32 bit libraries in SysWOW64 instead of System32
+      string(REPLACE "System32" "SysWOW64" item ${item})
+      execute_process( COMMAND ${dumpbin_cmd}  /dependents ${item} OUTPUT_VARIABLE dumpbin_cmd_ov  ERROR_VARIABLE dumpbin_cmd_ev RESULT_VARIABLE retcode)
+    endif(${item} MATCHES "System32")
+  endif(retcode)
   if(retcode)
+    MESSAGE( "dumpbin output: '${dumpbin_cmd_ov}'")
+    MESSAGE( "dumpbin error output: '${dumpbin_cmd_ev}'")
     MESSAGE(FATAL_ERROR "dumpbin stopped with return code: '${retcode}'")
   endif(retcode)
   # Convert to a list of lines:
@@ -693,6 +736,7 @@ function(get_dependencies_for_item  item list_var)
       string(REGEX REPLACE "${dumpbin_regex}" "\\1" dep "${candidate}")
       list(APPEND dep_list ${dep})
     endif("${candidate}" MATCHES "${dumpbin_regex}")
+  endforeach(candidate)
   set(${list_var} ${dep_list} PARENT_SCOPE)
 endfunction(get_dependencies_for_item)
 
@@ -712,7 +756,7 @@ function(is_system_lib item system_var)
   string(REGEX REPLACE "\\\\" "/" sysroot "${sysroot}")
   string(TOLOWER "$ENV{windir}" windir)
   string(REGEX REPLACE "\\\\" "/" windir "${windir}")
-  if(lower MATCHES "^(${sysroot}/sys(tem|wow)|${windir}/sys(tem|wow)|(.*/)*msvc[^/]+dll)")
+  if(lower MATCHES "^(${sysroot}/sys(tem|wow)|${windir}/sys(tem|wow)|(.*/)*msvc[^/]+dll)" AND NOT lower MATCHES "python.*dll")
     set(${system_var}  1 PARENT_SCOPE)
   else()
     set(${system_var}  0 PARENT_SCOPE)
@@ -736,6 +780,52 @@ function(copy_resolved_item resolved_item resolved_embedded_item)
 
 endfunction(copy_resolved_item)
 
+#=============================================================================
+# function copy_python (Windows)
+#=============================================================================
+function(copy_python include_path version new_binary_path)
+  get_filename_component(real_python_include_path ${include_path} REALPATH)
+  get_filename_component(python_root_dir ${real_python_include_path}/.. REALPATH) 
+  file(GLOB  lib_files "${python_root_dir}/Lib/*")
+  file(COPY ${lib_files} DESTINATION ${CMAKE_INSTALL_PREFIX}/${LIB_DIR}/python${version})
+  file(GLOB  dll_files "${python_root_dir}/DLLs/*")
+  file(COPY ${dll_files} DESTINATION ${CMAKE_INSTALL_PREFIX}/${LIB_DIR}/python${version})
+  file(GLOB  py_config_files "${include_path}/pyconfig*.h")
+  file(COPY ${py_config_files} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/python${version})
+  file(COPY ${python_root_dir}/python.exe DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
+  set(${new_binary_path} "${CMAKE_INSTALL_PREFIX}/bin/python.exe" PARENT_SCOPE)
+  
+  # copy msvc90 CRT for python
+  get_filename_component(msvc90_dir "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\9.0;InstallDir]" ABSOLUTE)
+  get_filename_component(msvc90_express_dir "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\9.0;InstallDir]" ABSOLUTE)
+  find_path(msvc_redist_dir NAMES x86/Microsoft.VC90.CRT/Microsoft.VC90.CRT.manifest
+            PATHS
+            "${msvc90_dir}/../../VC/redist"
+            "${msvc90_express_dir}/../../VC/redist"
+            "C:/Program Files/Microsoft Visual Studio 9.0/VC/redist"
+            "C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/redist"
+    )
+  set(msvc90_crt_dir "${msvc_redist_dir}/x86/Microsoft.VC90.CRT")
+  file(COPY "${msvc90_crt_dir}/Microsoft.VC90.CRT.manifest"
+            "${msvc90_crt_dir}/msvcm90.dll"
+            "${msvc90_crt_dir}/msvcp90.dll"
+            "${msvc90_crt_dir}/msvcr90.dll"
+       DESTINATION "${CMAKE_INSTALL_PREFIX}/bin")
+
+endfunction(copy_python)
+
+#=============================================================================
+# function copy_qt (Windows)
+#=============================================================================
+function(copy_qt library_dir plugin_dir plugins)
+  file(COPY ${plugin_dir}
+       DESTINATION ${CMAKE_INSTALL_PREFIX}/libexec/openstructure) 
+  file(GLOB_RECURSE QT_PLUGINS "${CMAKE_INSTALL_PREFIX}/libexec/openstructure/*.dll")
+  set(${plugins} ${QT_PLUGINS} PARENT_SCOPE)
+  file(WRITE "${CMAKE_INSTALL_PREFIX}/libexec/openstructure/qt.conf" "[Paths]\nPlugins=../plugins\n")
+endfunction(copy_qt)
+
+
 elseif(UNIX)
 
 
@@ -877,8 +967,29 @@ function(copy_resolved_item resolved_item resolved_embedded_item)
 
 endfunction(copy_resolved_item)
 
+#=============================================================================
+# function copy_python (Linux)
+#=============================================================================
+function(copy_python include_path version new_binary_path)
 
 
+  get_filename_component(real_python_include_path ${include_path} REALPATH)
+  get_filename_component(python_root_dir ${real_python_include_path}/../.. REALPATH) 
+  file(COPY ${python_root_dir}/${LIB_DIR}/python${version}/ DESTINATION ${CMAKE_INSTALL_PREFIX}/${LIB_DIR}/python${version})
+  file(GLOB  py_config_files "${include_path}/pyconfig*.h")
+  file(COPY ${py_config_files} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/python${version})
+  file(GLOB_RECURSE python_so_files "${CMAKE_INSTALL_PREFIX}/${LIB_DIR}/python${version}/*.so")
+  foreach(so_file ${python_so_files})
+    file(RPATH_REMOVE FILE "${so_file}")
+  endforeach(so_file)
+  read_config(ost_config)
+  file(GLOB python_libs "${python_root_dir}/${LIB_DIR}/libpython${version}.so*")
+  file(COPY ${python_libs} DESTINATION ${CMAKE_INSTALL_PREFIX}/${LIB_DIR})
+  file(COPY ${python_root_dir}/bin/python${version} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
+  set(${new_binary_path} "${CMAKE_INSTALL_PREFIX}/bin/python${version}" PARENT_SCOPE)
+  string(REGEX REPLACE "pyexec=\"[^\n\$]*\"" "pyexec=\"\$DNG_BINDIR/python${version}\"\nexport PYTHONHOME=\$DNG_ROOT" ost_config "${ost_config}")
+  write_config("${ost_config}")
+endfunction(copy_python)
 
 
 #=============================================================================
diff --git a/cmake_support/FindPython.cmake b/cmake_support/FindPython.cmake
index c3b6f7dfdf3da9f18f05561be504928a52dfe2f3..702744428efb4d11abff9b354f8c84a4d7a0950e 100644
--- a/cmake_support/FindPython.cmake
+++ b/cmake_support/FindPython.cmake
@@ -47,7 +47,7 @@ macro(_find_python PYTHON_ROOT VERSION)
     find_library(PYTHON_LIBRARIES
       NAMES "python${_VERSION_NO_DOTS}" "python${VERSION}"
       HINTS "${PYTHON_ROOT}"
-      PATH_SUFFIXES lib
+      PATH_SUFFIXES lib libs
       NO_SYSTEM_ENVIRONMENT_PATH NO_DEFAULT_PATH
     )
     find_path(PYTHON_INCLUDE_PATH
@@ -72,7 +72,7 @@ macro(_find_python_bin PYTHON_ROOT VERSION)
   string(REPLACE "." "" _VERSION_NO_DOTS "${VERSION}")
   if(PYTHON_ROOT)
     find_program(PYTHON_BINARY
-      NAMES "python${_VERSION_NO_DOTS}" "python${VERSION}"
+      NAMES "python${_VERSION_NO_DOTS}" "python${VERSION}" python.exe
       HINTS "${PYTHON_ROOT}"
       PATH_SUFFIXES bin
       NO_SYSTEM_ENVIRONMENT_PATH NO_DEFAULT_PATH
diff --git a/cmake_support/OST.cmake b/cmake_support/OST.cmake
index fb478ec085f04136e2ec359fc5f8c460572742ff..07e4817b359642c23f93b41b1cf58592fa7e71f6 100644
--- a/cmake_support/OST.cmake
+++ b/cmake_support/OST.cmake
@@ -192,25 +192,20 @@ macro(module)
   # create library  
   #-----------------------------------------------------------------------------
   file(MAKE_DIRECTORY ${LIB_STAGE_PATH})
-  file(MAKE_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
+  file(MAKE_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
   file(MAKE_DIRECTORY ${LIBEXEC_STAGE_PATH})
   file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/tests")
   if (NOT TARGET create_stage)
     add_custom_target(create_stage COMMAND ${CMAKE_COMMAND} -E make_directory ${LIB_STAGE_PATH}
-                                   COMMAND ${CMAKE_COMMAND} -E make_directory ${EXECUTABLE_OUTPUT_PATH}
+                                   COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
                                    COMMAND ${CMAKE_COMMAND} -E make_directory ${LIBEXEC_STAGE_PATH}
                                    COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/tests")
   endif()
-  if (WIN32)
-    set(_ABS_FILE_PATTERN "^[A-Z]:/")
-  else()
-    set(_ABS_FILE_PATTERN "^/")
-  endif()
   if (_ARG_SOURCES)
     # when there is at least one source file, we build a library
     set(_ABS_SOURCE_NAMES)
     foreach(_SOURCE ${_ARG_SOURCES})
-      if (_SOURCE MATCHES ${_ABS_FILE_PATTERN})
+      if (IS_ABSOLUTE ${_SOURCE})
         list(APPEND _ABS_SOURCE_NAMES "${_SOURCE}")
       else()
         list(APPEND _ABS_SOURCE_NAMES "${CMAKE_CURRENT_SOURCE_DIR}/${_SOURCE}")
@@ -243,8 +238,7 @@ macro(module)
                             INSTALL_NAME_DIR "@rpath")
     endif()
     if (WIN32)
-      #set_target_properties(${_LIB_NAME} PROPERTIES PREFIX "../")
-      install(TARGETS ${_LIB_NAME} ARCHIVE DESTINATION "${LIB_DIR}")
+      install(TARGETS ${_LIB_NAME} RUNTIME DESTINATION bin)
     else()
       if (ENABLE_STATIC)
         install(TARGETS ${_LIB_NAME} ARCHIVE DESTINATION "${LIB_DIR}")
@@ -293,7 +287,9 @@ macro(stage_and_install_headers HEADERLIST HEADER_OUTPUT_DIR TARGET)
     set(_HDR_STAGE_DIR "${HEADER_OUTPUT_DIR}/${_DIR}")
     set(_FULL_HEADER_DIR "${HEADER_STAGE_PATH}/${_HDR_STAGE_DIR}")
     copy_if_different("" "${_FULL_HEADER_DIR}" "${_ABS_HEADER_NAMES}" "" "${TARGET}_headers")
-    install(FILES ${_ABS_HEADER_NAMES} DESTINATION "include/${_HDR_STAGE_DIR}")
+    if(NOT WIN32)
+      install(FILES ${_ABS_HEADER_NAMES} DESTINATION "include/${_HDR_STAGE_DIR}")
+    endif(NOT WIN32)
   endforeach()
 endmacro()
 
@@ -357,6 +353,12 @@ macro(executable_libexec)
   set_target_properties(${_ARG_NAME}
                         PROPERTIES RUNTIME_OUTPUT_DIRECTORY
                        "${LIBEXEC_STAGE_PATH}")  
+  set_target_properties(${_ARG_NAME}
+                        PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE
+                       "${LIBEXEC_STAGE_PATH}")  
+  set_target_properties(${_ARG_NAME}
+                        PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG
+                       "${LIBEXEC_STAGE_PATH}")  
   if (NOT _ARG_NO_RPATH AND NOT _ARG_STATIC)
     if (APPLE)
       set_target_properties(${_ARG_NAME} PROPERTIES
@@ -423,6 +425,7 @@ macro(script)
     if (NOT _ARG_INPUT)
       message(FATAL_ERROR "script() can only substitute when INPUT is present.")    
     endif()
+
     substitute(IN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${_INPUT}" OUT_FILE ${_ARG_NAME} 
                DICT ${_ARG_SUBSTITUTE})
   endif()
@@ -446,7 +449,7 @@ macro(ui_to_python LIBNAME PYMODDIR STAGEDIR)
   add_custom_target("${LIBNAME}_ui" ALL)
   add_dependencies("_${LIBNAME}" "${LIBNAME}_ui")
   find_program(_PYUIC_EXECUTABLE
-    NAMES pyuic4-${PYTHON_VERSION} pyuic4 pyuic
+    NAMES pyuic4-${PYTHON_VERSION} pyuic4 pyuic pyuic4.bat
     PATHS  ENV PATH 
   )  
   if(NOT _PYUIC_EXECUTABLE)
@@ -464,23 +467,26 @@ macro(ui_to_python LIBNAME PYMODDIR STAGEDIR)
                        )
     list(APPEND out_files ${_abs_out_file})
   endforeach()
-  compile_py_files(_${LIBNAME} ${STAGEDIR} ${out_files})
+  compile_py_files(_${LIBNAME} ${STAGEDIR} compiled_files ${out_files})
   install(FILES ${out_files} DESTINATION "${LIB_DIR}/${PYMODDIR}")
+  install(FILES ${compiled_files} DESTINATION "${LIB_DIR}/${PYMODDIR}")
 endmacro()
 
 #-------------------------------------------------------------------------------
 # Synopsis:
-#   compile_py_files(module out_files [input_file1 ...])
+#   compile_py_files(module out_dir compiled_files [input_file1 ...])
 # Description:
 #   Calls pyuic on every input file. The resulting python files are stored in
-#   the variable with name out_files.
+#   the variable with name compiled_files.
 #-------------------------------------------------------------------------------
-macro(compile_py_files module out_dir)
+macro(compile_py_files module out_dir compiled_files_name)
   set(_input_files ${ARGN})
+  set(${compiled_files_name})
   foreach(input_file ${_input_files})
     get_filename_component(_out_file ${input_file} NAME_WE)
     get_filename_component(_in_file ${input_file} ABSOLUTE)
     set(_out_file ${out_dir}/${_out_file}.pyc)
+    list(APPEND ${compiled_files_name} ${_out_file})
     get_filename_component(_in_name ${input_file} NAME)
     file(MAKE_DIRECTORY  ${out_dir})
     add_custom_command(TARGET ${module}
@@ -544,7 +550,11 @@ macro(pymod)
 
     set_target_properties("_${_LIB_NAME}"
                           PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PYMOD_STAGE_DIR})
- 
+    set_target_properties("_${_LIB_NAME}"
+                          PROPERTIES LIBRARY_OUTPUT_DIRECTORY_RELEASE ${PYMOD_STAGE_DIR})
+    set_target_properties("_${_LIB_NAME}"
+                          PROPERTIES LIBRARY_OUTPUT_DIRECTORY_DEBUG ${PYMOD_STAGE_DIR})
+
     if (NOT ENABLE_STATIC)
       if (_USE_RPATH)
         string(REGEX REPLACE "/[^/]*" "/.." inv_pymod_path "/${PYMOD_DIR}")
@@ -565,12 +575,8 @@ macro(pymod)
       set_target_properties("_${_LIB_NAME}"
                           PROPERTIES PREFIX "")
     else ()
-      set_target_properties("_${_LIB_NAME}"
-                          PROPERTIES PREFIX "../")
-
       set_target_properties("_${_LIB_NAME}"
                           PROPERTIES SUFFIX ".pyd")
-
     endif()
     install(TARGETS "_${_LIB_NAME}" LIBRARY DESTINATION
             "${LIB_DIR}/${PYMOD_DIR}")
@@ -604,7 +610,8 @@ macro(pymod)
       copy_if_different("./" "${PYMOD_STAGE_DIR}/${_DIR}"
                         "${_ABS_PY_FILES}" "TARGETS"
                         "${_PYMOD_TARGET}")
-      compile_py_files(_${_LIB_NAME} ${PYMOD_STAGE_DIR}/${_DIR} ${_ABS_PY_FILES})
+      compile_py_files(_${_LIB_NAME} ${PYMOD_STAGE_DIR}/${_DIR} compiled_files ${_ABS_PY_FILES})
+      install(FILES ${compiled_files} DESTINATION "${LIB_DIR}/${PYMOD_DIR}/${_DIR}")
     endforeach()
   endif()  
   get_target_property(_MOD_DEPS "${_PARENT_NAME}" MODULE_DEPS)
@@ -650,14 +657,20 @@ macro(ost_unittest)
       else()
         add_executable(${_test_name} EXCLUDE_FROM_ALL ${_SOURCES})
       endif()
+      set_target_properties(${_test_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/tests"  )
+      set_target_properties(${_test_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/tests"  )
+      set_target_properties(${_test_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/tests"  )
+
       if (WIN32)
         target_link_libraries(${_test_name} ${BOOST_UNIT_TEST_LIBRARIES} "${_ARG_PREFIX}_${_ARG_MODULE}")  
-        add_custom_target("${_test_name}_run":
-                        COMMAND ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${_test_name}.exe || echo
-                        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${CMAKE_BUILD_TYPE}/..
-                        COMMENT "running checks for module ${_ARG_MODULE}"
-                        DEPENDS ${_test_name})
-        add_test("${_test_name}" ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${_test_name}.exe)
+        #add_custom_target("${_test_name}_run":
+        #                COMMAND ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${_test_name}.exe || echo
+        #                WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${CMAKE_BUILD_TYPE}/..
+        #                COMMENT "running checks for module ${_ARG_MODULE}"
+        #                DEPENDS ${_test_name})
+        #add_test("${_test_name}" ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${_test_name}.exe)
+        #set_target_properties("${_test_name}_run" PROPERTIES EXCLUDE_FROM_ALL "1")
+        #add_dependencies(check "${_test_name}_run")
       else()
         target_link_libraries(${_test_name} ${BOOST_UNIT_TEST_LIBRARIES}
                             "${_ARG_PREFIX}_${_ARG_MODULE}")
@@ -672,30 +685,37 @@ macro(ost_unittest)
                         COMMENT "running checks for module ${_ARG_MODULE}"
                         DEPENDS ${_test_name})
         add_test("${_test_name}" ${CMAKE_CURRENT_BINARY_DIR}/${_test_name} )
+        add_dependencies(check_xml "${_test_name}_run_xml")
+        add_dependencies(check "${_test_name}_run")
       endif()
       
       if (_ARG_LINK)
         target_link_libraries("${_test_name}" ${_ARG_LINK})
       endif()
 
-      add_dependencies(check "${_test_name}_run")
-      add_dependencies(check_xml "${_test_name}_run_xml")
       set_target_properties(${_test_name}
                             PROPERTIES RUNTIME_OUTPUT_DIRECTORY
                             "${CMAKE_CURRENT_BINARY_DIR}")
-      if (WIN32)
-        set_target_properties("${_test_name}_run" PROPERTIES EXCLUDE_FROM_ALL "1")
-      endif()
     endif()
+
     foreach(py_test ${PY_TESTS})
       if(WIN32)
-        set (PY_TESTS_CMD "${EXECUTABLE_OUTPUT_PATH}/ost.bat")
-        add_custom_target("${py_test}_run"
-                  CALL "${PY_TESTS_CMD} ${CMAKE_CURRENT_SOURCE_DIR}/${py_test} || echo"
-                  WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-                  COMMENT "running checks ${py_test}" VERBATIM)
+        # todo fix python unit test running for Windows
+        #set (PY_TESTS_CMD "${EXECUTABLE_OUTPUT_PATH}/ost.bat")
+        #add_custom_target("${py_test}_run"
+        #          CALL "${PY_TESTS_CMD} ${CMAKE_CURRENT_SOURCE_DIR}/${py_test} || echo"
+        #          WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+        #          COMMENT "running checks ${py_test}" VERBATIM)
+        #set_target_properties("${py_test}_run" PROPERTIES EXCLUDE_FROM_ALL "1")
+        #add_dependencies("${py_test}_run" ost_scripts "_${_ARG_PREFIX}_${_ARG_MODULE}")
+        #add_dependencies(check "${py_test}_run")
       else()
-        set (PY_TESTS_CMD "${EXECUTABLE_OUTPUT_PATH}/ost")
+        set(python_path $ENV{PYTHONPATH})
+        if(python_path)
+          set(python_path "${python_path}:")
+        endif(python_path)
+        set(python_path "${python_path}${LIB_STAGE_PATH}/python${PYTHON_VERSION}/site-packages")
+        set (PY_TESTS_CMD "PYTHONPATH=${python_path}  ${PYTHON_BINARY}")
         add_custom_target("${py_test}_run"
                   sh -c "${PY_TESTS_CMD} ${CMAKE_CURRENT_SOURCE_DIR}/${py_test} || echo"
                   WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
@@ -704,13 +724,10 @@ macro(ost_unittest)
                   sh -c "${PY_TESTS_CMD} ${CMAKE_CURRENT_SOURCE_DIR}/${py_test} xml || echo"
                   WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
                   COMMENT "running checks ${py_test}" VERBATIM)
-      endif()
-      add_dependencies("${py_test}_run" ost_scripts "_${_ARG_PREFIX}_${_ARG_MODULE}")
-      add_dependencies("${py_test}_run_xml" ost_scripts "_${_ARG_PREFIX}_${_ARG_MODULE}")
-      add_dependencies(check "${py_test}_run")
-      add_dependencies(check_xml "${py_test}_run_xml")
-      if (WIN32)
-        set_target_properties("${py_test}_run" PROPERTIES EXCLUDE_FROM_ALL "1")
+        add_dependencies("${py_test}_run_xml" ost_scripts "_${_ARG_PREFIX}_${_ARG_MODULE}")
+        add_dependencies("${py_test}_run" ost_scripts "_${_ARG_PREFIX}_${_ARG_MODULE}")
+        add_dependencies(check "${py_test}_run")
+        add_dependencies(check_xml "${py_test}_run_xml")
       endif()
       
     endforeach()
@@ -801,7 +818,9 @@ endmacro()
 #-------------------------------------------------------------------------------
 macro(setup_stage)
   set(STAGE_DIR "${CMAKE_BINARY_DIR}/stage")
-  set(EXECUTABLE_OUTPUT_PATH ${STAGE_DIR}/bin  )
+  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${STAGE_DIR}/bin  )
+  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${STAGE_DIR}/bin  )
+  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${STAGE_DIR}/bin  )
   set(HEADER_STAGE_PATH ${STAGE_DIR}/include )
   set(SHARED_DATA_PATH ${STAGE_DIR}/share/openstructure  )
 
@@ -854,12 +873,12 @@ macro(setup_compiler_flags)
 
      add_definitions(-D_USE_MATH_DEFINES -D_CRT_SECURE_NO_DEPRECATE
                      -D_SCL_SECURE_NO_DEPRECATE -DNOMINMAX)
-     add_definitions(-Zc:wchar_t-)   #
+     #add_definitions(-Zc:wchar_t-)   #
     # add_definitions(-MDd -vmg -EHsc -GR)
     #GR:Uses the __fastcall calling convention (x86 only).
     #-EHsc to specify the synchronous exception handling mode/
     #-vmg Uses full generality for pointers to members.
-    add_definitions(-DBOOST_ZLIB_BINARY=zdll)
+    #add_definitions(-DBOOST_ZLIB_BINARY=zdll)
     #add_definitions(-NODEFAULTLIB:LIBCMTD.lib)
   endif()
 
diff --git a/deployment/CMakeLists.txt b/deployment/CMakeLists.txt
index 19d084aec2979e7d898f2dfaebb4cab60f1135d0..7f455981bfe56bf0d5b0f3f20f2221e9fd13aa64 100644
--- a/deployment/CMakeLists.txt
+++ b/deployment/CMakeLists.txt
@@ -24,7 +24,7 @@ if(${PROJECT_SOURCE_DIR} STREQUAL ${CMAKE_SOURCE_DIR})
   elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
     include(linux/CMakeLists.txt) 
   elseif(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
-    include(windows/CMakeLists.txt) 
+    include(win/CMakeLists.txt) 
   endif()
 
   INCLUDE(CPack) 
diff --git a/deployment/linux/create_bundle_centos5.py b/deployment/linux/create_bundle_centos5.py
new file mode 100644
index 0000000000000000000000000000000000000000..3200447770ffb48ea4080a7f4387e45ee59064b1
--- /dev/null
+++ b/deployment/linux/create_bundle_centos5.py
@@ -0,0 +1,162 @@
+import os
+import shutil
+import subprocess
+import string
+import sys
+import datetime
+import sip
+import PyQt4
+
+
+# parameters that can be modified
+qt4_plugins_location='/usr/lib/qt47/plugins'
+qt4_qmake_location='/usr/lib/qt47/bin/qmake'
+ssl_crypto_location='/lib/'
+chemlib_dictionary_location='/home/bundler/compounds.chemlib'
+list_of_excluded_libraries=[
+'ld-linux',
+'libexpat',
+'libgcc_s',
+'libglib',
+'cmov',
+'libice',
+'libdl',
+'libGLU',
+'libelf',
+'libpthread',
+'libstdc++',
+'libSM',
+'libX',
+'libg',
+'libGL.so',
+'libfontconfig',
+'libfreetype',
+'libdrm',
+'libxcb',
+'libICE',
+'libnvidia',
+'libc',
+'libuuid'
+]
+
+if len(sys.argv) < 2:
+  print 'usage: create_bundle.py  additional_label'
+  sys.exit()
+
+additional_label=sys.argv[1]
+
+currdir=os.getcwd()
+if currdir.find('deployment')==-1 or currdir.find('linux')==-1:
+  print '\n'
+  print 'ERROR: Please run this script from the deployment/linux directory'
+  print '\n'
+  sys.exit()
+
+print "WARNING: If this script does not run to completion, please run 'git reset --hard HEAD' in the main directory (two up from here) before restarting"
+
+system_python_version=sys.version_info
+system_python_executable='python'+str(system_python_version[0])+'.'+str(system_python_version[1])
+system_python_bin='/usr/bin/'+system_python_executable
+system_python_libs='/usr/lib/'+system_python_executable
+qt4_module_location=os.path.dirname(PyQt4.__file__)
+sip_module_location=os.path.dirname(sip.__file__)
+print '\n'
+print '\n'
+print 'Detecting architecture and revision'
+uname_output=subprocess.Popen('uname -a', shell=True, cwd='../../',stdout=subprocess.PIPE).stdout
+uname_line=uname_output.readlines()
+if uname_line[0].find('x86_64') !=-1:
+  libdir='lib64'
+  archstring='64bit'
+else: 
+  libdir='lib'
+  archstring='32bit'
+directory_name='openstructure-linux-'+archstring+'-'+additional_label
+print 'Hardcoding package python binary path in openstructure executables'
+subprocess.call('rm -f scripts/ost_config.in.pre* scripts/ost_config.in.backup',shell=True,cwd='../../')
+subprocess.call('mv scripts/ost_config.in scripts/ost_config.in.backup',shell=True,cwd='../../')
+subprocess.call('sed "s/@PYTHON_BINARY@/\$DNG_ROOT\/bin\/python/g" scripts/ost_config.in.backup > scripts/ost_config.in.preprepre',shell=True,cwd='../../')
+subprocess.call('sed "s/\#export PYTHONHOME/ export PYTHONHOME/g" scripts/ost_config.in.preprepre > scripts/ost_config.in.prepre',shell=True,cwd='../../')
+subprocess.call('sed "s/\#export PYTHONPATH/ export PYTHONPATH/g" scripts/ost_config.in.prepre > scripts/ost_config.in.pre',shell=True,cwd='../../')
+subprocess.call('sed "s/\#export QT_PLUGIN_PATH/ export QT_PLUGIN_PATH/g" scripts/ost_config.in.pre > scripts/ost_config.in',shell=True,cwd='../../')
+print 'Compiling Openstructure'
+subprocess.call('cmake ./ -DCMAKE_BUILD_TYPE=Release -DQT_QMAKE_EXECUTABLE='+qt4_qmake_location+' -DPREFIX='+directory_name+' -DCOMPOUND_LIB='+chemlib_dictionary_location+' -DENABLE_IMG=ON -DUSE_RPATH=ON -DENABLE_GUI=ON -DENABLE_GFX=ON -DOPTIMIZE=ON',shell=True,cwd='../../')
+subprocess.call('make -j2',shell=True,cwd='../../')
+print 'Removing obsolete packages and package directory'
+subprocess.call('rm -fr openstructure-linux*',shell=True,cwd='../../')
+print 'Creating new package directory'
+subprocess.call('mkdir '+directory_name,shell=True,cwd='../../')
+subprocess.call('mkdir '+directory_name+'/bin',shell=True,cwd='../../')
+print 'Copy python executable into stage for dependency detection'
+subprocess.call('cp '+system_python_bin+ ' stage/bin/python',shell=True,cwd='../../')
+print 'Copy python libraries into the stage for dependency detection'
+subprocess.call('cp -pRL '+system_python_libs+' stage/'+libdir+'/',shell=True,cwd='../../')
+subprocess.call('rm -fr stage/'+libdir+'/'+system_python_executable+'/dist-packages',shell=True,cwd='../../')
+subprocess.call('cp -pRL '+sip_module_location+'/sip* stage/'+libdir+'/'+system_python_executable+'/',shell=True,cwd='../../')
+subprocess.call('cp -pRL '+qt4_module_location+' stage/'+libdir+'/'+system_python_executable+'/',shell=True,cwd='../../')
+print 'Copy boost program option libraries into the stage for dependency detection'
+subprocess.call('cp -pRL /usr/lib/libboost_program_options.so* stage/'+libdir+'/',shell=True,cwd='../../')
+print 'Creating new dependency list'
+so_list=[]
+walk_list=os.walk('../../stage')
+for dir_entry in walk_list:
+  for file_entry in dir_entry[2]:
+    if file_entry.find('.so')==len(file_entry)-3 or file_entry=='gosty':
+      filepath=os.path.join(dir_entry[0],file_entry)
+      so_list.append(filepath)  
+dep_list=[]
+for so_entry in so_list:
+   dep=subprocess.Popen('perl ./ldd-rec.pl '+so_entry,shell=True,stdout=subprocess.PIPE,cwd='./').stdout
+   dep_so_entry=dep.readlines()
+   for dep_entry in dep_so_entry:
+     dep_list.append(dep_entry[:-1]) 
+sorted_dep_list=sorted(list(set(dep_list)))
+print 'Filtering system libraries from depenedency list'
+filtered_dep_list=[]
+for entry in sorted_dep_list:
+   exclude=False
+   for exclusion in list_of_excluded_libraries:
+     if entry.find(exclusion)!=-1:
+       exclude=True
+   if exclude==False: 
+     filtered_dep_list.append(entry)
+print 'Installing OpenStructure into package directory structure'
+subprocess.call('make install',shell=True,cwd='../../')
+print 'Copy libraries in the package directory structure'
+for entry in filtered_dep_list:
+  subprocess.call('cp '+entry+' '+directory_name+'/'+libdir,shell=True,cwd='../../')
+print 'Copy python executable into package directory structure'
+subprocess.call('cp '+system_python_bin+ ' '+directory_name+'/bin/python',shell=True,cwd='../../')
+print 'Copy python libraries into package directory structure'
+subprocess.call('cp -pRL '+system_python_libs+' '+directory_name+'/'+libdir+'/'+system_python_executable+'/',shell=True,cwd='../../')
+subprocess.call('rm -fr '+directory_name+'/'+libdir+'/'+system_python_executable+'/dist-packages',shell=True,cwd='../../')
+subprocess.call('cp -pRL '+sip_module_location+'/sip* '+directory_name+'/'+libdir+'/'+system_python_executable+'/',shell=True,cwd='../../')
+subprocess.call('cp -pRL '+qt4_module_location+' '+directory_name+'/'+libdir+'/'+system_python_executable+'/',shell=True,cwd='../../')
+print 'Copy Qt 4 plugins into package directory structure'
+subprocess.call('cp -pRL '+qt4_plugins_location+' '+directory_name+'/bin/',shell=True,cwd='../../')
+print 'Copying supplementary material into package directory structure'
+subprocess.call('cp -pRL  stage/share/openstructure  '+directory_name+'/share/',shell=True,cwd='../../')
+print 'Copying examples into package directory structure'
+subprocess.call('cp -pRL  examples  '+directory_name+'/share/openstructure/',shell=True,cwd='../../')
+print 'Copying ReadMe file into package directory structure'
+subprocess.call('cp deployment/README.html '+directory_name,shell=True,cwd='../../')
+print 'Creating executables at the top level of the package directory structure'
+subprocess.call('ln -sf bin/dng ./dng',shell=True,cwd='../../'+directory_name)
+subprocess.call('ln -sf bin/ost ./ost',shell=True,cwd='../../'+directory_name)
+subprocess.call('ln -sf bin/lddt ./lddt',shell=True,cwd='../../'+directory_name)
+print 'Copying additional libraries in the package directory structure'
+subprocess.call('cp '+ssl_crypto_location+'/libssl.so* '+directory_name+'/'+libdir,shell=True,cwd='../../')
+subprocess.call('cp '+ssl_crypto_location+'/libcrypto.so* '+directory_name+'/'+libdir,shell=True,cwd='../../')
+subprocess.call('cp -pRL /usr/lib/libboost_program_options.so* '+directory_name+'/'+libdir+'/',shell=True,cwd='../../')
+print 'Copying python headers in the package directory structure'
+subprocess.call('mkdir -p '+directory_name+'/local/include/',shell=True,cwd='../../')
+subprocess.call('cp -r /usr/include/'+system_python_executable+' '+directory_name+'/local/include/',shell=True,cwd='../../')
+print 'Stripping pyc files from bundle'
+subprocess.call('rm -rf $(find . -name *.pyc)',shell=True,cwd='../../')
+print 'removing dokk and harmony examples from bundle'
+subprocess.call('rm -rf '+directory_name+'/share/openstructure/examples/code_fragments/dokk',shell=True,cwd='../../')
+subprocess.call('rm -rf '+directory_name+'/share/openstructure/examples/code_fragments/harmony',shell=True,cwd='../../')
+print 'Compressing the bundle'
+subprocess.call('tar cfz '+directory_name+'.tgz '+directory_name,shell=True,cwd='../../')
+print "Done. Please run 'git reset --hard HEAD' in the top directory before restarting."
+
diff --git a/deployment/linux/create_bundle_centos6.py b/deployment/linux/create_bundle_centos6.py
new file mode 100644
index 0000000000000000000000000000000000000000..191ffd0e5e28f81ac71bab9454ee3e44e5c55a4a
--- /dev/null
+++ b/deployment/linux/create_bundle_centos6.py
@@ -0,0 +1,162 @@
+import os
+import shutil
+import subprocess
+import string
+import sys
+import datetime
+import sip
+import PyQt4
+
+
+# parameters that can be modified
+qt4_plugins_location='/usr/lib/qt4/plugins'
+qt4_qmake_location='/usr/lib/qt4/bin/qmake'
+ssl_crypto_location='/usr/lib/'
+chemlib_dictionary_location='/home/bundler/compounds.chemlib'
+list_of_excluded_libraries=[
+'ld-linux',
+'libexpat',
+'libgcc_s',
+'libglib',
+'cmov',
+'libice',
+'libdl',
+'libGLU',
+'libelf',
+'libpthread',
+'libstdc++',
+'libSM',
+'libX',
+'libg',
+'libGL.so',
+'libfontconfig',
+'libfreetype',
+'libdrm',
+'libxcb',
+'libICE',
+'libnvidia',
+'libc',
+'libuuid'
+]
+
+if len(sys.argv) < 2:
+  print 'usage: create_bundle.py  additional_label'
+  sys.exit()
+
+additional_label=sys.argv[1]
+
+currdir=os.getcwd()
+if currdir.find('deployment')==-1 or currdir.find('linux')==-1:
+  print '\n'
+  print 'ERROR: Please run this script from the deployment/linux directory'
+  print '\n'
+  sys.exit()
+
+print "WARNING: If this script does not run to completion, please run 'git reset --hard HEAD' in the main directory (two up from here) before restarting"
+
+system_python_version=sys.version_info
+system_python_executable='python'+str(system_python_version[0])+'.'+str(system_python_version[1])
+system_python_bin='/usr/bin/'+system_python_executable
+system_python_libs='/usr/lib/'+system_python_executable
+qt4_module_location=os.path.dirname(PyQt4.__file__)
+sip_module_location=os.path.dirname(sip.__file__)
+print '\n'
+print '\n'
+print 'Detecting architecture and revision'
+uname_output=subprocess.Popen('uname -a', shell=True, cwd='../../',stdout=subprocess.PIPE).stdout
+uname_line=uname_output.readlines()
+if uname_line[0].find('x86_64') !=-1:
+  libdir='lib64'
+  archstring='64bit'
+else: 
+  libdir='lib'
+  archstring='32bit'
+directory_name='openstructure-linux-'+archstring+'-'+additional_label
+print 'Hardcoding package python binary path in openstructure executables'
+subprocess.call('rm -f scripts/ost_config.in.pre* scripts/ost_config.in.backup',shell=True,cwd='../../')
+subprocess.call('mv scripts/ost_config.in scripts/ost_config.in.backup',shell=True,cwd='../../')
+subprocess.call('sed "s/@PYTHON_BINARY@/\$DNG_ROOT\/bin\/python/g" scripts/ost_config.in.backup > scripts/ost_config.in.preprepre',shell=True,cwd='../../')
+subprocess.call('sed "s/\#export PYTHONHOME/ export PYTHONHOME/g" scripts/ost_config.in.preprepre > scripts/ost_config.in.prepre',shell=True,cwd='../../')
+subprocess.call('sed "s/\#export PYTHONPATH/ export PYTHONPATH/g" scripts/ost_config.in.prepre > scripts/ost_config.in.pre',shell=True,cwd='../../')
+subprocess.call('sed "s/\#export QT_PLUGIN_PATH/ export QT_PLUGIN_PATH/g" scripts/ost_config.in.pre > scripts/ost_config.in',shell=True,cwd='../../')
+print 'Compiling Openstructure'
+subprocess.call('cmake ./ -DCMAKE_BUILD_TYPE=Release -DQT_QMAKE_EXECUTABLE='+qt4_qmake_location+' -DPREFIX='+directory_name+' -DCOMPOUND_LIB='+chemlib_dictionary_location+' -DENABLE_IMG=ON -DUSE_RPATH=ON -DENABLE_GUI=ON -DENABLE_GFX=ON -DOPTIMIZE=ON',shell=True,cwd='../../')
+subprocess.call('make -j2',shell=True,cwd='../../')
+print 'Removing obsolete packages and package directory'
+subprocess.call('rm -fr openstructure-linux*',shell=True,cwd='../../')
+print 'Creating new package directory'
+subprocess.call('mkdir '+directory_name,shell=True,cwd='../../')
+subprocess.call('mkdir '+directory_name+'/bin',shell=True,cwd='../../')
+print 'Copy python executable into stage for dependency detection'
+subprocess.call('cp '+system_python_bin+ ' stage/bin/python',shell=True,cwd='../../')
+print 'Copy python libraries into the stage for dependency detection'
+subprocess.call('cp -pRL '+system_python_libs+' stage/'+libdir+'/',shell=True,cwd='../../')
+subprocess.call('rm -fr stage/'+libdir+'/'+system_python_executable+'/dist-packages',shell=True,cwd='../../')
+subprocess.call('cp -pRL '+sip_module_location+'/sip* stage/'+libdir+'/'+system_python_executable+'/',shell=True,cwd='../../')
+subprocess.call('cp -pRL '+qt4_module_location+' stage/'+libdir+'/'+system_python_executable+'/',shell=True,cwd='../../')
+print 'Copy boost program option libraries into the stage for dependency detection'
+subprocess.call('cp -pRL /usr/lib/libboost_program_options.so* stage/'+libdir+'/',shell=True,cwd='../../')
+print 'Creating new dependency list'
+so_list=[]
+walk_list=os.walk('../../stage')
+for dir_entry in walk_list:
+  for file_entry in dir_entry[2]:
+    if file_entry.find('.so')==len(file_entry)-3 or file_entry=='gosty':
+      filepath=os.path.join(dir_entry[0],file_entry)
+      so_list.append(filepath)  
+dep_list=[]
+for so_entry in so_list:
+   dep=subprocess.Popen('perl ./ldd-rec.pl '+so_entry,shell=True,stdout=subprocess.PIPE,cwd='./').stdout
+   dep_so_entry=dep.readlines()
+   for dep_entry in dep_so_entry:
+     dep_list.append(dep_entry[:-1]) 
+sorted_dep_list=sorted(list(set(dep_list)))
+print 'Filtering system libraries from depenedency list'
+filtered_dep_list=[]
+for entry in sorted_dep_list:
+   exclude=False
+   for exclusion in list_of_excluded_libraries:
+     if entry.find(exclusion)!=-1:
+       exclude=True
+   if exclude==False: 
+     filtered_dep_list.append(entry)
+print 'Installing OpenStructure into package directory structure'
+subprocess.call('make install',shell=True,cwd='../../')
+print 'Copy libraries in the package directory structure'
+for entry in filtered_dep_list:
+  subprocess.call('cp '+entry+' '+directory_name+'/'+libdir,shell=True,cwd='../../')
+print 'Copy python executable into package directory structure'
+subprocess.call('cp '+system_python_bin+ ' '+directory_name+'/bin/python',shell=True,cwd='../../')
+print 'Copy python libraries into package directory structure'
+subprocess.call('cp -pRL '+system_python_libs+' '+directory_name+'/'+libdir+'/'+system_python_executable+'/',shell=True,cwd='../../')
+subprocess.call('rm -fr '+directory_name+'/'+libdir+'/'+system_python_executable+'/dist-packages',shell=True,cwd='../../')
+subprocess.call('cp -pRL '+sip_module_location+'/sip* '+directory_name+'/'+libdir+'/'+system_python_executable+'/',shell=True,cwd='../../')
+subprocess.call('cp -pRL '+qt4_module_location+' '+directory_name+'/'+libdir+'/'+system_python_executable+'/',shell=True,cwd='../../')
+print 'Copy Qt 4 plugins into package directory structure'
+subprocess.call('cp -pRL '+qt4_plugins_location+' '+directory_name+'/bin/',shell=True,cwd='../../')
+print 'Copying supplementary material into package directory structure'
+subprocess.call('cp -pRL  stage/share/openstructure  '+directory_name+'/share/',shell=True,cwd='../../')
+print 'Copying examples into package directory structure'
+subprocess.call('cp -pRL  examples  '+directory_name+'/share/openstructure/',shell=True,cwd='../../')
+print 'Copying ReadMe file into package directory structure'
+subprocess.call('cp deployment/README.html '+directory_name,shell=True,cwd='../../')
+print 'Creating executables at the top level of the package directory structure'
+subprocess.call('ln -sf bin/dng ./dng',shell=True,cwd='../../'+directory_name)
+subprocess.call('ln -sf bin/ost ./ost',shell=True,cwd='../../'+directory_name)
+subprocess.call('ln -sf bin/lddt ./lddt',shell=True,cwd='../../'+directory_name)
+print 'Copying additional libraries in the package directory structure'
+subprocess.call('cp '+ssl_crypto_location+'/libssl.so* '+directory_name+'/'+libdir,shell=True,cwd='../../')
+subprocess.call('cp '+ssl_crypto_location+'/libcrypto.so* '+directory_name+'/'+libdir,shell=True,cwd='../../')
+subprocess.call('cp -pRL /usr/lib/libboost_program_options.so* '+directory_name+'/'+libdir+'/',shell=True,cwd='../../')
+print 'Copying python headers in the package directory structure'
+subprocess.call('mkdir -p '+directory_name+'/local/include/',shell=True,cwd='../../')
+subprocess.call('cp -r /usr/include/'+system_python_executable+' '+directory_name+'/local/include/',shell=True,cwd='../../')
+print 'Stripping pyc files from bundle'
+subprocess.call('rm -rf $(find . -name *.pyc)',shell=True,cwd='../../')
+print 'removing dokk and harmony examples from bundle'
+subprocess.call('rm -rf '+directory_name+'/share/openstructure/examples/code_fragments/dokk',shell=True,cwd='../../')
+subprocess.call('rm -rf '+directory_name+'/share/openstructure/examples/code_fragments/harmony',shell=True,cwd='../../')
+print 'Compressing the bundle'
+subprocess.call('tar cfz '+directory_name+'.tgz '+directory_name,shell=True,cwd='../../')
+print "Done. Please run 'git reset --hard HEAD' in the top directory before restarting."
+
diff --git a/examples/code_fragments/surf/test_surf_clip.py b/examples/code_fragments/surf/test_surf_clip.py
new file mode 100644
index 0000000000000000000000000000000000000000..6cdfdf3c5f2f39f8f24096c0fb5b7bb569fcea05
--- /dev/null
+++ b/examples/code_fragments/surf/test_surf_clip.py
@@ -0,0 +1,18 @@
+struct=io.LoadEntity("sdh.pdb")
+surf=io.LoadSurface("sdh","msms")
+surf.Attach(struct,5.0)
+go=gfx.Surface("surf",surf)
+# this is broken
+#go.clip=True
+#go.clip_plane=geom.Vec4(0,0,-1,-130)
+# this works, z offset to near clipping plane, must be >0
+go.clip_offset=1
+go.solid=True
+go.solid_color=gfx.RGB(1,1,0)
+
+scene.rtc=geom.Mat4(0.914075, -0.355397, 0.195293, 29.688, 0.405471, 0.7934, -0.45397, 19.9405, 0.00639453, 0.494153, 0.869337, 73.0075, 0, 0, -143.077, 1)
+
+scene.Add(go)
+scene.SetCenter(go.GetCenter())
+scene.Autoslab()
+scene.auto_autoslab=False
diff --git a/modules/base/pymod/CMakeLists.txt b/modules/base/pymod/CMakeLists.txt
index 6a011018fb032d44e07680e214e9bfcb5c14e454..433dfeb9f35290e7330ea5a608e35f39292a5b88 100644
--- a/modules/base/pymod/CMakeLists.txt
+++ b/modules/base/pymod/CMakeLists.txt
@@ -7,5 +7,28 @@ set(OST_BASE_PYMOD_SOURCES
 if (NOT ENABLE_STATIC)
   pymod(NAME base OUTPUT_DIR ost 
         CPP ${OST_BASE_PYMOD_SOURCES} 
-        PY __init__.py settings.py stutil.py table.py xmlrunner.py testutils.py)
+        PY settings.py stutil.py table.py xmlrunner.py testutils.py)
 endif() 
+
+set(SQ "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'")
+set(SUBST_DICT "ALL_ADDITIONAL_MODULES=")
+if(ENABLE_GUI)
+  set(SUBST_DICT "${SUBST_DICT},${SQ}gui${SQ}")
+endif(ENABLE_GUI)
+if(ENABLE_GFX)
+  set(SUBST_DICT "${SUBST_DICT},${SQ}gfx${SQ}")
+endif(ENABLE_GFX)
+if(ENABLE_IMG)
+  set(SUBST_DICT "${SUBST_DICT},${SQ}img${SQ}")
+endif(ENABLE_IMG)
+if(ENABLE_INFO)
+  set(SUBST_DICT ${SUBST_DICT},${SQ}info${SQ})
+endif(ENABLE_INFO)
+
+
+script(NAME __init__.py
+       INPUT __init__.py.in
+       SUBSTITUTE "${SUBST_DICT}"
+       TARGET ost_base_pymod
+       OUTPUT_DIR "${LIB_DIR}/python${PYTHON_VERSION}/site-packages/ost")
+
diff --git a/modules/base/pymod/__init__.py b/modules/base/pymod/__init__.py.in
similarity index 67%
rename from modules/base/pymod/__init__.py
rename to modules/base/pymod/__init__.py.in
index 8ecfacd79cddae2336ab0000b30def062c46a515..4b1be9f6cdfd7c504bf4cd7b0b5094b0f5b8a147 100644
--- a/modules/base/pymod/__init__.py
+++ b/modules/base/pymod/__init__.py.in
@@ -16,27 +16,12 @@
 # along with this library; if not, write to the Free Software Foundation, Inc.,
 # 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 #------------------------------------------------------------------------------
-from _ost_base import *
-from stutil import *
 
-from ost import geom
-from ost import io
-from ost import mol
-from ost import seq
 
-try:
-  from ost import gfx
-  scene = gfx.Scene()
-  scene.Stereo=gfx.Stereo
-except ImportError:
-  pass
-  
-  
-try:
-  from ost import img
-except ImportError:
-  pass
+__all__=['Correl', 'FileLogSink', 'FloatList', 'GetCurrentLogSink', 'GetPrefixPath', 'GetSharedDataPath', 'GetVerbosityLevel', 'Histogram', 'IntList', 'LogDebug', 'LogError', 'LogInfo', 'LogScript', 'LogSink', 'LogTrace', 'LogVerbose', 'LogWarning', 'Max', 'Mean', 'Median', 'Min', 'MultiLogSink', 'PopLogSink', 'PopVerbosityLevel', 'PushLogSink', 'PushVerbosityLevel', 'Range', 'SetPrefixPath', 'StdDev', 'StreamLogSink', 'StringList', 'StringLogSink', 'Units', 'VERSION', 'VERSION_MAJOR', 'VERSION_MINOR', 'VERSION_PATCH', 'WITH_NUMPY', 'conop', 'geom', 'io', 'mol', 'seq', 'stutil' @ALL_ADDITIONAL_MODULES@]
 
+from _ost_base import *
+from stutil import *
 
 class StreamLogSink(LogSink):
   def __init__(self, stream):
diff --git a/modules/base/pymod/stutil.py b/modules/base/pymod/stutil.py
index e61a1687c24e4be08ccf40320c4bf49a94603b37..506675f1213db243103f4a9ecd4a8b2c5502beec 100644
--- a/modules/base/pymod/stutil.py
+++ b/modules/base/pymod/stutil.py
@@ -1,44 +1,5 @@
 import math
-from ost import mol
 
-def FloatValueExtract(func):
-  """
-  Decorator to wrap functions that take a list of float values. In addition to 
-  passing in a list of float values directly, it is possible to extract the 
-  values from attributes or generic properties.
-  """
-  def _dec(xs, prop=None, attr=None):
-    if prop!=None:
-      if len(xs)==0:
-        return func([])
-      assert attr==None
-      level=mol.Prop.Level.UNSPECIFIED
-      if isinstance(xs[0], mol.AtomBase):
-        level=mol.Prop.Level.ATOM
-      elif isinstance(xs[0], mol.ResidueBase):
-        level=mol.Prop.Level.RESIDUE
-      elif isinstance(xs[0], mol.ChainBase):
-        level=mol.Prop.Level.CHAIN
-      epm=mol.EntityPropertyMapper(prop, level)
-      vals=[]
-      for x in xs:
-        try:
-          vals.append(epm.Get(x))
-        except:
-          pass
-      return func(vals)
-    if attr!=None:
-      vals=[]
-      for x in xs:
-        try:
-          vals.append(getattr(x, attr))
-        except:
-          pass
-      return func(vals)
-    return func(xs)
-  return _dec
-
-@FloatValueExtract  
 def Mean(xs):
   """
   Calculate mean of dataset
@@ -47,7 +8,6 @@ def Mean(xs):
     raise RuntimeError("Can't calculate mean of empty sequence")
   return float(sum(xs))/len(xs)
 
-@FloatValueExtract
 def Median(xs):
   """
   Calculate median of dataset
@@ -60,7 +20,6 @@ def Median(xs):
   else:
     return sorted_xs[(len(xs)-1)/2]
 
-@FloatValueExtract
 def StdDev(xs):
   """
   Calculate standard-deviation of dataset
@@ -72,11 +31,9 @@ def StdDev(xs):
   mean=Mean(xs)
   return math.sqrt(sum([(x-mean)**2 for x in xs])/len(xs))
 
-@FloatValueExtract
 def Min(xs):
   return min(xs)
 
-@FloatValueExtract
 def Max(xs):
   return max(xs)
 
diff --git a/modules/base/pymod/table.py b/modules/base/pymod/table.py
index 8ad6bf5776afa335ff67e5988ac12d1bad70cf82..4e88a8bdd90aa8d7c24633489c802ef8e4af689a 100644
--- a/modules/base/pymod/table.py
+++ b/modules/base/pymod/table.py
@@ -5,6 +5,7 @@ from ost import stutil
 import itertools
 import operator
 import cPickle
+import weakref
 from ost import LogError, LogWarning, LogInfo, LogVerbose
 
 def MakeTitle(col_name):
@@ -126,6 +127,45 @@ class TableCol:
   def __div__(self, rhs):
     return BinaryColExpr(operator.div, self, rhs)
 
+class TableRow:
+  """
+  Essentially a named tuple, but allows column names that are not valid 
+  python variable names.
+  """
+  def __init__(self, row_data, tab):
+    self.__dict__['tab'] = weakref.proxy(tab)
+    self.__dict__['row_data'] = row_data
+
+  def __getitem__(self, col_name):
+    if type(col_name)==int:
+      return self.row_data[col_name]
+    return self.row_data[self.tab.GetColIndex(col_name)]
+
+  def __str__(self):
+    s = []
+    for k, v in zip(self.__dict__['tab'].col_names, self.__dict__['row_data']):
+      s.append('%s=%s' % (k, str(v)))
+    return ', '.join(s)
+      
+      
+  def __len__(self):
+    return len(self.row_data)
+
+  def __setitem__(self, col_name, val):
+    if type(col_name)==int:
+      self.row_data[col_name] = val
+    else:
+      self.row_data[self.tab.GetColIndex(col_name)] = val
+
+  def __getattr__(self, col_name):
+    if 'col_names' not in self.tab.__dict__ or col_name not in self.tab.col_names:
+      raise AttributeError(col_name)
+    return self.row_data[self.tab.GetColIndex(col_name)]
+
+  def __setattr__(self, col_name, val):
+    if 'col_names' not in self.tab.__dict__ or col_name not in self.tab.col_names:
+      raise AttributeError(col_name)
+    self.row_data[self.tab.GetColIndex(col_name)] = val
 
 class Table(object):
   """
@@ -193,6 +233,15 @@ class Table(object):
       if len(kwargs)>0:
         self._AddRowsFromDict(kwargs)
 
+  def __getattr__(self, col_name):
+    # pickling doesn't call the standard __init__ defined above and thus
+    # col_names might not be defined. This leads to infinite recursions.
+    # Protect against it by checking that col_names is contained in 
+    # __dict__
+    if 'col_names' not in self.__dict__ or col_name not in self.col_names:
+      raise AttributeError(col_name)
+    return TableCol(self, col_name)
+
   @staticmethod
   def _ParseColTypes(types, exp_num=None):
     if types==None:
@@ -614,7 +663,6 @@ Statistics for column %(col)s
       self._AddRowsFromDict(data, overwrite)
     else:
       if len(data)!=len(self.col_names):
-        print data, self.col_names
         msg='data array must have %d elements, not %d'
         raise ValueError(msg % (len(self.col_names), len(data)))
       new_row = [self._Coerce(v, t) for v, t in zip(data, self.col_types)]
@@ -771,6 +819,449 @@ Statistics for column %(col)s
         filt_tab.AddRow(row)
     return filt_tab
 
+
+  def _EvaluateEqualNone(self, lhs, rhs):
+    return (lhs==None or lhs!=lhs) == (rhs==None or rhs!=rhs)
+ 
+  def _EvaluateNonEqualNone(self, lhs, rhs):
+    return (lhs==None or lhs!=lhs) != (rhs==None or rhs!=rhs)
+ 
+  def _EvaluateAnd(self, lhs, rhs):
+    return lhs and rhs
+
+  def _EvaluateOr(self, lhs, rhs):
+    return lhs or rhs
+
+  def _EvaluateEqual(self, lhs, rhs):
+    return lhs==rhs
+
+  def _EvaluateNonEqual(self, lhs, rhs):
+    return lhs!=rhs
+
+  def _EvaluateLower(self, lhs, rhs):
+    return lhs<rhs
+
+  def _EvaluateGreater(self, lhs, rhs):
+    return lhs>rhs
+
+  def _EvaluateLowerEqual(self, lhs, rhs):
+    return lhs<=rhs
+
+  def _EvaluateGreaterEqual(self, lhs, rhs):
+    return lhs>=rhs
+
+  def _EvaluateAdd(self, lhs, rhs):
+    if lhs==None or lhs!=lhs or rhs==None or rhs!=rhs:
+      return None
+    return lhs+rhs
+
+  def _EvaluateSubtract(self, lhs, rhs):
+    if lhs==None or lhs!=lhs or rhs==None or rhs!=rhs:
+      return None
+    return lhs-rhs
+
+  def _EvaluateMultiply(self, lhs, rhs):
+    if lhs==None or lhs!=lhs or rhs==None or rhs!=rhs:
+      return None
+    return lhs*rhs
+
+  def _EvaluateDivide(self, lhs, rhs):
+    if lhs==None or lhs!=lhs or rhs==None or rhs!=rhs:
+      return None
+    return lhs/rhs
+
+
+  def _EvaluateOperator(self, op, lhs, rhs):
+
+    if op=='+':
+      return self._EvaluateAdd(lhs, rhs)
+    elif op=='-':
+      return self._EvaluateSubtract(lhs, rhs)
+    elif op=='/':
+      return self._EvaluateDivide(lhs, rhs)
+    elif op=='*':
+      return self._EvaluateMultiply(lhs, rhs)
+    elif lhs==None or lhs!=lhs or rhs==None or rhs!=rhs:
+      if op=='=':
+        return self._EvaluateEqualNone(lhs,rhs)
+      elif op=='!=':
+        return self._EvaluateNonEqualNone(lhs,rhs)
+      return None
+    elif op=='and':
+      return self._EvaluateAnd(lhs, rhs)
+    elif op=='or':
+      return self._EvaluateOr(lhs, rhs)
+    elif op=='=':
+      return self._EvaluateEqual(lhs, rhs)
+    elif op=='!=':
+      return self._EvaluateNonEqual(lhs, rhs)
+    elif op=='<':
+      return self._EvaluateLower(lhs, rhs)
+    elif op=='>':
+      return self._EvaluateGreater(lhs, rhs)
+    elif op=='<=':
+      return self._EvaluateLowerEqual(lhs, rhs)
+    elif op=='>=':
+      return self._EvaluateGreaterEqual(lhs, rhs)
+
+    else:
+      raise ValueError('Unknown operator: '+op)
+
+  def _EvaluateRPN(self, RPNExp, valid_operators):
+    #Evaluates the reverse polish notation
+    stack=list()
+    while True:
+      if len(RPNExp)==0:
+        break
+      exp=RPNExp.pop(0)
+      if exp in valid_operators:
+        if len(stack)<2:
+          raise ValueError('Cannot evaluate operator on less than two operands!')
+        rhs=stack.pop()
+        lhs=stack.pop()
+        result=self._EvaluateOperator(exp, lhs, rhs)
+        if result==None:
+          return False
+        stack.append(result)
+      else:
+        stack.append(exp)
+    if len(stack)>1:
+      raise ValueError('Too many operands for given operators!')
+    return stack.pop()
+
+  def _ShuntingYard(self, split_expression, valid_operators, precedence):
+    #Creates the so called reverse polish notation out of the expression parser output.
+    #note, that there won't be parenthesis anymore and potential parenthesis
+    #mismatches get recognized.
+    #The shunting yard algorithm from dijkstra gets used.
+
+    output_stack=list()
+    operator_stack=list()
+
+    while True:
+      if len(split_expression)==0:
+        while True:
+          if len(operator_stack)==0:
+            break
+          if operator_stack[-1] in ['(',')']:
+            raise ValueError('Parenthesis mismatch!')
+          output_stack.append(operator_stack.pop())
+        break
+
+      exp=split_expression.pop(0)
+
+      if exp == '(':
+        operator_stack.append('(')
+        continue
+
+      if exp in valid_operators:
+        prec=precedence[exp]
+        while len(operator_stack)>0:
+          if operator_stack[-1]=='(':
+            break
+          elif prec>=precedence[operator_stack[-1]]:
+            output_stack.append(operator_stack.pop())
+          else:
+            break
+        operator_stack.append(exp)
+        continue
+        
+      if exp == ')':
+        while True:
+          if len(operator_stack)==0:
+            raise ValueError('Parenthesis mismatch!')
+          if operator_stack[-1]=='(':
+            operator_stack.pop()
+            break
+          output_stack.append(operator_stack.pop())
+        continue
+
+      output_stack.append(exp)
+
+    return output_stack
+
+  def _EvaluateOperand(self, operand):
+
+    import re
+
+    float_expression=re.compile('[-+]?[0-9]*\.[0-9]+(?:[eE][-+]?[0-9]+)?$')
+    int_expression=re.compile('[-+]?[0-9]+(?:[eE][-+]?[0-9]+)?$')
+    bool_expression=re.compile('true$|True$|false$|False$')
+    none_expression=re.compile('None$|none$|nan$|NAN$|NaN$')
+
+    if re.match(float_expression,operand):
+      return float(operand)
+    elif re.match(int_expression, operand):
+      return int(operand)
+    elif re.match(bool_expression,operand):
+      if operand == 'false' or operand == 'False':
+        return False
+      return True
+    elif re.match(none_expression,operand):
+      return None
+    return operand
+
+    #If nothing above matches, operand must be a string, full string
+    #gets returned.
+
+
+  def _LexerHelper(self, operand):
+    if len(operand.strip())>0:
+      if ' ' in operand.strip():
+        raise ValueError('Cannot Evaluate %s'%(operand))
+      return [operand.strip()]
+    return []
+
+
+
+  def _ExpressionLexer(self, expression, valid_operators, precedence):
+
+    #Reads token after token and searches for brackets and valid_operators
+    #everything, that doesn't match the above is assumed to be an operand
+    #and is cast into the most likely type based on regular expression
+    #Note, that there is no check, wether the operands can be processed by
+    #their corresponding operators (with respect to types)!
+
+    split_expression=list()
+    actual_position=0
+    eaten_stuff=''
+
+    while True:
+
+      if actual_position>=len(expression):
+        if len(eaten_stuff.strip())>0:
+          op=eaten_stuff.strip()
+          if ' ' in op:
+            raise ValueError('cannot evaluate %s'%(op))
+          split_expression.append(op)
+
+        #check for problematic cases like 'a<=b<=c'. We don't know which operator to evaluate first
+        for i in range(len(split_expression)-3):
+          if (split_expression[i] in valid_operators) and (split_expression[i+2] in valid_operators):
+            if precedence[split_expression[i]]==precedence[split_expression[i+2]]:
+              raise ValueError('Cannot Evaluate '+' '.join(split_expression[i:i+3])+' since both operators have same precedence!')
+
+
+        #handle , operator
+        #replaces an expression like 'rnum=1,2,3' with '(rnum=1 or rnum=2 or rnum=3)'
+
+        temp_split_expression=list()
+        skips=0
+
+        for i in range(len(split_expression)):
+          if skips>0:
+            skips-=1
+            continue
+          if ',' in split_expression[i]:
+
+            if split_expression[max(0,i-1)] != '=' and split_expression[min(i+1,len(split_expression)-1)] != '=':
+              raise ValueError('Can evaluate \',\' sign only in combination with \'=\'')
+
+            single_operands=split_expression[i].split(',')
+
+            if split_expression[max(0,i-1)]=='=':
+              if i-2<0:
+                raise ValueError('Does it really make sense to start with an \'=\'')
+              main_operand=split_expression[i-2]
+              temp_split_expression.pop()
+              temp_split_expression.pop()
+              skips=0
+
+            else:
+              if i+2>len(split_expression)-1:
+                raise ValueError('Does it really make sense to end with an \'=\'')
+              main_operand=split_expression[i+2]
+              skips=2
+
+            temp_expression=list(['('])
+            temp_expression+=' or '.join(['%s = %s'% (a,b) for (a,b) in zip(len(single_operands)*[main_operand],single_operands)]).split()
+            temp_expression.append(')')
+            temp_split_expression+=temp_expression
+            continue
+
+          temp_split_expression.append(split_expression[i])
+
+        split_expression=temp_split_expression
+
+        #handle ':' operator
+        #replaces an expression like 'col_a=x:y' with '(col_a>=x and col_a<=y)'
+        
+        temp_split_expression=list()
+        skips=0
+
+        for i in range(len(split_expression)):
+          if skips>0:
+            skips-=1
+            continue
+          if ':' in split_expression[i]:
+            if split_expression[max(0,i-1)] != '=' and split_expression[min(i+1,len(split_expression)-1)] != '=':
+              raise ValueError('Can evaluate \':\' sign only in combination with \'=\'')
+            if len(split_expression[i].split(':')) != 2:
+              raise ValueError('Can operate \':\' operator only on 2 operands')
+            
+            #even though we are still in the lexer, its necessary to evaluate the next
+            #expressions... They will be written back into the splitexpression as string again
+            lhs=self._EvaluateOperand(split_expression[i].split(':')[0])
+            rhs=self._EvaluateOperand(split_expression[i].split(':')[1])
+
+            template_expression=['(','','<=','','and','','<=','',')']
+
+            if split_expression[max(0,i-1)] == '=':
+              if i-2<0:
+                raise ValueError('Does it really make sense to start with an \'=\'?')
+              temp_split_expression.pop()
+              temp_split_expression.pop()
+              template_expression[3]=split_expression[i-2]
+              template_expression[5]=split_expression[i-2]
+              skips=0
+
+            else:
+              if i+2>len(split_expression)-1:
+                raise ValueError('Does it really make sense to end with an \'=\'?')
+              template_expression[3]=split_expression[i+2]
+              template_expression[5]=split_expression[i+2]
+              skips=2 
+
+            template_expression[1]=str(min(lhs,rhs))
+            template_expression[7]=str(max(lhs,rhs))
+            temp_split_expression+=template_expression
+            continue
+
+          temp_split_expression.append(split_expression[i])
+  
+        split_expression=temp_split_expression
+
+        return split_expression
+
+      token=expression[actual_position]
+
+      if token.isspace():
+        split_expression+=self._LexerHelper(eaten_stuff)
+        actual_position+=1
+        eaten_stuff=''
+        continue
+
+      if token in ['(','[','{']:
+        split_expression+=self._LexerHelper(eaten_stuff)
+        split_expression.append('(')
+        actual_position+=1
+        eaten_stuff=''
+        continue
+
+      if token in [')',']','}']:
+        split_expression+=self._LexerHelper(eaten_stuff)
+        split_expression.append(')')
+        actual_position+=1
+        eaten_stuff=''
+        continue
+
+      if token in ['+','-','*','/','=']:
+        split_expression+=self._LexerHelper(eaten_stuff)
+        split_expression.append(token)
+        actual_position+=1
+        eaten_stuff=''
+        continue
+
+      if token == '!':
+        if actual_position+1==len(expression):
+          raise ValueError('Cannot evaluate \'!\'')
+        if expression[actual_position+1]== '=':
+          split_expression+=self._LexerHelper(eaten_stuff)
+          split_expression.append('!=')
+          actual_position+=2
+          eaten_stuff=''
+          continue
+        else:
+          raise ValueError('Cannot evaluate single \'!\'')
+
+      if token in ['<','>']:
+        if actual_position+1<len(expression):
+          if expression[actual_position+1]=='=':
+            split_expression+=self._LexerHelper(eaten_stuff)
+            split_expression.append(token+'=')
+            actual_position+=2
+            eaten_stuff=''
+            continue
+        split_expression+=self._LexerHelper(eaten_stuff)
+        split_expression.append(token)
+        actual_position+=1
+        eaten_stuff=''
+        continue
+
+      eaten_stuff+=token
+      actual_position+=1
+
+
+  def Select(self, query):
+
+    """
+    Returns a new table object containing all rows matching a logical query expression.
+    
+    *query* is a string containing the logical expression, that will be evaluated
+    for every row. 
+
+    Operands have to be the name of a column or an expression that can be parsed to 
+    float, int, bool or string.
+    Valid operators are: and, or, !=, <=, >=, =, <, >, +, -, *, / 
+    
+    .. code-block:: python
+    
+      subtab=tab.Select('col_a>0.5 and (col_b=5 or col_c=5)')
+
+    The selection query should be self explaining. Allowed parenthesis are: (), [], {}, 
+    whereas parenthesis mismatches get recognized. If there is a row containing 'None'
+    in a query relevant column, it will be neglected.
+
+    There are two special expressions:
+
+    .. code-block:: python
+
+      #selects rows, where 1.0<=col_a<=1.5
+      subtab=tab.Select('col_a=1.0:1.5')
+
+      #selects rows, where col_a=1 or col_a=2 or col_a=3
+      subtab=tab.Select('col_a=1,2,3')
+
+    Be aware, that there is no typechecking! Non consistent combinations of types
+    can lead to weird behaviour!
+
+    """
+
+    valid_operators=['and','or','!=','<=','>=','=','<','>','+','-','*','/']
+
+    #http://en.wikipedia.org/wiki/Order_of_operations
+
+    precedence={'or':6 , 'and':5 , '!=':4 , '=':4 , '<=':3 , 
+                '>=':3 , '<':3 , '>':3 , '+':2 , '-':2 , '*':1 , '/':1}
+
+    split_expression=self._ExpressionLexer(query, valid_operators, precedence)
+    rpn_expression=self._ShuntingYard(list(split_expression), valid_operators, precedence)
+
+    tab_indices=list()
+    exp_indices=list()
+
+    #extract indices for tab values and cast other operands in their most likely type based on
+    #regular expressions
+    for i, exp in enumerate(rpn_expression):
+      if exp in self.col_names:
+        tab_indices.append(self.GetColIndex(exp))
+        exp_indices.append(i)
+        continue
+      elif exp in valid_operators or exp in ['(',')']:
+        continue
+      rpn_expression[i] = self._EvaluateOperand(exp)
+
+    selected_tab=Table(list(self.col_names), list(self.col_types))
+
+    for row in self.rows:
+      for ti, ei in zip(tab_indices, exp_indices):
+        rpn_expression[ei] = row[ti]
+      if self._EvaluateRPN(list(rpn_expression), valid_operators):
+        selected_tab.AddRow(row)
+
+    return selected_tab
+
+
   @staticmethod
   def _LoadOST(stream_or_filename):
     fieldname_pattern=re.compile(r'(?P<name>[^[]+)(\[(?P<type>\w+)\])?')
@@ -1222,7 +1713,7 @@ Statistics for column %(col)s
         if y_range:
           plt.ylim(y_range[0], y_range[1])
         if diag_line:
-          plt.plot(x_range, y_range, '-')
+          plt.plot(x_range, y_range, '-', color='black')
         
         plt.ylabel(nice_y, size='x-large')
       else:
@@ -1468,7 +1959,6 @@ Statistics for column %(col)s
     fig=plt.figure()
     ax=fig.add_subplot(111)
     legend_data=[]
-
     for i in range(len(data)):
       legend_data.append(ax.bar(ind+i*single_bar_width,data[i],single_bar_width,bottom=bottom,color=colors[i],yerr=yerr_data[i], ecolor='black')[0])
       
@@ -1496,7 +1986,10 @@ Statistics for column %(col)s
     ax.set_xticklabels(x_labels, rotation = x_labels_rotation)
       
     if legend:
-      ax.legend(legend_data, cols)   
+      if legend == True:
+        ax.legend(legend_data, cols)   
+      else:
+        ax.legend(legend_data, legend)
       
     if save:
       plt.savefig(save)
@@ -1599,14 +2092,20 @@ Statistics for column %(col)s
       raise ValueError('parameter x_range must contain exactly two elements')
     if y_range and (IsScalar(y_range) or len(y_range)!=2):
       raise ValueError('parameter y_range must contain exactly two elements')
+
+    ext = [min(xdata),max(xdata),min(ydata),max(ydata)]
+
     if x_range:
       plt.xlim((x_range[0], x_range[1]))
+      ext[0]=x_range[0]
+      ext[1]=x_range[1]
     if y_range:
       plt.ylim(y_range[0], y_range[1])
-    extent = None
-    if x_range and y_range:
-      extent = [x_range[0], x_range[1], y_range[0], y_range[1]]
-    plt.hexbin(xdata, ydata, bins=binning, cmap=colormap, extent=extent)
+      ext[2]=y_range[0]
+      ext[3]=y_range[1]
+
+
+    plt.hexbin(xdata, ydata, bins=binning, cmap=colormap, extent=ext)
 
     plt.title(title, size='x-large', fontweight='bold',
               verticalalignment='bottom')
@@ -2750,6 +3249,7 @@ Statistics for column %(col)s
             return False
     return True
     
+
   def Extend(self, tab, overwrite=None):
     """
     Append each row of *tab* to the current table. The data is appended based
diff --git a/modules/base/src/boost_filesystem_helper.hh b/modules/base/src/boost_filesystem_helper.hh
index 5418253fd7553f7f715e8259d1f6f08615080ca1..450ffa94deaef5b230c11cd0129e3a5422549fda 100644
--- a/modules/base/src/boost_filesystem_helper.hh
+++ b/modules/base/src/boost_filesystem_helper.hh
@@ -37,6 +37,16 @@ String BFPathToString(const boost::filesystem::path& path)
 #endif
 }
 
+inline String BFPathStem(const boost::filesystem::path& path) {
+#if BOOST_FILESYSTEM_VERSION<103400
+  String name = BFPathToString(path);
+  size_t n = name.rfind('.');
+  return name.substr(0, n);
+#else
+  return path.stem();
+#endif
+}
+
 }
 
 
diff --git a/modules/base/src/stdint.hh b/modules/base/src/stdint.hh
index 282a564d9c618918f46a2b8d93f63c8bf5d8299e..5007525f7efb2c4a994348b8dfe7626f3ffe36a9 100644
--- a/modules/base/src/stdint.hh
+++ b/modules/base/src/stdint.hh
@@ -1,5 +1,9 @@
 #ifdef _MSC_VER
-#include <ost/stdint_msc.hh>
+  #if _MSC_VER >= 1600
+    #include <stdint.h>
+  #else
+    #include <ost/stdint_msc.hh>
+  #endif
 #else
 #include <stdint.h>
 #endif
diff --git a/modules/base/tests/test_log.py b/modules/base/tests/test_log.py
index cec9378edc965174e460c392ee8bf28a69d106e8..2527159d43b7470ca681a158f700f8dc2315d410 100644
--- a/modules/base/tests/test_log.py
+++ b/modules/base/tests/test_log.py
@@ -30,6 +30,7 @@ class TestLog(unittest.TestCase):
         self.severity=severity
         ost.PushLogSink(ls)
     ls=CapturingLogSink()
+    ost.PushVerbosityLevel(1)
     ost.PushLogSink(ls)
     ost.LogError('error message')
     self.assertEqual(ls.message, 'error message\n')
diff --git a/modules/base/tests/test_table.py b/modules/base/tests/test_table.py
index cd11bd729623d9b5463f4cc8a67daf43a0f10cd6..b3c1921d95a70cd665314348080576ae067f7228 100644
--- a/modules/base/tests/test_table.py
+++ b/modules/base/tests/test_table.py
@@ -163,11 +163,17 @@ class TestTable(unittest.TestCase):
     diff = ImageChops.difference(img1, img2)
     self.assertEqual(diff.getbbox(),None)
 
-  def testSearchColNames(self):
+  def testAllowsToSearchColNames(self):
     tab = self.CreateTestTable()
     self.assertEquals(tab.SearchColNames('d$'), ['second', 'third'])
     self.assertEquals(tab.SearchColNames('(first|third)'), ['first','third'])
 
+  def testProvidesDirectAccessToColumns(self):
+    tab = Table(['x', 'two'], 'ii')
+    tab.AddRow([1,2])
+    self.assertEqual([1], list(tab.x))
+    self.assertEqual([2], list(tab.two))
+    self.assertRaises(AttributeError, tab.__getattr__, 'one')
   def testZip(self):
     tab=Table(['col1', 'col2', 'col3', 'col4'], 'sssi')
     tab.AddRow(['a', 'b', 'c', 1])
@@ -1666,6 +1672,107 @@ class TestTable(unittest.TestCase):
     tab = Table('aaa','s',a=['a','b'])
     tab2 = Table('aaa','i',a=[1,2])
     self.assertRaises(TypeError, tab.Extend, tab2)
+
+  def testSelection(self):
+
+    #create table with some data
+    tab = Table(['a','b','c','d'],'ifbs',
+                a=[0,1,2,3,4,5,6,7,8,9],
+                b=[0.5,1.0,1.1,1.2,1.3,1.4,1.5,2.3,2.5,3.0],
+                c=[True,True,True,True,False,False,False,False,None,None],
+                d=['a','b','c','d','e','f','g','h','i','j'])
+
+    valid_operators=['and','or','!=','<=','>=','=','<','>','+','-','*','/']
+
+    precedence={'or':6 , 'and':5 , '!=':4 , '=':4 , '<=':3 , 
+                '>=':3 , '<':3 , '>':3 , '+':2 , '-':2 , '*':1 , '/':1}
+
+    #check wether special operators get parsed correctly
+    exp_one=['a','=','1','and','(','1.0','<=','b','and','b','<=','2.0',')']
+    exp_two=['a','=','1','and','(','b','=','1.0','or','b','=','2.0',')']
+    self.assertEquals(tab._ExpressionLexer('a=1 and b=1.0:2.0', valid_operators, precedence),exp_one)
+    self.assertEquals(tab._ExpressionLexer('a=1 and 1.0:2.0=b', valid_operators, precedence),exp_one)
+    self.assertEquals(tab._ExpressionLexer('a=1 and b=1.0,2.0', valid_operators, precedence),exp_two)
+    self.assertEquals(tab._ExpressionLexer('a=1 and 1.0,2.0=b', valid_operators, precedence),exp_two)
+    self.assertRaises(ValueError, tab._ExpressionLexer,'a=1 and b=1.0:2.0:3.0',valid_operators, precedence)
+
+    #check wether error gets raised in problematic cases like: a=1=b
+    self.assertRaises(ValueError, tab.Select, 'a=1=b and c=True')
+
+    #check wether errors get raised in stupid cases like: =1,2 and b=1.0
+    self.assertRaises(ValueError, tab.Select, '=1,2 and c=True')
+    self.assertRaises(ValueError, tab.Select, '1,2=')
+    self.assertRaises(ValueError, tab.Select, '=1:2 and c=True')
+    self.assertRaises(ValueError, tab.Select, '1:2=')
+
+    #check wether errors get raised in parenthesis mismatches
+    self.assertRaises(ValueError,tab.Select,'a=1,2 and ((b=1.0 or c=True)')
+    self.assertRaises(ValueError,tab.Select,'a=1,2 and (b=1.0 or c=True))')
+
+    #check wether error gets raised when two operands are not separated by an operator
+    self.assertRaises(ValueError,tab.Select,'a=1 b=1.0')
+
+    #check some examples for dijkstras shunting yard algorithm
+    query_one='a=1:4 and ((b>5.0 or b<2.0) and c=True)'
+    split_exp_one=tab._ExpressionLexer(query_one,valid_operators,precedence)
+    rpn_one=['1', 'a', '<=', 'a', '4', '<=', 'and', 'b', '5.0', '>', 'b', '2.0', '<', 'or', 'c', 'True', '=', 'and', 'and']
+    query_two='(a=1,2) or (b>5.0+a or b<2.0)'
+    split_exp_two=tab._ExpressionLexer(query_two,valid_operators,precedence)
+    rpn_two=['a', '1', '=', 'a', '2', '=', 'or', 'b', '5.0', 'a', '+', '>', 'b', '2.0', '<', 'or', 'or']
+    self.assertEquals(tab._ShuntingYard(split_exp_one,valid_operators,precedence),rpn_one)
+    self.assertEquals(tab._ShuntingYard(split_exp_two,valid_operators,precedence),rpn_two)
+
+    #check operator evaluations
+    self.assertTrue(tab._EvaluateOperator('=',False,False))
+    self.assertFalse(tab._EvaluateOperator('=',False,True))
+    self.assertTrue(tab._EvaluateOperator('and',True,True))
+    self.assertFalse(tab._EvaluateOperator('and',True,False))
+    self.assertTrue(tab._EvaluateOperator('or',True,False))
+    self.assertTrue(tab._EvaluateOperator('or',False,True))
+    self.assertFalse(tab._EvaluateOperator('or',False,False))
+    self.assertTrue(tab._EvaluateOperator('!=',False,True))
+    self.assertFalse(tab._EvaluateOperator('!=',True,True))
+    self.assertTrue(tab._EvaluateOperator('<=',1.0,2.0))
+    self.assertTrue(tab._EvaluateOperator('<=',1.0,1.0))
+    self.assertFalse(tab._EvaluateOperator('<=',2.0,1.0))
+    self.assertFalse(tab._EvaluateOperator('>=',1.0,2.0))
+    self.assertTrue(tab._EvaluateOperator('>=',2.0,1.0))
+    self.assertTrue(tab._EvaluateOperator('>=',1.0,1.0))
+    self.assertTrue(tab._EvaluateOperator('<',1.0,2.0))
+    self.assertFalse(tab._EvaluateOperator('<',2.0,1.0))
+    self.assertFalse(tab._EvaluateOperator('<',1.0,1.0))
+    self.assertFalse(tab._EvaluateOperator('>',1.0,2.0))
+    self.assertTrue(tab._EvaluateOperator('>',2.0,1.0))
+    self.assertFalse(tab._EvaluateOperator('>',1.0,1.0))
+    self.assertEqual(tab._EvaluateOperator('+',1,1),2)
+    self.assertEqual(tab._EvaluateOperator('-',1,1),0)
+    self.assertEqual(tab._EvaluateOperator('*',2,2),4)
+    self.assertEqual(tab._EvaluateOperator('/',2,2),1)
+
+    #check a few rpn evaluation examples
+
+    rpn_one=[1, 2, '<=', 2, 4, '<=', 'and', 6.0, 5.0, '>', 2.0, 2.0, '<', 'or', True, True, '=', 'and', 'and']
+    rpn_two=[1, 0, '<=', 2, 4, '<=', 'and', 6.0, 5.0, '>', 2.0, 2.0, '<', 'or', True, True, '=', 'and', 'and']
+    rpn_three=[1, 0, '<=', 2, 4, '<=', 'or', 6.0, 5.0, '>', 2.0, 2.0, '<', 'or', True, True, '=', 'and', 'and']
+
+    self.assertTrue(tab._EvaluateRPN(rpn_one, valid_operators))
+    self.assertFalse(tab._EvaluateRPN(rpn_two, valid_operators))
+    self.assertTrue(tab._EvaluateRPN(rpn_three, valid_operators))
+
+    #check a few selection examples
+
+    query_one='c'
+    query_two='a=2:9 and c'
+    query_three='d=e,f,j and a!=4'
+    query_four='(b=2.0:3.0 and c=False) or (b<1.0 and c)'
+    query_five='b=0.0:1.2,2.5:8.0'
+
+    self.assertEqual([0,1,2,3], list(r[0] for r in tab.Select(query_one).rows))
+    self.assertEqual([2,3], list(r[0] for r in tab.Select(query_two).rows))
+    self.assertEqual([5,9], list(r[0] for r in tab.Select(query_three).rows))
+    self.assertEqual([0,7], list(r[0] for r in tab.Select(query_four).rows))
+    self.assertEqual([0,1,2,3,8,9], list(r[0] for r in tab.Select(query_five).rows))
+
     
 if __name__ == "__main__":
   from ost import testutils
diff --git a/modules/bindings/pymod/CMakeLists.txt b/modules/bindings/pymod/CMakeLists.txt
index 8cd78a87cdf3491c6839bdbb33e0e76d86dc91dc..52c855f25e792401fde6f6befa48ca443009f91f 100644
--- a/modules/bindings/pymod/CMakeLists.txt
+++ b/modules/bindings/pymod/CMakeLists.txt
@@ -10,5 +10,6 @@ utils.py
 naccess.py
 blast.py
 cadscore.py
+kclust.py
 )
 pymod(NAME bindings PY ${OST_BINDINGS})
diff --git a/modules/bindings/pymod/blast.py b/modules/bindings/pymod/blast.py
index 30784713f3990df9802f8292204c38dfe8d027a1..3de9edd1175fbb1bd5b048076ed08a9c01c1b51c 100644
--- a/modules/bindings/pymod/blast.py
+++ b/modules/bindings/pymod/blast.py
@@ -3,8 +3,9 @@ import subprocess
 from xml.dom import minidom
 from ost import io, seq
 import ost
-import re
-import os
+import os, re, sys
+sys.path.append('PYMODULES')
+
 
 class AlignedPatch:
   """
@@ -28,12 +29,17 @@ class AlignedPatch:
   .. attribute:: evalue
 
     The E-value of the HSP
+
+  .. attribute:: seqid
+
+    The sequence identity of the HSP
   """
-  def __init__(self, aln, bit_score, score, evalue):
+  def __init__(self, aln, bit_score, score, evalue, seqid):
     self.aln=aln
     self.bit_score=bit_score
     self.score=score
     self.evalue=evalue
+    self.seqid=seqid
 
 class BlastHit:
   """
@@ -54,36 +60,11 @@ class BlastHit:
     self.identifier=identifier
     self.aligned_patches=aligned_patches
 
-class BlastError(RuntimeError):
-  """
-  Raised when something goes wrong during parsing/execution of the blast
-  executable.
 
-  .. attribute:: brief
-
-    Short explanation of the problem
-
-  .. attribute:: details
-
-    If set, explains in more detail what caused the error. Might be empty.
+def ParseBlastOutput(string, seqid_thres=0, evalue_thres=float("infinity")):
   """
-  def __init__(self, brief, details):
-    self.brief=brief
-    self.details=details
-
-  def __str__(self):
-    if self.details:
-      return '%s\n%s' % (self.brief, self.details)
-    else:
-      return self.brief
-
-def ParseBlastOutput(string):
-  """
-  Parses the blast output and returns a list of :class:`BlastHit` instances.
-
-  :raises: :class:`BlastError` if the output could not be parsed.
-
-  This functions is only capable of dealing with the BLAST XML output.
+  Parses the blast output and returns a list of BlastHits
+  setting no seqid_thres or evalue_thres, restores default behaviour without filtering
   """
   def _GetText(node):
     rc=''
@@ -91,98 +72,208 @@ def ParseBlastOutput(string):
         if child.nodeType==child.TEXT_NODE:
             rc+=child.data
     return rc
-      
+
   def _GetValue(node, tag_name):
     tag=node.getElementsByTagName(tag_name)
     assert len(tag)==1
     return _GetText(tag[0])
-    
+
   def _GetInt(node, tag_name):
     return int(_GetValue(node, tag_name))
 
-  def _ParseHsp(query_id, hit_id, hsp):
+  def _ParseHsp(query_id, hit_id, hsp, tot_query_len, seqid_thres=0, evalue_thres=float("infinity")):
     bit_score=float(_GetValue(hsp, 'Hsp_bit-score'))
     score=float(_GetValue(hsp, 'Hsp_score'))
     evalue=float(_GetValue(hsp, 'Hsp_evalue'))
+    identity=float(_GetValue(hsp, 'Hsp_identity'))
+    hsp_align_len=float(_GetValue(hsp, 'Hsp_align-len'))
+    seqid=identity/hsp_align_len
     query_offset=_GetInt(hsp, 'Hsp_query-from')-1
     hit_offset=_GetInt(hsp, 'Hsp_hit-from')-1
     query_seq=seq.CreateSequence(str(query_id), str(_GetValue(hsp, 'Hsp_qseq')))
     query_seq.offset=query_offset
     hit_seq=seq.CreateSequence(str(hit_id), str(_GetValue(hsp, 'Hsp_hseq')))
     hit_seq.offset=hit_offset
-    aln=seq.CreateAlignment(query_seq, hit_seq)
-    return AlignedPatch(aln, bit_score, score, evalue)
+    try:
+      if seqid > float(seqid_thres) and evalue < evalue_thres:
+        aln=seq.CreateAlignment(query_seq, hit_seq)
+        return AlignedPatch(aln, bit_score, score, evalue, seqid)
+
+    except Exception, e:
+      print str(e), query_seq, hit_seq
+
   try:
     doc=minidom.parseString(string)
   except Exception, e:
-    raise BlastError('Error while parsing BLAST output: %s' % str(e), '')
+    ost.LogError('Error while parsing BLAST output: %s' % str(e))
+    return None
   hits=[]
   query_id=_GetValue(doc, 'BlastOutput_query-def')
+  tot_query_len=_GetValue(doc, 'BlastOutput_query-len')
   for hit in doc.getElementsByTagName('Hit'):
     hit_id=_GetValue(hit, 'Hit_def')
     hsps=hit.getElementsByTagName('Hsp')
-    aligned_patches=[_ParseHsp(query_id, hit_id, hsp) for hsp in hsps]
+    aligned_patches=[_ParseHsp(query_id, hit_id, hsp, tot_query_len, seqid_thres, evalue_thres) for hsp in hsps]
     hits.append(BlastHit(hit_id, aligned_patches))
   return hits
 
+
+
+class BlastError(RuntimeError):
+  def __init__(self, brief, details):
+    self.brief=brief
+    self.details=details
+
+  def __str__(self):
+    if self.details:
+      return '%s\n%s' % (self.brief, self.details)
+    else:
+      return self.brief
+
+def CreateDB(infasta, dbout, mkdb_cmd=None):
+  """
+  Create a blast DB from a fasta file
+
+  :param infasta: the pdb fasta from which the database will be created
+  :type infasta: :class:`string`
+
+  :param dbout: output location for blastDB file
+  :type dbout: :class:`string`
+
+
+  """
+  if mkdb_cmd==None:
+    try:
+      exe=settings.Locate('formatdb')
+      args=[exe, '-i', infasta, '-v',str(10000),'-n',dbout]
+    except:
+      try:
+        exe=settings.Locate('makeblastdb')
+        args=[exe, '-in', infasta, ' -max_file_sz 10GB -out', dbout,'-dbtype','prot']
+        
+      except:
+        raise RuntimeError('could not find makeblastdb/formatdb executable')
+  else:
+    if os.path.basename(mkdb_cmd)=='makeblastdb':
+      exe=settings.Locate('makeblastdb',explicit_file_name=mkdb_cmd)
+      args=[exe, '-in', infasta, ' -max_file_sz 10GB -out', dbout,'-dbtype','prot']
+    elif os.path.basename(mkdb_cmd)=='formatdb':
+        exe=settings.Locate('formatdb',explicit_filename=mkdb_cmd)
+        args=[exe, '-i', infasta, '-v',str(10000),'-n',dbout]
+    else:
+      raise IOError('mkdb command must either be the path to formatdb or makeblastdb!')
+
+  cmd=' '.join(args)
+  ost.LogInfo('creating blast DB (%s)' % cmd)
+  os.system(cmd)
+
 def BlastVersion(blast_location=None):
   """
   Returns the version of the BLAST executable, e.g. 2.2.24 as a string
   """
-  blastall_exe=settings.Locate('blastall', explicit_file_name=blast_location)
-  blast_pipe=subprocess.Popen(blastall_exe, stdout=subprocess.PIPE,
+
+  try:
+    blast_exe=settings.Locate('blastall',explicit_file_name=blast_location)
+  except:
+    try:
+      blast_exe=settings.Locate('blastp', explicit_file_name=blast_location)
+    except:
+      raise RuntimeError('could not find blast executable')
+
+  if os.path.basename(blast_exe)=='blastall':
+    args=[blast_exe]
+    pattern=re.compile(r'blastall (\d+\.\d+\.\d+)\s+arguments:\s*')
+
+  else:
+    args=[blast_exe, '-version']
+    pattern=re.compile(r'Package: blast (\d+\.\d+\.\d+),\s+')
+
+  blast_pipe=subprocess.Popen(args, stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE)
   lines=blast_pipe.stdout.readlines()
-  pattern=re.compile(r'blastall (\d+\.\d+\.\d+)\s+arguments:\s*')
+
   for line in lines:
     m=pattern.match(line)
     if m:
       return m.group(1)
-  raise IOError("could not determine blast version for '%s'" % blastall_exe)
+  raise IOError("could not determine blast version for '%s'" % blast_exe)
+
+
 
 def Blast(query, database, gap_open=11, gap_ext=1, matrix='BLOSUM62',
-         blast_location=None):
+         blast_location=None, outfmt=0, filter_low_complexity=True):
   """
-  Runs a protein vs. protein blast search. The results are returned as a 
+  Runs a protein vs. protein blast search. The results are returned as a
   list of :class:`BlastHit` instances.
-  
+
   :param query: the query sequence
   :type query: :class:`seq.ConstSequenceHandle`
-  
-  :param database: The filename of the sequence database. Make sure that 
-      formatdb has been run on the database and the <database>.pin or
-      <database>.pal file exists.
+
+  :param database: The filename of the sequence database. Make sure that
+      formatdb has been run on the database and the <database>.pin file exists.
   :param matrix: The substitution matrix to be used. Must be one of 'BLOSUM45',
      'BLOSUM62', 'BLOSUM80', 'PAM30', 'PAM70'.
-  :param gap_open: Gap opening penalty. Note that only a subset of gap opening 
-     penalties is supported for each substitutition matrix. Consult the blast 
+  :param gap_open: Gap opening penalty. Note that only a subset of gap opening
+     penalties is supported for each substitutition matrix. Consult the blast
      docs for more information.
-  :param gap_ext: Gap extension penalty. Only a subset of gap extension 
-     penalties are supported for each of the substitution matrices. Consult the 
+  :param gap_ext: Gap extension penalty. Only a subset of gap extension
+     penalties are supported for each of the substitution matrices. Consult the
      blast docs for more information.
-
-  :raises: :class:`~ost.settings.FileNotFound` if the BLAST executable could not 
-           be found
-  :raises: :class:`BlastError` if there was a problem during execution of BLAST.
-  :raises: :class:`ValueError` if the substitution matrix is invalid
-  :raises: :class:`IOError` if the database does not exist
+  :param outfmt: output format, where '0' corresponds to default output (parsed blast output and 1 to raw output)
+  :param filter_low_complexity: Mask off segments of the query sequence that 
+     have low compositional complexity, as determined by the SEG program of 
+     Wootton & Federhen (Computers and Chemistry, 1993)
   """
   subst_mats=('BLOSUM45', 'BLOSUM62', 'BLOSUM80', 'PAM30', 'PAM70',)
   if matrix not in subst_mats:
     raise ValueError('matrix must be one of %s' % ', '.join(subst_mats))
   if not os.path.exists('%s.pin' % database) and not os.path.exists('%s.pal' % database):
     raise IOError("Database %s does not exist" % database)
-  blastall_exe=settings.Locate('blastall', explicit_file_name=blast_location)
-  args=[blastall_exe, '-d', database, '-p', 'blastp', 
-        '-m', '7', '-M', matrix, '-G', str(gap_open), '-E', str(gap_ext)]
+  if blast_location!=None and not os.path.exists(blast_location):
+    ost.LogScript('Could not find %s' %blast_location)
+
+  if blast_location==None:
+    try:
+      blast_exe=settings.Locate('blastall')
+    except:
+      try:
+        blast_exe=settings.Locate('blastp')
+      except:
+        raise RuntimeError('could not find blast executable')
+  else:
+    blast_exe=settings.Locate(os.path.basename(blast_location),explicit_file_name=blast_location)
+
+  if os.path.basename(blast_exe)=='blastall':
+    args=[blast_exe, '-d', database, '-p', 'blastp',
+          '-m', '7', '-M', matrix, '-G', str(gap_open), '-E', str(gap_ext)]
+    if filter_low_complexity==False:
+      args.append('-F')
+      args.append('F')
+          
+  else:
+    complexity_opt='-seg'
+    if filter_low_complexity==True:
+      complexity_arg='yes'
+    else:
+      complexity_arg='no'
+    args=[blast_exe, '-db', database, '-matrix', matrix,
+          '-gapopen', str(gap_open), '-gapextend', str(gap_ext), '-outfmt', '5', complexity_opt, complexity_arg ]
+
   ost.LogInfo('running BLAST (%s)' % ' '.join(args))
-  blast_pipe=subprocess.Popen(args, stderr=subprocess.PIPE, 
+  blast_pipe=subprocess.Popen(args, stderr=subprocess.PIPE,
                               stdout=subprocess.PIPE, stdin=subprocess.PIPE)
-  stdout, stderr=blast_pipe.communicate(io.SequenceToString(query, 'fasta'))
+  if isinstance(query, str):
+    stdout, stderr=blast_pipe.communicate(query)
+  else:
+    stdout, stderr=blast_pipe.communicate(io.SequenceToString(query, 'fasta'))
+
   if len(stderr)>0:
      pattern=re.compile(r'^\[.*\]\s+ERROR:\s+(.*)')
      lines=stderr.split('\n')
      error_message=pattern.match(lines[0])
      if error_message:
        raise BlastError(error_message.group(1), '\n'.join(lines[1:]))
-  return ParseBlastOutput(stdout)
+  if outfmt==0:
+    return ParseBlastOutput(stdout)
+  else:
+    return stdout
diff --git a/modules/bindings/pymod/dssp.py b/modules/bindings/pymod/dssp.py
index f27aa9db9405357a3221adffb190921092febad5..fe33b33f18987c7e3713016efe78406711d2cfea 100644
--- a/modules/bindings/pymod/dssp.py
+++ b/modules/bindings/pymod/dssp.py
@@ -111,7 +111,7 @@ def AssignDSSP(ent, pdb_path="", extract_burial_status=False, tmp_dir=None,
   # are handled in the parser LoadDSSP)
   temp_dssp_path=_ExecuteDSSP(pdb_path, dssp_bin)
   if not os.path.exists(temp_dssp_path):
-    raise RuntimeEror('DSSP output file does not exist.')
+    raise RuntimeError('DSSP output file does not exist.')
   # assign DSSP to entity
   try:
     LoadDSSP(temp_dssp_path, ent, extract_burial_status,
diff --git a/modules/bindings/pymod/kclust.py b/modules/bindings/pymod/kclust.py
new file mode 100644
index 0000000000000000000000000000000000000000..5ecdf11d01a72ff8d9ba5812888b8674511ab5ba
--- /dev/null
+++ b/modules/bindings/pymod/kclust.py
@@ -0,0 +1,150 @@
+import subprocess, os, tempfile
+from ost import io, seq, settings
+
+"""
+Wrapper for kClust a protein sequence clustering algorithm
+
+unpublished, but mentioned in:
+
+Michael Remmert, Andreas Biegert, Andreas Hauser & Johannes Soeding
+HHblits: lighting-fast iterative protein sequence searching by
+HMM-HMM alignment
+Nature Methods 9, 173-175 (2012)
+
+source code can be downloaded from:
+
+ftp://toolkit.genzentrum.lmu.de/pub/
+"""
+
+class cluster:
+
+  """
+  Holds the information of one cluster
+  
+  .. attribute:: sequences
+    
+    SequenceList containing all sequences of the cluster
+  
+  .. attribute:: representative_id
+  
+    a string, that contains the name of the representative sequence of the cluster
+    as estimated by kClust. 
+    
+  .. attribute:: alignment
+
+    alignment handle containing a multiple sequence alignment of all sequences of
+    the cluster. Gets only calculated when binding is called with appropriate flag.
+  """
+
+  def __init__(self, sequences, representative_id):
+
+    self.sequences=sequences
+    self.representative_id=representative_id
+    self.alignment=None
+
+def _SetupFiles(sequences):
+
+  # create temporary directory
+  tmp_dir_name=tempfile.mkdtemp()
+  io.SaveSequenceList(sequences, os.path.join(tmp_dir_name,'fastadb.fasta'))
+  return tmp_dir_name
+
+def _CleanupFiles(tmp_dir_name):
+
+  import shutil
+  shutil.rmtree(tmp_dir_name)
+
+def _ParseOutput(tmp_dir_name):
+
+  header_data=open(os.path.join(tmp_dir_name,'headers.dmp'),'r').readlines()
+  cluster_data=open(os.path.join(tmp_dir_name,'clusters.dmp'),'r').readlines()
+  sequences=io.LoadSequenceList(os.path.join(tmp_dir_name,'fastadb.fasta'))
+
+  clusters=dict()
+  header_mapper=dict()
+  for line in header_data:
+    header_mapper[int(line.split()[0])]=line.split()[1].strip().strip('>')
+
+  #find numeric ids of the representatives of the clusters
+  unique_representatives=list()
+  for line in cluster_data[1:]:
+    actual_cluster=int(line.split()[1])
+    try:
+      unique_representatives.index(actual_cluster)
+    except:
+      unique_representatives.append(actual_cluster)
+
+  #assign every header to its corresponding cluster, where the
+  #cluster id is given by the id of the representative of the cluster
+  for idx in unique_representatives:
+    clusters[idx]=seq.CreateSequenceList()
+  for line in cluster_data[1:]:
+    clusters[int(line.split()[1])].AddSequence(sequences.FindSequence(header_mapper[int(line.split()[0])]))
+
+  #translate into final output
+
+  res=list()
+  for k, v in clusters.iteritems():
+    res.append(cluster(v, header_mapper[k]))
+
+  return res
+  
+def _RunkClust(tmp_dir_name, clustering_thresh, create_alignments):
+
+  bitscore=clustering_thresh*0.060269-0.68498
+
+  executable=settings.Locate('kClust') 
+
+  cmd=[]
+  cmd.append(executable)
+  cmd.append('-i')
+  cmd.append(os.path.join(tmp_dir_name,'fastadb.fasta'))
+  cmd.append('-d')
+  cmd.append(tmp_dir_name)
+  cmd.append('-s')
+  cmd.append(str(bitscore))
+
+  cmd=' '.join(cmd)
+  ps=subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+  stdout, stderr = ps.communicate()
+
+  result=_ParseOutput(tmp_dir_name)
+
+  if(create_alignments):
+    from ost.bindings import clustalw
+    for c in result:
+      if len(c.sequences)>1:
+        c.alignment=clustalw.ClustalW(c.sequences)
+      else:
+        aln=seq.CreateAlignment()
+        aln.AddSequence(c.sequences[0])
+        c.alignment=aln
+
+  return result
+
+def kClust(sequences, clustering_thresh=30, create_alignments=False):
+
+  """
+  Uses kClust to generate clusters of amino acid sequences.
+  
+  :param sequences: All sequences you want to cluster. 
+  :type sequences: :class:`ost.seq.SequenceList`
+
+  :param clustering_thres: Sequence identity threshold to build clusters. Note,
+                           that clustering_thresh is more a rule of thumb, since
+                           compositional bias in the sequence can also play a role.
+                           The value gets transformed in a bitscore, that is used
+                           as an input parameter of kClust 
+
+  :param create_alignments: Flag, wether the alignments of the clusters get calculated.
+                            Requires clustalw in the path.
+
+  :returns: A list of cluster instances
+  
+  :raises: :class:`~ost.settings.FileNotFound` if kClust could not be located.
+  """
+
+  tmp_dir_name=_SetupFiles(sequences)
+  result=_RunkClust(tmp_dir_name, clustering_thresh, create_alignments)
+  _CleanupFiles(tmp_dir_name)
+  return result
diff --git a/modules/bindings/pymod/naccess.py b/modules/bindings/pymod/naccess.py
index f9f2e5703e99cf9a12740c89a192ce95119338a3..b02aeab7a02fff665d7217be36db95e438839657 100644
--- a/modules/bindings/pymod/naccess.py
+++ b/modules/bindings/pymod/naccess.py
@@ -205,7 +205,7 @@ def CalculateSurfaceArea(entity,  radius=1.4,
   # parse selection
   
   # setup files for msms
-  (naccess_data_dir, naccess_data_file,naccess_data_base )=_SetupFiles(entity, selection, scratch_dir)
+  (naccess_data_dir, naccess_data_file,naccess_data_base )=_SetupFiles(entity, selection, scratch_dir, max_number_of_atoms)
 
   # set command line
   command="%s %s -p %f " % \
diff --git a/modules/bindings/pymod/tmtools.py b/modules/bindings/pymod/tmtools.py
index 3c53b9975db978068aaa4397fca2f2e34be74813..294da0e50ff29a1e13839287ddead4445ca7c062 100644
--- a/modules/bindings/pymod/tmtools.py
+++ b/modules/bindings/pymod/tmtools.py
@@ -88,20 +88,20 @@ class TMAlignResult:
     self.ref_sequence =ref_sequence
     self.alignment=alignment
 
-def _ParseTmAlign(lines):
-  info_line=lines[11].split(',')
+def _ParseTmAlign(lines,lines_matrix):
+  info_line=lines[12].split(',')
   aln_length=float(info_line[0].split('=')[1].strip())
   rmsd=float(info_line[1].split('=')[1].strip())  
-  tm_score=float(info_line[2].split('=')[1].strip())
-  tf1=[float(i.strip()) for i in lines[15].split()]
-  tf2=[float(i.strip()) for i in lines[16].split()]
-  tf3=[float(i.strip()) for i in lines[17].split()]
+  tm_score=float(lines[14].split('=')[1].split('(')[0].strip())
+  tf1=[float(i.strip()) for i in lines_matrix[2].split()]
+  tf2=[float(i.strip()) for i in lines_matrix[3].split()]
+  tf3=[float(i.strip()) for i in lines_matrix[4].split()]
   rot=geom.Mat3(tf1[2], tf1[3], tf1[4], tf2[2], tf2[3],
                 tf2[4], tf3[2], tf3[3], tf3[4])
   tf=geom.Mat4(rot)
   tf.PasteTranslation(geom.Vec3(tf1[1], tf2[1], tf3[1]))
-  seq1 = seq.CreateSequence("1",lines[26].strip())
-  seq2 = seq.CreateSequence("2",lines[28].strip())
+  seq1 = seq.CreateSequence("1",lines[18].strip())
+  seq2 = seq.CreateSequence("2",lines[20].strip())
   alignment = seq.CreateAlignment()
   alignment.AddSequence(seq2)
   alignment.AddSequence(seq1)
@@ -112,17 +112,20 @@ def _RunTmAlign(tmalign, tmp_dir):
   model2_filename=os.path.join(tmp_dir, 'model02.pdb')
   if platform.system() == "Windows":
     tmalign_path=settings.Locate('tmalign.exe', explicit_file_name=tmalign)
-    command="\"%s\" %s %s" %(os.path.normpath(tmalign_path), model1_filename, model2_filename)
+    command="\"%s\" %s %s -m %s" %(os.path.normpath(tmalign_path), model1_filename, model2_filename, os.path.join(tmp_dir,'matrix.txt'))
   else:
     tmalign_path=settings.Locate('tmalign', explicit_file_name=tmalign)  
-    command="\"%s\" \"%s\" \"%s\"" %(tmalign_path, model1_filename, model2_filename)
+    command="\"%s\" \"%s\" \"%s\" -m \"%s\"" %(tmalign_path, model1_filename, model2_filename, os.path.join(tmp_dir,'matrix.txt'))
   ps=subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
   ps.wait()
   lines=ps.stdout.readlines()
   if (len(lines))<22:
     _CleanupFiles(tmp_dir)
     raise RuntimeError("tmalign superposition failed")
-  return _ParseTmAlign(lines)
+  matrix_file=open(os.path.join(tmp_dir,'matrix.txt'))
+  lines_matrix=matrix_file.readlines()
+  matrix_file.close() 
+  return _ParseTmAlign(lines,lines_matrix)
 
 class MMAlignResult:
   def __init__(self, rmsd, tm_score, aligned_length, transform, ref_sequence, alignment):
diff --git a/modules/bindings/src/tmalign.f b/modules/bindings/src/tmalign.f
index 152453538d37421c7a836f56142a9d980be4028b..26c0abf9aeedd5a43d4a1fbc20d06e890fd63c10 100644
--- a/modules/bindings/src/tmalign.f
+++ b/modules/bindings/src/tmalign.f
@@ -1,3 +1,4 @@
+
 **************************************************************************
 *     This program is to identify the best alignment of two protein 
 *     structures that gives the highest TM-score. Input structures must 
@@ -16,7 +17,7 @@
 *     the Software. It is provided "as is" without express or implied 
 *     warranty.
 ************************ updating history ********************************
-*     2005/06/01: A small bug of two-point superposition was fixed.
+*     2005/06/01: A bug of two-point superposition was fixed.
 *     2005/10/19: the program was reformed so that the alignment
 *                 results are not dependent on the specific compilers.
 *     2006/06/20: select 'A' if there is altLoc when reading PDB file.
@@ -25,7 +26,8 @@
 *                 length, shorter length, or longer length of two 
 *                 structures.
 *     2007/05/23: added additional output file 'TM.sup_all' for showing
-*                 all atoms while 'TM.sup' is only for aligned atoms
+*                 full-chain C-alpha traces while 'TM.sup' is only for 
+*                 aligned regions.
 *     2007/09/19: added a new feature alignment to deal with the problem
 *                 of aligning fractional structures (e.g. protein
 *                 interfaces).
@@ -36,14 +38,41 @@
 *     2009/08/20: A bug for asymmetry alignment result was fixed.
 *     2010/08/02: A new RMSD matrix was used to remove obsolete statements.
 *                 Staled subroutines were deleted.
-*     2011/01/03: The length of pdb file names were extended to 500
-*     2011/01/24: Fixed a bug on output file name created on 2011/01/03
-*     2011/01/30: An open source license is attached to the program
+*     2011/01/03: The length of pdb file names were extended to 500.
+*     2011/01/24: Fixed a bug on output file name created on 2011/01/03.
+*     2011/01/30: An open source license is attached to the program.
+*     2011/09/03: A new option "-d" is added to allow users to change
+*                 TM-score normalization scale. A version number is attached 
+*                 to the program from now on.
+*     2011/10/11: A new scale (d0) was introduced for alignment search. This
+*                 is to mainly improve alignment selection for small proteins 
+*                 (e.g. L<50 residues) but also increase alignment coverage
+*                 of larger proteins. Second, TM-align output format is changed
+*                 and two TM-scores normalized by both chains are reported.
+*     2011/10/12: Distance cutoff for gap is increased from 3.85A to 4.25A.
+*                 Added 'TMalign -v' to allow user to check version number.
+*     2012/01/24: Fix a bug for secondary structure definition
+*     2012/04/16: Add an option to allow user to specify seed alignments, e.g.
+*                 '-i align.txt'. This is used together with other inherent
+*                 TM-align seeds. An example of the fasta file can be seen at
+*                 http://zhanglab.ccmb.med.umich.edu/TM-align/align.txt.
+*     2012/04/17: Add an option '-m matrix.txt' to output the rotation matrix
+*                 in separate file, drop-off secondary-structure smooth 
+*                 procedure, and add one iteration in initial5. This change 
+*                 increases the alignment accuracy (TM-score) by 2%.
+*     2012/04/19: Add additional output file 'TM.sup_atm' 'TM.sup_all_atm' for 
+*                 showing all-atom superposition while 'TM.sup' and 'TM.sup_all' 
+*                 are only for C-alpha traces.
+*     2012/05/07: Improved RMSD calculation subroutine which speeds up TM-algin
+*                 program by 10%.
+*     2012/07/07: Add an option '-I align.txt' to allow user to STICK TO the
+*                 inital alignment. This is different from '-i align.txt' where
+*                 initial alignment can be optimized.
 **************************************************************************
       
       program TMalign
-      PARAMETER(nmax=5000)
-      PARAMETER(nmax2=10000)
+      PARAMETER(nmax=5000)      !maximum length of the sequence
+      PARAMETER(nmax2=10000)    !for alignment output
       
       COMMON/BACKBONE/XA(3,nmax,0:1)
       common/dpc/score(nmax,nmax),gap_open,invmap(nmax)
@@ -53,12 +82,20 @@
       common/d0min/d0_min
       common/d00/d00,d002
       
-      character*500 fnam,pdb(100),outname
+      common/alignment/m_alignment,sequence(10),TM_ali,L_ali,rmsd_ali
+      common/alignment1/m_alignment_stick
+      character*10000 sequence
+      
+      common/sequence/seq1(0:nmax),seq2(0:nmax)
+      character seq1,seq2
+      
+      character*500 fnam,pdb(100),outname,falign,fmatrix
       character*3 aa(-1:20),aanam,ss1(nmax),ss2(nmax)
       character*500 s,du
       character*504 outnameall_tmp,outnameall
-      character seq1(0:nmax),seq2(0:nmax)
       character aseq1(nmax2),aseq2(nmax2),aseq3(nmax2)
+      character*8 version
+      character*5000 s1         !maximum length of protein is 5000
       
       dimension m1(nmax),m2(nmax)
       dimension xtm1(nmax),ytm1(nmax),ztm1(nmax)
@@ -68,6 +105,15 @@
       common/TM/TM,TMmax
       common/d8/d8
       common/initial4/mm1(nmax),mm2(nmax)
+      
+      character*10 aa1,ra1,aa2,ra2
+      dimension ia1(90000),aa1(90000),ra1(90000),ir1(90000)
+      dimension xa1(90000),ya1(90000),za1(90000)
+      dimension ia2(90000),aa2(90000),ra2(90000),ir2(90000)
+      dimension xa2(90000),ya2(90000),za2(90000)
+      
+      dimension ma1(nmax),ma2(nmax)
+      dimension nc1(nmax),nc2(nmax)
 
 ccc   RMSD:
       double precision r_1(3,nmax),r_2(3,nmax),w(nmax)
@@ -94,46 +140,66 @@ ccc
          write(*,*)'(For detail: Zhang & Skolnick, Nucl. Acid. Res.',
      &     ' 33, 2303, 2005)'
          write(*,*)
-         write(*,*)'1. Align ''structure.pdb'' to ''target.pdb'''
-         write(*,*)'  (By default, TM-score is normalized by the ',
-     &        'length of ''target.pdb'')'
-         write(*,*)'  >TMalign structure.pdb target.pdb'
+         write(*,*)'1. Align ''chain_1.pdb'' and ''chain_2.pdb'':'
+         write(*,*)'   >TMalign chain_1.pdb chain_2.pdb'
          write(*,*)
-         write(*,*)'2. Run TM-align and output the superposition ',
-     &        'to ''TM.sup'' and ''TM.sup_all'':'
-         write(*,*)'  >TMalign structure.pdb target.pdb -o TM.sup'
-         write(*,*)'      To view the superimposed structures of the',
+         write(*,*)'2. Ask TM-align to start with an alignment',
+     &        ' specified in fasta file ''align.txt'':'
+         write(*,*)'   >TMalign chain_1.pdb chain_2.pdb -i align.txt'
+         write(*,*)'   or to stick the alignment to ''align.txt'':'
+         write(*,*)'   >TMalign chain_1.pdb chain_2.pdb -I align.txt'
+         write(*,*)
+         write(*,*)'3. Output the superposition to ''TM.sup'', ',
+     &        '''TM.sup_all'' and ''TM.sup_atm'':'
+         write(*,*)'   >TMalign chain_1.pdb chain_2.pdb -o TM.sup'
+         write(*,*)'      To view superimposed C-alpha traces of',
      &        ' aligned regions by rasmol:'
          write(*,*)'        >rasmol -script TM.sup'
-         write(*,*)'      To view the superimposed structures of all',
-     &        ' regions by rasmol:'
+         write(*,*)'      To view superimposed C-alpha traces of',
+     &        ' all regions:'
          write(*,*)'        >rasmol -script TM.sup_all'
+         write(*,*)'      To view superimposed full-atom structures of',
+     &        ' aligned regions:'
+         write(*,*)'        >rasmol -script TM.sup_atm'
+         write(*,*)'      To view superimposed full-atom structures of',
+     &        ' all regions:'
+         write(*,*)'        >rasmol -script TM.sup_all_atm'
          write(*,*)
-         write(*,*)'3. If you want output TM-score normalized by ',
-     &        'an assigned length, e.g. 100 aa:'
-         write(*,*)'  >TMalign structure.pdb target.pdb -L 100'
-         write(*,*)'   If you want TM-score normalized by the ',
-     &        'average length of two structures:'
-         write(*,*)'  >TMalign structure.pdb target.pdb -a'
-         write(*,*)'   If you want TM-score normalized by the ',
-     &        'shorter length of two structures:'
-         write(*,*)'  >TMalign structure.pdb target.pdb -b'
+         write(*,*)'4. There are two TM-scores reported. You ',
+     &        'should use the one normalized by'
+         write(*,*)'   the length of the protein you ',
+     &        'are interested in.'
          write(*,*)'   If you want TM-score normalized by the ',
-     &        'longer length of two structures:'
-         write(*,*)'  >TMalign structure.pdb target.pdb -c'
+     &        'average length of two proteins:'
+         write(*,*)'      >TMalign chain_1.pdb chain_2.pdb -a'
+         write(*,*)'   or TM-score normalized by an ',
+     &        'assigned length (>L_min), e.g. 100 AA:'
+         write(*,*)'      >TMalign chain_1.pdb chain_2.pdb -L 100'
+         write(*,*)'   If you want TM-score scaled by an assigned d0,',
+     &        ' e.g. 5 A:'
+         write(*,*)'      >TMalign chain_1.pdb chain_2.pdb -d 5'
          write(*,*)
-         write(*,*)'(All above options do not change the ',
-     &         'final structure alignment results)'
+         write(*,*)'5. Output TM-align rotation matrix:'
+         write(*,*)'   >TMalign chain_1.pdb chain_2.pdb -m matrix.txt'
          write(*,*)
          goto 9999
       endif
       
+      version='20120707'
+      if(fnam.eq.'-v')then
+         write(*,*)'TM-align Version ',version
+         goto 9999
+      endif
+      
 ******* options ----------->
       m_out=-1                  !decided output
       m_fix=-1                  !fixed length-scale only for output
       m_ave=-1                  !using average length
       m_d0_min=-1               !diminum d0 for search
-      m_d0=-1                   !given d0 for both search and output
+      m_d0=-1                   !given d0 for output
+      m_alignment=-1            !without initial alignment
+      m_alignment_stick=-1      !without initial alignment
+      m_matrix=-1               !no output of matrix
       narg=iargc()
       i=0
       j=0
@@ -144,30 +210,34 @@ ccc
          m_out=1
          i=i+1
          call getarg(i,outname)
+      elseif(fnam.eq.'-a')then  !change superposed output but not the alignment
+         m_ave=1
+         i=i+1
       elseif(fnam.eq.'-L')then  !change both L_all and d0
          m_fix=1
          i=i+1
          call getarg(i,fnam)
          read(fnam,*)L_fix
-      elseif(fnam.eq.'-dmin')then
-         m_d0_min=1
-         i=i+1
-         call getarg(i,fnam)
-         read(fnam,*)d0_min_input
-      elseif(fnam.eq.'-d0')then
+      elseif(fnam.eq.'-d')then
          m_d0=1
          i=i+1
          call getarg(i,fnam)
          read(fnam,*)d0_fix
-      elseif(fnam.eq.'-a')then  !change superposed output but not the alignment
-         m_ave=1
+      elseif(fnam.eq.'-i')then
+         m_alignment=1
          i=i+1
-      elseif(fnam.eq.'-b')then
-        m_ave=2
+         call getarg(i,fnam)
+         falign=fnam
+      elseif(fnam.eq.'-I')then
+         m_alignment_stick=1
          i=i+1
-      elseif(fnam.eq.'-c')then
-        m_ave=3
+         call getarg(i,fnam)
+         falign=fnam
+      elseif(fnam.eq.'-m')then
+         m_matrix=1
          i=i+1
+         call getarg(i,fnam)
+         fmatrix=fnam
       else
          j=j+1
          pdb(j)=fnam
@@ -177,15 +247,20 @@ ccc
 ccccccccc read data from first CA file:
       open(unit=10,file=pdb(1),status='old')
       i=0
+      na1=0
       do while (.true.)
          read(10,9001,end=1010) s
          if(i.gt.0.and.s(1:3).eq.'TER')goto 1010
          if(s(1:3).eq.'ATO')then
+            na1=na1+1
+            if(na1.ge.90000)goto 1010
+            read(s,8999)du,ia1(na1),du,aa1(na1),du,ra1(na1),du,
+     &           ir1(na1),du,xa1(na1),ya1(na1),za1(na1)
             if(s(13:16).eq.'CA  '.or.s(13:16).eq.' CA '.or
      &           .s(13:16).eq.'  CA')then
                if(s(17:17).eq.' '.or.s(17:17).eq.'A')then
                   i=i+1
-                  read(s,9000)du,aanam,du,mm1(i),du,
+                  read(s,9000)du,ma1(i),du,aanam,du,mm1(i),du,
      $                 xa(1,i,0),xa(2,i,0),xa(3,i,0)
                   do j=-1,20
                      if(aanam.eq.aa(j))then
@@ -202,7 +277,8 @@ ccccccccc read data from first CA file:
          endif
       enddo
  1010 continue
- 9000 format(A17,A3,A2,i4,A4,3F8.3)
+ 8999 format(a6,I5,a1,A4,a1,A3,a2,I4,a4,3F8.3)
+ 9000 format(a6,I5,a6,A3,A2,i4,A4,3F8.3)
  9001 format(A100)
       close(10)
       nseq1=i
@@ -211,15 +287,20 @@ c^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 ccccccccc read data from the second CA file:
       open(unit=10,file=pdb(2),status='old')
       i=0
+      na2=0
       do while (.true.)
          read(10,9001,end=1011) s
          if(i.gt.0.and.s(1:3).eq.'TER')goto 1011
          if(s(1:3).eq.'ATO')then
+            na2=na2+1
+            if(na2.ge.90000)goto 1011
+            read(s,8999)du,ia2(na2),du,aa2(na2),du,ra2(na2),du,
+     &           ir2(na2),du,xa2(na2),ya2(na2),za2(na2)
             if(s(13:16).eq.'CA  '.or.s(13:16).eq.' CA '.or.
      &           s(13:16).eq.'  CA')then
                if(s(17:17).eq.' '.or.s(17:17).eq.'A')then
                   i=i+1
-                  read(s,9000)du,aanam,du,mm2(i),du,
+                  read(s,9000)du,ma2(i),du,aanam,du,mm2(i),du,
      $                 xa(1,i,1),xa(2,i,1),xa(3,i,1)
                   do j=-1,20
                      if(aanam.eq.aa(j))then
@@ -240,21 +321,54 @@ ccccccccc read data from the second CA file:
       nseq2=i
 c^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       
-*     Scale of TM-score in search is based on the smaller protein --------->
-      d0_min=0.5
-      if(m_d0_min.eq.1)then
-         d0_min=d0_min_input    !for search
+ccccccccc read initial alignment file from 'alignment.txt':
+      if(m_alignment.eq.1.or.m_alignment_stick.eq.1)then
+         open(unit=10,file=falign,status='old')
+         n_p=0
+         do while (.true.)
+            read(10,9002,end=1012)s1
+c            write(*,*)'s1=',trim(s1)
+            if(s1(1:1).eq.">")then
+               n_p=n_p+1
+               sequence(n_p)=''
+               if(n_p.gt.2)goto 1012
+            else
+               if(n_p.gt.0)then
+                  sequence(n_p)=trim(sequence(n_p))//trim(s1)
+c                  write(*,*)n_p,trim(sequence(n_p))
+               endif
+            endif
+         enddo
+ 1012    continue
+         close(10)
+c         write(*,*)trim(sequence(1))
+c         write(*,*)trim(sequence(2))
+         if(n_p.lt.2)then
+            write(*,*)'ERROR: FASTA format is wrong, two proteins',
+     &           ' should be included'
+            stop
+         endif
+         if(len_trim(sequence(1)).ne.len_trim(sequence(2)))then
+            write(*,*)'Warning: FASTA format may be wrong, the',
+     &           ' length in alignment should be equal. But we',
+     &           ' run it anyway'
+         endif
       endif
-      anseq_min=min(nseq1,nseq2)
+ 9002 format(A5000)
+c^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+      
+*     Scale of TM-score in search based on length of smaller protein --------->
+      anseq_min=min(nseq1,nseq2) !both search and d8_cut use nseq_min
       anseq=anseq_min           !length for defining TMscore in search
       d8=1.5*anseq_min**0.3+3.5 !remove pairs with dis>d8 during search & final
-      if(anseq.gt.15)then
+      if(anseq.gt.19)then       !L=19, d0=0.168
          d0=1.24*(anseq-15)**(1.0/3.0)-1.8 !scale for defining TM-score
       else
-         d0=d0_min
+         d0=0.168
       endif
-      if(d0.lt.d0_min)d0=d0_min
-      if(m_d0.eq.1)d0=d0_fix
+      d0_min=d0+0.8             !best for search, this should be changed when calculate real TM-score
+      if(d0.lt.d0_min)d0=d0_min !min d0 in search=0.968, min d0 in output=0.5
+c     write(*,*)'d0 in search=',d0 
       d00=d0                    !for quickly calculate TM-score in searching
       if(d00.gt.8)d00=8
       if(d00.lt.4.5)d00=4.5
@@ -262,10 +376,10 @@ c^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       nseq=max(nseq1,nseq2)
       
 ***** do alignment **************************
-      CALL TM_align          !to find invmap(j)
+      CALL TM_align             !to find invmap(j)
       
 ************************************************************
-***   resuperpose to find residues of dis<d8 ------------------------>
+***   Refine alignment by cutting dis>d8 ------------------------>
       n_al=0
       do j=1,nseq2
          if(invmap0(j).gt.0)then
@@ -281,33 +395,15 @@ c^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
             m2(n_al)=j
          endif
       enddo
-      d0_input=d0
+      d0_input=d0               !scaled by seq_min
       call TMscore8(d0_input,n_al,xtm1,ytm1,ztm1,n_al,
      &     xtm2,ytm2,ztm2,TM,Rcomm,Lcomm) !TM-score with dis<d8 only
-
-*     Output TM-score is based on the second protein------------------>
-      d0_min=0.5                !for output
-      anseq=nseq2               !length for defining final TMscore
-      if(m_ave.eq.1)anseq=(nseq1+nseq2)/2.0 !<L>
-      if(m_ave.eq.2)anseq=min(nseq1,nseq2)
-      if(m_ave.eq.3)anseq=max(nseq1,nseq2)
-      if(anseq.lt.anseq_min)anseq=anseq_min
-      if(m_fix.eq.1)anseq=L_fix !input length
-      if(anseq.gt.15)then
-         d0=1.24*(anseq-15)**(1.0/3.0)-1.8 !scale for defining TM-score
-      else
-         d0=d0_min
-      endif
-      if(d0.lt.d0_min)d0=d0_min
-      if(m_d0.eq.1)d0=d0_fix
-      
-***   remove dis>d8 in normal TM-score calculation for final report----->
       j=0
       n_eq=0
       do i=1,n_al
          dis2=sqrt((xtm1(i)-xtm2(i))**2+(ytm1(i)-ytm2(i))**2+
      &        (ztm1(i)-ztm2(i))**2)
-         if(dis2.le.d8)then
+         if(dis2.le.d8.or.m_alignment_stick.eq.1)then
             j=j+1
             xtm1(j)=xtm1(i)
             ytm1(j)=ytm1(i)
@@ -315,119 +411,238 @@ c^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
             xtm2(j)=xtm2(i)
             ytm2(j)=ytm2(i)
             ztm2(j)=ztm2(i)
-            m1(j)=m1(i)
+
+            r_1(1,j)=xtm1(i)
+            r_1(2,j)=ytm1(i)
+            r_1(3,j)=ztm1(i)
+            r_2(1,j)=xtm2(i)
+            r_2(2,j)=ytm2(i)
+            r_2(3,j)=ztm2(i)
+            
+            m1(j)=m1(i)         !record alignment
             m2(j)=m2(i)
             if(ss1(m1(i)).eq.ss2(m2(i)))then
                n_eq=n_eq+1
             endif
          endif
       enddo
-      seq_id=float(n_eq)/(n_al+0.00000001)
       n8_al=j
+      seq_id=float(n_eq)/(n8_al+0.00000001)
+      call u3b(w,r_1,r_2,n8_al,0,rms,u,t,ier)
+      rmsd=dsqrt(rms/n8_al)
+c      write(*,*)'---------',rms,n8_al,RMSD,u(1,1),t(1)
+      
+*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+*^^^^^^^ alignment is done, all cutoffs were based on shorter chain^^^^^^^^
+*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+************************************************************
+***   Output TM-score -------------------------->
+      d0_out=5                  !only for showing residue-pair distance
+      d0_min=0.5                !for TM-score output, consistent stdrd TM-score
+*     Based on Chain_1===>
+      anseq=nseq1
+      if(anseq.gt.21)then
+         d0=1.24*(anseq-15)**(1.0/3.0)-1.8 !scale for defining TM-score
+      else
+         d0=d0_min
+      endif
+      if(d0.lt.d0_min)d0=d0_min
       d0_input=d0
       call TMscore(d0_input,n8_al,xtm1,ytm1,ztm1,n8_al,
      &     xtm2,ytm2,ztm2,TM8,Rcomm,Lcomm) !normal TMscore
-      rmsd8_al=Rcomm
-      TM8=TM8*n8_al/anseq       !TM-score after cutoff
-
-      
+      TM1=TM8*n8_al/anseq
+*     Based on Chain_2===>
+      anseq=nseq2
+      if(anseq.gt.21)then
+         d0=1.24*(anseq-15)**(1.0/3.0)-1.8 !scale for defining TM-score
+      else
+         d0=d0_min
+      endif
+      if(d0.lt.d0_min)d0=d0_min
+      d0_input=d0
+      call TMscore(d0_input,n8_al,xtm1,ytm1,ztm1,n8_al,
+     &     xtm2,ytm2,ztm2,TM8,Rcomm,Lcomm) !normal TMscore
+      TM2=TM8*n8_al/anseq
+*     Based on Average length===>
+      if(m_ave.eq.1)then
+         anseq=(nseq1+nseq2)/2.0
+         if(anseq.gt.21)then
+            d0=1.24*(anseq-15)**(1.0/3.0)-1.8 !scale for defining TM-score
+         else
+            d0=d0_min
+         endif
+         if(d0.lt.d0_min)d0=d0_min
+         d0_input=d0
+         call TMscore(d0_input,n8_al,xtm1,ytm1,ztm1,n8_al,
+     &        xtm2,ytm2,ztm2,TM8,Rcomm,Lcomm) !normal TMscore
+         TM12=TM8*n8_al/anseq
+      endif
+*     Based on assigned length===>
+      if(m_fix.eq.1)then
+         anseq=L_fix            !input length
+         if(anseq.gt.21)then
+            d0=1.24*(anseq-15)**(1.0/3.0)-1.8 !scale for defining TM-score
+         else
+            d0=d0_min
+         endif
+         if(d0.lt.d0_min)d0=d0_min
+         d0_input=d0
+         call TMscore(d0_input,n8_al,xtm1,ytm1,ztm1,n8_al,
+     &        xtm2,ytm2,ztm2,TM8,Rcomm,Lcomm) !normal TMscore
+         TML=TM8*n8_al/anseq
+      endif
+*     Based on user-specified d0===>
+      if(m_d0.eq.1)then
+         d0=d0_fix
+         d0_out=d0_fix
+         d0_input=d0
+         call TMscore(d0_input,n8_al,xtm1,ytm1,ztm1,n8_al,
+     &        xtm2,ytm2,ztm2,TM8,Rcomm,Lcomm) !normal TMscore
+         TMfix=TM8*n8_al/nseq2
+      endif
       
 ********* for output summary ******************************
       write(*,*)
       write(*,*)'*****************************************************',
      &     '*********************'
-      write(*,*)'*                               TM-align             ',
-     &     '                    *'
-      write(*,*)'* A protein structural alignment algorithm based on T',
-     &     'M-score             *'
-      write(*,*)'* Reference: Y. Zhang and J. Skolnick, Nucl. Acids Re',
-     &     's. 2005 33, 2302-9  *'
-      write(*,*)'* Comments on the program, please email to: zhng@umic',
-     &     'h.edu               *'
+      write(*,*)'* TM-align (Version ',version,
+     &     '): A protein structural a',
+     &     'lignment algorithm  *'
+      write(*,*)'* Reference: Y Zhang and J Skolnick, Nucl Acids Res 3',
+     &     '3, 2302-9 (2005)    *'
+      write(*,*)'* Please email your comments and suggestions to: zhng',
+     &     '@umich.edu          *'
       write(*,*)'*****************************************************',
      &     '*********************'
       write(*,*)
-      write(*,101)pdb(1),nseq1
- 101  format('Chain 1:',A10,'  Size=',I4)
-      write(*,102)pdb(2),nseq2,int(anseq)
- 102  format('Chain 2:',A10,'  Size=',I4,
-     &     ' (TM-score is normalized by ',I4,')')
+      write(*,101)pdb(1)
+ 101  format('Name of Chain_1: ',A50)
+      write(*,102)pdb(2)
+ 102  format('Name of Chain_2: ',A50)
+      write(*,103)nseq1
+ 103  format('Length of Chain_1: ',I4,' residues')
+      write(*,201)nseq2
+ 201  format('Length of Chain_2: ',I4,' residues')
+      
+      if(m_alignment.eq.1.or.m_alignment_stick.eq.1)then
+         write(*,72)TM_ali,L_ali,rmsd_ali
+ 72      format('User-specified initial alignment: TM/Lali/rmsd= ',
+     &        f7.5,', ',I4,', ',f6.3)
+      endif
+      
       write(*,*)
-      write(*,103)n8_al,rmsd8_al,TM8,seq_id
- 103  format('Aligned length=',I4,', RMSD=',f6.2,
-     &     ', TM-score=',f7.5,', ID=',f5.3)
+      write(*,203)n8_al,rmsd,seq_id
+ 203  format('Aligned length= ',I4,', RMSD= ',f6.2,
+     &     ', Seq_ID=n_identical/n_aligned= ',f5.3)
+      write(*,204)TM1
+ 204  format('TM-score= ',f7.5,' (if normalized by length of Chain_1)')
+      write(*,205)TM2
+ 205  format('TM-score= ',f7.5,' (if normalized by length of Chain_2)')
+      if(m_ave.eq.1)then
+         write(*,206)TM12,(nseq1+nseq2)/2.0
+ 206     format('TM-score= ',f7.5,
+     &        ' (if normalized by average length of chains =',f6.1,')')
+      endif
+      if(m_fix.eq.1)then
+         write(*,207)TML,L_fix
+ 207     format('TM-score= ',f7.5,
+     &        ' (if scaled by user-specified L=',I4,')')
+      endif
+      if(m_d0.eq.1)then
+         write(*,208)TMfix,d0_fix
+ 208     format('TM-score= ',f7.5,
+     &        ' (if scaled by user-specified d0=',f4.1,')')
+      endif
+      write(*,210)
+ 210  format('(You should use TM-score normalized by length',
+     &     ' of the reference protein)')
       write(*,*)
 
-********* extract rotation matrix ------------>
-      L=0
-      do i=1,n8_al
-         k=m1(i)
-         L=L+1
-         r_1(1,L)=xa(1,k,0)
-         r_1(2,L)=xa(2,k,0)
-         r_1(3,L)=xa(3,k,0)
-         r_2(1,L)=xtm1(i)
-         r_2(2,L)=ytm1(i)
-         r_2(3,L)=ztm1(i)
-       enddo
-       if(L.gt.3)then
-         call u3b(w,r_1,r_2,L,1,rms,u,t,ier) !u rotate r_1 to r_2
-         write(*,*)'-------- Rotation matrix to rotate Chain-1 to ',
-     &        'Chain-2 ------'
-         write(*,*)'m          t(m)         u(m,1)         u(m,2) ',
+********* extract rotation matrix based on TMscore8 ------------>
+      if(m_matrix.eq.1.or.m_out.eq.1)then !we need to extract rotation matrix
+         L=0
+         do i=1,n8_al
+            k=m1(i)
+            L=L+1
+            r_1(1,L)=xa(1,k,0)
+            r_1(2,L)=xa(2,k,0)
+            r_1(3,L)=xa(3,k,0)
+            r_2(1,L)=xtm1(i)
+            r_2(2,L)=ytm1(i)
+            r_2(3,L)=ztm1(i)
+         enddo
+         if(L.le.3)then
+            write(*,*)'Aligned length is too short,',
+     &           ' no matrix outout'
+            goto 211
+         endif
+         call u3b(w,r_1,r_2,L,1,rms,u,t,ier) !u rotate r_1 to r_2, this will be used by whole-chain
+ 211     continue
+      endif
+
+********* output rotation matrix -------------------------->
+      if(m_matrix.eq.1)then
+         open(unit=1,file=fmatrix,status='unknown')
+         write(1,*)'-------- Rotation matrix to rotate Chain_1 to ',
+     &        'Chain_2 ------'
+         write(1,*)'m          t(m)         u(m,1)         u(m,2) ',
      &        '        u(m,3)'
          do i=1,3
-            write(*,204)i,t(i),u(i,1),u(i,2),u(i,3)
+            write(1,209)i,t(i),u(i,1),u(i,2),u(i,3)
          enddo
-         write(*,*)'Code for rotating Chain-1 from (x,y,z) to (X,Y,Z):'
-         write(*,*)'  do i=1,L'
-         write(*,*)'    X(i)=t(1)+u(1,1)*x(i)+u(1,2)*y(i)+u(1,3)*z(i)'
-         write(*,*)'    Y(i)=t(2)+u(2,1)*x(i)+u(2,2)*y(i)+u(2,3)*z(i)'
-         write(*,*)'    Z(i)=t(3)+u(3,1)*x(i)+u(3,2)*y(i)+u(3,3)*z(i)'
-         write(*,*)'  enddo'
-         write(*,*)
+         write(1,*)'Code for rotating Chain_1 from (x,y,z) to (X,Y,Z):'
+         write(1,*)'   do i=1,L'
+         write(1,*)'     X(i)=t(1)+u(1,1)*x(i)+u(1,2)*y(i)+u(1,3)*z(i)'
+         write(1,*)'     Y(i)=t(2)+u(2,1)*x(i)+u(2,2)*y(i)+u(2,3)*z(i)'
+         write(1,*)'     Z(i)=t(3)+u(3,1)*x(i)+u(3,2)*y(i)+u(3,3)*z(i)'
+         write(1,*)'   enddo'
+         write(1,*)
+         close(1)
+ 209     format(I2,f18.10,f15.10,f15.10,f15.10)
       endif
- 204  format(I2,f18.10,f15.10,f15.10,f15.10)
       
-********* for output superposition ******************************
+********* output superposition ******************************
       if(m_out.eq.1)then
- 1237    format('ATOM  ',i5,'  CA  ',A3,I6,4X,3F8.3)
+c     11, output superimpostion in the aligned regions ------------->
+ 1236    format('ATOM  ',i5,'  CA  ',A3,' A',I4,4X,3F8.3)
+ 1237    format('ATOM  ',i5,'  CA  ',A3,' B',I4,4X,3F8.3)
  1238    format('TER')
  1239    format('CONECT',I5,I5)
  900     format(A)
- 901     format('select atomno=',I4)
+ 902     format('select ',I4,':A,',I4,':B')
+ 903     format('REMARK TM-align Version ',A8,'')
  104     format('REMARK Chain 1:',A10,'  Size=',I4)
  105     format('REMARK Chain 2:',A10,'  Size=',I4,
-     &        ' (TM-score is normalized by ',I4,')')
+     &        ' (TM-score is normalized by ',I4,', d0=',f6.2,')')
  106     format('REMARK Aligned length=',I4,', RMSD=',f6.2,
      &        ', TM-score=',f7.5,', ID=',f5.3)
-         OPEN(unit=7,file=outname,status='unknown') !pdb1.aln + pdb2.aln
+         OPEN(unit=7,file=outname,status='unknown') !TM.sup=pdb1.aln + pdb2.aln
 ***   script:
          write(7,900)'load inline'
-         write(7,900)'select atomno<2000'
+         write(7,900)'select *A'
          write(7,900)'wireframe .45'
-         write(7,900)'select none'
-         write(7,900)'select atomno>2000'
+         write(7,900)'select *B'
          write(7,900)'wireframe .20'
+         write(7,900)'select all'
          write(7,900)'color white'
          do i=1,n8_al
             dis2=sqrt((xtm1(i)-xtm2(i))**2+
      &           (ytm1(i)-ytm2(i))**2+(ztm1(i)-ztm2(i))**2)
-            if(dis2.le.5)then
-               write(7,901)m1(i)
-               write(7,900)'color red'
-               write(7,901)2000+m2(i)
+            if(dis2.le.d0_out)then
+               write(7,902)mm1(m1(i)),mm2(m2(i))
                write(7,900)'color red'
             endif
          enddo
          write(7,900)'select all'
          write(7,900)'exit'
+         write(7,903)version
          write(7,104)pdb(1),nseq1
-         write(7,105)pdb(2),nseq2,int(anseq)
-         write(7,106)n8_al,rmsd8_al,TM8,seq_id
+         write(7,105)pdb(2),nseq2,int(anseq),d0
+         write(7,106)n8_al,rmsd,TM2,seq_id
 ***   chain1:
          do i=1,n8_al
-            write(7,1237)m1(i),ss1(m1(i)),mm1(m1(i)),
+            write(7,1236)m1(i),ss1(m1(i)),mm1(m1(i)),
      &           xtm1(i),ytm1(i),ztm1(i)
          enddo
          write(7,1238)          !TER
@@ -436,69 +651,132 @@ c^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
          enddo
 ***   chain2:
          do i=1,n8_al
-            write(7,1237)2000+m2(i),ss2(m2(i)),mm2(m2(i)),
+            write(7,1237)5000+m2(i),ss2(m2(i)),mm2(m2(i)),
      $           xtm2(i),ytm2(i),ztm2(i)
          enddo
          write(7,1238)
          do i=2,n8_al
-            write(7,1239)2000+m2(i-1),2000+m2(i)
+            write(7,1239)5000+m2(i-1),5000+m2(i)
          enddo
          close(7)
-ccc   
-         k=0
-         outnameall_tmp=outname//'_all'
-         outnameall=''
-         do i=1,504
-            if(outnameall_tmp(i:i).ne.' ')then
-               k=k+1
-               outnameall(k:k)=outnameall_tmp(i:i)
-            endif
-         enddo
+c     22, output CA-trace of whole chain in 'TM.sup_all' -------->
+         outnameall=trim(outname)//'_all'
          OPEN(unit=8,file=outnameall,status='unknown') !pdb1.aln + pdb2.aln
 ***   script:
          write(8,900)'load inline'
-         write(8,900)'select atomno<2000'
+         write(8,900)'select *A'
          write(8,900)'wireframe .45'
          write(8,900)'select none'
-         write(8,900)'select atomno>2000'
+         write(8,900)'select *B'
          write(8,900)'wireframe .20'
          write(8,900)'color white'
          do i=1,n8_al
             dis2=sqrt((xtm1(i)-xtm2(i))**2+
      &           (ytm1(i)-ytm2(i))**2+(ztm1(i)-ztm2(i))**2)
-            if(dis2.le.5)then
-               write(8,901)m1(i)
-               write(8,900)'color red'
-               write(8,901)2000+m2(i)
+            if(dis2.le.d0_out)then
+               write(8,902)mm1(m1(i)),mm2(m2(i)) !select residue
                write(8,900)'color red'
             endif
          enddo
          write(8,900)'select all'
          write(8,900)'exit'
+         write(8,903)version
          write(8,104)pdb(1),nseq1
-         write(8,105)pdb(2),nseq2,int(anseq)
-         write(8,106)n8_al,rmsd8_al,TM8,seq_id
+         write(8,105)pdb(2),nseq2,int(anseq),d0
+         write(8,106)n8_al,rmsd,TM2,seq_id
 ***   chain1:
          do i=1,nseq1
             ax=t(1)+u(1,1)*xa(1,i,0)+u(1,2)*xa(2,i,0)+u(1,3)*xa(3,i,0)
             ay=t(2)+u(2,1)*xa(1,i,0)+u(2,2)*xa(2,i,0)+u(2,3)*xa(3,i,0)
             az=t(3)+u(3,1)*xa(1,i,0)+u(3,2)*xa(2,i,0)+u(3,3)*xa(3,i,0)
-            write(8,1237)i,ss1(i),mm1(i),ax,ay,az
+            write(8,1236)i,ss1(i),mm1(i),ax,ay,az
          enddo
          write(8,1238)          !TER
          do i=2,nseq1
-            write(8,1239)i-1,i
+            write(8,1239)i-1,i !CONECT atom numbers
          enddo
 ***   chain2:
          do i=1,nseq2
-            write(8,1237)2000+i,ss2(i),mm2(i),
+            write(8,1237)5000+i,ss2(i),mm2(i),
      $           xa(1,i,1),xa(2,i,1),xa(3,i,1)
          enddo
          write(8,1238)
          do i=2,nseq2
-            write(8,1239)2000+i-1,2000+i
+            write(8,1239)5000+i-1,5000+i
+         enddo
+         close(8)
+c     33, output full-atomic structure of whole chain in 'TM.sup_atm' -------->
+         outnameall=trim(outname)//'_atm'
+         OPEN(unit=8,file=outnameall,status='unknown') !pdb1.aln + pdb2.aln
+***   script:
+         write(8,900)'load inline'
+         write(8,900)'select *A'
+         write(8,900)'color blue'
+         write(8,900)'select *B'
+         write(8,900)'color red'
+         write(8,900)'select all'
+         write(8,900)'cartoon'
+         write(8,900)'exit'
+         write(8,903)version
+         write(8,104)pdb(1),nseq1
+         write(8,105)pdb(2),nseq2,int(anseq),d0
+         write(8,106)n8_al,rmsd,TM2,seq_id
+***   chain1:
+         do i=1,na1
+            do j=1,n8_al
+               if(ir1(i).eq.mm1(m1(j)))then !aligned residues
+                  ax=t(1)+u(1,1)*xa1(i)+u(1,2)*ya1(i)+u(1,3)*za1(i)
+                  ay=t(2)+u(2,1)*xa1(i)+u(2,2)*ya1(i)+u(2,3)*za1(i)
+                  az=t(3)+u(3,1)*xa1(i)+u(3,2)*ya1(i)+u(3,3)*za1(i)
+                  write(8,8888)ia1(i),aa1(i),ra1(i),ir1(i),ax,ay,az
+               endif
+            enddo
+         enddo
+         write(8,1238)          !TER
+***   chain2:
+         do i=1,na2
+            do j=1,n8_al
+               if(ir2(i).eq.mm2(m2(j)))then !aligned residues
+                  write(8,8889)ia2(i),aa2(i),ra2(i),ir2(i),
+     &                 xa2(i),ya2(i),za2(i)
+               endif
+            enddo
          enddo
+         write(8,1238)          !TER
          close(8)
+c     44, output full-atomic structure of whole chain in 'TM.sup_all_atm' -------->
+         outnameall=trim(outname)//'_all_atm'
+         OPEN(unit=8,file=outnameall,status='unknown') !pdb1.aln + pdb2.aln
+***   script:
+         write(8,900)'load inline'
+         write(8,900)'select *A'
+         write(8,900)'color blue'
+         write(8,900)'select *B'
+         write(8,900)'color red'
+         write(8,900)'select all'
+         write(8,900)'cartoon'
+         write(8,900)'exit'
+         write(8,903)version
+         write(8,104)pdb(1),nseq1
+         write(8,105)pdb(2),nseq2,int(anseq),d0
+         write(8,106)n8_al,rmsd,TM2,seq_id
+***   chain1:
+         do i=1,na1
+            ax=t(1)+u(1,1)*xa1(i)+u(1,2)*ya1(i)+u(1,3)*za1(i)
+            ay=t(2)+u(2,1)*xa1(i)+u(2,2)*ya1(i)+u(2,3)*za1(i)
+            az=t(3)+u(3,1)*xa1(i)+u(3,2)*ya1(i)+u(3,3)*za1(i)
+            write(8,8888)ia1(i),aa1(i),ra1(i),ir1(i),ax,ay,az
+         enddo
+         write(8,1238)          !TER
+***   chain2:
+         do i=1,na2
+            write(8,8889)ia2(i),aa2(i),ra2(i),ir2(i),
+     &           xa2(i),ya2(i),za2(i)
+         enddo
+         write(8,1238)          !TER
+         close(8)
+ 8888    format('ATOM  ',I5,1x,A4,1x,A3,' A',I4,4x,3F8.3)
+ 8889    format('ATOM  ',I5,1x,A4,1x,A3,' B',I4,4x,3F8.3)
       endif
 *^^^^^^^^^^^^^^^^^^ output finished ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
@@ -524,7 +802,7 @@ ccc
          aseq2(ii)=seq2(m2(i))
          dis2=sqrt((xtm1(i)-xtm2(i))**2+
      &     (ytm1(i)-ytm2(i))**2+(ztm1(i)-ztm2(i))**2)
-         if(dis2.le.5)then
+         if(dis2.le.d0_out)then
            aseq3(ii)=':'
          else
            aseq3(ii)='.'
@@ -544,9 +822,9 @@ ccc
          aseq2(ii)=seq2(i)
          aseq3(ii)=' '
       enddo
-      write(*,50)
- 50   format('(":" denotes residue pairs of d < 5 Angstrom,',
-     &     ' "." denotes other aligned residues)')
+      write(*,50)d0_out
+ 50   format('(":" denotes aligned residue pairs of d < ',f3.1,
+     &     ' A, "." denotes other aligned residues)')
       write(*,10)(aseq1(i),i=1,ii)
       write(*,10)(aseq3(i),i=1,ii)
       write(*,10)(aseq2(i),i=1,ii)
@@ -572,17 +850,62 @@ c^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       common/zscore/zrms,n_al,rmsd_al
       common/TM/TM,TMmax
       common/init/invmap_i(nmax)
+      common/d0/d0,anseq
       dimension gapp(100)
       
+      common/alignment/m_alignment,sequence(10),TM_ali,L_ali,rmsd_ali
+      common/alignment1/m_alignment_stick
+      character*10000 sequence
+      
       TMmax=0
       n_gapp=2
       gapp(1)=-0.6
       gapp(2)=0
       
+      ddcc=0.4
+      if(anseq.le.40)then
+         ddcc=0.1
+      endif
+      
+ccc   stick to the initial alignment -------------->
+      if(m_alignment_stick.eq.1)then
+         do j=1,nseq2
+            invmap(j)=-1
+         enddo
+         i1=0
+         i2=0
+         L1=LEN_TRIM(sequence(1))
+         L2=LEN_TRIM(sequence(2))
+         L=L1
+         if(L2.lt.L)L=L2
+         do 6661 i=1,L
+            if(sequence(1)(i:i).ne.'-')i1=i1+1
+            if(sequence(2)(i:i).ne.'-')then
+               i2=i2+1
+               if(i2.gt.nseq2)then
+                  goto 6661
+               endif
+               if(sequence(1)(i:i).ne.'-')then
+                  invmap(i2)=i1
+               endif
+            endif
+ 6661    enddo
+         call standard_TMscore(TM_ali,L_ali,rmsd_ali) !calc TM-score from invmap, nmlzd by nseq2
+ccc   
+         call get_score         !TM, matrix score(i,j)
+         if(TM.gt.TMmax)then
+            TMmax=TM
+            do j=1,nseq2
+               invmap0(j)=invmap(j)
+            enddo
+         endif
+         return
+      endif
+      
 *11111111111111111111111111111111111111111111111111111111
 *     get initial alignment from gapless threading
 **********************************************************
-      call get_initial          !gapless threading
+      call get_initial1          !gapless threading
       do i=1,nseq2
          invmap(i)=invmap_i(i)  !with highest zcore
       enddo
@@ -681,7 +1004,7 @@ c     record the best alignment in whole search ---------->
             invmap0(j)=invmap(j)
          enddo
       endif
-      if(TM.le.TMmax*0.8)goto 5555
+      if(TM.le.TMmax*ddcc)goto 5555
 *****************************************************************
 *     initerative alignment, for different gap_open:
 *****************************************************************
@@ -724,7 +1047,7 @@ c     record the best alignment in whole search ---------->
             invmap0(j)=invmap(j)
          enddo
       endif
-      if(TM.le.TMmax*0.2)goto 3333
+      if(TM.le.TMmax*ddcc)goto 3333
 *****************************************************************
 *     initerative alignment, for different gap_open:
 *****************************************************************
@@ -768,7 +1091,7 @@ c     record the best alignment in whole search ---------->
             invmap0(j)=invmap(j)
          enddo
       endif
-      if(TM.le.TMmax*0.3)goto 4444
+      if(TM.le.TMmax*ddcc)goto 4444
 *****************************************************************
 *     initerative alignment, for different gap_open:
 *****************************************************************
@@ -790,7 +1113,76 @@ c     record the best alignment in whole search ---------->
  44      continue
  4    continue
  4444 continue
-
+      
+*666666666666666666666666666666666666666666666666666666666666
+*     get initial alignment from user's input:
+*************************************************************
+      if(m_alignment.ne.1)goto 6666
+      do j=1,nseq2
+         invmap(j)=-1
+      enddo
+      i1=0
+      i2=0
+      L1=LEN_TRIM(sequence(1))
+      L2=LEN_TRIM(sequence(2))
+c     write(*,*)'seq1= ',trim(sequence(1))
+c     write(*,*)'seq2= ',trim(sequence(2))
+      L=L1
+      if(L2.lt.L)L=L2
+      do 666 i=1,L
+c         write(*,*)i,sequence(1)(i:i),sequence(2)(i:i)
+         if(sequence(1)(i:i).ne.'-')i1=i1+1
+         if(sequence(2)(i:i).ne.'-')then
+            i2=i2+1
+            if(i2.gt.nseq2)then
+               goto 666
+            endif
+            if(sequence(1)(i:i).ne.'-')then
+               invmap(i2)=i1
+c               write(*,*)i2,i1
+            endif
+         endif
+ 666  enddo
+ccc   
+c      L_ali=0
+c      do j=1,nseq2
+c     write(*,*)j,invmap(j)
+c         if(invmap(j).gt.0)then
+c            L_ali=L_ali+1
+c         endif
+c      enddo
+c     write(*,*)'L_ali=',L_ali
+      call standard_TMscore(TM_ali,L_ali,rmsd_ali) !calc TM-score from invmap, nmlzd by nseq2
+ccc   
+      call get_score            !TM, matrix score(i,j)
+      if(TM.gt.TMmax)then
+         TMmax=TM
+         do j=1,nseq2
+            invmap0(j)=invmap(j)
+         enddo
+      endif
+*****************************************************************
+*     initerative alignment, for different gap_open:
+*****************************************************************
+      DO 6 i_gapp=1,n_gapp	!different gap panalties
+         GAP_OPEN=gapp(i_gapp)  !gap panalty
+         do 66 id=1,30          !maximum interation is 200
+            call DP(NSEQ1,NSEQ2) !produce alignment invmap(j)
+*     Input: score(i,j), and gap_open
+*     Output: invmap(j)
+            
+            call get_score      !calculate TM-score, score(i,j)
+c     record the best alignment in whole search ---------->
+            if(TM.gt.TMmax)then
+               TMmax=TM
+               do j=1,nseq2
+                  invmap0(j)=invmap(j)
+               enddo
+            endif
+ 66      continue
+ 6    continue
+ 6666 continue
+      
 c^^^^^^^^^^^^^^^ best alignment invmap0(j) found ^^^^^^^^^^^^^^^^^^
       RETURN
       END
@@ -798,7 +1190,7 @@ c^^^^^^^^^^^^^^^ best alignment invmap0(j) found ^^^^^^^^^^^^^^^^^^
 **************************************************************
 *     get initial alignment invmap0(i) from gapless threading
 **************************************************************
-      subroutine get_initial
+      subroutine get_initial1
       PARAMETER(nmax=5000)
       COMMON/BACKBONE/XA(3,nmax,0:1)
       common/length/nseq1,nseq2
@@ -889,8 +1281,7 @@ c     1->coil, 2->helix, 3->turn, 4->strand
             jsec(i)=make_sec(dis13,dis14,dis15,dis24,dis25,dis35)
          endif
       enddo
-      call smooth               !smooth the assignment
-
+      
 ********** score matrix **************************
       do i=1,nseq1
          do j=1,nseq2
@@ -901,7 +1292,7 @@ c     1->coil, 2->helix, 3->turn, 4->strand
             endif
          enddo
       enddo
-
+      
 ********** find initial alignment: invmap(j) ************
       gap_open=-1.0             !should be -1
       call DP(NSEQ1,NSEQ2)      !produce alignment invmap(j)
@@ -975,7 +1366,7 @@ c     1->coil, 2->helix, 3->turn, 4->strand
       
       fra_min=4                 !>=4,minimum fragment for search
       fra_min1=fra_min-1        !cutoff for shift, save time
-      dcu0=3.85
+      dcu0=4.25
       
 ccc   Find the smallest continuous fragments -------->
       do i=1,nseq1
@@ -1030,7 +1421,7 @@ ccc   Find the smallest continuous fragments -------->
             endif
          enddo
          if(Lfr_max.lt.r_min)then
-            dcu=1.1*dcu
+            dcu=dcu+0.01
             goto 20
          endif
       enddo
@@ -1160,217 +1551,95 @@ ccc   get initial ------------->
       data w /nmax*1.0/
       common/inv/invmap_a(nmax)
       integer aL,m1,m2,n_frag
+      dimension n_frag(10)
       
 ***** setting parameters ************************************
       d01=d0+1.5
       if(d01.lt.d0_min)d01=d0_min
       d02=d01*d01
       GLmaxA=0
-      
       aL=min(nseq1,nseq2)
-      if(aL.gt.250)then
-         n_frag=50
-      elseif(aL.gt.200)then
-         n_frag=40
-      elseif(aL.gt.150)then
-         n_frag=30
+      
+c     jump on sequence1 -------------->
+      if(nseq1.gt.250)then
+         n_jump1=45
+      elseif(nseq1.gt.200)then
+         n_jump1=35
+      elseif(nseq1.gt.150)then
+         n_jump1=25
       else
-         n_frag=20              !length of fragment for superposition
+         n_jump1=15
       endif
-      if(n_frag.gt.aL/2)n_frag=aL/2
-      ns=20                     !tail length to discard
-      if(ns.gt.aL/2)ns=aL/2
-      
-      m1=nseq1-n_frag-ns
-      m2=nseq2-n_frag-ns
-      do ii=ns,m1,n_frag
-         do jj=ns,m2,n_frag
-            do k=1,n_frag
-               iii=ii+k-1
-               jjj=jj+k-1
-               r_1(1,k)=xa(1,iii,0)
-               r_1(2,k)=xa(2,iii,0)
-               r_1(3,k)=xa(3,iii,0)
-               r_2(1,k)=xa(1,jjj,1)
-               r_2(2,k)=xa(2,jjj,1)
-               r_2(3,k)=xa(3,jjj,1)
-            enddo
-            
+      if(n_jump1.gt.nseq1/3)n_jump1=nseq1/3
+      
+c     jump on sequence2 -------------->
+      if(nseq2.gt.250)then
+         n_jump2=45
+      elseif(nseq2.gt.200)then
+         n_jump2=35
+      elseif(nseq2.gt.150)then
+         n_jump2=25
+      else
+         n_jump2=15
+      endif
+      if(n_jump2.gt.nseq2/3)n_jump2=nseq2/3
+      
+c     fragment to superimpose -------------->
+      n_frag(1)=20
+      n_frag(2)=100
+      if(n_frag(1).gt.aL/3)n_frag(1)=aL/3
+      if(n_frag(2).gt.aL/2)n_frag(2)=aL/2
+
+c     start superimpose search -------------->
+      do i_frag=1,2
+         m1=nseq1-n_frag(i_frag)+1
+         m2=nseq2-n_frag(i_frag)+1
+         do ii=1,m1,n_jump1
+            do jj=1,m2,n_jump2
+               do k=1,n_frag(i_frag)
+                  iii=ii+k-1
+                  jjj=jj+k-1
+                  r_1(1,k)=xa(1,iii,0)
+                  r_1(2,k)=xa(2,iii,0)
+                  r_1(3,k)=xa(3,iii,0)
+                  r_2(1,k)=xa(1,jjj,1)
+                  r_2(2,k)=xa(2,jjj,1)
+                  r_2(3,k)=xa(3,jjj,1)
+               enddo
+               
 *********superpose the two structures and rotate it *****************
-            call u3b(w,r_1,r_2,n_frag,1,rms,u,t,ier) !u rotate r_1 to r_2
-            do i1=1,nseq1
-               xx=t(1)+u(1,1)*xa(1,i1,0)+u(1,2)*xa(2,i1,0)+u(1,3)
-     &              *xa(3,i1,0)  
-               yy=t(2)+u(2,1)*xa(1,i1,0)+u(2,2)*xa(2,i1,0)+u(2,3)
-     &              *xa(3,i1,0)
-               zz=t(3)+u(3,1)*xa(1,i1,0)+u(3,2)*xa(2,i1,0)+u(3,3)
-     &              *xa(3,i1,0)
-               do j1=1,nseq2
-                  dd=(xx-xa(1,j1,1))**2+(yy-xa(2,j1,1))**2+
-     &                 (zz-xa(3,j1,1))**2
-                  score(i1,j1)=1/(1+dd/d02) ! changing
+               call u3b(w,r_1,r_2,n_frag(i_frag),1,rms,u,t,ier) !u rotate r_1 to r_2
+               do i1=1,nseq1
+                  xx=t(1)+u(1,1)*xa(1,i1,0)+u(1,2)*xa(2,i1,0)+u(1,3)
+     &                 *xa(3,i1,0)  
+                  yy=t(2)+u(2,1)*xa(1,i1,0)+u(2,2)*xa(2,i1,0)+u(2,3)
+     &                 *xa(3,i1,0)
+                  zz=t(3)+u(3,1)*xa(1,i1,0)+u(3,2)*xa(2,i1,0)+u(3,3)
+     &                 *xa(3,i1,0)
+                  do j1=1,nseq2
+                     dd=(xx-xa(1,j1,1))**2+(yy-xa(2,j1,1))**2+
+     &                    (zz-xa(3,j1,1))**2
+                     score(i1,j1)=1/(1+dd/d02) ! changing
+                  enddo
                enddo
-            enddo
-            
+               
 *********extract alignement with score(i,j) *****************
-            call DP(NSEQ1,NSEQ2)
-            call get_GL(GL)
-            if(GL.gt.GLmaxA)then
-               GLmaxA=GL
-               do j1=1,nseq2
-                  invmap_i(j1)=invmap(j1)
-               enddo
-            endif
-         enddo
-      enddo
-      
-      return
-      end
-
-**************************************************************
-*     smooth the secondary structure assignment
-**************************************************************
-      subroutine smooth
-      PARAMETER(nmax=5000)
-      common/sec/isec(nmax),jsec(nmax)
-      common/length/nseq1,nseq2
-
-***   smooth single -------------->
-***   --x-- => -----
-      do i=1,nseq1
-         if(isec(i).eq.2.or.isec(i).eq.4)then
-            j=isec(i)
-            if(isec(i-2).ne.j)then
-               if(isec(i-1).ne.j)then
-                  if(isec(i+1).ne.j)then
-                     if(isec(i+1).ne.j)then
-                        isec(i)=1
-                     endif
-                  endif
-               endif
-            endif
-         endif
-      enddo
-      do i=1,nseq2
-         if(jsec(i).eq.2.or.jsec(i).eq.4)then
-            j=jsec(i)
-            if(jsec(i-2).ne.j)then
-               if(jsec(i-1).ne.j)then
-                  if(jsec(i+1).ne.j)then
-                     if(jsec(i+1).ne.j)then
-                        jsec(i)=1
-                     endif
-                  endif
+               call DP(NSEQ1,NSEQ2)
+               call get_GL(GL)
+               if(GL.gt.GLmaxA)then
+                  GLmaxA=GL
+                  do j1=1,nseq2
+                     invmap_i(j1)=invmap(j1)
+                  enddo
                endif
-            endif
-         endif
-      enddo
-
-***   smooth double -------------->
-***   --xx-- => ------
-      do i=1,nseq1
-         if(isec(i).ne.2)then
-         if(isec(i+1).ne.2)then
-         if(isec(i+2).eq.2)then
-         if(isec(i+3).eq.2)then
-         if(isec(i+4).ne.2)then
-         if(isec(i+5).ne.2)then
-            isec(i+2)=1
-            isec(i+3)=1
-         endif
-         endif
-         endif
-         endif
-         endif
-         endif
-
-         if(isec(i).ne.4)then
-         if(isec(i+1).ne.4)then
-         if(isec(i+2).eq.4)then
-         if(isec(i+3).eq.4)then
-         if(isec(i+4).ne.4)then
-         if(isec(i+5).ne.4)then
-            isec(i+2)=1
-            isec(i+3)=1
-         endif
-         endif
-         endif
-         endif
-         endif
-         endif
-      enddo
-      do i=1,nseq2
-         if(jsec(i).ne.2)then
-         if(jsec(i+1).ne.2)then
-         if(jsec(i+2).eq.2)then
-         if(jsec(i+3).eq.2)then
-         if(jsec(i+4).ne.2)then
-         if(jsec(i+5).ne.2)then
-            jsec(i+2)=1
-            jsec(i+3)=1
-         endif
-         endif
-         endif
-         endif
-         endif
-         endif
 
-         if(jsec(i).ne.4)then
-         if(jsec(i+1).ne.4)then
-         if(jsec(i+2).eq.4)then
-         if(jsec(i+3).eq.4)then
-         if(jsec(i+4).ne.4)then
-         if(jsec(i+5).ne.4)then
-            jsec(i+2)=1
-            jsec(i+3)=1
-         endif
-         endif
-         endif
-         endif
-         endif
-         endif
-      enddo
-
-***   connect -------------->
-***   x-x => xxx
-      do i=1,nseq1
-         if(isec(i).eq.2)then
-         if(isec(i+1).ne.2)then
-         if(isec(i+2).eq.2)then
-            isec(i+1)=2
-         endif
-         endif
-         endif
-
-         if(isec(i).eq.4)then
-         if(isec(i+1).ne.4)then
-         if(isec(i+2).eq.4)then
-            isec(i+1)=4
-         endif
-         endif
-         endif
-      enddo
-      do i=1,nseq2
-         if(jsec(i).eq.2)then
-         if(jsec(i+1).ne.2)then
-         if(jsec(i+2).eq.2)then
-            jsec(i+1)=2
-         endif
-         endif
-         endif
-
-         if(jsec(i).eq.4)then
-         if(jsec(i+1).ne.4)then
-         if(jsec(i+2).eq.4)then
-            jsec(i+1)=4
-         endif
-         endif
-         endif
+            enddo
+         enddo
       enddo
-
+      
       return
       end
-
+      
 *************************************************************
 *     assign secondary structure:
 *************************************************************
@@ -1553,7 +1822,8 @@ c^^^^^^^^^^^^^^^^ GL done ^^^^^^^^^^^^^^^^^^^^^^^^^^^
       dimension xtm1(nmax),ytm1(nmax),ztm1(nmax)
       dimension xtm2(nmax),ytm2(nmax),ztm2(nmax)
       common/TM/TM,TMmax
-      
+      common/ut/u,t
+
 ccc   RMSD:
       double precision r_1(3,nmax),r_2(3,nmax),w(nmax)
       double precision u(3,3),t(3),rms !armsd is real
@@ -1585,12 +1855,6 @@ ccc   for rotation matrix:
      &     n_al,xtm2,ytm2,ztm2,TM,Rcomm,Lcomm) !simplified search engine
       TM=TM*n_al/anseq          !TM-score
 ***   calculate score matrix score(i,j)------------------>
-      do i=1,n_al
-         r_2(1,i)=xtm1(i)
-         r_2(2,i)=ytm1(i)
-         r_2(3,i)=ztm1(i)
-      enddo
-      call u3b(w,r_1,r_2,n_al,1,rms,u,t,ier) !u rotate r_1 to r_2
       do i=1,nseq1
          xx=t(1)+u(1,1)*xa(1,i,0)+u(1,2)*xa(2,i,0)+u(1,3)*xa(3,i,0)
          yy=t(2)+u(2,1)*xa(1,i,0)+u(2,2)*xa(2,i,0)+u(2,3)*xa(3,i,0)
@@ -1657,8 +1921,69 @@ ccc   for rotation matrix:
 c^^^^^^^^^^^^^^^^ score(i,j) done ^^^^^^^^^^^^^^^^^^^^^^^^^^^
       return
       end
+      
+ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
+c     calculate TM-score for a given alignment specified by invmap (Based on Chain_2)
+ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
+      subroutine standard_TMscore(TM2,L_ali,RMSD)
+      PARAMETER(nmax=5000)      !maximum length of the sequence
+      common/length/nseq1,nseq2
+      common/dpc/score(nmax,nmax),gap_open,invmap(nmax)
+      COMMON/BACKBONE/XA(3,nmax,0:1)
+      dimension xtm1(nmax),ytm1(nmax),ztm1(nmax)
+      dimension xtm2(nmax),ytm2(nmax),ztm2(nmax)
+      common/d0min/d0_min
+      
+ccc   RMSD:
+      double precision r_1(3,nmax),r_2(3,nmax),w(nmax)
+      double precision u(3,3),t(3),rms !armsd is real
+      data w /nmax*1.0/
+ccc   
 
+      d0_min=0.5                !for TM-score output, consistent stdrd TM-score
+      anseq=nseq2
+      if(anseq.gt.21)then
+         d0=1.24*(anseq-15)**(1.0/3.0)-1.8 !scale for defining TM-score
+      else
+         d0=d0_min
+      endif
+      if(d0.lt.d0_min)d0=d0_min
+      d0_input=d0               !scaled by seq_min
+      
+cccc  collect aligned residues from invmap ------->
+      n_al=0
+      do j=1,nseq2
+         if(invmap(j).gt.0)then
+            i=invmap(j)
+            n_al=n_al+1
+            xtm1(n_al)=xa(1,i,0)
+            ytm1(n_al)=xa(2,i,0)
+            ztm1(n_al)=xa(3,i,0)
+            xtm2(n_al)=xa(1,j,1)
+            ytm2(n_al)=xa(2,j,1)
+            ztm2(n_al)=xa(3,j,1)
 
+            r_1(1,n_al)=xa(1,i,0)
+            r_1(2,n_al)=xa(2,i,0)
+            r_1(3,n_al)=xa(3,i,0)
+            r_2(1,n_al)=xa(1,j,1)
+            r_2(2,n_al)=xa(2,j,1)
+            r_2(3,n_al)=xa(3,j,1)
+         endif
+      enddo
+      call u3b(w,r_1,r_2,n_al,0,rms,u,t,ier)
+      L_ali=n_al
+      RMSD=dsqrt(rms/n_al)
+c      write(*,*)'---------',rms,n_al,RMSD,u(1,1),t(1)
+      
+      call TMscore(d0_input,n_al,xtm1,ytm1,ztm1,n_al,
+     &     xtm2,ytm2,ztm2,TM8,Rcomm,Lcomm) !normal TMscore
+      TM2=TM8*n_al/anseq
+      
+c^^^^^^^^^^ TM-score calculation is done ^^^^^^^^^^^^^^^^^^^^^^^^
+      return
+      end
+      
 *************************************************************************
 *************************************************************************
 *     This is a subroutine to compare two structures and find the 
@@ -1695,6 +2020,7 @@ c^^^^^^^^^^^^^^^^ score(i,j) done ^^^^^^^^^^^^^^^^^^^^^^^^^^^
       double precision score,score_max
       dimension xa(nmax),ya(nmax),za(nmax)
       dimension iL0(nmax)
+      common/ut/u,t
 
       dimension x1(nmax),y1(nmax),z1(nmax)
       dimension x2(nmax),y2(nmax),z2(nmax)
@@ -1786,10 +2112,7 @@ ccc
               k_ali(ka)=k
            enddo
            call u3b(w,r_1,r_2,LL,1,rms,u,t,ier) !u rotate r_1 to r_2
-           if(i_init.eq.1)then  !global superposition
-              armsd=dsqrt(rms/LL)
-              Rcomm=armsd
-           endif
+           Rcomm=0              !not used
            do j=1,nseqA
               xt(j)=t(1)+u(1,1)*xa(j)+u(1,2)*ya(j)+u(1,3)*za(j)
               yt(j)=t(2)+u(2,1)*xa(j)+u(2,2)*ya(j)+u(2,3)*za(j)
@@ -1847,7 +2170,7 @@ ccc
  302       continue
  300    continue                !for shift
  333  continue                  !for initial length, L_ali/M
-
+      
 ******** return the final rotation ****************
       LL=0
       do i=1,ka0
@@ -1867,7 +2190,7 @@ ccc
          z1(j)=t(3)+u(3,1)*xa(j)+u(3,2)*ya(j)+u(3,3)*za(j)
       enddo
       TM=score_max
-
+      
 c^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       return
       END
@@ -1985,10 +2308,6 @@ ccc
               k_ali(ka)=k
            enddo
            call u3b(w,r_1,r_2,LL,1,rms,u,t,ier) !u rotate r_1 to r_2
-           if(i_init.eq.1)then  !global superposition
-              armsd=dsqrt(rms/LL)
-              Rcomm=armsd
-           endif
            do j=1,nseqA
               xt(j)=t(1)+u(1,1)*xa(j)+u(1,2)*ya(j)+u(1,3)*za(j)
               yt(j)=t(2)+u(2,1)*xa(j)+u(2,2)*ya(j)+u(2,3)*za(j)
@@ -2225,10 +2544,6 @@ c      d0=1.24*(nseqB-15)**(1.0/3.0)-1.8
               k_ali(ka)=k
            enddo
            call u3b(w,r_1,r_2,LL,1,rms,u,t,ier) !u rotate r_1 to r_2
-           if(i_init.eq.1)then  !global superposition
-              armsd=dsqrt(rms/LL)
-              Rcomm=armsd
-           endif
            do j=1,nseqA
               xt(j)=t(1)+u(1,1)*xa(j)+u(1,2)*ya(j)+u(1,3)*za(j)
               yt(j)=t(2)+u(2,1)*xa(j)+u(2,2)*ya(j)+u(2,3)*za(j)
@@ -2286,25 +2601,7 @@ c      d0=1.24*(nseqB-15)**(1.0/3.0)-1.8
  302       continue
  300    continue                !for shift
  333  continue                  !for initial length, L_ali/M
-
-******** return the final rotation ****************
-      LL=0
-      do i=1,ka0
-         m=k_ali0(i)            !record of the best alignment
-         r_1(1,i)=xa(iA(m))
-         r_1(2,i)=ya(iA(m))
-         r_1(3,i)=za(iA(m))
-         r_2(1,i)=xb(iB(m))
-         r_2(2,i)=yb(iB(m))
-         r_2(3,i)=zb(iB(m))
-         LL=LL+1
-      enddo
-      call u3b(w,r_1,r_2,LL,1,rms,u,t,ier) !u rotate r_1 to r_2
-      do j=1,nseqA
-         x1(j)=t(1)+u(1,1)*xa(j)+u(1,2)*ya(j)+u(1,3)*za(j)
-         y1(j)=t(2)+u(2,1)*xa(j)+u(2,2)*ya(j)+u(2,3)*za(j)
-         z1(j)=t(3)+u(3,1)*xa(j)+u(3,2)*ya(j)+u(3,3)*za(j)
-      enddo
+      
       TM=score_max
 
 c^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -2325,7 +2622,7 @@ ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
       common/nscore/i_ali(nmax),n_cut ![1,n_ali],align residues for the score
       common/scores/score
       double precision score
-
+      
       d_tmp=d
  21   n_cut=0                   !number of residue-pairs dis<d, for iteration
       score_sum=0               !TMscore
@@ -2424,15 +2721,16 @@ ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
 c^^^^^^^^^^^^^^^Dynamical programming done ^^^^^^^^^^^^^^^^^^^
       return
       END
-
+      
 cccccccccccccccc Calculate sum of (r_d-r_m)^2 cccccccccccccccccccccccccc
-c  w    - w(m) is weight for atom pair  c m                 (given)
-c  x    - x(i,m) are coordinates of atom c m in set x       (given)
-c  y    - y(i,m) are coordinates of atom c m in set y       (given)
-c  n    - n is number of atom pairs                         (given)
-c  mode  - 0:calculate rms only                             (given)
-c          1:calculate rms,u,t                              (takes longer)
-c  rms   - sum of w*(ux+t-y)**2 over all atom pairs         (result)
+c  w    - w(m) is weight for atom pair  c m                    (given)
+c  x    - x(i,m) are coordinates of atom c m in set x          (given)
+c  y    - y(i,m) are coordinates of atom c m in set y          (given)
+c  n    - n is number of atom pairs                            (given)
+c  mode  - 0:calculate rms     only                            (given,short)
+c          1:calculate     u,t only                            (given,medium)
+c          2:calculate rms,u,t                                 (given,longer)
+c  rms   - sum of w*(ux+t-y)**2 over all atom pairs            (result)
 c  u    - u(i,j) is   rotation  matrix for best superposition  (result)
 c  t    - t(i)   is translation vector for best superposition  (result)
 c  ier  - 0: a unique optimal superposition has been determined(result)
@@ -2453,6 +2751,9 @@ cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
       double precision a(3,3), b(3,3), e(3), rr(6), ss(6)
       double precision e0, d, spur, det, cof, h, g
       double precision cth, sth, sqrth, p, sigma
+      double precision c1x, c1y, c1z, c2x, c2y, c2z
+      double precision s1x, s1y, s1z, s2x, s2y, s2z
+      double precision sxx, sxy, sxz, syx, syy, syz, szx, szy, szz
       
       double precision sqrt3, tol, zero
       
@@ -2462,9 +2763,24 @@ cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
       data ip / 1, 2, 4, 2, 3, 5, 4, 5, 6 /
       data ip2312 / 2, 3, 1, 2 /
       
-      wc = zero
+      wc  = zero
       rms = zero
-      e0 = zero
+      e0  = zero
+      s1x = zero
+      s1y = zero
+      s1z = zero
+      s2x = zero
+      s2y = zero
+      s2z = zero
+      sxx = zero
+      sxy = zero
+      sxz = zero
+      syx = zero
+      syy = zero
+      syz = zero
+      szx = zero 
+      szy = zero
+      szz = zero
       
       do i=1, 3
          xc(i) = zero
@@ -2484,29 +2800,61 @@ cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
       ier = -1
       if( n .lt. 1 ) return
       ier = -2
+      
       do m=1, n
-         if( w(m) .lt. 0.0 ) return
-         wc = wc + w(m)
-         do i=1, 3
-            xc(i) = xc(i) + w(m)*x(i,m)
-            yc(i) = yc(i) + w(m)*y(i,m)
-         end do
-      end do
-      if( wc .le. zero ) return
-      do i=1, 3
-         xc(i) = xc(i) / wc
-         yc(i) = yc(i) / wc
+         c1x=x(1, m)
+         c1y=x(2, m)
+         c1z=x(3, m)
+         
+         c2x=y(1, m)
+         c2y=y(2, m)
+         c2z=y(3, m)
+         
+         s1x = s1x + c1x
+         s1y = s1y + c1y;
+         s1z = s1z + c1z;
+         
+         s2x = s2x + c2x;
+         s2y = s2y + c2y;
+         s2z = s2z + c2z;
+         
+         sxx = sxx + c1x*c2x; 
+         sxy = sxy + c1x*c2y; 
+         sxz = sxz + c1x*c2z; 
+         
+         syx = syx + c1y*c2x; 
+         syy = syy + c1y*c2y; 
+         syz = syz + c1y*c2z;
+         
+         szx = szx + c1z*c2x; 
+         szy = szy + c1z*c2y; 
+         szz = szz + c1z*c2z;
       end do
       
-      do m=1, n
-         do i=1, 3
-            e0=e0+w(m)*((x(i,m)-xc(i))**2+(y(i,m)-yc(i))**2)
-            d = w(m) * ( y(i,m) - yc(i) )
-            do j=1, 3
-               r(i,j) = r(i,j) + d*( x(j,m) - xc(j) )
-            end do
+      xc(1) = s1x/n;
+      xc(2) = s1y/n; 	
+      xc(3) = s1z/n;
+      
+      yc(1) = s2x/n;
+      yc(2) = s2y/n; 	
+      yc(3) = s2z/n;
+      if(mode.eq.2.or.mode.eq.0) then ! need rmsd                     		
+         do m=1, n		
+            do i=1, 3
+               e0 = e0+ (x(i, m)-xc(i))**2 + (y(i, m)-yc(i))**2			
+            end do				
          end do
-      end do
+      endif
+      
+      r(1, 1) = sxx-s1x*s2x/n;
+      r(2, 1) = sxy-s1x*s2y/n;
+      r(3, 1) = sxz-s1x*s2z/n;
+      r(1, 2) = syx-s1y*s2x/n;
+      r(2, 2) = syy-s1y*s2y/n;
+      r(3, 2) = syz-s1y*s2z/n;
+      r(1, 3) = szx-s1z*s2x/n;
+      r(2, 3) = szy-s1z*s2y/n;
+      r(3, 3) = szz-s1z*s2z/n;
       
       det = r(1,1) * ( (r(2,2)*r(3,3)) - (r(2,3)*r(3,2)) )
      &     - r(1,2) * ( (r(2,1)*r(3,3)) - (r(2,3)*r(3,1)) )
@@ -2550,7 +2898,7 @@ cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
       e(1) = (spur + cth) + cth
       e(2) = (spur - cth) + sth
       e(3) = (spur - cth) - sth
-	
+      
       if( mode .eq. 0 ) then
          goto 50
       end if
@@ -2693,8 +3041,11 @@ cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
       end if
       d = (d + e(2)) + e(1)
       
-      rms = (e0 - d) - d
-      if( rms .lt. 0.0 ) rms = 0.0
+      if(mode .eq. 2.or.mode.eq.0) then ! need rmsd                     		
+         rms = (e0 - d) - d
+         if( rms .lt. 0.0 ) rms = 0.0
+      endif
       
       return
       end
+      
diff --git a/modules/bindings/src/tmscore.f b/modules/bindings/src/tmscore.f
index 86340daf7416f0f4bf14449a267767694ead8f55..6a4c57484b292f113170be446107ad7a284b536a 100644
--- a/modules/bindings/src/tmscore.f
+++ b/modules/bindings/src/tmscore.f
@@ -25,10 +25,14 @@
 *     2010/08/02: A new RMSD matrix was used and obsolete statement removed.
 *     2011/01/03: The length of pdb file names were extended to 500.
 *     2011/01/30: An open source license is attached to the program.
+*     2012/05/07: Improved RMSD calculation subroutine which speeds up 
+*                 TM-score program by 30%.
+*     2012/06/05: Added option '-l L' which calculates TM-score (and maxsub
+*                 and GDT scores) normalized by a specific length 'L'.
 *************************************************************************
       
       program TMscore
-      PARAMETER(nmax=3000)
+      PARAMETER(nmax=5000)
       
       common/stru/xt(nmax),yt(nmax),zt(nmax),xb(nmax),yb(nmax),zb(nmax)
       common/nres/nresA(nmax),nresB(nmax),nseqA,nseqB
@@ -76,15 +80,19 @@ ccc
          write(*,*)'(For detail: Zhang & Skolnick,  Proteins, 2004',
      &        ' 57:702-10)'
          write(*,*)
-         write(*,*)'1. Run TM-score to compare ''model'' and ''native',
-     &        ':'
+         write(*,*)'1. Run TM-score to compare ''model'' and ',
+     &        '''native'':'
          write(*,*)'   >TMscore model native'
          write(*,*)
-         write(*,*)'2. Run TM-score with an assigned d0, e.g. 5',
-     &        ' Angstroms:'
+         write(*,*)'2. TM-score normalized with an assigned scale d0',
+     &        ' e.g. 5 A:'
          write(*,*)'   >TMscore model native -d 5'
          write(*,*)
-         write(*,*)'3. Run TM-score with superposition output, e.g. ',
+         write(*,*)'3. TM-score normalized by a specific length, ',
+     &        'e.g. 120 AA:'
+         write(*,*)'   >TMscore model native -l 120'
+         write(*,*)
+         write(*,*)'4. TM-score with superposition output, e.g. ',
      &        '''TM.sup'':'
          write(*,*)'   >TMscore model native -o TM.sup'
          write(*,*)'   To view the superimposed structures by rasmol:'
@@ -96,6 +104,7 @@ ccc
 ******* options ----------->
       m_out=-1
       m_fix=-1
+      m_len=-1
       narg=iargc()
       i=0
       j=0
@@ -111,6 +120,11 @@ ccc
          i=i+1
          call getarg(i,fnam)
          read(fnam,*)d0_fix
+      elseif(fnam.eq.'-l')then
+         m_len=1
+         i=i+1
+         call getarg(i,fnam)
+         read(fnam,*)l0_fix
       else
          j=j+1
          pdb(j)=fnam
@@ -207,6 +221,9 @@ c^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       else
          d0=0.5
       endif
+      if(m_len.eq.1)then
+         d0=1.24*(l0_fix-15)**(1.0/3.0)-1.8
+      endif
       if(d0.lt.0.5)d0=0.5
       if(m_fix.eq.1)d0=d0_fix
 ***   d0_search ----->
@@ -262,10 +279,12 @@ c^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
               k_ali(ka)=k
               LL=LL+1
            enddo
-           call u3b(w,r_1,r_2,LL,1,rms,u,t,ier) !u rotate r_1 to r_2
            if(i_init.eq.1)then  !global superposition
+              call u3b(w,r_1,r_2,LL,2,rms,u,t,ier) !0:rmsd; 1:u,t; 2:rmsd,u,t
               armsd=dsqrt(rms/LL)
               rmsd_ali=armsd
+           else
+              call u3b(w,r_1,r_2,LL,1,rms,u,t,ier) !u rotate r_1 to r_2
            endif
            do j=1,nseqA
               xt(j)=t(1)+u(1,1)*xa(j)+u(1,2)*ya(j)+u(1,3)*za(j)
@@ -340,7 +359,12 @@ c^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  302       continue
  300    continue                !for shift
  333  continue                  !for initial length, L_ali/M
-
+      
+      ratio=1
+      if(m_len.gt.0)then
+         ratio=float(nseqB)/float(l0_fix)
+      endif
+      
 ******************************************************************
 *     Output
 ******************************************************************
@@ -367,7 +391,14 @@ c^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       write(*,*)
       write(*,501)pdb(1),nseqA
  501  format('Structure1: ',A10,'  Length= ',I4)
-      write(*,502)pdb(2),nseqB
+      if(m_len.eq.1)then
+         write(*,411)pdb(2),nseqB
+         write(*,412)l0_fix
+      else
+         write(*,502)pdb(2),nseqB
+      endif
+ 411  format('Structure2: ',A10,'  Length= ',I4)
+ 412  format('TM-score is notmalized by ',I4)
  502  format('Structure2: ',A10,'  Length= ',I4,
      &     ' (by which all scores are normalized)')
       write(*,503)n_ali
@@ -375,20 +406,25 @@ c^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       write(*,513)rmsd_ali
  513  format('RMSD of  the common residues= ',F8.3)
       write(*,*)
-      write(*,504)score_max,d0,score10_max
- 504  format('TM-score    = ',f6.4,'  (d0=',f5.2,',',' TM10= ',f6.4,')')
-      write(*,505)score_maxsub_max
+      if(m_len.eq.1)then
+         score_max=score_max*float(nseqB)/float(l0_fix)
+      endif
+      write(*,504)score_max,d0
+ 504  format('TM-score    = ',f6.4,'  (d0=',f5.2,')')
+      write(*,505)score_maxsub_max*ratio
  505  format('MaxSub-score= ',f6.4,'  (d0= 3.50)')
       score_GDT=(n_GDT1_max+n_GDT2_max+n_GDT4_max+n_GDT8_max)
      &     /float(4*nseqB)
-      write(*,506)score_GDT,n_GDT1_max/float(nseqB),n_GDT2_max
-     &     /float(nseqB),n_GDT4_max/float(nseqB),n_GDT8_max/float(nseqB)
+      write(*,506)score_GDT*ratio,n_GDT1_max/float(nseqB)*ratio,
+     &     n_GDT2_max/float(nseqB)*ratio,n_GDT4_max/float(nseqB)*ratio,
+     &     n_GDT8_max/float(nseqB)*ratio
  506  format('GDT-TS-score= ',f6.4,' %(d<1)=',f6.4,' %(d<2)=',f6.4,
      $     ' %(d<4)=',f6.4,' %(d<8)=',f6.4)
       score_GDT_HA=(n_GDT05_max+n_GDT1_max+n_GDT2_max+n_GDT4_max)
      &     /float(4*nseqB)
-      write(*,507)score_GDT_HA,n_GDT05_max/float(nseqB),n_GDT1_max
-     &     /float(nseqB),n_GDT2_max/float(nseqB),n_GDT4_max/float(nseqB)
+      write(*,507)score_GDT_HA*ratio,n_GDT05_max/float(nseqB)*ratio,
+     &     n_GDT1_max/float(nseqB)*ratio,n_GDT2_max/float(nseqB)*ratio,
+     &     n_GDT4_max/float(nseqB)*ratio
  507  format('GDT-HA-score= ',f6.4,' %(d<0.5)=',f6.4,' %(d<1)=',f6.4,
      $     ' %(d<2)=',f6.4,' %(d<4)=',f6.4)
       write(*,*)
@@ -576,7 +612,7 @@ c     1, collect those residues with dis<d;
 c     2, calculate score_GDT, score_maxsub, score_TM
 ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
       subroutine score_fun
-      PARAMETER(nmax=3000)
+      PARAMETER(nmax=5000)
 
       common/stru/xt(nmax),yt(nmax),zt(nmax),xb(nmax),yb(nmax),zb(nmax)
       common/nres/nresA(nmax),nresB(nmax),nseqA,nseqB
@@ -646,13 +682,14 @@ ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
       end
 
 cccccccccccccccc Calculate sum of (r_d-r_m)^2 cccccccccccccccccccccccccc
-c  w    - w(m) is weight for atom pair  c m           (given)
-c  x    - x(i,m) are coordinates of atom c m in set x       (given)
-c  y    - y(i,m) are coordinates of atom c m in set y       (given)
-c  n    - n is number of atom pairs                         (given)
-c  mode  - 0:calculate rms only                             (given)
-c          1:calculate rms,u,t                              (takes longer)
-c  rms   - sum of w*(ux+t-y)**2 over all atom pairs         (result)
+c  w    - w(m) is weight for atom pair  c m                    (given)
+c  x    - x(i,m) are coordinates of atom c m in set x          (given)
+c  y    - y(i,m) are coordinates of atom c m in set y          (given)
+c  n    - n is number of atom pairs                            (given)
+c  mode  - 0:calculate rms     only                            (given,short)
+c          1:calculate     u,t only                            (given,medium)
+c          2:calculate rms,u,t                                 (given,longer)
+c  rms   - sum of w*(ux+t-y)**2 over all atom pairs            (result)
 c  u    - u(i,j) is   rotation  matrix for best superposition  (result)
 c  t    - t(i)   is translation vector for best superposition  (result)
 c  ier  - 0: a unique optimal superposition has been determined(result)
@@ -673,6 +710,9 @@ cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
       double precision a(3,3), b(3,3), e(3), rr(6), ss(6)
       double precision e0, d, spur, det, cof, h, g
       double precision cth, sth, sqrth, p, sigma
+      double precision c1x, c1y, c1z, c2x, c2y, c2z
+      double precision s1x, s1y, s1z, s2x, s2y, s2z
+      double precision sxx, sxy, sxz, syx, syy, syz, szx, szy, szz
       
       double precision sqrt3, tol, zero
       
@@ -682,9 +722,24 @@ cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
       data ip / 1, 2, 4, 2, 3, 5, 4, 5, 6 /
       data ip2312 / 2, 3, 1, 2 /
       
-      wc = zero
+      wc  = zero
       rms = zero
-      e0 = zero
+      e0  = zero
+      s1x = zero
+      s1y = zero
+      s1z = zero
+      s2x = zero
+      s2y = zero
+      s2z = zero
+      sxx = zero
+      sxy = zero
+      sxz = zero
+      syx = zero
+      syy = zero
+      syz = zero
+      szx = zero 
+      szy = zero
+      szz = zero
       
       do i=1, 3
          xc(i) = zero
@@ -704,29 +759,61 @@ cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
       ier = -1
       if( n .lt. 1 ) return
       ier = -2
+      
       do m=1, n
-         if( w(m) .lt. 0.0 ) return
-         wc = wc + w(m)
-         do i=1, 3
-            xc(i) = xc(i) + w(m)*x(i,m)
-            yc(i) = yc(i) + w(m)*y(i,m)
-         end do
-      end do
-      if( wc .le. zero ) return
-      do i=1, 3
-         xc(i) = xc(i) / wc
-         yc(i) = yc(i) / wc
+         c1x=x(1, m)
+         c1y=x(2, m)
+         c1z=x(3, m)
+         
+         c2x=y(1, m)
+         c2y=y(2, m)
+         c2z=y(3, m)
+         
+         s1x = s1x + c1x
+         s1y = s1y + c1y;
+         s1z = s1z + c1z;
+         
+         s2x = s2x + c2x;
+         s2y = s2y + c2y;
+         s2z = s2z + c2z;
+         
+         sxx = sxx + c1x*c2x; 
+         sxy = sxy + c1x*c2y; 
+         sxz = sxz + c1x*c2z; 
+         
+         syx = syx + c1y*c2x; 
+         syy = syy + c1y*c2y; 
+         syz = syz + c1y*c2z;
+         
+         szx = szx + c1z*c2x; 
+         szy = szy + c1z*c2y; 
+         szz = szz + c1z*c2z;
       end do
       
-      do m=1, n
-         do i=1, 3
-            e0=e0+w(m)*((x(i,m)-xc(i))**2+(y(i,m)-yc(i))**2)
-            d = w(m) * ( y(i,m) - yc(i) )
-            do j=1, 3
-               r(i,j) = r(i,j) + d*( x(j,m) - xc(j) )
-            end do
+      xc(1) = s1x/n;
+      xc(2) = s1y/n; 	
+      xc(3) = s1z/n;
+      
+      yc(1) = s2x/n;
+      yc(2) = s2y/n; 	
+      yc(3) = s2z/n;
+      if(mode.eq.2.or.mode.eq.0) then ! need rmsd                     		
+         do m=1, n		
+            do i=1, 3
+               e0 = e0+ (x(i, m)-xc(i))**2 + (y(i, m)-yc(i))**2			
+            end do				
          end do
-      end do
+      endif
+      
+      r(1, 1) = sxx-s1x*s2x/n;
+      r(2, 1) = sxy-s1x*s2y/n;
+      r(3, 1) = sxz-s1x*s2z/n;
+      r(1, 2) = syx-s1y*s2x/n;
+      r(2, 2) = syy-s1y*s2y/n;
+      r(3, 2) = syz-s1y*s2z/n;
+      r(1, 3) = szx-s1z*s2x/n;
+      r(2, 3) = szy-s1z*s2y/n;
+      r(3, 3) = szz-s1z*s2z/n;
       
       det = r(1,1) * ( (r(2,2)*r(3,3)) - (r(2,3)*r(3,2)) )
      &     - r(1,2) * ( (r(2,1)*r(3,3)) - (r(2,3)*r(3,1)) )
@@ -770,7 +857,7 @@ cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
       e(1) = (spur + cth) + cth
       e(2) = (spur - cth) + sth
       e(3) = (spur - cth) - sth
-	
+      
       if( mode .eq. 0 ) then
          goto 50
       end if
@@ -913,8 +1000,12 @@ cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
       end if
       d = (d + e(2)) + e(1)
       
-      rms = (e0 - d) - d
-      if( rms .lt. 0.0 ) rms = 0.0
+      if(mode .eq. 2.or.mode.eq.0) then ! need rmsd                     		
+         rms = (e0 - d) - d
+         if( rms .lt. 0.0 ) rms = 0.0
+      endif
       
       return
       end
+      
+
diff --git a/modules/bindings/tests/CMakeLists.txt b/modules/bindings/tests/CMakeLists.txt
index d1b344ff59ab2b6972b901c1c4f2387b4484dbe2..7b04104d9d230d61ab27b4c56dce4730bd42f49e 100644
--- a/modules/bindings/tests/CMakeLists.txt
+++ b/modules/bindings/tests/CMakeLists.txt
@@ -2,6 +2,7 @@ set(OST_BINDINGS_UNIT_TESTS
   test_msms.py
   test_clustalw.py
   test_blast.py
+  test_kclust.py
 )
 
 ost_unittest(MODULE bindings 
diff --git a/modules/bindings/tests/test_blast.py b/modules/bindings/tests/test_blast.py
index 707f5c93b3bc49a71d0059dbfc74252768626373..48cb560685d5dd46dfb6682c6bfe5271cc7ca9c0 100644
--- a/modules/bindings/tests/test_blast.py
+++ b/modules/bindings/tests/test_blast.py
@@ -1,7 +1,12 @@
+import sys
 import unittest
 from ost import *
 from ost import settings
 from ost.bindings import blast
+import re
+import tempfile
+import os
+import shutil
 
 class TestBlastBindings(unittest.TestCase):
   def setUp(self):
@@ -9,8 +14,6 @@ class TestBlastBindings(unittest.TestCase):
                                        'DFSLSVKFGNDVQHFKVLRDGAGKYFLWVVKFNSLNELV'+
                                        'DYHRSTSVSRNQQIFLRDIEQVP')
   def testAllowedMatricesAndPenalties(self):
-    self.assertRaises(blast.BlastError, blast.Blast, self.query, 
-                      'testfiles/seqdb', matrix='BLOSUM45')
     blast.Blast(self.query, 'testfiles/seqdb', matrix='BLOSUM45', 
                 gap_open=13, gap_ext=3)
     blast.Blast(self.query, 'testfiles/seqdb', matrix='BLOSUM80')
@@ -20,38 +23,83 @@ class TestBlastBindings(unittest.TestCase):
     blast.Blast(self.query, 'testfiles/seqdb', matrix='BLOSUM62')
     self.assertRaises(ValueError, blast.Blast, self.query, 'testfiles/seqdb', 
                       matrix='MUAHA')
+    self.assertRaises(RuntimeError, blast.Blast, self.query, 'testfiles/seqdb',
+                      blast_location='/I/do/not/exist')
+
   def testMissingDB(self):
     self.assertRaises(IOError, blast.Blast, self.query, 
                       'testfiles/nonexistentdb')
   
-  def testParseBlastOutput(self):
+  def testBlastExec(self):
+
     hits=blast.Blast(self.query, 'testfiles/seqdb')
-    blast_version=blast.BlastVersion()
-    if blast_version=='2.2.16':
-      expected_output=[{'evalue':4.808930E-59,'bitscore':210.305,'score':534}, 
-                       {'evalue':2.366130E-59,'bitscore':210.305,'score':534}, 
-                       {'evalue':5.361450E-58,'bitscore':206.068,'score':523}, 
-                       {'evalue':2.965230E+00,'bitscore':15.0086,'score':27}, 
-                       {'evalue':9.696520E+00,'bitscore':13.4678,'score':23}]
- 
-    else:
-      expected_output=[{'evalue':2.366130E-59,'bitscore':211.460,'score':537}, 
-                       {'evalue':4.808930E-59,'bitscore':210.305,'score':534}, 
-                       {'evalue':5.361450E-58,'bitscore':206.838,'score':525}, 
-                       {'evalue':3.277500E+00,'bitscore':15.0086,'score':27}, 
-                       {'evalue':9.696520E+00,'bitscore':13.4678,'score':23}]
+
+    expected_hits=['1griA','1fhsA','3n84E','1mw9X']
     self.assertEqual(len(hits), 4)
-    for expected, hit in zip(expected_output, hits):
-      patch=hit.aligned_patches[0]
-      self.assertAlmostEqual(patch.evalue, expected['evalue'])
-      self.assertAlmostEqual(patch.bit_score, expected['bitscore'])
-      self.assertAlmostEqual(patch.score, expected['score'])
+
+    found=0
+    hit_ids=[]
+
+    for h in hits:
+      hit_ids.append(h.identifier)
+
+    for identifier in expected_hits:
+      if identifier in hit_ids:
+        found+=1
+    self.assertEqual(found, 4)
+
+  def testBlastParseOutput(self):
+
+    raw_out=open('testfiles/raw_blastout.txt','r').read()
+
+    parsed_out=blast.ParseBlastOutput(raw_out)
+
+    expected_ids=['1griA','1fhsA','3n84E','1mw9X']
+    expected_evalues=[4.80893e-59,4.80893e-59,9.06925e-58,2.96523]
+    expected_scores=[534,534,523,27]
+    expected_bitscores=[210.305,210.305,206.068,15.0086]
+    expected_seqid=[1.0,1.0,1.0,0.30769]
+
+    for i in range(4):
+      patch=parsed_out[i].aligned_patches[0]
+      self.assertEqual(expected_ids[i],parsed_out[i].identifier)
+      self.assertAlmostEqual(patch.evalue,expected_evalues[i])
+      self.assertAlmostEqual(patch.score,expected_scores[i])
+      self.assertAlmostEqual(patch.bit_score,expected_bitscores[i])
+      self.assertAlmostEqual(patch.seqid,expected_seqid[i],places=5)
+
+  def testBlastVersion(self):
+
+    self.assertRaises(RuntimeError, blast.Blast, self.query, 'testfiles/seqdb',
+                      blast_location='/I/do/not/exist')
+    version=blast.BlastVersion()
+    self.assertTrue(isinstance(version,str))
+    re_v = re.compile('\d+\.\d+\.\d+')
+    match=False
+    if re_v.match(version):
+      match=True
+    self.assertEqual(match,True)
+
+  def testBuildDatabase(self):
+
+    tmp_dir_name=tempfile.mkdtemp()
+    db_name=os.path.join(tmp_dir_name,'testdb')
+    blast.CreateDB('testfiles/multiple.fasta',db_name)
+    self.assertRaises(IOError,blast.CreateDB, 'testfiles/multiple.fasta',db_name,
+                      mkdb_cmd='I/am/not/a/damn/executable')
+
+    test_seq=seq.CreateSequence('B','ALRLVKDGFAVAIADYNDATATAVAAEINQAGGRAVAIKVDV'+
+                                    'SRRDQVFAAVEQARKALGGFNVIVNNAGIAPSTPIESIT')
+    blastout=blast.Blast(test_seq,db_name)
+    self.assertTrue(len(blastout)>10)
+    shutil.rmtree(tmp_dir_name)
+
 if __name__ == "__main__":
   # test if blast package is available on system, otherwise ignore tests
   try:
-    blastpath=settings.Locate('blastall')
+    blastpath=settings.Locate(('blastp','blastall'))
   except(settings.FileNotFound):
-    print "Could not find blastall executable: ignoring unit tests"
+    print "Could not find blast executable: ignoring unit tests"
     sys.exit(0)
   from ost import testutils
   testutils.RunTests()
diff --git a/modules/bindings/tests/test_clustalw.py b/modules/bindings/tests/test_clustalw.py
index fa5a5e6b5eb44cbe11a0a11a68dc93d7d64cf123..9aaf210f8be644f2126b7a1bff6e859c43ce3fe0 100644
--- a/modules/bindings/tests/test_clustalw.py
+++ b/modules/bindings/tests/test_clustalw.py
@@ -1,3 +1,4 @@
+import sys
 import unittest
 from ost import *
 from ost import settings
diff --git a/modules/bindings/tests/test_kclust.py b/modules/bindings/tests/test_kclust.py
new file mode 100644
index 0000000000000000000000000000000000000000..fe7251613484b55ad248f21edb2df12f61c0ca3e
--- /dev/null
+++ b/modules/bindings/tests/test_kclust.py
@@ -0,0 +1,44 @@
+import sys
+import unittest
+from ost import *
+from ost import settings
+from ost.bindings import kclust
+
+class TestkClustBindings(unittest.TestCase):
+  
+  def testkClustExec(self):
+
+    seq_list=io.LoadSequenceList('testfiles/multiple.fasta')
+
+    clusters40=kclust.kClust(seq_list,clustering_thresh=40)
+    clusters90=kclust.kClust(seq_list,clustering_thresh=90)
+
+    self.assertEqual(len(clusters40),16)
+    self.assertEqual(len(clusters90),27)
+
+  def testkClustParseOutput(self):
+
+    representative_ids=['Q5KTS5.1','P46331.2','P66776.1','P42317.2','P50199.1',
+                        'Q59787.1','Q9WYG0.1','P50197.1','P50198.1','Q7Z4W1.2',
+                        'Q04520.1']
+
+    cluster_sizes=[3,3,4,1,7,3,2,1,1,3,1]
+
+    result=kclust._ParseOutput('testfiles')
+
+    self.assertEqual(len(result),11)
+
+    for c, r_id in zip(result, representative_ids):
+      self.assertEqual(c.representative_id, r_id)
+    for c, s in zip(result, cluster_sizes):
+      self.assertEqual(len(c.sequences),s)
+
+if __name__ == "__main__":
+  # test if kClust is available on system, otherwise ignore tests
+  try:
+    blastpath=settings.Locate(('kClust'))
+  except(settings.FileNotFound):
+    print "Could not find kClust executable: ignoring unit tests"
+    sys.exit(0)
+  from ost import testutils
+  testutils.RunTests()
diff --git a/modules/bindings/tests/testfiles/clusters.dmp b/modules/bindings/tests/testfiles/clusters.dmp
new file mode 100644
index 0000000000000000000000000000000000000000..f3974d2148114cc147a9b6ddb69e63a270a50e9c
--- /dev/null
+++ b/modules/bindings/tests/testfiles/clusters.dmp
@@ -0,0 +1,30 @@
+# 29
+1 1
+2 1
+3 1
+4 4
+17 4
+18 4
+5 5
+6 5
+7 5
+10 5
+8 8
+9 9
+13 9
+14 9
+15 9
+16 9
+23 9
+25 9
+11 11
+12 11
+24 11
+19 19
+22 19
+20 20
+21 21
+26 26
+27 26
+28 26
+29 29
diff --git a/modules/bindings/tests/testfiles/fastadb.fasta b/modules/bindings/tests/testfiles/fastadb.fasta
new file mode 100644
index 0000000000000000000000000000000000000000..56895f50475694418d7f7c4dab0cb5d0a0dc737f
--- /dev/null
+++ b/modules/bindings/tests/testfiles/fastadb.fasta
@@ -0,0 +1,58 @@
+>P50198.1
+MANRLAGKVALITGGASGLGAAQAKRFAEEGAKVVIGDLNEEMAKGVVAEIRAAGGDALFIRLDVTDAASWNNAIAAAVDGFGGLTTLSNTAGIIHPGGFEEESIEGWNKMVAVNQTAIFLGIKAAIPELVKSGNGSIINISSLIGMFPTAGNASYCATKAAVRIMSKAAALEFVDRGVRVNTIVPGGMNTPITANVPPDVLKQQTSQIPMGKLGDPIDIANGALFLASDEAKYITGVDLPIDGGWSVGV
+>Q9WYG0.1
+MNFQGKVVLITGAGSGIGKKAAVMFAERGAKVAINDISEEKGKETVELIKSMGGEAAFIFGDVAKDAEQIVKKTVETFGRLDILVNNAGIVPYGNIEETSEEDFDKTMAVNVKGPFLLSKYAVEQMKKQGGGVIVNVSSEAGLIGIPRRCVYSVSKAALLGLTRSLAVDYVDYGIRVNAVCPGTTQSEGLMARVKASPNPEELLKKMTSRIPMKRLGKEEEIAFAILFAACDEAGFMTGSIINIDGGSTAV
+>Q8KWT4.1
+MNLTDKTVLITGGASGIGYAAVQAFLNQQANVVVADIDEAQGEAMIRKENNDRLHFVHTDITDEPACQNAIRSAVDKFGGLDVLINNAGIEIVAPIHEMELSNWNKVLNVNLTGMFLMSKHALKYMLKSGKGNIINTCSVGGVVAWPDIPAYNASKGGVLQLTRSMAVDYAKHNIRVNCVCPGIIDTPLNEKSFLENNEGTLEEIKKEKAKVNPLLRLGKPEEIANVMLFLASDLSSYMTGSAITADGGYTAQ
+>P39640.2
+MNLTDKTVLITGGASGIGYAAVQAFLGQQANVVVADIDEAQGEAMVRKENNDRLHFVQTDITDEAACQHAVESAVHTFGGLDVLINNAGIEIVAPIHEMELSDWNKVLQVNLTGMFLMSKHALKHMLAAGKGNIINTCSVGGLVAWPDIPAYNASKGGVLQLTKSMAVDYAKHQIRVNCVCPGIIDTPLNEKSFLENNEGTLEEIKKEKAKVNPLLRLGKPEEIANVMLFLASDLSSYMTGSAITADGGYTAQ
+>P46331.2
+MGRLENKTAVITGAATGIGQATAEVFANEGARVIIGDINKDQMEETVDAIRKNGGQAESFHLDVSDENSVKAFADQIKDACGTIDILFNNAGVDQEGGKVHEYPVDLFDRIIAVDLRGTFLCSKYLIPLMLENGGSIINTSSMSGRAADLDRSGYNAAKGGITNLTKAMAIDYARNGIRVNSISPGTIETPLIDKLAGTKEQEMGEQFREANKWITPLGRLGQPKEMATVALFLASDDSSYVTGEDITADGGIMAYTWPGKMLIEEKWKEETK
+>P50197.1
+MSDLSGKTIIVTGGGSGIGRATVELLVASGANVPVADINDEAGEAVVATSGGKAAYFRCDIAQEEDVKALVAQTLAAFGGLDGSFNNAAIPQAGLPLAEVSLERFRQSMDINVTGTFLCMKYQILAMIERGTKGSIVNTASAAGVVGVPMHGEYVGAKHAVVGLTRVAAADYGKHGIRVNALVPGAVRTPMLQRAMDNDAGLEPYLNSIHPIGRFSEPHEQAQAAVWLLSDAASFVTGSCLAADGGFTAI
+>P42317.2
+MRKQVALVTGAAGGIGFEIAREFAREGASVIVSDLRPEACEKAASKLAEEGFDAAAIPYDVTKEAQVADTVNVIQKQYGRLDILVNNAGIQHVAPIEEFPTDTFEQLIKVMLTAPFIAMKHVFPIMKKQQFGRIINIASVNGLVGFAGKSAYNSAKHGVIGLTKVGALEGAPHGITVNALCPGYVDTQLVRNQLSDLSKTRNVPYDSVLEQVIFPLVPQKRLLSVKEIADYAVFLASEKAKGVTGQAVVLDGGYTAQ
+>target
+MRLDGKTALITGSARGIGRAFAEAYVREGARVAIADINLEAARATAAEIGPAACAIALDVTDQASIDRCVAELLDRWGSIDILVNNAALFDLAPIVEITRESYDRLFAINVSGTLFMMQAVARAMIAGGRGGKIINMASQAGRRGEALVGVYCATKAAVISLTQSAGLNLIRHGINVNAIAPGVVDGEHWDGVDAKFADYENLPRGEKKRQVGAAVPFGRMGRAEDLTGMAIFLATPEADYIVAQTYNVDGGNWMS
+>Q59787.1
+MRLDGKTALITGSARGIGRAFAEAYVREGARVAIADINLEAARATAAEIGPAACAIALDVTDQASIDRCVAELLDRWGSIDILVNNAALFDLAPIVEITRESYDRLFAINVSGTLFMMQAVARAMIAGGRGGKIINMASQAGRRGEALVGVYCATKAAVISLTQSAGLNLIRHGINVNAIAPGVVDGEHWDGVDAKFADYENLPRGEKKRQVGAAVPFGRMGRAEDLTGMAIFLATPEADYIVAQTYNVDGGNWMS
+>Q48436.2
+MKKVALVTGAGQGIGKAIALRLVKDGFAVAIADYNDATAKAVASEINQAGGRAMAVKVDVSDRDQVFAAVEQARKTLGGFDVIVNNAGVAPSTPIESITPEIVDKVYNINVKGVIWGIQAAVEAFKKEGHGGKIINACSQAGHVGNPELAVYSSSKFAVRGLTQTAARDLAPLGITVNGYCPGIVKTPMWAEIDRQVSEAAGKPLGYGTAEFAKRITLGRLSEPEDVAACVSYLASPDSDYMTGQSLLIDGGMVFN
+>Q04520.1
+MQKVALVTGAGQGIGKAIALRLVKDGFAVAIADYNDATATAVAAEINQAGGRAVAIKVDVSRRDQVFAAVEQARKALGGFNVIVNNAGIAPSTPIESITEEIVDRVYNINVKGVIWGMQAAVEAFKKEGHGGKIVNACSQAGHVGNPELAVYSSSKFAVRGLTQTAARDLAPLGITVNGFCPGIVKTPMWAEIDRQCRKRRANRWATARLNLPNASPLAACRSLKTSPPACRSSPARIPTI
+>P66776.1
+MTNNKVALVTGGAQGIGFKIAERLVEDGFKVAVVDFNEEGAKAAALKLSSDGTKAIAIKADVSNRDDVFNAVRQTAAQFGDFHVMVNNAGLGPTTPIDTITEEQFKTVYGVNVAGVLWGIQAAHEQFKKFNHGGKIINATSQAGVEGNPGLSLYCSTKFAVRGLTQVAAQDLASEGITVNAFAPGIVQTPMMESIAVATAEEAGKPEAWGWEQFTSQIALGRVSQPEDVSNVVSFLAGKDSDYITGQTIIVDGGMRFR
+>Q5HKG6.1
+MSKTAIITGSAGGLGKGIAERLANDGFNIVLQDINEALLLETEKEFKEKGYQAVAFKSDVSKKKEQEELVQFAVTEFGQLDVMVNNAGVDAVTPILEIGEEELSKLFNINVFGTLFGIQAAANQFIKQKSKGKIINACSIAGHESYEVLGTYSATKHSVRSFTQTAAKELADKGITVNAYCPGVAKTEMWDRIDEEMVKLDDSLEIGDAFEAFSSEIKLGRYQEPSDVANLVSFLASNDSDYITGQSILTDGGLVYR
+>Q8CQD2.1
+MSKTAIITGAAGGLGKGIAERLANDGFNIVLQDINEALLLETEKEFKEKGYQAVAYKSDVSKKKEQEELVQFAVTEFGQLDVMVNNAGVDAVTPILEIGEEELSKLFNINVFGTLFGIQAAANQFIKQKSKGKIINACSIAGHESYEVLGTYSATKHSVRSFTQTAAKELADKGITVNAYCPGVAKTEMWDRIDEEMVKLDDSLEIGDAFEAFSSEIKLGRYQEPSDVANLVSFLASNDSDYITGQSILTDGGLVYR
+>P50199.1
+MSHPDLFSLSGARALVTGASRGIGLTLAKGLARYGAEVVLNGRNAESLDSAQSGFEAEGLKASTAVFDVTDQDAVIDGVAAIERDMGPIDILINNAGIQRRAPLEEFSRKDWDDLMSTNVNAVFFVGQAVARHMIPRGRGKIVNICSVQSELARPGIAPYTATKGAVKNLTKGMATDWGRHGLQINGLAPGYFATEMTERLVADEEFTDWLCKRTPAGRWGQVEELVGAAVFLSSRASSFVNGQVLMVDGGITVSL
+>P0A9Q0.1
+MNDLFSLAGKNILITGSAQGIGFLLATGLGKYGAQIIINDITAERAELAVEKLHQEGIQAVAAPFNVTHKHEIDAAVEHIEKDIGPIDVLVNNAGIQRRHPFTEFPEQEWNDVIAVNQTAVFLVSQAVTRHMVERKAGKVINICSMQSELGRDTITPYAASKGAVKMLTRGMCVELARHNIQVNGIAPGYFKTEMTKALVEDEAFTAWLCKRTPAARWGDPQELIGAAVFLSSKASDFVNGHLLFVDGGMLVAV
+>Q05528.1
+MILNTFNLQGKVALITGCDTGLGQGMAVGLAEAGCDIVGVNIVEPKETIEKVTAVGRRFLSLTADMSDISGHAALVEKAVAEFGKVDILVNNAGIIRREDAIEFSEKNWDDVMNLNIKSVFFMSQTVARQFIKQGHGGKIINIASMLSFQGGIPVPSYTASKKRVMGITRIVANEWAKHNINVNAIAPGYMATNNTQHVRADQDRSKEILDRIPAGRWGLPQDLQGPAVFLASSASDYVNGYTIAVDGGWLAR
+>P37769.2
+MILSAFSLEGKVAVVTGCDTGLGQGMALGLAQAGCDIVGINIVEPTETIEQVTALGRRFLSLTADLRKIDGIPALLDRAVAEFGHIDILVNNAGLIRREDALEFSEKDWDDVMNLNIKSVFFMSQAAAKHFIAQGNGGKIINIASMLSFQGGIRVPSYTASKSGVMGVTRLMANEWAKHNINVNAIAPGYMATNNTQQLRADEQRSAEILDRIPAGRWGLPSDLMGPIVFLASSASDYVNGYTIAVDGGWLAR
+>P50842.1
+MGYLHDAFSLKGKTALVTGPGTGIGQGIAKALAGAGADIIGTSHTSSLSETQQLVEQEGRIFTSFTLDMSKPEAIKDSAAELFENRQIDILVNNAGIIHREKAEDFPEENWQHVLNVNLNSLFILTQLAGRHMLKRGHGKIINIASLLSFQGGILVPAYTASKHAVAGLTKSFANEWAASGIQVNAIAPGYISTANTKPIRDDEKRNEDILKRIPAGRWGQADDIGGTAVFLASRASDYVNGHILAVDGGWLSR
+>Q1JP75.1
+MDLRLAGRRALVTGAGKGIGRSIVKALHAAGARVVAVSRTQADLDSLVRECPGVETVCVDLADWEATEQALGGVGPVDLLVNNAAVAFLQPFLEVTKEAYDMSFSVNLRAVIQVSQIVARGLIARGAPGVIVNVSSQASQRGLTNHSVYCSTKGALDTLTKVMAVELGPHKIRVNAVNPTVVMTPMGQAAWSDPQKAKAMLDRIPLGRFAEVENVVDTILFLLSDRSSMTTGSTVPVDGGFLAT
+>Q91XV4.1
+MDLGLAGRRALVTGAGKGIGRSTVLALQAAGAHVVAVSRTQADLDSLVSECPGVETVCVDLADWEATEQALSSVGPVDLLVNNAAVALLQPFLEVTKEAFDMSFNVNLRAVIQVSQIVARGMIARGAPGAIVNVSSQASQRALANHSVYCSTKGALDMLTKMMALELGPHKIRVNAVNPTVVMTSMGRTNWSDPHKAKVMLDRIPLGKFAEVENVVDAILFLLSHRSNMTTGSTLPVDGGFLVT
+>Q7Z4W1.2
+MELFLAGRRVLVTGAGKGIGRGTVQALHATGARVVAVSRTQADLDSLVRECPGIEPVCVDLGDWEATERALGSVGPVDLLVNNAAVALLQPFLEVTKEAFDRSFEVNLRAVIQVSQIVARGLIARGVPGAIVNVSSQCSQRAVTNHSVYCSTKGALDMLTKVMALELGPHKIRVNAVNPTVVMTSMGQATWSDPHKAKTMLNRIPLGKFAEVEHVVNAILFLLSDRSGMTTGSTLPVEGGFWAC
+>P40397.2
+MANQKKKTLPPQHQNQQPGFEYLMDPRPVFDKPKKAKKLEGKTAIITGGDSGIGRAVSVLFAKEGANVVIVYLNEHQDAEETKQYVEKEGVKCLLIAGDVGDEAFCNDVVGQASQVFPSIDILVNNAAEQHVQPSIEKITSHQLIRTFQTNIFSMFYLTKAVLPHLKKGSSIINTASITAYKGNKTLIDYSATKGAIVTFTRSLSQSLVQQGIRVNAVAPGPIWTPLIPASFAAKDVEVFGSDVPMERPGQPVEVAPSYLYLASDDSTYVTGQTIHVNGGTIVNG
+>O07575.1
+MNPMDRQTEGQEPQHQDRQPGIESKMNPLPLSEDEDYRGSGKLKGKVAIITGGDSGIGRAAAIAFAKEGADISILYLDEHSDAEETRKRIEKENVRCLLIPGDVGDENHCEQAVQQTVDHFGKLDILVNNAAEQHPQDSILNISTEQLEKTFRTNIFSMFHMTKKALPHLQEGCAIINTTSITAYEGDTALIDYSSTKGAIVSFTRSMAKSLADKGIRVNAVAPGPIWTPLIPATFPEEKVKQHGLDTPMGRPGQPVEHAGAYVLLASDESSYMTGQTIHVNGGRFIST
+>Q5KTS5.1
+MASGGQFPPQKQESQPGKEHLMDPSPQHASPHYKPANKLQGKVALVTGGDSGIGRSVCYHFALEGATVAFTFVKGHEDKDANETLELLRKAKSSDAKDPIAIAADLGFDDNCKKVVDQVVNAFGSIDVLVNNAAEQYKASTVEDIDEERLERVFRTNIFAYFFMARHALKHMREGSTIINTTSINAYKGNAKLLDYTATKGAIVAFTRGLSLQLISKGIRVNGVAPGPVWTPLIPSSFDEEEVKQFGSEVPMKRAGQPYEIATAYVFLASCDSSYYSGQVLHPNGGAIVNG
+>Q49117.2
+MSKLEGKVAVVTGASKGIGAAIAKALAKDGAAVVVNYASSKAGADAVVEAITAAGGKAIAVQADVSQAVQARGLVEAAVQQFGRLDVLVNNSGVYEFAAIEEVTEEHYRRIFDVNVLGVLLATQAASKHLGEGGSIINISSVVTDVLMPTSAVYSGTKGALNAISGVLANELAPRKIRVNVVSPGYVVTEGTHTAGIAGSEMEAGLVAQTPLGRSGQPDDIAGVVAFLASDDARWVTGEVINASGGVR
+>Q9KQH7.2
+MNLEGKVALVTGASRGIGKAIAELLAERGAKVIGTATSESGAQAISDYLGDNGKGMALNVTNPESIEAVLKAITDEFGGVDILVNNAGITRDNLLMRMKEEEWSDIMETNLTSIFRLSKAVLRGMMKKRQGRIINVGSVVGTMGNAGQANYAAAKAGVIGFTKSMAREVASRGVTVNTVAPGFIETDMTKALNDEQRTATLAQVPAGRLGDPREIASAVAFLASPEAAYITGETLHVNGGMYMI
+>P55336.1
+MNLEGKIALVTGASRGIGRAIAELLVERGATVIGTATSEGGAAAISEYLGENGKGLALNVTDVESIEATLKTINDECGAIDILVNNAGITRDNLLMRMKDDEWNDIINTNLTPIYRMSKAVLRGMMKKRAGRIINVGSVVGTMGNAGQTNYAAAKAGVIGFTKSMAREVASRGVTVNTVAPGFIETDMTKALNDDQRAATLSNVPAGRLGDPREIASAVVFLASPEAAYITGETLHVNGGMYMV
+>P0A2C9.1
+MSFEGKIALVTGASRGIGRAIAETLVARGAKVIGTATSENGAKNISDYLGANGKGLMLNVTDPASIESVLENIRAEFGEVDILVNNAGITRDNLLMRMKDDEWNDIIETNLSSVFRLSKAVMRAMMKKRCGRIITIGSVVGTMGNAGQANYAAAKAGLIGFSKSLAREVASRGITVNVVAPGFIETDMTRALSDDQRAGILAQVPAGRLGGAQEIASAVAFLASDEASYITGETLHVNGGMYMV
diff --git a/modules/bindings/tests/testfiles/headers.dmp b/modules/bindings/tests/testfiles/headers.dmp
new file mode 100644
index 0000000000000000000000000000000000000000..7c188177f057ad5bad8d2ce8518f39e3b16450d3
--- /dev/null
+++ b/modules/bindings/tests/testfiles/headers.dmp
@@ -0,0 +1,29 @@
+1 >Q5KTS5.1
+2 >O07575.1
+3 >P40397.2
+4 >P46331.2
+17 >P39640.2
+18 >Q8KWT4.1
+5 >P66776.1
+6 >Q8CQD2.1
+7 >Q5HKG6.1
+10 >Q48436.2
+8 >P42317.2
+9 >P50199.1
+13 >P50842.1
+14 >P0A9Q0.1
+15 >P37769.2
+16 >Q05528.1
+23 >P0A2C9.1
+25 >Q9KQH7.2
+11 >Q59787.1
+12 >target
+24 >P55336.1
+19 >Q9WYG0.1
+22 >Q49117.2
+20 >P50197.1
+21 >P50198.1
+26 >Q7Z4W1.2
+27 >Q91XV4.1
+28 >Q1JP75.1
+29 >Q04520.1
diff --git a/modules/bindings/tests/testfiles/raw_blastout.txt b/modules/bindings/tests/testfiles/raw_blastout.txt
new file mode 100644
index 0000000000000000000000000000000000000000..95f567513d6584287e112cdb7e8796dad95b9a8d
--- /dev/null
+++ b/modules/bindings/tests/testfiles/raw_blastout.txt
@@ -0,0 +1,167 @@
+<?xml version="1.0"?>
+<!DOCTYPE BlastOutput PUBLIC "-//NCBI//NCBI BlastOutput/EN" "http://www.ncbi.nlm.nih.gov/dtd/NCBI_BlastOutput.dtd">
+<BlastOutput>
+  <BlastOutput_program>blastp</BlastOutput_program>
+  <BlastOutput_version>blastp 2.2.16 [Mar-25-2007]</BlastOutput_version>
+  <BlastOutput_reference>~Reference: Altschul, Stephen F., Thomas L. Madden, Alejandro A. Schaffer, ~Jinghui Zhang, Zheng Zhang, Webb Miller, and David J. Lipman (1997), ~&quot;Gapped BLAST and PSI-BLAST: a new generation of protein database search~programs&quot;,  Nucleic Acids Res. 25:3389-3402.</BlastOutput_reference>
+  <BlastOutput_db>seqdb</BlastOutput_db>
+  <BlastOutput_query-ID>lcl|1_0</BlastOutput_query-ID>
+  <BlastOutput_query-def>A</BlastOutput_query-def>
+  <BlastOutput_query-len>101</BlastOutput_query-len>
+  <BlastOutput_param>
+    <Parameters>
+      <Parameters_matrix>BLOSUM62</Parameters_matrix>
+      <Parameters_expect>10</Parameters_expect>
+      <Parameters_gap-open>11</Parameters_gap-open>
+      <Parameters_gap-extend>1</Parameters_gap-extend>
+      <Parameters_filter>F</Parameters_filter>
+    </Parameters>
+  </BlastOutput_param>
+  <BlastOutput_iterations>
+    <Iteration>
+      <Iteration_iter-num>1</Iteration_iter-num>
+      <Iteration_query-ID>lcl|1_0</Iteration_query-ID>
+      <Iteration_query-def>A</Iteration_query-def>
+      <Iteration_query-len>101</Iteration_query-len>
+      <Iteration_hits>
+        <Hit>
+          <Hit_num>1</Hit_num>
+          <Hit_id>gnl|BL_ORD_ID|1</Hit_id>
+          <Hit_def>1griA</Hit_def>
+          <Hit_accession>1</Hit_accession>
+          <Hit_len>211</Hit_len>
+          <Hit_hsps>
+            <Hsp>
+              <Hsp_num>1</Hsp_num>
+              <Hsp_bit-score>210.305</Hsp_bit-score>
+              <Hsp_score>534</Hsp_score>
+              <Hsp_evalue>4.80893e-59</Hsp_evalue>
+              <Hsp_query-from>1</Hsp_query-from>
+              <Hsp_query-to>101</Hsp_query-to>
+              <Hsp_hit-from>49</Hsp_hit-from>
+              <Hsp_hit-to>149</Hsp_hit-to>
+              <Hsp_query-frame>1</Hsp_query-frame>
+              <Hsp_hit-frame>1</Hsp_hit-frame>
+              <Hsp_identity>101</Hsp_identity>
+              <Hsp_positive>101</Hsp_positive>
+              <Hsp_align-len>101</Hsp_align-len>
+              <Hsp_qseq>MKPHPWFFGKIPRAKAEEMLSKQRHDGAFLIRESESAPGDFSLSVKFGNDVQHFKVLRDGAGKYFLWVVKFNSLNELVDYHRSTSVSRNQQIFLRDIEQVP</Hsp_qseq>
+              <Hsp_hseq>MKPHPWFFGKIPRAKAEEMLSKQRHDGAFLIRESESAPGDFSLSVKFGNDVQHFKVLRDGAGKYFLWVVKFNSLNELVDYHRSTSVSRNQQIFLRDIEQVP</Hsp_hseq>
+              <Hsp_midline>MKPHPWFFGKIPRAKAEEMLSKQRHDGAFLIRESESAPGDFSLSVKFGNDVQHFKVLRDGAGKYFLWVVKFNSLNELVDYHRSTSVSRNQQIFLRDIEQVP</Hsp_midline>
+            </Hsp>
+          </Hit_hsps>
+        </Hit>
+        <Hit>
+          <Hit_num>2</Hit_num>
+          <Hit_id>gnl|BL_ORD_ID|0</Hit_id>
+          <Hit_def>1fhsA</Hit_def>
+          <Hit_accession>0</Hit_accession>
+          <Hit_len>112</Hit_len>
+          <Hit_hsps>
+            <Hsp>
+              <Hsp_num>1</Hsp_num>
+              <Hsp_bit-score>210.305</Hsp_bit-score>
+              <Hsp_score>534</Hsp_score>
+              <Hsp_evalue>4.80893e-59</Hsp_evalue>
+              <Hsp_query-from>1</Hsp_query-from>
+              <Hsp_query-to>101</Hsp_query-to>
+              <Hsp_hit-from>4</Hsp_hit-from>
+              <Hsp_hit-to>104</Hsp_hit-to>
+              <Hsp_query-frame>1</Hsp_query-frame>
+              <Hsp_hit-frame>1</Hsp_hit-frame>
+              <Hsp_identity>101</Hsp_identity>
+              <Hsp_positive>101</Hsp_positive>
+              <Hsp_align-len>101</Hsp_align-len>
+              <Hsp_qseq>MKPHPWFFGKIPRAKAEEMLSKQRHDGAFLIRESESAPGDFSLSVKFGNDVQHFKVLRDGAGKYFLWVVKFNSLNELVDYHRSTSVSRNQQIFLRDIEQVP</Hsp_qseq>
+              <Hsp_hseq>MKPHPWFFGKIPRAKAEEMLSKQRHDGAFLIRESESAPGDFSLSVKFGNDVQHFKVLRDGAGKYFLWVVKFNSLNELVDYHRSTSVSRNQQIFLRDIEQVP</Hsp_hseq>
+              <Hsp_midline>MKPHPWFFGKIPRAKAEEMLSKQRHDGAFLIRESESAPGDFSLSVKFGNDVQHFKVLRDGAGKYFLWVVKFNSLNELVDYHRSTSVSRNQQIFLRDIEQVP</Hsp_midline>
+            </Hsp>
+          </Hit_hsps>
+        </Hit>
+        <Hit>
+          <Hit_num>3</Hit_num>
+          <Hit_id>gnl|BL_ORD_ID|2</Hit_id>
+          <Hit_def>3n84E</Hit_def>
+          <Hit_accession>2</Hit_accession>
+          <Hit_len>102</Hit_len>
+          <Hit_hsps>
+            <Hsp>
+              <Hsp_num>1</Hsp_num>
+              <Hsp_bit-score>206.068</Hsp_bit-score>
+              <Hsp_score>523</Hsp_score>
+              <Hsp_evalue>9.06925e-58</Hsp_evalue>
+              <Hsp_query-from>1</Hsp_query-from>
+              <Hsp_query-to>99</Hsp_query-to>
+              <Hsp_hit-from>4</Hsp_hit-from>
+              <Hsp_hit-to>102</Hsp_hit-to>
+              <Hsp_query-frame>1</Hsp_query-frame>
+              <Hsp_hit-frame>1</Hsp_hit-frame>
+              <Hsp_identity>99</Hsp_identity>
+              <Hsp_positive>99</Hsp_positive>
+              <Hsp_align-len>99</Hsp_align-len>
+              <Hsp_qseq>MKPHPWFFGKIPRAKAEEMLSKQRHDGAFLIRESESAPGDFSLSVKFGNDVQHFKVLRDGAGKYFLWVVKFNSLNELVDYHRSTSVSRNQQIFLRDIEQ</Hsp_qseq>
+              <Hsp_hseq>MKPHPWFFGKIPRAKAEEMLSKQRHDGAFLIRESESAPGDFSLSVKFGNDVQHFKVLRDGAGKYFLWVVKFNSLNELVDYHRSTSVSRNQQIFLRDIEQ</Hsp_hseq>
+              <Hsp_midline>MKPHPWFFGKIPRAKAEEMLSKQRHDGAFLIRESESAPGDFSLSVKFGNDVQHFKVLRDGAGKYFLWVVKFNSLNELVDYHRSTSVSRNQQIFLRDIEQ</Hsp_midline>
+            </Hsp>
+          </Hit_hsps>
+        </Hit>
+        <Hit>
+          <Hit_num>4</Hit_num>
+          <Hit_id>gnl|BL_ORD_ID|5</Hit_id>
+          <Hit_def>1mw9X</Hit_def>
+          <Hit_accession>5</Hit_accession>
+          <Hit_len>556</Hit_len>
+          <Hit_hsps>
+            <Hsp>
+              <Hsp_num>1</Hsp_num>
+              <Hsp_bit-score>15.0086</Hsp_bit-score>
+              <Hsp_score>27</Hsp_score>
+              <Hsp_evalue>2.96523</Hsp_evalue>
+              <Hsp_query-from>31</Hsp_query-from>
+              <Hsp_query-to>43</Hsp_query-to>
+              <Hsp_hit-from>123</Hsp_hit-from>
+              <Hsp_hit-to>135</Hsp_hit-to>
+              <Hsp_query-frame>1</Hsp_query-frame>
+              <Hsp_hit-frame>1</Hsp_hit-frame>
+              <Hsp_identity>4</Hsp_identity>
+              <Hsp_positive>10</Hsp_positive>
+              <Hsp_align-len>13</Hsp_align-len>
+              <Hsp_qseq>IRESESAPGDFSL</Hsp_qseq>
+              <Hsp_hseq>IRQAFNKPGELNI</Hsp_hseq>
+              <Hsp_midline>IR++ + PG+ ++</Hsp_midline>
+            </Hsp>
+            <Hsp>
+              <Hsp_num>2</Hsp_num>
+              <Hsp_bit-score>13.853</Hsp_bit-score>
+              <Hsp_score>24</Hsp_score>
+              <Hsp_evalue>6.60584</Hsp_evalue>
+              <Hsp_query-from>9</Hsp_query-from>
+              <Hsp_query-to>33</Hsp_query-to>
+              <Hsp_hit-from>170</Hsp_hit-from>
+              <Hsp_hit-to>194</Hsp_hit-to>
+              <Hsp_query-frame>1</Hsp_query-frame>
+              <Hsp_hit-frame>1</Hsp_hit-frame>
+              <Hsp_identity>5</Hsp_identity>
+              <Hsp_positive>12</Hsp_positive>
+              <Hsp_align-len>25</Hsp_align-len>
+              <Hsp_qseq>GKIPRAKAEEMLSKQRHDGAFLIRE</Hsp_qseq>
+              <Hsp_hseq>GRVQSVAVRLVVEREREIKAFVPEE</Hsp_hseq>
+              <Hsp_midline>G++       ++ ++R   AF+  E</Hsp_midline>
+            </Hsp>
+          </Hit_hsps>
+        </Hit>
+      </Iteration_hits>
+      <Iteration_stat>
+        <Statistics>
+          <Statistics_db-num>6</Statistics_db-num>
+          <Statistics_db-len>1507</Statistics_db-len>
+          <Statistics_hsp-len>28</Statistics_hsp-len>
+          <Statistics_eff-space>97747</Statistics_eff-space>
+          <Statistics_kappa>0.041</Statistics_kappa>
+          <Statistics_lambda>0.267</Statistics_lambda>
+          <Statistics_entropy>0.14</Statistics_entropy>
+        </Statistics>
+      </Iteration_stat>
+    </Iteration>
+  </BlastOutput_iterations>
+</BlastOutput>
diff --git a/modules/conop/pymod/export_heuristic.cc b/modules/conop/pymod/export_heuristic.cc
index 11efd96d82517aaf4f94744614fac49a82383a74..f25ca9814bf0e7589d58fa2db35c261acafee8cc 100644
--- a/modules/conop/pymod/export_heuristic.cc
+++ b/modules/conop/pymod/export_heuristic.cc
@@ -29,6 +29,12 @@ void export_heuristic() {
   class_<HeuristicProcessor, HeuristicProcessorPtr, 
          boost::noncopyable, bases<Processor> >("HeuristicProcessor", 
          init<>())
+    .def(init<bool,bool,bool,bool,ConopAction>(
+         (arg("check_bond_feasibility")=false,
+         arg("assign_torsions")=false,
+         arg("connect")=true,
+         arg("peptide_bonds")=true,
+         arg("zero_occ_treatment")=CONOP_WARN)))
   ;
 }
 
diff --git a/modules/conop/pymod/export_processor.cc b/modules/conop/pymod/export_processor.cc
index c6f1cf2a236ce0a49bfb1df5e9f3873de04d607e..00c72521b07a6218f60b811ef6c7bb4b5a0dcc30 100644
--- a/modules/conop/pymod/export_processor.cc
+++ b/modules/conop/pymod/export_processor.cc
@@ -52,6 +52,15 @@ void export_processor() {
     .value("CHARMM_DIALECT", CHARMM_DIALECT)
     .export_values()
   ;
+  enum_<ConopAction>("ConopAction")
+    .value("CONOP_WARN", CONOP_WARN)
+    .value("CONOP_SILENT", CONOP_SILENT)
+    .value("CONOP_REMOVE", CONOP_REMOVE)
+    .value("CONOP_REMOVE_ATOM", CONOP_REMOVE_ATOM)
+    .value("CONOP_REMOVE_RESIDUE", CONOP_REMOVE_RESIDUE)
+    .value("CONOP_FATAL", CONOP_FATAL)
+    .export_values()
+  ;
   class_<Processor, ProcessorPtr, boost::noncopyable>("_Processor", no_init)
     .def("Copy", &Processor::Copy)
     .add_property("check_bond_feasibility", 
diff --git a/modules/conop/pymod/export_rule_based.cc b/modules/conop/pymod/export_rule_based.cc
index 5331dd917a80e82d16847e3b34457aab5ec81c95..6fef009a0bd22913a8c850246e71176ff529a295 100644
--- a/modules/conop/pymod/export_rule_based.cc
+++ b/modules/conop/pymod/export_rule_based.cc
@@ -28,6 +28,15 @@ void export_rule_based() {
   class_<RuleBasedProcessor, RuleBasedProcessorPtr, 
          boost::noncopyable, bases<Processor> >("RuleBasedProcessor", 
          init<CompoundLibPtr>())
+    .def(init<CompoundLibPtr,bool,bool,ConopAction,ConopAction,bool,bool,bool,bool,ConopAction>(
+         (arg("lib"), arg("fix_elements")=true, arg("strict_hydrogens")=false,
+         arg("unknown_res_treatment")=CONOP_WARN,
+         arg("unknown_atom_treatment")=CONOP_WARN,
+         arg("check_bond_feasibility")=false,
+         arg("assign_torsions")=false,
+         arg("connect")=true,
+         arg("peptide_bonds")=true,
+         arg("zero_occ_treatment")=CONOP_WARN)))
     .add_property("fix_element", &RuleBasedProcessor::GetFixElement,
                  &RuleBasedProcessor::SetFixElement)
     .add_property("unk_res_treatment", &RuleBasedProcessor::GetUnkResidueTreatment,
diff --git a/modules/conop/src/CMakeLists.txt b/modules/conop/src/CMakeLists.txt
index d5649f4008b5df9bd7241ce8553e474ca803f78b..3709e846aa244c06bc2fbca34e8e848fe95d8d22 100644
--- a/modules/conop/src/CMakeLists.txt
+++ b/modules/conop/src/CMakeLists.txt
@@ -34,7 +34,12 @@ ring_finder.cc
 module(NAME conop SOURCES ${OST_CONOP_SOURCES}
        HEADERS ${OST_CONOP_HEADERS} DEPENDS_ON ost_mol ost_mol_alg ost_geom ost_db)
 
-executable(NAME chemdict_tool SOURCES chemdict_tool.cc DEPENDS_ON ost_io STATIC)
+
+if (WIN32)
+  executable(NAME chemdict_tool SOURCES chemdict_tool.cc ../../io/src/zlib.cpp ../../io/src/gzip.cpp DEPENDS_ON ost_io STATIC)
+else(WIN32)
+  executable(NAME chemdict_tool SOURCES chemdict_tool.cc DEPENDS_ON ost_io STATIC)
+endif(WIN32)
 
 if (COMPOUND_LIB)
   if (EXISTS "${COMPOUND_LIB}")
diff --git a/modules/conop/src/compound_lib.cc b/modules/conop/src/compound_lib.cc
index db00bcc771502cd99b8c58c9d72e58d3723545e3..90e5df87c00ecc2aa8714bcb6df499ad878d4c09 100644
--- a/modules/conop/src/compound_lib.cc
+++ b/modules/conop/src/compound_lib.cc
@@ -159,7 +159,6 @@ Date CompoundLib::GetCreationDate(void){
     }
     assert(SQLITE_DONE==sqlite3_step(stmt));
   } else {
-    LOG_ERROR("ERROR: " << sqlite3_errmsg(conn_));
     sqlite3_finalize(stmt);      
     return Date();
   }
@@ -168,7 +167,7 @@ Date CompoundLib::GetCreationDate(void){
 }
 
 
-String CompoundLib::GetOSTVersionUsed(){
+String CompoundLib::GetOSTVersionUsed() {
   String query="SELECT ost_version_used FROM chemlib_info";
   sqlite3_stmt* stmt;
   String version;
@@ -189,7 +188,7 @@ String CompoundLib::GetOSTVersionUsed(){
     }
     assert(SQLITE_DONE==sqlite3_step(stmt));
   } else {
-    LOG_ERROR("ERROR: " << sqlite3_errmsg(conn_) << " - your compound library might be outdated!");
+    LOG_WARNING("your compound library might be outdated.");
     sqlite3_finalize(stmt);      
     return String();
   }
diff --git a/modules/conop/src/heuristic.hh b/modules/conop/src/heuristic.hh
index 568b05d0df535479c45f3ead5df2b958a8c767ba..6fb8a7877c50ad6f83e8f02da1b464a8da7fa141 100644
--- a/modules/conop/src/heuristic.hh
+++ b/modules/conop/src/heuristic.hh
@@ -38,6 +38,8 @@ public:
   virtual ProcessorPtr Copy() const {
     return ProcessorPtr(new HeuristicProcessor(*this));
   }
+  HeuristicProcessor(bool bf, bool at, bool cn, bool aa, ConopAction zo): 
+    Processor(bf, at, cn, aa, zo) {}
 protected:
   void ProcessUnkResidue(DiagnosticsPtr diags, mol::ResidueHandle res) const;
   virtual void DoProcess(DiagnosticsPtr diags, 
diff --git a/modules/conop/src/processor.hh b/modules/conop/src/processor.hh
index 6e15fc4797f11541f879b2e0690be4049fd182e6..01435123366e496c41d649bdd209fea6b9a6b51f 100644
--- a/modules/conop/src/processor.hh
+++ b/modules/conop/src/processor.hh
@@ -66,6 +66,9 @@ protected:
   void DistanceBasedConnect(mol::AtomHandle atom) const;
   mol::AtomHandle LocateAtom(const mol::AtomHandleList&, int ordinal) const;
 public:
+  Processor(bool bf, bool at, bool cn, bool aa, ConopAction zo): check_bond_feasibility_(bf),
+    assign_torsions_(at), connect_(cn), connect_aa_(aa),
+    zero_occ_treatment_(zo) {}
   Processor(): check_bond_feasibility_(false),
     assign_torsions_(false), connect_(true), connect_aa_(true),
     zero_occ_treatment_(CONOP_SILENT) {}
diff --git a/modules/conop/src/rule_based.hh b/modules/conop/src/rule_based.hh
index 62ae2d47014831ec3479007f9c8ccad573ca92ec..6fa83490c5a2b065f071a5cf2eaf98b0e5a711e9 100644
--- a/modules/conop/src/rule_based.hh
+++ b/modules/conop/src/rule_based.hh
@@ -42,6 +42,10 @@ public:
   {
   }
 
+  RuleBasedProcessor(CompoundLibPtr compound_lib, bool fe, bool sh, ConopAction ur, 
+                     ConopAction ua, bool bf, bool at, bool cn, bool aa, ConopAction zo): 
+    lib_(compound_lib), fix_element_(fe), strict_hydrogens_(sh), unk_res_treatment_(ur), 
+    unk_atom_treatment_(ua),Processor(bf, at, cn, aa, zo) {}
   ConopAction GetUnkResidueTreatment() const {
     return unk_res_treatment_;
   }
diff --git a/modules/conop/tests/test_cleanup.py b/modules/conop/tests/test_cleanup.py
index c2b3b2b0e1614ae50f195d433b62e36034f5e971..9c5f0cf27fc1f340aef4b48c7753b1671bd86e04 100644
--- a/modules/conop/tests/test_cleanup.py
+++ b/modules/conop/tests/test_cleanup.py
@@ -1,3 +1,4 @@
+import sys
 import unittest
 from ost import geom, conop
 from ost.conop import cleanup
diff --git a/modules/conop/tests/test_processor.py b/modules/conop/tests/test_processor.py
index b8662c44283a2e4298d50281d88724e5295a8b5a..94a1a7c27d4009a86feeb5d97c671e0e6b5038f5 100644
--- a/modules/conop/tests/test_processor.py
+++ b/modules/conop/tests/test_processor.py
@@ -1,5 +1,5 @@
 import unittest
-from ost import conop
+from ost import conop, mol
 
 
 class TestProcessor(unittest.TestCase):
@@ -14,6 +14,7 @@ class TestProcessor(unittest.TestCase):
     ent = mol.CreateEntity()
     p.Process(ent)
     self.assertEqual(p.count, 1)
+
 if __name__ == "__main__":
   from ost import testutils
   testutils.RunTests()
diff --git a/modules/db/src/CMakeLists.txt b/modules/db/src/CMakeLists.txt
index 8da34460be841e381308fcff5e6ca7e47cd59115..7d39362067e04933ceb279ea31ac044046ff106e 100644
--- a/modules/db/src/CMakeLists.txt
+++ b/modules/db/src/CMakeLists.txt
@@ -12,8 +12,9 @@ sqlite3.c
 
 module(NAME db SOURCES ${OST_DB_SOURCES} HEADERS ${OST_DB_HEADERS} 
        DEPENDS_ON ost_base)
-add_definitions(-DSQLITE_OMIT_LOAD_EXTENSION) 
 if(WIN32)
-  set_target_properties(ost_db PROPERTIES LINK_FLAGS "/DEF:sqlite3.def")
+  set_target_properties(ost_db PROPERTIES LINK_FLAGS "/DEF:${CMAKE_CURRENT_SOURCE_DIR}/sqlite3.def")
   add_definitions(/DSQLITE_ENABLE_COLUMN_METADATA)
+else(WIN32)
+  add_definitions(-DSQLITE_OMIT_LOAD_EXTENSION)
 endif(WIN32)
diff --git a/modules/geom/pymod/export_mat2.cc b/modules/geom/pymod/export_mat2.cc
index 0338f1ddd482fea1c6c5bf0078b262234119374a..446aca95ce24f013b8fa3c3c58953f0d28383973 100644
--- a/modules/geom/pymod/export_mat2.cc
+++ b/modules/geom/pymod/export_mat2.cc
@@ -23,8 +23,17 @@ using namespace boost::python;
 
 
 
-const Real Mat2_getitem(const geom::Mat2& m, tuple i) {return m(extract<int> (i[0]),extract<int> (i[1]));}
-void Mat2_setitem(geom::Mat2& m,const  tuple i,const  Real val) {m(extract<int> (i[0]),extract<int> (i[1]))=val;}
+const Real Mat2_getitem(const geom::Mat2& m, tuple i) {
+  int a = extract<int> (i[0]);
+  int b = extract<int> (i[1]);
+  return m.At(a, b);
+}
+
+void Mat2_setitem(geom::Mat2& m,const  tuple i,const  Real val) {
+  int a = extract<int> (i[0]);
+  int b = extract<int> (i[1]);
+  m.At(a, b) = val;
+}
 
 String mat2_repr(const geom::Mat2& m) {
   std::stringstream ss;
diff --git a/modules/geom/pymod/export_mat3.cc b/modules/geom/pymod/export_mat3.cc
index 1e543b7d912cb9b20f96f54ba8de2bb902dd5249..c12f6402c86e1b1a8426007bfa71fec4044bba74 100644
--- a/modules/geom/pymod/export_mat3.cc
+++ b/modules/geom/pymod/export_mat3.cc
@@ -25,8 +25,16 @@ using namespace geom;
 
 
 
-const Real Mat3_getitem(const geom::Mat3& m, tuple i) {return m(extract<int> (i[0]),extract<int> (i[1]));}
-void Mat3_setitem(geom::Mat3& m,const  tuple i,const  Real val) {m(extract<int> (i[0]),extract<int> (i[1]))=val;}
+const Real Mat3_getitem(const geom::Mat3& m, tuple i) {
+  int a = extract<int> (i[0]);
+  int b = extract<int> (i[1]);
+  return m.At(a, b);
+}
+void Mat3_setitem(geom::Mat3& m,const  tuple i,const  Real val) { 
+  int a = extract<int> (i[0]);
+  int b = extract<int> (i[1]);
+  m.At(a, b) = val;
+}
 
 Mat2 Mat3_getslice(const geom::Mat3& m, slice s) {
   tuple start=extract<tuple> (s.start());
diff --git a/modules/geom/pymod/export_mat4.cc b/modules/geom/pymod/export_mat4.cc
index 1745e35b7e64a277eb102497736b343b4089f5d8..ec003a0e36105c29014fc8c93c1c80845cf5b805 100644
--- a/modules/geom/pymod/export_mat4.cc
+++ b/modules/geom/pymod/export_mat4.cc
@@ -26,8 +26,17 @@ using namespace geom;
 
 
 
-const Real Mat4_getitem(const geom::Mat4& m, tuple i) {return m(extract<int> (i[0]),extract<int> (i[1]));}
-void Mat4_setitem(geom::Mat4& m,const  tuple i,const  Real val) {m(extract<int> (i[0]),extract<int> (i[1]))=val;}
+const Real Mat4_getitem(const geom::Mat4& m, tuple i) {
+  int a = extract<int> (i[0]);
+  int b = extract<int> (i[1]);
+  return m.At(a, b);
+}
+
+void Mat4_setitem(geom::Mat4& m,const  tuple i,const  Real val) {
+  int a = extract<int> (i[0]);
+  int b = extract<int> (i[1]);
+  m.At(a, b) = val;
+}
 
 Mat3 Mat4_getslice(const geom::Mat4& m, slice s) {
   tuple start=extract<tuple> (s.start());
@@ -38,7 +47,9 @@ Mat3 Mat4_getslice(const geom::Mat4& m, slice s) {
   int end1=extract<int> (end[1]);
   if(end0-start0==1 && end1-start1==1) throw GeomException("Invalid slice: Only Mat3 slices allowed");
   if(end0-start0!=2 || end1-start1!=2) throw GeomException("Invalid slice");
-  return Mat3(m(start0,start1),m(start0,start1+1),m(start0,start1+2),m(start0+1,start1),m(start0+1,start1+1),m(start0+1,start1+2),m(start0+2,start1),m(start0+2,start1+1),m(start0+2,start1+2));
+  return Mat3(m.At(start0+0,start1), m.At(start0+0,start1+1), m.At(start0+0,start1+2),
+              m.At(start0+1,start1), m.At(start0+1,start1+1), m.At(start0+1,start1+2),
+              m.At(start0+2,start1), m.At(start0+2,start1+1), m.At(start0+2,start1+2));
 }
 void Mat4_setslice2(geom::Mat4& m,const  slice s,const  Mat2& m2)
 {
@@ -49,10 +60,10 @@ void Mat4_setslice2(geom::Mat4& m,const  slice s,const  Mat2& m2)
   int end0=extract<int> (end[0]);
   int end1=extract<int> (end[1]);
   if(end0-start0!=1 || end1-start1!=1) throw GeomException("Invalid slice");
-  m(start0,start1)=m2(0,0);
-  m(start0,start1+1)=m2(0,1);
-  m(start0+1,start1)=m2(1,0);
-  m(start0+1,start1+1)=m2(1,1);
+  m.At(start0,start1)=m2(0,0);
+  m.At(start0,start1+1)=m2(0,1);
+  m.At(start0+1,start1)=m2(1,0);
+  m.At(start0+1,start1+1)=m2(1,1);
 }
 void Mat4_setslice3(geom::Mat4& m,const  slice s,const  Mat3& m2)
 {
@@ -63,15 +74,15 @@ void Mat4_setslice3(geom::Mat4& m,const  slice s,const  Mat3& m2)
   int end0=extract<int> (end[0]);
   int end1=extract<int> (end[1]);
   if(end0-start0!=2 || end1-start1!=2) throw GeomException("Invalid slice");
-  m(start0,start1)=m2(0,0);
-  m(start0,start1+1)=m2(0,1);
-  m(start0,start1+2)=m2(0,2);
-  m(start0+1,start1)=m2(1,0);
-  m(start0+1,start1+1)=m2(1,1);
-  m(start0+1,start1+2)=m2(1,2);
-  m(start0+2,start1)=m2(2,0);
-  m(start0+2,start1+1)=m2(2,1);
-  m(start0+2,start1+2)=m2(2,2);
+  m.At(start0,start1)=m2(0,0);
+  m.At(start0,start1+1)=m2(0,1);
+  m.At(start0,start1+2)=m2(0,2);
+  m.At(start0+1,start1)=m2(1,0);
+  m.At(start0+1,start1+1)=m2(1,1);
+  m.At(start0+1,start1+2)=m2(1,2);
+  m.At(start0+2,start1)=m2(2,0);
+  m.At(start0+2,start1+1)=m2(2,1);
+  m.At(start0+2,start1+2)=m2(2,2);
 }
 
 String mat4_repr(const geom::Mat4& m) {
diff --git a/modules/geom/pymod/export_vec2.cc b/modules/geom/pymod/export_vec2.cc
index 161bda9f6d93b2515d59eb941c785adac4df0d71..f760d7e7032f74cd89d2690f76d24e1096b8c6ec 100644
--- a/modules/geom/pymod/export_vec2.cc
+++ b/modules/geom/pymod/export_vec2.cc
@@ -24,8 +24,12 @@
 
 using namespace boost::python;
 
-const Real Vec2_getitem(const geom::Vec2& v, int i) {return v[i];}
-void Vec2_setitem(geom::Vec2& v,const  int i,const  Real val) {v[i]=val;}
+const Real Vec2_getitem(const geom::Vec2& v, int i) {
+  return v.At(i);
+}
+void Vec2_setitem(geom::Vec2& v,const  int i,const  Real val) {
+  v.At(i)=val;
+}
 
 
 String vec2_repr(const geom::Vec2& v)
diff --git a/modules/geom/pymod/export_vec3.cc b/modules/geom/pymod/export_vec3.cc
index aab91add33e3a2fa09378c5e1734789199eb2bfb..e0c4ac6c8e4b7bf4184bf79ddfa445188a643f59 100644
--- a/modules/geom/pymod/export_vec3.cc
+++ b/modules/geom/pymod/export_vec3.cc
@@ -24,8 +24,12 @@
 
 using namespace boost::python;
 
-const Real Vec3_getitem(const geom::Vec3& v, int i) {return v[i];}
-void Vec3_setitem(geom::Vec3& v,const  int i,const  Real val) {v[i]=val;}
+const Real Vec3_getitem(const geom::Vec3& v, int i) {
+  return v.At(i);
+}
+void Vec3_setitem(geom::Vec3& v,const  int i,const  Real val) {
+  v.At(i)=val;
+}
 
 geom::Vec3 NormalizeV3(const geom::Vec3& v) {
   return geom::Normalize(v);
diff --git a/modules/geom/pymod/export_vec4.cc b/modules/geom/pymod/export_vec4.cc
index 986fbfa73a8b61b04eb077f75d25026fa0e3dccc..810c9de1c7cde2d5a19e6e1c3d2931ade3bb893b 100644
--- a/modules/geom/pymod/export_vec4.cc
+++ b/modules/geom/pymod/export_vec4.cc
@@ -23,8 +23,13 @@ using namespace boost::python;
 
 
 
-const Real Vec4_getitem(const geom::Vec4& v, int i) {return v[i];}
-void Vec4_setitem(geom::Vec4& v,const  int i,const  Real val) {v[i]=val;}
+const Real Vec4_getitem(const geom::Vec4& v, int i) {
+  return v.At(i);
+}
+
+void Vec4_setitem(geom::Vec4& v,const  int i,const  Real val) {
+  v.At(i)=val;
+}
 
 String vec4_repr(const geom::Vec4& v)
 {
diff --git a/modules/geom/src/mat2.hh b/modules/geom/src/mat2.hh
index cb5910df4dac9a292e575cf3f88bf3e84985b40e..b7743dfc03e18656648513bf48be068d901f4038 100644
--- a/modules/geom/src/mat2.hh
+++ b/modules/geom/src/mat2.hh
@@ -64,20 +64,35 @@ public:
   //! comparable
   bool operator==(const Mat2& rhs) const;
 
+
+  //! const element access
+  const Real& At(std::size_t r, std::size_t c) const
+  {
+    if (r>1 || c>1) {
+      throw std::out_of_range("indices must be smaller than 2");
+    }
+    return data_[r][c];
+  }
+
   //! element access
-  Real& operator()(std::size_t r, std::size_t c)
+  Real& At(std::size_t r, std::size_t c)
   {
-    if (r>1 || c >1) {
-      throw std::out_of_range("row and column must be in the range [0-1]");
+    if (r>1 || c>1) {
+      throw std::out_of_range("indices must be smaller than 2");
     }
     return data_[r][c];
   }
+
+  //! element access
+  Real& operator()(std::size_t r, std::size_t c)
+  {
+    assert(r<2 && c<2);
+    return data_[r][c];
+  }
   //! const element access
   const Real& operator()(std::size_t r, std::size_t c) const
   {
-    if (r>1 || c >1) {
-      throw std::out_of_range("row and column must be in the range [0-1]");
-    }
+    assert(r<2 && c<2);
     return data_[r][c];
   }
 
diff --git a/modules/geom/src/mat3.hh b/modules/geom/src/mat3.hh
index 3cef352edb5fdce4b0b802c66d35352939d804c3..35cae2f03f078e7d7c7fa9e97c5bf06ba09c0344 100644
--- a/modules/geom/src/mat3.hh
+++ b/modules/geom/src/mat3.hh
@@ -82,19 +82,31 @@ public:
     this->set(x, 0.0, 0.0, 0.0, y, 0.0, 0.0, 0.0, z);
   }
   //! element access
-  Real& operator()(std::size_t r, std::size_t c)
+  Real& At(std::size_t r, std::size_t c)
+  {
+    if (r>2 || c>2) {
+      throw std::out_of_range("indices must be smaller than 3");
+    }
+    return data_[r][c];
+  }
+  //! element access
+  const Real& At(std::size_t r, std::size_t c) const
   {
-    if (r>2 || c >2) {
-      throw std::out_of_range("row and column must be in the range [0-2]");
+    if (r>2 || c>2) {
+      throw std::out_of_range("indices must be smaller than 3");
     }
     return data_[r][c];
   }
+  //! element access
+  Real& operator()(std::size_t r, std::size_t c)
+  {
+    assert(r<3 && c<3);
+    return data_[r][c];
+  }
   //! const element access
   const Real& operator()(std::size_t r, std::size_t c) const
   {
-    if (r>2 || c >2) {
-      throw std::out_of_range("row and column must be in the range [0-2]");
-    }
+    assert(r<3 && c<3);
     return data_[r][c];
   }
 
diff --git a/modules/geom/src/mat4.cc b/modules/geom/src/mat4.cc
index fbbc1c2a05d811e78793ee8fe1b933aee729bbe8..c43780e0a44f1b35447b82a6af60422f25ffc8cc 100644
--- a/modules/geom/src/mat4.cc
+++ b/modules/geom/src/mat4.cc
@@ -121,17 +121,6 @@ bool Mat4::operator==(const Mat4& rhs) const
     data_[3][3] ==  rhs.data_[3][3];
 }
 
-Real& Mat4::operator()(std::size_t r, std::size_t c)
-{
-  if(r>3 || c>3) throw std::out_of_range("row and column must be in range [0-3]");
-  return data_[r][c];
-}
-
-const Real& Mat4::operator()(std::size_t r, std::size_t c) const
-{
-  if(r>3 || c>3) throw std::out_of_range("row and column must be in range [0-3]");
-  return data_[r][c];
-}
 
 
 Mat4& Mat4::operator+=(const Mat4& rhs)
diff --git a/modules/geom/src/mat4.hh b/modules/geom/src/mat4.hh
index 0c504a5710d95a411e90555d3d01d9d1c029d176..998bbc485fe885d0f3734ef543dc4dec724d0a2c 100644
--- a/modules/geom/src/mat4.hh
+++ b/modules/geom/src/mat4.hh
@@ -19,6 +19,7 @@
 #ifndef GEOM_MAT4_HH
 #define GEOM_MAT4_HH
 
+#include <cassert>
 #include <cstddef> // for size_t
 #include <ostream>
 
@@ -77,10 +78,33 @@ public:
   //! comparable
   bool operator==(const Mat4& rhs) const;
 
-  //! element access
-  Real& operator()(std::size_t r, std::size_t c);
-  //! const element access
-  const Real& operator()(std::size_t r, std::size_t c) const;
+  const Real& At(std::size_t r, std::size_t c) const
+  {
+    if (r>3 || c>3) {
+      throw std::out_of_range("indices must be smaller than 4");
+    }
+    return data_[r][c];
+  }
+
+  Real& At(std::size_t r, std::size_t c)
+  {
+    if (r>3 || c>3) {
+      throw std::out_of_range("indices must be smaller than 4");
+    }
+    return data_[r][c];
+  }
+
+  Real& operator()(std::size_t r, std::size_t c)
+  {
+    assert(r<4 && c < 4);
+    return data_[r][c];
+  }
+
+  const Real& operator()(std::size_t r, std::size_t c) const
+  {
+    assert(r<4 && c < 4);
+    return data_[r][c];
+  }
 
   //! addable op
   Mat4& operator+=(const Mat4& rhs);
diff --git a/modules/geom/src/vec2.hh b/modules/geom/src/vec2.hh
index 6978381ff33734f35ff5f8a2d2c5ab4ace8bd72b..b0191ac7f4be32ef99592e46f91f02288bcffae3 100644
--- a/modules/geom/src/vec2.hh
+++ b/modules/geom/src/vec2.hh
@@ -20,6 +20,7 @@
 #define GEOM_VEC2_H
 
 #include <stdexcept>
+#include <cassert>
 #include <cstddef> // for size_t
 #include <ostream>
 #include <vector>
@@ -83,17 +84,27 @@ public:
   //! element access
   Real& operator[](std::size_t indx)
   {
-    if (indx>1) {
-      throw std::out_of_range("Index must be in the range [0-1]");
-    }
+    assert(indx<2);
     return (&x)[indx];
   }
   
   //! const element access
   const Real& operator[](std::size_t indx) const
   {
+    assert(indx<2);
+    return (&x)[indx];
+  }
+
+  Real& At(size_t indx) {
+    if (indx>1) {
+      throw std::out_of_range("index must be smaller than 2");
+    }
+    return (&x)[indx];
+  }
+
+  const Real& At(size_t indx) const {
     if (indx>1) {
-      throw std::out_of_range("Index must be in the range [0-1]");
+      throw std::out_of_range("index must be smaller than 2");
     }
     return (&x)[indx];
   }
diff --git a/modules/geom/src/vec3.hh b/modules/geom/src/vec3.hh
index c1cde046c0174c7571701ca6ee82e9645ccc41c8..b585d4a76e5e8ba29e618794338e888deca3584f 100644
--- a/modules/geom/src/vec3.hh
+++ b/modules/geom/src/vec3.hh
@@ -20,6 +20,7 @@
 #define GEOM_VEC3_H
 
 #include <stdexcept>
+#include <cassert>
 #include <cstddef> // for size_t
 #include <ostream>
 #include <vector>
@@ -90,17 +91,27 @@ public:
   //! element access
   Real& operator[](std::size_t indx)
   {
-    if (indx>2) {
-      throw std::out_of_range("Index must be in the range [0-2]");
-    }
+    assert(indx<3);
     return (&x)[indx];
   }
   
   //! const element access
   const Real& operator[](std::size_t indx) const
   {
+    assert(indx<3);
+    return (&x)[indx];
+  }
+
+  Real& At(size_t indx) {
+    if (indx>2) {
+      throw std::out_of_range("index must be smaller than 3");
+    }
+    return (&x)[indx];
+  }
+
+  const Real& At(size_t indx) const {
     if (indx>2) {
-      throw std::out_of_range("Index must be in the range [0-2]");
+      throw std::out_of_range("index must be smaller than 3");
     }
     return (&x)[indx];
   }
diff --git a/modules/geom/src/vec4.hh b/modules/geom/src/vec4.hh
index 20b5fd2a748e6d5e9677eea7c7b0d65da1af4aed..5947a1c06a1d18c898c0ff08a4ff84e364d5e451 100644
--- a/modules/geom/src/vec4.hh
+++ b/modules/geom/src/vec4.hh
@@ -20,6 +20,7 @@
 #define GEOM_VEC4_H
 
 #include <stdexcept>
+#include <cassert>
 #include <cstddef> // for size_t
 #include <ostream>
 
@@ -83,20 +84,31 @@ public:
   //! element access
   Real& operator[](std::size_t indx)
   {
-    if (indx>3) {
-      throw std::out_of_range("Index must be in the range [0-3]");
-    }
+    assert(indx<4);
     return (&x)[indx];
   }
   
   //! const element access
   const Real& operator[](std::size_t indx) const
   {
+    assert(indx<4);
+    return (&x)[indx];
+  }
+
+  Real& At(size_t indx) {
     if (indx>3) {
-      throw std::out_of_range("Index must be in the range [0-3]");
+      throw std::out_of_range("index must be smaller than 4");
     }
     return (&x)[indx];
   }
+
+  const Real& At(size_t indx) const {
+    if (indx>3) {
+      throw std::out_of_range("index must be smaller than 4");
+    }
+    return (&x)[indx];
+  }
+
   //! element access
   Real GetX() const { return x; }
   Real GetY() const { return y; }
diff --git a/modules/geom/src/vecmat2_op.cc b/modules/geom/src/vecmat2_op.cc
index ea0a4521376d510ccc9db2a0471fe275bd9833cd..221a6bbf2a4401da31dd118d04c86f4e0ca9723e 100644
--- a/modules/geom/src/vecmat2_op.cc
+++ b/modules/geom/src/vecmat2_op.cc
@@ -50,7 +50,7 @@ Mat2 Invert(const Mat2& m)
 
 Real Angle(const Vec2& v1, const Vec2& v2)
 {
-  return std::acos(Dot(v1,v2)/Length(v1)/Length(v2));
+  return std::acos(std::max(static_cast<Real>(-1.0),std::min(static_cast<Real>(1.0),Dot(v1,v2)/Length(v1)/Length(v2))));
 }
 
 Real SignedAngle(const Vec2& v1, const Vec2& v2)
@@ -63,7 +63,7 @@ Real SignedAngle(const Vec2& v1, const Vec2& v2)
   if(vc.z!=0.0){
     sign=vc.z/std::fabs(vc.z);
   }
-  return acos(Dot(v1,v2)/Length(v1)/Length(v2))*sign;
+  return acos(std::max(static_cast<Real>(-1.0),std::min(static_cast<Real>(1.0),Dot(v1,v2)/Length(v1)/Length(v2))))*sign;
 }
 
 Vec2 Rotate(const Vec2& v,Real ang)
diff --git a/modules/geom/src/vecmat3_op.hh b/modules/geom/src/vecmat3_op.hh
index 49d466081cb45b913dfb9b6ae2638f9a84030dcd..e13c2f07657c1c1489436b21f80b6e16b7e2a139 100644
--- a/modules/geom/src/vecmat3_op.hh
+++ b/modules/geom/src/vecmat3_op.hh
@@ -211,15 +211,15 @@ inline Real DistanceWithPBC(const Vec3& v1, const Vec3& v2, const Vec3& basis_ve
   return sqrt(Distance2WithPBC(v1, v2, basis_vec));
 }
 //! returns the minimal distance between the points in two Vec3List
-DLLEXPORT_OST_GEOM Real MinDistance(const Vec3List& l1, const Vec3List& l2);
+Real DLLEXPORT_OST_GEOM MinDistance(const Vec3List& l1, const Vec3List& l2);
 //! returns the minimal distance between the points in two Vec3List 
 //  with periodic boundaries in x,y,z given in basis_vec
-DLLEXPORT_OST_GEOM Real MinDistanceWithPBC(const Vec3List& l1, const Vec3List& l2, Vec3& basis_vec);
+Real DLLEXPORT_OST_GEOM MinDistanceWithPBC(const Vec3List& l1, const Vec3List& l2, Vec3& basis_vec);
 
 //!wraps a vector in a box with periodic boundaries
-DLLEXPORT_OST_GEOM Vec3 WrapVec3(const Vec3& v1,const Vec3& box_center,const Vec3& basis_vec);
-//!wraps all the vectors in a Vec3List in a box with periodic boundaries
-DLLEXPORT_OST_GEOM Vec3List WrapVec3List(const Vec3List& vl,const Vec3& box_center,const Vec3& basis_vec);
+Vec3 DLLEXPORT_OST_GEOM WrapVec3(const Vec3& v1,const Vec3& box_center,const Vec3& basis_vec);
+//!wraps all the verctors in a Vec3List in a box with periodic boundaries
+Vec3List DLLEXPORT_OST_GEOM WrapVec3List(const Vec3List& vl,const Vec3& box_center,const Vec3& basis_vec);
 
   
 } // ns
diff --git a/modules/geom/tests/test_composite2.cc b/modules/geom/tests/test_composite2.cc
index acec86fb900f5b32460c1cfb4fdb85855474b9be..612d73b0a13b3ef27f6ad86b88e0ffbcc72c6b0f 100644
--- a/modules/geom/tests/test_composite2.cc
+++ b/modules/geom/tests/test_composite2.cc
@@ -20,12 +20,12 @@
 
 #include <ost/geom/geom.hh>
 
-#include "helper.hh"
 
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 #include <boost/test/auto_unit_test.hpp>
 
+#include "helper.hh"
 using namespace geom;
 
 BOOST_AUTO_TEST_SUITE( geom );
diff --git a/modules/geom/tests/test_composite3.cc b/modules/geom/tests/test_composite3.cc
index 317068280dd1a761c288e88b2a45e53089929547..a9fb6ea4d6bf4038c91450ac4b74f6edec35b8b8 100644
--- a/modules/geom/tests/test_composite3.cc
+++ b/modules/geom/tests/test_composite3.cc
@@ -20,14 +20,15 @@
 #include <cmath>
 #include <ost/geom/geom.hh>
 
-#include "helper.hh"
-using namespace geom;
 
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 #include <boost/test/auto_unit_test.hpp>
 #include <boost/test/floating_point_comparison.hpp>
 
+#include "helper.hh"
+using namespace geom;
+
 BOOST_AUTO_TEST_SUITE( geom );
 
 BOOST_AUTO_TEST_CASE(init_composite3)
diff --git a/modules/geom/tests/test_geom.py b/modules/geom/tests/test_geom.py
index f563add91955b88fcc383b714df2f472a1a9b64e..60a989ac42e19ad9e237f6560947ffdc5389d63c 100644
--- a/modules/geom/tests/test_geom.py
+++ b/modules/geom/tests/test_geom.py
@@ -78,7 +78,104 @@ class TestGeom(unittest.TestCase):
                       5,6,7,8,
                       9,10,11,12,
                       13,14,15,16])
-    
+
+  def test_boundary_checks_vec2(self): 
+    v = geom.Vec2()
+
+    v[0] = v[0]
+    v[1] = v[1]
+    self.assertRaises(IndexError, v.__setitem__, (-1), 1)
+    self.assertRaises(IndexError, v.__setitem__, ( 2), 1)
+    self.assertRaises(IndexError, v.__getitem__, (-1))
+    self.assertRaises(IndexError, v.__getitem__, ( 2))
+
+  def test_boundary_checks_vec3(self): 
+    v = geom.Vec3()
+
+    v[0] = v[0]
+    v[1] = v[1]
+    v[2] = v[2]
+    self.assertRaises(IndexError, v.__setitem__, (-1), 1)
+    self.assertRaises(IndexError, v.__setitem__, ( 3), 1)
+    self.assertRaises(IndexError, v.__getitem__, (-1))
+    self.assertRaises(IndexError, v.__getitem__, ( 3))
+
+  def test_boundary_checks_vec4(self): 
+    v = geom.Vec4()
+    v[0] = v[0]
+    v[1] = v[1]
+    v[2] = v[2]
+    v[3] = v[3]
+    self.assertRaises(IndexError, v.__setitem__, (-1), 1)
+    self.assertRaises(IndexError, v.__setitem__, ( 4), 1)
+    self.assertRaises(IndexError, v.__getitem__, (-1))
+    self.assertRaises(IndexError, v.__getitem__, ( 4))
+
+  def test_boundary_checks_mat2(self): 
+    m = geom.Mat2()
+    m[0,0] = m[0,0]
+    m[0,1] = m[0,1]
+    m[1,0] = m[1,0]
+    m[1,1] = m[1,1]
+    self.assertRaises(IndexError, m.__setitem__, (-1,0), 1)
+    self.assertRaises(IndexError, m.__setitem__, ( 2,0), 1)
+    self.assertRaises(IndexError, m.__setitem__, (0,-1), 1)
+    self.assertRaises(IndexError, m.__setitem__, (-1,2), 1)
+
+    self.assertRaises(IndexError, m.__getitem__, (-1,0))
+    self.assertRaises(IndexError, m.__getitem__, ( 2,0))
+    self.assertRaises(IndexError, m.__getitem__, (0,-1))
+    self.assertRaises(IndexError, m.__getitem__, (0,2))
+
+  def test_boundary_checks_mat3(self): 
+    m = geom.Mat3()
+    m[0,0] = m[0,0]
+    m[0,1] = m[0,1]
+    m[0,2] = m[0,2]
+    m[1,0] = m[1,0]
+    m[1,1] = m[1,1]
+    m[1,2] = m[1,2]
+    m[2,0] = m[2,0]
+    m[2,1] = m[2,1]
+    m[2,2] = m[2,2]
+    self.assertRaises(IndexError, m.__setitem__, (-1,0), 1)
+    self.assertRaises(IndexError, m.__setitem__, ( 3,0), 1)
+    self.assertRaises(IndexError, m.__setitem__, (0,-1), 1)
+    self.assertRaises(IndexError, m.__setitem__, (-1,3), 1)
+
+    self.assertRaises(IndexError, m.__getitem__, (-1,0))
+    self.assertRaises(IndexError, m.__getitem__, ( 3,0))
+    self.assertRaises(IndexError, m.__getitem__, (0,-1))
+    self.assertRaises(IndexError, m.__getitem__, (0,3))
+
+  def test_boundary_checks_mat4(self): 
+    m = geom.Mat4()
+    m[0,0] = m[0,0]
+    m[0,1] = m[0,1]
+    m[0,2] = m[0,2]
+    m[0,3] = m[0,3]
+    m[1,0] = m[1,0]
+    m[1,1] = m[1,1]
+    m[1,2] = m[1,2]
+    m[1,3] = m[1,3]
+    m[2,0] = m[2,0]
+    m[2,1] = m[2,1]
+    m[2,2] = m[2,2]
+    m[2,3] = m[2,3]
+    m[3,0] = m[3,0]
+    m[3,1] = m[3,1]
+    m[3,2] = m[3,2]
+    m[3,3] = m[3,3]
+    self.assertRaises(IndexError, m.__setitem__, (-1,0), 1)
+    self.assertRaises(IndexError, m.__setitem__, ( 4,0), 1)
+    self.assertRaises(IndexError, m.__setitem__, (0,-1), 1)
+    self.assertRaises(IndexError, m.__setitem__, (-1,4), 1)
+
+    self.assertRaises(IndexError, m.__getitem__, (-1,0))
+    self.assertRaises(IndexError, m.__getitem__, ( 4,0))
+    self.assertRaises(IndexError, m.__getitem__, (0,-1))
+    self.assertRaises(IndexError, m.__getitem__, (0,4))
+
 if __name__== '__main__':
   from ost import testutils
   testutils.RunTests()
diff --git a/modules/geom/tests/test_mat2.cc b/modules/geom/tests/test_mat2.cc
index c7da1125e3edef8c78e4f1304f535199be6618cd..c0f2e429f130a93186f9114e7275b5be9bbd3f23 100644
--- a/modules/geom/tests/test_mat2.cc
+++ b/modules/geom/tests/test_mat2.cc
@@ -19,13 +19,13 @@
 
 #include <ost/geom/geom.hh>
 
-#include "helper.hh"
-using namespace geom;
-
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 #include <boost/test/auto_unit_test.hpp>
 
+#include "helper.hh"
+using namespace geom;
+
 BOOST_AUTO_TEST_SUITE( geom );
 
 
@@ -53,13 +53,4 @@ BOOST_AUTO_TEST_CASE(init_mat2)
   BOOST_CHECK(match(m1,m4(0,0),m4(0,1),m4(1,0),m4(1,1)));
 }
 
-
-
-BOOST_AUTO_TEST_CASE(access_mat2)
-{
-  Mat2 m;
-  BOOST_CHECK_THROW( m(2,2)=1.0, std::out_of_range);
-  BOOST_CHECK_THROW( m(2,2), std::out_of_range);
-}
-
 BOOST_AUTO_TEST_SUITE_END();
diff --git a/modules/geom/tests/test_mat3.cc b/modules/geom/tests/test_mat3.cc
index 8a8b40e53c7749832c8143379950a6ee66cc9670..7481e519e4bbf2d8b9c26943521fd73044a24bdd 100644
--- a/modules/geom/tests/test_mat3.cc
+++ b/modules/geom/tests/test_mat3.cc
@@ -19,13 +19,13 @@
 
 #include <ost/geom/geom.hh>
 
-#include "helper.hh"
-using namespace geom;
-
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 #include <boost/test/auto_unit_test.hpp>
 
+#include "helper.hh"
+using namespace geom;
+
 BOOST_AUTO_TEST_SUITE( geom );
 
 BOOST_AUTO_TEST_CASE(init_mat3)
@@ -55,18 +55,6 @@ BOOST_AUTO_TEST_CASE(init_mat3)
   BOOST_CHECK(match(m5,2.0,3.0,0.0,4.0,5.0,0.0,0.0,0.0,1.0));
 }
 
-BOOST_AUTO_TEST_CASE(access_mat3)
-{
-  Mat3 m;
-  BOOST_CHECK_THROW( m(3,3)=1.0, std::out_of_range);
-  BOOST_CHECK_THROW( m(3,0)=1.0, std::out_of_range);
-  BOOST_CHECK_THROW( m(0,3)=1.0, std::out_of_range);
-  BOOST_CHECK_THROW( m(3,3), std::out_of_range);
-  BOOST_CHECK_THROW( m(3,0), std::out_of_range);
-  BOOST_CHECK_THROW( m(0,3), std::out_of_range);
-}
-
-
 BOOST_AUTO_TEST_CASE(mult_mat3)
 {
   Mat3 m1=rnd_mat3();
diff --git a/modules/geom/tests/test_mat4.cc b/modules/geom/tests/test_mat4.cc
index 36ea668c19a2ffa7483a98bc1a2c697afc57bc8e..64c0eff7a9efa0f9d2b06ca920f793ad9fa0e433 100644
--- a/modules/geom/tests/test_mat4.cc
+++ b/modules/geom/tests/test_mat4.cc
@@ -19,13 +19,13 @@
 
 #include <ost/geom/geom.hh>
 
-#include "helper.hh"
-using namespace geom;
-
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 #include <boost/test/auto_unit_test.hpp>
 
+#include "helper.hh"
+using namespace geom;
+
 BOOST_AUTO_TEST_SUITE( geom );
 
 BOOST_AUTO_TEST_CASE(init_mat4)
@@ -91,15 +91,4 @@ BOOST_AUTO_TEST_CASE(init_mat4)
         
 }
 
-BOOST_AUTO_TEST_CASE(access_mat4)
-{
-  Mat4 m;
-  BOOST_CHECK_THROW( m(4,4)=1.0, std::out_of_range);
-  BOOST_CHECK_THROW( m(4,0)=1.0, std::out_of_range);
-  BOOST_CHECK_THROW( m(0,4)=1.0, std::out_of_range);
-  BOOST_CHECK_THROW( m(4,4), std::out_of_range);
-  BOOST_CHECK_THROW( m(4,0), std::out_of_range);
-  BOOST_CHECK_THROW( m(0,4), std::out_of_range);
-}
-
 BOOST_AUTO_TEST_SUITE_END();
diff --git a/modules/geom/tests/test_op2.cc b/modules/geom/tests/test_op2.cc
index 2815b3e65d3e99d74ea6ee780c240bd552ab1d25..fd52c6f3b32cb9d50ab370be1c99cf670e7dc78b 100644
--- a/modules/geom/tests/test_op2.cc
+++ b/modules/geom/tests/test_op2.cc
@@ -19,13 +19,13 @@
 
 #include <ost/geom/geom.hh>
 
-#include "helper.hh"
-using namespace geom;
-
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 #include <boost/test/auto_unit_test.hpp>
 
+#include "helper.hh"
+using namespace geom;
+
 BOOST_AUTO_TEST_SUITE( geom );
 
 BOOST_AUTO_TEST_CASE(vecmat_mult2)
diff --git a/modules/geom/tests/test_op3.cc b/modules/geom/tests/test_op3.cc
index 1d4660b4e8cf92d2f6506bd900bad16aaf480dec..b37013a8c096bc5d2c90566f36ee9c26fa926377 100644
--- a/modules/geom/tests/test_op3.cc
+++ b/modules/geom/tests/test_op3.cc
@@ -19,13 +19,14 @@
 
 #include <ost/geom/geom.hh>
 
-#include "helper.hh"
-using namespace geom;
-
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 #include <boost/test/auto_unit_test.hpp>
 
+#include "helper.hh"
+using namespace geom;
+
+
 BOOST_AUTO_TEST_SUITE( geom );
 
 BOOST_AUTO_TEST_CASE(vecmat_mult3)
diff --git a/modules/geom/tests/test_op4.cc b/modules/geom/tests/test_op4.cc
index df5995eca4b06298cd400111b6a4b46b952d9ee0..b9c4beeedfaa2e8e91693dbd86fbb17788a592d9 100644
--- a/modules/geom/tests/test_op4.cc
+++ b/modules/geom/tests/test_op4.cc
@@ -19,13 +19,14 @@
 
 #include <ost/geom/geom.hh>
 
-#include "helper.hh"
-using namespace geom;
-
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 #include <boost/test/auto_unit_test.hpp>
 
+
+#include "helper.hh"
+using namespace geom;
+
 BOOST_AUTO_TEST_SUITE( geom );
 
 BOOST_AUTO_TEST_CASE(vecmat_mult4)
diff --git a/modules/geom/tests/test_quat.cc b/modules/geom/tests/test_quat.cc
index cfd36460be4d09487e15000f2579cfdb78ed8697..54b8cea33e8ae65206d96dfcf35af88e43f19082 100644
--- a/modules/geom/tests/test_quat.cc
+++ b/modules/geom/tests/test_quat.cc
@@ -19,14 +19,15 @@
 
 #include <ost/geom/geom.hh>
 
-#include "helper.hh"
-using namespace geom;
-
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 #include <boost/test/auto_unit_test.hpp>
 #include <boost/test/floating_point_comparison.hpp>
 
+#include "helper.hh"
+using namespace geom;
+
+
 BOOST_AUTO_TEST_SUITE( geom );
 
 BOOST_AUTO_TEST_CASE(init_quat)
diff --git a/modules/geom/tests/test_vec2.cc b/modules/geom/tests/test_vec2.cc
index 87cc3aba086dbd08cd72409859175713cbf81616..c7cb014de5378c0da4745ad327c260d48fe9c592 100644
--- a/modules/geom/tests/test_vec2.cc
+++ b/modules/geom/tests/test_vec2.cc
@@ -19,13 +19,13 @@
 
 #include <ost/geom/geom.hh>
 
-#include "helper.hh"
-using namespace geom;
-
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 #include <boost/test/auto_unit_test.hpp>
 
+#include "helper.hh"
+using namespace geom;
+
 BOOST_AUTO_TEST_SUITE( geom );
   
 BOOST_AUTO_TEST_CASE(init_vec2)
@@ -61,16 +61,6 @@ BOOST_AUTO_TEST_CASE(init_vec2)
   BOOST_CHECK_THROW( Vec2(Vec4(1.0,1.0,1.0,0.0)), DivideByZeroException);
 }
 
-BOOST_AUTO_TEST_CASE(access_vec2)
-{
-  Vec2 v;
-  v[0]=1.1;
-  v[1]=2.3;
-  BOOST_CHECK(match(v,1.1,2.3));
-  BOOST_CHECK_NO_THROW( v[0]=1.0);
-  BOOST_CHECK_THROW( v[2]=1.0, std::out_of_range);
-}
-
 BOOST_AUTO_TEST_CASE(operators_vec2)
 {
   Vec2 v1(1.2,2.3);
diff --git a/modules/geom/tests/test_vec3.cc b/modules/geom/tests/test_vec3.cc
index 3964daf007ade2efcb4db4b0d97547761135fbd5..9b2a4cc8bb9919c1cee60581a11312ed8e76da57 100644
--- a/modules/geom/tests/test_vec3.cc
+++ b/modules/geom/tests/test_vec3.cc
@@ -19,13 +19,14 @@
 
 #include <ost/geom/geom.hh>
 
-#include "helper.hh"
-using namespace geom;
-
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 #include <boost/test/auto_unit_test.hpp>
 
+#include "helper.hh"
+using namespace geom;
+
+
 BOOST_AUTO_TEST_SUITE( geom );
   
 BOOST_AUTO_TEST_CASE(init_vec3)
@@ -62,23 +63,6 @@ BOOST_AUTO_TEST_CASE(init_vec3)
   BOOST_CHECK(match(Vec3(Vec4(2.0,1.0,3.0,0.0)),2.0,1.0,3.0));
 }
 
-BOOST_AUTO_TEST_CASE(access_vec3)
-{
-  Vec3 v;
-  v[0]=1.1;
-  v[1]=2.3;
-  v[2]=5.6;
-  BOOST_CHECK(match(v,1.1,2.3,5.6));
-
-  BOOST_CHECK_NO_THROW(v[0]=1);
-  BOOST_CHECK_NO_THROW(v[1]=1);
-  BOOST_CHECK_NO_THROW(v[2]=1);
-  BOOST_CHECK_NO_THROW(v[0]);
-  BOOST_CHECK_NO_THROW(v[1]);
-  BOOST_CHECK_NO_THROW(v[2]);
-  BOOST_CHECK_THROW( v[3]=1.0, std::out_of_range);
-  BOOST_CHECK_THROW( v[3], std::out_of_range);
-}
 
 BOOST_AUTO_TEST_CASE(operators_vec3) 
 {
diff --git a/modules/geom/tests/test_vec4.cc b/modules/geom/tests/test_vec4.cc
index 25276e4f33e55055ce3a75383e724bbb8f4ab8ee..f39988a41eef50063a77810c0e8ff5b08f785915 100644
--- a/modules/geom/tests/test_vec4.cc
+++ b/modules/geom/tests/test_vec4.cc
@@ -19,13 +19,14 @@
 
 #include <ost/geom/geom.hh>
 
-#include "helper.hh"
-using namespace geom;
 
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 #include <boost/test/auto_unit_test.hpp>
 
+#include "helper.hh"
+using namespace geom;
+
 BOOST_AUTO_TEST_SUITE( geom );
 
 BOOST_AUTO_TEST_CASE(init_vec4)
@@ -61,18 +62,6 @@ BOOST_AUTO_TEST_CASE(init_vec4)
 }
 
 
-BOOST_AUTO_TEST_CASE(access_vec4)
-{
-  Vec4 v;
-  v[0]=1.1;
-  v[1]=2.3;
-  v[2]=5.6;
-  v[3]=2.0;
-  BOOST_CHECK(match(v,1.1,2.3,5.6,2.0));
-
-  BOOST_CHECK_THROW( v[4]=1.0, std::out_of_range);
-}
-
 BOOST_AUTO_TEST_CASE(operators_vec4)
 {
   Vec4 v1(0.8,1.2,2.3,3.4);
diff --git a/modules/gfx/pymod/__init__.py b/modules/gfx/pymod/__init__.py
index bd5750d32178c50d2ce7758af2a053dd2ea4c0f1..7cb3cc51452eca9c2a1507b9e7b692e591ba2aa1 100644
--- a/modules/gfx/pymod/__init__.py
+++ b/modules/gfx/pymod/__init__.py
@@ -329,3 +329,81 @@ def _entity_reset(self,*args,**kwargs):
     self._reset3(eh,qr,qf)
 
 Entity.Reset=_entity_reset
+
+def _scene_export(self,*args,**kwargs):
+  """
+  scene.Export(Exporter)
+  scene.Export("file.png")
+  scene.Export("file.png",(width,height),samples=0,transparency=False)
+  deprecated:
+  scene.Export("file.png",width,height,samples=0,transparency=False)
+  scene.Export("file.png",width,height,transparency) 
+  """
+  scene=Scene()
+  tp=False
+  sa=0
+  if "tp" in kwargs:
+    tp=int(kwargs["tp"])
+  if "transparency" in kwargs:
+    tp=int(kwargs["transparency"])
+  if "samples" in kwargs:
+    sa=int(kwargs["samples"])
+
+  if len(args)==1:
+    if isinstance(args[0],Exporter):
+      scene._export_via_exporter(args[0])
+      return
+    elif type(args[0])==type(""):
+      scene._export_screen(args[0],tp)
+      return
+  elif len(args)==2:
+    if type(args[0]==type("")):
+      # assume second argument is a dimension
+      width=int(args[1][0])
+      height=int(args[1][1])
+      scene._export_buffer(args[0],width,height,sa,tp)
+      return
+  elif len(args)==3:
+    if type(args[0]==type("")):
+      width=int(args[1])
+      height=int(args[2])
+      scene._export_buffer(args[0],width,height,sa,tp)
+      return
+  elif len(args)==4:
+    if type(args[0]==type("")):
+      width=int(args[1])
+      height=int(args[2])
+      tp=int(args[3])
+      scene._export_buffer(args[0],width,height,sa,tp)
+      return
+  # getting here indicates an error
+  raise RuntimeError("""invalid arguments to scene.Export; expected one of
+  Export(gfx.Exporter)
+  Export('file.png')
+  Export('file.png',(width,height),samples=0, transparency=False)
+  Export('file.png',width,height,samples=0, transparency=False) -> deprecated
+  Export('file.png',width,height,transparency) -> deprecated
+  """)
+
+SceneSingleton.Export=_scene_export
+
+import __main__ as main_mod
+main_mod.scene=Scene()
+main_mod.scene.Stereo=Stereo
+
+import ost as ost_mod
+ost_mod.scene=Scene()
+ost_mod.scene.Stereo=Stereo
+
+def GostExporter(file,scale=1.0,to_origin=True):
+  e=GostExporter_(file)
+  e.scale=scale
+  e.to_origin=to_origin
+  return e
+
+def ColladaExporter(file,scale=1.0,to_origin=True):
+  e=ColladaExporter_(file)
+  e.scale=scale
+  e.to_origin=to_origin
+  return e
+
diff --git a/modules/gfx/pymod/export_exporter.cc b/modules/gfx/pymod/export_exporter.cc
index 655fe54f77282e2d6656142addf51e18006d7f7c..22c9a97432477c8f8c47b4ba6fd7d2cfac58451d 100644
--- a/modules/gfx/pymod/export_exporter.cc
+++ b/modules/gfx/pymod/export_exporter.cc
@@ -28,11 +28,16 @@ using namespace ost::gfx;
 
 void export_Exporter()
 {
-  class_<Exporter, boost::noncopyable>("Exporter", no_init);
+  class_<Exporter, boost::noncopyable>("Exporter", no_init)
+    .add_property("scale",&Exporter::GetScale,&Exporter::SetScale)
+    .add_property("to_origin",&Exporter::GetToOrigin,&Exporter::SetToOrigin)
+  ;
 
-  class_<GostExporter, bases<Exporter>, boost::noncopyable>("GostExporter", init<const std::string&>())
+  // internal class, factory function in __init__.py
+  class_<GostExporter, bases<Exporter>, boost::noncopyable>("GostExporter_", init<const std::string&>())
     ;
 
-  class_<ColladaExporter, bases<Exporter>, boost::noncopyable>("ColladaExporter", init<const std::string&, optional<float> >())
+  // internal class, factory function in __init__.py
+  class_<ColladaExporter, bases<Exporter>, boost::noncopyable>("ColladaExporter_", init<const std::string&>())
     ;
 }
diff --git a/modules/gfx/pymod/export_gfx_obj.cc b/modules/gfx/pymod/export_gfx_obj.cc
index 07d845636676fbd2c381ee1bbab25a4bf8aa0ca4..68e88f90169ae1c1f190a3b778da26d0f63160a1 100644
--- a/modules/gfx/pymod/export_gfx_obj.cc
+++ b/modules/gfx/pymod/export_gfx_obj.cc
@@ -157,6 +157,9 @@ void export_GfxObj()
     .add_property("opacity",&GfxObjBase::GetOpacity,&GfxObjBase::SetOpacity)
     .add_property("solid",&GfxObjBase::GetSolid,&GfxObjBase::SetSolid)
     .add_property("solid_color",&GfxObjBase::GetSolidColor,&GfxObjBase::SetSolidColor)
+    .add_property("clip",&GfxObjBase::GetClip,&GfxObjBase::SetClip)
+    .add_property("clip_plane",&GfxObjBase::GetClipPlane,&GfxObjBase::SetClipPlane)
+    .add_property("clip_offset",&GfxObjBase::GetClipOffset,&GfxObjBase::SetClipOffset)
     COLOR_BY_DEF()
    ;
 
diff --git a/modules/gfx/pymod/export_scene.cc b/modules/gfx/pymod/export_scene.cc
index 9f3042cb2d7328097691db1d338744d680d0946c..59098ea93c962890101edd9598b2618e9fb9aba0 100644
--- a/modules/gfx/pymod/export_scene.cc
+++ b/modules/gfx/pymod/export_scene.cc
@@ -82,14 +82,15 @@ void export_Scene()
   void (Scene::* set_light_prop1)(const Color&,const Color&,const Color&) = &Scene::SetLightProp;
   void (Scene::* set_light_prop2)(float,float,float) = &Scene::SetLightProp;
 
-  void (Scene::* export1)(const String&, uint, uint, bool) = &Scene::Export;
-  void (Scene::* export2)(const String&, bool) = &Scene::Export;
-  void (Scene::* export3)(Exporter*) const = &Scene::Export;
+  void (Scene::* export_buffer)(const String&, uint, uint, int, bool) = &Scene::Export;
+  void (Scene::* export_screen)(const String&, bool) = &Scene::Export;
+  void (Scene::* export_via_exporter)(Exporter*) const = &Scene::Export;
   void (Scene::*remove1)(const GfxNodeP&) = &Scene::Remove;
   void (Scene::*remove2)(const String&) = &Scene::Remove;
   void (Scene::*center_on1)(const String&) = &Scene::CenterOn;
   void (Scene::*center_on2)(const GfxObjP&) = &Scene::CenterOn;
-  
+  bool (Scene::*start_offscreen_mode1)(unsigned int, unsigned int) = &Scene::StartOffscreenMode;  
+  bool (Scene::*start_offscreen_mode2)(unsigned int, unsigned int, int) = &Scene::StartOffscreenMode;  
   class_<Viewport>("Viewport", init<>())
     .def_readwrite("x", &Viewport::x)
     .def_readwrite("y", &Viewport::y)
@@ -195,9 +196,9 @@ void export_Scene()
     .def("SetLightProp",set_light_prop1)
     .def("SetLightProp",set_light_prop2)
     .def("Apply", apply)
-    .def("Export",export1, arg("transparent")=false)
-    .def("Export",export2, arg("transparent")=false)
-    .def("Export",export3)
+    .def("_export_screen",export_screen)
+    .def("_export_buffer",export_buffer)
+    .def("_export_via_exporter",export_via_exporter)
     .def("ExportPov",&Scene::ExportPov,
          scene_export_pov_overloads())
     .def("PushView",&Scene::PushView)
@@ -227,7 +228,8 @@ void export_Scene()
     .add_property("ao_quality",&Scene::GetAmbientOcclusionQuality,&Scene::SetAmbientOcclusionQuality)
     .add_property("ao_size",&Scene::GetAmbientOcclusionSize,&Scene::SetAmbientOcclusionSize)
     .def("AttachObserver",&Scene::AttachObserver)
-    .def("StartOffscreenMode",&Scene::StartOffscreenMode)
+    .def("StartOffscreenMode",start_offscreen_mode1)
+    .def("StartOffscreenMode",start_offscreen_mode2)
     .def("StopOffscreenMode",&Scene::StopOffscreenMode)
     .def("SetShadingMode",&Scene::SetShadingMode)
     .def("SetBeacon",&Scene::SetBeacon)
diff --git a/modules/gfx/src/CMakeLists.txt b/modules/gfx/src/CMakeLists.txt
index 57cf1601f715667068611be5abaa0559efaf7165..bb60b35f1081586e5b3bbe65137b2e7a51dc181d 100644
--- a/modules/gfx/src/CMakeLists.txt
+++ b/modules/gfx/src/CMakeLists.txt
@@ -94,6 +94,7 @@ endif()
 
 set(OST_GFX_SOURCES
 bitmap_io.cc
+exporter.cc
 collada_exporter.cc
 color.cc
 primitives.cc
@@ -268,6 +269,7 @@ if (USE_SHADER)
     shader/material_hemi.glsl
     shader/material_toon1.glsl
     shader/material_toon2.glsl
+    shader/anaglyph_fs.glsl
   )
   copy_if_different("${CMAKE_CURRENT_SOURCE_DIR}" "${SHARED_DATA_PATH}/shader" "${SHADER_FILES}" 
                     "SHADER_TARGETS" ost_gfx)  
diff --git a/modules/gfx/src/collada_exporter.cc b/modules/gfx/src/collada_exporter.cc
index 902334f851fc0df651f58f380e3c3771e8ae1e96..d2b45c21e76db54c311f10ff1e8c7389049151b6 100644
--- a/modules/gfx/src/collada_exporter.cc
+++ b/modules/gfx/src/collada_exporter.cc
@@ -29,10 +29,10 @@
 
 namespace ost { namespace gfx {
 
-ColladaExporter::ColladaExporter(const std::string& file, float scale):
+ColladaExporter::ColladaExporter(const std::string& file):
+  Exporter(),
   file_(file),
   out_(file_.c_str()),
-  scale_(scale),
   obj_()
 {
   out_ << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
@@ -75,13 +75,23 @@ void ColladaExporter::SceneEnd(const Scene* scene)
   out_ << "   </node>\n";
 
   out_ << "   <node id=\"Root\" name=\"Root\">\n";
-  out_ << "    <matrix>\n";
-  geom::Mat4 tm=scene->GetTransform().GetMatrix();
-  out_ << "    " << tm(0,0) << " " << tm(0,1) << " " << tm(0,2) << " " << tm(0,3) << "\n";
-  out_ << "    " << tm(1,0) << " " << tm(1,1) << " " << tm(1,2) << " " << tm(1,3) << "\n";
-  out_ << "    " << tm(2,0) << " " << tm(2,1) << " " << tm(2,2) << " " << tm(2,3) << "\n";
-  out_ << "    " << tm(3,0) << " " << tm(3,1) << " " << tm(3,2) << " " << tm(3,3) << "\n";
-  out_ << "    </matrix>\n";
+  if(GetToOrigin()) {
+    out_ << "    <matrix>\n";
+    geom::Vec3 cen=scene->GetTransform().GetCenter();
+    out_ << "    1 0 0 " << -cen[0] << "\n";
+    out_ << "    0 1 0 " << -cen[1] << "\n";
+    out_ << "    0 0 1 " << -cen[2] << "\n";
+    out_ << "    0 0 0 1\n";
+    out_ << "    </matrix>\n";
+  } else {
+    out_ << "    <matrix>\n";
+    geom::Mat4 tm=scene->GetTransform().GetMatrix();
+    out_ << "    " << tm(0,0) << " " << tm(0,1) << " " << tm(0,2) << " " << tm(0,3) << "\n";
+    out_ << "    " << tm(1,0) << " " << tm(1,1) << " " << tm(1,2) << " " << tm(1,3) << "\n";
+    out_ << "    " << tm(2,0) << " " << tm(2,1) << " " << tm(2,2) << " " << tm(2,3) << "\n";
+    out_ << "    " << tm(3,0) << " " << tm(3,1) << " " << tm(3,2) << " " << tm(3,3) << "\n";
+    out_ << "    </matrix>\n";
+  }
   for(std::vector<std::string>::const_iterator oit=obj_.begin();oit!=obj_.end();++oit) {
     out_ << "    <node id=\"" << *oit << "\" name=\"" << *oit <<"\">\n";
     out_ << "     <instance_geometry url=\"#" << *oit << "\"/>\n";
@@ -126,10 +136,13 @@ void ColladaExporter::WriteVertexData(const float* vdata,
   out_ << "   <float_array count=\"" << count*3 << "\" id=\"" << name+"-Positions-array" << "\">\n";
   if(vdata) {
     const float* src=vdata;
+    float tmpv[3];
     for(unsigned int i=0;i<count;++i) {
-      out_ << scale_*src[0] << " ";
-      out_ << scale_*src[1] << " ";
-      out_ << scale_*src[2] << " ";
+      tmpv[0]=src[0]; tmpv[1]=src[1]; tmpv[2]=src[2];
+      TransformPosition(tmpv);
+      out_ << tmpv[0] << " ";
+      out_ << tmpv[1] << " ";
+      out_ << tmpv[2] << " ";
       src+=stride;
     }
   } else {
@@ -152,10 +165,13 @@ void ColladaExporter::WriteVertexData(const float* vdata,
   out_ << "   <float_array count=\"" << count*3 << "\" id=\"" << name+"-Normals-array" << "\">\n";
   if(ndata) {
     const float* src=ndata;
+    float tmpn[3];
     for(unsigned int i=0;i<count;++i) {
-      out_ << src[0] << " ";
-      out_ << src[1] << " ";
-      out_ << src[2] << " ";
+      tmpn[0]=src[0]; tmpn[1]=src[1]; tmpn[2]=src[2];
+      TransformNormal(tmpn);
+      out_ << tmpn[0] << " ";
+      out_ << tmpn[1] << " ";
+      out_ << tmpn[2] << " ";
       src+=stride;
     }
   } else {
diff --git a/modules/gfx/src/collada_exporter.hh b/modules/gfx/src/collada_exporter.hh
index c0192a10097e6cb0d2b48801431a3be2437509d5..7a05417c6826528bc49d956e33dc8109a3803a6d 100644
--- a/modules/gfx/src/collada_exporter.hh
+++ b/modules/gfx/src/collada_exporter.hh
@@ -35,7 +35,7 @@ namespace ost { namespace gfx {
 class DLLEXPORT_OST_GFX ColladaExporter: public Exporter
 {
 public:
-  ColladaExporter(const std::string& collada_file, float scale=1.0);
+  ColladaExporter(const std::string& collada_file);
   virtual ~ColladaExporter();
 
   // exporter interface
@@ -53,7 +53,6 @@ public:
 private:
   std::string file_;
   std::ofstream out_;
-  float scale_;
   std::vector<std::string> obj_;
 };
 
diff --git a/modules/gfx/src/color.cc b/modules/gfx/src/color.cc
index 43316f51c455e0643c7660274d10a5177177652b..60607ad0ed0fd0c85a0a67342b4b2929cfcbe426 100644
--- a/modules/gfx/src/color.cc
+++ b/modules/gfx/src/color.cc
@@ -263,7 +263,7 @@ Color& Color::operator/=(float rhs)
 
 void Color::to_rgb() const
 {
-  float hh=fmod(hsv_[0],1.0);
+  float hh=fmod(hsv_[0],1.0f);
   if(hh<0.0) hh+=1.0;
   float ss=std::min(1.0f,std::max(0.0f,hsv_[1]));
   float vv=std::min(1.0f,std::max(0.0f,hsv_[2]));
diff --git a/modules/gfx/src/color.hh b/modules/gfx/src/color.hh
index 6f0220bc2d2863c2744b502fee8c96dad21424ac..1340967f9b61d53d1aa4b5e307b0f9f560413d2d 100644
--- a/modules/gfx/src/color.hh
+++ b/modules/gfx/src/color.hh
@@ -159,7 +159,7 @@ private:
   mutable bool hsv_dirty_;
 };
 
-
+#undef RGB
 /// \brief RGB color spec from floats (0.0-1.0)
 Color DLLEXPORT_OST_GFX RGB(float r, float g, float b);
 
diff --git a/modules/gfx/src/entity.cc b/modules/gfx/src/entity.cc
index df1ad6bfc08fc8b9b7d421653eca750d7f0469cd..6c613225463b6a0da0777ecc3d2e5f4ea3215655 100644
--- a/modules/gfx/src/entity.cc
+++ b/modules/gfx/src/entity.cc
@@ -376,8 +376,9 @@ void Entity::CustomRenderPov(PovState& pov)
 
 void Entity::Export(Exporter* ex)
 {
+  if(!IsVisible()) return;
+
   ex->NodeStart(GetName(),Exporter::OBJ);
-  // in the simplest case, just export va
   if(rebuild_ || refresh_) {
     PreRenderGL(true);
   }
@@ -395,12 +396,17 @@ mol::AtomHandle Entity::PickAtom(const geom::Line3& line, Real line_width)
 {
   mol::AtomHandle picked_atom;
   if (!this->IsVisible())
-    return picked_atom;  
+    return picked_atom;
+  geom::Mat4 it=GetTF().GetInvertedMatrix();
+  geom::Vec3 l1=geom::Vec3(it*geom::Vec4(line.At(0.0)));
+  geom::Vec3 l2=geom::Vec3(it*geom::Vec4(line.At(1.0)));
+  geom::Line3 tf_line(l1,l2);
+
   for (RendererMap::iterator i=renderer_.begin(), 
        e=renderer_.end(); i!=e; ++i) {
     impl::EntityRenderer* r=i->second;
     if (r->HasDataToRender() && r->IsEnabled()) {
-      r->PickAtom(line, line_width, picked_atom);      
+      r->PickAtom(tf_line, line_width, picked_atom);      
     }
   }
   return picked_atom;
@@ -447,7 +453,7 @@ bool Entity::OnSelect(const geom::Line3& line, geom::Vec3& result,
         if(av.IsValid()) {
           LOG_DEBUG("de-selected atom: " << sel);
           sel_.RemoveAtom(av);
-          if(av.GetResidue().GetAtomCount()==0){
+          if(!av.GetResidue().HasAtoms()){
             av.GetResidue().GetChain().RemoveResidue(av.GetResidue());
           }
         } else {
@@ -608,7 +614,7 @@ void Entity::OnRenderModeChange()
   for (RendererMap::iterator i=renderer_.begin(), 
 	 e=renderer_.end(); i!=e; ++i) {
     mol::EntityView rv=i->second->GetFullView();
-    if (rv.IsValid() && rv.GetAtomCount()>0) {
+    if (rv.IsValid() && rv.HasAtoms()) {
       i->second->SetSelection(mol::Intersection(sel_, rv));
     }         
     i->second->UpdateViews();
@@ -998,7 +1004,7 @@ void Entity::set_static_max_rad()
 
 bool Entity::HasSelection() const
 {
-  return (sel_.IsValid() && sel_.GetAtomCount()>0);
+  return (sel_.IsValid() && sel_.HasAtoms());
 }
 
 namespace {
diff --git a/modules/gfx/src/exporter.cc b/modules/gfx/src/exporter.cc
new file mode 100644
index 0000000000000000000000000000000000000000..28dbd9b692365f4cfd1590d584a92a0ebbac7477
--- /dev/null
+++ b/modules/gfx/src/exporter.cc
@@ -0,0 +1,62 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+
+#include <ost/gfx/scene.hh>
+#include "exporter.hh"
+
+namespace ost { namespace gfx {
+
+  void Exporter::SetupTransform(const Scene* scene)
+  {
+    vertex_tf_=geom::Mat4();
+    normal_tf_=geom::Mat3();
+    geom::Mat4 Tmat,Rmat,Smat,Cmat;
+    if(to_origin_) {
+      geom::Vec3 trans=scene->GetTransform().GetTrans();
+      geom::Vec3 cen=scene->GetTransform().GetCenter();
+      vertex_tf_=geom::Mat4(scene->GetTransform().GetRot()) *
+                 geom::Mat4(scale_, 0.0, 0.0, 0.0,
+                            0.0, scale_, 0.0, 0.0,
+                            0.0, 0.0, scale_, 0.0,
+                            0.0, 0.0, 0.0, 1.0)*
+                 geom::Mat4(1.0,0.0,0.0,-cen[0],
+                           0.0,1.0,0.0,-cen[1],
+                           0.0,0.0,1.0,-cen[2],
+                           0.0,0.0,0.0,1.0);
+      normal_tf_=scene->GetTransform().GetRot();
+    } else {
+      vertex_tf_=geom::Mat4(scale_, 0.0, 0.0, 0.0,
+                            0.0, scale_, 0.0, 0.0,
+                            0.0, 0.0, scale_, 0.0,
+                            0.0, 0.0, 0.0, 1.0);
+    }
+  }
+
+  void Exporter::TransformPosition(float* v) const
+  {
+    geom::Vec3 result(vertex_tf_*geom::Vec4(v[0],v[1],v[2],1.0));
+    v[0]=result[0]; v[1]=result[1]; v[2]=result[2];
+  }
+
+  void Exporter::TransformNormal(float* n) const
+  {
+    geom::Vec3 result=normal_tf_*geom::Vec3(n[0],n[1],n[2]);
+    n[0]=result[0]; n[1]=result[1]; n[2]=result[2];
+  }
+}} // ns
diff --git a/modules/gfx/src/exporter.hh b/modules/gfx/src/exporter.hh
index 20b0601aee6a110a4c713a687db50d4834c5978c..1780851eb94e5470f778ea648fed821782717f66 100644
--- a/modules/gfx/src/exporter.hh
+++ b/modules/gfx/src/exporter.hh
@@ -19,6 +19,11 @@
 #ifndef OST_GFX_EXPORTER_HH
 #define OST_GFX_EXPORTER_HH
 
+#include <ost/geom/vec3.hh>
+#include <ost/geom/vec4.hh>
+#include <ost/geom/mat3.hh>
+#include <ost/geom/mat4.hh>
+
 #include <ost/gfx/module_config.hh>
 
 namespace ost { namespace gfx {
@@ -34,6 +39,10 @@ public:
     OBJ=3
   };
 
+  Exporter() :
+    scale_(1.0),
+    to_origin_(true)
+  {}
   virtual ~Exporter() {}
   virtual void SceneStart(const Scene* scene) {}
   virtual void SceneEnd(const Scene* scene) {}
@@ -49,8 +58,32 @@ public:
   virtual void WriteLineData(const unsigned int* ij, size_t count) {}
   virtual void WriteTriData(const unsigned int* ijk, size_t count) {}
   virtual void WriteQuadData(const unsigned int* ijkl, size_t count) {}
+
+  // scale positions for absolute data formats (like dae)
+  void SetScale(float s) {scale_=s;}
+  float GetScale() const {return scale_;}
+  // if true (default), re-orient so that center is at (0,0,0)
+  // and viewing direction is along z
+  // (basically apply modelview matrix)
+  void SetToOrigin(bool b) {to_origin_=b;}
+  bool GetToOrigin() const {return to_origin_;}
+
+  // used by Scene::Export
+  void SetupTransform(const Scene* scene);
+  // used by WriteVertexData in derived classes
+  // modifies input arg!!
+  void TransformPosition(float* p) const;
+  void TransformNormal(float* n) const;
+
+private:
+  float scale_;
+  bool to_origin_;
+  geom::Mat4 vertex_tf_;
+  geom::Mat3 normal_tf_;
 };
 
+
+
 }} // ns
 
 #endif
diff --git a/modules/gfx/src/gfx_node.cc b/modules/gfx/src/gfx_node.cc
index 813ce6f413e677e8b884ae191f4b3a608b27a47c..59b44d162d991620c77bd58ad300f49f5d3fc8de 100644
--- a/modules/gfx/src/gfx_node.cc
+++ b/modules/gfx/src/gfx_node.cc
@@ -108,7 +108,9 @@ void GfxNode::Export(Exporter* ex)
   if(!IsVisible()) return;
   ex->NodeStart(GetName(),Exporter::GROUP);
   for(GfxNodeVector::iterator it=node_vector_.begin();it!=node_vector_.end();++it) {
-    (*it)->Export(ex);
+    if((*it)->IsVisible()) {
+      (*it)->Export(ex);
+    }
   }
   ex->NodeEnd(GetName());
 }
diff --git a/modules/gfx/src/gfx_object.cc b/modules/gfx/src/gfx_object.cc
index 63003cd5bce9481772ed5d8f3f1e8aa919e2e7c8..90c82ca1cdfec297a7d6ee077e00076d7522668f 100644
--- a/modules/gfx/src/gfx_object.cc
+++ b/modules/gfx/src/gfx_object.cc
@@ -39,6 +39,10 @@
 #  include <ost/img/alg/stat.hh>
 #endif // OST_IMG_ENABLED
 
+#if OST_SHADER_SUPPORT_ENABLED
+#include "shader.hh"
+#endif
+
 namespace ost { namespace gfx {
 
 GfxObj::GfxObj(const String& name):
@@ -66,6 +70,9 @@ GfxObj::GfxObj(const String& name):
 #endif
   solid_(false),
   solid_color_(RGB(0.7,0.7,0.7)),
+  clip_flag_(false),
+  clip_plane_(),
+  clip_offset_(0.0),
   c_ops_(),
   labels_(),
   use_occlusion_(false)
@@ -102,6 +109,11 @@ void GfxObj::DeepSwap(GfxObj& go)
   std::swap(smoothf_,go.smoothf_);
   std::swap(outline_flag_,go.outline_flag_);
   std::swap(outline_mode_,go.outline_mode_);
+  std::swap(solid_,go.solid_);
+  std::swap(solid_color_,go.solid_color_);
+  std::swap(clip_flag_,go.clip_flag_);
+  std::swap(clip_plane_,go.clip_plane_);
+  std::swap(clip_offset_,go.clip_offset_);
   std::swap(c_ops_,go.c_ops_);
   std::swap(labels_,go.labels_);
   std::swap(use_occlusion_,go.use_occlusion_);
@@ -152,7 +164,27 @@ void GfxObj::RenderGL(RenderPass pass)
       only STANDARD_RENDER_PASS and GLOW_RENDER_PASS are
       passed down to the custom rendering routines
     */
-   
+  
+    if(clip_flag_) {
+#if OST_SHADER_SUPPORT_ENABLED && GL_VERSION_3_0
+      glEnable(GL_CLIP_DISTANCE0);
+      GLuint cp = Shader::Instance().GetCurrentProgram();
+      if(cp>0) {
+        glUniform1i(glGetUniformLocation(cp,"clip_flag"),1);
+        glUniform4f(glGetUniformLocation(cp,"clip_plane"),
+                   clip_plane_[0],clip_plane_[1],clip_plane_[2],clip_plane_[3]);
+      } else {
+        GLdouble eq[4];
+        for(size_t i=0;i<4;++i) eq[i]=clip_plane_[i];
+        glClipPlane(GL_CLIP_PLANE0,eq);
+      }
+#else
+      GLdouble eq[4];
+      for(size_t i=0;i<4;++i) eq[i]=clip_plane_[i];
+      glClipPlane(GL_CLIP_PLANE0,eq);
+#endif
+    }
+
     if(pass==DEPTH_RENDER_PASS) {
       render_depth_only();
     } else if(pass==TRANSPARENT_RENDER_PASS) {
@@ -181,6 +213,12 @@ void GfxObj::RenderGL(RenderPass pass)
       render_labels();
     }
 
+    if(clip_flag_) {
+#if OST_SHADER_SUPPORT_ENABLED && GL_VERSION_3_0
+      glDisable(GL_CLIP_DISTANCE0);
+#endif
+    }
+
     glPopMatrix();    
   }
 }
@@ -393,6 +431,27 @@ void GfxObj::SetSolidColor(const Color& c)
   Scene::Instance().RequestRedraw();
 }
 
+void GfxObj::SetClip(bool f)
+{
+  clip_flag_=f;
+  // va_.SetClip(clip_flag_);
+  Scene::Instance().RequestRedraw();
+}
+
+void GfxObj::SetClipPlane(const geom::Vec4& p)
+{
+  clip_plane_=p;
+  // va_.SetSolidColor(solid_color_);
+  Scene::Instance().RequestRedraw();
+}
+
+void GfxObj::SetClipOffset(float f)
+{
+  clip_offset_=f;
+  va_.SetClipOffset(clip_offset_);
+  Scene::Instance().RequestRedraw();
+}
+
 void GfxObj::ColorBy(const mol::EntityView& ev, 
                       const String& prop,
                       const Gradient& g, float minv, float maxv)
@@ -487,6 +546,11 @@ void GfxObj::OnInput(const InputEvent& e)
       trans+=geom::Vec3(0.0, -fy*e.GetDelta(), 0.0)*rot;
     }
     transform_.SetTrans(trans);
+  } else if (e.GetCommand()==INPUT_COMMAND_TRANSZ) {
+    float currz=transform_.GetTrans()[2];
+    float delta=currz*pow(1.01f,-e.GetDelta())-currz;
+    transform_.ApplyZAxisTranslation(delta);
+    transformed=true;
   }
   if (transformed) {
     GfxObjP obj=dyn_cast<GfxObj>(this->shared_from_this());
@@ -630,7 +694,7 @@ void GfxObj::render_labels() const
 }
 
 void GfxObj::ReapplyColorOps(){
-  if(c_ops_.size()>0){
+  if(! c_ops_.empty()){
     GfxObjP o=dyn_cast<GfxObj>(shared_from_this());
     for(boost::ptr_vector<gfx::ColorOp>::iterator it=c_ops_.begin();
       it!=c_ops_.end();++it) {
@@ -656,6 +720,7 @@ void GfxObj::Debug(unsigned int flags)
 void GfxObj::render_depth_only()
 {
   glPushAttrib(GL_ALL_ATTRIB_BITS);
+  glPushClientAttrib(GL_ALL_ATTRIB_BITS);
   glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
   glDisable(GL_LIGHTING);
   glDisable(GL_COLOR_MATERIAL);
@@ -671,6 +736,7 @@ void GfxObj::render_depth_only()
   CustomRenderGL(STANDARD_RENDER_PASS);
   CustomRenderGL(TRANSPARENT_RENDER_PASS);
   glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);      
+  glPopClientAttrib();
   glPopAttrib();
 }
 
diff --git a/modules/gfx/src/gfx_object.hh b/modules/gfx/src/gfx_object.hh
index 0b70065d7f820ca924ef07b3d2ad3005fe4e71b2..e0e8f5b829f735fc611e918644205e0a171201cf 100644
--- a/modules/gfx/src/gfx_object.hh
+++ b/modules/gfx/src/gfx_object.hh
@@ -93,6 +93,13 @@ public:
   virtual void SetSolidColor(const Color& c);
   virtual Color GetSolidColor() const {return solid_color_;}
   
+  virtual void SetClip(bool f);
+  virtual bool GetClip() const {return clip_flag_;}
+  virtual void SetClipPlane(const geom::Vec4&);
+  virtual geom::Vec4 GetClipPlane() const {return clip_plane_;}
+  virtual void SetClipOffset(float f);
+  virtual float GetClipOffset() const {return clip_offset_;}
+
   virtual void ColorBy(const mol::EntityView& ev, 
                        const String& prop,
                        const Gradient& g, float minv, float maxv);
@@ -211,6 +218,9 @@ public:
 
   void Debug(unsigned int flags);
 
+  IndexedVertexArray& GetVA() {return va_;}
+  const IndexedVertexArray& GetVA() const {return va_;}
+
  protected:
   
   void PreRenderGL(bool flag);
@@ -250,6 +260,10 @@ public:
   bool solid_;
   Color solid_color_;
 
+  bool clip_flag_;
+  geom::Vec4 clip_plane_;
+  float clip_offset_;
+
   boost::ptr_vector<gfx::ColorOp> c_ops_;
 
   TextPrimList labels_;
diff --git a/modules/gfx/src/gfx_object_base.hh b/modules/gfx/src/gfx_object_base.hh
index 448de0cf2687781045e7b59bc72b145be0ee1c2d..07e49a92eb4df39fa9359b3f09e37f4e3eb9ef40 100644
--- a/modules/gfx/src/gfx_object_base.hh
+++ b/modules/gfx/src/gfx_object_base.hh
@@ -121,6 +121,13 @@ class DLLEXPORT_OST_GFX GfxObjBase: public GfxNode
   virtual bool GetSolid() const = 0;
   virtual void SetSolidColor(const Color& c) = 0;
   virtual Color GetSolidColor() const = 0;
+
+  virtual void SetClip(bool f) = 0;
+  virtual bool GetClip() const = 0;
+  virtual void SetClipPlane(const geom::Vec4&) = 0;
+  virtual geom::Vec4 GetClipPlane() const = 0;
+  virtual void SetClipOffset(float f) = 0;
+  virtual float GetClipOffset() const = 0;
   
   /// \brief color each component based on the gradient-mapped property of 
   ///    the given entity
diff --git a/modules/gfx/src/gfx_prim.hh b/modules/gfx/src/gfx_prim.hh
index d3b97cec8bb5bf6c7b9c249d0ddaf23507151305..cb545425462042868a60be6b0a49c99adda6d065 100644
--- a/modules/gfx/src/gfx_prim.hh
+++ b/modules/gfx/src/gfx_prim.hh
@@ -74,18 +74,18 @@ struct CylinderPrim {
     calc_rotmat();
   }
 
-  CylinderPrim(const geom::Vec3& st, const geom::Vec3& en, float rad1, float rad2, const Color& col):
+  CylinderPrim(const geom::Vec3& st, const geom::Vec3& en, float radius_1, float radius_2, const Color& col):
     start(st), end(en),
-    radius1(rad1), radius2(rad2),
+    radius1(radius_1), radius2(radius_2),
     color1(col), color2(col),
     length(geom::Length(end-start)), rotmat(), rotmat_t() 
   {
     calc_rotmat();
   }
 
-  CylinderPrim(const geom::Vec3& st, const geom::Vec3& en, float rad1, float rad2, const Color& col1, const Color& col2):
+  CylinderPrim(const geom::Vec3& st, const geom::Vec3& en, float radius_1, float radius_2, const Color& col1, const Color& col2):
     start(st), end(en),
-    radius1(rad1), radius2(rad2),
+    radius1(radius_1), radius2(radius_2),
     color1(col1), color2(col2),
     length(geom::Length(end-start)), rotmat(), rotmat_t() 
   {
diff --git a/modules/gfx/src/gost_exporter.cc b/modules/gfx/src/gost_exporter.cc
index 79a6e9b28390f1ce2d1890e88d824de48856e358..525a70aba0334a0dcdc1e0bfbbccee7ff28975e3 100644
--- a/modules/gfx/src/gost_exporter.cc
+++ b/modules/gfx/src/gost_exporter.cc
@@ -57,6 +57,7 @@ namespace ost { namespace gfx {
   }
 
 GostExporter::GostExporter(const std::string& fname):
+  Exporter(),
   file_(0)
 {
   file_=fopen(fname.c_str(),"w");
diff --git a/modules/gfx/src/gradient.cc b/modules/gfx/src/gradient.cc
index f1c93ffbbbfa7ff799073a49a3da5210fc688eb7..0018f3aa6bbd8c9eb07fd7a0b6f13b5eb70ec91b 100644
--- a/modules/gfx/src/gradient.cc
+++ b/modules/gfx/src/gradient.cc
@@ -39,6 +39,7 @@ Gradient::Gradient():
 Gradient::Gradient(const String& name)
 {
   Gradient gradient = GradientManager::Instance().GetGradient(name);
+  hsv_mode_ = gradient.hsv_mode_;
   // why doesn't this work:
   //  stops_=gradient.stops_
   // or even better
diff --git a/modules/gfx/src/impl/entity_renderer.cc b/modules/gfx/src/impl/entity_renderer.cc
index fb22e24a375988bdcb36bf8b9b1b9b0e34695fef..9b623cc11455a1a93737045f576e3279cf6d3637 100644
--- a/modules/gfx/src/impl/entity_renderer.cc
+++ b/modules/gfx/src/impl/entity_renderer.cc
@@ -113,7 +113,7 @@ void EntityRenderer::SubstractView(const mol::EntityView& view)
 
 void EntityRenderer::ClearViews()
 {
-  if (full_view_.IsValid() && full_view_.GetAtomCount()>0) {
+  if (full_view_.IsValid() && full_view_.HasAtoms()) {
     full_view_=full_view_.CreateEmptyView();
     if(effective_view_.IsValid()){
       effective_view_=effective_view_.CreateEmptyView();
@@ -127,7 +127,7 @@ void EntityRenderer::ClearViews()
 
 bool EntityRenderer::HasDataToRender() const
 {
-  return effective_view_ && effective_view_.GetAtomCount()>0;
+  return effective_view_ && effective_view_.HasAtoms();
 }
 
 mol::EntityView EntityRenderer::GetFullView()
@@ -163,7 +163,7 @@ void EntityRenderer::Export(Exporter* ex)
 
 bool EntityRenderer::HasSelection() const
 {
-  return (sel_.IsValid() && sel_.GetAtomCount()>0);
+  return (sel_.IsValid() && sel_.HasAtoms());
 }
 
 void EntityRenderer::SetSelection(const mol::EntityView& sel)
diff --git a/modules/gfx/src/impl/glx_offscreen_buffer.cc b/modules/gfx/src/impl/glx_offscreen_buffer.cc
index 2c3002343969c240c86c6406ae3d6fa0caba91b5..41bca43a363a7c873f0ee719e2ca68c0859a893b 100644
--- a/modules/gfx/src/impl/glx_offscreen_buffer.cc
+++ b/modules/gfx/src/impl/glx_offscreen_buffer.cc
@@ -21,12 +21,24 @@
   Author: Ansgar Philippsen
 */
 
+#include <iomanip>
+
 #include <ost/log.hh>
 #include <ost/gfx/offscreen_buffer.hh>
 #include <ost/gfx/scene.hh>
 
 namespace ost { namespace gfx {
 
+namespace {
+  Display* get_dpy() {
+    static Display* dpy=0;
+    if(not dpy) {
+      dpy=XOpenDisplay(getenv("DISPLAY"));
+    }
+    return dpy;
+  }
+}
+
 OffscreenBuffer::OffscreenBuffer(unsigned int width, unsigned int height, const OffscreenBufferFormat& f, bool shared):
   width_(width), height_(height), valid_(false), active_(false)
 {
@@ -37,7 +49,7 @@ OffscreenBuffer::OffscreenBuffer(unsigned int width, unsigned int height, const
   }
 
   LOG_DEBUG("offscreen buffer: XOpenDisplay");
-  dpy_ = XOpenDisplay(getenv("DISPLAY"));
+  dpy_ = get_dpy();
   if(dpy_==NULL) {
     LOG_ERROR("error creating offscreen rendering context: XOpenDisplay failed");
     return;
@@ -60,15 +72,59 @@ OffscreenBuffer::OffscreenBuffer(unsigned int width, unsigned int height, const
   attrib_list.push_back(f.cbits);
   attrib_list.push_back(GLX_ALPHA_SIZE);
   attrib_list.push_back(f.abits);
+  attrib_list.push_back(GLX_STENCIL_SIZE);
+  attrib_list.push_back(8);
+  attrib_list.push_back(GLX_SAMPLE_BUFFERS);
+  attrib_list.push_back(f.multisample ? 1 : 0);
   attrib_list.push_back(0);
-
+  bool search_multisample=f.multisample;
   int nelem=0;
   LOG_DEBUG("offscreen buffer: glXChooseFBConfig");
   fbconfig_ =glXChooseFBConfig(dpy_,0,&attrib_list[0],&nelem);
   if(fbconfig_==0 || nelem==0) {
-    LOG_ERROR("error creating offscreen rendering context: glXChooseFBConfig failed");
-    return;
+    if(f.multisample) {
+      LOG_DEBUG("no offscreen rendering context with multisample, trying without");
+      // take out the multisample requirement
+      attrib_list[attrib_list.size()-2]=0;
+      fbconfig_ =glXChooseFBConfig(dpy_,0,&attrib_list[0],&nelem);
+      if(fbconfig_==0 || nelem==0) {
+        LOG_ERROR("error creating offscreen rendering context: glXChooseFBConfig failed");
+        return;
+      }
+      search_multisample=false;
+    } else {
+      LOG_ERROR("error creating offscreen rendering context: glXChooseFBConfig failed");
+      return;
+    }
+  }
+#ifndef NDEBUG
+  LOG_VERBOSE("offscreen buffer: available framebuffer configs");
+  for(int i=0;i<nelem;++i) {
+    int rbits; glXGetFBConfigAttrib(dpy_,fbconfig_[i], GLX_RED_SIZE, &rbits);
+    int gbits; glXGetFBConfigAttrib(dpy_,fbconfig_[i], GLX_GREEN_SIZE, &gbits);
+    int bbits; glXGetFBConfigAttrib(dpy_,fbconfig_[i], GLX_BLUE_SIZE, &bbits);
+    int dbits; glXGetFBConfigAttrib(dpy_,fbconfig_[i], GLX_DEPTH_SIZE, &dbits);
+    int sbits; glXGetFBConfigAttrib(dpy_,fbconfig_[i], GLX_STENCIL_SIZE, &sbits);
+    int ms; glXGetFBConfigAttrib(dpy_,fbconfig_[i], GLX_SAMPLES, &ms);
+    LOG_VERBOSE(" " << std::setw(3) << i << std::setw(0) << ": rgb=" << rbits << "." << gbits << "." << bbits << " d=" << dbits << " s=" << sbits << " ms=" << ms);
+  }
+#endif
+  fb_config_id_=0;
+  if(search_multisample) {
+    int ms;
+    int best_ms;
+    glXGetFBConfigAttrib(dpy_,fbconfig_[0], GLX_SAMPLES, &best_ms);
+    for(int i=1;i<nelem;++i) {
+      glXGetFBConfigAttrib(dpy_,fbconfig_[i], GLX_SAMPLES, &ms);
+      if(ms<=static_cast<int>(f.samples) && ms>best_ms) {
+        fb_config_id_=i;
+        best_ms=ms;
+      }
+    }
   }
+#ifndef NDEBUG
+  LOG_VERBOSE("offscreen buffer: using buffer # " << fb_config_id_ << " for export");
+#endif
 
   attrib_list.clear();
   attrib_list.push_back(GLX_PBUFFER_WIDTH);
@@ -78,19 +134,20 @@ OffscreenBuffer::OffscreenBuffer(unsigned int width, unsigned int height, const
   attrib_list.push_back(0);
   
   LOG_DEBUG("offscreen buffer: glXCreatePBuffer");
-  pbuffer_ = glXCreatePbuffer(dpy_, fbconfig_[0], &attrib_list[0]);
+  pbuffer_ = glXCreatePbuffer(dpy_, fbconfig_[fb_config_id_], &attrib_list[0]);
   if(!pbuffer_) {
     LOG_ERROR("error creating offscreen rendering context: glXCreatePBuffer failed");
+    XFree(fbconfig_);
     return;
   }
 
   if(shared) {
     LOG_DEBUG("offscreen buffer: glxCreateNewContext(shared=true)");
-    context_ = glXCreateNewContext(dpy_, fbconfig_[0], GLX_RGBA_TYPE, 
+    context_ = glXCreateNewContext(dpy_, fbconfig_[fb_config_id_], GLX_RGBA_TYPE, 
 				   glXGetCurrentContext(), True);
   } else {
     LOG_DEBUG("offscreen buffer: glxCreateNewContext(shared=false)");
-    context_ = glXCreateNewContext(dpy_, fbconfig_[0], GLX_RGBA_TYPE, 
+    context_ = glXCreateNewContext(dpy_, fbconfig_[fb_config_id_], GLX_RGBA_TYPE, 
 				   NULL, True);
     
   }
@@ -98,6 +155,7 @@ OffscreenBuffer::OffscreenBuffer(unsigned int width, unsigned int height, const
   if(!context_) {
     LOG_ERROR("error creating offscreen rendering context: glXCreateNewContext failed");
     glXDestroyPbuffer(dpy_, pbuffer_);
+    XFree(fbconfig_);
     return;
   }
 
@@ -111,6 +169,8 @@ OffscreenBuffer::~OffscreenBuffer()
     glXDestroyContext(dpy_, context_);
     LOG_DEBUG("offscreen buffer: glXDestroyPbuffer()");
     glXDestroyPbuffer(dpy_, pbuffer_);
+    LOG_DEBUG("offscreen buffer: XFree(fbconfig_list)");
+    //XFree(fbconfig_);
   }
 }
 
@@ -123,14 +183,14 @@ bool OffscreenBuffer::Resize(unsigned int width, unsigned int height)
   attrib_list.push_back(height);
   attrib_list.push_back(0);
   
-  GLXPbuffer new_pbuffer = glXCreatePbuffer(dpy_, fbconfig_[0], &attrib_list[0]);
+  GLXPbuffer new_pbuffer = glXCreatePbuffer(dpy_, fbconfig_[fb_config_id_], &attrib_list[0]);
 
   if(!new_pbuffer) {
     LOG_ERROR("offscreen rendering resize failed to allocate new pbuffer");
     return false;
   }
   
-  GLXContext new_context = glXCreateNewContext(dpy_, fbconfig_[0], GLX_RGBA_TYPE, 
+  GLXContext new_context = glXCreateNewContext(dpy_, fbconfig_[fb_config_id_], GLX_RGBA_TYPE, 
                                                glXGetCurrentContext(), True);
   
   if(!new_context) {
diff --git a/modules/gfx/src/impl/glx_offscreen_buffer.hh b/modules/gfx/src/impl/glx_offscreen_buffer.hh
index df809d8027343bc1e2a3f9190352e06f30cab438..e089e8ace66d32b46cf9f4d3d6884211d225a449 100644
--- a/modules/gfx/src/impl/glx_offscreen_buffer.hh
+++ b/modules/gfx/src/impl/glx_offscreen_buffer.hh
@@ -55,6 +55,7 @@ private:
   GLXFBConfig* fbconfig_;
   GLXPbuffer  pbuffer_;
   GLXContext  context_;
+  size_t fb_config_id_;
 };
 
 }} // ns
diff --git a/modules/gfx/src/offscreen_buffer.cc b/modules/gfx/src/offscreen_buffer.cc
deleted file mode 100644
index 02b619148326dec910dbaff11a820a5a5d8e6b18..0000000000000000000000000000000000000000
--- a/modules/gfx/src/offscreen_buffer.cc
+++ /dev/null
@@ -1,400 +0,0 @@
-//------------------------------------------------------------------------------
-// This file is part of the OpenStructure project <www.openstructure.org>
-//
-// Copyright (C) 2008-2011 by the OpenStructure authors
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License as published by the Free
-// Software Foundation; either version 3.0 of the License, or (at your option)
-// any later version.
-// This library is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with this library; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//------------------------------------------------------------------------------
-/*
-  Authors: Ansgar Philippsen, Marco Biasini
-*/
-
-#include <ost/log.hh>
-
-#include <ost/gfx/glext_include.hh>
-
-#include "offscreen_buffer.hh"
-
-#include <ost/gfx/scene.hh>
-
-namespace ost { namespace gfx {
-
-OffscreenBuffer& OffscreenBuffer::Instance()
-{
-  static OffscreenBuffer instance(500,500,8,8,8,8,24);
-  return instance;
-}
-
-bool OffscreenBuffer::Begin() 
-{
-  LOG_DEBUG("switching to offscreen rendering");
-
-  if(active_) return true;
-  
-  glGetIntegerv(GL_VIEWPORT,old_vp_);
-#if defined(__linux__)
-
-  old_context_ = glXGetCurrentContext();
-
-  if(context_ != old_context_) {
-    old_dr1_ = glXGetCurrentDrawable();
-    old_dr2_ = glXGetCurrentReadDrawable();
-    
-    if(!glXMakeContextCurrent(dpy_, pbuffer_, pbuffer_, context_)) {
-      LOG_ERROR("error switching to offscreen rendering context: glXMakeContextCurrent failed");
-      return false;
-    }
-  }
-#elif defined(__APPLE__)
-
-  old_context_=CGLGetCurrentContext();
-
-  if(context_ != old_context_) {
-    if (CGLError err=CGLSetCurrentContext(context_)) {
-      LOG_ERROR("error switching to offscreen rendering context. "
-                 "CGLSetCurrentContext failed: " << CGLErrorString(err));
-      return false;
-    }
-  }
-#elif defined(_WIN32)
-  /*old_context_ = wglGetCurrentContext();
-  
-  if(context_ != old_context_) {
-    dev_context_=wglGetCurrentDC();
-    if (BOOL err=wglMakeCurrent(dev_context_, context_)) {
-      LOG_ERROR("error switching to offscreen rendering context. "
-                 "wglMakeCurrent failed: ");
-      return false;
-    }
-  }
-  */
-#endif
-  active_=true;
-  return true;
-}
-
-bool OffscreenBuffer::End() 
-{
-  LOG_DEBUG("switching back to normal rendering");
-
-  if(!active_) return true;
-
-#if defined(__linux__)
-
-  if(context_ != old_context_) {
-    // ignore error
-    glXMakeContextCurrent(dpy_, old_dr1_, old_dr2_, old_context_);
-  }
-
-#elif defined(__APPLE__)
-
-  if(context_!=old_context_) {
-    // ignore error
-    CGLSetCurrentContext(old_context_);
-  }
-  
-#elif defined(_WIN32)
-  /*
-  if(context_!=old_context_) {
-    old_dev_context_=wglGetCurrentDC();
-    wglMakeCurrent(old_dev_context_, old_context_);
-  }
-  */
-#endif  
-
-  Scene::Instance().SetViewport(old_vp_[2],old_vp_[3]);
-  active_=false;
-  return true;
-}
-
-bool OffscreenBuffer::Resize(unsigned int width, unsigned int height)
-{
-#if defined(__linux__)
-
-  std::vector<int> attrib_list;
-  attrib_list.push_back(GLX_PBUFFER_WIDTH);
-  attrib_list.push_back(width);
-  attrib_list.push_back(GLX_PBUFFER_HEIGHT);
-  attrib_list.push_back(height);
-  attrib_list.push_back(0);
-  
-  GLXPbuffer new_pbuffer = glXCreatePbuffer(dpy_, fbconfig_[0], &attrib_list[0]);
-
-  if(!new_pbuffer) {
-    LOG_ERROR("offscreen rendering resize failed");
-    return false;
-  }
-  
-  GLXContext new_context = glXCreateNewContext(dpy_, fbconfig_[0], GLX_RGBA_TYPE, 
-                                               glXGetCurrentContext(), True);
-  
-  if(!new_context) {
-    LOG_ERROR("offscreen rendering resize failed to get new context");
-    return false;
-  }
-
-  glXDestroyContext(dpy_, context_);
-  glXDestroyPbuffer(dpy_, pbuffer_);
-
-  context_=new_context;
-  pbuffer_=new_pbuffer;
-
-#elif defined(__APPLE__)
-  CGLPBufferObj      new_pbuffer;  
-  CGLError err=CGLCreatePBuffer(width, height, GL_TEXTURE_RECTANGLE_EXT,
-                                GL_RGBA, 0,  &new_pbuffer);
-  if (err) {
-    LOG_ERROR("error resizing offscreen rendering context: "
-               "CGLCreatePBuffer failed: " << CGLErrorString(err));
-    return false;
-  }
-  GLint screen=0;
-  assert(CGLGetVirtualScreen(context_, &screen)==0);  
-  err=CGLSetPBuffer(context_, new_pbuffer, 0, 0, screen);
-  if (err) {
-    LOG_ERROR("error resizing offscreen rendering context. "
-               "CGLSetPBuffer failed: " << CGLErrorString(err));
-    return false;
-  }
-  CGLDestroyPBuffer(pbuffer_);
-  pbuffer_=new_pbuffer;
-
-#elif defined(_WIN32)
- /* int attribList[] = {0};
-  int format = 0;
-
-  HPBUFFERARB        new_pbuffer;
-  new_pbuffer = wglCreatePbufferARB(dev_context_, format, width, height, attribList);
-  if (new_pbuffer == NULL) 
-  {
-    LOG_ERROR("Error resizing offscreen rendering context (wglCreatePbufferARB failed)\n");
-    return false;
-  }
-
-  dev_context_ = wglGetPbufferDCARB(new_pbuffer);
-  if (dev_context_ == NULL) 
-  {
-    LOG_ERROR("Unable to retrieve handle to resized pbuffer device context\n");
-    return false;
-  }
-
-  context_ = wglCreateContext(dev_context_);
-  if (context_ == NULL) 
-  {
-    LOG_ERROR("Unable to create a rendering context for the resized pbuffer\n");
-    return false;
-  }
-  //
-  //if (!wglShareLists(old_context_, context_)) 
-  //{
-  //  LOG_ERROR("Unable to share data between resized rendering contexts\n");
-  //  return;
-  //}
-  */
-#endif
-  // nothing failed, set new width and height
-  width_=width;
-  height_=height;
-  return true;
-}
-
-bool OffscreenBuffer::IsValid() const
-{
-  return valid_;
-}
-
-bool OffscreenBuffer::IsActive() const
-{
-  return valid_;
-}
-
-OffscreenBuffer::OffscreenBuffer(int width, int height, int r_bits, 
-                                 int b_bits, int g_bits, 
-                                 int a_bits, int depth_bits):
-  width_(width), height_(height),valid_(false)
-{
-
-#if defined(__linux__)
-
-  if(getenv("DISPLAY")==NULL) {
-    LOG_ERROR("error creating offscreen rendering context: missing DISPLAY environment variable");
-    return;
-  }
-  dpy_ = XOpenDisplay(getenv("DISPLAY"));
-  if(dpy_==NULL) {
-    LOG_ERROR("error creating offscreen rendering context: XOpenDisplay failed");
-    return;
-  }
-
-  std::vector<int> attrib_list;
-  attrib_list.push_back(GLX_RENDER_TYPE);
-  attrib_list.push_back(GLX_RGBA_BIT);
-  attrib_list.push_back(GLX_DRAWABLE_TYPE);
-  attrib_list.push_back(GLX_PBUFFER_BIT);
-  attrib_list.push_back(GLX_DOUBLEBUFFER);
-  attrib_list.push_back(False);
-  attrib_list.push_back(GLX_DEPTH_SIZE);
-  attrib_list.push_back(depth_bits);
-  attrib_list.push_back(GLX_RED_SIZE);
-  attrib_list.push_back(r_bits);
-  attrib_list.push_back(GLX_GREEN_SIZE);
-  attrib_list.push_back(g_bits);
-  attrib_list.push_back(GLX_BLUE_SIZE);
-  attrib_list.push_back(b_bits);
-  attrib_list.push_back(GLX_ALPHA_SIZE);
-  attrib_list.push_back(a_bits);
-  attrib_list.push_back(0);
-
-  int nelem=0;
-  fbconfig_ =glXChooseFBConfig(dpy_,0,&attrib_list[0],&nelem);
-  if(fbconfig_==0 || nelem==0) {
-    LOG_ERROR("error creating offscreen rendering context: glXChooseFBConfig failed");
-    return;
-  }
-
-  attrib_list.clear();
-  attrib_list.push_back(GLX_PBUFFER_WIDTH);
-  attrib_list.push_back(width);
-  attrib_list.push_back(GLX_PBUFFER_HEIGHT);
-  attrib_list.push_back(height);
-  attrib_list.push_back(0);
-  
-  pbuffer_ = glXCreatePbuffer(dpy_, fbconfig_[0], &attrib_list[0]);
-  if(!pbuffer_) {
-    LOG_ERROR("error creating offscreen rendering context: glXCreatePBuffer failed");
-    return;
-  }
-
-  context_ = glXCreateNewContext(dpy_, fbconfig_[0], GLX_RGBA_TYPE, 
-                                 glXGetCurrentContext(), True);
-  if(!context_) {
-    LOG_ERROR("error creating offscreen rendering context: glXCreateNewContext failed");
-    return;
-  }
-
-#elif defined(__APPLE__)                                   
-  CGLPixelFormatAttribute attributes[]={
-    kCGLPFAPBuffer,
-    kCGLPFAColorSize, CGLPixelFormatAttribute(8),
-    kCGLPFAAlphaSize, CGLPixelFormatAttribute(8),
-    kCGLPFADepthSize, CGLPixelFormatAttribute(24),
-    CGLPixelFormatAttribute(0)
-  };
-  GLint npix=0;
-  CGLError err=CGLChoosePixelFormat(attributes, &pix_format_, &npix);
-  if(err) {
-    LOG_ERROR("error creating offscreen rendering context. "
-               "CGLChoosePixFormat failed:" << CGLErrorString(err));
-    return;
-  }
-  // if a context exists, share resources such as shader programs and display
-  // lists.
-  err=CGLCreateContext(pix_format_, CGLGetCurrentContext(), &context_);
-  if(err) {
-    LOG_ERROR("error creating offscreen rendering context. "
-               "CGLCreateContext failed" << CGLErrorString(err));
-    return;
-  }
-  err=CGLCreatePBuffer(width, height, GL_TEXTURE_RECTANGLE_EXT, GL_RGBA, 0, 
-                       &pbuffer_);
-  if (err) {
-    LOG_ERROR("error creating offscreen rendering context. "
-               "CGLCreatePBuffer failed: " << CGLErrorString(err));
-    return;
-  }
-  GLint screen=0;
-  assert(CGLGetVirtualScreen(context_, &screen)==0);  
-  err=CGLSetPBuffer(context_, pbuffer_, 0, 0, screen);
-  if (err) {
-    LOG_ERROR("error creating offscreen rendering context. "
-               "CGLSetPBuffer failed: " << CGLErrorString(err));
-    return;
-  }
-
-#elif defined(_WIN32)
-  /*    
-  // store current windows device and rendering context
-  dev_context_ = wglGetCurrentDC();
-  context_ = wglGetCurrentContext();
-
-  int format = 0;
-  unsigned int nformats;
-  int attribList[] = 
-  {
-      WGL_RED_BITS_ARB,               32,
-      WGL_GREEN_BITS_ARB,             32,
-      WGL_BLUE_BITS_ARB,              32,
-      WGL_ALPHA_BITS_ARB,             32,
-      WGL_STENCIL_BITS_ARB,           8,
-      WGL_DEPTH_BITS_ARB,             24,
-      WGL_FLOAT_COMPONENTS_NV,        true,
-      WGL_DRAW_TO_PBUFFER_ARB,        true,
-      0,
-  };
-
-  wglChoosePixelFormatARB(dev_context_, attribList, NULL, 1, &format, &nformats);
-  if (nformats == 0)
-  {
-    LOG_ERROR("Unable to find any RGBA32 floating point pixel formats\n");
-    return;
-  }
-
-  // clear attribute list
-  //attribList[0] = 0;
-  
-  int attribs[] = {
-      WGL_RED_BITS_ARB,               8,
-      WGL_GREEN_BITS_ARB,             8,
-      WGL_BLUE_BITS_ARB,              8,
-      WGL_ALPHA_BITS_ARB,             8,
-      WGL_STENCIL_BITS_ARB,           8,
-      WGL_DEPTH_BITS_ARB,             24,
-      0,
-  };
-
-  pbuffer_ = wglCreatePbufferARB(dev_context_, format, width, height, attribs);
-  if (pbuffer_ == NULL) 
-  {
-    LOG_ERROR("Unable to create floating point pbuffer (wglCreatePbufferARB failed)\n");
-    return;
-  }
-
-  old_dev_context_ = wglGetPbufferDCARB(pbuffer_);
-  if (dev_context_ == NULL) 
-  {
-    LOG_ERROR("Unable to retrieve handle to pbuffer device context\n");
-    return;
-  }
-
-  context_ = wglCreateContext(dev_context_);
-  if (context_ == NULL) 
-  {
-    LOG_ERROR("Unable to create a rendering context for the pbuffer\n");
-    return;
-  }
-  
-  if (!wglShareLists(old_context_, context_)) 
-  {
-    LOG_ERROR("Unable to share data between rendering contexts\n");
-    return;
-  }
-*/
-#endif
-
-  // nothing failed, all is good
-  valid_=true;
-  active_=false;
-} 
-
-}}
diff --git a/modules/gfx/src/prim_list.hh b/modules/gfx/src/prim_list.hh
index 80eabe333a1b9264da03f015d1f423905aa36f56..ec790dc9590d3346edaf74ef7f51a48653c16338 100644
--- a/modules/gfx/src/prim_list.hh
+++ b/modules/gfx/src/prim_list.hh
@@ -49,9 +49,9 @@ class DLLEXPORT_OST_GFX PrimList: public GfxObj
 
   struct LineEntry {
     LineEntry(const geom::Vec3& p1, const geom::Vec3& p2, float r1, float r2, const Color& c1, const Color& c2):
-      pos1(p1), pos2(p2), rad1(r1), rad2(r2), col1(c1), col2(c2) {}
+      pos1(p1), pos2(p2), radius_1(r1), radius_2(r2), col1(c1), col2(c2) {}
     geom::Vec3 pos1, pos2;
-    float rad1, rad2;
+    float radius_1, radius_2;
     Color col1, col2;
   };
 
diff --git a/modules/gfx/src/scene.cc b/modules/gfx/src/scene.cc
index e4d37b841160760a1c130f832f0b9828abc03daa..57faf873cc5ca163c9ccb1ded63c6a0be1c55c6b 100644
--- a/modules/gfx/src/scene.cc
+++ b/modules/gfx/src/scene.cc
@@ -141,6 +141,7 @@ Scene::Scene():
   bg_grad_(),
   bg_bm_(),
   bg_tex_(),
+  ms_flag_(false),
   export_aspect_(1.0),
   show_export_aspect_(false)
 {
@@ -437,7 +438,8 @@ void Scene::InitGL(bool full)
   glClearDepth(1.0);
 
   // background
-  glClearColor(background_.Red(),background_.Green(),background_.Blue(),background_.Alpha());
+  //glClearColor(background_.Red(),background_.Green(),background_.Blue(),background_.Alpha());
+  glClearColor(background_.Red(),background_.Green(),background_.Blue(),0.0);
   fog_color_=background_;
 
   // polygon orientation setting
@@ -477,7 +479,9 @@ void Scene::InitGL(bool full)
     glDisable(GL_POINT_SMOOTH);
     glDisable(GL_POLYGON_SMOOTH);
     glEnable(GL_MULTISAMPLE);
+    ms_flag_=true;
   } else {
+    ms_flag_=false;
     glEnable(GL_LINE_SMOOTH);
     glDisable(GL_POINT_SMOOTH);
     glDisable(GL_POLYGON_SMOOTH);
@@ -579,7 +583,8 @@ void Scene::SetBackground(const Color& c)
   background_=c;
   bg_mode_=0;
   if(gl_init_) {
-    glClearColor(c.Red(),c.Green(),c.Blue(),c.Alpha());
+    //glClearColor(c.Red(),c.Green(),c.Blue(),c.Alpha());
+    glClearColor(c.Red(),c.Green(),c.Blue(),0.0);
     SetFogColor(c);
     RequestRedraw();
   }
@@ -815,7 +820,7 @@ void Scene::RenderGL()
 
   prep_blur();
 
-  if(stereo_mode_==1 || stereo_mode_==2) {
+  if(stereo_mode_==1 || stereo_mode_==2 || stereo_mode_==3) {
     render_stereo();
   } else {
     render_scene();
@@ -1488,6 +1493,8 @@ void Scene::SetStereoMode(unsigned int m)
     }
   } else if(m==2) {
     stereo_mode_=2;
+  } else if(m==3) {
+    stereo_mode_=3;
   } else {
     stereo_mode_=0;
   }
@@ -1584,11 +1591,22 @@ uint Scene::GetSelectionMode() const
   return selection_mode_;
 }
 
-bool Scene::StartOffscreenMode(unsigned int width, unsigned int height)
+bool Scene::StartOffscreenMode(unsigned int width, unsigned int height) {
+  return StartOffscreenMode(width,height,2);
+}
+
+bool Scene::StartOffscreenMode(unsigned int width, unsigned int height, int max_samples)
 {
   LOG_DEBUG("Scene: starting offscreen rendering mode " << width << "x" << height);
   if(main_offscreen_buffer_) return false;
-  main_offscreen_buffer_ = new OffscreenBuffer(width,height,OffscreenBufferFormat(),true);
+  OffscreenBufferFormat obf;
+  if(max_samples>0) {
+    obf.multisample=true;
+    obf.samples=max_samples;
+  } else {
+    obf.multisample=false;
+  }
+  main_offscreen_buffer_ = new OffscreenBuffer(width,height,obf,true);
 
   if(!main_offscreen_buffer_->IsValid()) {
     LOG_ERROR("Scene: error during offscreen buffer creation");
@@ -1642,6 +1660,12 @@ void Scene::StopOffscreenMode()
 
 void Scene::Export(const String& fname, unsigned int width,
                    unsigned int height, bool transparent)
+{
+  Export(fname,width,height,0,transparent);
+}
+
+void Scene::Export(const String& fname, unsigned int width,
+                   unsigned int height, int max_samples, bool transparent)
 {
   int d_index=fname.rfind('.');
   if (d_index==-1) {
@@ -1658,7 +1682,16 @@ void Scene::Export(const String& fname, unsigned int width,
 
   // only switch if offscreen mode is not active
   if(of_flag) {
-    if(!StartOffscreenMode(width,height)) {
+    if(max_samples<0) {
+      int msamples=0;
+#if OST_SHADER_SUPPORT_ENABLED
+      if(OST_GL_VERSION_2_0) {
+        glGetIntegerv(GL_SAMPLES, &msamples);
+      }
+#endif
+      max_samples=msamples;
+    }
+    if(!StartOffscreenMode(width,height, max_samples)) {
       return;
     }
   }
@@ -1751,6 +1784,7 @@ void Scene::ExportPov(const std::string& fname, const std::string& wdir)
 
 void Scene::Export(Exporter* ex) const
 {
+  ex->SetupTransform(this);
   ex->SceneStart(this);
   root_node_->Export(ex);
   ex->SceneEnd(this);
@@ -2039,21 +2073,26 @@ namespace {
         glTexCoord2f(1.0,1.0); glVertex2i(vp_width_,vp_height_);
         glTexCoord2f(1.0,0.0); glVertex2i(vp_width_,0);
         glEnd();
-     }
-
-     ~ViewportRenderer() {
-       glBindTexture(GL_TEXTURE_2D, 0);
-       glDisable(GL_TEXTURE_2D);
-       glMatrixMode(GL_PROJECTION);
-       glPopMatrix();
-       glMatrixMode(GL_MODELVIEW);
-       glPopMatrix();
-       glPopClientAttrib();
-       glPopAttrib();
+      }
+
+      ~ViewportRenderer() {
+        glBindTexture(GL_TEXTURE_2D, 0);
+        glDisable(GL_TEXTURE_2D);
+        glMatrixMode(GL_PROJECTION);
+        glPopMatrix();
+        glMatrixMode(GL_MODELVIEW);
+        glPopMatrix();
+        glPopClientAttrib();
+        glPopAttrib();
+#if defined(OST_GL_VERSION_2_0)
+        if(Scene::Instance().HasMultisample()) {
+          glEnable(GL_MULTISAMPLE);
+        }
+#endif
 #if OST_SHADER_SUPPORT_ENABLED
-       Shader::Instance().PopProgram();
+        Shader::Instance().PopProgram();
 #endif
-     }
+      }
   };
 }
 
@@ -2205,6 +2244,8 @@ void Scene::render_glow()
 #endif  
 }
 
+#undef far
+#undef near
 namespace {
   geom::Mat4 frustum(float left, float right, float bot, float top, float near, float far) {
     float rl=1.0/(right-left);
@@ -2354,71 +2395,94 @@ void Scene::render_stereo()
   glPushMatrix();
   glLoadIdentity();
 
-  if(stereo_mode_==2) {
-    // draw interlaced lines in stencil buffer
-    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-    glLineWidth(1.0);
-    glEnable(GL_STENCIL_TEST);
-    glStencilMask(0x1);
-    glClearStencil(0x0);
-    glClear(GL_STENCIL_BUFFER_BIT);
-    glStencilFunc(GL_ALWAYS,0x1,0x1);
-    glStencilOp(GL_REPLACE,GL_REPLACE,GL_REPLACE);
-    glBegin(GL_LINES);
-    glColor3f(1.0,1.0,1.0);
-    for(unsigned int i=0;i<vp_height_;i+=2) {
-      glVertex2i(0,i);
-      glVertex2i(vp_width_-1,i);
-    } 
+  if(stereo_mode_==3) {
+#if OST_SHADER_SUPPORT_ENABLED
+    // anaglyph shader
+    Shader::Instance().PushProgram();
+    Shader::Instance().Activate("anaglyph");
+    GLuint cpr=Shader::Instance().GetCurrentProgram();
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, stereo_inverted_ ? scene_right_tex_ : scene_left_tex_);
+    glUniform1i(glGetUniformLocation(cpr,"left_scene"),0);
+    glActiveTexture(GL_TEXTURE1);
+    glBindTexture(GL_TEXTURE_2D, stereo_inverted_ ? scene_left_tex_ : scene_right_tex_);
+    glUniform1i(glGetUniformLocation(cpr,"right_scene"),1);
+    glActiveTexture(GL_TEXTURE0);
+    // draw screen quad
+    glColor3f(1.0,0.0,1.0);
+    glBegin(GL_QUADS);
+    glTexCoord2f(0.0,0.0); glVertex2i(0,0);
+    glTexCoord2f(0.0,1.0); glVertex2i(0,vp_height_);
+    glTexCoord2f(1.0,1.0); glVertex2i(vp_width_,vp_height_);
+    glTexCoord2f(1.0,0.0); glVertex2i(vp_width_,0);
     glEnd();
-    
-    glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP);
-  }
+    Shader::Instance().PopProgram();
+#endif
+  } else {
+    if(stereo_mode_==2) {
+      // draw interlaced lines in stencil buffer
+      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+      glLineWidth(1.0);
+      glEnable(GL_STENCIL_TEST);
+      glStencilMask(0x1);
+      glClearStencil(0x0);
+      glClear(GL_STENCIL_BUFFER_BIT);
+      glStencilFunc(GL_ALWAYS,0x1,0x1);
+      glStencilOp(GL_REPLACE,GL_REPLACE,GL_REPLACE);
+      glBegin(GL_LINES);
+      glColor3f(1.0,1.0,1.0);
+      for(unsigned int i=0;i<vp_height_;i+=2) {
+        glVertex2i(0,i);
+        glVertex2i(vp_width_-1,i);
+      } 
+      glEnd();
+      glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP);
+    }
 
-  // right eye
-  if(stereo_mode_==1) {
-    glDrawBuffer(GL_BACK_RIGHT);
-    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-  } else if(stereo_mode_==2) {
-    glStencilFunc(GL_EQUAL,0x0,0x1);
-  }
+    // right eye
+    if(stereo_mode_==1) {
+      glDrawBuffer(GL_BACK_RIGHT);
+      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    } else if(stereo_mode_==2) {
+      glStencilFunc(GL_EQUAL,0x0,0x1);
+    } 
 #if OST_SHADER_SUPPORT_ENABLED
-  if(OST_GL_VERSION_2_0) {
-    glActiveTexture(GL_TEXTURE0);
-  }
+    if(OST_GL_VERSION_2_0) {
+      glActiveTexture(GL_TEXTURE0);
+    }
 #endif
-  glBindTexture(GL_TEXTURE_2D, stereo_inverted_ ? scene_left_tex_ : scene_right_tex_);
-  // draw
-  glColor3f(1.0,0.0,1.0);
-  glBegin(GL_QUADS);
-  glTexCoord2f(0.0,0.0); glVertex2i(0,0);
-  glTexCoord2f(0.0,1.0); glVertex2i(0,vp_height_);
-  glTexCoord2f(1.0,1.0); glVertex2i(vp_width_,vp_height_);
-  glTexCoord2f(1.0,0.0); glVertex2i(vp_width_,0);
-  glEnd();
+    glBindTexture(GL_TEXTURE_2D, stereo_inverted_ ? scene_left_tex_ : scene_right_tex_);
+    // draw
+    glColor3f(1.0,0.0,1.0);
+    glBegin(GL_QUADS);
+    glTexCoord2f(0.0,0.0); glVertex2i(0,0);
+    glTexCoord2f(0.0,1.0); glVertex2i(0,vp_height_);
+    glTexCoord2f(1.0,1.0); glVertex2i(vp_width_,vp_height_);
+    glTexCoord2f(1.0,0.0); glVertex2i(vp_width_,0);
+    glEnd();
 
-  // left eye
-  if(stereo_mode_==1) {
-    glDrawBuffer(GL_BACK_LEFT);
-    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-  } else if(stereo_mode_==2) {
-    glStencilFunc(GL_EQUAL,0x1,0x1);
-  }
+    // left eye
+    if(stereo_mode_==1) {
+      glDrawBuffer(GL_BACK_LEFT);
+      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    } else if(stereo_mode_==2) {
+      glStencilFunc(GL_EQUAL,0x1,0x1);
+    }
 #if OST_SHADER_SUPPORT_ENABLED
-  if(OST_GL_VERSION_2_0) {
-    glActiveTexture(GL_TEXTURE0);
-  }
+    if(OST_GL_VERSION_2_0) {
+      glActiveTexture(GL_TEXTURE0);
+    }
 #endif
-  glBindTexture(GL_TEXTURE_2D, stereo_inverted_ ? scene_right_tex_ : scene_left_tex_);
-  // draw
-  glColor3f(1.0,0.0,1.0);
-  glBegin(GL_QUADS);
-  glTexCoord2f(0.0,0.0); glVertex2i(0,0);
-  glTexCoord2f(0.0,1.0); glVertex2i(0,vp_height_);
-  glTexCoord2f(1.0,1.0); glVertex2i(vp_width_,vp_height_);
-  glTexCoord2f(1.0,0.0); glVertex2i(vp_width_,0);
-  glEnd();
-  
+    glBindTexture(GL_TEXTURE_2D, stereo_inverted_ ? scene_right_tex_ : scene_left_tex_);
+    // draw
+    glColor3f(1.0,0.0,1.0);
+    glBegin(GL_QUADS);
+    glTexCoord2f(0.0,0.0); glVertex2i(0,0);
+    glTexCoord2f(0.0,1.0); glVertex2i(0,vp_height_);
+    glTexCoord2f(1.0,1.0); glVertex2i(vp_width_,vp_height_);
+    glTexCoord2f(1.0,0.0); glVertex2i(vp_width_,0);
+    glEnd();
+  }
   // restore settings
   glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 0, 0, 0);
   glBindTexture(GL_TEXTURE_2D, 0);
@@ -2429,6 +2493,11 @@ void Scene::render_stereo()
   glPopMatrix();
   glPopClientAttrib();
   glPopAttrib();
+#if defined(OST_GL_VERSION_2_0)
+  if(HasMultisample()) {
+    glEnable(GL_MULTISAMPLE);
+  }
+#endif
 #if OST_SHADER_SUPPORT_ENABLED
   Shader::Instance().PopProgram();
 #endif
diff --git a/modules/gfx/src/scene.hh b/modules/gfx/src/scene.hh
index a8a9afbe1a8170083358694a2be1b06da7724936..4b9483666a18a62929e87b0c3bf3213f4b702a66 100644
--- a/modules/gfx/src/scene.hh
+++ b/modules/gfx/src/scene.hh
@@ -294,6 +294,10 @@ class DLLEXPORT_OST_GFX Scene {
   /// dimensions here are ignored
   void Export(const String& fname, unsigned int w,
               unsigned int h, bool transparent=false);
+  /// \brief export into bitmap, using multisample anti-aliasing
+  /// \ref Scene::StartOfffscreenMode(unsigned int, unsigned int, int) for more detail
+  void Export(const String& fname, unsigned int w,
+              unsigned int h, int max_samples, bool transparent=false);
 
   /// \brief export snapshot of current scene
   void Export(const String& fname, bool transparent=false);
@@ -465,9 +469,18 @@ class DLLEXPORT_OST_GFX Scene {
     During batch mode, this is the only way to get meaningful
     functionality with the gfx module
 
-    returns true upon success and false upon failure
+    Returns true upon success and false upon failure
+
+    You can ask for multisampling to be enabled by giving the
+    max_samples a value larger than zero; in this case, the framebuffer
+    with at most this many samplebuffers will be used. The recommended
+    value here is 4; going to 8 or 16 may give you higher export times
+    with usually no marked increase in quality.
+
   */
+  bool StartOffscreenMode(unsigned int w, unsigned int h, int max_samples);
   bool StartOffscreenMode(unsigned int w, unsigned int h);
+
   /// \brief stops offline rendering in interactive mode
   void StopOffscreenMode();
 
@@ -500,6 +513,7 @@ class DLLEXPORT_OST_GFX Scene {
   void SetShowExportAspect(bool f);
   bool GetShowExportAspect() const {return show_export_aspect_;}
 
+  bool HasMultisample() const {return ms_flag_;}
 protected:
   friend class GfxObj; 
   friend class GfxNode;
@@ -590,6 +604,8 @@ private:
   Bitmap bg_bm_;
   unsigned int bg_tex_;
   
+  bool ms_flag_; // multisample flag
+
   float export_aspect_; 
   bool show_export_aspect_;
 
diff --git a/modules/gfx/src/shader.cc b/modules/gfx/src/shader.cc
index 3ed15cac334785fbb45e4d1b63fb91d62c70f599..f514aeebf3e0a401da2bfde639a5ecc6f66fcfaa 100644
--- a/modules/gfx/src/shader.cc
+++ b/modules/gfx/src/shader.cc
@@ -176,7 +176,8 @@ void Shader::Setup()
     {"material_phong.glsl", GL_FRAGMENT_SHADER},
     {"material_hemi.glsl", GL_FRAGMENT_SHADER},
     {"material_toon1.glsl", GL_FRAGMENT_SHADER},
-    {"material_toon2.glsl", GL_FRAGMENT_SHADER}
+    {"material_toon2.glsl", GL_FRAGMENT_SHADER},
+    {"anaglyph_fs.glsl", GL_FRAGMENT_SHADER}
     //////////////////////////////////////////////////////////////////
   };
 
@@ -287,6 +288,9 @@ void Shader::Setup()
   Link("test_tex",
        shader_code_map["fraglight_vs.glsl"],
        shader_code_map["test_tex_fs.glsl"]);
+  Link("anaglyph",
+       shader_code_map["quadpp_vs.glsl"],
+       shader_code_map["anaglyph_fs.glsl"]);
 
   valid_=true;
 }
diff --git a/modules/gfx/src/shader/anaglyph_fs.glsl b/modules/gfx/src/shader/anaglyph_fs.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..85f334882d32139df19110e95ae44a3aba30e797
--- /dev/null
+++ b/modules/gfx/src/shader/anaglyph_fs.glsl
@@ -0,0 +1,12 @@
+uniform sampler2D left_scene;
+uniform sampler2D right_scene;
+
+void main()
+{
+  vec4 left_color=texture2D(left_scene,gl_TexCoord[0].xy);
+  vec4 right_color=texture2D(right_scene,gl_TexCoord[0].xy);
+  gl_FragColor.a = left_color.a+right_color.a;
+  gl_FragColor.r=pow(0.7*left_color.g+0.3*left_color.b,1.5);
+  gl_FragColor.gb=right_color.gb;
+}
+
diff --git a/modules/gfx/src/shader/basic_fs.glsl b/modules/gfx/src/shader/basic_fs.glsl
index 9856cd3a47445b3ea94d57e9e00ea34c90ec2474..c0a9d6f084f88fc66f8844d8a595edcc5c4ea10b 100644
--- a/modules/gfx/src/shader/basic_fs.glsl
+++ b/modules/gfx/src/shader/basic_fs.glsl
@@ -1,7 +1,12 @@
 uniform bool fog_flag;
+uniform float clip_offset;
 
 void main()
 {
+  if(gl_FragCoord.z<clip_offset) {
+    discard;
+  }
+
   float fog = fog_flag ? clamp((gl_Fog.end-gl_FogFragCoord) * gl_Fog.scale, 0.0, 1.0) : 1.0;
   gl_FragColor.rgb = mix(gl_Fog.color.rgb, gl_Color.rgb, fog);
   gl_FragColor.a = gl_Color.a;
diff --git a/modules/gfx/src/shader/dumpnorm_fs.glsl b/modules/gfx/src/shader/dumpnorm_fs.glsl
index 09bee99284fd774c4d5a010f10b31c603d104aa9..926622a7dc2085624f570c3388a55f9277a64a8d 100644
--- a/modules/gfx/src/shader/dumpnorm_fs.glsl
+++ b/modules/gfx/src/shader/dumpnorm_fs.glsl
@@ -1,5 +1,10 @@
+uniform float clip_offset;
+
 void main()
 {
+  if(gl_FragCoord.z<clip_offset) {
+    discard;
+  }
   gl_FragColor.rgb=normalize(gl_TexCoord[0]).stp*0.5+0.5;
 }
 
diff --git a/modules/gfx/src/shader/fraglight_fs.glsl b/modules/gfx/src/shader/fraglight_fs.glsl
index 9baa64b043a516b1293a66beaaf684e1627600b9..b8c7b6b21ded3428e6907d06d27b83d14c8f206b 100644
--- a/modules/gfx/src/shader/fraglight_fs.glsl
+++ b/modules/gfx/src/shader/fraglight_fs.glsl
@@ -5,9 +5,13 @@ uniform sampler2D depth_map;
 uniform int depth_mode;
 uniform bool tex_flag;
 uniform sampler2D tex_map;
+uniform float clip_offset;
 
 void main()
 {
+  if(gl_FragCoord.z<clip_offset) {
+    discard;
+  }
   vec4 color = gl_Color;
 
   if(tex_flag) {
diff --git a/modules/gfx/src/surface.cc b/modules/gfx/src/surface.cc
index 0500e72b1482ae2ea32b7cd80fd3ee794a96e5bd..390f2d27a6453d10e01cbd3aee31373e9cdfdf98 100644
--- a/modules/gfx/src/surface.cc
+++ b/modules/gfx/src/surface.cc
@@ -152,7 +152,7 @@ geom::AlignedCuboid Surface::GetBoundingBox(bool use_tf) const
                     -std::numeric_limits<float>::max());
     
     std::vector<mol::SurfaceVertexID> svid_list = sh_.GetVertexIDList();
-    if(svid_list.size()>0) {
+    if(! svid_list.empty()) {
       for(std::vector<mol::SurfaceVertexID>::const_iterator it=svid_list.begin();
           it!=svid_list.end();++it) {
         geom::Vec3 pos = sh_.GetVertex(*it).position;
diff --git a/modules/gfx/src/texture.hh b/modules/gfx/src/texture.hh
index dd71404feb5f946a0965416546e7f57b42467fc3..aa3fec45f8f0a5d288d977dd290e40210a9c5253 100644
--- a/modules/gfx/src/texture.hh
+++ b/modules/gfx/src/texture.hh
@@ -32,7 +32,7 @@
 
 namespace ost { namespace gfx {
 
-class Bitmap;
+struct Bitmap;
 
 class Texture
 {
diff --git a/modules/gfx/src/vertex_array.cc b/modules/gfx/src/vertex_array.cc
index 155417b65e2cb2080bd6a5230ee30b936c3f5134..520e0d0e9c95f640c3578b99af95090e7f4aabec 100644
--- a/modules/gfx/src/vertex_array.cc
+++ b/modules/gfx/src/vertex_array.cc
@@ -58,21 +58,6 @@ static const int VA_AMBIENT_BUFFER=4;
 static const int VA_NORMAL_BUFFER=5;
 static const int VA_COLOR_BUFFER=6;
 
-IndexedVertexArray::Entry::Entry()
-{
-  v[0]=0.0; v[1]=0.0; v[2]=0.0;
-  n[0]=0.0; n[1]=0.0; n[2]=1.0;
-  c[0]=0.0; c[1]=0.0; c[2]=0.0; c[3]=0.0;
-  t[0]=0.0; t[1]=0.0;
-}
-
-  IndexedVertexArray::Entry::Entry(const Vec3& vv, const Vec3& nn, const Color& cc, const geom::Vec2& tt)
-{
-  v[0]=vv[0]; v[1]=vv[1]; v[2]=vv[2];
-  n[0]=nn[0]; n[1]=nn[1]; n[2]=nn[2];
-  c[0]=cc[0]; c[1]=cc[1]; c[2]=cc[2]; c[3]=cc[3];
-  t[0]=tt[0]; t[1]=tt[1];
-}
 
 
 IndexedVertexArray::IndexedVertexArray()
@@ -141,15 +126,6 @@ void IndexedVertexArray::SetOutlineMaterial(const Material& m)
 void IndexedVertexArray::SetOutlineExpandFactor(float f) { outline_exp_factor_=f;}
 void IndexedVertexArray::SetOutlineExpandColor(const Color& c) {outline_exp_color_=c;}
 
-VertexID IndexedVertexArray::Add(const Vec3& vert, 
-                                 const Vec3& norm,
-                                 const Color& col,
-                                 const Vec2& texc) 
-{
-  dirty_=true;
-  entry_list_.push_back(Entry(vert,norm,col,texc));
-  return entry_list_.size()-1;
-}
 
 unsigned int IndexedVertexArray::GetVertexCount() const
 {
@@ -222,6 +198,7 @@ void IndexedVertexArray::AddSphere(const SpherePrim& prim, unsigned int detail)
 
   // use prebuild list of vertices which define given unit sphere
   std::vector<VertexID> vid_table;
+  vid_table.reserve(se.vlist.size());
   for(std::vector<Vec3>::const_iterator it=se.vlist.begin();it!=se.vlist.end();++it) {
     VertexID id = Add(prim.radius*(*it)+prim.position,(*it),prim.color);
     vid_table.push_back(id);
@@ -315,82 +292,20 @@ void IndexedVertexArray::AddCylinder(const CylinderPrim& prim, unsigned int deta
   }
 }
 
-Vec3 IndexedVertexArray::GetVert(VertexID id) const
-{
-  Vec3 nrvo;
-  if(id>=entry_list_.size()) return nrvo;
-  nrvo = Vec3(entry_list_[id].v);
-  return nrvo;
-} 
-
-void IndexedVertexArray::SetVert(VertexID id, const Vec3& v) 
-{
-  if(id>=entry_list_.size()) return;
-  entry_list_[id].v[0]=v[0];
-  entry_list_[id].v[1]=v[1];
-  entry_list_[id].v[2]=v[2];
-}
-
-Vec3 IndexedVertexArray::GetNormal(VertexID id) const
-{
-  Vec3 nrvo;
-  if(id>=entry_list_.size()) return nrvo;
-  nrvo = Vec3(entry_list_[id].n);
-  return nrvo;
-} 
-
-void IndexedVertexArray::SetNormal(VertexID id, const Vec3& n) 
-{
-  if(id>=entry_list_.size()) return;
-  entry_list_[id].n[0]=n[0];
-  entry_list_[id].n[1]=n[1];
-  entry_list_[id].n[2]=n[2];
-}
-
-Color IndexedVertexArray::GetColor(VertexID id) const
-{
-  Color nrvo;
-  if(id>=entry_list_.size()) return nrvo;
-  nrvo = Color(entry_list_[id].c[0],
-               entry_list_[id].c[1],
-               entry_list_[id].c[2],
-               entry_list_[id].c[3]);
-  return nrvo;
-} 
-
-void IndexedVertexArray::SetColor(VertexID id, const Color& c) 
-{
-  if(id>=entry_list_.size()) return;
-  entry_list_[id].c[0]=c[0];
-  entry_list_[id].c[1]=c[1];
-  entry_list_[id].c[2]=c[2];
-  entry_list_[id].c[3]=c[3];
-}
-
-Vec2 IndexedVertexArray::GetTexCoord(VertexID id) const
-{
-  Vec2 nrvo;
-  if(id>=entry_list_.size()) return nrvo;
-  nrvo = Vec2(entry_list_[id].t);
-  return nrvo;
-} 
-
-void IndexedVertexArray::SetTexCoord(VertexID id, const Vec2& t) 
-{
-  if(id>=entry_list_.size()) return;
-  entry_list_[id].t[0]=t[0];
-  entry_list_[id].t[1]=t[1];
-}
-
 void IndexedVertexArray::SetOpacity(float o)
 {
   o=std::max(0.0f,std::min(1.0f,o));
+  if (std::abs(opacity_-o)<1e-6) {
+    opacity_=o;
+    return;
+  }
   // this should really just set a value in the shader... 
   // but we need to support the fixed function pipeline as well
   for(EntryList::iterator it=entry_list_.begin();it!=entry_list_.end();++it) {
     it->c[3]=o;
   }
   opacity_=o;
+  LOG_ERROR("new opacity (slow)" << opacity_);
   FlagRefresh();
 }
 
@@ -431,7 +346,9 @@ void IndexedVertexArray::RenderGL()
   
   glPushAttrib(GL_ALL_ATTRIB_BITS);
   glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
-  
+
+  set_clip_offset(clip_offset_);
+
   if(use_tex_) {
     glEnable(GL_TEXTURE_2D);
   } else {
@@ -493,7 +410,7 @@ void IndexedVertexArray::RenderGL()
     } else {
       glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
     }
-    if(cull_face_ && !solid_) {
+    if(cull_face_ && !solid_ && clip_offset_<=0.0) {
       glEnable(GL_CULL_FACE);
     } else { 
       glDisable(GL_CULL_FACE); 
@@ -537,6 +454,7 @@ void IndexedVertexArray::RenderGL()
       glUniform4f(glGetUniformLocation(Shader::Instance().GetCurrentProgram(),"color"),
                   outline_exp_color_[0],outline_exp_color_[1],
                   outline_exp_color_[2],opacity_);
+      set_clip_offset(clip_offset_);
       glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
       draw_ltq(use_buff);
 
@@ -699,7 +617,9 @@ void IndexedVertexArray::Reset()
   outline_exp_factor_=0.1;
   outline_exp_color_=Color(0,0,0);
   solid_=false;
+  #undef RGB
   solid_color_=RGB(1,1,1);
+  clip_offset_=0.0;
   draw_normals_=false;
   use_tex_=false;
 }
@@ -1098,6 +1018,7 @@ void IndexedVertexArray::copy(const IndexedVertexArray& va)
   outline_exp_color_=va.outline_exp_color_;
   solid_=va.solid_;
   solid_color_=va.solid_color_;
+  clip_offset_=va.clip_offset_;
   draw_normals_=va.draw_normals_;
   use_tex_=va.use_tex_;
 }
@@ -1253,10 +1174,12 @@ void IndexedVertexArray::draw_ltq(bool use_buff)
     float aspect=Scene::Instance().GetAspect();
     float rh=2.0*fabs(tan(fov)*znear);
     float rw=rh*aspect;
-    float rz=-znear-0.1;
+    float rz=-(znear+clip_offset_)-0.05;
 
     glDisable(GL_LIGHTING);
-  
+
+    set_clip_offset(0.0);
+
     glBegin(GL_TRIANGLE_STRIP);
     glColor3fv(solid_color_);
     glNormal3f(0,0,1);
@@ -1265,6 +1188,9 @@ void IndexedVertexArray::draw_ltq(bool use_buff)
     glVertex3f(-rw,rh,rz);
     glVertex3f(rw,rh,rz);
     glEnd();
+
+    set_clip_offset(clip_offset_);
+
     glDisable(GL_STENCIL_TEST);
     glPopMatrix();
   }
@@ -1402,6 +1328,7 @@ void IndexedVertexArray::draw_aalines()
   float hwr = 0.5*w+r;
 
   AALineList line_list;
+  line_list.reserve(line_index_list_.size() >> 1);
   for(unsigned int i=0;i<line_index_list_.size();i+=2) {
     Entry& ve0 = entry_list_[line_index_list_[i]];
     Entry& ve1 = entry_list_[line_index_list_[i+1]];
@@ -1486,4 +1413,16 @@ geom::AlignedCuboid IndexedVertexArray::GetBoundingBox() const
   }
 }
 
+void IndexedVertexArray::set_clip_offset(float o)
+{
+#if OST_SHADER_SUPPORT_ENABLED
+  float n=Scene::Instance().GetNear();
+  float f=Scene::Instance().GetFar();
+  float z=n+o;
+  float t=(f*(-n+o)+n*(n+o))/((f-n)*(n+o));
+  t=(t+1.0)*0.5;
+  glUniform1f(glGetUniformLocation(Shader::Instance().GetCurrentProgram(),"clip_offset"),t);
+#endif
+}
+
 }} // ns
diff --git a/modules/gfx/src/vertex_array.hh b/modules/gfx/src/vertex_array.hh
index 539d871b775c6219a397c0ca4795a23baa8c402b..ac24ef85a01f8e6b0680af7d47729a7e154c4725 100644
--- a/modules/gfx/src/vertex_array.hh
+++ b/modules/gfx/src/vertex_array.hh
@@ -49,9 +49,23 @@ typedef unsigned int TriID;
 typedef unsigned int QuadID;
 class DLLEXPORT_OST_GFX IndexedVertexArray {
  public:
-  struct Entry {
-    Entry();
-    Entry(const geom::Vec3& vv, const geom::Vec3& nn, const Color& cc, const geom::Vec2& tt);
+  struct DLLEXPORT Entry {
+    Entry()
+    {
+      v[0]=0.0; v[1]=0.0; v[2]=0.0;
+      n[0]=0.0; n[1]=0.0; n[2]=1.0;
+      c[0]=0.0; c[1]=0.0; c[2]=0.0; c[3]=0.0;
+      t[0]=0.0; t[1]=0.0;
+    }
+
+    Entry(const geom::Vec3& vv, const geom::Vec3& nn, const Color& cc, 
+          const geom::Vec2& tt)
+    {
+      v[0]=vv[0]; v[1]=vv[1]; v[2]=vv[2];
+      n[0]=nn[0]; n[1]=nn[1]; n[2]=nn[2];
+      c[0]=cc[0]; c[1]=cc[1]; c[2]=cc[2]; c[3]=cc[3];
+      t[0]=tt[0]; t[1]=tt[1];
+    }
     float t[2];
     float c[4];
     float n[3];
@@ -120,10 +134,18 @@ class DLLEXPORT_OST_GFX IndexedVertexArray {
   void SetSolid(bool f) {solid_=f;}
   bool GetSolid() const {return solid_;}
   void SetSolidColor(const Color& c) {solid_color_=c;}
-  bool GetSolidcolor() const {return solid_color_;}
+  Color GetSolidcolor() const {return solid_color_;}
+  void SetClipOffset(float f) {clip_offset_=f;}
+  float GetClipOffset() const {return clip_offset_;}
 
   // vertex, normal, color and texcoord (T2F_C4F_N3F_V3F)
-  VertexID Add(const geom::Vec3& vert, const geom::Vec3& norm, const Color& col, const geom::Vec2& tex=geom::Vec2());
+  VertexID Add(const geom::Vec3& vert, const geom::Vec3& norm, 
+               const Color& col, const geom::Vec2& texc=geom::Vec2()) {
+    dirty_=true;
+    entry_list_.push_back(Entry(vert,norm,col,texc));
+    entry_list_.back().c[3] = opacity_;
+    return entry_list_.size()-1;
+  }
 
   unsigned int GetVertexCount() const;
   void DumpVertices() const;
@@ -148,18 +170,6 @@ class DLLEXPORT_OST_GFX IndexedVertexArray {
 
   void AddCylinder(const CylinderPrim& prim, unsigned int detail,bool cap=false);
 
-  geom::Vec3 GetVert(VertexID id) const;
-  void SetVert(VertexID id, const geom::Vec3& vert);
-
-  geom::Vec3 GetNormal(VertexID id) const;
-  void SetNormal(VertexID id, const geom::Vec3& norm);
-
-  Color GetColor(VertexID id) const;
-  void SetColor(VertexID id, const Color& col);
-
-  geom::Vec2 GetTexCoord(VertexID id) const;
-  void SetTexCoord(VertexID id, const geom::Vec2& tex);
-
   void SetOpacity(float o);
 
   // OpenGL rendering call
@@ -208,6 +218,72 @@ class DLLEXPORT_OST_GFX IndexedVertexArray {
   /// return min/max of vertex entries - this call is not cached!
   geom::AlignedCuboid GetBoundingBox() const;
 
+  geom::Vec3 GetVert(VertexID id) const
+  {
+    geom::Vec3 nrvo;
+    if(id>=entry_list_.size()) return nrvo;
+    nrvo = geom::Vec3(entry_list_[id].v);
+    return nrvo;
+  } 
+
+  void SetVert(VertexID id, const geom::Vec3& v) 
+  {
+    if(id>=entry_list_.size()) return;
+    entry_list_[id].v[0]=v[0];
+    entry_list_[id].v[1]=v[1];
+    entry_list_[id].v[2]=v[2];
+  }
+
+  geom::Vec3 GetNormal(VertexID id) const
+  {
+    geom::Vec3 nrvo;
+    if(id>=entry_list_.size()) return nrvo;
+    nrvo = geom::Vec3(entry_list_[id].n);
+    return nrvo;
+  } 
+
+  void SetNormal(VertexID id, const geom::Vec3& n) 
+  {
+    if(id>=entry_list_.size()) return;
+    entry_list_[id].n[0]=n[0];
+    entry_list_[id].n[1]=n[1];
+    entry_list_[id].n[2]=n[2];
+  }
+
+  Color GetColor(VertexID id) const
+  {
+    Color nrvo;
+    if(id>=entry_list_.size()) return nrvo;
+    nrvo = Color(entry_list_[id].c[0],
+                entry_list_[id].c[1],
+                entry_list_[id].c[2],
+                entry_list_[id].c[3]);
+    return nrvo;
+  } 
+
+  void SetColor(VertexID id, const Color& c) 
+  {
+    if(id>=entry_list_.size()) return;
+    entry_list_[id].c[0]=c[0];
+    entry_list_[id].c[1]=c[1];
+    entry_list_[id].c[2]=c[2];
+    entry_list_[id].c[3]=opacity_;
+  }
+
+  geom::Vec2 GetTexCoord(VertexID id) const
+  {
+    geom::Vec2 nrvo;
+    if(id>=entry_list_.size()) return nrvo;
+    nrvo = geom::Vec2(entry_list_[id].t);
+    return nrvo;
+  } 
+
+  void SetTexCoord(VertexID id, const geom::Vec2& t) 
+  {
+    if(id>=entry_list_.size()) return;
+    entry_list_[id].t[0]=t[0];
+    entry_list_[id].t[1]=t[1];
+  }
  private:
   bool initialized_;
   
@@ -240,6 +316,7 @@ class DLLEXPORT_OST_GFX IndexedVertexArray {
   Color outline_exp_color_;
   bool solid_;
   Color solid_color_;
+  float clip_offset_;
   bool draw_normals_;
 
   bool use_tex_;
@@ -253,6 +330,7 @@ class DLLEXPORT_OST_GFX IndexedVertexArray {
   void draw_p(bool use_buff);
   void draw_aalines();
   void draw_line_halo(bool use_buff);
+  void set_clip_offset(float);
 };
 
 }} // ns
diff --git a/modules/gfx/tests/test_color.cc b/modules/gfx/tests/test_color.cc
index 88856fb1762fa5b636fc2f4ec449ea735865c62f..26784b4cc6bbac872aa3b4703564b1b3be8aeb95 100644
--- a/modules/gfx/tests/test_color.cc
+++ b/modules/gfx/tests/test_color.cc
@@ -36,13 +36,13 @@ static const float tolerance=1e-4;
 
 namespace {
   bool compare_colors(const Color& c1, const Color& c2, float tol=1e-6) {
-    return std::fabs(c1.GetRed()-c2.GetRed()<tol) &&
-      std::fabs(c1.GetGreen()-c2.GetGreen()<tol) &&
-      std::fabs(c1.GetBlue()-c2.GetBlue()<tol) &&
-      std::fabs(c1.GetAlpha()-c2.GetAlpha()<tol) &&
-      std::fabs(c1.GetHue()-c2.GetHue()<tol) &&
-      std::fabs(c1.GetSat()-c2.GetSat()<tol) &&
-      std::fabs(c1.GetVal()-c2.GetVal()<tol);
+    return std::abs<float>(c1.GetRed()-c2.GetRed()<tol) &&
+      std::abs<float>(c1.GetGreen()-c2.GetGreen()<tol) &&
+      std::abs<float>(c1.GetBlue()-c2.GetBlue()<tol) &&
+      std::abs<float>(c1.GetAlpha()-c2.GetAlpha()<tol) &&
+      std::abs<float>(c1.GetHue()-c2.GetHue()<tol) &&
+      std::abs<float>(c1.GetSat()-c2.GetSat()<tol) &&
+      std::abs<float>(c1.GetVal()-c2.GetVal()<tol);
   }
 }
 
diff --git a/modules/gui/pymod/CMakeLists.txt b/modules/gui/pymod/CMakeLists.txt
index 4ac7f7cfe75a5fe6a0e843a4389e64e02e8228ed..522f664438ced8d36172d6fb1ef3af4f3c1f39f6 100644
--- a/modules/gui/pymod/CMakeLists.txt
+++ b/modules/gui/pymod/CMakeLists.txt
@@ -65,6 +65,7 @@ query_editor.py
 )
 if (ENABLE_IMG)
   list(APPEND OST_GUI_PYMOD_SOURCES
+  data_viewer_proxy.cc
   export_data_viewer.cc
   export_overlay.cc
   export_overlay_manager.cc
@@ -86,6 +87,7 @@ set(OST_GUI_PYMOD_MODULES
   traj.py
   helpwidget.py
   table.py
+  gosty_startup.py
 )
 
 set(OST_GUI_PYMOD_DNG_MODULES
diff --git a/modules/gui/pymod/data_viewer_proxy.cc b/modules/gui/pymod/data_viewer_proxy.cc
new file mode 100644
index 0000000000000000000000000000000000000000..9ee1c099aff32fdf1be85223af69f5bd4c89499e
--- /dev/null
+++ b/modules/gui/pymod/data_viewer_proxy.cc
@@ -0,0 +1,200 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2010 by the OpenStructure authors
+// Copyright (C) 2003-2010 by the IPLT authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+
+/*
+  Authors: Ansgar Philippsen, Andreas Schenk
+*/
+
+#include <ost/message.hh>
+
+#include "data_viewer_proxy.hh"
+
+namespace ost { namespace img { namespace gui {
+
+DataViewerProxy::DataViewerProxy(DataViewer* v):
+  viewer_ptr_(v)
+{
+}
+
+
+NormalizerPtr DataViewerProxy::GetNormalizer() const
+{
+  return viewer()->GetNormalizer();
+}
+
+void DataViewerProxy::Renormalize()
+{
+  viewer()->Renormalize();
+}
+
+void DataViewerProxy::UpdateView()
+{
+  viewer()->UpdateView();
+}
+
+void DataViewerProxy::Recenter()
+{
+  viewer()->Recenter();
+}
+
+Extent DataViewerProxy::GetSelection() const
+{
+  return viewer()->GetSelection();
+}
+void DataViewerProxy::SetSelection(const Extent& selection)
+{
+  viewer()->SetSelection(selection);
+}
+
+void DataViewerProxy::SetSlab(int slab)
+{
+  viewer()->SetSlab(slab);
+}
+
+int DataViewerProxy::GetSlab() const
+{
+  return viewer()->GetSlab();
+}
+
+void DataViewerProxy::SetZoomScale(Real zoomscale)
+{
+  viewer()->SetZoomScale(zoomscale);
+}
+
+Real DataViewerProxy::GetZoomScale() const
+{
+  return viewer()->GetZoomScale();
+}
+
+void DataViewerProxy::SetViewerMin(Real min)
+{
+  viewer()->SetViewerMin(min);
+}
+
+Real DataViewerProxy::GetViewerMin() const
+{
+  return viewer()->GetViewerMin();
+}
+
+void DataViewerProxy::SetViewerMax(Real max)
+{
+  viewer()->SetViewerMax(max);
+}
+
+Real DataViewerProxy::GetViewerMax() const
+{
+  return viewer()->GetViewerMax();
+}
+
+void DataViewerProxy::SetGamma(Real gamma)
+{
+  viewer()->SetGamma(gamma);
+}
+
+Real DataViewerProxy::GetGamma() const
+{
+  return viewer()->GetGamma();
+}
+
+void DataViewerProxy::SetInvert(bool invert)
+{
+  viewer()->SetInvert(invert);
+}
+
+bool DataViewerProxy::GetInvert() const
+{
+  return viewer()->GetInvert();
+}
+
+void DataViewerProxy::SetOffset(const geom::Vec2& offset)
+{
+  viewer()->SetOffset(offset);
+}
+
+geom::Vec2 DataViewerProxy::GetOffset() const
+{
+  return viewer()->GetOffset();
+}
+
+
+void DataViewerProxy::SetData(const ImageHandle& d)
+{
+  viewer()->SetData(d);
+}
+
+void DataViewerProxy::SetName(const String& name)
+{
+  viewer()->SetName(name);
+}
+
+int DataViewerProxy::AddOverlay(const OverlayPtr& ov, bool make_active)
+{
+  return viewer()->AddOverlay(ov,make_active);
+}
+
+void DataViewerProxy::ClearOverlays()
+{
+  viewer()->ClearOverlays();
+}
+
+OverlayManagerPtr DataViewerProxy::GetOverlayManager() const
+{
+  return viewer()->GetOverlayManager();
+}
+
+
+void DataViewerProxy::AddDockWidget(QWidget* w, const QString& name, bool shown, int area)
+{
+  viewer()->AddDockWidget(w,name, shown,area);
+}
+
+void DataViewerProxy::RemoveDockWidget(QWidget* w)
+{
+  viewer()->RemoveDockWidget(w);
+}
+
+void DataViewerProxy::SetAntialiasing(bool f)
+{
+  viewer()->SetAntialiasing(f);
+}
+
+void DataViewerProxy::Show()
+{
+  viewer()->show();
+}
+
+void DataViewerProxy::Hide() 
+{
+  viewer()->hide();
+}
+
+
+object DataViewerProxy::GetQObject(){
+  return ost::gui::get_py_qobject<DataViewer>(viewer());
+}
+
+DataViewer* DataViewerProxy::viewer() const
+{
+  if(!viewer_ptr_){
+     throw Error("DataViewer no longer exists");
+  }
+  return viewer_ptr_;
+}
+}}}  //ns
diff --git a/modules/gui/pymod/data_viewer_proxy.hh b/modules/gui/pymod/data_viewer_proxy.hh
new file mode 100644
index 0000000000000000000000000000000000000000..de1cd16fd74831cc371033451c3c93724c244386
--- /dev/null
+++ b/modules/gui/pymod/data_viewer_proxy.hh
@@ -0,0 +1,112 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2010 by the OpenStructure authors
+// Copyright (C) 2003-2010 by the IPLT authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+
+/*
+  DataViewer proxy
+
+  Authors: Ansgar Philippsen, Andreas Schenk
+*/
+
+#ifndef IMG_GUI_DATA_VIEWER_PROXY_H
+#define IMG_GUI_DATA_VIEWER_PROXY_H
+
+#include <boost/shared_ptr.hpp>
+#include <QPointer>
+
+#include <ost/img/point.hh>
+#include <ost/img/extent.hh>
+#include <ost/img/normalizer_impl.hh>
+
+#include <ost/gui/data_viewer/overlay_base_fw.hh>
+#include <ost/gui/data_viewer/overlay_manager_fw.hh>
+#include <ost/gui/data_viewer/data_viewer.hh>
+#include <ost/gui/module_config.hh>
+
+#include "sip_handler.hh"
+
+class QWidget;
+class QString;
+
+namespace ost { namespace img { namespace gui {
+
+// fw decl
+class DataViewer;
+
+class TEMPLATE_EXPORT DataViewerProxy  {
+public:
+  DataViewerProxy(DataViewer* v);
+
+  // data viewer interface
+
+  void SetData(const ImageHandle& data);
+  void SetName(const String& name);
+
+  NormalizerPtr GetNormalizer() const;
+  void Renormalize();
+  void Recenter();
+  void UpdateView();
+
+  Extent GetSelection() const;
+  void SetSelection(const Extent& selection);
+  void SetSlab(int slab);
+  int GetSlab() const;
+  void SetZoomScale(Real zoomscale);
+  Real GetZoomScale() const;
+  void SetViewerMin(Real min);
+  Real GetViewerMin() const;
+  void SetViewerMax(Real max);
+  Real GetViewerMax() const;
+  void SetGamma(Real gamma);
+  Real GetGamma() const;
+  void SetInvert(bool invert);
+  bool GetInvert() const;
+  void SetOffset(const geom::Vec2& offset);
+  geom::Vec2 GetOffset() const;
+
+  int AddOverlay(const OverlayPtr& ov, bool make_active=true);
+  OverlayManagerPtr GetOverlayManager() const;
+  void ClearOverlays();
+
+  void AddDockWidget(QWidget* w, const QString& name, bool shown=true, int area=2);
+  void RemoveDockWidget(QWidget* w);
+
+  void SetAntialiasing(bool f);
+
+  // ensure that data viewer is visible
+  void Show();
+
+  //void ShowClickedPosition(bool show=true);
+  //Vec3 GetClickedPosition();
+
+  void Hide();  
+
+  object GetQObject();
+protected:
+  QPointer<DataViewer> viewer_ptr_;
+  DataViewer* viewer() const;
+};
+
+typedef boost::shared_ptr<DataViewerProxy> DataViewerProxyPtr;
+
+}}}  //ns
+
+#endif
+
+
diff --git a/modules/gui/pymod/dng/init.py b/modules/gui/pymod/dng/init.py
index 1b7ed8043bdce2c426565f1a4dee2435a163a218..ebe63ed4eb84abb8bd083161ee3df585e1f62c4c 100644
--- a/modules/gui/pymod/dng/init.py
+++ b/modules/gui/pymod/dng/init.py
@@ -12,6 +12,7 @@ try:
 except ImportError:
   _img_present=False
   pass
+
 import httplib
 
 from PyQt4 import QtGui, QtCore
diff --git a/modules/gui/pymod/export_data_viewer.cc b/modules/gui/pymod/export_data_viewer.cc
index 6efdef65e1a980d4a77b4b79111a0e77bd38babf..e1b047d84cd09022b75a953bbeb25fdf631304d5 100644
--- a/modules/gui/pymod/export_data_viewer.cc
+++ b/modules/gui/pymod/export_data_viewer.cc
@@ -25,91 +25,87 @@
 #include <boost/python.hpp>
 #include <ost/base.hh>
 #include <ost/gui/data_viewer/data_viewer.hh>
+#include "data_viewer_proxy.hh"
 #include <ost/gui/data_viewer/overlay_manager.hh>
 
-#include "sip_handler.hh"
-
 using namespace boost::python;
 using namespace ost::img;
 using namespace ost;
-using namespace ost::img::gui;
 using namespace ost::gui;
+using namespace ost::img::gui;
 
 namespace {
 
-void add_dock1(DataViewer* p, QWidget* w, const String& name)
+void add_dock1(DataViewerProxy* p, QWidget* w, const String& name) 
 {
   p->AddDockWidget(w,QString::fromStdString(name));
 }
 
-void add_dock2(DataViewer* p, QWidget* w, const QString& name)
-{
-  p->AddDockWidget(w,name);
-}
-
-void add_dock3(DataViewer* p, QWidget* w, const String& name, bool s)
+void add_dock2(DataViewerProxy* p, QWidget* w, const String& name, bool s)
 {
   p->AddDockWidget(w,QString::fromStdString(name),s);
 }
 
-void add_dock4(DataViewer* p, QWidget* w, const QString& name, bool s)
+void add_dock3(DataViewerProxy* p, QWidget* w, const String& name, bool s, int area)
 {
-  p->AddDockWidget(w,name,s);
+  p->AddDockWidget(w,QString::fromStdString(name),s,area);
 }
 
 } // anon ns
 
 BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(o_AddOverlay, AddOverlay, 1, 2)
+BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(o_AddDockWidget, AddDockWidget, 2, 4)
 
 void export_data_viewer()
 {
-  class_<DataViewer, boost::noncopyable >("DataViewer",no_init)
-    .def("SetData",&DataViewer::SetData)
-    .def("SetName",&DataViewer::SetName)
-    .def("GetOverlayManager",&DataViewer::GetOverlayManager)
-    .def("GetNormalizer",&DataViewer::GetNormalizer,return_value_policy<return_by_value>())
-    .def("Renormalize",&DataViewer::Renormalize)
-    .def("AddOverlay",&DataViewer::AddOverlay,o_AddOverlay())
-    .def("ClearOverlays",&DataViewer::ClearOverlays)
-    .def("GetSelection",&DataViewer::GetSelection)
-    .def("SetSelection",&DataViewer::SetSelection)
-    .def("UpdateView",&DataViewer::UpdateView)
-    .def("Recenter",&DataViewer::Recenter)
+  class_<DataViewerProxy, DataViewerProxyPtr >("DataViewer",no_init)
+    .def("SetData",&DataViewerProxy::SetData)
+    .def("SetName",&DataViewerProxy::SetName)
+    .def("GetOverlayManager",&DataViewerProxy::GetOverlayManager)
+    .def("GetNormalizer",&DataViewerProxy::GetNormalizer,return_value_policy<return_by_value>())
+    .def("Renormalize",&DataViewerProxy::Renormalize)
+    .def("AddOverlay",&DataViewerProxy::AddOverlay,o_AddOverlay())
+    .def("ClearOverlays",&DataViewerProxy::ClearOverlays)
+    .def("GetSelection",&DataViewerProxy::GetSelection)
+    .def("SetSelection",&DataViewerProxy::SetSelection)
+    .def("UpdateView",&DataViewerProxy::UpdateView)
+    .def("Recenter",&DataViewerProxy::Recenter)
+    .def("AddDockWidget",&DataViewerProxy::AddDockWidget,o_AddDockWidget())
     .def("AddDockWidget",add_dock1)
     .def("AddDockWidget",add_dock2)
-    .def("SetSlab", &DataViewer::SetSlab)
-    .def("GetSlab", &DataViewer::GetSlab)
-    .add_property("slab", &DataViewer::GetSlab, &DataViewer::SetSlab)
-    .def("SetZoomScale", &DataViewer::SetZoomScale)
-    .def("GetZoomScale", &DataViewer::GetZoomScale)
-    .add_property("zoomscale", &DataViewer::GetZoomScale, &DataViewer::SetZoomScale)
-    .def("SetViewerMin", &DataViewer::SetViewerMin)
-    .def("GetViewerMin", &DataViewer::GetViewerMin)
-    .add_property("viewer_min", &DataViewer::GetViewerMin, &DataViewer::SetViewerMin)
-    .def("SetViewerMax", &DataViewer::SetViewerMax)
-    .def("GetViewerMax", &DataViewer::GetViewerMax)
-    .add_property("viewer_max", &DataViewer::GetViewerMax, &DataViewer::SetViewerMax)
-    .def("SetGamma", &DataViewer::SetGamma)
-    .def("GetGamma", &DataViewer::GetGamma)
-    .add_property("gamma", &DataViewer::GetGamma, &DataViewer::SetGamma)
-    .def("SetInvert", &DataViewer::SetInvert)
-    .def("GetInvert", &DataViewer::GetInvert)
-    .add_property("invert", &DataViewer::GetInvert, &DataViewer::SetInvert)
-    .def("SetOffset", &DataViewer::SetOffset)
-    .def("GetOffset", &DataViewer::GetOffset)
-    .add_property("offset", &DataViewer::GetOffset, &DataViewer::SetOffset)
     .def("AddDockWidget",add_dock3)
-    .def("AddDockWidget",add_dock4)
-    .def("RemoveDockWidget",&DataViewer::RemoveDockWidget)
-    .def("SetAntialiasing",&DataViewer::SetAntialiasing)
-    .def("Show",&DataViewer::show)
-    .def("Hide", &DataViewer::hide)
-    .def("GetQObject",&get_py_qobject<DataViewer>)
-    .add_property("qobject", &get_py_qobject<DataViewer>)
-    /*
-    .def("SetAutoNormalize",&DataViewer::SetAutoNormalize)
-    .def("ShowClickedPosition",&DataViewer::ShowClickedPosition,o_ShowClickedPosition())
-    .def("GetClickedPosition",&DataViewer::GetClickedPosition)
-    */
+    .def("RemoveDockWidget",&DataViewerProxy::RemoveDockWidget)
+    .def("SetAntialiasing",&DataViewerProxy::SetAntialiasing)
+    .def("Show",&DataViewerProxy::Show)
+    .def("Hide", &DataViewerProxy::Hide)
+    .def("SetSlab", &DataViewerProxy::SetSlab)
+    .def("GetSlab", &DataViewerProxy::GetSlab)
+    .add_property("slab", &DataViewerProxy::GetSlab, &DataViewerProxy::SetSlab)
+    .def("SetZoomScale", &DataViewerProxy::SetZoomScale)
+    .def("GetZoomScale", &DataViewerProxy::GetZoomScale)
+    .add_property("zoomscale", &DataViewerProxy::GetZoomScale, &DataViewerProxy::SetZoomScale)
+    .def("SetViewerMin", &DataViewerProxy::SetViewerMin)
+    .def("GetViewerMin", &DataViewerProxy::GetViewerMin)
+    .add_property("viewer_min", &DataViewerProxy::GetViewerMin, &DataViewerProxy::SetViewerMin)
+    .def("SetViewerMax", &DataViewerProxy::SetViewerMax)
+    .def("GetViewerMax", &DataViewerProxy::GetViewerMax)
+    .add_property("viewer_max", &DataViewerProxy::GetViewerMax, &DataViewerProxy::SetViewerMax)
+    .def("SetGamma", &DataViewerProxy::SetGamma)
+    .def("GetGamma", &DataViewerProxy::GetGamma)
+    .add_property("gamma", &DataViewerProxy::GetGamma, &DataViewerProxy::SetGamma)
+    .def("SetInvert", &DataViewerProxy::SetInvert)
+    .def("GetInvert", &DataViewerProxy::GetInvert)
+    .add_property("invert", &DataViewerProxy::GetInvert, &DataViewerProxy::SetInvert)
+    .def("SetOffset", &DataViewerProxy::SetOffset)
+    .def("GetOffset", &DataViewerProxy::GetOffset)
+    .add_property("offset", &DataViewerProxy::GetOffset, &DataViewerProxy::SetOffset)
+    .def("GetQObject",&DataViewerProxy::GetQObject)
+    .add_property("qobject",&DataViewerProxy::GetQObject)
+
+      /*
+    .def("SetAutoNormalize",&DataViewerProxy::SetAutoNormalize)
+    .def("ShowClickedPosition",&DataViewerProxy::ShowClickedPosition,o_ShowClickedPosition())
+    .def("GetClickedPosition",&DataViewerProxy::GetClickedPosition)
+    */    
     ;
 }
diff --git a/modules/gui/pymod/export_gosty.cc b/modules/gui/pymod/export_gosty.cc
index 1cd37fae447b9bd593a82c750196b29ef7a3dc55..adc5594a8454dfb71042755a10c28e1818229e5d 100644
--- a/modules/gui/pymod/export_gosty.cc
+++ b/modules/gui/pymod/export_gosty.cc
@@ -36,9 +36,7 @@ using namespace boost::python;
 #include "sip_handler.hh"
 
 #if OST_IMG_ENABLED
-  #include <ost/gui/data_viewer/data_viewer.hh>
-#include <ost/img/data.hh>
-#include <ost/gui/data_viewer/data_viewer.hh>
+#include "data_viewer_proxy.hh"
 using namespace ost::img::gui;
 #endif
 
@@ -48,15 +46,13 @@ using namespace ost::gui;
 namespace {
 
 #if OST_IMG_ENABLED
-DataViewer* app_create_data_viewer1(GostyApp* app, 
-                                    const ost::img::Data& d, 
-                                    const QString& name)
+DataViewerProxyPtr app_create_data_viewer1(GostyApp* app, const ost::img::ImageHandle& d, const QString& name)
 {
-  return app->CreateDataViewer(d,name);
+  return DataViewerProxyPtr(new DataViewerProxy(app->CreateDataViewer(d,name)));
 }
-DataViewer* app_create_data_viewer2(GostyApp* app, const ost::img::Data& d)
+DataViewerProxyPtr app_create_data_viewer2(GostyApp* app, const ost::img::ImageHandle& d)
 {
-  return app->CreateDataViewer(d);
+  return DataViewerProxyPtr(new DataViewerProxy(app->CreateDataViewer(d)));
 }
 #endif
 
@@ -117,8 +113,8 @@ void export_Gosty()
     .add_property("message_widget", make_function(&GostyApp::GetMessageWidget,
         return_value_policy<reference_existing_object>()))
      #if OST_IMG_ENABLED
-    .def("CreateDataViewer", &app_create_data_viewer1,return_value_policy<reference_existing_object>())
-    .def("CreateDataViewer", &app_create_data_viewer2,return_value_policy<reference_existing_object>())
+    .def("CreateDataViewer", &app_create_data_viewer1)
+    .def("CreateDataViewer", &app_create_data_viewer2)
     #endif
     .def("ProcessEvents", &GostyApp::ProcessEvents)           
     .add_property("perspective", 
diff --git a/modules/gui/pymod/export_plot.cc b/modules/gui/pymod/export_plot.cc
deleted file mode 100644
index 9091a73139b4bc51b8a04be621c92ef5010dfc7b..0000000000000000000000000000000000000000
--- a/modules/gui/pymod/export_plot.cc
+++ /dev/null
@@ -1,203 +0,0 @@
-//------------------------------------------------------------------------------
-// This file is part of the OpenStructure project <www.openstructure.org>
-//
-// Copyright (C) 2008-2011 by the OpenStructure authors
-// Copyright (C) 2003-2010 by the IPLT authors
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License as published by the Free
-// Software Foundation; either version 3.0 of the License, or (at your option)
-// any later version.
-// This library is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with this library; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//------------------------------------------------------------------------------
-
-/*
-  Author: Ansgar Philippsen, Andreas Schenk
-*/
-
-#include <boost/python.hpp>
-#include <ost/gui/plot_viewer/plot_viewer_proxy.hh>
-#include <ost/gui/plot_viewer/plot_data.hh>
-#include <ost/gui/plot_viewer/plot_data_info.hh>
-#include <ost/gui/plot_viewer/plot_function_info.hh>
-#include <ost/gui/plot_viewer/plot_function.hh>
-#include <ost/gui/plot_viewer/plot_group.hh>
-
-using namespace boost::python;
-using namespace ost;
-using namespace ost::gui;
-
-namespace {
-
-struct PlotFunctionWrap : PlotFunction, wrapper<PlotFunction>
-{
-  IOProfileWrap(PyObject*&, const ost::io::IOProfile&)
-  Real  Func(Real val) const
-  {
-    return this->get_override("Func")(val);
-  }
-};
-
-
-//PlotDataInfoWrappers
-PlotInfoBasePtr plot_info_base_set_mode(PlotInfoBasePtr inptr, unsigned int val ){inptr->SetMode(val);return inptr;}
-PlotInfoBasePtr plot_info_base_set_name(PlotInfoBasePtr inptr, const String& s ){inptr->SetName(QString::fromStdString(s));return inptr;}
-PlotInfoBasePtr plot_info_base_set_visible(PlotInfoBasePtr inptr, bool val ){inptr->SetVisible(val);return inptr;}
-PlotInfoBasePtr plot_info_base_set_color(PlotInfoBasePtr inptr, QColor color){inptr->SetColor(color);return inptr;}
-PlotInfoBasePtr plot_info_base_set_color2(PlotInfoBasePtr inptr, int r, int g, int b){inptr->SetColor(r,g,b);return inptr;}
-PlotInfoBasePtr plot_info_base_set_linecolor1(PlotInfoBasePtr inptr, QColor color ){inptr->SetLineColor(color);return inptr;}
-PlotInfoBasePtr plot_info_base_set_fillcolor1(PlotInfoBasePtr inptr, QColor color){inptr->SetFillColor(color);return inptr;}
-PlotInfoBasePtr plot_info_base_set_linecolor2(PlotInfoBasePtr inptr, int r, int g, int b){inptr->SetLineColor(r,g,b);return inptr;}
-PlotInfoBasePtr plot_info_base_set_fillcolor2(PlotInfoBasePtr inptr, int r, int g, int b){inptr->SetFillColor(r,g,b);return inptr;}
-
-
-
-PlotDataInfoPtr plot_data_info_set_quality(PlotDataInfoPtr inptr, bool val ){inptr->SetQuality(val);return inptr;}
-PlotDataInfoPtr plot_data_info_set_symbol(PlotDataInfoPtr inptr, unsigned int val ){inptr->SetSymbol(val);return inptr;}
-PlotDataInfoPtr plot_data_info_set_symbolsize(PlotDataInfoPtr inptr, unsigned int val ){inptr->SetSymbolSize(val);return inptr;}
-PlotDataInfoPtr plot_data_info_set_errormode(PlotDataInfoPtr inptr, unsigned int val ){inptr->SetErrorMode(val);return inptr;}
-PlotDataInfoPtr plot_data_info_set_callback(PlotDataInfoPtr inptr, object cb){inptr->SetCallback(cb);return inptr;}
-PlotDataInfoPtr plot_data_info_set_name(PlotDataInfoPtr inptr, const String& name ){inptr->SetName(QString(name.c_str()));return inptr;}
-
-PlotGroupInfoPtr plot_group_info_set_quality(PlotGroupInfoPtr inptr, bool val ){inptr->SetQuality(val);return inptr;}
-PlotGroupInfoPtr plot_group_info_set_name(PlotGroupInfoPtr inptr, const String& name ){inptr->SetName(QString(name.c_str()));return inptr;}
-PlotGroupInfoPtr plot_group_info_set_symbol(PlotGroupInfoPtr inptr, unsigned int val ){inptr->SetSymbol(val);return inptr;}
-PlotGroupInfoPtr plot_group_info_set_symbolsize(PlotGroupInfoPtr inptr, unsigned int val ){inptr->SetSymbolSize(val);return inptr;}
-PlotGroupInfoPtr plot_group_info_set_errormode(PlotGroupInfoPtr inptr, unsigned int val ){inptr->SetErrorMode(val);return inptr;}
-PlotGroupInfoPtr plot_group_info_set_callback(PlotGroupInfoPtr inptr, object cb){inptr->SetCallback(cb);return inptr;}
-
-} // ns
-
-BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(PlotData_AddY_Overloads,PlotData::AddY, 1, 2)
-BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(PlotData_AddYE_Overloads,PlotData::AddYE, 2,3)
-BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(PlotData_AddYQ_Overloads,PlotData::AddYQ, 2,3)
-BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(PlotData_AddYEQ_Overloads,PlotData::AddYEQ, 3,4)
-
-BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(PlotData_AddXY_Overloads,PlotData::AddXY, 2,3)
-BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(PlotData_AddXYQ_Overloads,PlotData::AddXYQ, 3,4)
-BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(PlotData_AddXYE_Overloads,PlotData::AddXYE, 3,4)
-BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(PlotData_AddXYEQ_Overloads,PlotData::AddXYEQ, 4,5)
-BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(PlotData_AddXEYE_Overloads,PlotData::AddXEYE, 4,5)
-BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(PlotData_AddXEYEQ_Overloads,PlotData::AddXEYEQ, 5,6)
-
-
-void (PlotGroup::*PlotGroup_add1)(PlotDataPtr dataptr)=&PlotGroup::Add;
-void (PlotGroup::*PlotGroup_add2)(PlotFunctionPtr functionptr)=&PlotGroup::Add;
-void (PlotGroup::*PlotGroup_add3)(PlotGroupPtr groupptr)=&PlotGroup::Add;
-
-PlotDataInfoPtr (PlotViewerProxy::*PlotViewerProxy_add1)(PlotDataPtr dataptr,bool)=&PlotViewerProxy::Add;
-PlotFunctionInfoPtr (PlotViewerProxy::*PlotViewerProxy_add2)(PlotFunctionPtr functionptr)=&PlotViewerProxy::Add;
-PlotGroupInfoPtr (PlotViewerProxy::*PlotViewerProxy_add3)(PlotGroupPtr groupptr,bool)=&PlotViewerProxy::Add;
-
-BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(PlotViewerProxy_Add_Overloads, Add, 1,2)
-
-void export_Plot()
-{
-  class_<PlotFunctionWrap, boost::noncopyable>("PlotFunction")
-    ;
-
-  class_<PlotInfoBase,PlotInfoBasePtr>("PlotInfoBase",init<>())
-    .def("SetMode",plot_info_base_set_mode)
-    .def("SetName",plot_info_base_set_name)
-    .def("SetVisible",plot_info_base_set_visible)
-    .def("SetColor",plot_info_base_set_color)
-    .def("SetColor",plot_info_base_set_color2)
-    .def("SetFillColor",plot_info_base_set_fillcolor1)
-    .def("SetLineColor",plot_info_base_set_linecolor1)
-    .def("SetFillColor",plot_info_base_set_fillcolor2)
-    .def("SetLineColor",plot_info_base_set_linecolor2)
-    ;
-
-  class_<PlotDataInfo,PlotDataInfoPtr, bases<PlotInfoBase> >("PlotDataInfo",init<>())
-    .def("SetSymbol",plot_data_info_set_symbol)
-    .def("SetSymbolSize",plot_data_info_set_symbolsize)
-    .def("SetErrorMode",plot_data_info_set_errormode)
-    .def("SetQuality",plot_data_info_set_quality)
-    .def("SetName", plot_data_info_set_name)
-    .def("SetCallback",plot_data_info_set_callback)
-    ;
-
-  class_<PlotGroupInfo,PlotGroupInfoPtr, bases<PlotInfoBase> >("PlotGroupInfo",init<>())
-    .def("SetSymbol",plot_group_info_set_symbol)
-    .def("SetSymbolSize",plot_group_info_set_symbolsize)
-    .def("SetErrorMode",plot_group_info_set_errormode)
-    .def("SetQuality",plot_group_info_set_quality)
-    .def("SetCallback",plot_group_info_set_callback)
-    ;
-
-  class_<PlotFunctionInfo,PlotFunctionInfoPtr, bases<PlotInfoBase> >("PlotFunctionInfo",init<>())
-    ;
-
-  class_<PlotData,PlotDataPtr>("PlotData",init<>())
-    .def("AddY",&PlotData::AddY,PlotData_AddY_Overloads())
-    .def("AddYQ",&PlotData::AddYE,PlotData_AddYQ_Overloads())
-    .def("AddYE",&PlotData::AddYQ,PlotData_AddYE_Overloads())
-    .def("AddYEQ",&PlotData::AddYEQ,PlotData_AddYEQ_Overloads())
-    .def("AddXY",&PlotData::AddXY,PlotData_AddXY_Overloads())
-    .def("AddXYQ",&PlotData::AddXYQ,PlotData_AddXYQ_Overloads())
-    .def("AddXYE",&PlotData::AddXYE,PlotData_AddXYE_Overloads())
-    .def("AddXYEQ",&PlotData::AddXYEQ,PlotData_AddXYEQ_Overloads())
-    .def("AddXEYE",&PlotData::AddXEYE,PlotData_AddXEYE_Overloads())
-    .def("AddXEYEQ",&PlotData::AddXEYEQ,PlotData_AddXEYEQ_Overloads())
-    .def("GetMinimumX",&PlotData::GetMinimumX)
-    .def("GetMaximumX",&PlotData::GetMaximumX)
-    .def("GetMinimumY",&PlotData::GetMinimumY)
-    .def("GetMaximumY",&PlotData::GetMaximumY)
-    ;
-
-  class_<PlotGroup,PlotGroupPtr>("PlotGroup",init<>())
-    .def("Add",PlotGroup_add1)
-    .def("Add",PlotGroup_add2)
-    .def("Add",PlotGroup_add3)
-    ;
-
-
-  {//scope
-
-    scope PlotViewerScope =
-      class_<PlotViewerProxy,PlotViewerProxyPtr>("PlotViewer", no_init)
-        .def("Add",PlotViewerProxy_add1,PlotViewerProxy_Add_Overloads())
-        .def("Add",PlotViewerProxy_add2)
-        .def("Add",PlotViewerProxy_add3,PlotViewerProxy_Add_Overloads())
-        .def("SetMinimumX", &PlotViewerProxy::SetMinimumX)
-        .def("SetMaximumX", &PlotViewerProxy::SetMaximumX)
-        .def("SetMinimumY", &PlotViewerProxy::SetMinimumY)
-        .def("SetMaximumY", &PlotViewerProxy::SetMaximumY)
-        .def("GetMinimumX", &PlotViewerProxy::GetMinimumX)
-        .def("GetMaximumX", &PlotViewerProxy::GetMaximumX)
-        .def("GetMinimumY", &PlotViewerProxy::GetMinimumY)
-        .def("GetMaximumY", &PlotViewerProxy::GetMaximumY)
-        .def("SetAutofit", &PlotViewerProxy::SetAutofit)
-    ;
-
-    enum_<PlotInfoBase::modes>("modes")
-      .value("POINTS", PlotDataInfo::POINTS)
-      .value("LINES", PlotDataInfo::LINES)
-      .value("POINTSANDLINES", PlotDataInfo::POINTSANDLINES)
-      .value("AREA", PlotDataInfo::AREA)
-      .value("POINTSANDAREA", PlotDataInfo::POINTSANDAREA)
-      .export_values()
-      ;
-    enum_<PlotInfoBase::shapes>("shapes")
-      .value("CIRCLE", PlotDataInfo::CIRCLE)
-      .value("RECTANGLE", PlotDataInfo::RECTANGLE)
-      .value("CROSS", PlotDataInfo::CROSS)
-      .value("DIAGONALCROSS", PlotDataInfo::DIAGONALCROSS)
-      .export_values()
-      ;
-    enum_<PlotInfoBase::errormodes>("errormodes")
-      .value("NONE", PlotDataInfo::NONE)
-      .value("LINE", PlotDataInfo::LINE)
-      .value("BOX", PlotDataInfo::BOX)
-      .value("VECTOR", PlotDataInfo::VECTOR)
-      .export_values()
-      ;
-  }//scope
-}
diff --git a/modules/gui/pymod/gosty_startup.py b/modules/gui/pymod/gosty_startup.py
new file mode 100644
index 0000000000000000000000000000000000000000..029dc19704fc62a4165c0e4ca8f90e01be7d7ee4
--- /dev/null
+++ b/modules/gui/pymod/gosty_startup.py
@@ -0,0 +1,6 @@
+from ost import *
+from ost import gui
+gui_mode=True
+scene=gfx.Scene()
+scene.Stereo=gfx.Stereo
+
diff --git a/modules/gui/pymod/scene/custom_widget.py b/modules/gui/pymod/scene/custom_widget.py
index 7a7eb2e9283042f1ae8145870fc417b42e76cd3e..a0413862db119dd0e0fce07c3534ad889617f436 100644
--- a/modules/gui/pymod/scene/custom_widget.py
+++ b/modules/gui/pymod/scene/custom_widget.py
@@ -33,14 +33,14 @@ class CustomWidget(RenderModeWidget):
     
     #Defaults
     min_sphere_detail = 1
-    max_sphere_detail = 20
+    max_sphere_detail = 12
     
     min_arc_detail = 1
-    max_arc_detail = 20
+    max_arc_detail = 12
     
     min_rad = 0.05
-    max_bond_rad = 1.0
-    max_sphere_rad = 1.0
+    max_bond_rad = 5.0
+    max_sphere_rad = 5.0
     
     
     
diff --git a/modules/gui/pymod/scene/hsc_widget.py b/modules/gui/pymod/scene/hsc_widget.py
index c81a5f4174782c655549603ebd65c9ff776ec2cc..c67dc97214fdf7531c23b7b703212baf9564e30c 100644
--- a/modules/gui/pymod/scene/hsc_widget.py
+++ b/modules/gui/pymod/scene/hsc_widget.py
@@ -42,8 +42,8 @@ class HSCWidget(RenderModeWidget):
     max_arc_detail = 20
     
     min_width = 0.1
-    max_width = 2.5
-    max_tube_width= 2.0
+    max_width = 5.0
+    max_tube_width= 5.0
 
     min_tube_ratio = 0.2
     max_tube_ratio = 4
diff --git a/modules/gui/pymod/table.py b/modules/gui/pymod/table.py
index fd65e9ff69ad2a9f496894c3e30b58ad5f18e52e..94f1c64182bda5bde67b5ed5bd8a7541878851b7 100644
--- a/modules/gui/pymod/table.py
+++ b/modules/gui/pymod/table.py
@@ -1,7 +1,7 @@
 from PyQt4.QtGui import *
 from PyQt4.QtCore import *
 
-
+from ost import table
 __all__=('Table', )
 
 class TableModel(QAbstractTableModel):
@@ -40,10 +40,20 @@ class Table(QTableView):
      self.setFrameShape(QFrame.NoFrame)    
      self.setAttribute(Qt.WA_MacSmallSize)
      self.setShowGrid(False)
-     #self.horizontalHeader().setStretchLastSection(True)
+     self.double_click = None
+     self.horizontalHeader().setStretchLastSection(True)
      self.setContextMenuPolicy(Qt.CustomContextMenu)
      self.setSelectionBehavior(QAbstractItemView.SelectRows)
      self.setSizePolicy(QSizePolicy.MinimumExpanding, 
                         QSizePolicy.MinimumExpanding)
      self.setSortingEnabled(True)
-     self.setModel(self._model)
\ No newline at end of file
+     self.setModel(self._model)
+     QObject.connect(self, SIGNAL('doubleClicked(QModelIndex)'), 
+                     self.OnDoubleClick)
+  def OnDoubleClick(self, model_index):
+    print 'DOUBLE'
+    if not self.double_click:
+      return
+    row = table.TableRow(self._model.table.rows[model_index.row()],
+                         self._model.table)
+    self.double_click(row)
diff --git a/modules/gui/src/CMakeLists.txt b/modules/gui/src/CMakeLists.txt
index b4d9ee6e433268164006b2c8806b1ebaf905e168..190cb6f6685b9643dfe54697786804ecc4df533f 100644
--- a/modules/gui/src/CMakeLists.txt
+++ b/modules/gui/src/CMakeLists.txt
@@ -476,12 +476,8 @@ include_directories(${PYTHON_INCLUDE_PATH})
 qt4_add_resources(OST_QT_RESOURCE dngr.qrc)
 qt4_wrap_cpp(OST_GOSTY_MOC "gosty.hh"
              OPTIONS -DBOOST_TT_HAS_OPERATOR_HPP_INCLUDED)
-# if someone has ANY idea why windows already has the boost program options
-# symbols defined, please talk to Marco and Juergen. You will be rewarded with
-# dogfood for a lifetime!
-if (NOT WIN32)
-  set(LINK LINK ${BOOST_PROGRAM_OPTIONS_LIBRARIES})
-endif()
+
+set(LINK LINK ${BOOST_PROGRAM_OPTIONS_LIBRARIES})
 
 executable_libexec(NAME gosty SOURCES gosty.cc ${OST_GOSTY_MOC} ${OST_QT_RESOURCE} 
            DEPENDS_ON ost_gui ${LINK})
diff --git a/modules/gui/src/data_viewer/argand.cc b/modules/gui/src/data_viewer/argand.cc
index 6fceabe8f36723f1e0006c5e394cffa891cecb26..585283e2f4ecb3e8fc93c56875b2845431ffee09 100644
--- a/modules/gui/src/data_viewer/argand.cc
+++ b/modules/gui/src/data_viewer/argand.cc
@@ -31,7 +31,7 @@
 #include <QResizeEvent>
 namespace ost { namespace img { namespace gui {
 
-Argand::Argand(const Data& data, QWidget* p):
+Argand::Argand(const ImageHandle& data, QWidget* p):
   QWidget(p),
   DataObserver(data),
   extent_(),
diff --git a/modules/gui/src/data_viewer/argand.hh b/modules/gui/src/data_viewer/argand.hh
index 492bce04fa481f20e4bc9963ac5142aee81339df..8f09c241499b55a900e1a33b560f726cfedd5ba7 100644
--- a/modules/gui/src/data_viewer/argand.hh
+++ b/modules/gui/src/data_viewer/argand.hh
@@ -41,7 +41,7 @@ class DLLEXPORT_OST_GUI Argand: public QWidget, public DataObserver
 {
   Q_OBJECT;
 public:
-  Argand(const Data& data, QWidget* p);
+  Argand(const ImageHandle& data, QWidget* p);
   ~Argand();
 
   // QWidget interface
diff --git a/modules/gui/src/data_viewer/data_viewer.cc b/modules/gui/src/data_viewer/data_viewer.cc
index 8db37d504cbb4556e365c6e3ffd293a6ad7a5b51..a13a6d7ab900d2952a9249ba06d13a5b2b5c91e3 100644
--- a/modules/gui/src/data_viewer/data_viewer.cc
+++ b/modules/gui/src/data_viewer/data_viewer.cc
@@ -60,7 +60,7 @@ int ipow(int base, unsigned int exponent){
 }
 }
 
-DataViewer::DataViewer(QWidget* p, const Data& data, const QString& name):
+DataViewer::DataViewer(QWidget* p, const ImageHandle& data, const QString& name):
   ost::gui::MainWindow(p,0),
   name_(name),
   panel_(new DataViewerPanel(data,this)),
@@ -80,13 +80,17 @@ DataViewer::~DataViewer()
 {
 }
 
-void DataViewer::SetData(const Data& d)
+void DataViewer::SetData(const ImageHandle& d)
 {
   panel_->SetData(d);
   fft_->SetData(d);
   info_->SetImageInfo(d);
 }
 
+const ImageHandle& DataViewer::GetData() const{
+  return panel_->GetObservedData();
+}
+
 NormalizerPtr DataViewer::GetNormalizer() const 
 {
   assert(panel_);
@@ -263,7 +267,7 @@ void DataViewer::SetAntialiasing(bool f)
 //////////////////////////
 // private methods
 
-void DataViewer::build(const Data& data) 
+void DataViewer::build(const ImageHandle& data)
 {
   build_menu();
 
@@ -278,9 +282,9 @@ void DataViewer::build(const Data& data)
   statusBar()->addWidget(zoomlabel_);
   statusBar()->addWidget(slablabel_);
 
-  AddDockWidget(ov_manager_gui_,"Overlays",true,0);
+  AddDockWidget(ov_manager_gui_,"Overlays",true,2);
   info_->SetImageInfo(data);
-  AddDockWidget(info_,"Info",true,0);
+  AddDockWidget(info_,"Info",true,2);
   AddDockWidget(argand_,"Argand",false,1);
   AddDockWidget(fft_,"FFT",false,1);
 
diff --git a/modules/gui/src/data_viewer/data_viewer.hh b/modules/gui/src/data_viewer/data_viewer.hh
index e9e417f6b0c6a0076ab728ae8dd60b0dacabf71d..6b056de385de7b07a0fe53fcf3746e2b4bad4ce3 100644
--- a/modules/gui/src/data_viewer/data_viewer.hh
+++ b/modules/gui/src/data_viewer/data_viewer.hh
@@ -67,7 +67,10 @@ public:
   virtual ~DataViewer();
 
   //! set new image or function to display
-  void SetData(const Data& data);
+  void SetData(const ImageHandle& data);
+
+  //! get the current displayed image
+  const ImageHandle& GetData() const;
 
   //! retrieve used normalizer
   NormalizerPtr GetNormalizer() const;
@@ -151,7 +154,7 @@ public slots:
 
  protected:
   //! initialize with data to view, plus a name
-  DataViewer(QWidget* p, const Data& data, const QString& name="");
+  DataViewer(QWidget* p, const ImageHandle& data, const QString& name="");
 
  private:
   // inhibit coping and assignement
@@ -173,7 +176,7 @@ public slots:
   QLabel* slablabel_;
   QPoint lastmouse_;
 
-  void build(const Data& data);
+  void build(const ImageHandle& data);
 
   void build_menu();
 };
diff --git a/modules/gui/src/data_viewer/data_viewer_panel.cc b/modules/gui/src/data_viewer/data_viewer_panel.cc
index 06a58bb1eb46ca12278277524cf94ca459f9607c..9de780147ac2c43179d6f4d2cd80d36029c439d7 100644
--- a/modules/gui/src/data_viewer/data_viewer_panel.cc
+++ b/modules/gui/src/data_viewer/data_viewer_panel.cc
@@ -21,7 +21,7 @@
 
 namespace ost { namespace img { namespace gui {
 
-DataViewerPanel::DataViewerPanel(const Data& d, QWidget* p):
+DataViewerPanel::DataViewerPanel(const ImageHandle& d, QWidget* p):
   DataViewerPanelBase(d,p)
 {}
 
diff --git a/modules/gui/src/data_viewer/data_viewer_panel.hh b/modules/gui/src/data_viewer/data_viewer_panel.hh
index e72530e36b7810f8a6557740ec0af8abfad16c75..71fe55351ca6038afc73d138d4f9cca87d78b3d9 100644
--- a/modules/gui/src/data_viewer/data_viewer_panel.hh
+++ b/modules/gui/src/data_viewer/data_viewer_panel.hh
@@ -28,7 +28,7 @@ namespace ost { namespace img { namespace gui {
 class DLLEXPORT_OST_GUI DataViewerPanel: public DataViewerPanelBase
 {
 public:
-  DataViewerPanel(const Data& d, QWidget* parent);
+  DataViewerPanel(const ImageHandle& d, QWidget* parent);
 };
 
 }}}  //ns
diff --git a/modules/gui/src/data_viewer/data_viewer_panel_base.cc b/modules/gui/src/data_viewer/data_viewer_panel_base.cc
index 6405eb7774f285a666e80fc14eec050491dfe493..3f145e555ed84c3d216fc0382b5f46d4f01de7ce 100644
--- a/modules/gui/src/data_viewer/data_viewer_panel_base.cc
+++ b/modules/gui/src/data_viewer/data_viewer_panel_base.cc
@@ -43,7 +43,7 @@
 namespace ost { namespace img { namespace gui {
 
 
-DataViewerPanelBase::DataViewerPanelBase(const Data& data,QWidget* parent):
+DataViewerPanelBase::DataViewerPanelBase(const ImageHandle& data,QWidget* parent):
   QWidget(parent),
   DataObserver(data),
   popupmenu_(new QMenu(this)),
@@ -78,7 +78,14 @@ DataViewerPanelBase::DataViewerPanelBase(const Data& data,QWidget* parent):
   fast_low_mag_(true),
   fast_high_mag_(true),
   antialiasing_(true),
-  drag_start_()
+  drag_start_(),
+  phase_toggle_action_(),
+  invert_toggle_action_(),
+  show_click_pos_toggle_action_(),
+  fast_low_mag_toggle_action_(),
+  fast_high_mag_toggle_action_(),
+  display_pixel_toggle_action_(),
+  antialiasing_toggle_action_()
 {
   update_min_max();
   UpdateNormalizer(data_min_,data_max_,1.0,false);
@@ -92,32 +99,68 @@ DataViewerPanelBase::DataViewerPanelBase(const Data& data,QWidget* parent):
   setFocusPolicy(Qt::WheelFocus);
   //TODO cursors
   setCursor(cursor_);
-  /*
-  QMenu* m_zoom = new QMenu();
-  m_zoom->Append(ID_ZOOM_PLUS,QT("Zoom In"));
-  m_zoom->Append(ID_ZOOM_MINUS,QT("Zoom Out"));
-  m_zoom->AppendSeparator();
-  m_zoom->Append(ID_ZOOM_1,QT("Original Size"));
-
-  QMenu* m_slab = new QMenu();
-  m_slab->Append(ID_SLAB_PLUS,QT("Next Slab"));
-  m_slab->Append(ID_SLAB_MINUS,QT("Previous Slab"));
-  m_slab->AppendSeparator();
-  m_slab->Append(ID_SLAB_CENTER,QT("Center Slab"));
-  m_slab->Append(ID_SLAB_START,QT("First Slab"));
-  m_slab->Append(ID_SLAB_END,QT("Last Slab"));
-  
-  popupmenu_->Append(ID_NORMALIZE,QT("Normalize"));
-  popupmenu_->Append(ID_CENTER,QT("Center image"));
-  popupmenu_->AppendSeparator();
-  popupmenu_->Append(ID_ZOOM,QT("Zoom"),m_zoom);
-  popupmenu_->Append(ID_SLAB,QT("Slab"),m_slab);
-  popupmenu_->AppendSeparator();
-  popupmenu_->AppendCheckItem(ID_PHASECOLOR,QT("Phase Color Display"));
-  popupmenu_->AppendCheckItem(ID_INVERT,QT("Invert"));
-  popupmenu_->AppendCheckItem(ID_DISP_PIXEL_VAL,QT("Display pixel values"));
-  popupmenu_->AppendCheckItem(ID_SHOW_CLICK_POS,QT("Show last clicked point"));
-  */
+
+  QMenu* m_zoom = new QMenu("Zoom");
+  QAction* action=m_zoom->addAction("Zoom In");
+  connect(action, SIGNAL(triggered()), this, SLOT(zoom_plus()));
+  action=m_zoom->addAction("Zoom Out");
+  connect(action, SIGNAL(triggered()), this, SLOT(zoom_minus()));
+  m_zoom->addSeparator();
+  action=m_zoom->addAction("Original Size");
+  connect(action, SIGNAL(triggered()), this, SLOT(zoom_reset()));
+
+  QMenu* m_slab = new QMenu("Slab");
+  action=m_slab->addAction("Next Slab");
+  connect(action, SIGNAL(triggered()), this, SLOT(slab_plus()));
+  action=m_slab->addAction("Previous Slab");
+  connect(action, SIGNAL(triggered()), this, SLOT(slab_minus()));
+  m_slab->addSeparator();
+  action=m_slab->addAction("Center Slab");
+  connect(action, SIGNAL(triggered()), this, SLOT(slab_center()));
+  action=m_slab->addAction("First Slab");
+  connect(action, SIGNAL(triggered()), this, SLOT(slab_start()));
+  action=m_slab->addAction("Last Slab");
+  connect(action, SIGNAL(triggered()), this, SLOT(slab_end()));
+
+  action=popupmenu_->addAction("Normalize");
+  connect(action, SIGNAL(triggered()), this, SLOT(normalize()));
+  action=popupmenu_->addAction("Center image");
+  connect(action, SIGNAL(triggered()), this, SLOT(center()));
+  popupmenu_->addSeparator();
+  popupmenu_->addMenu(m_zoom);
+  popupmenu_->addMenu(m_slab);
+  popupmenu_->addSeparator();
+
+  phase_toggle_action_=popupmenu_->addAction("Phase Color Display");
+  phase_toggle_action_->setCheckable(true);
+  phase_toggle_action_->setChecked(false);
+  connect(phase_toggle_action_, SIGNAL(triggered()), this, SLOT(toggle_phase_color()));
+  invert_toggle_action_=popupmenu_->addAction("Invert");
+  invert_toggle_action_->setCheckable(true);
+  invert_toggle_action_->setChecked(false);
+  connect(invert_toggle_action_, SIGNAL(triggered()), this, SLOT(toggle_invert()));
+  display_pixel_toggle_action_=popupmenu_->addAction("Display pixel values");
+  display_pixel_toggle_action_->setCheckable(true);
+  display_pixel_toggle_action_->setChecked(true);
+  connect(display_pixel_toggle_action_, SIGNAL(triggered()), this, SLOT(toggle_display_pixels()));
+  show_click_pos_toggle_action_=popupmenu_->addAction("Show last clicked point");
+  show_click_pos_toggle_action_->setCheckable(true);
+  show_click_pos_toggle_action_->setChecked(false);
+  connect(show_click_pos_toggle_action_, SIGNAL(triggered()), this, SLOT(toggle_show_click_pos()));
+  popupmenu_->addSeparator();
+  fast_low_mag_toggle_action_=popupmenu_->addAction("Fast low magnification drawing");
+  fast_low_mag_toggle_action_->setCheckable(true);
+  fast_low_mag_toggle_action_->setChecked(true);
+  connect(fast_low_mag_toggle_action_, SIGNAL(triggered()), this, SLOT(toggle_fast_low_mag()));
+  fast_high_mag_toggle_action_=popupmenu_->addAction("Fast high magnification drawing");
+  fast_high_mag_toggle_action_->setCheckable(true);
+  fast_high_mag_toggle_action_->setChecked(true);
+  connect(fast_high_mag_toggle_action_, SIGNAL(triggered()), this, SLOT(toggle_fast_high_mag()));
+  antialiasing_toggle_action_=popupmenu_->addAction("Antialiasing");
+  antialiasing_toggle_action_->setCheckable(true);
+  antialiasing_toggle_action_->setChecked(false);
+  connect(antialiasing_toggle_action_, SIGNAL(triggered()), this, SLOT(toggle_antialiasing()));
+
   QPixmapCache::setCacheLimit(51200);
 
 }
@@ -128,7 +171,7 @@ DataViewerPanelBase::~DataViewerPanelBase()
   delete pixmap_;
 }
 
-void DataViewerPanelBase::SetData(const Data& d)
+void DataViewerPanelBase::SetData(const ImageHandle& d)
 {
   SetObservedData(d);
   update_min_max();
@@ -150,83 +193,83 @@ ViewerNormalizerPtr DataViewerPanelBase::GetNormalizer() const
   return normalizer_;
 }
 
-#if 0
-void DataViewerPanelBase::OnMenu(QCommandEvent& e)
-{
-  switch(e.GetId()){
-  case ID_PHASECOLOR:
-    if(e.IsChecked()){
-      SetColorMode(RasterImage::PHASECOLOR);
-    }else{
-      SetColorMode(RasterImage::GREY);
-    }
-    break;
-  case ID_NORMALIZE:
-    Renormalize();
-    break;
-  case ID_CENTER:
-    Recenter();
-    break;
-  case ID_INVERT:
-    SetInvert(!GetInvert());
-    break;
-  case ID_DISP_PIXEL_VAL:
-    SetDisplayPixelValues(!display_pixel_values_);
-    break;
-  case ID_SHOW_CLICK_POS:
-    ShowClickedPosition(!show_clicked_position_);
-    break;
-  case ID_ZOOM_PLUS:
-    SetZoomScale(2.0*GetZoomScale());
-    break;
-  case ID_ZOOM_MINUS:
-    SetZoomScale(0.5*GetZoomScale());
-    break;
-  case ID_ZOOM_1:
-    SetZoomScale(1.0);
-    break;
-  case ID_SLAB_PLUS:
-    SetSlab(GetSlab()+1);
-    break;
-  case ID_SLAB_MINUS:
-    SetSlab(GetSlab()-1);
-    break;
-  case ID_SLAB_START:
-    SetSlab(GetObservedData().GetExtent().GetStart()[2]);
-    break;
-  case ID_SLAB_END:
-    SetSlab(GetObservedData().GetExtent().GetEnd()[2]);
-    break;
-  case ID_SLAB_CENTER:
-    SetSlab(static_cast<int>((GetObservedData().GetExtent().GetEnd()[2]
-                             -GetObservedData().GetExtent().GetStart()[2])/2.0));
-    break;
-  default:
-    e.Skip();
-    break;
+void DataViewerPanelBase::toggle_phase_color(){
+  if(GetColorMode()!=RasterImage::PHASECOLOR){
+    SetColorMode(RasterImage::PHASECOLOR);
+  }else{
+    SetColorMode(RasterImage::GREY);
   }
 }
-void DataViewerPanelBase::OnUpdateMenu(QUpdateUIEvent& e)
+void DataViewerPanelBase::normalize(){
+  Renormalize();
+}
+void DataViewerPanelBase::center(){
+  Recenter();
+}
+void DataViewerPanelBase::toggle_invert(){
+  SetInvert(!GetInvert());
+}
+void DataViewerPanelBase::toggle_display_pixels(){
+  SetDisplayPixelValues(!display_pixel_values_);
+}
+void DataViewerPanelBase::toggle_show_click_pos(){
+  ShowClickedPosition(!show_clicked_position_);
+}
+void DataViewerPanelBase::zoom_plus(){
+  SetZoomScale(2.0*GetZoomScale());
+}
+void DataViewerPanelBase::zoom_minus(){
+  SetZoomScale(0.5*GetZoomScale());
+}
+void DataViewerPanelBase::zoom_reset(){
+  SetZoomScale(1.0);
+}
+void DataViewerPanelBase::slab_plus(){
+  SetSlab(GetSlab()+1);
+}
+void DataViewerPanelBase::slab_minus(){
+  SetSlab(GetSlab()-1);
+}
+void DataViewerPanelBase::slab_start(){
+  SetSlab(GetObservedData().GetExtent().GetStart()[2]);
+}
+void DataViewerPanelBase::slab_end(){
+  SetSlab(GetObservedData().GetExtent().GetEnd()[2]);
+}
+void DataViewerPanelBase::slab_center(){
+  SetSlab(static_cast<int>((GetObservedData().GetExtent().GetEnd()[2]
+                           -GetObservedData().GetExtent().GetStart()[2])/2.0));
+}
+void DataViewerPanelBase::toggle_fast_low_mag(){
+  SetFastLowMagnificationDrawing(!GetFastLowMagnificationDrawing());
+}
+void DataViewerPanelBase::toggle_fast_high_mag(){
+  SetFastHighMagnificationDrawing(!GetFastHighMagnificationDrawing());
+}
+void DataViewerPanelBase::toggle_antialiasing(){
+  SetAntialiasing(!GetAntialiasing());
+}
+
+void DataViewerPanelBase::SetFastLowMagnificationDrawing(bool flag)
 {
-  switch(e.GetId()){
-  case ID_PHASECOLOR:
-    e.Check(GetColorMode()==RasterImage::PHASECOLOR);
-    break;
-  case ID_INVERT:
-    e.Check(GetInvert());
-    break;
-  case ID_DISP_PIXEL_VAL:
-    e.Check(display_pixel_values_);
-    break;
-  case ID_SHOW_CLICK_POS:
-    e.Check(show_clicked_position_);
-    break;
-  default:
-    e.Skip();
-    break;
-  }
+  fast_low_mag_=flag;
+  fast_low_mag_toggle_action_->setChecked(flag);
+  UpdateView();
+}
+bool DataViewerPanelBase::GetFastLowMagnificationDrawing()
+{
+  return fast_low_mag_;
+}
+void DataViewerPanelBase::SetFastHighMagnificationDrawing(bool flag)
+{
+  fast_high_mag_=flag;
+  fast_high_mag_toggle_action_->setChecked(flag);
+  UpdateView();
+}
+bool DataViewerPanelBase::GetFastHighMagnificationDrawing()
+{
+  return fast_high_mag_;
 }
-#endif
 
 void DataViewerPanelBase::Renormalize() 
 {
@@ -252,12 +295,6 @@ void DataViewerPanelBase::ObserverUpdate()
   update_min_max();
   UpdateNormalizer(data_min_,data_max_,normalizer_->GetGamma(),normalizer_->GetInvert());
   UpdateView(true);
-
-  /*
-  QCommandEvent ev=QCommandEvent(QEVT_VIEWER_DATA_CHANGE,GetId());
-  ev.SetEventObject(this);
-  AddPendingEvent(ev);
-  */
 }
 
 void DataViewerPanelBase::ObserverUpdate(const Extent& e)
@@ -347,11 +384,6 @@ void DataViewerPanelBase::ObserverUpdate(const Point& p)
 void DataViewerPanelBase::ObserverRelease()
 {
   emit released();
-  /*
-  QCommandEvent ev=QCommandEvent(QEVT_VIEWER_RELEASE,GetId());
-  ev.SetEventObject(this);
-  AddPendingEvent(ev);
-  */
 }
 
 void DataViewerPanelBase::resizeEvent(QResizeEvent* event)
@@ -433,6 +465,12 @@ void DataViewerPanelBase::paintEvent(QPaintEvent* event)
   if(zoom_level_<7) {
     draw_extent(painter);
   }
+  if(show_clicked_position_){
+    painter.setPen(QPen(QColor(0,255,0),1));
+    painter.setBrush(QBrush(Qt::NoBrush));
+    painter.drawLine(FracPointToWin(geom::Vec2(clicked_position_))-QPoint(4,0),FracPointToWin(geom::Vec2(clicked_position_))+QPoint(4,0));
+    painter.drawLine(FracPointToWin(geom::Vec2(clicked_position_))-QPoint(0,4),FracPointToWin(geom::Vec2(clicked_position_))+QPoint(0,4));
+  }
 }
 
 void DataViewerPanelBase::keyPressEvent(QKeyEvent * event)
@@ -475,11 +513,17 @@ void DataViewerPanelBase::mousePressEvent(QMouseEvent* event)
   if(!IsDataValid()) return;
   if(event->button() == Qt::LeftButton && event->modifiers()==Qt::NoModifier) {
     selection_=Extent();
+    update(rubberband_->geometry());
     rubberband_->setGeometry(QRect(event->pos(),QSize(0,0)));
     rubberband_->hide();
     last_x_=event->x();
     last_y_=event->y();
+    geom::Vec3 old_position=clicked_position_;
     clicked_position_ = geom::Vec3(WinToFracPoint(QPoint(event->x(),event->y())));
+    if(show_clicked_position_){
+      update(QRect(FracPointToWin(geom::Vec2(old_position))-QPoint(4,4),FracPointToWin(geom::Vec2(old_position))+QPoint(4,4)));
+      update(QRect(FracPointToWin(geom::Vec2(clicked_position_))-QPoint(4,4),FracPointToWin(geom::Vec2(clicked_position_))+QPoint(4,4)));
+    }
     clicked_position_[2]=slab_;
     emit clicked(clicked_position_);
 
@@ -696,6 +740,7 @@ void DataViewerPanelBase::SetCursor(const QCursor& cursor)
 void DataViewerPanelBase::SetDisplayPixelValues(bool show)
 {
   display_pixel_values_ = show;
+  display_pixel_toggle_action_->setChecked(show);
   UpdateView(false);
 }
 
@@ -855,6 +900,7 @@ void DataViewerPanelBase::slab(int dz)
 void DataViewerPanelBase::SetColorMode(RasterImage::Mode m) 
 {
   cmode_=m;
+  phase_toggle_action_->setChecked(m==RasterImage::PHASECOLOR);
   UpdateView(true);
 }
 
@@ -872,7 +918,8 @@ ImageHandle DataViewerPanelBase::Extract(const Extent& e)
 void DataViewerPanelBase::ShowClickedPosition(bool show = true)
 {
   show_clicked_position_ = show;
-  UpdateView(false);
+  show_click_pos_toggle_action_->setChecked(show);
+  update(QRect(FracPointToWin(geom::Vec2(clicked_position_))-QPoint(4,4),FracPointToWin(geom::Vec2(clicked_position_))+QPoint(4,4)));
 }
 
 void DataViewerPanelBase::HideClickedPosition()
@@ -935,6 +982,7 @@ void DataViewerPanelBase::SetInvert(bool invert)
   UpdateNormalizer(normalizer_->GetMinimum(),
                    normalizer_->GetMaximum(),
                    normalizer_->GetGamma(),invert);
+  invert_toggle_action_->setChecked(invert);
   UpdateView(true);
 }
 
@@ -988,6 +1036,7 @@ void DataViewerPanelBase::SetOffset(const geom::Vec2& offset)
 void DataViewerPanelBase::SetAntialiasing(bool f)
 {
   antialiasing_=f;
+  antialiasing_toggle_action_->setChecked(f);
   update();
 }
 
@@ -1014,8 +1063,7 @@ void DataViewerPanelBase::draw_pixel_values(QPainter& painter)
   if(GetObservedData().GetType()==REAL){
     for(int i = 0; i <= (b[0] - a[0]); ++i) {
       for(int j = 0; j <= (b[1] - a[1]); ++j) {
-        Real pixel_value = GetObservedData().GetReal(Point(a[0]+i,
-                                                                 a[1]+j,slab_));
+        Real pixel_value = GetObservedData().GetReal(Point(a[0]+i,a[1]+j,slab_));
         QString value_string = QString("%1").arg(pixel_value,0,'g',5);
         Real rv = GetNormalizer()->Convert(pixel_value);
         QPoint p = FracPointToWinCenter(geom::Vec2(static_cast<Real>(a[0]+i),
@@ -1048,7 +1096,9 @@ void DataViewerPanelBase::draw_pixel_values(QPainter& painter)
 
 void DataViewerPanelBase::update_rubberband_from_selection_()
 {
+  QRect old_geometry=rubberband_->geometry();
   rubberband_->setGeometry(QRect(PointToWin(selection_.GetStart()),PointToWin(selection_.GetEnd()+Point(1,1))));
+  update(old_geometry);
 }
 
 }}}  //ns
diff --git a/modules/gui/src/data_viewer/data_viewer_panel_base.hh b/modules/gui/src/data_viewer/data_viewer_panel_base.hh
index 1727ea9a3e0d5c0fa6c2c9363e9acc77eaf72996..699efd372cad4dc5b0a9f26a205b4487f5b33168 100644
--- a/modules/gui/src/data_viewer/data_viewer_panel_base.hh
+++ b/modules/gui/src/data_viewer/data_viewer_panel_base.hh
@@ -32,6 +32,7 @@
 
 #include <ost/base.hh>
 #include <ost/img/extent.hh>
+#include <ost/img/data_observer.hh>
 #include <ost/img/normalizer_impl.hh>
 #include <ost/img/raster_image/raster_image.hh>
 
@@ -56,10 +57,10 @@ class DLLEXPORT_OST_GUI DataViewerPanelBase: public QWidget,
   Q_OBJECT;
 
 public:
-  DataViewerPanelBase(const Data& data,QWidget* parent);
+  DataViewerPanelBase(const ImageHandle& data,QWidget* parent);
   virtual ~DataViewerPanelBase();
 
-  virtual void SetData(const Data& d);
+  virtual void SetData(const ImageHandle& d);
 
   //////////////////
   // event handling
@@ -71,8 +72,6 @@ public:
   virtual void mouseMoveEvent(QMouseEvent* event);
   virtual void keyPressEvent(QKeyEvent * event);
 
-  //void OnMenu(wxCommandEvent& e);
-  //void OnUpdateMenu(wxUpdateUIEvent& e);
 
   //////////////////////
   // observer interface
@@ -160,10 +159,10 @@ public:
   RasterImage::Mode GetColorMode(){return cmode_;};
 
   //! set/get fast drawing modes for low and high magnification
-  void SetFastLowMagnificationDrawing(bool flag){fast_low_mag_=flag;UpdateView();}  
-  bool GetFastLowMagnificationDrawing(){return fast_low_mag_;}
-  void SetFastHighMagnificationDrawing(bool flag){fast_high_mag_=flag;UpdateView();}  
-  bool GetFastHighMagnificationDrawing(){return fast_high_mag_;}
+  void SetFastLowMagnificationDrawing(bool flag);
+  bool GetFastLowMagnificationDrawing();
+  void SetFastHighMagnificationDrawing(bool flag);
+  bool GetFastHighMagnificationDrawing();
 
   geom::Vec2 GetMousePosition(){return mouseposition_;};
   void MoveTo(const geom::Vec2& p);
@@ -206,6 +205,27 @@ signals:
 protected:
   QMenu* popupmenu_;
 
+protected slots:
+  // slots for popup menu
+  void toggle_phase_color();
+  void normalize();
+  void center();
+  void toggle_invert();
+  void toggle_display_pixels();
+  void toggle_show_click_pos();
+  void zoom_plus();
+  void zoom_minus();
+  void zoom_reset();
+  void slab_plus();
+  void slab_minus();
+  void slab_start();
+  void slab_end();
+  void slab_center();
+  void toggle_fast_low_mag();
+  void toggle_fast_high_mag();
+  void toggle_antialiasing();
+
+
 private:
   Real data_min_;
   Real data_max_;
@@ -246,6 +266,14 @@ private:
 
   bool antialiasing_;
   Point drag_start_;
+  QAction* phase_toggle_action_;
+  QAction* invert_toggle_action_;
+  QAction* show_click_pos_toggle_action_;
+  QAction* fast_low_mag_toggle_action_;
+  QAction* fast_high_mag_toggle_action_;
+  QAction* display_pixel_toggle_action_;
+  QAction* antialiasing_toggle_action_;
+
 
   void move(int dx, int dy);
   void slab(int dz);
diff --git a/modules/gui/src/data_viewer/fft_panel.cc b/modules/gui/src/data_viewer/fft_panel.cc
index 17dd63b4a9da18678ae40f712241b1c9a2a98f67..554cc67c2a6c5ec3a62139042a9c66e0ae7172d3 100644
--- a/modules/gui/src/data_viewer/fft_panel.cc
+++ b/modules/gui/src/data_viewer/fft_panel.cc
@@ -32,7 +32,7 @@
 
 namespace ost { namespace img { namespace gui {
     
-FFTPanel::FFTPanel(const Data& parent_data, QWidget* parent):
+FFTPanel::FFTPanel(const ImageHandle& parent_data, QWidget* parent):
   DataViewerPanelBase(parent_data,parent),
   size_(std::min<int>(256,std::min<int>(parent_data.GetSize()[0],parent_data.GetSize()[1]))),
   parent_position_(parent_data.GetExtent().GetCenter()),
@@ -95,7 +95,7 @@ unsigned int FFTPanel::GetFFTSize()
   return size_;
 }
 
-void FFTPanel::SetData(const Data& parent_data)
+void FFTPanel::SetData(const ImageHandle& parent_data)
 {
   parent_observer_=ParentDataObserver(parent_data);
 }
diff --git a/modules/gui/src/data_viewer/fft_panel.hh b/modules/gui/src/data_viewer/fft_panel.hh
index 2add54b8d2ca8140a078249250382751dc18ae3e..75a30fed87e8a1018887d10a56fd7e0465674ce0 100644
--- a/modules/gui/src/data_viewer/fft_panel.hh
+++ b/modules/gui/src/data_viewer/fft_panel.hh
@@ -25,6 +25,7 @@
 */
 
 #include <ost/gui/module_config.hh>
+#include <ost/img/data_observer.hh>
 #include "data_viewer_panel_base.hh"
 
 namespace ost { namespace img { namespace gui {
@@ -32,7 +33,7 @@ namespace ost { namespace img { namespace gui {
 class ParentDataObserver: public DataObserver
 {
 public:
-  ParentDataObserver(const Data& d):DataObserver(d){}
+  ParentDataObserver(const ImageHandle& d):DataObserver(d){}
   virtual void ObserverRelease()
   {
    // Noop as parent takes care of this.
@@ -44,12 +45,12 @@ class DLLEXPORT_OST_GUI FFTPanel: public DataViewerPanelBase
 Q_OBJECT
 
 public:
-  FFTPanel(const Data& parent_data, QWidget* parent);
+  FFTPanel(const ImageHandle& parent_data, QWidget* parent);
   virtual ~FFTPanel();
   void SetFFTSize(unsigned int size);
   unsigned int GetFFTSize();
   virtual void ObserverUpdate();
-  virtual void SetData(const Data& parent_data);
+  virtual void SetData(const ImageHandle& parent_data);
 
 public slots:
   void SetPosition(const Point& p);
diff --git a/modules/gui/src/data_viewer/img2qt.cc b/modules/gui/src/data_viewer/img2qt.cc
index 2194c6030b115e53e230857601d45964bc46e469..fdf5b8cb415b72fa918069162208fea2ff36505e 100644
--- a/modules/gui/src/data_viewer/img2qt.cc
+++ b/modules/gui/src/data_viewer/img2qt.cc
@@ -70,15 +70,6 @@ public:
 
   }
 
-  void VisitFunction(const Function& f)
-  {
-    for(int y=0;y<img_->size().height();++y) {
-      for(int x=0;x<img_->size().width();++x) {
-        int cv=clamp(static_cast<int>(norm_->Convert(f.GetReal(Point(x,y)+off_))),0,255);
-        img_->setPixel(x,y,qRgb(cv,cv,cv));
-      }
-    }
-  }
 
   static String GetAlgorithmName() {return "Conv0";}
 
diff --git a/modules/gui/src/data_viewer/info_panel.cc b/modules/gui/src/data_viewer/info_panel.cc
index f90d45b17feb18b469fb205e4ad36f684f395932..a593884b16e90db34d864fa075c118adab3f22bf 100644
--- a/modules/gui/src/data_viewer/info_panel.cc
+++ b/modules/gui/src/data_viewer/info_panel.cc
@@ -64,9 +64,9 @@ InfoPanel::InfoPanel(QWidget* parent):
   QFont fnt=font();
   fnt.setPointSize(font().pointSize()-1);
   setFont(fnt);
-  int maxw = QFontMetrics(fnt).width("(9999,9999,1) to (9999,9999,1)");
-  setMaximumWidth(maxw);
-  setMinimumWidth(maxw);
+  //int maxw = QFontMetrics(fnt).width("(9999,9999,1) to (9999,9999,1)");
+  //setMaximumWidth(maxw);
+  //setMinimumWidth(maxw);
 
   QFont fnt2(fnt);
   fnt2.setWeight(QFont::Bold);
diff --git a/modules/gui/src/file_browser.cc b/modules/gui/src/file_browser.cc
index a41ff0a293f864c6a43f67382d5acf4236dedeb2..7c33f7d1f48ba176eaae8df1990ee98d121dc910 100644
--- a/modules/gui/src/file_browser.cc
+++ b/modules/gui/src/file_browser.cc
@@ -267,7 +267,7 @@ void FileBrowser::ShowContextMenu(const QPoint& pos){
     }
     menu->addAction(system_open_action);
   }
-  if(menu->actions().size()>0){
+  if(! menu->actions().empty()){
     menu->exec(QCursor::pos());
   }
 }
diff --git a/modules/gui/src/gl_win.cc b/modules/gui/src/gl_win.cc
index cfaade7eab9f85915b5217ab9ce398d28d38c1c0..fc584da9b937abeb26c2eb282cc34d8781fef517 100644
--- a/modules/gui/src/gl_win.cc
+++ b/modules/gui/src/gl_win.cc
@@ -58,7 +58,7 @@ gl_canvas_(NULL)
   
   if(try_stereo) {
     LOG_VERBOSE("GLCanvas: trying stereo visuals first");
-    for(int format_id=3;format_id>=0;--format_id) {
+    for(int format_id=4;format_id>=0;--format_id) {
       QGLFormat format=GLWin::CreateFormat(format_id);
       if (try_stereo) {
         format.setStereo(true);
@@ -76,7 +76,7 @@ gl_canvas_(NULL)
     if(try_stereo) {
       LOG_VERBOSE("GLCanvas: no stereo visual found, trying normal ones");
     }
-    for(int format_id=3;format_id>=0;--format_id) {
+    for(int format_id=4;format_id>=0;--format_id) {
       QGLFormat format=GLWin::CreateFormat(format_id);
       gl_canvas_=new GLCanvas(this, main, format);
       if(gl_canvas_->isValid()) {
@@ -97,16 +97,23 @@ gl_canvas_(NULL)
   gfx::Scene::Instance().AttachObserver(this);
   QGLFormat format = gl_canvas_->format();
 
-  LOG_DEBUG("GLCanvas: rbits=" << format.redBufferSize() 
-               << " gbits=" << format.greenBufferSize() 
-               << " bbits=" << format.blueBufferSize() 
-               << " abits=" << format.alphaBufferSize() 
-               << " dbits=" << format.depthBufferSize()
-               << " accumbits=" << format.accumBufferSize()
-               << " multisample=" << format.sampleBuffers()
-               << " with samples=" << format.samples());
+
+  LOG_VERBOSE("GLCanvas: using " << format.redBufferSize() << "." 
+                              << format.greenBufferSize() << "."
+                              << format.blueBufferSize() << "."
+                              << format.alphaBufferSize() << " RGBA bits, " 
+                              << format.depthBufferSize() << " depth bits, "
+                              << format.accumBufferSize() << " accum bits, and "
+                              << format.stencilBufferSize() << " stencil bits")
   if(gl_canvas_->format().stereo()) {
     LOG_VERBOSE("GLCanvas: using stereo visual");
+  } else {
+    LOG_VERBOSE("GLCanvas: no stereo visual found");
+  }
+  if(format.sampleBuffers()) {
+    LOG_VERBOSE("GLCanvas: using multisampling with " << format.samples() << " samples per pixel");
+  } else {
+    LOG_VERBOSE("GLCanvas: no multisampling");
   }
   main->setCentralWidget(gl_canvas_);
   connect(gl_canvas_, SIGNAL(ReleaseFocus()), this, SIGNAL(ReleaseFocus()));
@@ -129,7 +136,17 @@ void GLWin::ActiveToolChanged(Tool* t)
 QGLFormat GLWin::CreateFormat(int fid)
 {
   QGLFormat format = QGLFormat::defaultFormat();
-  if(fid==3) {
+  if(fid==4) {
+    format.setDepthBufferSize(24);
+    format.setRedBufferSize(8);
+    format.setGreenBufferSize(8);
+    format.setBlueBufferSize(8);
+    format.setAlpha(true);
+    format.setAlphaBufferSize(8);
+    format.setAccum(true);
+    format.setStencil(true);
+    format.setSampleBuffers(true);
+  } else if(fid==3) {
     format.setDepthBufferSize(24);
     format.setRedBufferSize(8);
     format.setGreenBufferSize(8);
diff --git a/modules/gui/src/gosty.cc b/modules/gui/src/gosty.cc
index a0be0fae0762c45d1ae9596cdf57f65c168d8d5a..ad13d07b313a2a018c66cbe4a0aee89d0579097f 100644
--- a/modules/gui/src/gosty.cc
+++ b/modules/gui/src/gosty.cc
@@ -96,8 +96,6 @@ String get_ost_root()
 #else
   #ifdef _MSC_VER
     dir.cdUp();
-    dir.cdUp();
-    dir.cdUp();
   #else
     dir.cdUp();
     dir.cdUp();
@@ -106,25 +104,23 @@ String get_ost_root()
   return dir.path().toStdString();
 }
 
-void setup_python_search_path(const String& root, PythonInterpreter& pi)
+String setup_python_search_path(const String& root, PythonInterpreter& pi)
 {
   std::stringstream site_pkgs;
   site_pkgs << "python" << PY_MAJOR_VERSION << "." << PY_MINOR_VERSION;
 #ifdef _MSC_VER
-  pi.AppendModulePath(QString::fromStdString(root+"\\lib\\"+site_pkgs.str()
-                                             +"\\site-packages"));
+  String loc=root+"\\lib\\"+site_pkgs.str()+"\\site-packages";
 #else  
-#  if (defined(__ppc64__) || defined(__x86_64__)) && !defined(__APPLE__)
-  pi.AppendModulePath(QString::fromStdString(root+"/lib64/"+
-                                             site_pkgs.str()+
-                                             "/site-packages"));
-#  else
-  pi.AppendModulePath(QString::fromStdString(root+"/lib/"+
-                                             site_pkgs.str()+
-                                             "/site-packages"));
-#  endif
+# if (defined(__ppc64__) || defined(__x86_64__)) && !defined(__APPLE__)
+  String loc=root+"/lib64/"+site_pkgs.str()+"/site-packages";
+# else
+  String loc=root+"/lib/"+site_pkgs.str()+"/site-packages";
+# endif
 #endif
+  pi.AppendModulePath(QString::fromStdString(loc));
+  // dng is an interactive python session, so add '.' to search path
   pi.AppendModulePath(".");  
+  return loc;
 }
   
 int setup_resources(QApplication& app) 
@@ -186,9 +182,18 @@ int init_python_interpreter()
                      console_logger,
                      SLOT(AppendOutput(unsigned int, const QString &)));
   }  
-  setup_python_search_path(root, py);
-  py.RunCommand("from ost import *");
-  py.RunCommand("gui_mode=True");
+  String python_loc=setup_python_search_path(root, py);
+  //py.RunCommand("from ost import *");
+  //py.RunCommand("gui_mode=True");
+  std::stringstream cmd;
+  cmd << "execfile('" << python_loc;
+#ifdef _MSC_VER
+  cmd << "\\ost\\gui\\";
+#else  
+  cmd << "/ost/gui/";
+#endif
+  cmd << "gosty_startup.py')";
+  py.RunCommand(QString::fromStdString(cmd.str()));
   return 0;
 }
 
@@ -220,6 +225,9 @@ public:
 
 }
 
+#ifdef _MSC_VER
+  #pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:mainCRTStartup")
+#endif
 // initialise gosty - the graphical open structure interpreter
 int main(int argc, char** argv)
 {
diff --git a/modules/gui/src/gosty_app.cc b/modules/gui/src/gosty_app.cc
index ac5ce3105fec41b031796ae17e86712b7af2ad7e..2c1b644ec94221e4e18ff7ece0957e8cacdef3da 100644
--- a/modules/gui/src/gosty_app.cc
+++ b/modules/gui/src/gosty_app.cc
@@ -109,12 +109,14 @@ SequenceViewer* GostyApp::GetSequenceViewer()
 }
 
 #if OST_IMG_ENABLED
-ost::img::gui::DataViewer* GostyApp::CreateDataViewer(const ost::img::Data& d, const QString& name)
+ost::img::gui::DataViewer* GostyApp::CreateDataViewer(const ost::img::ImageHandle& d, const QString& name)
 {
   ost::img::gui::DataViewer* viewer=new ost::img::gui::DataViewer(main_,d,name);
   QMdiSubWindow* mdi=new QMdiSubWindow(this->GetPerspective()->GetMainArea());
   mdi->setWindowTitle(name);
   mdi->setWidget(viewer);
+  viewer->setAttribute(Qt::WA_DeleteOnClose);
+  mdi->setAttribute(Qt::WA_DeleteOnClose);
   viewer->setParent(mdi);
   this->GetPerspective()->GetMainArea()->addSubWindow(mdi);
   mdi->showMaximized();
diff --git a/modules/gui/src/gosty_app.hh b/modules/gui/src/gosty_app.hh
index 787404aa34abefc5df6a628929284eb8fc8735ed..a635c407ae9cd3e75570101b73aeb3948f0f5910 100644
--- a/modules/gui/src/gosty_app.hh
+++ b/modules/gui/src/gosty_app.hh
@@ -46,7 +46,7 @@ namespace ost {
 
 namespace img { 
 
-class Data;
+class ImageHandle;
 
 namespace gui { 
 class DataViewer; 
@@ -124,7 +124,7 @@ public:
 #if OST_IMG_ENABLED
   /// \brief create new DataViewer
   /// 
-  ost::img::gui::DataViewer* CreateDataViewer(const ost::img::Data& d, const QString& name="");
+  ost::img::gui::DataViewer* CreateDataViewer(const ost::img::ImageHandle& d, const QString& name="");
 #endif
 
   /// \brief give the application time to run the mainloop and process events
diff --git a/modules/gui/src/main_area.cc b/modules/gui/src/main_area.cc
index 230c7d7763bce559f9af741f9b52a9ae48555dc8..3c931ca8e74859b43eae25db173d3d2785b6fad2 100644
--- a/modules/gui/src/main_area.cc
+++ b/modules/gui/src/main_area.cc
@@ -115,10 +115,12 @@ void MainArea::EnableTabbedMode(bool tm)
 void MainArea::AddWidget(const QString& title, QWidget* widget)
 {
   QMdiSubWindow* mdi=new QMdiSubWindow(this);
+  mdi->setAttribute(Qt::WA_DeleteOnClose);
   mdi->setWindowTitle(title);
   mdi->setWidget(widget);
   widget->setParent(mdi);
   this->addSubWindow(mdi);
+  connect(widget, SIGNAL(destroyed()), mdi, SLOT(close()));
   mdi->show();
 }
 
diff --git a/modules/gui/src/main_window.cc b/modules/gui/src/main_window.cc
index f8f428c4350577a4873a2e021727bd2b203ffd92..098e7cfabab81a14ffe20a9c0963f4949d9f257d 100644
--- a/modules/gui/src/main_window.cc
+++ b/modules/gui/src/main_window.cc
@@ -39,11 +39,28 @@ MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags flags):
 
 void MainWindow::AddDockWidget(QWidget* w, const QString& name, bool shown, int area)
 {
+  Qt::DockWidgetArea dock_area;
+  switch(area){
+    case 1:
+      dock_area=Qt::LeftDockWidgetArea;
+      break;
+    case 2:
+      dock_area=Qt::RightDockWidgetArea;
+      break;
+    case 4:
+      dock_area=Qt::TopDockWidgetArea;
+      break;
+    case 8:
+      dock_area=Qt::BottomDockWidgetArea;
+      break;
+    default:
+      dock_area=Qt::RightDockWidgetArea;
+      break;
+  }
   DockWidget* dock = new DockWidget(name, this);
   dock->adjustSize();
-  dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
   dock->setWidget(w);
-  addDockWidget(area==0 ? Qt::RightDockWidgetArea : Qt::LeftDockWidgetArea, dock);
+  addDockWidget(dock_area, dock);
   dock_widget_map_[w]=dock;
   connect(dock,SIGNAL(OnClose(QDockWidget*)),this,SLOT(OnDockClose(QDockWidget*)));
   if(!shown) dock->hide();
diff --git a/modules/gui/src/main_window.hh b/modules/gui/src/main_window.hh
index 2b273f36dd5426f292d9c596537a6581e17916ae..61c6055d15225830ab30b1ba8ac476f43a6e6801 100644
--- a/modules/gui/src/main_window.hh
+++ b/modules/gui/src/main_window.hh
@@ -46,7 +46,7 @@ public:
   MainWindow(QWidget* parent=0, Qt::WindowFlags flags=0);
 
   //! add a custom docking widget
-  void AddDockWidget(QWidget* w, const QString& name, bool show=true, int area=0);
+  void AddDockWidget(QWidget* w, const QString& name, bool show=true, int area=2);
   //! remove a previously added custom docking widget
   void RemoveDockWidget(QWidget* w);
 
diff --git a/modules/gui/src/messages/message_widget.cc b/modules/gui/src/messages/message_widget.cc
index 038840ae1482d064608385c2e62225c8b7f19b88..b16df9afe9a950a5e2071222a56aa9ad6d462ffb 100644
--- a/modules/gui/src/messages/message_widget.cc
+++ b/modules/gui/src/messages/message_widget.cc
@@ -216,7 +216,7 @@ void MessageWidget::ContextMenuRequested(const QPoint& pos) {
 
   QMenu* menu = new QMenu();
   menu->addAction(remove_selected_action);
-  if (menu->actions().size() > 0) {
+  if (! menu->actions().empty()) {
     menu->popup(view_->viewport()->mapToGlobal(pos));
   }
 }
diff --git a/modules/gui/src/perspective.cc b/modules/gui/src/perspective.cc
index 4affd2e1e0aa45fc9de10bbd959278f6cc5bd69b..318f01f2c3343627ad7b15c07c053c4876981f38 100644
--- a/modules/gui/src/perspective.cc
+++ b/modules/gui/src/perspective.cc
@@ -61,7 +61,9 @@ Perspective::Perspective(QMainWindow* parent):
   quick_access_bar_(new QWidget),
   verbosity_slider_(new QSlider(Qt::Horizontal,quick_access_bar_))
 {
+#if !defined(__APPLE__)
   parent->setMenuBar(menu_bar_);
+#endif
 
   QVBoxLayout* l=new QVBoxLayout(central_);
   l->setMargin(0);
diff --git a/modules/gui/src/python_shell/python_context_parser.cc b/modules/gui/src/python_shell/python_context_parser.cc
index 6b5338cea4de8d6fd3df1cf7f2f938701508ca8d..944951114d44e1936d4c32265c9206dc9d39a5d2 100644
--- a/modules/gui/src/python_shell/python_context_parser.cc
+++ b/modules/gui/src/python_shell/python_context_parser.cc
@@ -92,7 +92,7 @@ void PythonContextParser::Parse(PythonContext*& parent_context)
         Parse(current_context);
         if (tokenizer_.CurrentToken().GetType() != PythonToken::END)
           current_context->AddToken(tokenizer_.CurrentToken());   
-        else if (current_context->GetSubContexts().size() > 0) {
+        else if (! current_context->GetSubContexts().empty()) {
           Range last_sub = current_context->GetSubContexts().back()->GetRange();
           Range curr_range(current_context->GetRange().location,
                            last_sub.End()-current_context->GetRange().location);
diff --git a/modules/gui/src/python_shell/python_interpreter.cc b/modules/gui/src/python_shell/python_interpreter.cc
index 08b745b714a21ff9014ab2420784bd63e068296a..8fe84743fa5e1d70ea746719a3c2a263db3a7914 100644
--- a/modules/gui/src/python_shell/python_interpreter.cc
+++ b/modules/gui/src/python_shell/python_interpreter.cc
@@ -126,7 +126,7 @@ CodeBlockStatus PythonInterpreter::GetCodeBlockStatus(const QString& command)
       break;
     }
     bool complete=false;
-    if (!(lines[i].size()>0 && (lines[i][0]=='\t' || lines[i][0]==' '))) {
+    if (!(! lines[i].isEmpty() && (lines[i][0]=='\t' || lines[i][0]==' '))) {
       cmd.clear();
     }
     while (!complete && i<lines.size()) {
diff --git a/modules/gui/src/python_shell/python_namespace_tree_item.cc b/modules/gui/src/python_shell/python_namespace_tree_item.cc
index 465c99f6fa3fdd77dda068809dd72518285e1df4..b3e2960901f91b003c3fed8184f5d9e39a6313e6 100644
--- a/modules/gui/src/python_shell/python_namespace_tree_item.cc
+++ b/modules/gui/src/python_shell/python_namespace_tree_item.cc
@@ -82,7 +82,7 @@ QString PythonNamespaceTreeItem::GetName()  const
 bool PythonNamespaceTreeItem::HasChildren() const 
 {
   if (initialized_) {
-    return children_.size()>0;
+    return ! children_.empty();
   } else {
     return true;
   }
diff --git a/modules/gui/src/python_shell/python_shell_widget.cc b/modules/gui/src/python_shell/python_shell_widget.cc
index 8b0fd88d3456405632b9068fb98fed33359e5aea..9adafdd7c764e8727f3a7dab0912c4b82347bbd3 100644
--- a/modules/gui/src/python_shell/python_shell_widget.cc
+++ b/modules/gui/src/python_shell/python_shell_widget.cc
@@ -521,7 +521,7 @@ void PythonShellWidget::OnExecuteStateEntered()
   QString command=GetCommand();
 
   QString command_trimmed=command.trimmed();
-  if (command_trimmed.size()>0) {
+  if (! command_trimmed.isEmpty()) {
     unsigned int id=PythonInterpreter::Instance().RunCommand(command);
     output_blocks_.insert(id,textCursor().block());
     history_.AppendCommand(command_trimmed,get_block_edit_mode_());
@@ -878,11 +878,11 @@ void PythonShellWidget::insertFromMimeData(const QMimeData * source)
     lines[i]=QString(num_spaces, '\t')+right;
   }
   text=lines.join(QString(1, QChar::LineSeparator));
-  if(lines.size()>0){
+  if(! lines.empty()){
     machine_->setActive(multiline_active_state_);
   }
   QPlainTextEdit::insertFromMimeData(source);
-  if(lines.size()>0){
+  if(! lines.empty()){
     set_block_type_(block_edit_start_,document()->lastBlock(),BLOCKTYPE_BLOCKEDIT);
   }
   setFocus();
diff --git a/modules/gui/src/scene_selection.cc b/modules/gui/src/scene_selection.cc
index f0fea54e2f196b624d1d814890162386817386d9..2faa79d6c09bbe1c5e3092126cf42a2acbe03bfb 100644
--- a/modules/gui/src/scene_selection.cc
+++ b/modules/gui/src/scene_selection.cc
@@ -197,7 +197,7 @@ void SceneSelection::Hide() {
 
 mol::EntityView SceneSelection::GetViewUnion() {
   mol::EntityView view;
-  if(views_.size()>0){
+  if(! views_.empty()){
     view = views_[0].GetEntityView().Copy();
     for(unsigned int i = 1; i < views_.size(); i++){
       view = mol::Union(view,views_[i].GetEntityView());
diff --git a/modules/gui/src/scene_win/context_menu.cc b/modules/gui/src/scene_win/context_menu.cc
index 1834b71a4db5170185b1a86191c5ae0ca90438a0..370800556aa052a3f11460a4c0578dfb2935c157 100644
--- a/modules/gui/src/scene_win/context_menu.cc
+++ b/modules/gui/src/scene_win/context_menu.cc
@@ -125,7 +125,7 @@ void ContextMenu::ShowMenu(const QPoint& pos)
 
   gfx::EntityP view_entity = gfx::EntityP();
   int cnt = 0;
-  if(indexes.size()>0){
+  if(! indexes.empty()){
     for(int i = 0; i < indexes.size(); i++){
       if(indexes[i].column()==0){
         cnt++;
@@ -209,7 +209,7 @@ void ContextMenu::ShowMenu(const QPoint& pos)
         }
     }
 
-    if(menu->actions().size()>0){
+    if(! menu->actions().empty()){
       menu->popup(pos);
     }
   }
diff --git a/modules/gui/src/sequence_viewer/secstr_row.cc b/modules/gui/src/sequence_viewer/secstr_row.cc
index 1f7153753832abd520ea59a9481f8e46e2b561b6..50239343426ec233a0641ed5958a9a1d2e1ef7fd 100644
--- a/modules/gui/src/sequence_viewer/secstr_row.cc
+++ b/modules/gui/src/sequence_viewer/secstr_row.cc
@@ -98,7 +98,7 @@ void SecStrRow::DoubleClicked(int column)
   if(column>0){
     column-=1;
     const QVarLengthArray<mol::SecStructure>& sec = this->secstr_;
-    if(sec.size()>0 && column < sec.size()){
+    if(! sec.isEmpty()>0 && column < sec.size()){
       const mol::SecStructure& src_str = sec[column];
       QVarLengthArray<bool> src_type(3);
       src_type[0] = src_str.IsHelical();
diff --git a/modules/gui/src/sequence_viewer/seq_secstr_painter.cc b/modules/gui/src/sequence_viewer/seq_secstr_painter.cc
index 2fd54b35e3f1cab696cb58f7f6c2e4e761ca3562..8d07b4dd0f0145f2a2bf8fb5010d9a6f6c95c2e7 100644
--- a/modules/gui/src/sequence_viewer/seq_secstr_painter.cc
+++ b/modules/gui/src/sequence_viewer/seq_secstr_painter.cc
@@ -38,7 +38,7 @@ void SeqSecStrPainter::Paint(QPainter* painter, const QStyleOptionViewItem& opti
   painter->setPen(QPen(Qt::lightGray));
   const QVarLengthArray<mol::SecStructure>& sec_str = index.data(Qt::UserRole).value<QVarLengthArray<mol::SecStructure> >();
   int column = index.column()-1;
-  if(sec_str.size()>0 && column < sec_str.size()){
+  if(! sec_str.isEmpty() && column < sec_str.size()){
     QSize size = index.data(Qt::UserRole+1).toSize();
     mol::SecStructure sec_element = sec_str[column];
 
diff --git a/modules/gui/src/sequence_viewer/sequence_viewer.cc b/modules/gui/src/sequence_viewer/sequence_viewer.cc
index 29314805cad9465325bad4281f8e670a3e8bb2ad..85ff6ece69a9ab57da281a0b310233d6cf3a17dc 100644
--- a/modules/gui/src/sequence_viewer/sequence_viewer.cc
+++ b/modules/gui/src/sequence_viewer/sequence_viewer.cc
@@ -315,7 +315,7 @@ void SequenceViewer::CopyEvent(QKeyEvent* event)
 {
   QItemSelectionModel* model = seq_table_view_->selectionModel();
   const QModelIndexList& list = model->selectedIndexes();
-  if(list.size()>0){
+  if(! list.empty()){
     QString clipboard_string;
     QSet<int> rows;
     int min_col=model_->columnCount();
@@ -388,7 +388,7 @@ void SequenceViewer::SelectList(const QModelIndexList& list)
       rows_visited.insert(row);
     }
   }
-  if (list.size() > 0) {
+  if (! list.empty()) {
     int last_row = 0;
     int last_col = 0;
     QModelIndex topleft_idx;
diff --git a/modules/gui/src/tools/manipulator.cc b/modules/gui/src/tools/manipulator.cc
index c24691c4463aaf276c11ebac494eca384840b661..ee663099d35393bb0ea9698f87256fbc90056bd0 100644
--- a/modules/gui/src/tools/manipulator.cc
+++ b/modules/gui/src/tools/manipulator.cc
@@ -39,27 +39,44 @@ Manipulator::Manipulator():
 
 void Manipulator::MouseMove(const MouseEvent& event)
 {
-  if (event.GetButtons()==MouseEvent::LeftButton) {
-    if (event.IsShiftPressed()) {
-      SendCommand(gfx::INPUT_COMMAND_TRANSX,
-                  static_cast<Real>(event.GetDelta().x()));
-      SendCommand(gfx::INPUT_COMMAND_TRANSY,
-                  static_cast<Real>(-event.GetDelta().y()));
-    } else {
-      SendCommand(gfx::INPUT_COMMAND_ROTY,
-                  static_cast<Real>(event.GetDelta().x())); // rotation around y
-      SendCommand(gfx::INPUT_COMMAND_ROTX,
-                  static_cast<Real>(event.GetDelta().y())); // rotation around x
-    }
-  } else if (event.GetButtons()==MouseEvent::MiddleButton) {
+  static bool warn=true;
+  // reference is GLCanvas::HandleMouseMoveEvent
+  if (event.GetButtons() & MouseEvent::LeftButton) {
+    if (event.GetButtons() & MouseEvent::MiddleButton) {
       if (event.IsShiftPressed()) {
-        // rotation around z
+        // slab in view, ignore here
+      } else {
         Real d=static_cast<Real>(event.GetDelta().x()+event.GetDelta().y());
-        SendCommand(gfx::INPUT_COMMAND_ROTZ, d);        
+        SendCommand(gfx::INPUT_COMMAND_ROTZ, -d);
+      }
+    } else {
+      if (event.IsShiftPressed()) {
+        SendCommand(gfx::INPUT_COMMAND_TRANSX,
+                    static_cast<Real>(event.GetDelta().x()));
+        SendCommand(gfx::INPUT_COMMAND_TRANSY,
+                    static_cast<Real>(-event.GetDelta().y()));
       } else {
-        SendCommand(gfx::INPUT_COMMAND_TRANSZ,
-                    static_cast<Real>(event.GetDelta().y())); // translate along z
+        SendCommand(gfx::INPUT_COMMAND_ROTY,
+                    static_cast<Real>(event.GetDelta().x())); // rotation around y
+        SendCommand(gfx::INPUT_COMMAND_ROTX,
+                    static_cast<Real>(event.GetDelta().y())); // rotation around x
+      }
+    }
+  } else if (event.GetButtons() & MouseEvent::MiddleButton) {
+    if (event.IsShiftPressed()) {
+      if(warn) {
+        LOG_WARNING("Manipulation Tool: MMB + Shift for z rotation is deprecated; use LMB+MMB instead");
+        warn=false;
       }
+      // rotation around z
+      // WHY? this does not match the scene view transformation, which has a slab tf here
+      // will be removed in a next update...
+      Real d=static_cast<Real>(event.GetDelta().x()+event.GetDelta().y());
+      SendCommand(gfx::INPUT_COMMAND_ROTZ, d);        
+    } else {
+      SendCommand(gfx::INPUT_COMMAND_TRANSZ,
+                  static_cast<Real>(event.GetDelta().y())); // translate along z
+    }
   }  
 }
 
diff --git a/modules/gui/src/tools/measure_tool.cc b/modules/gui/src/tools/measure_tool.cc
index 79de57b9689ca180c61b9e81a13034f2444394c2..5b4cc3d2cd039fb59cbf3bbe0bc6326bb2a8e2e6 100644
--- a/modules/gui/src/tools/measure_tool.cc
+++ b/modules/gui/src/tools/measure_tool.cc
@@ -205,7 +205,7 @@ Measurement::Measurement(mol::AtomHandleList ahl, gfx::Color col, Real line_widt
       name_=ahl_[0].GetQualifiedName()+" - "+ahl_[1].GetQualifiedName()+" - "
              +ahl_[2].GetQualifiedName();
       measurement_=57.2958*geom::Angle(ahl_[0].GetPos()-ahl_[1].GetPos(),
-                                       ahl_[1].GetPos()-ahl_[2].GetPos());
+                                       ahl_[2].GetPos()-ahl_[1].GetPos());
       valid_=true;
       break;
     }
diff --git a/modules/img/alg/pymod/wrap_alg.cc b/modules/img/alg/pymod/wrap_alg.cc
index 7185f34021a1b70e7f6a8f380896ec7feeafcdc6..b024609d30df25346d118fbfaa133b1526908a6a 100644
--- a/modules/img/alg/pymod/wrap_alg.cc
+++ b/modules/img/alg/pymod/wrap_alg.cc
@@ -236,7 +236,7 @@ BOOST_PYTHON_MODULE(_ost_img_alg)
     .def("GetBlocksize",&alg::DiscreteShrink::GetBlocksize)
     ;
 
-  class_<alg::FractionalShift, bases<ModIPAlgorithm> >("FractionalShift", init<optional <Real,Real,Real> >() )
+  class_<alg::FractionalShift, bases<ConstModIPAlgorithm> >("FractionalShift", init<optional <Real,Real,Real> >() )
     .def(init<const Vec3&>())
     .def("SetShift",frac_shift0)
     .def("SetShift",frac_shift1)
diff --git a/modules/img/alg/src/fft.cc b/modules/img/alg/src/fft.cc
index ddc137d1a5272ee98d091b211458ce3791f0c7c7..955f218346844dedbb6e816606664be9f864169b 100644
--- a/modules/img/alg/src/fft.cc
+++ b/modules/img/alg/src/fft.cc
@@ -78,39 +78,12 @@ template <>
 ImageStateBasePtr FFTFnc::VisitState<Real,SpatialDomain>(const RealSpatialImageState& in_state) const
 {
   int rank,n[3]; // for actual fftw call
-  size_t block_count,src_size,dst_size; // padding parameters
 
   Size in_size = in_state.GetExtent().GetSize();
-
-  switch (in_size.GetDim()) {
-  case 1: 
-    rank = 1; 
-    n[0] = in_size.GetWidth();
-    block_count=1;
-    src_size=n[0]; // real values
-    dst_size=half_plus_one(n[0]); // complex values
-    break;
-  case 2: 
-    rank = 2; 
-    n[0] = in_size.GetWidth();
-    n[1] = in_size.GetHeight();
-    block_count=n[0];
-    src_size=n[1]; // real values
-    dst_size=half_plus_one(n[1]); // complex values
-    break;
-  case 3:
-    rank = 3; 
-    n[0] = in_size.GetWidth();
-    n[1] = in_size.GetHeight();
-    n[2] = in_size.GetDepth();
-    block_count=n[0]*n[1];
-    src_size=n[2]; // real values
-    dst_size=half_plus_one(n[2]); // complex values
-    break;
-  default:
-    throw(FFTException("unexpected dimension in FFT R2C"));
-  }
-
+  n[0] = in_size.GetWidth();
+  n[1] = in_size.GetHeight();
+  n[2] = in_size.GetDepth();
+  rank=in_size.GetDim();
 
   PixelSampling ps=in_state.GetSampling();
   ps.SetDomain(FREQUENCY);
@@ -121,25 +94,10 @@ ImageStateBasePtr FFTFnc::VisitState<Real,SpatialDomain>(const RealSpatialImageS
   out_state->SetAbsoluteOrigin(in_state.GetAbsoluteOrigin());
 
   assert(sizeof(OST_FFTW_fftw_complex)==sizeof(Complex));
-  OST_FFTW_fftw_complex* fftw_out =
-reinterpret_cast<OST_FFTW_fftw_complex*>(out_state->Data().GetData());
-
-  /*
-    Since the input array is not preserved in fftw3, a copy is made, and
-    then an in-place transform is performed. The real array must be padded
-    correctly for this to work. 
-  */
-  Real* fftw_in = reinterpret_cast<Real*>(fftw_out);
-  Real* in_ptr = reinterpret_cast<Real*>(in_state.Data().GetData());
-
-  for(size_t i=0;i<block_count;i++) {
-    std::copy(&in_ptr[i*src_size],&in_ptr[(i+1)*src_size],&fftw_in[i*2*dst_size]);
-  }
+  OST_FFTW_fftw_complex* fftw_out = reinterpret_cast<OST_FFTW_fftw_complex*>(out_state->Data().GetData());
+  Real* fftw_in = const_cast<Real*>(in_state.Data().GetData());
   OST_FFTW_fftw_plan_with_nthreads(std::max<int>(1,IDEAL_NUMBER_OF_THREADS()));
-  OST_FFTW_fftw_plan plan = OST_FFTW_fftw_plan_dft_r2c(rank,n,
-				     fftw_in,fftw_out,
-				     FFTW_ESTIMATE);
-
+  OST_FFTW_fftw_plan plan = OST_FFTW_fftw_plan_dft_r2c(rank,n,fftw_in,fftw_out,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
   OST_FFTW_fftw_execute(plan);
   OST_FFTW_fftw_destroy_plan(plan);
 
@@ -153,9 +111,11 @@ template <>
 ImageStateBasePtr FFTFnc::VisitState<Complex,HalfFrequencyDomain>(const ComplexHalfFrequencyImageState& in_state) const
 {
   int rank,n[3]; // for actual fftw call
-  size_t block_count,src_size,dst_size; // padding parameters
 
   Size in_size=in_state.GetLogicalExtent().GetSize();
+  n[0]=in_size.GetWidth();
+  n[1]=in_size.GetHeight();
+  n[2]=in_size.GetDepth();
   // copy
   ComplexHalfFrequencyImageState tmp_state(in_state);
   // correct phase origin
@@ -164,31 +124,16 @@ ImageStateBasePtr FFTFnc::VisitState<Complex,HalfFrequencyDomain>(const ComplexH
   switch (in_size.GetDim()) {
   case 1: 
     rank=1; 
-    n[0]=in_size.GetWidth();
-    block_count=0; // no un-padding for 1D necessary
-    src_size=half_plus_one(n[0]); // complex values
-    dst_size=n[0]; // real values
     break;
   case 2: 
     rank=2; 
-    n[0]=in_size.GetWidth();
-    n[1]=in_size.GetHeight();
-    block_count=n[0]; 
-    src_size=half_plus_one(n[1]); // complex values
-    dst_size=n[1]; // real values
     // complete zero line
     for(int i=1;i<half_plus_one(n[0]);++i){
         tmp_state.Data().Value(Index(n[0]-i,0,0))=conj(tmp_state.Data().Value(Index(i,0,0)));
     }
     break;
   case 3:
-    rank=3; 
-    n[0]=in_size.GetWidth();
-    n[1]=in_size.GetHeight();
-    n[2]=in_size.GetDepth();
-    block_count=n[0]*n[1];
-    src_size=half_plus_one(n[2]); // complex values
-    dst_size=n[2]; // real values
+    rank=3;
     // complete zero line
     for(int i=1;i<half_plus_one(n[0]);++i){
         tmp_state.Data().Value(Index(n[0]-i,0,0))=conj(tmp_state.Data().Value(Index(i,0,0)));
@@ -208,9 +153,8 @@ ImageStateBasePtr FFTFnc::VisitState<Complex,HalfFrequencyDomain>(const ComplexH
   PixelSampling ps=in_state.GetSampling();
   ps.SetDomain(SPATIAL);
 
-  // convert (!) to real spatial image state
   Size out_size = in_state.GetLogicalExtent().GetSize();
-  boost::shared_ptr<RealSpatialImageState> out_state(new RealSpatialImageState(out_size,tmp_state.Data(),ps ));
+  boost::shared_ptr<RealSpatialImageState> out_state(new RealSpatialImageState(out_size,ps ));
   out_state->SetSpatialOrigin(in_state.GetSpatialOrigin());
   out_state->SetAbsoluteOrigin(in_state.GetAbsoluteOrigin());
 
@@ -220,21 +164,14 @@ ImageStateBasePtr FFTFnc::VisitState<Complex,HalfFrequencyDomain>(const ComplexH
   
   assert(sizeof(OST_FFTW_fftw_complex)==sizeof(Complex));
   OST_FFTW_fftw_plan_with_nthreads(std::max<int>(1,IDEAL_NUMBER_OF_THREADS()));
-  OST_FFTW_fftw_complex* fftw_in =
-reinterpret_cast<OST_FFTW_fftw_complex*>(out_ptr);
+  Complex* in_ptr = tmp_state.Data().GetData();
+  OST_FFTW_fftw_complex* fftw_in =reinterpret_cast<OST_FFTW_fftw_complex*>(in_ptr);
 
-  OST_FFTW_fftw_plan plan = OST_FFTW_fftw_plan_dft_c2r(rank,n,
-				     fftw_in,fftw_out,
-				     FFTW_ESTIMATE);
+  OST_FFTW_fftw_plan plan = OST_FFTW_fftw_plan_dft_c2r(rank,n,fftw_in,fftw_out,FFTW_ESTIMATE | FFTW_DESTROY_INPUT);
 
   OST_FFTW_fftw_execute(plan);
   OST_FFTW_fftw_destroy_plan(plan);
 
-  // un-pad (leftover from in-place transform)
-  Real* dout_ptr = reinterpret_cast<Real*>(out_ptr);
-  for(size_t i=1;i<block_count;++i) {
-    std::copy(&dout_ptr[i*2*src_size],&dout_ptr[i*2*src_size+dst_size],&dout_ptr[i*dst_size]);
-  }
 
   Real fac = 1.0/static_cast<Real>(out_state->GetSize().GetVolume());
   for(Real* ptr = out_state->Data().GetData(); ptr<out_state->Data().GetEnd(); ++ptr) {
@@ -249,29 +186,24 @@ reinterpret_cast<OST_FFTW_fftw_complex*>(out_ptr);
 template <>
 ImageStateBasePtr FFTFnc::VisitState<Complex,SpatialDomain>(const ComplexSpatialImageState& in_state) const
 {
+  assert(sizeof(OST_FFTW_fftw_complex)==sizeof(Complex));
+
   Size size=in_state.GetExtent().GetSize();
   PixelSampling ps=in_state.GetSampling();
   ps.SetDomain(FREQUENCY);
-  boost::shared_ptr<ComplexFrequencyImageState> out_state(new ComplexFrequencyImageState(size,ps));
-  out_state->SetSpatialOrigin(in_state.GetSpatialOrigin());
-  out_state->SetAbsoluteOrigin(in_state.GetAbsoluteOrigin());
-
-  out_state->Data()=in_state.Data(); // use assignement op to copy data area to new state
   int rank = size.GetDim();
   int n[3] = {static_cast<int>(size[0]),static_cast<int>(size[1]),static_cast<int>(size[2])};
   int dir = FFTW_FORWARD;
+  OST_FFTW_fftw_complex* fftw_in = const_cast<OST_FFTW_fftw_complex*>(reinterpret_cast<const OST_FFTW_fftw_complex*>(in_state.Data().GetData()));
 
-  assert(sizeof(OST_FFTW_fftw_complex)==sizeof(Complex));
-  OST_FFTW_fftw_complex* fftw_out =
-reinterpret_cast<OST_FFTW_fftw_complex*>(out_state->Data().GetData());
+  boost::shared_ptr<ComplexFrequencyImageState> out_state(new ComplexFrequencyImageState(size,ps));
+  out_state->SetSpatialOrigin(in_state.GetSpatialOrigin());
+  out_state->SetAbsoluteOrigin(in_state.GetAbsoluteOrigin());
+  OST_FFTW_fftw_complex* fftw_out = reinterpret_cast<OST_FFTW_fftw_complex*>(out_state->Data().GetData());
 
-  // in place transform
+  // out of place transform
   OST_FFTW_fftw_plan_with_nthreads(std::max<int>(1,IDEAL_NUMBER_OF_THREADS()));
-  OST_FFTW_fftw_plan plan = OST_FFTW_fftw_plan_dft(rank,n,
-				 fftw_out, fftw_out, 
-				 dir, 
-				 FFTW_ESTIMATE);
-
+  OST_FFTW_fftw_plan plan = OST_FFTW_fftw_plan_dft(rank,n,fftw_in, fftw_out,dir,FFTW_ESTIMATE | FFTW_PRESERVE_INPUT);
   OST_FFTW_fftw_execute(plan);
   OST_FFTW_fftw_destroy_plan(plan);
 
@@ -284,35 +216,39 @@ reinterpret_cast<OST_FFTW_fftw_complex*>(out_state->Data().GetData());
 template <>
 ImageStateBasePtr FFTFnc::VisitState<Complex,FrequencyDomain>(const ComplexFrequencyImageState& in_state) const
 {
-  // copy in state
-  ComplexFrequencyImageState tmp(in_state);
-  if(ori_flag_) tmp.AdjustPhaseOrigin(-in_state.GetSpatialOrigin());
+  assert(sizeof(OST_FFTW_fftw_complex)==sizeof(Complex));
 
   Size size=in_state.GetExtent().GetSize();
   PixelSampling ps=in_state.GetSampling();
   ps.SetDomain(SPATIAL);
-  // use memory located for tmp
-  boost::shared_ptr<ComplexSpatialImageState> out_state(new ComplexSpatialImageState(size,tmp.Data(),ps));
-  out_state->SetSpatialOrigin(in_state.GetSpatialOrigin());
-  out_state->SetAbsoluteOrigin(in_state.GetAbsoluteOrigin());
-
   int rank = size.GetDim();
   int n[3] = {static_cast<int>(size[0]),static_cast<int>(size[1]),static_cast<int>(size[2])};
   int dir = FFTW_BACKWARD;
 
-  assert(sizeof(OST_FFTW_fftw_complex)==sizeof(Complex));
-  OST_FFTW_fftw_complex* fftw_out =
-reinterpret_cast<OST_FFTW_fftw_complex*>(out_state->Data().GetData());
-
-  // in place transform
-  OST_FFTW_fftw_plan_with_nthreads(std::max<int>(1,IDEAL_NUMBER_OF_THREADS()));
-  OST_FFTW_fftw_plan plan = OST_FFTW_fftw_plan_dft(rank,n,
-				 fftw_out, fftw_out, 
-				 dir, 
-				 FFTW_ESTIMATE);
-
-  OST_FFTW_fftw_execute(plan);
-  OST_FFTW_fftw_destroy_plan(plan);
+  boost::shared_ptr<ComplexSpatialImageState> out_state(new ComplexSpatialImageState(size,ps));
+  out_state->SetSpatialOrigin(in_state.GetSpatialOrigin());
+  out_state->SetAbsoluteOrigin(in_state.GetAbsoluteOrigin());
+  OST_FFTW_fftw_complex* fftw_out = reinterpret_cast<OST_FFTW_fftw_complex*>(out_state->Data().GetData());
+
+  if(ori_flag_){
+    // copy in state
+    ComplexFrequencyImageState tmp_state(in_state);
+    tmp_state.AdjustPhaseOrigin(-in_state.GetSpatialOrigin());
+    OST_FFTW_fftw_complex* fftw_in = reinterpret_cast<OST_FFTW_fftw_complex*>(tmp_state.Data().GetData());
+    // out of place transform
+    OST_FFTW_fftw_plan_with_nthreads(std::max<int>(1,IDEAL_NUMBER_OF_THREADS()));
+    OST_FFTW_fftw_plan plan = OST_FFTW_fftw_plan_dft(rank,n, fftw_in, fftw_out,dir,FFTW_ESTIMATE | FFTW_PRESERVE_INPUT);
+    OST_FFTW_fftw_execute(plan);
+    OST_FFTW_fftw_destroy_plan(plan);
+  }else{
+    // use in state
+    OST_FFTW_fftw_complex* fftw_in = const_cast<OST_FFTW_fftw_complex*>(reinterpret_cast<const OST_FFTW_fftw_complex*>(in_state.Data().GetData()));
+    // out of place transform
+    OST_FFTW_fftw_plan_with_nthreads(std::max<int>(1,IDEAL_NUMBER_OF_THREADS()));
+    OST_FFTW_fftw_plan plan = OST_FFTW_fftw_plan_dft(rank,n, fftw_in, fftw_out,dir,FFTW_ESTIMATE | FFTW_PRESERVE_INPUT);
+    OST_FFTW_fftw_execute(plan);
+    OST_FFTW_fftw_destroy_plan(plan);
+  }
 
   Real fac = 1.0/static_cast<Real>(size.GetVolume());
   for(Complex* ptr = out_state->Data().GetData(); ptr<out_state->Data().GetEnd(); ++ptr) {
diff --git a/modules/img/alg/src/fractional_shift.cc b/modules/img/alg/src/fractional_shift.cc
index 1d10dac297ab035d9a22643540abc8fa3aa6a882..c9ac40bc9e06ba14524670e3c3d7c71d0ea9c787 100644
--- a/modules/img/alg/src/fractional_shift.cc
+++ b/modules/img/alg/src/fractional_shift.cc
@@ -29,12 +29,12 @@
 namespace ost { namespace img { namespace alg {
 
 FractionalShift::FractionalShift(Real sx, Real sy, Real sz):
-  ModIPAlgorithm("FractionalShift"),
+  ConstModIPAlgorithm("FractionalShift"),
   shift_(sx,sy,sz)
 {
 }
 FractionalShift::FractionalShift(const Vec3& v):
-  ModIPAlgorithm("FractionalShift"),
+  ConstModIPAlgorithm("FractionalShift"),
   shift_(v)
 {
 }
@@ -54,7 +54,7 @@ Vec3 FractionalShift::GetShift() const
   return shift_;
 }
 
-void FractionalShift::Visit(ImageHandle& ih)
+void FractionalShift::Visit(ImageHandle& ih) const
 {  
   Vec3 ao=ih.GetAbsoluteOrigin();
 
diff --git a/modules/img/alg/src/fractional_shift.hh b/modules/img/alg/src/fractional_shift.hh
index 0328e66202234d16f8d2cca4d85b54a91696bf58..ad787c1dd94020b4e91ebd06746bd8dbb41fcd07 100644
--- a/modules/img/alg/src/fractional_shift.hh
+++ b/modules/img/alg/src/fractional_shift.hh
@@ -29,7 +29,7 @@
 
 namespace ost { namespace img { namespace alg {
 
-class DLLEXPORT_IMG_ALG FractionalShift: public ModIPAlgorithm
+class DLLEXPORT_IMG_ALG FractionalShift: public ConstModIPAlgorithm
 {
 public:
   FractionalShift(Real sx=0.0, Real sy=0.0, Real sz=0.0);
@@ -38,7 +38,7 @@ public:
   void SetShift(Real sx=0.0, Real sy=0.0, Real sz=0.0);
   void SetShift(const Vec3& v);
   Vec3 GetShift() const;
-  virtual void Visit(ImageHandle& ih);
+  virtual void Visit(ImageHandle& ih) const;
 private:
   Vec3 shift_;
   
diff --git a/modules/img/alg/src/highest_peak_search_3d.cc b/modules/img/alg/src/highest_peak_search_3d.cc
index c8e884577be8e601c78c58eecaf1221cb461283e..913586a08a631285f7991f133be8d1890beb5b33 100644
--- a/modules/img/alg/src/highest_peak_search_3d.cc
+++ b/modules/img/alg/src/highest_peak_search_3d.cc
@@ -173,10 +173,6 @@ template <typename T, class D>
     peak_collector.ClearPeakList();
   }
 
-  void HighestPeakSearch3DBase::VisitFunction(const Function& f)
-  {
-    throw Error("VisitFunction not implemented");
-  }
 
 } // ns
 
diff --git a/modules/img/alg/src/highest_peak_search_3d.hh b/modules/img/alg/src/highest_peak_search_3d.hh
index d61c8a84753eac1fc67c51b5c4fa6a6081269c6b..1f2bc2fd6dadd91ac58e1d31736357c87314fe8c 100644
--- a/modules/img/alg/src/highest_peak_search_3d.hh
+++ b/modules/img/alg/src/highest_peak_search_3d.hh
@@ -35,8 +35,6 @@ class DLLEXPORT_IMG_ALG HighestPeakSearch3DBase
     template <typename T, class D>
     void VisitState(const ImageStateImpl<T,D>& isi);
     
-    void VisitFunction(const Function& f);
-
     static String GetAlgorithmName() {return "HighestPeakSearch3D";}
   
     //! Main "return" function returns a list of Peaks
diff --git a/modules/img/alg/src/histogram.cc b/modules/img/alg/src/histogram.cc
index 0a094bd8319675c59f587a7ea1638c6f79ed78c1..16d90f3518f722ca71afc402659292715eef08eb 100644
--- a/modules/img/alg/src/histogram.cc
+++ b/modules/img/alg/src/histogram.cc
@@ -58,7 +58,7 @@ template <typename T, class D>
 void HistogramBase::VisitState(const ImageStateImpl<T,D>& isi)
 {
   bins_=Bins(bin_count_,0);
-  for(T* ptr = isi.Data().GetData(); ptr<isi.Data().GetEnd(); ++ptr) {
+  for(const T* ptr = isi.Data().GetData(); ptr<isi.Data().GetEnd(); ++ptr) {
     Real val=Val2Val<T,Real>(*ptr);
     val = std::max(min_,val);
     val=std::min(max_,val);
@@ -66,18 +66,6 @@ void HistogramBase::VisitState(const ImageStateImpl<T,D>& isi)
     bins_[bin]++;
   }
 }
-void HistogramBase::VisitFunction(const Function& fnc)
-{
-  bins_=Bins(bin_count_,0);
-  for(ExtentIterator it(fnc.GetExtent());!it.AtEnd(); ++it) {
-    Real val=fnc.GetReal(it);
-    val = std::max(min_,val);
-    val=std::min(max_,val);
-    int bin = int(floor((val-min_)*cfac_));
-    bins_[bin]++;
-  }
-}
-
 
 }
 
diff --git a/modules/img/alg/src/histogram.hh b/modules/img/alg/src/histogram.hh
index 820744d31b01ace41437c9d0293a24f086291dfa..c930ba43a20e118bcd2cbbe953a3c1932fbca052 100644
--- a/modules/img/alg/src/histogram.hh
+++ b/modules/img/alg/src/histogram.hh
@@ -55,8 +55,6 @@ public:
   template <typename T, class D>
   void VisitState(const ImageStateImpl<T,D>& isi);
 
-  void VisitFunction(const Function& f);
-
   const Bins& GetBins() const;
 
   static String GetAlgorithmName() {return "Histogram";}
diff --git a/modules/img/alg/src/stat.cc b/modules/img/alg/src/stat.cc
index 01053ab7e28bbccdfaf0a7c4839633246d675995..2623149985969502481659c094ffc6192a43385e 100644
--- a/modules/img/alg/src/stat.cc
+++ b/modules/img/alg/src/stat.cc
@@ -99,59 +99,6 @@ void StatBase::VisitState(const ImageStateImpl<T,D>& isi)
   }
 }
 
-void StatBase::VisitFunction(const Function& fnc)
-{
-  sum_=0.0;
-  mean_=0.0;
-
-  Real n = (Real)(fnc.GetSize().GetVol());
-  if(n==0.0){
-    var_=0.0;
-    std_dev_=0.0;
-    min_=0.0;
-    max_=0.0;
-    maxpos_=Point(0,0,0),
-    minpos_=Point(0,0,0),
-    rms_=0.0;
-    skewness_=0.0;
-    kurtosis_=0.0;
-    center_of_mass_=Vec3(0.0,0.0,0.0);
-    return;
-  }
-
-  Vec3 sumcenter(0.0,0.0,0.0);
-  ValIndex minindex(std::numeric_limits<Real>::max(),Point(0,0,0));
-  ValIndex maxindex(-std::numeric_limits<Real>::max(),Point(0,0,0));
-  min_ = std::numeric_limits<Real>::max();
-  max_ = -std::numeric_limits<Real>::max();
-  StatAccumulator<> acc;
-
-  for(ExtentIterator it(fnc.GetExtent());!it.AtEnd(); ++it) {
-    Real val=fnc.GetReal(it);
-    ValIndex vi(val,it);
-    minindex=std::min<ValIndex>(vi,minindex);
-    maxindex=std::max<ValIndex>(vi,maxindex);
-    sumcenter+=Point(it).ToVec3()*val;
-    acc(val);
-  }
-  min_=minindex.first;
-  max_=maxindex.first;
-  minpos_=minindex.second;
-  maxpos_=maxindex.second;
-  var_=acc.GetVariance();
-  std_dev_=acc.GetStandardDeviation();
-  rms_=acc.GetRootMeanSquare();
-  skewness_=acc.GetSkewness();
-  kurtosis_= acc.GetKurtosis();
-  sum_=acc.GetSum();
-  mean_=acc.GetMean();
-  if(sum_!=0.0){
-    center_of_mass_=sumcenter/sum_;
-  }else{
-    center_of_mass_=Vec3(0.0,0.0,0.0);
-  }
-}
-
 std::ostream& operator<<(std::ostream& o, const Stat& s)
 {
   o << "mean=" << s.GetMean() << " ";
diff --git a/modules/img/alg/src/stat.hh b/modules/img/alg/src/stat.hh
index 47009785a94a72bc50d967cb8be8f99021963181..ba1861621612f2dd9fd6cb2900bda916c843b450 100644
--- a/modules/img/alg/src/stat.hh
+++ b/modules/img/alg/src/stat.hh
@@ -68,8 +68,6 @@ class DLLEXPORT_IMG_ALG StatBase
   template <typename T, class D>
   void VisitState(const ImageStateImpl<T,D>& isi);
 
-  void VisitFunction(const Function& f);
-
   static String GetAlgorithmName() {return "Stat";}
 
   // other interface
diff --git a/modules/img/alg/src/stat_accumulator.hh b/modules/img/alg/src/stat_accumulator.hh
index a07d6219e5dae160cb8198f611d5b38e0ccd4838..53399f8be99c0cb4e1a445b38aabfd7252bb4c41 100644
--- a/modules/img/alg/src/stat_accumulator.hh
+++ b/modules/img/alg/src/stat_accumulator.hh
@@ -27,7 +27,7 @@
 namespace ost { namespace img { namespace alg {
 
 template<unsigned int MAX_MOMENT=4>
-class DLLEXPORT_IMG_ALG StatAccumulator
+class  StatAccumulator
 {
 public:
   StatAccumulator():
@@ -70,14 +70,14 @@ public:
     sum2_+=val*val;
   }
 
-  StatAccumulator operator+(const StatAccumulator& acc2) const
+  StatAccumulator<MAX_MOMENT> operator+(const StatAccumulator<MAX_MOMENT>& acc2) const
   {
-    StatAccumulator acc(acc2);
+    StatAccumulator<MAX_MOMENT> acc(acc2);
     acc+=*this;
     return acc;
   }
 
-  StatAccumulator& operator+=(const StatAccumulator& acc)
+  StatAccumulator<MAX_MOMENT>& operator+=(const StatAccumulator<MAX_MOMENT>& acc)
   {
     if(acc.n_==1){
       return *this;
diff --git a/modules/img/alg/src/stat_min_max.cc b/modules/img/alg/src/stat_min_max.cc
index 3b46db02e0fce3668e78c21386c91cf7f2e57c4c..c6963864462aa53fad855adede023496333fe016 100644
--- a/modules/img/alg/src/stat_min_max.cc
+++ b/modules/img/alg/src/stat_min_max.cc
@@ -66,28 +66,6 @@ void StatMinMaxBase::VisitState(const ImageStateImpl<T,D>& isi)
   maxpos_=maxindex.second+isi.GetExtent().GetStart();  
 }
 
-void StatMinMaxBase::VisitFunction(const Function& fnc)
-{
-  ValIndex minindex(std::numeric_limits<Real>::max(),Point(0,0,0));
-  ValIndex maxindex(-std::numeric_limits<Real>::max(),Point(0,0,0));
-  Real n = (Real)(fnc.GetSize().GetVol());
-
-  if(n==0.0)  return;
-
-  min_ = std::numeric_limits<Real>::max();
-  max_ = -std::numeric_limits<Real>::max();
-
-  for(ExtentIterator it(fnc.GetExtent());!it.AtEnd(); ++it) {
-    Real val=fnc.GetReal(it);
-    ValIndex vi(val,it);
-    minindex=std::min<ValIndex>(vi,minindex);
-    maxindex=std::max<ValIndex>(vi,maxindex);
-  }
-  min_=minindex.first;
-  max_=maxindex.first;
-  minpos_=minindex.second;
-  maxpos_=maxindex.second;  
-}
 
 std::ostream& operator<<(std::ostream& o, const StatMinMax& s)
 {
diff --git a/modules/img/alg/src/stat_min_max.hh b/modules/img/alg/src/stat_min_max.hh
index b1a89bc81b1f30564c72fe9b88e400830403da85..15d7300bc335a7930d67dcc2f09bb76c72903ff6 100644
--- a/modules/img/alg/src/stat_min_max.hh
+++ b/modules/img/alg/src/stat_min_max.hh
@@ -56,8 +56,6 @@ class DLLEXPORT_IMG_ALG StatMinMaxBase
   template <typename T, class D>
   void VisitState(const ImageStateImpl<T,D>& isi);
 
-  void VisitFunction(const Function& f);
-
   static String GetAlgorithmName() {return "StatMinMax";}
 
   // other interface
diff --git a/modules/img/alg/src/transcendentals.hh b/modules/img/alg/src/transcendentals.hh
index 84de4bd3812e4c7996bc5c75ad0b0f061617fd8d..60c1f6bcfd24bc7f759090c4c62d48c926745308 100644
--- a/modules/img/alg/src/transcendentals.hh
+++ b/modules/img/alg/src/transcendentals.hh
@@ -36,22 +36,22 @@
 #include <ost/img/alg/module_config.hh>
 
 
-#define IMG_ALG_TRANSCENDENTALS_BLOCK(FF,NN,SS)                               \
-struct FF {					                                                           \
+#define IMG_ALG_TRANSCENDENTALS_BLOCK(FF,NN,SS)                                \
+struct FF {					                                                   \
   FF() {}                                                                      \
   ~FF() {}                                                                     \
   template <typename T, class D>                                               \
   void VisitState(ImageStateImpl<T,D>& isi) const {	                           \
-    T* end = isi.Data().GetEnd();                                              \
+    const T* end = isi.Data().GetEnd();                                        \
     for(T* it = isi.Data().GetData(); it!=end; ++it) {                         \
       (*it) = SS (*it);                                                        \
     }                                                                          \
   }                                                                            \
   template <class D>                                                           \
   void VisitState(ImageStateImpl<Word,D>& isi) const {                         \
-    Word* end = isi.Data().GetEnd();                                           \
+    const Word* end = isi.Data().GetEnd();                                     \
     for(Word* it = isi.Data().GetData(); it!=end; ++it) {                      \
-      (*it) = static_cast<Word>(SS(static_cast<Real>(*it)));                 \
+      (*it) = static_cast<Word>(SS(static_cast<Real>(*it)));                   \
     }                                                                          \
   }                                                                            \
   static String GetAlgorithmName() {return "";}                                \
@@ -75,7 +75,7 @@ struct PowFnc {
 
   template <typename T, class D>
   void VisitState(ImageStateImpl<T,D>& isi) const {
-    T* end = isi.Data().GetEnd();
+    const T* end = isi.Data().GetEnd();
     for(T* it = isi.Data().GetData(); it!=end; ++it) {
       (*it) = std::pow(*it,exp_);
     }
diff --git a/modules/img/alg/tests/test_fft.cc b/modules/img/alg/tests/test_fft.cc
index 3e3702690117843ed71fc633b0ddbfeb69e0d418..7d8d0a1d125b91424af099b77db3c6f1a53d3a13 100644
--- a/modules/img/alg/tests/test_fft.cc
+++ b/modules/img/alg/tests/test_fft.cc
@@ -408,7 +408,7 @@ void Test_DFT(DataType TYPE)
     Real absdiff=std::abs(ri3.GetReal(it)-ri1.GetReal(it));
     msg.str("");
     msg << "@" << Point(it) << ": abs(" << ri3.GetReal(it) << "-" <<ri1.GetReal(it) << ")="<<absdiff;
-    BOOST_REQUIRE(absdiff<1e-5);
+    BOOST_REQUIRE_MESSAGE(absdiff<1e-5,msg.str());
   }
 }
 
diff --git a/modules/img/base/pymod/CMakeLists.txt b/modules/img/base/pymod/CMakeLists.txt
index de787d14064aa27fb4f0117e9f9bf3bdac06c596..a14d21e6820ed757b457bc5da7614277bfcb417c 100644
--- a/modules/img/base/pymod/CMakeLists.txt
+++ b/modules/img/base/pymod/CMakeLists.txt
@@ -2,7 +2,6 @@ set(OST_IMG_PYMOD_SOURCES
 export_data.cc
 export_data_algorithm.cc
 export_extent.cc
-export_function.cc
 export_image_handle.cc
 export_peak.cc
 export_phase.cc
diff --git a/modules/img/base/pymod/export_data_algorithm.cc b/modules/img/base/pymod/export_data_algorithm.cc
index f1f8056c56c582a2dcc702ab16ae34f8812c205e..4fe222395eb9da2c1772c8e79cce852d927fca94 100644
--- a/modules/img/base/pymod/export_data_algorithm.cc
+++ b/modules/img/base/pymod/export_data_algorithm.cc
@@ -43,11 +43,6 @@ public:
   virtual void VisitImage(const ConstImageHandle&) {
     throw(Error("NonModAlgorithm Base: VisitImage not overridden"));
   }
-
-  virtual void Visit(const Function& f) {VisitFunction(f);}
-  virtual void VisitFunction(const Function&) {
-    throw(Error("NonModAlgorithm Base: VisitFunction not overridden"));
-  }
 };
 
 class WrapPyNonModAlgorithm: public PyNonModAlgorithm {
@@ -59,9 +54,6 @@ public:
   virtual void VisitImage(const ConstImageHandle& ih) {
     call_method<void>(self_, "VisitImage", ih); 
   }
-  virtual void VisitFunction(const Function& f) {
-    call_method<void>(self_, "VisitFunction", f); 
-  }
 
 private:
   PyObject* const self_;
diff --git a/modules/img/base/pymod/export_function.cc b/modules/img/base/pymod/export_function.cc
deleted file mode 100644
index 2660574394b0cc909f73573e04fe975cf83d2be5..0000000000000000000000000000000000000000
--- a/modules/img/base/pymod/export_function.cc
+++ /dev/null
@@ -1,98 +0,0 @@
-//------------------------------------------------------------------------------
-// This file is part of the OpenStructure project <www.openstructure.org>
-//
-// Copyright (C) 2008-2011 by the OpenStructure authors
-// Copyright (C) 2003-2010 by the IPLT authors
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License as published by the Free
-// Software Foundation; either version 3.0 of the License, or (at your option)
-// any later version.
-// This library is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with this library; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//------------------------------------------------------------------------------
-
-/*
-  Author: Ansgar Philippsen
-*/
-
-#include <boost/python.hpp>
-#include <ost/img/function.hh>
-using namespace boost::python;
-
-namespace ost { namespace img {
-
-class WrapRealFunction: public RealFunction
-{
-public:
-  WrapRealFunction(PyObject* self, const RealFunction& f):
-    RealFunction(f),
-    self_(self) {}
-    
-  WrapRealFunction(PyObject* self)
-    : RealFunction(SPATIAL),
-      self_(self)
-    { }
-  WrapRealFunction(PyObject* self, DataDomain domain)
-    : RealFunction(domain),
-      self_(self)
-    { }  
-  virtual Real Func(const Vec3& v) const {
-    return call_method<Real>(self_,"Func",v);
-  }
-
-private:
-  PyObject* self_;
-};
-
-class WrapComplexFunction: public ComplexFunction
-{
-public:
-  WrapComplexFunction(PyObject* self, const ComplexFunction& f):
-    ComplexFunction(f),
-    self_(self) {}
-    
-  WrapComplexFunction(PyObject* self)
-    : ComplexFunction(SPATIAL),
-      self_(self)
-    { }
-    
-  WrapComplexFunction(PyObject* self, DataDomain domain)
-    : ComplexFunction(domain),
-      self_(self)
-    { }    
-  virtual Complex Func(const Vec3& v) const {
-    return call_method<Complex>(self_,"Func",v);
-  }
-
-private:
-  PyObject* self_;
-};
-
-}} // namespace
-
-void export_Function()
-{
-  using namespace ost::img;
-  using namespace ost;
-  class_<Function, bases<Data>, boost::noncopyable>("Function", no_init)
-    .def("SetExtent",&Function::SetExtent)
-    ;
-
-  class_<RealFunction, WrapRealFunction, bases<Function>, boost::noncopyable>("RealFunction")
-    .def(init<DataDomain>())
-    .def("Func",&RealFunction::Func)
-    ;
-
-  class_<ComplexFunction, WrapComplexFunction, bases<Function>, boost::noncopyable>("ComplexFunction")
-    .def(init<DataDomain>())  
-    .def("Func",&ComplexFunction::Func)
-    ;
-
-}
diff --git a/modules/img/base/pymod/export_image_handle.cc b/modules/img/base/pymod/export_image_handle.cc
index 24aace26cb7b1a4d4945296e592c6ee3cd27d8f5..1c6481b8750bbcd411444d2630b712a050057de5 100644
--- a/modules/img/base/pymod/export_image_handle.cc
+++ b/modules/img/base/pymod/export_image_handle.cc
@@ -28,7 +28,6 @@ using namespace boost::python;
 #include <ost/message.hh>
 #include <ost/img/algorithm.hh>
 #include <ost/img/image.hh>
-#include <ost/img/function.hh>
 #include "wrap_extent_iterator.hh"
 
 using namespace ost::img;
@@ -253,14 +252,6 @@ void export_ImageHandle()
     .def(Real() * self)
     .def(self /= Real())
     .def(self / Real())
-    .def(self += other<Function>())
-    .def(self + other<Function>())
-    .def(self -= other<Function>())
-    .def(self - other<Function>())
-    .def(self *= other<Function>())
-    .def(self * other<Function>())
-    .def(self /= other<Function>())
-    .def(self / other<Function>())
     ;
 
   def("CreateImage",c0);
@@ -325,10 +316,6 @@ void export_ConstImageHandle()
     .def(self * Complex())
     .def(Complex() * self)
     .def(self / Complex())
-    .def(self + other<Function>())
-    .def(self - other<Function>())
-    .def(self * other<Function>())
-    .def(self / other<Function>())
      ;
 
   implicitly_convertible<ImageHandle,ConstImageHandle>();
diff --git a/modules/img/base/pymod/export_image_list.cc b/modules/img/base/pymod/export_image_list.cc
index e97b34bff6fd36598a7598727c6dec73775a80ce..f1fb6a6cfa26dc251f03887b89998f2101a00003 100644
--- a/modules/img/base/pymod/export_image_list.cc
+++ b/modules/img/base/pymod/export_image_list.cc
@@ -29,7 +29,6 @@ using namespace boost::python;
 #include <ost/img/algorithm.hh>
 #include <ost/img/image.hh>
 #include <ost/img/image_list.hh>
-#include <ost/img/function.hh>
 
 using namespace ost::img;
 using namespace ost;
@@ -86,10 +85,6 @@ void export_ImageList()
     .def(self -= Real())
     .def(self *= Real())
     .def(self /= Real())
-    .def(self += other<Function>())
-    .def(self -= other<Function>())
-    .def(self *= other<Function>())
-    .def(self /= other<Function>())
     ;
 }
 
diff --git a/modules/img/base/pymod/wrap_img.cc b/modules/img/base/pymod/wrap_img.cc
index a23f89745e442a4ecf2c6a060fdcfb79cdac8726..f89f14e95eda56af6de0be53a27bca8db4a6ffbd 100644
--- a/modules/img/base/pymod/wrap_img.cc
+++ b/modules/img/base/pymod/wrap_img.cc
@@ -39,7 +39,6 @@ using namespace boost::python;
 void export_Data();
 void export_DataAlgorithm();
 void export_Extent();
-void export_Function();
 void export_ImageHandle();
 void export_ImageList();
 void export_ConstImageHandle();
@@ -60,7 +59,6 @@ BOOST_PYTHON_MODULE(_ost_img)
   export_Data();
   export_DataAlgorithm();
   export_Extent();
-  export_Function();
   export_ImageHandle();
   export_ImageList();
   export_ConstImageHandle();
diff --git a/modules/img/base/src/CMakeLists.txt b/modules/img/base/src/CMakeLists.txt
index ff5191865fc22a3364106ba0980174417946742b..78097d2ab0af3686fa5298e23c5e7d062eaec9fb 100644
--- a/modules/img/base/src/CMakeLists.txt
+++ b/modules/img/base/src/CMakeLists.txt
@@ -3,92 +3,86 @@ add_subdirectory(image_state)
 
 
 set(OST_IMG_SOURCES 
-data.cc
+circle_mask.cc
+composite_mask.cc
 data_algorithm.cc
 data_observer.cc
-extent.cc
+data.cc
 extent_iterator.cc
-function_base.cc
-function_impl.cc
+extent_mask.cc
+extent.cc
 image_factory.cc
 image_handle.cc
 image_impl.cc
+image_list.cc
+inverted_mask.cc
+map.cc
+mask_base.cc
+mask_op.cc
+mask.cc
+observable.cc
 paste_impl.cc
 peak.cc
-pixel_sampling.cc
 phase.cc
-point.cc
+physical_units.cc
+pixel_sampling.cc
 point_list.cc
-size.cc
-mask.cc
-mask_base.cc
-composite_mask.cc
-inverted_mask.cc
+point.cc
 polygon_mask.cc
-extent_mask.cc
-spherical_mask.cc
-mask_op.cc
-circle_mask.cc
-image_list.cc
-physical_units.cc
 progress.cc
-map.cc
+size.cc
+spherical_mask.cc
 )
 
 set(OST_IMG_HEADERS
 algorithm.hh
+circle_mask.hh
+composite_mask.hh
 data_algorithm.hh
-data.hh
-data_types.hh
 data_observer.hh
+data_types.hh
+data.hh
 debug.hh
 dllexport.hh
-extent.hh
 extent_iterator.hh
-function.hh
-function_base.hh
-function_fw.hh
-function_impl.hh
-image.hh
+extent_mask.hh
+extent.hh
 image_factory.hh
 image_fw.hh
-image_handle.hh
 image_handle_fw.hh
+image_handle.hh
 image_impl.hh
-image_state.hh
+image_list.hh
 image_state_fw.hh
+image_state.hh
+image.hh
+inverted_mask.hh
+map.hh
+mask_base_fw.hh
+mask_base.hh
+mask_op.hh
 mask_visitor.hh
+mask.hh
+module_config.hh
 normalizer_fw.hh
 normalizer_impl.hh
 null_data.hh
-null_function.hh
 observable.hh
 paste_impl.hh
 peak.hh
-pixel_sampling.hh
 phase.hh
-point.hh
+physical_units.hh
+pixel_sampling.hh
 point_list.hh
+point.hh
+polygon_mask.hh
+progress.hh
 size.hh
-util.hh
+spherical_mask.hh
 util.cc
-module_config.hh
+util.hh
 value_util.hh
 vecmat.hh
-mask_base_fw.hh
-mask_base.hh
-composite_mask.hh
-inverted_mask.hh
-polygon_mask.hh
-extent_mask.hh
-spherical_mask.hh
-mask_op.hh
-mask.hh
-circle_mask.hh
-image_list.hh
-physical_units.hh
-progress.hh
-map.hh
 )
 
 if (ENABLE_INFO)
diff --git a/modules/img/base/src/algorithm.hh b/modules/img/base/src/algorithm.hh
index 68f9cec6ff52975a2f4c7a468897b57352d0bec6..4b00bc04465f48f62dc2764dfbccb670f9b54840 100644
--- a/modules/img/base/src/algorithm.hh
+++ b/modules/img/base/src/algorithm.hh
@@ -32,7 +32,6 @@
 #include "data.hh"
 #include "data_algorithm.hh"
 #include "image_handle.hh"
-#include "function.hh"
 #include "extent.hh"
 #include "size.hh"
 #include "point.hh"
diff --git a/modules/img/base/src/data.hh b/modules/img/base/src/data.hh
index fc2401b077ad23f3d410eab8d33a146813f54bd7..3ab5d6063a93e997ff1f94981ffd236f7a3ba2a6 100644
--- a/modules/img/base/src/data.hh
+++ b/modules/img/base/src/data.hh
@@ -248,7 +248,7 @@ private:
    - setting the spatial origin
    - modifying the pixel sampling
 
-  It servers mainly as the base class for ImageHandle and Function.
+  It servers mainly as the base class for ImageHandle.
 */
 class DLLEXPORT_OST_IMG_BASE Data: public ConstData {
 public:
diff --git a/modules/img/base/src/data_algorithm.hh b/modules/img/base/src/data_algorithm.hh
index 1cc85d3437dbb4e3d23d709acd82fc49330ba411..02e05ff4cb1ba198c63ee2b134594f526cd40600 100644
--- a/modules/img/base/src/data_algorithm.hh
+++ b/modules/img/base/src/data_algorithm.hh
@@ -28,7 +28,6 @@
 #define IMG_DATA_ALG_H
 
 #include <ost/img/module_config.hh>
-#include "function_fw.hh"
 #include "image_fw.hh"
 
 /*
@@ -69,8 +68,6 @@ class DLLEXPORT_OST_IMG_BASE NonModAlgorithm: public AlgorithmBase
 public:
   //! visitor implementation for images
   virtual void Visit(const ConstImageHandle& i) = 0;
-  //! visitor implementation for real functions
-  virtual void Visit(const Function& f) = 0;
 
 protected:
   //! ctor, must be initialized with name
diff --git a/modules/img/base/src/data_observer.cc b/modules/img/base/src/data_observer.cc
index 804056db48593dd92ebe6a69bd1c85de3bce0f7f..4d42d66213ae5e60f4ae131f76229576c0caa957 100644
--- a/modules/img/base/src/data_observer.cc
+++ b/modules/img/base/src/data_observer.cc
@@ -30,54 +30,54 @@
 
 namespace ost { namespace img {
 
-DataObserver::DataObserver(const Data& d):
-  data_(boost::cref(d)) 
+DataObserver::DataObserver(const ImageHandle& d):
+  data_(d)
 {
-  data_.get().Attach(this);
+  data_.Attach(this);
 }
 
 DataObserver::DataObserver(const DataObserver& o):
   data_(o.data_) 
 {
-  data_.get().Attach(this);
+  data_.Attach(this);
 }
 
 DataObserver& DataObserver::operator=(const DataObserver& o)
 {
   if(this!=&o) {
-    data_.get().Detach(this);
+    data_.Detach(this);
     data_=o.data_;
-    data_.get().Attach(this);
+    data_.Attach(this);
   }
   return *this;
 }
 
 DataObserver::~DataObserver() 
 {
-  data_.get().Detach(this);
+  data_.Detach(this);
 }
 
 void DataObserver::ObserverInvalidate()
 {
-  data_=boost::cref(NullData::Instance());
+  data_=ImageHandle();
 }
 
-const Data& DataObserver::GetObservedData() const 
+const ImageHandle& DataObserver::GetObservedData() const
 {
   if(!is_valid()) {
     std::cerr << "invalid observed data access" << std::endl;
     throw InvalidObserver("GetData called for invalidated observer");
   }
-  return data_.get();
+  return data_;
 }
 
-void DataObserver::SetObservedData(const Data& d) 
+void DataObserver::SetObservedData(const ImageHandle& d)
 {
   if(is_valid()) {
-    data_.get().Detach(this);
+    data_.Detach(this);
   }
-  data_ = boost::cref(d);
-  data_.get().Attach(this);
+  data_ = d;
+  data_.Attach(this);
 }
 
 void DataObserver::ObserverUpdate()
@@ -97,7 +97,7 @@ void DataObserver::ObserverUpdate(const Point&)
 
 bool DataObserver::is_valid() const 
 {
-  return data_.get_pointer() != &NullData::Instance();
+  return data_.IsValid();
 }
 
 }} // namespace
diff --git a/modules/img/base/src/data_observer.hh b/modules/img/base/src/data_observer.hh
index c99e2f5855eb719a056b839730acaec8b6e47a01..0d369a2bdadf2597c60a12e06922b65d91d57cc3 100644
--- a/modules/img/base/src/data_observer.hh
+++ b/modules/img/base/src/data_observer.hh
@@ -27,9 +27,8 @@
 #ifndef IMG_DATA_OBSERVER
 #define IMG_DATA_OBSERVER
 
-#include <boost/ref.hpp>
 
-#include "data.hh"
+#include "image_handle.hh"
 
 namespace ost { namespace img {
 
@@ -63,7 +62,7 @@ class DLLEXPORT_OST_IMG_BASE DataObserver {
   /*!
     requires reference to data, then attaches itself to data
   */
-  DataObserver(const Data& d);
+  DataObserver(const ImageHandle& d);
 
   DataObserver(const DataObserver& o);
 
@@ -92,7 +91,7 @@ class DLLEXPORT_OST_IMG_BASE DataObserver {
   void ObserverInvalidate();
   
   //! Returns data that is observed
-  virtual const Data& GetObservedData() const;
+  virtual const ImageHandle& GetObservedData() const;
 
   bool IsDataValid() const {return is_valid();}
 
@@ -102,12 +101,12 @@ class DLLEXPORT_OST_IMG_BASE DataObserver {
   /*!
     Automatically unregister previously observed data
   */
-  void SetObservedData(const Data& d);
+  void SetObservedData(const ImageHandle& d);
 
   bool is_valid() const;
 
 private:
-  boost::reference_wrapper<const Data> data_;
+  ImageHandle data_;
 
 };
 
diff --git a/modules/img/base/src/function.hh b/modules/img/base/src/function.hh
deleted file mode 100644
index 2961df320ebf8b4f741ab8040905483ef387d1ed..0000000000000000000000000000000000000000
--- a/modules/img/base/src/function.hh
+++ /dev/null
@@ -1,48 +0,0 @@
-//------------------------------------------------------------------------------
-// This file is part of the OpenStructure project <www.openstructure.org>
-//
-// Copyright (C) 2008-2011 by the OpenStructure authors
-// Copyright (C) 2003-2010 by the IPLT authors
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License as published by the Free
-// Software Foundation; either version 3.0 of the License, or (at your option)
-// any later version.
-// This library is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with this library; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//------------------------------------------------------------------------------
-
-/*
-  real and complex function abstract base class,
-  implemented in terms of the templated
-  function implementation
-
-  Author: Ansgar Philippsen
-*/
-
-#ifndef IMG_FUNCTION_H
-#define IMG_FUNCTION_H
-
-#include "function_base.hh"
-#include "function_impl.hh"
-
-namespace ost { namespace img {
-
-/// \sa \ref modulate_image.py "Modulate Image Example"
-typedef detail::FunctionImpl<Real> RealFunction;
-typedef detail::FunctionImpl<Complex> ComplexFunction;
-
-
-}} // namespace img
-
-#endif
-
-/// \example modulate_image.py
-///
-/// This script shows how to define a python function that modulates an image by a sine. Note the explicit call of RealFunction.__init__ in the modulator class.
diff --git a/modules/img/base/src/function_base.cc b/modules/img/base/src/function_base.cc
deleted file mode 100644
index 7c3672159d6d336fa1e490c11a31a10b44c49cb7..0000000000000000000000000000000000000000
--- a/modules/img/base/src/function_base.cc
+++ /dev/null
@@ -1,157 +0,0 @@
-//------------------------------------------------------------------------------
-// This file is part of the OpenStructure project <www.openstructure.org>
-//
-// Copyright (C) 2008-2011 by the OpenStructure authors
-// Copyright (C) 2003-2010 by the IPLT authors
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License as published by the Free
-// Software Foundation; either version 3.0 of the License, or (at your option)
-// any later version.
-// This library is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with this library; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//------------------------------------------------------------------------------
-
-/*
-  function base
-  
-  Author: Ansgar Philippsen
-*/
-
-#include "function_base.hh"
-#include "data_algorithm.hh"
-#include "image_factory.hh"
-#include "image_handle.hh"
-namespace ost {
-namespace img {
-
-Function::Function(DataDomain d, const Extent& e):
-  extent_(e),
-  domain_(d),
-  obs_(DataObservable()),
-  sampling_(Vec3(1.0,1.0,1.0),domain_,extent_)
-{}
-
-Function::Function(const Function& f):
-  Data(f),
-  extent_(f.extent_),
-  domain_(f.domain_),
-  obs_(f.obs_), // use Observable copy logic
-  sampling_(f.sampling_)
-{}
-
-Function& Function::operator=(const Function& f)
-{
-  Data::operator=(f);
-  extent_=f.extent_;
-  domain_=f.domain_;
-  obs_=f.obs_; // use Observable assignement logic
-  sampling_=f.sampling_;
-  return *this;
-}
-
-Function::~Function()
-{}
-
-DataDomain Function::GetDomain() const 
-{
-  return domain_;
-}
-
-Extent Function::GetExtent() const 
-{
-  return extent_;
-}
-
-void Function::SetSpatialOrigin(const Point& o) 
-{
-  extent_=Extent(o,extent_.GetSize());
-}
-
-Point Function::GetSpatialOrigin() const
-{
-  return extent_.GetStart();
-}
-
-void Function::SetExtent(const Extent& e) 
-{
-  extent_ = e;
-  sampling_.SetExtent(extent_);
-}
-
-void Function::Apply(NonModAlgorithm& a) const
-{
-  a.Visit(*this);
-}
-void Function::ApplyIP(NonModAlgorithm& a) const
-{
-  Apply(a);
-}
-
-
-void Function::Attach(DataObserver *o) const
-{
-  obs_.Attach(o);
-}
-
-void Function::Detach(DataObserver *o) const
-{
-  obs_.Detach(o);
-}
-
-void Function::Notify() const
-{
-  obs_.Notify();
-}
-
-PixelSampling& Function::Sampling()
-{
-  return sampling_;
-}
-
-const PixelSampling& Function::Sampling() const
-{
-  return sampling_;
-}
-
-Real Function::GetReal(const Point& p) const
-{
-  return GetIntpolReal(p.ToVec3());
-}
-
-Complex Function::GetComplex(const Point& p) const
-{
-  return GetIntpolComplex(p.ToVec3());
-}
-
-Real Function::GetIntpolReal(const Vec2 &v) const
-{
-  Vec3 v3(v);
-  v3[2]=extent_.GetStart()[2];
-  return GetIntpolReal(v3);
-}
-Real Function::GetIntpolReal(const Real &d) const
-{
-  Vec3 v3(d,extent_.GetStart()[1],extent_.GetStart()[2]);
-  return GetIntpolReal(v3);
-}
-
-Complex Function::GetIntpolComplex(const Vec2 &v) const
-{
-  Vec3 v3(v);
-  v3[2]=extent_.GetStart()[2];
-  return GetIntpolComplex(v3);
-}
-Complex Function::GetIntpolComplex(const Real &d) const
-{
-  Vec3 v3(d,extent_.GetStart()[1],extent_.GetStart()[2]);
-  return GetIntpolComplex(v3);
-}
-
-}} //ns
diff --git a/modules/img/base/src/function_base.hh b/modules/img/base/src/function_base.hh
deleted file mode 100644
index 05fe24e73020c13ac3b1e37f628f4435e034f547..0000000000000000000000000000000000000000
--- a/modules/img/base/src/function_base.hh
+++ /dev/null
@@ -1,170 +0,0 @@
-//------------------------------------------------------------------------------
-// This file is part of the OpenStructure project <www.openstructure.org>
-//
-// Copyright (C) 2008-2011 by the OpenStructure authors
-// Copyright (C) 2003-2010 by the IPLT authors
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License as published by the Free
-// Software Foundation; either version 3.0 of the License, or (at your option)
-// any later version.
-// This library is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with this library; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//------------------------------------------------------------------------------
-
-/*
-  function base
-
-  Author: Ansgar Philippsen
-*/
-
-#ifndef IMG_FUNCTION_BASE_H
-#define IMG_FUNCTION_BASE_H
-
-#include "module_config.hh"
-#include "data.hh"
-#include "data_observer.hh"
-#include "observable.hh"
-#include "pixel_sampling.hh"
-
-namespace ost { namespace img {
-
-// forward declaration
-class NonModAlgorithm;
-class ImageHandle;
-
-//! Base class that defines the function interface
-/*!
-  Function only partially implementes the Data interface and 
-  is thus still an abstract base class. In particular, the 
-  methods GetType(), GetReal() and GetComplex() are still
-  pure virtual methods.
-
-  In contrast to ImageHandle, a ConstFunction class is not
-  necessary, since assignement and copy-construction do
-  not share the underlying implementation.
-*/
-
-/*
-  Observer implementation will result in empty observer list
-  upon copy construction or assignement.
-*/
-
-class DLLEXPORT_OST_IMG_BASE Function: public Data {
-  typedef Observable<DataObserver> DataObservable;
-
- public:
-  /*! @name Initialization and deconstruction
-    No publically accessible ctors, Function is an abstract base class.
-   */
-  //@{
-  virtual ~Function();
-  //@}
-
-  /*! @name Properties
-  */
-  //@{
-
-  //! See Data::GetType
-  virtual DataType GetType() const = 0;
-
-  //! Returns data domain, defaults to \c SPATIAL
-  virtual DataDomain GetDomain() const;
-
-  //! Returns extent of function
-  /*!
-    defaults to [Point(0,0,0), Point(0,0,0)], may be
-    modified by using SetExtent
-  */
-  virtual Extent GetExtent() const;
-  //! set Extent that this function is evaluated in
-  void SetExtent(const Extent& e);
-
-  //! see Data::SetSpatialOrigin
-  virtual void SetSpatialOrigin(const Point& o);
-  //! see Data::GetSpatialOrigin
-  virtual Point GetSpatialOrigin() const;
-
-  //@}
-
-  /*! @name Value retrieval
-    The pure virtual methods GetReal() and GetComplex() are
-    only given here for completeness. They still need to be 
-    implemented by a derived class.
-  */
-  //@{
-
-  //! see Data:GetReal
-  virtual Real GetReal(const Point& p) const; 
-
-  //! see Data:GetComplex
-  virtual Complex GetComplex(const Point& p) const; 
-
-  //! Get interpolated real value from 3D,2D or 1D vec
-  virtual Real GetIntpolReal(const Vec3 &v) const=0;
-  virtual Real GetIntpolReal(const Vec2 &v) const;
-  virtual Real GetIntpolReal(const Real &d) const;
-
-  //! Get interpolated complex value from 3D,2D or 1D vec
-  virtual Complex GetIntpolComplex(const Vec3 &v) const=0;
-  virtual Complex GetIntpolComplex(const Vec2 &v) const;
-  virtual Complex GetIntpolComplex(const Real &d) const;
-
-  //@}
-
-
-  /*! @name Algorithm interface
-    On the level of Function, only NonModAlgorithms may be applied
-  */
-  //@{
-  // use doc from Data
-  virtual void Apply(NonModAlgorithm& a) const;
-  virtual void ApplyIP(NonModAlgorithm& a) const;
-  //@}
-
-  /*! @name Observer interface
-   */
-  // use doc from Data
-  //@{
-  virtual void Attach(DataObserver *o) const;
-  virtual void Detach(DataObserver *o) const;
-  virtual void Notify() const;
-  //@}
-
-
- protected:
-  //! Initialization with Domain (required) and Extent(defaults to Size(1))
-  Function(DataDomain d, const Extent& e=Extent());
-
-  Function(const Function& f);
-
-  Function& operator=(const Function& f);
-
-  /*! @name Sampling implementation
-   */
-  //@{
-  virtual PixelSampling& Sampling();
-  virtual const PixelSampling& Sampling() const;
-  //@}
-
-private:
-  Extent extent_;
-  DataDomain domain_;
-
-  /*
-    implement logical constness for Attach and Detach
-  */
-  mutable DataObservable obs_;
-
-  PixelSampling sampling_;
-};
-
-}} // namespace
-
-#endif
diff --git a/modules/img/base/src/function_fw.hh b/modules/img/base/src/function_fw.hh
deleted file mode 100644
index 17473cf94ec7ac3266e16bfcaf09696944c79a56..0000000000000000000000000000000000000000
--- a/modules/img/base/src/function_fw.hh
+++ /dev/null
@@ -1,36 +0,0 @@
-//------------------------------------------------------------------------------
-// This file is part of the OpenStructure project <www.openstructure.org>
-//
-// Copyright (C) 2008-2011 by the OpenStructure authors
-// Copyright (C) 2003-2010 by the IPLT authors
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License as published by the Free
-// Software Foundation; either version 3.0 of the License, or (at your option)
-// any later version.
-// This library is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with this library; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//------------------------------------------------------------------------------
-
-/*
-  convenience header for forward declaration of Function
-
-  Author: Ansgar Philippsen
-*/
-
-#ifndef IMG_FUNCTION_FW_H
-#define IMG_FUNCTION_FW_H
-
-#include <ost/img/module_config.hh>
-
-namespace ost { namespace img {
-  class Function;
-}}
-
-#endif
diff --git a/modules/img/base/src/function_impl.cc b/modules/img/base/src/function_impl.cc
deleted file mode 100644
index 47cb883488e7c5252964fa9842519ba3810708ce..0000000000000000000000000000000000000000
--- a/modules/img/base/src/function_impl.cc
+++ /dev/null
@@ -1,76 +0,0 @@
-//------------------------------------------------------------------------------
-// This file is part of the OpenStructure project <www.openstructure.org>
-//
-// Copyright (C) 2008-2011 by the OpenStructure authors
-// Copyright (C) 2003-2010 by the IPLT authors
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License as published by the Free
-// Software Foundation; either version 3.0 of the License, or (at your option)
-// any later version.
-// This library is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with this library; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//------------------------------------------------------------------------------
-
-/*
-  function implementation
-
-  Author: Ansgar Philippsen
-*/
-
-#include "function_impl.hh"
-#include "value_util.hh"
-
-namespace ost { namespace img { namespace detail {
-
-template <typename T>
-DataType FunctionImpl<T>::GetType() const
-{
-  return Val2Type<T>();
-}
-
-
-template <typename T>
-Real FunctionImpl<T>::GetIntpolReal(const Vec3 &v) const
-{
-  return Val2Val<T,Real>(Func(v));
-}
-
-template <typename T>
-Complex FunctionImpl<T>::GetIntpolComplex(const Vec3 &v) const
-{
-  return Val2Val<T,Complex>(Func(v));
-}
-
-template <typename T>
-FunctionImpl<T>::FunctionImpl(DataDomain d):
-  Function(d)
-{}
-
-
-template <typename T>
-FunctionImpl<T>::FunctionImpl(const FunctionImpl<T>& f):
-  Function(f)
-{}
-
-template <typename T>
-FunctionImpl<T>& FunctionImpl<T>::operator=(const FunctionImpl<T>& f) 
-{
-  Function::operator=(f);
-  return *this;
-}
-
-
-} // namespace
-
-// explicit instantiations
-template class TEMPLATE_DEF_EXPORT detail::FunctionImpl<Real>;
-template class TEMPLATE_DEF_EXPORT detail::FunctionImpl<Complex>;
-
-}} // namespace
diff --git a/modules/img/base/src/function_impl.hh b/modules/img/base/src/function_impl.hh
deleted file mode 100644
index 8283b57df9c1f2cd75612144573f672c4c5797c1..0000000000000000000000000000000000000000
--- a/modules/img/base/src/function_impl.hh
+++ /dev/null
@@ -1,71 +0,0 @@
-//------------------------------------------------------------------------------
-// This file is part of the OpenStructure project <www.openstructure.org>
-//
-// Copyright (C) 2008-2011 by the OpenStructure authors
-// Copyright (C) 2003-2010 by the IPLT authors
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License as published by the Free
-// Software Foundation; either version 3.0 of the License, or (at your option)
-// any later version.
-// This library is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with this library; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//------------------------------------------------------------------------------
-
-/*
-  template function implementation, to serve
-  as the basis for RealFunction and ComplexFunction
-
-  Author: Ansgar Philippsen
-*/
-
-#ifndef IMG_FUNCTION_IMPL_H
-#define IMG_FUNCTION_IMPL_H
-
-#include <ost/img/module_config.hh>
-#include "function_base.hh"
-
-namespace ost { namespace img { namespace detail {
-
-template <typename T>
-class TEMPLATE_EXPORT FunctionImpl: public Function {
- public:
-
-  ////////////////////////////
-  // Data interface
-
-  virtual DataType GetType() const;
-
-  /////////////////////////////
-  // Function interface
-
-  virtual Real GetIntpolReal(const Vec3 &v) const;
-  virtual Complex GetIntpolComplex(const Vec3 &v) const;
-
-  //////////////////////////////////
-  // FunctionImpl interface
-
-  /*!
-    abstract method that returns actual function value. Must
-    be implemented by derived classes
-  */
-  virtual T Func(const Vec3 &v) const = 0;
-
- protected:
-  //! instantiation requires domain specification
-  FunctionImpl(DataDomain d);
-
-  FunctionImpl(const FunctionImpl& f);
-
-  FunctionImpl& operator=(const FunctionImpl& f);
-};
-
-}}} // namespaces
-
-#endif
diff --git a/modules/img/base/src/image_handle.cc b/modules/img/base/src/image_handle.cc
index 92234663c3a0d14a7444373c433d155c68cd90f7..c0059be0b852490c5e50306fffab6fca18f23208 100644
--- a/modules/img/base/src/image_handle.cc
+++ b/modules/img/base/src/image_handle.cc
@@ -21,7 +21,7 @@
 /*
   image handle and const handle
 
-  Author: Ansgar Philippsen
+  Author: Ansgar Philippsen, Andreas Schenk
 */
 
 #include <ost/message.hh>
@@ -37,6 +37,7 @@
 #include "image_impl.hh"
 #include "observable.hh"
 #include "paste_impl.hh"
+#include "data_observer.hh"
 
 #include "image_state/image_state_factory.hh"
 #include "image_state/image_state_base.hh"
@@ -572,47 +573,6 @@ ImageHandle& ImageHandle::operator/=(const ConstImageHandle& h)
   return *this;
 }
 
-ImageHandle& ImageHandle::operator+=(const Function& h)
-{
-  try {
-    ImageStatePtr()->operator+=(h);
-  } catch(InvalidExtentException&) {
-    // ignore
-  }
-  return *this;
-}
-
-ImageHandle& ImageHandle::operator-=(const Function& h)
-{
-  try {
-    ImageStatePtr()->operator-=(h);
-  } catch(InvalidExtentException&) {
-    // ignore
-  }
-  return *this;
-}
-
-ImageHandle& ImageHandle::operator*=(const Function& h)
-{
-  try {
-    ImageStatePtr()->operator*=(h);
-  } catch(InvalidExtentException&) {
-    // ignore
-  }
-  return *this;
-}
-
-ImageHandle& ImageHandle::operator/=(const Function& h)
-{
-  try {
-    ImageStatePtr()->operator/=(h);
-  } catch(InvalidExtentException&) {
-    // ignore
-  }
-  return *this;
-}
-
-
 void ImageHandle::Reciproce()
 {
   throw Error("Reciproce not implemented");
@@ -989,53 +949,6 @@ ImageHandle operator/(const ConstImageHandle& h1, const ConstImageHandle& h2)
   return nh;
 }
 
-ImageHandle operator+(const ConstImageHandle& h1, const Function& h2)
-{
-  ImageHandle nh=h1.Copy();
-  nh+=h2;
-  return nh;
-}
 
-ImageHandle operator-(const ConstImageHandle& h1, const Function& h2)
-{
-  ImageHandle nh=h1.Copy();
-  nh-=h2;
-  return nh;
-}
-
-ImageHandle operator*(const ConstImageHandle& h1, const Function& h2)
-{
-  ImageHandle nh=h1.Copy();
-  nh*=h2;
-  return nh;
-}
-
-ImageHandle operator/(const ConstImageHandle& h1, const Function& h2)
-{
-  ImageHandle nh=h1.Copy();
-  nh/=h2;
-  return nh;
-}
-
-ImageHandle operator+(const Function& h1, const ConstImageHandle& h2)
-{
-  ImageHandle nh=h2.Copy();
-  nh+=h1;
-  return nh;
-}
-
-ImageHandle operator-(const Function& h1, const ConstImageHandle& h2)
-{
-  ImageHandle nh=h2.Copy();
-  nh+=h1;
-  return nh;
-}
-
-ImageHandle operator*(const Function& h1, const ConstImageHandle& h2)
-{
-  ImageHandle nh=h2.Copy();
-  nh*=h1;
-  return nh;
-}
 
 }} // namespace
diff --git a/modules/img/base/src/image_handle.hh b/modules/img/base/src/image_handle.hh
index 4acf4e2718c2ee3d56ad80b7d8216d6ca8361731..847d897c40b88b7ed3bf0c31516e048c922c967c 100644
--- a/modules/img/base/src/image_handle.hh
+++ b/modules/img/base/src/image_handle.hh
@@ -23,7 +23,7 @@
 
   offers the Image interface
 
-  Author: Ansgar Philippsen
+  Author: Ansgar Philippsen, Andreas Schenk
 */
 
 #ifndef IMG_IMAGE_HANDLE_H
@@ -37,8 +37,6 @@
 
 #include "data.hh"
 #include "observable.hh"
-#include "data_observer.hh"
-#include "function.hh"
 #include "extent_iterator.hh"
 
 #include "image_state/image_state_visitor_fw.hh"
@@ -70,6 +68,7 @@ class ModIPAlgorithm;
 class ConstModIPAlgorithm;
 class ModOPAlgorithm;
 class ConstModOPAlgorithm;
+class DataObserver;
 
 //! Exception thrown upon invalid image handle usage
 class DLLEXPORT InvalidImageHandle: public Error {
@@ -118,7 +117,7 @@ class DLLEXPORT_OST_IMG_BASE ImageHandle: public Data {
   // for access to Sampling
   friend class ConstImageHandle;
 
-  typedef Observable<DataObserver> DataObservable;
+  typedef Observable DataObservable;
   typedef boost::shared_ptr<DataObservable> ObsPtr;
 
   typedef boost::shared_ptr<ImageStateBasePtr> StatePtrPtr;
@@ -463,11 +462,6 @@ public:
   ImageHandle& operator*=(const ConstImageHandle& h);
   ImageHandle& operator/=(const ConstImageHandle& h);
 
-  ImageHandle& operator+=(const Function& h);
-  ImageHandle& operator-=(const Function& h);
-  ImageHandle& operator*=(const Function& h);
-  ImageHandle& operator/=(const Function& h);
-
   //@}
 
   /*! @name low-level access
@@ -736,14 +730,6 @@ DLLEXPORT_OST_IMG_BASE ImageHandle operator-(const ConstImageHandle& h1, const C
 DLLEXPORT_OST_IMG_BASE ImageHandle operator*(const ConstImageHandle& h1, const ConstImageHandle& h2);
 DLLEXPORT_OST_IMG_BASE ImageHandle operator/(const ConstImageHandle& h1, const ConstImageHandle& h2);
 
-DLLEXPORT_OST_IMG_BASE ImageHandle operator+(const ConstImageHandle& h1, const Function& h2);
-DLLEXPORT_OST_IMG_BASE ImageHandle operator-(const ConstImageHandle& h1, const Function& h2);
-DLLEXPORT_OST_IMG_BASE ImageHandle operator*(const ConstImageHandle& h1, const Function& h2);
-DLLEXPORT_OST_IMG_BASE ImageHandle operator/(const ConstImageHandle& h1, const Function& h2);
-
-DLLEXPORT_OST_IMG_BASE ImageHandle operator+(const Function& h1, const ConstImageHandle& h2);
-DLLEXPORT_OST_IMG_BASE ImageHandle operator-(const Function& h1, const ConstImageHandle& h2);
-DLLEXPORT_OST_IMG_BASE ImageHandle operator*(const Function& h1, const ConstImageHandle& h2);
 
 }} // namespace img
 
diff --git a/modules/img/base/src/image_list.cc b/modules/img/base/src/image_list.cc
index 27c47423b66be12ab4156bfd89e602782f292d00..522e5f7af76c67f2b171ec5ad6f07e9782adef4c 100644
--- a/modules/img/base/src/image_list.cc
+++ b/modules/img/base/src/image_list.cc
@@ -329,32 +329,4 @@ ImageList& ImageList::operator/=(const ConstImageHandle& h)
     }
     return *this;
 }
-ImageList& ImageList::operator+=(const Function& h)
-{
-    for(iterator it=begin();it!=end();++it){
-        (*it)+=h;    
-    }
-    return *this;
-}
-ImageList& ImageList::operator-=(const Function& h)
-{
-    for(iterator it=begin();it!=end();++it){
-        (*it)-=h;    
-    }
-    return *this;
-}
-ImageList& ImageList::operator*=(const Function& h)
-{
-    for(iterator it=begin();it!=end();++it){
-        (*it)*=h;    
-    }
-    return *this;
-}
-ImageList& ImageList::operator/=(const Function& h)
-{
-    for(iterator it=begin();it!=end();++it){
-        (*it)/=h;    
-    }
-    return *this;
-}
 }}//ns
diff --git a/modules/img/base/src/image_list.hh b/modules/img/base/src/image_list.hh
index 70fd1ca478055b87995723e1ad8edeb8e62f65fa..43314701376a1a550918eebb83c2c5f2f97df99e 100644
--- a/modules/img/base/src/image_list.hh
+++ b/modules/img/base/src/image_list.hh
@@ -135,10 +135,6 @@ public:
   ImageList& operator-=(const ConstImageHandle& h);
   ImageList& operator*=(const ConstImageHandle& h);
   ImageList& operator/=(const ConstImageHandle& h);
-  ImageList& operator+=(const Function& h);
-  ImageList& operator-=(const Function& h);
-  ImageList& operator*=(const Function& h);
-  ImageList& operator/=(const Function& h);
 private:
   Size get_max_size_();
   DataType get_data_type_();
diff --git a/modules/img/base/src/image_state/image_state_algorithm.hh b/modules/img/base/src/image_state/image_state_algorithm.hh
index e5546583a2208bd600c66d73667783aa3acb8338..54a4b939ebb48e56b1abd32c24e090a77aac4418 100644
--- a/modules/img/base/src/image_state/image_state_algorithm.hh
+++ b/modules/img/base/src/image_state/image_state_algorithm.hh
@@ -226,16 +226,13 @@ namespace ost { namespace img { namespace image_state {
     FNC(p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,pa,pb), BASE (FNC::GetAlgorithmName()) {}
 
 
-//! non-modifying image state visitor plus data algorithm
+//! non-modifying image state visitor plus non-mod algorithm
 /*!
   This convenience hybrid class combines the functionality of
   the NonModAlgorithm and the ImageStateNonModVisitor by implementing
-  both interfaces. The template is expected to be a class with two
-  methods, a VisitState() method as for 
-  img::image_state::ImageStateNonModVisitor, and in addition a 
-  Visit(const Function&) method for the implementation of the
-  img::NonModAlgorithm interface and a static GetAlgorithmName() for
-  the initialization of the img::NonModAlgorithm ctor
+  both interfaces. The template parameter is expected to be a class
+  offering VisitState (see img::image_state::ImageStateNonModVisitor ),
+  plus a static GetAlgorithmName() method:
 
   \code
 
@@ -244,8 +241,6 @@ namespace ost { namespace img { namespace image_state {
     template<typename T, class D>
     void VisitState(const img::image_state::ImageStateImpl<T,D>& isi);
 
-    void VisitFunction(const Funcion& f);
-
     static String GetAlgorithmName();
   };
 
@@ -275,9 +270,6 @@ public:
   virtual void Visit(const ConstImageHandle& h) {
     h.StateApply(*this);
   }
-  virtual void Visit(const Function& f) {
-    this->VisitFunction(f);
-  }
   
 private:
   /*
diff --git a/modules/img/base/src/image_state/image_state_base.hh b/modules/img/base/src/image_state/image_state_base.hh
index 016fab63a063394b5515e42dbb482bf302b874cc..34fc74e61d9a531807763a5b2f633f4c486ff3bf 100644
--- a/modules/img/base/src/image_state/image_state_base.hh
+++ b/modules/img/base/src/image_state/image_state_base.hh
@@ -30,7 +30,8 @@
 #include "image_state_base_fw.hh"
 
 #include <ost/base.hh>
-#include <ost/img/function.hh>
+#include <ost/img/module_config.hh>
+#include <ost/img/data.hh>
 
 #include "image_state_visitor_fw.hh"
 #include "type_fw.hh"
@@ -57,7 +58,7 @@ public:
   // provide deep copy
   virtual ImageStateBasePtr Clone(bool cc=true) const = 0;
 
-  virtual long MemSize() const = 0;
+  virtual size_t MemSize() const = 0;
 
   ///////////////////////////////////////
   // abstract virtual methods
@@ -208,11 +209,6 @@ public:
   ImageStateBase& operator*=(const ImageStateBase& b);
   ImageStateBase& operator/=(const ImageStateBase& b);
 
-  virtual void operator+=(const Function& b) = 0;
-  virtual void operator-=(const Function& b) = 0;
-  virtual void operator*=(const Function& b) = 0;
-  virtual void operator/=(const Function& b) = 0;
-
 protected:
   ImageStateBase() {}
   ImageStateBase(const ImageStateBase& s) {}
diff --git a/modules/img/base/src/image_state/image_state_impl.cc b/modules/img/base/src/image_state/image_state_impl.cc
index fbef8e2e68dcb65f89f3f8dcd74f9176168da83f..2575a1adb3ffe4493461bc68fe798127dba55449 100644
--- a/modules/img/base/src/image_state/image_state_impl.cc
+++ b/modules/img/base/src/image_state/image_state_impl.cc
@@ -117,7 +117,7 @@ ImageStateBasePtr ImageStateImpl<T,D>::Clone(bool cc) const
 
 
 template <typename T, class D>
-long ImageStateImpl<T,D>::MemSize() const 
+size_t ImageStateImpl<T,D>::MemSize() const
 {
   return data_.MemSize();
 }
@@ -125,7 +125,7 @@ long ImageStateImpl<T,D>::MemSize() const
 template <typename T, class D>
 DataType ImageStateImpl<T,D>::GetType() const
 {
-  return Val2Type<T>();
+  return data_.GetDataType();
 }
 
 template <typename T, class D>
@@ -564,15 +564,15 @@ const T& ImageStateImpl<T,D>::Value(const Index& i) const
 }
 
 template <typename T, class D>
-T& ImageStateImpl<T,D>::Value(unsigned int i)
+T& ImageStateImpl<T,D>::Value(size_t i)
 {
-  return data_.Value(i);
+    return data_.GetData()[i];
 }
 
 template <typename T, class D>
-const T& ImageStateImpl<T,D>::Value(unsigned int i) const
+const T& ImageStateImpl<T,D>::Value(size_t i) const
 {
-  return data_.Value(i);
+    return data_.GetData()[i];
 }
 
 template <typename T, class D>
@@ -702,130 +702,6 @@ ImageStateBase& ImageStateImpl<T,D>::operator/=(const Complex& v)
   return *this;
 }
 
-// add function
-
-template<typename T>
-void add_func_value(T& v, const Function& f, const Point& p);
-
-template<>
-void add_func_value(Real& v, const Function& f, const Point& p)
-{
-  v+=f.GetReal(p);
-}
-
-template<>
-void add_func_value(Complex& v, const Function& f, const Point& p)
-{
-  v+=f.GetComplex(p);
-}
-
-template<typename T>
-void add_func_value(T& v, const Function& f, const Point& p)
-{
-  v+=static_cast<T>(f.GetReal(p));
-}
-
-template <typename T, class D>
-void ImageStateImpl<T,D>::operator+=(const Function& f)
-{
-  for(ExtentIterator it(this->GetExtent());!it.AtEnd();++it) {
-    add_func_value(this->Value(it),f,it);
-  }
-}
-
-// sub function
-
-template<typename T>
-void sub_func_value(T& v, const Function& f, const Point& p);
-
-template<>
-void sub_func_value(Real& v, const Function& f, const Point& p)
-{
-  v-=f.GetReal(p);
-}
-
-template<>
-void sub_func_value(Complex& v, const Function& f, const Point& p)
-{
-  v-=f.GetComplex(p);
-}
-
-template<typename T>
-void sub_func_value(T& v, const Function& f, const Point& p)
-{
-  v-=static_cast<T>(f.GetReal(p));
-}
-
-template <typename T, class D>
-void ImageStateImpl<T,D>::operator-=(const Function& f)
-{
-  for(ExtentIterator it(this->GetExtent());!it.AtEnd();++it) {
-    sub_func_value(this->Value(it),f,it);
-  }
-}
-
-// mul function
-
-template<typename T>
-void mul_func_value(T& v, const Function& f, const Point& p);
-
-template<>
-void mul_func_value(Real& v, const Function& f, const Point& p)
-{
-  v*=f.GetReal(p);
-}
-
-template<>
-void mul_func_value(Complex& v, const Function& f, const Point& p)
-{
-  v*=f.GetComplex(p);
-}
-
-template<typename T>
-void mul_func_value(T& v, const Function& f, const Point& p)
-{
-  v*=static_cast<T>(f.GetReal(p));
-}
-
-template <typename T, class D>
-void ImageStateImpl<T,D>::operator*=(const Function& f)
-{
-  for(ExtentIterator it(this->GetExtent());!it.AtEnd();++it) {
-    mul_func_value(this->Value(it),f,it);
-  }
-}
-
-// div function
-
-template<typename T>
-void div_func_value(T& v, const Function& f, const Point& p);
-
-template<>
-void div_func_value(Real& v, const Function& f, const Point& p)
-{
-  v/=f.GetReal(p);
-}
-
-template<>
-void div_func_value(Complex& v, const Function& f, const Point& p)
-{
-  v/=f.GetComplex(p);
-}
-
-template<typename T>
-void div_func_value(T& v, const Function& f, const Point& p)
-{
-  v/=static_cast<T>(f.GetReal(p));
-}
-
-
-template <typename T, class D>
-void ImageStateImpl<T,D>::operator/=(const Function& f)
-{
-  for(ExtentIterator it(this->GetExtent());!it.AtEnd();++it) {
-    div_func_value(this->Value(it),f,it);
-  }
-}
 
 template <typename T, class D>
 template <typename U>
diff --git a/modules/img/base/src/image_state/image_state_impl.hh b/modules/img/base/src/image_state/image_state_impl.hh
index 62e6895cf03458c64d5798c39017a992271e0211..e3a70ae93ca6b402b4d708189b97742d51855207 100644
--- a/modules/img/base/src/image_state/image_state_impl.hh
+++ b/modules/img/base/src/image_state/image_state_impl.hh
@@ -74,19 +74,6 @@ public:
   // also takes absolute center, requires logical extent, not physical one!
   ImageStateImpl(const Extent& e, const PixelSampling& s, const Vec3& c);
 
-  /* 
-     special ctor to utilize pre-allocated memory: the data area allocated
-     by ValueHolder will be transfered to this image state
-  */
-  template <typename U>
-  ImageStateImpl(const Extent& e, ValueHolder<U>& d, const PixelSampling& s):
-    domain_(e),
-    data_(domain_.GetExtent().GetSize(),d),
-    sampling_(s)
-  {
-    assert(d.GetPhysicalSize()*sizeof(U)==data_.GetPhysicalSize()*sizeof(T));
-  }
-
   virtual ~ImageStateImpl();
 
   SharedPtrType CloneState(bool cc=true) const;
@@ -94,7 +81,7 @@ public:
   // image state base interface
   virtual ImageStateBasePtr Clone(bool cc=true) const;
   
-  virtual long MemSize() const;
+  virtual std::size_t MemSize() const;
 
   virtual DataType GetType() const;
 
@@ -181,10 +168,10 @@ public:
   const T& Value(const Index& i) const;
 
   // pass-through to value holder
-  T& Value(unsigned int i);
+  T& Value(std::size_t i);
 
   // pass-through to value holder
-  const T& Value(unsigned int i) const;
+  const T& Value(std::size_t i) const;
 
   //! direct access to value holder
   ValueHolder<T>& Data();
@@ -224,11 +211,6 @@ public:
   virtual ImageStateBase& operator/=(Real v);
   virtual ImageStateBase& operator/=(const Complex& v);
 
-  virtual void operator+=(const Function& b);
-  virtual void operator-=(const Function& b);
-  virtual void operator*=(const Function& b);
-  virtual void operator/=(const Function& b);
-
 protected:
   // helper methods for operators above
   template <typename U> void add_scalar(const U& v);
diff --git a/modules/img/base/src/image_state/image_state_spatial_domain.hh b/modules/img/base/src/image_state/image_state_spatial_domain.hh
index 5d5e883252984519a3ca5d52ebf348a7000bcd7a..432008e194c3e9bf045bcab2e3fcef5043ceac4a 100644
--- a/modules/img/base/src/image_state/image_state_spatial_domain.hh
+++ b/modules/img/base/src/image_state/image_state_spatial_domain.hh
@@ -49,8 +49,7 @@ namespace ost { namespace img { namespace image_state {
 class DLLEXPORT_OST_IMG_BASE SpatialDomain {
 public:
   SpatialDomain(const Extent& e):
-    extent_(e),
-    physical_extent_(ExtractPhysicalExtent(e))
+    extent_(e)
   {}
 
   // interface for ImageStateImpl
@@ -73,7 +72,7 @@ public:
   }
 
   Extent GetPhysicalExtent() const {
-    return physical_extent_;
+    return extent_;
   }
 
   template <typename V>
@@ -110,29 +109,13 @@ public:
 
   Index Point2Index(const Point& p) const {
     return Index(p[0]-extent_.GetStart()[0],
-		 p[1]-extent_.GetStart()[1],
-		 p[2]-extent_.GetStart()[2]);
+                 p[1]-extent_.GetStart()[1],
+                 p[2]-extent_.GetStart()[2]);
   }
   
 private:
   Extent extent_;
-  Extent physical_extent_;
-  
-  Extent ExtractPhysicalExtent(const Extent& e) const {
-#if 1
-    Point pad;
-    if(e.GetDim()==1) {
-      pad=Point( (e.GetSize()[0]&0x1) ? 1 : 2,0,0);
-    } else if(e.GetDim()==2) {
-      pad=Point(0,(e.GetSize()[1]&0x1) ? 1 : 2,0);
-    } else {
-      pad=Point(0,0,(e.GetSize()[2]&0x1) ? 1 : 2);
-    }
-    return Extent(e.GetStart(),e.GetEnd()+pad);
-#else
-    return Extent(e.GetStart(),e.GetEnd());
-#endif
-  }
+
 };
 
 }}} // ns
diff --git a/modules/img/base/src/image_state/value_holder.cc b/modules/img/base/src/image_state/value_holder.cc
index ed320e28e91c44a1232e25c1cd96aa687511ee06..b17acccbc93758dfaca5b0fda583e2f8569b0953 100644
--- a/modules/img/base/src/image_state/value_holder.cc
+++ b/modules/img/base/src/image_state/value_holder.cc
@@ -21,7 +21,7 @@
 /*
   value holder for image states
 
-  Author: Ansgar Philippsen
+  Authors: Ansgar Philippsen, Andreas Schenk
 */
 
 #ifndef IMG_IMAGE_STATE_INST_H
@@ -31,138 +31,103 @@
 #include <cassert>
 #include <algorithm>
 
+#include <ost/img/value_util.hh>
 #include <ost/img/size.hh>
 
 #include "value_holder.hh"
 #include "index.hh"
 
-#define USE_ROW_ORDER 1
-
 namespace ost { namespace img { namespace image_state {
 
 namespace {
 
-// helper function
-template <class V>
-V* ValueCopy(const V* src, size_t volume_)
-{
-  V* dest = new V[volume_]; // if this throws, nothing has happened yet
-  try {
-    std::copy(src,src+volume_,dest);
-  } catch (...) {
-    delete []dest; // remove already allocated data
-    throw;
-  }
-  return dest;
-}
-
-template <typename V>
-DataType GetValueType();
-
-template <>
-DataType GetValueType<Complex>() {return COMPLEX;}
-
 template <typename V>
-DataType GetValueType() {return REAL;}
-
-}
-
-template <typename V>
-ValueHolder<V>::ValueHolder(unsigned int wi, unsigned int he, unsigned int de):
-  width_( (wi<1) ? 1 : wi), 
-  height_( (he<1) ? 1: he ),
-  depth_( (de<1) ? 1: de ),
-  volume_(width_*height_*depth_),
-  volume2_(volume_),
-  data_(0),
-  row_(0),
-  slice_(0)
+std::size_t calc_volume(const Size& s)
 {
-  try {
-    data_ = new V[volume2_];
-    setup();
-    clear();
-  } catch(...) {
-    delete []data_;
+  unsigned int tmp;
+  unsigned int numbits = 0;
+  //find and add highest bit set for each dimension
+  tmp=s[0];
+  while (tmp >>= 1)
+  {
+    ++numbits;
+  }
+  tmp=s[1];
+  while (tmp >>= 1)
+  {
+    ++numbits;
+  }
+  tmp=s[2];
+  while (tmp >>= 1)
+  {
+    ++numbits;
+  }
+  tmp=sizeof(V);
+  while (tmp >>= 1)
+  {
+    ++numbits;
+  }
+  // check if number of pixels (2**(numbits+1)) larger than what std::size_t can handle
+  if(numbits>=sizeof(std::size_t)*8){
+      throw std::bad_alloc();
   }
+  return static_cast<std::size_t>(s[0])*static_cast<std::size_t>(s[1])*static_cast<std::size_t>(s[2]);
 }
 
+} //ns
+
 template <typename V>
 ValueHolder<V>::ValueHolder(const Size& s):
-  width_(s[0]),
-  height_(s[1]),
+#ifdef USE_ROW_ORDER
   depth_(s[2]),
-  volume_(width_*height_*depth_),
-  volume2_(volume_),
-  data_(0),
-  row_(0),
-  slice_(0)
+  height_depth_(s[1]*depth_),
+  data_(s[0]*height_depth_)
+#else
+  height_(s[1]),
+  width_height_(s[0]*height_),
+    data_(calc_volume<V>(s))
+#endif
 {
-  try {
-    data_ = new V[volume2_];
-    setup();
-    clear();
-  } catch(...) {
-    delete []data_;
-  }
 }
 
 template <typename V>
 ValueHolder<V>::ValueHolder(const Size& s, const Size& ps):
-  width_(s[0]),
-  height_(s[1]),
+#ifdef USE_ROW_ORDER
   depth_(s[2]),
-  volume_(width_*height_*depth_),
-  volume2_(ps.GetVolume()),
-  data_(0),
-  row_(0),
-  slice_(0)
+  height_depth_(s[1]*depth_),
+#else
+  height_(s[1]),
+  width_height_(s[0]*height_),
+#endif
+    data_(calc_volume<V>(ps))
 {
-  try {
-    data_ = new V[volume2_];
-    setup();
-    clear();
-  } catch(...) {
-    delete []data_;
-  }
 }
 
 template <typename V>
 ValueHolder<V>::ValueHolder(const ValueHolder<V>& h):
-  width_(h.width_),
-  height_(h.height_),
+#ifdef USE_ROW_ORDER
   depth_(h.depth_),
-  volume_(h.volume_),
-  volume2_(h.volume2_),
-  data_(ValueCopy(h.data_,h.volume2_)), // exception safe call
-  row_(0),
-  slice_(0)
+  height_depth_(h.height_depth_),
+#else
+  height_(h.height_),
+  width_height_(h.width_height_),
+#endif
+  data_(h.data_.begin(),h.data_.end())
 {
-  try {
-    setup();
-  } catch(...) {
-    delete []data_;
-  }
 }
 
 template <typename V>
 ValueHolder<V>& ValueHolder<V>::operator=(const ValueHolder<V>& h) 
 {
   if(this!=&h) {
-    delete []data_;
-    delete []row_;
-    delete []slice_;
-    data_ = ValueCopy(h.data_, h.volume2_);
-    width_=h.width_;
-    height_=h.height_;
-    depth_=h.depth_;
-    volume_=h.volume_;
-    volume2_=h.volume2_;
-    try {
-      setup();
-    } catch (...) {
-      throw;
-    }
+    data_.assign(h.data_.begin(),h.data_.end());
+    #ifdef USE_ROW_ORDER
+      depth_=h.depth_;
+      height_depth_=h.height_depth_;
+    #else
+      height_=h.height_;
+      width_height_=h.width_height_;
+    #endif
   }
   return *this;
 }
@@ -170,134 +135,59 @@ ValueHolder<V>& ValueHolder<V>::operator=(const ValueHolder<V>& h)
 template <typename V>
 ValueHolder<V>::~ValueHolder()
 {
-  delete []slice_;
-  delete []row_;
-  delete []data_;
 }
 
 template <typename V>
 void ValueHolder<V>::Swap(ValueHolder& vh)
 {
-  std::swap<>(width_,vh.width_);
-  std::swap<>(height_,vh.height_);
-  std::swap<>(depth_,vh.depth_);
-  std::swap<>(volume_,vh.volume_);
-  std::swap<>(volume2_,vh.volume2_);
+  #ifdef USE_ROW_ORDER
+    std::swap<>(depth_,vh.depth_);
+    std::swap<>(height_depth_,vh.height_depth_);
+  #else
+    std::swap<>(height_,vh.height_);
+    std::swap<>(width_height_,vh.width_height_);
+  #endif
   std::swap<>(data_,vh.data_);
-  std::swap<>(row_,vh.row_);
-  std::swap<>(slice_,vh.slice_);
 }
 
-template <typename V>
-V* ValueHolder<V>::ReleaseData()
-{
-  V* ret = data_; data_=0;
-  delete []slice_; slice_=0;
-  delete []row_; row_=0;
-  return ret;
-}
-
-template <typename V>
-Size ValueHolder<V>::GetSize() const
-{
-  return Size(width_,depth_,height_);
-}
 
 template <typename V>
 V& ValueHolder<V>::Value(const Index& i)
 {
-  assert(i.u<width_ && i.v<height_ && i.w<depth_);
 #ifdef USE_ROW_ORDER
-  //return ((slice_[i.u])[i.v])[i.w];
-  return data_[i.u*height_*depth_ + i.v*depth_ +i.w];
+  assert(i.w<depth_);
+  return data_[i.u*height_depth_ + i.v*depth_ +i.w];
 #else
-  //return ((slice_[i.w])[i.v])[i.u];
-  return data_[i.w*width_*height_ + i.v*height_ +i.u];
+  assert(i.v<height_);
+  return data_[i.w*width_height_ + i.v*height_ +i.u];
 #endif
 }
 
 template <typename V>
 const V& ValueHolder<V>::Value(const Index& i) const
 {
-  assert(i.u<width_ && i.v<height_ && i.w<depth_);
 #ifdef USE_ROW_ORDER
-  //return ((slice_[i.u])[i.v])[i.w];
-  return data_[i.u*height_*depth_ + i.v*depth_ +i.w];
+  assert(i.w<depth_);
+  return data_[i.u*height_depth_ + i.v*depth_ +i.w];
 #else
-  //return ((slice_[i.w])[i.v])[i.u];
-  return data_[i.w*width_*height_ + i.v*height_ +i.u];
+  assert(i.v<height_);
+  return data_[i.w*width_height_ + i.v*height_ +i.u];
 #endif
 }
 
-template <typename V>
-V& ValueHolder<V>::Value(unsigned int i) 
-{
-  assert(i<volume_);
-  return data_[i];
-}
-
-template <typename V>
-const V& ValueHolder<V>::Value(unsigned int i) const
-{
-  assert(i<volume_);
-  return data_[i];
-}
 
 template <typename V>
 DataType ValueHolder<V>::GetDataType() 
 {
-  return GetValueType<V>();
+  return Val2Type<V>();
 }
 
 template <typename V>
-long ValueHolder<V>::MemSize() const
+std::size_t ValueHolder<V>::MemSize() const
 {
-  //return sizeof(V)*volume2_+sizeof(V*)*width_*height_+sizeof(V**)*width_+sizeof(*this);
-  return sizeof(V)*volume2_;
+  return sizeof(V)*data_.size();
 }
 
-template <typename V>
-void ValueHolder<V>::setup()
-{
-  typedef V* VPtr;
-  typedef VPtr* VPtrPtr;
-  row_=0;
-  slice_=0;
-  try {
-#if 0
-#ifdef USE_ROW_ORDER
-    row_ = new VPtr[width_*height_];
-    slice_ = new VPtrPtr[width_];
-    for(unsigned int u=0;u<width_;++u) {
-      for(unsigned int v=0;v<height_;++v) {
-	row_[u*height_+v]=&data_[u*height_*depth_+v*depth_];
-      }
-      slice_[u]=&row_[u*height_];
-    }
-#else
-    row_ = new VPtr[height_*depth_];
-    slice_ = new VPtrPtr[depth_];
-    
-    for(unsigned int w=0;w<depth_;++w) {
-      for(unsigned int v=0;v<height_;++v) {
-	row_[w*height_+v]=&data_[w*width_*height_+v*width_];
-      }
-      slice_[w]=&row_[w*height_];
-    }
-#endif
-#endif
-  } catch (...) {
-    delete slice_;
-    delete row_;
-    throw;
-  }
-}
-
-template <typename V>
-void ValueHolder<V>::clear()
-{
-  for(unsigned int c=0;c<volume2_;++c) data_[c]=V();
-}
 
 
 }}} // namespaces
diff --git a/modules/img/base/src/image_state/value_holder.hh b/modules/img/base/src/image_state/value_holder.hh
index e0692f20af8a7810d626fc18aef40b491b134b3d..cb154c2e16f968b40141aa511d00e9a9b9bdf226 100644
--- a/modules/img/base/src/image_state/value_holder.hh
+++ b/modules/img/base/src/image_state/value_holder.hh
@@ -21,7 +21,7 @@
 /*
   value holder for image state
 
-  Author: Ansgar Philippsen
+  Authors: Ansgar Philippsen, Andreas Schenk
 */
 
 #ifndef VALUE_HOLDER_H
@@ -41,6 +41,10 @@ void ReleaseAndReconstruct();
 
 }
 
+#define USE_ROW_ORDER 1
+
+
+
 namespace ost { namespace img { namespace image_state {
 
 /*
@@ -57,14 +61,12 @@ template <typename V>
 class TEMPLATE_EXPORT ValueHolder {
 public:
   typedef V* VPtr;
+  typedef const V* ConstVPtr;
   typedef VPtr* VPtrPtr;
 
   /*! @name Construction, Release, etc
    */
   //@{
-  //! initialization with explicit width, height, and depth
-  ValueHolder(unsigned int wi, unsigned int he, unsigned int de);
-
   //! initialization with size
   ValueHolder(const Size& s);
 
@@ -74,25 +76,6 @@ public:
   //! copy ctor provides full copy!
   ValueHolder(const ValueHolder<V>& h);
 
-  //! initialize with a size and an existing value holder, grabbing the memory
-  template <typename U>
-  ValueHolder(const Size& s, ValueHolder<U>& v):
-    width_(s[0]),
-    height_(s[1]),
-    depth_(s[2]),
-    volume_(width_*height_*depth_),
-    volume2_(v.GetPhysicalSize()*sizeof(U)/sizeof(V)),
-    data_(reinterpret_cast<V*>(v.ReleaseData())),
-    row_(0),
-    slice_(0)
-  {
-    try {
-      setup();
-    } catch(...) {
-      delete []data_;
-    }
-  }
-
 
   //! assignement provides full copy!
   /*!
@@ -105,125 +88,52 @@ public:
   //! free allocated memory upon destruction
   ~ValueHolder();
 
-  //! release the held data, invalidates holder!
-  /*!
-    the data area is returned, but no longer belongs
-    to the value holder. it now belongs to the caller, who 
-    must eiter free it explicitely, or use it in a
-    constructor argument to a new value holder.
-   */
-  VPtr ReleaseData();
 
   //! swap data with another value holder
   void Swap(ValueHolder& vh);
   //@}
 
-  //! @name Property access
-  //@{
-
-  // retrieve width, at least 1
-  unsigned int GetWidth() const {return width_;}
-  // retrieve height, at least 1
-  unsigned int GetHeight() const {return height_;}
-  // retrieve depth, at least 1
-  unsigned int GetDepth() const {return depth_;}
-  // retrieve overall size (width*height*depth), at least 1
-  unsigned int GetVolume() const {return volume_;}
-  // retrieve dimensions as Size object
-  Size GetSize() const;
-
   static DataType GetDataType();
 
-  unsigned int GetPhysicalSize() const {return volume2_;}
-
-  long MemSize() const;
+  std::size_t  MemSize() const;
 
-  //@}
 
-  /*! @name Data Access
-    access is either via interface that uses the internal 
-    row and slice pointers, or these pointers may be
-    retrieved directly.
-  */
 
   //! return direct r/w access to the value without boundary check
   /*!
     The lookup is based on an integer triplet encapsulated within
-    Index. Efficient lookup using helper tables.
+    Index.
   */
   V& Value(const Index& i);
 
   //! return direct ro access to the value without boundary check
   /*!
     The lookup is based on an integer triplet encapsulated within
-    Index. Efficient lookup using helper tables.
+    Index.
   */
   const V& Value(const Index& i) const;
 
-  //! return direct r/w access to the value without boundary check
-  /*!
-    DEPRECATED! Use GetData()[i]
-  */
-  V& Value(unsigned int i);
-
-  //! return direct ro access to the value without boundary check
-  /*!
-    DEPRECATED! Use GetData()[i]
-  */
-  const V& Value(unsigned int i) const;
-
-
   //! return pointer to raw data
-  VPtr GetData() {return data_;}
+  VPtr GetData() {return &data_[0];}
   //! const version of GetData()
-  const VPtr GetData() const {return data_;}
-
-  //! return number of data items DEPRECATED
-  int DataCount() const {return volume_;}
-
-  //! return number of data items
-  /*!
-    this is the volume: width*height*depth
-  */
-  int GetDataCount() const {return volume_;}
+  ConstVPtr GetData() const {return &data_[0];}
 
-  const VPtr GetEnd() const {return &data_[volume_];}
 
-  //! return pointer to row pointers
-  VPtr* GetRows() {return row_;}
-  //! const version of GetRows()
-  const VPtr* GetRows() const {return row_;}
-  //! return number of row pointers
-  /*!
-    this is width*height
-  */
-  int GetRowCount() const {return width_*height_;}
+  ConstVPtr GetEnd() const {return &data_[0]+data_.size();}
 
-  //! return pointer to slice pointers
-  VPtrPtr* GetSlices() {return slice_;}
-  //! const version of GetSlices()
-  const VPtrPtr* GetSlices() const {return slice_;}
-  //! return number of slices
-  /*!
-    equals the width
-  */
-  int GetSliceCount() const {return width_;}
 
-  //@}
 private:
-  unsigned int width_, height_, depth_, volume_;
-  // this is a hack to get padding for fftw to work...
-  unsigned int volume2_;
+#ifdef USE_ROW_ORDER
+  std::size_t depth_;
+  std::size_t height_depth_;
+#else
+  std::size_t height_;
+  std::size_t width_height_;
+#endif
 
   // actual data storage
-  V* data_;
-  // optimization 
-  V** row_;
-  // optimization
-  V*** slice_;
-
-  void setup();
-  void clear();
+  std::vector<V> data_;
+
 };
 
 }}} // namespaces
diff --git a/modules/img/base/src/null_function.hh b/modules/img/base/src/observable.cc
similarity index 50%
rename from modules/img/base/src/null_function.hh
rename to modules/img/base/src/observable.cc
index d21613b0639e2eb9d88d9866dd1546cd27fcacc5..36d52009408a2d470d97cc3edfcf4396ba92ffb2 100644
--- a/modules/img/base/src/null_function.hh
+++ b/modules/img/base/src/observable.cc
@@ -19,40 +19,64 @@
 //------------------------------------------------------------------------------
 
 /*
-  convenience null function
+  abstract observable concept
 
   Author: Ansgar Philippsen
 */
 
-#ifndef IMG_NULL_FUNCTION_H
-#define IMG_NULL_FUNCTION_H
-
-#include "module_config.hh"
-#include "function_base.hh"
+#include <ost/img/observable.hh>
+#include <ost/img/data_observer.hh>
 
 namespace ost { namespace img {
 
-//! null function
-/*!
-  Implements Function interface, will always
-  return zero
-*/
-class DLLEXPORT NullFunction: public Function {
-public:
-  NullFunction():
-    Function(SPATIAL) 
-  {}
-  
-  virtual DataType GetType() const {return REAL;}
+Observable::Observable() {
+  list_.clear();
+}
 
-  virtual Real GetIntpolReal(const Vec3& v) const {return 0.0;}
+Observable::Observable(const Observable& o) {
+  list_.clear();
+}
 
-  virtual Complex GetIntpolComplex(const Vec3& v) const {return Complex(0.0,0.0);}
-  
-  virtual ~NullFunction(){};
-};
+Observable::~Observable() {
+  for(ObserverIter it=list_.begin();it!=list_.end();++it) {
+    (*it)->ObserverInvalidate();
+    (*it)->ObserverRelease();
+  }
+}
 
-}} // namespace
+Observable& Observable::operator=(const Observable& o) {
+  list_.clear();
+  return *this;
+}
+
+void Observable::Attach(DataObserver* d) {
+  list_.push_back(d);
+}
+
+void Observable::Detach(DataObserver* o) {
+  list_.remove(o);
+}
 
+void Observable::Notify() const {
+  for(ObserverConstIter it=list_.begin();it!=list_.end();++it)
+    (*it)->ObserverUpdate();
+}
+void Observable::Notify(const Extent& e) const {
+  for(ObserverConstIter it=list_.begin();it!=list_.end();++it)
+    (*it)->ObserverUpdate(e);
+}
+void Observable::Notify(const Point& p) const {
+  for(ObserverConstIter it=list_.begin();it!=list_.end();++it)
+    (*it)->ObserverUpdate(p);
+}
 
-#endif
+int Observable::GetListSize() const {
+  return list_.size();
+}
+
+long Observable::MemSize() const {
+  return sizeof(list_) + list_.size()*sizeof(DataObserver*);
+}
+
+
+}} // namespace
diff --git a/modules/img/base/src/observable.hh b/modules/img/base/src/observable.hh
index 90da00db135cb2c742b221545b2677525885ddc4..7b8ca63b81b135c88e5d4f9d42a4f6f35a06de55 100644
--- a/modules/img/base/src/observable.hh
+++ b/modules/img/base/src/observable.hh
@@ -19,7 +19,7 @@
 //------------------------------------------------------------------------------
 
 /*
-  abstract observable concept
+  observable concept
 
   Author: Ansgar Philippsen
 */
@@ -32,72 +32,43 @@
 
 namespace ost { namespace img {
 
+// fw decl
+class DataObserver;
+
 //! templated observable class
 /*
   manages a list of observers, which must
   offer the methods ObserverRelease, ObserverInvalidate
   and ObserverUpdate
 */
-template <class T>
 class DLLEXPORT Observable {
-  typedef std::list<T *> ObserverList;
-  typedef typename ObserverList::iterator ObserverIter;
-  typedef typename ObserverList::const_iterator ObserverConstIter;
+  typedef std::list<DataObserver *> ObserverList;
+  typedef  ObserverList::iterator ObserverIter;
+  typedef  ObserverList::const_iterator ObserverConstIter;
 public:
-  Observable() {
-    list_.clear();
-  }
-
+  Observable() ;
   /*
     copy logic: the observers are not copied
   */
-  Observable(const Observable& o) {
-    list_.clear();
-  }
+  Observable(const Observable& o) ;
 
-  ~Observable() {
-    for(ObserverIter it=list_.begin();it!=list_.end();++it) {
-      (*it)->ObserverInvalidate();
-      (*it)->ObserverRelease();
-    }
-  }
+  ~Observable() ;
 
   /*
     assignement logic: the observers are not copied
   */
-  Observable& operator=(const Observable& o) {
-    list_.clear();
-    return *this;
-  }
-
-  void Attach(T* d) {
-    list_.push_back(d);
-  }
-
-  void Detach(T* o) {
-    list_.remove(o);
-  }
-
-  void Notify() const {
-    for(ObserverConstIter it=list_.begin();it!=list_.end();++it)
-      (*it)->ObserverUpdate();
-  }
-  void Notify(const Extent& e) const {
-    for(ObserverConstIter it=list_.begin();it!=list_.end();++it)
-      (*it)->ObserverUpdate(e);
-  }
-  void Notify(const Point& p) const {
-    for(ObserverConstIter it=list_.begin();it!=list_.end();++it)
-      (*it)->ObserverUpdate(p);
-  }
-
-  int GetListSize() const {
-    return list_.size();
-  }
-
-  long MemSize() const {
-    return sizeof(list_) + list_.size()*sizeof(T*);
-  }
+  Observable& operator=(const Observable& o) ;
+
+  void Attach(DataObserver* d) ;
+
+  void Detach(DataObserver* o) ;
+
+  void Notify() const ;
+  void Notify(const Extent& e) const ;
+  void Notify(const Point& p) const ;
+  int GetListSize() const ;
+
+  long MemSize() const ;
 
   private:
     ObserverList list_;
diff --git a/modules/img/base/src/paste_impl.cc b/modules/img/base/src/paste_impl.cc
index 848cc7c5e8dfe2d8d469e2e7539d91c42ef3f1c7..77ea06c961347eef137d70f54d32c7c89b4f5943 100644
--- a/modules/img/base/src/paste_impl.cc
+++ b/modules/img/base/src/paste_impl.cc
@@ -25,7 +25,6 @@
 #include "paste_impl.hh"
 
 #include "image_state/binop.hh"
-#include "function.hh"
 #include "image.hh"
 
 namespace ost { namespace img { namespace detail {
@@ -45,18 +44,6 @@ void PasteFnc::VisitState(const image_state::ImageStateImpl<V,D>& isi)
   f_paste_ip(target_.ImageStatePtr().get(),&isi);
 }
 
-void PasteFnc::VisitFunction(const Function& f)
-{
-  if(target_.GetType()==REAL) {
-    for(ExtentIterator it(f.GetExtent());!it.AtEnd();++it) {
-      target_.SetReal(it,f.GetReal(it));
-    }
-  } else {
-    for(ExtentIterator it(f.GetExtent());!it.AtEnd();++it) {
-      target_.SetComplex(it,f.GetComplex(it));
-    }
-  }
-}
 
 }
 
diff --git a/modules/img/base/src/paste_impl.hh b/modules/img/base/src/paste_impl.hh
index 70e483cd59ab567117618b43108074492c47f5b7..700a786cd5c2592a09967e44563dfcf276f375bb 100644
--- a/modules/img/base/src/paste_impl.hh
+++ b/modules/img/base/src/paste_impl.hh
@@ -34,8 +34,6 @@ public:
   template<typename V, class D>
   void VisitState(const image_state::ImageStateImpl<V,D>& isi);
   
-  void VisitFunction(const Function& f);
-
   static String GetAlgorithmName() {return "Paste";}
 
 private:
diff --git a/modules/img/base/src/progress.hh b/modules/img/base/src/progress.hh
index fa5e2f9e25dde34d386c4e57507f75c52ad9a747..4af9cfc6b3f2db6ecaf96aa7b67ea2e9bd317ea4 100644
--- a/modules/img/base/src/progress.hh
+++ b/modules/img/base/src/progress.hh
@@ -43,7 +43,7 @@ public:
   void AdvanceProgress(const void* process,unsigned long step=1);
   Real GetProgress();
   void AddCallback(void(*fpt)(void)){function_pointer_=fpt;}
-  bool IsActive(){return processes_.size()>0;}
+  bool IsActive(){return ! processes_.empty();}
 private:
   Progress();
   Real progress_;
diff --git a/modules/img/base/src/raster_image/raster_image.cc b/modules/img/base/src/raster_image/raster_image.cc
index 20856e19f6b6fce55da9823aa5c71d61aceabf4f..143e1110b2c0e739a5c1b522886e54a409aeacfa 100644
--- a/modules/img/base/src/raster_image/raster_image.cc
+++ b/modules/img/base/src/raster_image/raster_image.cc
@@ -305,7 +305,6 @@ public:
 
   }
 
-  void VisitFunction(const Function& f) {}
 
   static String GetAlgorithmName() {return "RasterImageFiller";}
 
diff --git a/modules/img/base/tests/CMakeLists.txt b/modules/img/base/tests/CMakeLists.txt
index 503345f160b89b0c98997d43278f0c4e1e33b633..439133bf38f0909414bb91a8422eb536e27548e8 100644
--- a/modules/img/base/tests/CMakeLists.txt
+++ b/modules/img/base/tests/CMakeLists.txt
@@ -1,9 +1,7 @@
 set(OST_IMG_BASE_UNIT_TESTS
 test_data.cc
 test_extent.cc
-test_function.cc
 test_image.cc
-test_image_factory.cc
 test_image_state.cc
 test_image_state_visitor.cc
 test_index.cc
diff --git a/modules/img/base/tests/test_domains.cc b/modules/img/base/tests/test_domains.cc
index 4fdc4ad2548dd366e32b6598204b927413f5fc93..00357322ca3141f212d7e94f261c32235098527f 100644
--- a/modules/img/base/tests/test_domains.cc
+++ b/modules/img/base/tests/test_domains.cc
@@ -43,31 +43,31 @@ void test_spatial()
 
   SpatialDomain sd(Extent(Size(5,6)));
   Extent le(Point(0,0),Point(4,5));
-  Extent pe(Point(0,0),Point(4,7));
+  Extent pe(Point(0,0),Point(4,5));
 
   BOOST_CHECK(sd.GetDomain()==SPATIAL);
   mesg.str("");
   mesg << " expected " << le << " but got " << sd.GetExtent();
-  BOOST_CHECK(sd.GetExtent()==le);
+  BOOST_CHECK_MESSAGE(sd.GetExtent()==le,mesg.str());
   mesg.str("");
   mesg << " expected " << le << " but got " << sd.GetLogicalExtent();
-  BOOST_CHECK(sd.GetLogicalExtent()==le);
+  BOOST_CHECK_MESSAGE(sd.GetLogicalExtent()==le,mesg.str());
   mesg.str("");
   mesg << " expected " << pe << " but got " << sd.GetPhysicalExtent();
-  BOOST_CHECK(sd.GetPhysicalExtent()==pe);
+  BOOST_CHECK_MESSAGE(sd.GetPhysicalExtent()==pe,mesg.str());
 
   sd=SpatialDomain(Extent(Size(3,4,5)));
   le=Extent(Point(0,0,0),Point(2,3,4));
-  pe=Extent(Point(0,0,0),Point(2,3,5));
+  pe=Extent(Point(0,0,0),Point(2,3,4));
   mesg.str("");
   mesg << " expected " << le << " but got " << sd.GetExtent();
-  BOOST_CHECK(sd.GetExtent()==le);
+  BOOST_CHECK_MESSAGE(sd.GetExtent()==le,mesg.str());
   mesg.str("");
   mesg << " expected " << le << " but got " << sd.GetLogicalExtent();
-  BOOST_CHECK(sd.GetLogicalExtent()==le);
+  BOOST_CHECK_MESSAGE(sd.GetLogicalExtent()==le,mesg.str());
   mesg.str("");
   mesg << " expected " << pe << " but got " << sd.GetPhysicalExtent();
-  BOOST_CHECK(sd.GetPhysicalExtent()==pe);
+  BOOST_CHECK_MESSAGE(sd.GetPhysicalExtent()==pe,mesg.str());
 }
 
 void test_half_freq()
@@ -89,11 +89,6 @@ void test_half_freq()
   mesg << " expected " << pe << " but got " << hd.GetPhysicalExtent();
   BOOST_CHECK_MESSAGE(hd.GetPhysicalExtent()==pe,mesg.str());
 
-  SpatialDomain sd(Extent(Size(5,6)));
-  mesg.str("");
-  mesg << " expected volume match " << hd.GetPhysicalExtent() << " " << sd.GetPhysicalExtent();
-  BOOST_CHECK_MESSAGE(hd.GetPhysicalExtent().GetVolume()*2==sd.GetPhysicalExtent().GetVolume(),mesg.str());
-
   // 3d
   hd=HalfFrequencyDomain(Extent(Size(3,4,5)));
   le=Extent(Point(-1,-1,-2),Point(1,2,2));
@@ -110,10 +105,6 @@ void test_half_freq()
   mesg << " expected " << pe << " but got " << hd.GetPhysicalExtent();
   BOOST_CHECK_MESSAGE(hd.GetPhysicalExtent()==pe,mesg.str());
 
-  sd=SpatialDomain(Extent(Size(3,4,5)));
-  mesg.str("");
-  mesg << " expected volume match " << hd.GetPhysicalExtent() << " " << sd.GetPhysicalExtent();
-  BOOST_CHECK_MESSAGE(hd.GetPhysicalExtent().GetVolume()*2==sd.GetPhysicalExtent().GetVolume(),mesg.str());
 }
 
 
diff --git a/modules/img/base/tests/test_function.cc b/modules/img/base/tests/test_function.cc
deleted file mode 100644
index d3cffa9b62f744cd555120e2d336bbf3af5fdaa8..0000000000000000000000000000000000000000
--- a/modules/img/base/tests/test_function.cc
+++ /dev/null
@@ -1,85 +0,0 @@
-//------------------------------------------------------------------------------
-// This file is part of the OpenStructure project <www.openstructure.org>
-//
-// Copyright (C) 2008-2011 by the OpenStructure authors
-// Copyright (C) 2003-2010 by the IPLT authors
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License as published by the Free
-// Software Foundation; either version 3.0 of the License, or (at your option)
-// any later version.
-// This library is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with this library; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//------------------------------------------------------------------------------
-
-/*
-  Author: Ansgar Philippsen
-*/
-
-#include "test_function.hh"
-
-#include <ost/img/function.hh>
-#include <ost/img/null_function.hh>
-using namespace ost::img;
-
-namespace test_function {
-
-void test_NullFunc()
-{
-  NullFunction nf;
-
-  BOOST_CHECK(nf.GetDomain()==SPATIAL);
-  BOOST_CHECK(nf.GetReal(Point(-1,-4,-7))==0.0);
-}
-
-void test_RealFunc()
-{
-  class MyRealFunc: public RealFunction {
-  public:
-    MyRealFunc():
-      RealFunction(SPATIAL)
-    {}
-
-    Real Func(const Vec3& v) const {return 1.5;}
-  };
-
-  MyRealFunc f;
-
-  BOOST_CHECK(f.GetReal(Point())==1.5);
-}
-
-void test_ComplexFunc()
-{
-  class MyComplexFunc: public ComplexFunction {
-  public:
-    MyComplexFunc():
-      ComplexFunction(SPATIAL)
-    {}
-
-    Complex Func(const Vec3& v) const {return Complex(-1.5,8.0);}
-  };
-
-  MyComplexFunc f;
-
-  BOOST_CHECK(f.GetComplex(Point())==Complex(-1.5,8.0));
-}
-
-} // namespace 
-
-test_suite* CreateFunctionTest()
-{
-  using namespace test_function;
-  test_suite* ts=BOOST_TEST_SUITE("Function Test");
-
-  ts->add(BOOST_TEST_CASE(&test_NullFunc));
-  ts->add(BOOST_TEST_CASE(&test_RealFunc));
-  ts->add(BOOST_TEST_CASE(&test_ComplexFunc));
-
-  return ts;
-}
diff --git a/modules/img/base/tests/test_function.hh b/modules/img/base/tests/test_function.hh
deleted file mode 100644
index f2e7353bf1f8d84ca2d2700d40672ace904436fd..0000000000000000000000000000000000000000
--- a/modules/img/base/tests/test_function.hh
+++ /dev/null
@@ -1,34 +0,0 @@
-//------------------------------------------------------------------------------
-// This file is part of the OpenStructure project <www.openstructure.org>
-//
-// Copyright (C) 2008-2011 by the OpenStructure authors
-// Copyright (C) 2003-2010 by the IPLT authors
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License as published by the Free
-// Software Foundation; either version 3.0 of the License, or (at your option)
-// any later version.
-// This library is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with this library; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//------------------------------------------------------------------------------
-
-/*
-  Author: Ansgar Philippsen
-*/
-
-#ifndef IMG_TEST_FUNCTION_H
-#define IMG_TEST_FUNCTION_H
-
-#define BOOST_TEST_DYN_LINK
-#include <boost/test/unit_test.hpp>
-using boost::unit_test_framework::test_suite;
-
-test_suite* CreateFunctionTest();
-
-#endif
diff --git a/modules/img/base/tests/test_image.cc b/modules/img/base/tests/test_image.cc
index 160b7e044da1711751b03c677e498a6519460b4d..89a7663bc42df5f12f8a3e2f76c0d4845866807d 100644
--- a/modules/img/base/tests/test_image.cc
+++ b/modules/img/base/tests/test_image.cc
@@ -147,7 +147,7 @@ void test_Reset()
 
 class MyObserver: public DataObserver {
 public:
-  MyObserver(const Data& d):
+  MyObserver(const ImageHandle& d):
     DataObserver(d),
     update_count(0),
     release_count(0)
diff --git a/modules/img/base/tests/test_image_factory.cc b/modules/img/base/tests/test_image_factory.cc
deleted file mode 100644
index 04554c580960088ae19cfcea7a6962375bdd24c9..0000000000000000000000000000000000000000
--- a/modules/img/base/tests/test_image_factory.cc
+++ /dev/null
@@ -1,77 +0,0 @@
-//------------------------------------------------------------------------------
-// This file is part of the OpenStructure project <www.openstructure.org>
-//
-// Copyright (C) 2008-2011 by the OpenStructure authors
-// Copyright (C) 2003-2010 by the IPLT authors
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License as published by the Free
-// Software Foundation; either version 3.0 of the License, or (at your option)
-// any later version.
-// This library is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with this library; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//------------------------------------------------------------------------------
-
-/*
-  Author: Ansgar Philippsen
-*/
-
-#include "test_image_factory.hh"
-
-#include <ost/img/image_factory.hh>
-#include <ost/img/function.hh>
-#include <ost/img/image.hh>
-
-using namespace ost::img;
-
-namespace test_image_factory {
-
-void test_Generate()
-{
-  class MyComplexFunc: public ComplexFunction {
-  public:
-    MyComplexFunc():
-      ComplexFunction(FREQUENCY)
-    {}
-
-    virtual Complex Func(const Vec3& v) const {
-      return Complex(v[0],v[1]);
-    }
-  };
-
-
-  MyComplexFunc cf;
-  Extent ext(Point(-10,-10),Point(10,10));
-  cf.SetExtent(ext);
-
-  ImageHandle g1 = GenerateImage(cf);
-
-  BOOST_CHECK(g1.GetType()==COMPLEX);
-  BOOST_CHECK(g1.GetDomain()==FREQUENCY);
-  BOOST_CHECK(g1.GetExtent()==ext);
-  
-  for(ExtentIterator it(ext); !it.AtEnd(); ++it) {
-    Point p(it);
-    BOOST_REQUIRE(g1.GetComplex(p) == cf.GetComplex(p));
-    BOOST_REQUIRE(g1.GetComplex(p) == Complex(Real(p[0]),Real(p[1])));
-  }
-
-}
-
-} // namespace 
-
-test_suite* CreateImageFactoryTest()
-{
-  using namespace test_image_factory;
-  test_suite* ts=BOOST_TEST_SUITE("ImageFactory Test");
-
-  ts->add(BOOST_TEST_CASE(&test_Generate));
-
-  return ts;
-}
diff --git a/modules/img/base/tests/test_image_factory.hh b/modules/img/base/tests/test_image_factory.hh
deleted file mode 100644
index 90109184aa7665648810217972723a52bde06f2b..0000000000000000000000000000000000000000
--- a/modules/img/base/tests/test_image_factory.hh
+++ /dev/null
@@ -1,34 +0,0 @@
-//------------------------------------------------------------------------------
-// This file is part of the OpenStructure project <www.openstructure.org>
-//
-// Copyright (C) 2008-2011 by the OpenStructure authors
-// Copyright (C) 2003-2010 by the IPLT authors
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License as published by the Free
-// Software Foundation; either version 3.0 of the License, or (at your option)
-// any later version.
-// This library is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with this library; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//------------------------------------------------------------------------------
-
-/*
-  Author: Ansgar Philippsen
-*/
-
-#ifndef IMG_TEST_IMAGE_FACTORY_H
-#define IMG_TEST_IMAGE_FACTORY_H
-
-#define BOOST_TEST_DYN_LINK
-#include <boost/test/unit_test.hpp>
-using boost::unit_test_framework::test_suite;
-
-test_suite* CreateImageFactoryTest();
-
-#endif
diff --git a/modules/img/base/tests/test_value_holder.cc b/modules/img/base/tests/test_value_holder.cc
index d859912dd471c774ab21ef842e8a013b350eee5d..f5b09f938f0bd48ba09e0701631d10ab67f4e8c4 100644
--- a/modules/img/base/tests/test_value_holder.cc
+++ b/modules/img/base/tests/test_value_holder.cc
@@ -35,15 +35,6 @@ using namespace ost::img::image_state;
 
 namespace value_holder_test {
 
-template <typename V>
-void Construction()
-{
-  ValueHolder<V> v(8,6,10);
-  BOOST_CHECK (v.GetWidth()==8);
-  BOOST_CHECK (v.GetHeight()==6);
-  BOOST_CHECK (v.GetDepth()==10);
-  BOOST_CHECK (v.GetVolume()==8*6*10);
-}
 
 template <typename V>
 void ReadWrite()
@@ -51,7 +42,7 @@ void ReadWrite()
   int wi=4;
   int he=3;
   int de=5;
-  ValueHolder<V> vh(wi,he,de);
+  ValueHolder<V> vh(Size(wi,he,de));
 
   for(int u=0;u<wi;++u) {
     for(int v=0;v<he;++v) {
@@ -60,7 +51,7 @@ void ReadWrite()
 	int indx = w+de*(v+he*u);
 	vh.Value(Index(u,v,w))=val;
 	BOOST_REQUIRE(vh.Value(Index(u,v,w)) == val);
-	BOOST_REQUIRE(vh.Value(indx) == val);
+	BOOST_REQUIRE(vh.GetData()[indx] == val);
       }
     }
   }
@@ -73,7 +64,7 @@ void CopyCtor()
   int he=3;
   int de=5;
 
-  ValueHolder<V> vh1(wi,he,de);
+  ValueHolder<V> vh1(Size(wi,he,de));
 
   for(int u=0;u<wi;++u) {
     for(int v=0;v<he;++v) {
@@ -104,8 +95,6 @@ test_suite* CreateValueHolderTest()
 
   test_suite* ts=BOOST_TEST_SUITE("ValueHolder Test");
 
-  ts->add( BOOST_TEST_CASE(Construction<Real>) );
-  ts->add( BOOST_TEST_CASE(Construction<Complex>) );
   ts->add( BOOST_TEST_CASE(ReadWrite<Real>) );
   ts->add( BOOST_TEST_CASE(ReadWrite<Complex>) );
   ts->add( BOOST_TEST_CASE(CopyCtor<Real>) );
diff --git a/modules/img/base/tests/tests.cc b/modules/img/base/tests/tests.cc
index 2027c80088bd2164d511fec7dc02b0ce8f9f98a3..161687ebee631fcabb08218358556c594363862c 100644
--- a/modules/img/base/tests/tests.cc
+++ b/modules/img/base/tests/tests.cc
@@ -29,9 +29,7 @@
 
 #include "test_data.hh"
 #include "test_extent.hh"
-#include "test_function.hh"
 #include "test_image.hh"
-#include "test_image_factory.hh"
 #include "test_image_state.hh"
 #include "test_image_state_visitor.hh"
 #include "test_index.hh"
@@ -60,9 +58,7 @@ bool init_ost_img_base_unit_tests() {
   try {
     framework::master_test_suite().add(CreateDataTest());
     framework::master_test_suite().add(CreateExtentTest());
-    framework::master_test_suite().add(CreateFunctionTest());
     framework::master_test_suite().add(CreateImageTest());
-    framework::master_test_suite().add(CreateImageFactoryTest());
     framework::master_test_suite().add(CreateImageStateTest());
     framework::master_test_suite().add(CreateImageStateVisitorTest());
     framework::master_test_suite().add(CreateIndexTest());
diff --git a/modules/index.rst b/modules/index.rst
index cb92f375dcdc0b20527f1bc26fec308465c4cc62..5f043a23855946ee43aa3077d84288ef59d5bd44 100644
--- a/modules/index.rst
+++ b/modules/index.rst
@@ -28,6 +28,7 @@ OpenStructure documentation
   external
   contributing
   table
+  mol/alg/lddt
 
 For Starters
 --------------------------------------------------------------------------------
@@ -99,6 +100,8 @@ Varia
 
 **Users** :doc:`Reporting a problem <users>`
 
+**lDDT** :doc:`lDDT command line executable<mol/alg/lddt>`
+
 Extending OpenStructure
 --------------------------------------------------------------------------------
 
diff --git a/modules/io/doc/mmcif.rst b/modules/io/doc/mmcif.rst
index 0db17e2cf70cd825732b2f0103a7f430859e9554..9303b459d2c904b39038f75c529336c1640d759e 100644
--- a/modules/io/doc/mmcif.rst
+++ b/modules/io/doc/mmcif.rst
@@ -41,6 +41,7 @@ The following categories of a mmCIF file are considered by the reader:
 * ``struct_ref`` stored in :class:`MMCifInfoStructRef`
 * ``struct_ref_seq`` stored in :class:`MMCifInfoStructRefSeq`
 * ``struct_ref_seq_dif`` stored in :class:`MMCifInfoStructRefDif`
+* ``database_pdb_rev`` stored in :class:`MMCifInfoRevisions`
 
 Info Classes
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -99,6 +100,14 @@ of the annotation available.
   .. attribute:: struct_refs
 
     Lists all links to external databases in the mmCIF file.
+
+  .. attribute:: revisions
+
+    Stores a simple history of a PDB entry.
+
+    Also available as :meth:`GetRevisions`. May be extended by
+    :meth:`AddRevision`.
+
   .. method:: AddCitation(citation)
 
     Add a citation to the citation list of an info object.
@@ -196,6 +205,28 @@ of the annotation available.
     :type pdb_chain_id: :class:`str`
     :returns: atom_site.label_asym_id as :class:`str`
 
+  .. method:: AddRevision(num, date, status)
+
+    Add a new iteration to the history.
+
+    :param num: database_pdb_rev.num
+    :type num: :class:`int`
+    :param date: database_pdb_rev.date
+    :type date: :class:`str`
+    :param status: database_pdb_rev.status
+    :type status: :class:`str`
+
+  .. method:: GetRevisions()
+
+    See :attr:`revisions`
+
+  .. method:: SetRevisionsDateOriginal(date)
+
+    Set the date, when this entry first entered the PDB.
+
+    :param date: database_pdb_rev.date_original
+    :type date: :class:`str`
+
 .. class:: MMCifInfoCitation
 
   This stores citation information from an input file.
@@ -510,7 +541,7 @@ of the annotation available.
 
     See :attr:`operations`
 
-.. function:: PDBize(asu, seqres=None, min_polymer_size=10)
+.. function:: PDBize(asu, seqres=None, min_polymer_size=10, transformation=False)
 
     Returns the biological assembly (bio unit) for an entity. The new entity
     created is well suited to be saved as a PDB file. Therefore the function
@@ -525,6 +556,9 @@ of the annotation available.
       - ligands which resemble a polymer but have less than min_polymer_size
         residues are assigned the same numeric residue number. The residues are
         distinguished by insertion code.
+      - sometimes bio units exceed the coordinate system storable in a PDB file.
+        In that case, the box around the entity will be aligned to the lower
+        left corner of the coordinate system.
 
     Since this function is at the moment mainly used to create biounits from
     mmCIF files to be saved as PDBs, the function assumes that the
@@ -541,6 +575,9 @@ of the annotation available.
       get its own chain. Everything below that number will be sorted into the 
       ligand chain.
     :type min_polymer_size: int
+    :param transformation:  If set, return the transformation matrix used to
+      move the bounding box of the bio unit to the lower left corner.
+    :type transformation: :class:`bool`
 
 .. class:: MMCifInfoStructDetails
 
@@ -827,7 +864,88 @@ of the annotation available.
 
     :type: :class:`str`
 
-..  LocalWords:  cas isbn pubmed asu seqres conop casp COMPND OBSLTE
+.. class:: MMCifInfoRevisions
+
+  Revision history of a PDB entry. If you find a '?' somewhere, this means
+  'not set'.
+
+   .. attribute:: date_original
+
+   The date when this entry was seen in PDB for the very first time. This is
+   not necessarily the release date.
+
+   :type: :class:`str`
+
+   .. attribute:: first_release
+
+   Index + 1 of the revision releasing this entry. If the value is 0, was not
+   set, yet.
+
+   :type: :class:`int`
+
+   .. method:: SetDateOriginal(date)
+
+   Set the date, when this entry first entered the PDB.
+
+   :param date: database_pdb_rev.date_original
+   :type date: :class:`str`
+
+   .. method:: GetDateOriginal()
+
+   Retrieve  database_pdb_rev.date_original.
+
+   :returns: database_pdb_rev.date_original as :class:`str` in format
+   'yyyy-mm-dd'
+
+   .. method:: AddRevision(int num, String date, String status)
+
+   Add a new iteration to the history.
+
+   :param num: database_pdb_rev.num
+   :type num: :class:`int`
+   :param date: database_pdb_rev.date
+   :type date: :class:`str`
+   :param status: database_pdb_rev.status
+   :type status: :class:`str`
+
+   .. method:: GetSize()
+
+   :returns: Number of revisions as :class:`int`
+
+   .. method:: GetDate(i)
+
+   :param i: Index of revision
+   :type i: :class:`int`
+   :returns: database_pdb_rev.date as :class:`str`
+
+   .. method:: GetNum(i)
+
+   :param i: Index of revision
+   :type i: :class:`int`
+   :returns: database_pdb_rev.num as :class:`int`
+
+   .. method:: GetStatus(i)
+
+   :param i: Index of revision
+   :type i: :class:`int`
+   :returns: database_pdb_rev.status as :class:`str`
+
+   .. method:: GetLastDate()
+
+   The date of the latest revision.
+
+   :returns: date as :class:`str`
+
+   .. method:: GetFirstRelease()
+
+   Points to the revision releasing the entry.
+
+   :returns: Index as :class:`int`
+
+..  LocalWords:  cas isbn pubmed asu seqres conop ConnectAll casp COMPND OBSLTE
 ..  LocalWords:  SPRSDE pdb func autofunction exptl attr pdbx oper conf spr dif
 ..  LocalWords:  biounits biounit uniprot UNP seqs AddMMCifPDBChainTr cif asym
 ..  LocalWords:  auth GetMMCifPDBChainTr AddPDBCMMCifhainTr GetPDBMMCifChainTr
+..  LocalWords:  GetRevisions AddRevision SetRevisionsDateOriginal GetSize
+..  LocalWords:  GetNum num GetStatus GetLastDate GetFirstRelease storable
+..  LocalWords:  cas isbn pubmed asu seqres conop casp COMPND OBSLTE
diff --git a/modules/io/doc/profile.rst b/modules/io/doc/profile.rst
index a0a43565e6631ca9c2adc28449930a9ffbe3656c..82edfa484c1c25223b0c0595dad77da93c7ddab2 100644
--- a/modules/io/doc/profile.rst
+++ b/modules/io/doc/profile.rst
@@ -45,7 +45,7 @@ STRICT
 
     IOProfile(dialect='PDB', strict_hydrogens=False, quack_mode=False,
               fault_tolerant=False, join_spread_atom_records=False,
-              no_hetatms=False, bond_feasibility_check=True)
+              no_hetatms=False, bond_feasibility_check=False)
 
 SLOPPY:
 
diff --git a/modules/io/pymod/__init__.py b/modules/io/pymod/__init__.py
index c0ea293daa1fde9184b54443e213464b695b8ec6..2d402eeacec535b661b94cf82a0809c5e09cde13 100644
--- a/modules/io/pymod/__init__.py
+++ b/modules/io/pymod/__init__.py
@@ -49,11 +49,11 @@ if not profiles:
   else:
     processor = conop.HeuristicProcessor()
   profiles['STRICT']=IOProfile(dialect='PDB', fault_tolerant=False,
-                               quack_mode=False, processor=processor)
+                               quack_mode=False, processor=processor.Copy())
   profiles['SLOPPY']=IOProfile(dialect='PDB', fault_tolerant=True,
-                               quack_mode=True, processor=processor)
+                               quack_mode=True, processor=processor.Copy())
   profiles['CHARMM']=IOProfile(dialect='CHARMM', fault_tolerant=True,
-                               quack_mode=False, processor=processor)
+                               quack_mode=False, processor=processor.Copy())
   profiles['DEFAULT']='STRICT'
 
 def _override(val1, val2):
@@ -356,8 +356,10 @@ def LoadMMCIF(filename, restrict_chains="", fault_tolerant=None, calpha_only=Non
 # arguement is the usual 'self'.
 # documentation for this function was moved to mmcif.rst,
 # MMCifInfoBioUnit.PDBize, since this function is not included in SPHINX.
-def _PDBize(biounit, asu, seqres=None, min_polymer_size=10):
+def _PDBize(biounit, asu, seqres=None, min_polymer_size=10,
+            transformation=False):
   def _CopyAtoms(src_res, dst_res, edi, trans=geom.Mat4()):
+    atom_pos_wrong = False
     for atom in src_res.atoms:
       tmp_pos = geom.Vec4(atom.pos)
       new_atom=edi.InsertAtom(dst_res, atom.name, geom.Vec3(trans*tmp_pos), 
@@ -365,6 +367,12 @@ def _PDBize(biounit, asu, seqres=None, min_polymer_size=10):
                               occupancy=atom.occupancy, 
                               b_factor=atom.b_factor,
                               is_hetatm=atom.is_hetatom)
+      for p in range(0,3):
+        if new_atom.pos[p] <= -1000:
+          atom_pos_wrong = True
+        elif new_atom.pos[p] >= 10000:
+          atom_pos_wrong = True
+    return atom_pos_wrong
 
   chain_names='ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz'
   # create list of operations
@@ -404,6 +412,7 @@ def _PDBize(biounit, asu, seqres=None, min_polymer_size=10):
   cur_chain_name = 0
   water_chain = mol.ChainHandle()
   ligand_chain = mol.ChainHandle()
+  a_pos_wrong = False
   for tr in trans_matrices:
     # do a PDBize, add each new entity to the end product
     for chain in assu.chains:
@@ -425,7 +434,9 @@ def _PDBize(biounit, asu, seqres=None, min_polymer_size=10):
                                   chain.GetStringProp("pdb_auth_chain_name"))
         for res in chain.residues:
           new_res = edi.AppendResidue(new_chain, res.name, res.number)
-          _CopyAtoms(res, new_res, edi, tr)
+          a_b = _CopyAtoms(res, new_res, edi, tr)
+          if not a_pos_wrong:
+            a_pos_wrong = a_b
       elif chain.type == mol.CHAINTYPE_WATER:
         if not water_chain.IsValid():
           # water gets '-' as name
@@ -436,7 +447,9 @@ def _PDBize(biounit, asu, seqres=None, min_polymer_size=10):
           new_res = edi.AppendResidue(water_chain, res.name)
           new_res.SetStringProp('type', mol.StringFromChainType(chain.type))
           new_res.SetStringProp('description', chain.description)
-          _CopyAtoms(res, new_res, edi, tr)
+          a_b = _CopyAtoms(res, new_res, edi, tr)
+          if not a_pos_wrong:
+            a_pos_wrong = a_b
       else:
         if not ligand_chain.IsValid():
           # all ligands, put in one chain, are named '_'
@@ -459,8 +472,21 @@ def _PDBize(biounit, asu, seqres=None, min_polymer_size=10):
                                   chain.GetStringProp("pdb_auth_chain_name"))
           ins_code = chr(ord(ins_code)+1)
           _CopyAtoms(res, new_res, edi, tr)
-  # FIXME: get rid of connect all call...
-  # conop.ConnectAll(pdb_bu)
+          a_b = _CopyAtoms(res, new_res, edi, tr)
+          if not a_pos_wrong:
+            a_pos_wrong = a_b
+  move_to_origin = None
+  if a_pos_wrong:
+    start = pdb_bu.bounds.min
+    move_to_origin = geom.Mat4(1,0,0,(-999 - start[0]),
+                               0,1,0,(-999 - start[1]),
+                               0,0,1,(-999 - start[2]),
+                               0,0,0,1)
+    edi = pdb_bu.EditXCS(mol.UNBUFFERED_EDIT)
+    edi.ApplyTransform(move_to_origin)
+  conop.ConnectAll(pdb_bu)
+  if transformation:
+    return pdb_bu, move_to_origin
   return pdb_bu
 
 MMCifInfoBioUnit.PDBize = _PDBize
diff --git a/modules/io/pymod/export_mmcif_io.cc b/modules/io/pymod/export_mmcif_io.cc
index f2527066afca1d2d715c97dcc1413276eafa7a6b..78cd7e124f08460009e4f5b98432080e8422ae95 100644
--- a/modules/io/pymod/export_mmcif_io.cc
+++ b/modules/io/pymod/export_mmcif_io.cc
@@ -261,6 +261,21 @@ void export_mmcif_io()
                   &MMCifInfoObsolete::SetReplacedPDBID)
   ;
 
+  class_<MMCifInfoRevisions>("MMCifInfoRevisions", init<>())
+    .def("SetDateOriginal", &MMCifInfoRevisions::SetDateOriginal)
+    .def("GetDateOriginal", &MMCifInfoRevisions::GetDateOriginal)
+    .def("AddRevision", &MMCifInfoRevisions::AddRevision)
+    .def("GetSize", &MMCifInfoRevisions::GetSize)
+    .def("GetDate", &MMCifInfoRevisions::GetDate)
+    .def("GetNum", &MMCifInfoRevisions::GetNum)
+    .def("GetStatus", &MMCifInfoRevisions::GetStatus)
+    .def("GetLastDate", &MMCifInfoRevisions::GetLastDate)
+    .def("GetFirstRelease", &MMCifInfoRevisions::GetFirstRelease)
+    .add_property("date_original", &MMCifInfoRevisions::GetDateOriginal,
+                  &MMCifInfoRevisions::SetDateOriginal)
+    .add_property("first_release", &MMCifInfoRevisions::GetFirstRelease)
+  ;
+
   class_<MMCifInfo>("MMCifInfo", init<>())
     .def("AddCitation", &MMCifInfo::AddCitation)
     .def("GetCitations", make_function(&MMCifInfo::GetCitations,
@@ -284,6 +299,9 @@ void export_mmcif_io()
     .def("GetMMCifPDBChainTr", &MMCifInfo::GetMMCifPDBChainTr)
     .def("AddPDBMMCifChainTr", &MMCifInfo::AddPDBMMCifChainTr)
     .def("GetPDBMMCifChainTr", &MMCifInfo::GetPDBMMCifChainTr)
+    .def("SetRevisionsDateOriginal", &MMCifInfo::SetRevisionsDateOriginal)
+    .def("AddRevision", &MMCifInfo::AddRevision)
+    .def("GetRevisions", &MMCifInfo::GetRevisions)
     .add_property("citations", make_function(&MMCifInfo::GetCitations,
                                    return_value_policy<copy_const_reference>()))
     .add_property("biounits", make_function(&MMCifInfo::GetBioUnits,
@@ -299,5 +317,6 @@ void export_mmcif_io()
     			        return_value_policy<copy_const_reference>()))
     .add_property("obsolete", &MMCifInfo::GetObsoleteInfo,
                   &MMCifInfo::SetObsoleteInfo)
+    .add_property("revisions", &MMCifInfo::GetRevisions)
  ;
 }
diff --git a/modules/io/pymod/export_pdb_io.cc b/modules/io/pymod/export_pdb_io.cc
index a80aff690a098556f857a7536d4dfdd4e814c47d..c5062e20d92694a84a029346764bc55cbe4d41fe 100644
--- a/modules/io/pymod/export_pdb_io.cc
+++ b/modules/io/pymod/export_pdb_io.cc
@@ -36,15 +36,15 @@ void (PDBWriter::*write_b)(const mol::EntityView&)=&PDBWriter::Write;
 void export_pdb_io()
 {
   class_<IOProfile>("IOProfile",
-         init<String,bool,bool,bool,bool,bool,bool,
+         init<String,bool,bool,bool,bool,bool,
               conop::ProcessorPtr>((arg("dialect")="PDB",
                                     arg("quack_mode")=false,
                                     arg("fault_tolerant")=false,
                                     arg("join_spread_atom_records")=false,
                                     arg("no_hetatms")=false,
                                     arg("calpha_only")=false,
-                                    arg("bond_feasibility_check")=true,
                                     arg("processor")=conop::ProcessorPtr())))
+    .def(init<const IOProfile&>())
     .def_readwrite("dialect", &IOProfile::dialect)
     .def_readwrite("fault_tolerant", &IOProfile::fault_tolerant)
     .def_readwrite("quack_mode", &IOProfile::quack_mode)
diff --git a/modules/io/pymod/wrap_io.cc b/modules/io/pymod/wrap_io.cc
index 789efe111ba32661c5e0a3da15fb6901e55bbb9c..1e2b5186906a5f94cd11526f9837aa74c6af5fca 100644
--- a/modules/io/pymod/wrap_io.cc
+++ b/modules/io/pymod/wrap_io.cc
@@ -28,6 +28,7 @@ using namespace boost::python;
 #include <ost/io/seq/save.hh>
 #include <ost/io/mol/entity_io_pdb_handler.hh>
 #include <ost/io/mol/entity_io_crd_handler.hh>
+#include <ost/io/mol/entity_io_pqr_handler.hh>
 #include <ost/io/mol/entity_io_mae_handler.hh>
 #include <ost/io/mol/entity_io_sdf_handler.hh>
 #include <ost/io/mol/pdb_reader.hh>
@@ -113,6 +114,7 @@ BOOST_PYTHON_MODULE(_ost_io)
                                            arg("detect_swap")=true,arg("swap_bytes")=false))
 ;
   def("LoadMAE", &LoadMAE);
+  def("LoadPQR", &LoadPQR);
 
   export_pdb_io();
   export_mmcif_io();
diff --git a/modules/io/src/CMakeLists.txt b/modules/io/src/CMakeLists.txt
index c2a465686698258543707f91b5097e7d5f98ff11..58470a33136c2b794668dc2b39effab39cd2f805 100644
--- a/modules/io/src/CMakeLists.txt
+++ b/modules/io/src/CMakeLists.txt
@@ -22,7 +22,9 @@ io_manager.cc
 convert.cc
 io_utils.cc
 )
-
+if (WIN32)
+ set(OST_IO_SOURCES ${OST_IO_SOURCES} zlib.cpp gzip.cpp)
+endif(WIN32)
 
 foreach(fname ${OST_IO_MOL_SOURCES})
   set(OST_IO_SOURCES ${OST_IO_SOURCES} mol/${fname})
@@ -61,10 +63,7 @@ module(NAME io SOURCES "${OST_IO_SOURCES}"
                ${OST_IO_SEQ_HEADERS} IN_DIR seq            
                ${OST_IO_HEADERS} 
        DEPENDS_ON ${OST_IO_DEPENDENCIES})
-if (NOT WIN32)
-  # see note in modules/gui/src/CMakeLists.txt
-  target_link_libraries(ost_io ${BOOST_IOSTREAM_LIBRARIES})
-endif()
+target_link_libraries(ost_io ${BOOST_IOSTREAM_LIBRARIES})
 if (ENABLE_IMG)
   target_link_libraries(ost_io ${TIFF_LIBRARIES} ${PNG_LIBRARIES})
 endif()
\ No newline at end of file
diff --git a/modules/io/src/gzip.cpp b/modules/io/src/gzip.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..04cb71a54dde7568c4921fc76241202fab6e075c
--- /dev/null
+++ b/modules/io/src/gzip.cpp
@@ -0,0 +1,174 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2003-2007 Jonathan Turkanis
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
+
+// See http://www.boost.org/libs/iostreams for documentation.
+
+// To configure Boost to work with libbz2, see the 
+// installation instructions here:
+// http://boost.org/libs/iostreams/doc/index.html?path=7
+
+// Define BOOST_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp> 
+// knows that we are building the library (possibly exporting code), rather 
+// than using it (possibly importing code).
+#define BOOST_IOSTREAMS_SOURCE 
+
+#include <boost/iostreams/detail/config/dyn_link.hpp>
+#include <boost/iostreams/filter/gzip.hpp>
+#include <boost/throw_exception.hpp>
+
+namespace boost { namespace iostreams {
+
+//------------------Implementation of gzip_header-----------------------------//
+
+namespace detail {
+
+void gzip_header::process(char c)
+{
+    uint8_t value = static_cast<uint8_t>(c);
+    switch (state_) {
+    case s_id1:
+        if (value != gzip::magic::id1)
+            boost::throw_exception(gzip_error(gzip::bad_header));
+        state_ = s_id2;
+        break;
+    case s_id2:
+        if (value != gzip::magic::id2)
+            boost::throw_exception(gzip_error(gzip::bad_header));
+        state_ = s_cm;
+        break;
+    case s_cm:
+        if (value != gzip::method::deflate)
+            boost::throw_exception(gzip_error(gzip::bad_method));
+        state_ = s_flg;
+        break;
+    case s_flg:
+        flags_ = value;
+        state_ = s_mtime;
+        break;
+    case s_mtime:
+        mtime_ += value << (offset_ * 8);
+        if (offset_ == 3) {
+            state_ = s_xfl;
+            offset_ = 0;
+        } else {
+            ++offset_;
+        }
+        break;
+    case s_xfl:
+        state_ = s_os;
+        break;
+    case s_os:
+        os_ = value;
+        if (flags_ & gzip::flags::extra) {
+            state_ = s_extra;
+        } else if (flags_ & gzip::flags::name) {
+            state_ = s_name;
+        } else if (flags_ & gzip::flags::comment) {
+            state_ = s_comment;
+        } else if (flags_ & gzip::flags::header_crc) {
+            state_ = s_hcrc;
+        } else {
+            state_ = s_done;
+        }
+        break;
+    case s_xlen:
+        xlen_ += value << (offset_ * 8);
+        if (offset_ == 1) {
+            state_ = s_extra;
+            offset_ = 0;
+        } else {
+            ++offset_;
+        }
+        break;
+    case s_extra:
+        if (--xlen_ == 0) {
+            if (flags_ & gzip::flags::name) {
+                state_ = s_name;
+            } else if (flags_ & gzip::flags::comment) {
+                state_ = s_comment;
+            } else if (flags_ & gzip::flags::header_crc) {
+                state_ = s_hcrc;
+            } else {
+                state_ = s_done;
+            }
+        }
+        break;
+    case s_name:
+        if (c != 0) {
+            file_name_ += c;
+        } else if (flags_ & gzip::flags::comment) {
+            state_ = s_comment;
+        } else if (flags_ & gzip::flags::header_crc) {
+            state_ = s_hcrc;
+        } else {
+            state_ = s_done;
+        }
+        break;
+    case s_comment:
+        if (c != 0) {
+            comment_ += c;
+        } else if (flags_ & gzip::flags::header_crc) {
+            state_ = s_hcrc;
+        } else {
+            state_ = s_done;
+        }
+        break;
+    case s_hcrc:
+        if (offset_ == 1) {
+            state_ = s_done;
+            offset_ = 0;
+        } else {
+            ++offset_;
+        }
+        break;
+    default:
+        BOOST_ASSERT(0);
+    }
+}
+
+void gzip_header::reset()
+{
+    file_name_.clear();
+    comment_.clear();
+    os_ = flags_ = offset_ = xlen_ = 0;
+    mtime_ = 0;
+    state_ = s_id1;
+}
+
+//------------------Implementation of gzip_footer-----------------------------//
+
+void gzip_footer::process(char c)
+{
+    uint8_t value = static_cast<uint8_t>(c);
+    if (state_ == s_crc) {
+        crc_ += value << (offset_ * 8);
+        if (offset_ == 3) {
+            state_ = s_isize;
+            offset_ = 0;
+        } else {
+            ++offset_;
+        }
+    } else if (state_ == s_isize) {
+        isize_ += value << (offset_ * 8);
+        if (offset_ == 3) {
+            state_ = s_done;
+            offset_ = 0;
+        } else {
+            ++offset_;
+        }
+    } else {
+        BOOST_ASSERT(0);
+    }
+}
+
+void gzip_footer::reset()
+{
+    crc_ = isize_ = offset_ = 0;
+    state_ = s_crc;
+}
+
+} // End namespace boost::iostreams::detail.
+
+} } // End namespaces iostreams, boost.
diff --git a/modules/io/src/img/map_io_mrc_handler.cc b/modules/io/src/img/map_io_mrc_handler.cc
index b49e976eca8e9d1b45aa24b8cffa347934fb8dfe..c80ec39aba853070679aefdfd7b890cd5b876de0 100644
--- a/modules/io/src/img/map_io_mrc_handler.cc
+++ b/modules/io/src/img/map_io_mrc_handler.cc
@@ -76,9 +76,11 @@ u v w x . . .     d*c*b*a b c d   3
 #include <ost/img/image_state.hh>
 #include <ost/img/alg/stat.hh>
 #include <ost/img/alg/normalizer_factory.hh>
-#include <ost/io/io_exception.hh>
 #include <ost/img/util.hh>
 #include <ost/img/progress.hh>
+#include <ost/img/alg/fractional_shift.hh>
+#include <ost/img/alg/alg_shift.hh>
+#include <ost/io/io_exception.hh>
 #include <ost/io/img/image_format.hh>
 #include <ost/io/swap_util.hh>
 #include <ost/io/converting_streams.hh>
@@ -483,7 +485,9 @@ public:
       LOG_DEBUG("CCP4Import: reading little endian data");
       return OST_LITTLE_ENDIAN;
     } else{
-      throw(IOException("CCP4Import: Cray, Convex native and Fijitsu VP formats are not supported."));
+      LOG_VERBOSE("unknown machine stamp (" << (int)float_machst << "), using little endian");
+      return OST_LITTLE_ENDIAN;
+      //throw(IOException("CCP4Import: Cray, Convex native and Fijitsu VP formats are not supported."));
     }
   }
 
@@ -495,7 +499,7 @@ public:
 
     LOG_INFO("ccp4 header:");
     header_base::Print();
-    LOG_INFO(" arms: " << arms);
+    LOG_INFO("arms: " << arms);
   }
 
   int lskflag;
@@ -806,7 +810,7 @@ void import_helper(img::MapHandle& image, std::istream& in,const MRC& formatmrc)
                                           static_cast<Real>(header.y)/static_cast<Real>(header.ny),
                                           static_cast<Real>(header.z)/static_cast<Real>(header.nz)));
     }else{
-      LOG_INFO("Suspicious dell dimensions found. Cannot set sampling.");
+      LOG_INFO("Suspicious cell dimensions found. Cannot set sampling.");
     }
     LOG_INFO("resulting image extent: " << image.GetExtent());
     if(img::image_state::RealSpatialImageState *rs=dynamic_cast<img::image_state::RealSpatialImageState*>(image.ImageStatePtr().get())) {
@@ -985,12 +989,29 @@ void MapIOMrcHandler::Export(const img::MapHandle& sh, std::ostream& loc,const I
   } else {
     assert (formatstruct.GetFormatString()==UndefinedImageFormat::FORMAT_STRING);
   }
+  img::MapHandle sh2=sh;
+  if(geom::Length2(sh.GetAbsoluteOrigin())>0.0) {
+    /*
+      CCP4/MRC format does not allow arbitrary absolute origin to be used, hence
+      this correction routine to re-sample the map appropriately
+    */
+    LOG_VERBOSE("mrc io: applying absolute origin shift correction");
+    geom::Vec3 frac_shift=geom::CompDivide(sh.GetAbsoluteOrigin(),sh.GetSpatialSampling());
+    // apply fractional shift via Fourier space -> will wrap around!
+    sh2=sh.Apply(img::alg::FractionalShift(frac_shift));
+    // force origin to be zero now
+    sh2.SetAbsoluteOrigin(geom::Vec3(0.0,0.0,0.0));
+    // and correct for most of the wrap-around
+    img::Point int_shift(frac_shift);
+    sh2.ApplyIP(img::alg::Shift(-int_shift));
+    sh2.SetSpatialOrigin(int_shift);
+  }
   if (formatmrc.GetSubformat()==MRC_OLD_FORMAT) {
    LOG_DEBUG("mrc io: exporting old style format");
-   detail::export_endianess_switcher<detail::mrc_header>(sh,loc,formatmrc);
+   detail::export_endianess_switcher<detail::mrc_header>(sh2,loc,formatmrc);
   } else {
    LOG_DEBUG("mrc io: exporting new style format");
-   detail::export_endianess_switcher<detail::ccp4_header>(sh,loc,formatmrc);
+   detail::export_endianess_switcher<detail::ccp4_header>(sh2,loc,formatmrc);
   }
 }
 
diff --git a/modules/io/src/mol/CMakeLists.txt b/modules/io/src/mol/CMakeLists.txt
index cb80b67a9600ed5ec3f98e19a5669dcb4b1f1a1b..e7b729cb67c2361636103b86e1cb02f225db4c66 100644
--- a/modules/io/src/mol/CMakeLists.txt
+++ b/modules/io/src/mol/CMakeLists.txt
@@ -1,5 +1,6 @@
 set(OST_IO_MOL_SOURCES
 entity_io_crd_handler.cc	
+entity_io_pqr_handler.cc	
 entity_io_mae_handler.cc	
 pdb_reader.cc
 entity_io_pdb_handler.cc	
@@ -29,6 +30,7 @@ mmcif_info.hh
 io_profile.hh
 dcd_io.hh
 entity_io_crd_handler.hh
+entity_io_pqr_handler.hh
 entity_io_mae_handler.hh
 entity_io_mmcif_handler.hh
 entity_io_handler.hh
diff --git a/modules/io/src/mol/entity_io_pqr_handler.cc b/modules/io/src/mol/entity_io_pqr_handler.cc
new file mode 100644
index 0000000000000000000000000000000000000000..f1efaee3cc9da176584382cee45d26b2d530ed45
--- /dev/null
+++ b/modules/io/src/mol/entity_io_pqr_handler.cc
@@ -0,0 +1,341 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+/*
+  Author: Ansgar Philippsen
+*/
+
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+
+#include <boost/iostreams/filter/gzip.hpp>
+#include <boost/filesystem/convenience.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/format.hpp>
+#include <boost/tokenizer.hpp>
+
+#include <ost/log.hh>
+#include <ost/conop/conop.hh>
+#include <ost/mol/xcs_editor.hh>
+#include <ost/profile.hh>
+#include <ost/boost_filesystem_helper.hh>
+
+#include <ost/io/io_exception.hh>
+#include <ost/io/swap_util.hh>
+#include <ost/io/mol/io_profile.hh>
+
+#include "entity_io_pqr_handler.hh"
+
+namespace ost { namespace io {
+
+using boost::format;
+
+/// \brief Reader for PQR file format, used in APBS
+PQRReader::PQRReader(const boost::filesystem::path& loc):
+  sequential_atom_list_(),
+  curr_chain_(),
+  curr_residue_(),
+  chain_count_(0),
+  residue_count_(0),
+  atom_count_(0),
+  infile_(loc),
+  in_()
+{
+  if (boost::iequals(".gz", boost::filesystem::extension(loc))) {
+    in_.push(boost::iostreams::gzip_decompressor());    
+  }
+  in_.push(infile_);  
+  if(!infile_) throw IOException("could not open "+loc.string());
+}
+
+/// \brief Returns an vector containing all atom handles as observed in the file
+std::vector<mol::AtomHandle> PQRReader::GetSequentialAtoms() const
+{
+  return sequential_atom_list_;
+}
+
+/// \brief Performes file import
+void PQRReader::Import(mol::EntityHandle& ent)
+{
+  Profile profile_import("PQRReader::Import");
+
+  String line;
+  while(std::getline(in_,line)) {
+    if(line.substr(0,4)=="ATOM") {
+      ParseAndAddAtom(line,ent);
+    }
+  }
+
+  LOG_INFO("imported " << chain_count_ << " chains, " << residue_count_
+                << " residues, " << atom_count_ << " atoms");  
+}
+
+/// \brief Parsing for standard format
+void PQRReader::ParseAndAddAtom(const String& line, mol::EntityHandle& ent)
+{
+  static bool auto_chain=false;
+  static boost::char_separator<char> sep(" ");
+  mol::XCSEditor editor=ent.EditXCS(mol::BUFFERED_EDIT);
+
+  //int anum = boost::lexical_cast<int>(boost::trim_copy(line.substr(0,5)));
+  String aname = boost::trim_copy(line.substr(12,4));
+  String ele = aname.substr(0,1);
+  String rname = boost::trim_copy(line.substr(17,3));
+  int irnum = boost::lexical_cast<int>(boost::trim_copy(line.substr(22,4)));
+  String s_chain = boost::trim_copy(line.substr(21,1));
+
+  // space separated x y z charge rad at column 30+
+  Real ax=0.0,ay=0.0,az=0.0,ac=0.0,ar=0.0;
+  try {
+    std::string tmp(line.substr(30,std::string::npos));
+    boost::tokenizer<boost::char_separator<char> > tok(tmp,sep);
+    boost::tokenizer<boost::char_separator<char> >::iterator tit=tok.begin();
+    ax=boost::lexical_cast<Real>(*tit); ++tit;
+    ay=boost::lexical_cast<Real>(*tit); ++tit;
+    az=boost::lexical_cast<Real>(*tit); ++tit;
+    ac=boost::lexical_cast<Real>(*tit); ++tit;
+    ar=boost::lexical_cast<Real>(*tit); ++tit;
+  } catch (boost::bad_lexical_cast& e) {
+    return;
+  }
+  
+  geom::Vec3 apos(ax,ay,az);
+
+  mol::ResidueKey rkey(rname);
+  
+  mol::ResNum rnum(irnum);
+  
+  // determine chain and residue update
+  bool update_chain=false;
+  bool update_residue=false;
+  if(!curr_chain_) {
+    update_chain=true;
+    update_residue=true;
+    if(s_chain.empty()) {
+      s_chain="A";
+      auto_chain=true;
+    }
+  } else {
+    if(auto_chain) {
+      if(curr_residue_) {
+        if(rnum<curr_residue_.GetNumber()) {
+          update_chain=true;
+          update_residue=true;
+          std::ostringstream tmp;
+          tmp << static_cast<char>(65+chain_count_);
+          s_chain=tmp.str();
+        }
+      }
+    } else if(curr_chain_.GetName()!=s_chain) {
+      update_chain=true;
+      update_residue=true;
+    }  
+  }
+
+  if(!curr_residue_) {
+    update_residue=true;
+  } else if(curr_residue_.GetNumber()!=rnum) {
+    update_residue=true;
+  }
+
+  if(update_chain) {  
+    LOG_DEBUG("new chain " << s_chain);      
+    curr_chain_=editor.InsertChain(s_chain);
+    ++chain_count_;      
+  }
+
+  if(update_residue) {
+    LOG_DEBUG("new residue " << rkey << " " << rnum);
+    curr_residue_=editor.AppendResidue(curr_chain_, rkey, rnum);
+    assert(curr_residue_.IsValid());
+    ++residue_count_;
+  }
+
+  // finally add atom
+  LOG_DEBUG("adding atom " << aname << " (" << ele << ") @" << apos);
+  mol::AtomHandle ah = editor.InsertAtom(curr_residue_, aname, apos, ele);
+  ah.SetRadius(ar);
+  ah.SetCharge(ac);
+  sequential_atom_list_.push_back(ah);
+  ++atom_count_;
+}
+
+PQRWriter::PQRWriter(std::ostream& ostream, bool ext) :
+     outfile_(), outstream_(ostream), ext_(ext), atom_count_(0), res_count_(0)
+{}
+
+PQRWriter::PQRWriter(const boost::filesystem::path& filename, bool ext) :
+  outfile_(BFPathToString(filename).c_str()),
+  outstream_(outfile_), ext_(ext), atom_count_(0), res_count_(0)
+{}
+
+PQRWriter::PQRWriter(const String& filename, bool ext) :
+  outfile_(filename.c_str()), outstream_(outfile_), ext_(ext), atom_count_(0),
+  res_count_(0)
+{}
+
+/// \brief Write header containing standard title and atom count/format row
+void PQRWriter::WriteHeader(const mol::EntityView& ent)
+{
+}
+
+void PQRWriter::Init()
+{
+  res_count_ = 0;
+}
+
+void PQRWriter::Write(const mol::EntityView& ent)
+{
+  if (!outstream_) {
+    throw IOException("Can't write PQR file. Bad output stream");
+  }
+  this->Init();
+  mol::EntityView non_const_view = ent;
+  this->WriteHeader(non_const_view);
+  non_const_view.Apply(*this);
+}
+
+void PQRWriter::Write(const mol::EntityHandle& ent)
+{
+  if (!outstream_) {
+    throw IOException("Can't write PQR file. Bad output stream");
+  }
+  this->Init();
+  mol::EntityView non_const_view = ent.CreateFullView();
+  this->WriteHeader(non_const_view);
+  non_const_view.Apply(*this);
+}
+
+
+bool PQRWriter::VisitResidue(const mol::ResidueHandle& r)
+{
+  res_count_++;
+  return true;
+}
+
+bool PQRWriter::VisitAtom(const mol::AtomHandle& atom)
+{
+  atom_count_++;
+  String e_name=atom.GetEntity().GetName();
+  if (e_name=="") {
+    e_name="MOL";
+  }
+	
+  mol::ResidueHandle res=atom.GetResidue();
+/*
+  outstream_  << format("%5i") % atom_count_
+              << format("%5i") % res_count_ << " "
+	            << format("%-4s") % res.GetKey() << " "
+              << format("%-4s") % atom.GetName()
+              << format("%10.5f") % atom.GetPos().x
+              << format("%10.5f") % atom.GetPos().y
+              << format("%10.5f") % atom.GetPos().z << " "
+              << format("%-4s") % res.GetChain().GetName() << " "
+              << format("%-5i") % res.GetNumber() << " "
+              << format("%8.5f") % atom.GetBFactor()
+              << std::endl;
+              */
+ 
+  return true;
+}
+
+bool EntityIOPQRHandler::RequiresBuilder() const
+{
+  return true;
+}
+
+void EntityIOPQRHandler::Import(mol::EntityHandle& ent,
+                                const boost::filesystem::path& loc)
+{
+  PQRReader reader(loc);
+  reader.Import(ent);
+}
+
+void EntityIOPQRHandler::Export(const mol::EntityView& ent,
+                                std::ostream& stream) const
+{
+  PQRWriter writer(stream);
+  writer.Write(ent);
+}
+
+void EntityIOPQRHandler::Export(const mol::EntityView& ent,
+                                const boost::filesystem::path& loc) const
+{
+  PQRWriter writer(loc);
+  writer.Write(ent);
+}
+
+namespace {
+
+bool pqr_handler_is_responsible_for(const boost::filesystem::path& loc,
+                                    const String& type) {
+  if(type=="auto") {
+    String match_suf_string=loc.string();
+	std::transform(match_suf_string.begin(),match_suf_string.end(),match_suf_string.begin(),tolower);
+    if( detail::FilenameEndsWith(match_suf_string,".pqr") || detail::FilenameEndsWith(match_suf_string,".pqr.gz") ) {
+      return true;
+    }
+  } else if(type=="pqr") {
+    return true;
+  }
+
+  return false;
+}
+
+}
+
+bool EntityIOPQRHandler::ProvidesImport(const boost::filesystem::path& loc,
+                                        const String& type)
+{
+  return pqr_handler_is_responsible_for(loc, type);
+}
+
+bool EntityIOPQRHandler::ProvidesExport(const boost::filesystem::path& loc,
+                                        const String& type)
+{
+  return pqr_handler_is_responsible_for(loc, type);
+}
+
+mol::EntityHandle LoadPQR(const String& file_name) 
+{
+  Profile profile_load("LoadPQR");
+  IOProfile default_profile=IOProfileRegistry::Instance().GetDefault();
+  PQRReader reader(file_name);
+  mol::EntityHandle ent=mol::CreateEntity();
+  mol::XCSEditor editor=ent.EditXCS(mol::BUFFERED_EDIT);
+  reader.Import(ent);
+  if (default_profile.processor) 
+    default_profile.processor->Process(ent);
+  return ent;
+}
+
+
+void EntityIOPQRHandler::Import(mol::EntityHandle& ent, 
+                                std::istream& stream)
+{
+  throw IOException("PQR format does not support import from stream");
+}
+
+
+
+
+}} // ns
+
+
diff --git a/modules/io/src/mol/entity_io_pqr_handler.hh b/modules/io/src/mol/entity_io_pqr_handler.hh
new file mode 100644
index 0000000000000000000000000000000000000000..0b48e50be3a448d0ec2d7069b74e953a4b11c0cb
--- /dev/null
+++ b/modules/io/src/mol/entity_io_pqr_handler.hh
@@ -0,0 +1,115 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+/*
+  Author: Ansgar Philippsen
+*/
+
+#ifndef OST_IO_ENTITY_IO_PLUGIN_PQR_H
+#define OST_IO_ENTITY_IO_PLUGIN_PQR_H
+
+#include <ost/mol/entity_handle.hh>
+#include <ost/mol/chain_handle.hh>
+#include <ost/mol/residue_handle.hh>
+#include <ost/mol/entity_visitor.hh>
+#include <ost/io/mol/entity_io_handler.hh>
+
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/filesystem/fstream.hpp>
+
+namespace ost { namespace io {
+
+/// \brief CHARMM coordinate file import
+class DLLEXPORT_OST_IO PQRReader {
+public:
+  PQRReader(const boost::filesystem::path& loc);
+  
+  void Import(mol::EntityHandle& ent);
+
+  std::vector<mol::AtomHandle> GetSequentialAtoms() const;
+
+private:
+
+  void ParseAndAddAtom(const String& line, mol::EntityHandle& h);
+  void ParseAndAddAtomExpanded(const String& line, mol::EntityHandle& h);
+
+  std::vector<mol::AtomHandle> sequential_atom_list_;
+  mol::ChainHandle curr_chain_;
+  mol::ResidueHandle curr_residue_;
+  int chain_count_;
+  int residue_count_;
+  int atom_count_;
+  boost::filesystem::ifstream infile_;
+  boost::iostreams::filtering_stream<boost::iostreams::input>  in_;
+};
+
+/// \brief CHARMM coordinate file export
+class DLLEXPORT_OST_IO PQRWriter : public mol::EntityVisitor {
+public:
+  PQRWriter(const String& filename, bool ext=false);
+  PQRWriter(const boost::filesystem::path& filename, bool ext=false);
+  PQRWriter(std::ostream& outstream, bool ext=false);
+
+  void Write(const mol::EntityView& ent);
+  void Write(const mol::EntityHandle& ent);
+
+  virtual bool VisitAtom(const mol::AtomHandle& atom);
+  virtual bool VisitResidue(const mol::ResidueHandle& r);
+
+  void WriteHeader(const mol::EntityView& ent);
+
+private:
+  void Init();
+
+  std::ofstream   outfile_;
+  std::ostream&   outstream_;
+  bool ext_;
+  int atom_count_;
+  int atom_total_;
+  int res_count_;
+};
+
+class DLLEXPORT_OST_IO EntityIOPQRHandler: public EntityIOHandler {
+public:
+  virtual void Import(mol::EntityHandle& ent, const boost::filesystem::path& loc);
+  
+  virtual void Export(const mol::EntityView& ent, 
+                      const boost::filesystem::path& loc) const;
+                      
+  virtual void Import(mol::EntityHandle& ent, std::istream& stream);
+
+  virtual void Export(const mol::EntityView& ent, std::ostream& stream) const;
+  
+  static bool ProvidesImport(const boost::filesystem::path& loc, 
+                             const String& format="auto");
+  static bool ProvidesExport(const boost::filesystem::path& loc, 
+                             const String& format="auto");
+  virtual bool RequiresBuilder() const;
+
+  static String GetFormatName() { return String("Crd"); }
+  static String GetFormatDescription() { return String("CARD format file used by the Charmm software package"); }
+};
+
+
+typedef EntityIOHandlerFactory<EntityIOPQRHandler> EntityIOPQRHandlerFactory;
+
+mol::EntityHandle DLLEXPORT_OST_IO LoadPQR(const String& file_name);
+
+}} // ns
+
+#endif
diff --git a/modules/io/src/mol/io_profile.hh b/modules/io/src/mol/io_profile.hh
index b3c43b6db4dca42b2575a355b42200ede7409a51..f2214c2807ae4ca16898d81cbd0b0335c8c2e66b 100644
--- a/modules/io/src/mol/io_profile.hh
+++ b/modules/io/src/mol/io_profile.hh
@@ -31,12 +31,10 @@ namespace ost { namespace io {
 struct DLLEXPORT IOProfile {
 public:
   IOProfile(String d, bool qm, bool ft, bool js, bool nh, 
-            bool co, bool bf, conop::ProcessorPtr proc=conop::ProcessorPtr()):
+            bool co, conop::ProcessorPtr proc=conop::ProcessorPtr()):
     dialect(d), quack_mode(qm), fault_tolerant(ft), join_spread_atom_records(js), 
     no_hetatms(nh), calpha_only(co), processor(proc)
   {
-    if (!processor) return;
-    processor->SetCheckBondFeasibility(bf);
   }
 
   IOProfile(): dialect("PDB"), quack_mode(false), fault_tolerant(false), 
@@ -56,7 +54,6 @@ public:
   {
     return IOProfile(dialect, quack_mode, fault_tolerant, join_spread_atom_records, 
                      no_hetatms, calpha_only,  
-                     processor ? processor->GetCheckBondFeasibility() : false,
                      processor ? processor->Copy() : conop::ProcessorPtr());
   }
 };
diff --git a/modules/io/src/mol/mmcif_info.hh b/modules/io/src/mol/mmcif_info.hh
index 3eebf54b2369947c9d007e616c4d33c2f968750c..f567af0520381f6b726be63046235e2dd0b9a87a 100644
--- a/modules/io/src/mol/mmcif_info.hh
+++ b/modules/io/src/mol/mmcif_info.hh
@@ -545,7 +545,7 @@ private:
 /// 
 class DLLEXPORT_OST_IO MMCifInfoObsolete {
 public:
-  /// \brief Create an object of information baout an obsolete entry.
+  /// \brief Create an object of information about an obsolete entry.
   MMCifInfoObsolete(): date_(""), id_(UNKNOWN), pdb_id_(""),
     replaced_pdb_id_("") {};
 
@@ -620,6 +620,95 @@ private:
   String replaced_pdb_id_; ///< replaced entry
 };
 
+/// \brief container class for information on file revisions (database_pdb_rev)
+/// 
+class DLLEXPORT_OST_IO MMCifInfoRevisions {
+public:
+  /// \brief Start recording a revision process.
+  MMCifInfoRevisions(): date_original_("?"), first_release_(0) {};
+
+  /// \brief Set date the entry entered PDB.
+  ///
+  /// \param date
+  void SetDateOriginal(String date) { date_original_ = date; }
+
+  /// \brief Get date the entry entered PDB.
+  ///
+  /// \return date
+  String GetDateOriginal() const { return date_original_; }
+
+  /// \brief Add a revision to history
+  ///
+  /// \param num unique identifier
+  /// \param date date of revision
+  /// \param status status of the revision
+  void AddRevision(int num, String date, String status)
+  {
+    if (num_.size() && (num_.back() > num)) {
+      std::stringstream ss;
+      ss << "'num' component of 'database_pdb_rev' category has to increase ";
+      ss << "with every revision, last was ";
+      ss << num_.back();
+      ss << ", trying to add ";
+      ss << num;
+      throw IOException(ss.str());
+      }
+    num_.push_back(num);
+    date_.push_back(date);
+    status_.push_back(status);
+    // set first release date if not already occuoied
+    if (first_release_ == 0) {
+      if (status == "full release") {
+        first_release_ = status_.size();
+      }
+    }
+  }
+
+  /// \brief Get number of revisions stored.
+  ///
+  /// \return number
+  size_t GetSize() const { return num_.size(); }
+
+  /// \brief Get revision date by index in list.
+  ///
+  /// \param i position in list
+  /// \return date
+  String GetDate(size_t i) const { return date_[i]; }
+
+  /// \brief Get revision num by index in list.
+  ///
+  /// \param i position in list
+  /// \return num
+  int GetNum(size_t i) const { return num_[i]; }
+
+  /// \brief Get revision status by index in list.
+  ///
+  /// \param i position in list
+  /// \return status
+  String GetStatus(size_t i) const { return status_[i]; }
+
+  /// \brief Get date of last revision.
+  ///
+  /// \return date
+  String GetLastDate() const { return date_.back(); }
+
+  /// \brief Get the index of the full release revision.
+  ///
+  /// \return index
+  size_t GetFirstRelease() const
+  {
+    return first_release_;
+  }
+
+private:
+  String date_original_;       ///< first time seen in PDB
+  size_t first_release_;          ///< index of full release revision
+  std::vector<int> num_;       ///< sequential id of revision (gets larger)
+  std::vector<String> date_;   ///< date of revision
+  std::vector<String> status_; ///< ststus phrase for this revision
+};
+
+
 class MMCifInfoStructRef;
 class MMCifInfoStructRefSeq;
 class MMCifInfoStructRefSeqDif;
@@ -861,6 +950,32 @@ public:
   }
   const MMCifInfoStructRefs& GetStructRefs() const { return struct_refs_; }
   void SetStructRefs(const MMCifInfoStructRefs& sr) { struct_refs_=sr; }
+
+  /// \brief Set date_original of revisions.
+  ///
+  /// \param date
+  void SetRevisionsDateOriginal(String date)
+  {
+    revisions_.SetDateOriginal(date);
+  }
+
+  /// \brief Add a revision to history
+  ///
+  /// \param num unique identifier
+  /// \param date date of revision
+  /// \param status status of the revision
+  void AddRevision(int num, String date, String status)
+  {
+    revisions_.AddRevision(num, date, status);
+  }
+
+  /// \brief Get history
+  ///
+  /// \return MMCifInfoRevisions
+  MMCifInfoRevisions GetRevisions() const 
+  {
+    return revisions_;
+  }
 //protected:
 
 private:
@@ -869,6 +984,7 @@ private:
   Real resolution_;
   MMCifInfoStructDetails struct_details_;     ///< mmCIF struct category
   MMCifInfoObsolete obsolete_;                ///< obsolete/ superseded entry
+  MMCifInfoRevisions revisions_;              ///< database_pdb_rev category
   std::vector<MMCifInfoCitation> citations_;  ///< list of citations
   std::vector<MMCifInfoBioUnit>  biounits_;   ///< list of biounits
   std::vector<MMCifInfoTransOpPtr> transops_;
diff --git a/modules/io/src/mol/mmcif_reader.cc b/modules/io/src/mol/mmcif_reader.cc
index a9c0ad6bfc87cf72cf56a66dda0193ddd981db6b..5ae0f87f69cfebf692c362e83bad001b66e73c2f 100644
--- a/modules/io/src/mol/mmcif_reader.cc
+++ b/modules/io/src/mol/mmcif_reader.cc
@@ -306,31 +306,40 @@ bool MMCifReader::OnBeginLoop(const StarLoopDesc& header)
     this->TryStoreIdx(REPLACE_PDB_ID, "replace_pdb_id", header);
     cat_available = true;
   } else if (header.GetCategory() == "struct_ref") {
-  	category_ = STRUCT_REF;
-  	this->TryStoreIdx(SR_ENTITY_ID, "entity_id", header);
-  	this->TryStoreIdx(SR_ID, "id", header);
-  	this->TryStoreIdx(SR_DB_NAME, "db_name", header);
-  	this->TryStoreIdx(SR_DB_CODE, "db_code", header);
-  	indices_[SR_DB_ACCESS]=header.GetIndex("pdbx_db_accession");
-  	cat_available = true;
-	} else if (header.GetCategory() == "struct_ref_seq") {
-	  category_ = STRUCT_REF_SEQ;	
-  	this->TryStoreIdx(SRS_ALIGN_ID, "align_id", header);
-  	this->TryStoreIdx(SRS_STRUCT_REF_ID, "ref_id", header);
-  	this->TryStoreIdx(SRS_ENT_ALIGN_BEG, "seq_align_beg", header);
-  	this->TryStoreIdx(SRS_ENT_ALIGN_END, "seq_align_end", header);
-  	this->TryStoreIdx(SRS_DB_ALIGN_BEG, "db_align_beg", header);
-  	this->TryStoreIdx(SRS_DB_ALIGN_END, "db_align_end", header);
+    category_ = STRUCT_REF;
+    this->TryStoreIdx(SR_ENTITY_ID, "entity_id", header);
+    this->TryStoreIdx(SR_ID, "id", header);
+    this->TryStoreIdx(SR_DB_NAME, "db_name", header);
+    this->TryStoreIdx(SR_DB_CODE, "db_code", header);
+    indices_[SR_DB_ACCESS]=header.GetIndex("pdbx_db_accession");
+    cat_available = true;
+  } else if (header.GetCategory() == "struct_ref_seq") {
+    category_ = STRUCT_REF_SEQ;	
+    this->TryStoreIdx(SRS_ALIGN_ID, "align_id", header);
+    this->TryStoreIdx(SRS_STRUCT_REF_ID, "ref_id", header);
+    this->TryStoreIdx(SRS_ENT_ALIGN_BEG, "seq_align_beg", header);
+    this->TryStoreIdx(SRS_ENT_ALIGN_END, "seq_align_end", header);
+    this->TryStoreIdx(SRS_DB_ALIGN_BEG, "db_align_beg", header);
+    this->TryStoreIdx(SRS_DB_ALIGN_END, "db_align_end", header);
     indices_[SRS_PDBX_STRAND_ID]=header.GetIndex("pdbx_strand_id");
-	  cat_available = true;
-	} else if (header.GetCategory()=="struct_ref_seq_dif") {
-		category_ = STRUCT_REF_SEQ_DIF;
-  	this->TryStoreIdx(SRSD_ALIGN_ID, "align_id", header);
-  	this->TryStoreIdx(SRSD_SEQ_RNUM, "seq_num", header);
-  	this->TryStoreIdx(SRSD_DB_RNUM, "pdbx_seq_db_seq_num", header);
-  	indices_[SRSD_DETAILS]=header.GetIndex("details");
-  	cat_available = true;
-	}
+    cat_available = true;
+  } else if (header.GetCategory()=="struct_ref_seq_dif") {
+    category_ = STRUCT_REF_SEQ_DIF;
+    this->TryStoreIdx(SRSD_ALIGN_ID, "align_id", header);
+    this->TryStoreIdx(SRSD_SEQ_RNUM, "seq_num", header);
+    this->TryStoreIdx(SRSD_DB_RNUM, "pdbx_seq_db_seq_num", header);
+    indices_[SRSD_DETAILS]=header.GetIndex("details");
+    cat_available = true;
+  } else if (header.GetCategory()=="database_PDB_rev") {
+    category_ = DATABASE_PDB_REV;
+    // mandatory items
+    this->TryStoreIdx(DPI_NUM, "num", header);
+    // optional items
+    indices_[DPI_DATE] = header.GetIndex("date");
+    indices_[DPI_DATE_ORIGINAL] = header.GetIndex("date_original");
+    indices_[DPI_STATUS] = header.GetIndex("status");
+    cat_available = true;
+  }
   category_counts_[category_]++;
   return cat_available;
 }
@@ -360,7 +369,7 @@ bool MMCifReader::ParseAtomIdent(const std::vector<StringRef>& columns,
   auth_chain_name = columns[indices_[AUTH_ASYM_ID]].str();
   cif_chain_name = columns[indices_[LABEL_ASYM_ID]].str();
 
-  if (restrict_chains_.size() > 0 &&
+  if (! restrict_chains_.empty() &&
       restrict_chains_.find(cif_chain_name) == String::npos) {
     return false;
   } 
@@ -597,7 +606,6 @@ void MMCifReader::ParseAndAddAtom(const std::vector<StringRef>& columns)
   // record type
   ah.SetHetAtom(indices_[GROUP_PDB] == -1 ? false :  
                 columns[indices_[GROUP_PDB]][0]=='H');
-
 }
 
 void MMCifReader::ParseEntity(const std::vector<StringRef>& columns)
@@ -938,7 +946,7 @@ std::vector<std::vector<String> > MMCifReader::UnPackOperExperession(StringRef e
       } else if (*s == ')') {
         StoreExpression(l, s, is_range, lborder, single_block);
         l = s+1;
-        if (single_block.size() > 0) {
+        if (! single_block.empty()) {
           unpacked.push_back(single_block);
         }
         single_block.clear();
@@ -1300,6 +1308,29 @@ void MMCifReader::ParsePdbxDatabasePdbObsSpr(const std::vector<StringRef>&
   info_.SetObsoleteInfo(obs_data);
 }
 
+void MMCifReader::ParseDatabasePDBRev(const std::vector<StringRef>& columns)
+{
+  int num;
+  StringRef date;
+  StringRef status;
+
+  num = this->TryGetInt(columns[indices_[DPI_NUM]], "database_PDB_rev.num");
+  if (indices_[DPI_DATE] != -1) {
+    date = columns[indices_[DPI_DATE]];
+  } else {
+    date = StringRef("", 0);
+  }
+  if (indices_[DPI_DATE_ORIGINAL] != -1) {
+    info_.SetRevisionsDateOriginal(columns[indices_[DPI_DATE_ORIGINAL]].str());
+  }
+  if (indices_[DPI_STATUS] != -1) {
+    status = columns[indices_[DPI_STATUS]];
+  } else {
+    status = StringRef("", 0);
+  }
+  info_.AddRevision(num, date.str(), status.str());
+}
+
 void MMCifReader::OnDataRow(const StarLoopDesc& header, 
                             const std::vector<StringRef>& columns)
 {
@@ -1361,17 +1392,21 @@ void MMCifReader::OnDataRow(const StarLoopDesc& header,
     this->ParsePdbxDatabasePdbObsSpr(columns);
     break;
   case STRUCT_REF:
-  	LOG_TRACE("processing struct_ref entry");
-  	this->ParseStructRef(columns);
-  	break;
+    LOG_TRACE("processing struct_ref entry");
+    this->ParseStructRef(columns);
+    break;
   case STRUCT_REF_SEQ:
-  	LOG_TRACE("processing struct_ref entry");
-  	this->ParseStructRefSeq(columns);
-  	break;
+    LOG_TRACE("processing struct_ref entry");
+    this->ParseStructRefSeq(columns);
+    break;
   case STRUCT_REF_SEQ_DIF:
-  	LOG_TRACE("processing struct_ref entry");
-  	this->ParseStructRefSeqDif(columns);
-  	break;
+    LOG_TRACE("processing struct_ref entry");
+    this->ParseStructRefSeqDif(columns);
+    break;
+  case DATABASE_PDB_REV:
+    LOG_TRACE("processing database_PDB_rev entry");
+    this->ParseDatabasePDBRev(columns);
+    break;
   default:
     throw IOException(this->FormatDiagnostic(STAR_DIAG_ERROR,
                        "Uncatched category '"+ header.GetCategory() +"' found.",
@@ -1423,7 +1458,6 @@ void MMCifReader::AssignSecStructure(mol::EntityHandle ent)
   }
 }
 
-
 void MMCifReader::ParseStructRef(const std::vector<StringRef>& columns)
 {
 	String ent_id=columns[indices_[SR_ENTITY_ID]].str();
diff --git a/modules/io/src/mol/mmcif_reader.hh b/modules/io/src/mol/mmcif_reader.hh
index e9ff3b893f0e8ade4cce29838b79fb8ab89cf871..b8f6daed068fd5c96293d4d8e6442d24a74b3e0b 100644
--- a/modules/io/src/mol/mmcif_reader.hh
+++ b/modules/io/src/mol/mmcif_reader.hh
@@ -55,6 +55,7 @@ namespace ost { namespace io {
 /// \li struct_conf
 /// \li struct_sheet_range
 /// \li pdbx_database_PDB_obs_spr
+/// \li database_PDB_rev
 class DLLEXPORT_OST_IO MMCifReader : public StarParser  {
 public:
   /// \brief create a MMCifReader
@@ -237,8 +238,8 @@ protected:
   /// proper handling of our sequence classes, these need to be converted to 
   /// one-letter-codes. Ideally, we would use the canonical SEQRES. This is 
   /// not possible, however, since the PDB assigns multiple one letter codes 
-  /// to some of the residues. To be consistent, we have to do the conversion on 
-  /// our own.
+  /// to some of the residues. To be consistent, we have to do the conversion
+  /// on our own.
   String ConvertSEQRES(const String& seqres, conop::CompoundLibPtr compound_lib);
   /// \brief Fetch mmCIF citation_author information
   ///
@@ -287,6 +288,11 @@ protected:
   /// \param columns data row
   void ParsePdbxStructOperList(const std::vector<StringRef>& columns);
 
+  /// \brief Fetch mmCIF database_PDB_rev information
+  ///
+  /// \param columns data row
+  void ParseDatabasePDBRev(const std::vector<StringRef>& columns);
+
   /// \brief Fetch mmCIF struct information
   ///
   /// \param columns data row
@@ -420,24 +426,25 @@ private:
   	SR_DB_ACCESS
 	} StructRefItems;
 	
-	/// \enum items of the struct_ref_seq category
-	typedef enum {
-		SRS_ALIGN_ID,
-		SRS_STRUCT_REF_ID,
-		SRS_PDBX_STRAND_ID,
-		SRS_DB_ALIGN_BEG,
-		SRS_DB_ALIGN_END,
-		SRS_ENT_ALIGN_BEG,
-		SRS_ENT_ALIGN_END
-	} StructRefSeqItems;
-
-	/// \enum items of the struct_ref_seq_dif category
-	typedef enum {
-		SRSD_ALIGN_ID,
-		SRSD_SEQ_RNUM,
-		SRSD_DB_RNUM,
+  /// \enum items of the struct_ref_seq category
+  typedef enum {
+    SRS_ALIGN_ID,
+    SRS_STRUCT_REF_ID,
+    SRS_PDBX_STRAND_ID,
+    SRS_DB_ALIGN_BEG,
+    SRS_DB_ALIGN_END,
+    SRS_ENT_ALIGN_BEG,
+    SRS_ENT_ALIGN_END
+  } StructRefSeqItems;
+  
+  /// \enum items of the struct_ref_seq_dif category
+  typedef enum {
+    SRSD_ALIGN_ID,
+    SRSD_SEQ_RNUM,
+    SRSD_DB_RNUM,
     SRSD_DETAILS
-	} StructRefSeqDifItems;
+  } StructRefSeqDifItems;
+
   /// \enum items of the pdbx_struct_assembly_gen category
   typedef enum {
     ASSEMBLY_ID,                  ///< link to pdbx_struct_assembly.id
@@ -511,6 +518,14 @@ private:
     REPLACE_PDB_ID, ///< OLD PDB ID
   } PdbxDatabasePDBObsSpr;
 
+  /// \enum categories of the database_PDB_rev category
+  typedef enum {
+    DPI_NUM,           ///< unique identifier
+    DPI_DATE,          ///< revision date
+    DPI_DATE_ORIGINAL, ///< date of first sight
+    DPI_STATUS,        ///< status of a revision
+  } DatabasePDBRevItems;
+
   /// \enum categories of the mmcif format
   typedef enum {
     ATOM_SITE,
@@ -530,6 +545,7 @@ private:
     STRUCT_REF,
     STRUCT_REF_SEQ,
     STRUCT_REF_SEQ_DIF,
+    DATABASE_PDB_REV,
     DONT_KNOW
   } MMCifCategory;
 
diff --git a/modules/io/src/mol/pdb_reader.cc b/modules/io/src/mol/pdb_reader.cc
index 13638576106be52ab3e75ac8c640b0f3a18ad3a3..ea81f65c1614de11d645e0d90e5412f41072a7c3 100644
--- a/modules/io/src/mol/pdb_reader.cc
+++ b/modules/io/src/mol/pdb_reader.cc
@@ -492,7 +492,7 @@ void PDBReader::AssignMolIds(mol::EntityHandle ent) {
       }
     }
   }
-  if (compnds_.size()>0){
+  if (! compnds_.empty()){
     mol::ChainHandleList ch_list=ent.GetChainList();
     for (mol::ChainHandleList::const_iterator chain=ch_list.begin();
          chain!=ch_list.end(); ++chain) {
@@ -596,7 +596,7 @@ bool PDBReader::ParseAtomIdent(const StringRef& line, int line_num,
     }
   } else {
     chain_name=String(1, line[21]);    
-    if (restrict_chains_.size()>0 &&
+    if (! restrict_chains_.empty() &&
       restrict_chains_.find(chain_name)==String::npos) {
       return false;
     }    
diff --git a/modules/io/src/mol/pdb_writer.cc b/modules/io/src/mol/pdb_writer.cc
index 3df6a4917db7901bbc4cb246d8346cd3f7c25f19..af00fb80656f02846c90a47070e0f1aa609af807 100644
--- a/modules/io/src/mol/pdb_writer.cc
+++ b/modules/io/src/mol/pdb_writer.cc
@@ -69,6 +69,15 @@ bool shift_left(const String& atom_name, bool is_hetatm,
           element=="MG" || element=="LI");
 }
 
+
+bool atom_pos_ok(geom::Vec3 p) {
+  for (int i=0; i<3; ++i) {
+    if (p[i]<=-1000 || p[i] >= 10000) {
+      return false;
+    }
+  }
+  return true;
+}
 void write_atom(std::ostream& ostr, FormattedLine& line, 
                 const mol::AtomHandle& atom, int atomnum, 
                 bool is_pqr, bool charmm_style)
@@ -117,7 +126,7 @@ void write_atom(std::ostream& ostr, FormattedLine& line,
   
   String chain_name=res.GetChain().GetName();
   if (!charmm_style) {
-    if (chain_name.size()>0) {
+      if (! chain_name.empty()) {
       if (chain_name.size()==1) {
         line[21]=chain_name[0];
       } else {
@@ -132,6 +141,9 @@ void write_atom(std::ostream& ostr, FormattedLine& line,
   
   // deal with alternative atom locations
   if (names.empty()) {
+    if (!atom_pos_ok(p)) {
+      throw IOException("Atom position outside of bounds supported by PDB format");
+    }
     line(30, 8)=fmt::LPaddedFloat(p[0],  3);
     line(38, 8)=fmt::LPaddedFloat(p[1],  3);
     line(46, 8)=fmt::LPaddedFloat(p[2],  3);
@@ -162,6 +174,9 @@ void write_atom(std::ostream& ostr, FormattedLine& line,
       p=atom.GetEntity().GetTransform().Apply(atom.GetAltPos(*i));
       line(30, 50).Clear();
 
+      if (!atom_pos_ok(p)) {
+        throw IOException("Atom position outside of bounds supported by PDB format");
+      }
       if (i->size()>1) {
         throw IOException("Alternative atom indicator '"+atom.GetQualifiedName()+
                           "("+*i+")' too long for PDB output. At most 1 "
diff --git a/modules/io/src/zlib.cpp b/modules/io/src/zlib.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d765e855df48fce940be0bca71d373cd7074f0a4
--- /dev/null
+++ b/modules/io/src/zlib.cpp
@@ -0,0 +1,193 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2003-2007 Jonathan Turkanis
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
+
+// See http://www.boost.org/libs/iostreams for documentation.
+
+// To configure Boost to work with zlib, see the 
+// installation instructions here:
+// http://boost.org/libs/iostreams/doc/index.html?path=7
+
+// Define BOOST_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp> 
+// knows that we are building the library (possibly exporting code), rather 
+// than using it (possibly importing code).
+#define BOOST_IOSTREAMS_SOURCE 
+
+#include <boost/throw_exception.hpp>
+#include <boost/iostreams/detail/config/dyn_link.hpp>
+#include <boost/iostreams/filter/zlib.hpp> 
+#include "zlib.h"   // Jean-loup Gailly's and Mark Adler's "zlib.h" header.
+                    // To configure Boost to work with zlib, see the 
+                    // installation instructions here:
+                    // http://boost.org/libs/iostreams/doc/index.html?path=7
+
+namespace boost { namespace iostreams {
+
+namespace zlib {
+
+                    // Compression levels
+
+const int no_compression       = Z_NO_COMPRESSION;
+const int best_speed           = Z_BEST_SPEED;
+const int best_compression     = Z_BEST_COMPRESSION;
+const int default_compression  = Z_DEFAULT_COMPRESSION;
+
+                    // Compression methods
+
+const int deflated             = Z_DEFLATED;
+
+                    // Compression strategies
+
+const int default_strategy     = Z_DEFAULT_STRATEGY;
+const int filtered             = Z_FILTERED;
+const int huffman_only         = Z_HUFFMAN_ONLY;
+
+                    // Status codes
+
+const int okay                 = Z_OK;
+const int stream_end           = Z_STREAM_END;
+const int stream_error         = Z_STREAM_ERROR;
+const int version_error        = Z_VERSION_ERROR;
+const int data_error           = Z_DATA_ERROR;
+const int mem_error            = Z_MEM_ERROR;
+const int buf_error            = Z_BUF_ERROR;
+
+                    // Flush codes
+
+const int finish               = Z_FINISH;
+const int no_flush             = Z_NO_FLUSH;
+const int sync_flush           = Z_SYNC_FLUSH;
+
+                    // Code for current OS
+
+//const int os_code              = OS_CODE;
+
+} // End namespace zlib. 
+
+//------------------Implementation of zlib_error------------------------------//
+                    
+zlib_error::zlib_error(int error) 
+    : BOOST_IOSTREAMS_FAILURE("zlib error"), error_(error) 
+    { }
+
+void zlib_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(int error)
+{
+    switch (error) {
+    case Z_OK: 
+    case Z_STREAM_END: 
+    //case Z_BUF_ERROR: 
+        return;
+    case Z_MEM_ERROR: 
+        boost::throw_exception(std::bad_alloc());
+    default:
+        boost::throw_exception(zlib_error(error));
+        ;
+    }
+}
+
+//------------------Implementation of zlib_base-------------------------------//
+
+namespace detail {
+
+zlib_base::zlib_base()
+    : stream_(new z_stream), calculate_crc_(false), crc_(0), crc_imp_(0)
+    { }
+
+zlib_base::~zlib_base() { delete static_cast<z_stream*>(stream_); }
+
+void zlib_base::before( const char*& src_begin, const char* src_end,
+                        char*& dest_begin, char* dest_end )
+{
+    z_stream* s = static_cast<z_stream*>(stream_);
+    s->next_in = reinterpret_cast<zlib::byte*>(const_cast<char*>(src_begin));
+    s->avail_in = static_cast<zlib::uint>(src_end - src_begin);
+    s->next_out = reinterpret_cast<zlib::byte*>(dest_begin);
+    s->avail_out= static_cast<zlib::uint>(dest_end - dest_begin);
+}
+
+void zlib_base::after(const char*& src_begin, char*& dest_begin, bool compress)
+{
+    z_stream* s = static_cast<z_stream*>(stream_);
+    char* next_in = reinterpret_cast<char*>(s->next_in);
+    char* next_out = reinterpret_cast<char*>(s->next_out);
+    if (calculate_crc_) {
+        const zlib::byte* buf = compress ?
+            reinterpret_cast<const zlib::byte*>(src_begin) :
+            reinterpret_cast<const zlib::byte*>(
+                const_cast<const char*>(dest_begin)
+            );
+        zlib::uint length = compress ?
+            static_cast<zlib::uint>(next_in - src_begin) :
+            static_cast<zlib::uint>(next_out - dest_begin);
+        if (length > 0)
+            crc_ = crc_imp_ = crc32(crc_imp_, buf, length);
+    }
+    total_in_ = s->total_in;
+    total_out_ = s->total_out;
+    src_begin = const_cast<const char*>(next_in);
+    dest_begin = next_out;
+}
+
+int zlib_base::xdeflate(int flush)
+{ 
+    return ::deflate(static_cast<z_stream*>(stream_), flush);
+}
+
+int zlib_base::xinflate(int flush)
+{ 
+    return ::inflate(static_cast<z_stream*>(stream_), flush);
+}
+
+void zlib_base::reset(bool compress, bool realloc)
+{
+    z_stream* s = static_cast<z_stream*>(stream_);
+    // Undiagnosed bug:
+    // deflateReset(), etc., return Z_DATA_ERROR
+    //zlib_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(
+        realloc ?
+            (compress ? deflateReset(s) : inflateReset(s)) :
+            (compress ? deflateEnd(s) : inflateEnd(s))
+                ;
+    //);
+    crc_imp_ = 0;
+}
+
+void zlib_base::do_init
+    ( const zlib_params& p, bool compress, 
+      #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+          zlib::xalloc_func /* alloc */, zlib::xfree_func /* free*/, 
+      #endif
+      void* derived )
+{
+    calculate_crc_ = p.calculate_crc;
+    z_stream* s = static_cast<z_stream*>(stream_);
+
+    // Current interface for customizing memory management 
+    // is non-conforming and has been disabled:
+    //#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+    //    s->zalloc = alloc;
+    //    s->zfree = free;
+    //#else
+        s->zalloc = 0;
+        s->zfree = 0;
+    //#endif
+    s->opaque = derived;
+    int window_bits = p.noheader? -p.window_bits : p.window_bits;
+    zlib_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(
+        compress ?
+            deflateInit2( s, 
+                          p.level,
+                          p.method,
+                          window_bits,
+                          p.mem_level,
+                          p.strategy ) :
+            inflateInit2(s, window_bits)
+    );
+}
+
+} // End namespace detail.
+
+//----------------------------------------------------------------------------//
+
+} } // End namespaces iostreams, boost.
diff --git a/modules/io/tests/test_clustal.cc b/modules/io/tests/test_clustal.cc
index 0f8b4d63bd56e0aa4f51acba6dcb18c64b273bd6..b9ebf221b655b00c6c1a50b23d74685cfd389169 100644
--- a/modules/io/tests/test_clustal.cc
+++ b/modules/io/tests/test_clustal.cc
@@ -21,12 +21,13 @@
   Author: Marco Biasini
  */
 
-#include <ost/io/seq/clustal_io_handler.hh>
-#include <ost/io/seq/load.hh>
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 #include <boost/test/auto_unit_test.hpp>
 
+#include <ost/io/seq/clustal_io_handler.hh>
+#include <ost/io/seq/load.hh>
+
 using namespace ost;
 using namespace ost::io;
 const static String MOUSE="MFQAFPGDYDSGSRCSSSPSAESQYLSSVDSFGSPPTAAASQECAGLGEMPGSFVPTVTAITTSQDLQWLVQPTLISSMAQSQGQPLASQPPAVDPYDMPGTSYSTPGLSAYSTGGASGS";
diff --git a/modules/io/tests/test_io_crd.cc b/modules/io/tests/test_io_crd.cc
index 5fa943c87bd1cc942c0cf5b9dc1053ce15099a42..b317e936bce58126c130f2260c318af8112a7422 100644
--- a/modules/io/tests/test_io_crd.cc
+++ b/modules/io/tests/test_io_crd.cc
@@ -16,13 +16,14 @@
 // along with this library; if not, write to the Free Software Foundation, Inc.,
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 //------------------------------------------------------------------------------
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+#include <boost/test/auto_unit_test.hpp>
+
 #include <ost/test_utils/compare_files.hh>
 #include <ost/mol/mol.hh>
 #include <ost/io/mol/entity_io_crd_handler.hh>
 #include <ost/io/save_entity.hh>
-#define BOOST_TEST_DYN_LINK
-#include <boost/test/unit_test.hpp>
-#include <boost/test/auto_unit_test.hpp>
 
 using namespace ost;
 using namespace ost::io;
diff --git a/modules/io/tests/test_io_dcd.cc b/modules/io/tests/test_io_dcd.cc
index b326d381b68d15f4bf61c80df65ddc06f5446f11..016555e696f569175ff066ffef96ed43abdddb52 100644
--- a/modules/io/tests/test_io_dcd.cc
+++ b/modules/io/tests/test_io_dcd.cc
@@ -17,6 +17,10 @@
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 //------------------------------------------------------------------------------
 
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+#include <boost/test/auto_unit_test.hpp>
+
 #include <ost/io/mol/dcd_io.hh>
 #include <ost/mol/entity_handle.hh>
 #include <ost/mol/residue_handle.hh>
@@ -24,9 +28,6 @@
 #include <ost/mol/atom_handle.hh>
 #include <ost/mol/xcs_editor.hh>
 #include <ost/mol/coord_group.hh>
-#define BOOST_TEST_DYN_LINK
-#include <boost/test/unit_test.hpp>
-#include <boost/test/auto_unit_test.hpp>
 
 using namespace ost;
 using namespace ost::io;
diff --git a/modules/io/tests/test_io_img.cc b/modules/io/tests/test_io_img.cc
index 890a7a9c29a22beb57b4c7c0aa0ffb04273f8777..78093264b4b204fd095152fff381ae0ac5419512 100644
--- a/modules/io/tests/test_io_img.cc
+++ b/modules/io/tests/test_io_img.cc
@@ -16,12 +16,14 @@
 // along with this library; if not, write to the Free Software Foundation, Inc.,
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 //------------------------------------------------------------------------------
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+#include <boost/test/auto_unit_test.hpp>
+
 #include <map>
 #include <ost/io/load_map.hh>
 #include <ost/img/image_factory.hh>
 #include <ost/img/alg/randomize.hh>
-#define BOOST_TEST_DYN_LINK
-#include <boost/test/unit_test.hpp>
 #include  <ost/io/img/map_io_df3_handler.hh>
 #include  <ost/io/img/map_io_dat_handler.hh>
 #include  <ost/io/img/map_io_dx_handler.hh>
diff --git a/modules/io/tests/test_io_mmcif.py b/modules/io/tests/test_io_mmcif.py
index 94eb063301b5e56f697c7d67f43452c023b38f56..bc8a35aa2bc45f9a1a5ac9bb334bcbb28db32ec4 100644
--- a/modules/io/tests/test_io_mmcif.py
+++ b/modules/io/tests/test_io_mmcif.py
@@ -1,4 +1,5 @@
 import unittest
+import ost
 from ost import *
 
 class TestMMCifInfo(unittest.TestCase):
@@ -165,6 +166,21 @@ class TestMMCifInfo(unittest.TestCase):
     self.assertEquals(len(pdb_seqres_ent.GetChainList()[9].GetResidueList()),
                       414)
 
+  def test_mmcifinfo_biounit_pdbize_transformation(self):
+    ent, seqres, info = io.LoadMMCIF("testfiles/mmcif/3hqv.cif.gz",
+                                     seqres=True,
+                                     info=True)
+    pdb_ent, t = info.GetBioUnits()[0].PDBize(ent, transformation=True)
+    self.assertAlmostEquals(pdb_ent.GetCenterOfAtoms()[0], -915.759, 2)
+    self.assertAlmostEquals(pdb_ent.GetCenterOfAtoms()[1], -952.345, 2)
+    self.assertAlmostEquals(pdb_ent.GetCenterOfAtoms()[2], 3221.75, 2)
+    self.assertEquals(geom.Equal(t,
+                                 geom.Mat4(1,0,0,-920.462,
+                                           0,1,0,-966.654,
+                                           0,0,1,1703,
+                                           0,0,0,1),
+                                 epsilon=0.01), True)
+
   def test_mmcifinfo_structdetails(self):
     d = io.MMCifInfoStructDetails()
 
diff --git a/modules/io/tests/test_io_pdb.cc b/modules/io/tests/test_io_pdb.cc
index 33e08b19af7b3ac3fd08eae0f6705c32c8b2d8f6..7d33d8bce38ecc45702b190cbb37439b2b94960d 100644
--- a/modules/io/tests/test_io_pdb.cc
+++ b/modules/io/tests/test_io_pdb.cc
@@ -16,6 +16,12 @@
 // along with this library; if not, write to the Free Software Foundation, Inc.,
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 //------------------------------------------------------------------------------
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+#include <boost/test/auto_unit_test.hpp>
+#include <boost/test/floating_point_comparison.hpp>
+using boost::unit_test_framework::test_suite;
+
 #include <ost/test_utils/compare_files.hh>
 #include <ost/geom/vec_mat_predicates.hh>
 
@@ -31,11 +37,6 @@
 #include <ost/log.hh>
 
 #include <ost/io/io_exception.hh>
-#define BOOST_TEST_DYN_LINK
-#include <boost/test/unit_test.hpp>
-#include <boost/test/auto_unit_test.hpp>
-#include <boost/test/floating_point_comparison.hpp>
-using boost::unit_test_framework::test_suite;
 
 using namespace ost;
 using namespace ost::io;
@@ -924,8 +925,7 @@ BOOST_AUTO_TEST_CASE(charmm_rname)
 {
   {
     PDBWriter writer(String("testfiles/pdb/charmm_rname-out.pdb"),
-                     IOProfile("CHARMM", false, false,
-                               false, false, false, true));
+                     IOProfile("CHARMM", false, false, false, false, false));
 
     mol::EntityHandle ent=mol::CreateEntity();
     mol::XCSEditor edi=ent.EditXCS();
@@ -944,8 +944,7 @@ BOOST_AUTO_TEST_CASE(charmm_longcname)
 {
   {
     PDBWriter writer(String("testfiles/pdb/charmm_longcname-out.pdb"),
-                     IOProfile("CHARMM", false, false,
-                               false, false, false, true));
+                     IOProfile("CHARMM", false, false, false, false, false));
 
     mol::EntityHandle ent=mol::CreateEntity();
     mol::XCSEditor edi=ent.EditXCS();
@@ -964,8 +963,7 @@ BOOST_AUTO_TEST_CASE(write_charmm_ter)
 {
   {
     PDBWriter writer(String("testfiles/pdb/charmm_ter-out.pdb"),
-                     IOProfile("CHARMM", false, false,
-                               false, false, false, true));
+                     IOProfile("CHARMM", false, false, false, false, false));
 
     mol::EntityHandle ent=mol::CreateEntity();
     mol::XCSEditor edi=ent.EditXCS();
@@ -1033,6 +1031,24 @@ BOOST_AUTO_TEST_CASE(test_pqr_read_atom)
   BOOST_CHECK_CLOSE(a2.GetRadius(), Real(1.7503), Real(1e-4));
 }
 
+BOOST_AUTO_TEST_CASE(checks_for_atom_pos_overflow)
+{
+  std::stringstream out;
+  PDBWriter writer(out, IOProfile());
+  writer.SetIsPQR(true);
+
+  mol::EntityHandle ent=mol::CreateEntity();
+  mol::XCSEditor edi=ent.EditXCS();
+  mol::ChainHandle ch=edi.InsertChain("A");
+  mol::ResidueHandle r=edi.AppendResidue(ch, "GLY");
+
+  mol::AtomHandle a=edi.InsertAtom(r, "CA", geom::Vec3(0, -1000,0), "C");
+  
+  BOOST_CHECK_THROW(writer.Write(ent), IOException);
+  edi.SetAtomPos(a, geom::Vec3(10000,0,0));
+  BOOST_CHECK_THROW(writer.Write(ent), IOException);
+}
+
 BOOST_AUTO_TEST_CASE(test_pqr_write_atom)
 {
   std::stringstream out;
diff --git a/modules/io/tests/test_io_pdb.py b/modules/io/tests/test_io_pdb.py
index b446099a88feaea32650809080bb9a76bee2abab..9beb684d952f60bbbaf35e4b9b2369ddc896395c 100644
--- a/modules/io/tests/test_io_pdb.py
+++ b/modules/io/tests/test_io_pdb.py
@@ -12,16 +12,20 @@ class TestPDB(unittest.TestCase):
     self.assertEquals(ch.GetIntProp("mol_id"), 1)
 
   def test_no_bond_feasibility(self):
-    profiles=io.IOProfiles()
-    profiles['NO_FEAS_CHECK']=io.IOProfile(bond_feasibility_check=False,
-                                           processor=conop.HeuristicProcessor())
+    io.profiles['FEAS_CHECK']=io.IOProfile(processor=conop.HeuristicProcessor(check_bond_feasibility=True))
+    io.profiles['NO_FEAS_CHECK']=io.IOProfile(processor=conop.HeuristicProcessor(check_bond_feasibility=False))
         
-    e=io.LoadPDB('testfiles/pdb/simple_defective.pdb', restrict_chains="A", 
-                 profile='NO_FEAS_CHECK')
+    e1=io.LoadPDB('testfiles/pdb/simple_defective.pdb', restrict_chains="A",profile='FEAS_CHECK')
+    e2=io.LoadPDB('testfiles/pdb/simple_defective.pdb', restrict_chains="A",profile='NO_FEAS_CHECK')
+    ed=io.LoadPDB('testfiles/pdb/simple_defective.pdb', restrict_chains="A")
     
-    res=e.FindResidue('A',3)
-        
-    self.assertTrue(mol.BondExists(res.FindAtom("CA"),res.FindAtom("CB")))
+    res1=e1.FindResidue('A',3)
+    res2=e2.FindResidue('A',3)
+    resd=ed.FindResidue('A',3)
+
+    self.assertFalse(mol.BondExists(res1.FindAtom("CA"),res1.FindAtom("CB")))
+    self.assertTrue(mol.BondExists(res2.FindAtom("CA"),res2.FindAtom("CB")))
+    self.assertTrue(mol.BondExists(resd.FindAtom("CA"),resd.FindAtom("CB")))
     
 if __name__== '__main__':
   from ost import testutils
diff --git a/modules/io/tests/test_io_sdf.cc b/modules/io/tests/test_io_sdf.cc
index dcf7df6daf7afb4d5ea08bd6a19b1236f9128d91..289bdfea3a7a79247a762cb7a300eab4c6957910 100644
--- a/modules/io/tests/test_io_sdf.cc
+++ b/modules/io/tests/test_io_sdf.cc
@@ -16,11 +16,6 @@
 // along with this library; if not, write to the Free Software Foundation, Inc.,
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 //------------------------------------------------------------------------------
-#include <ost/test_utils/compare_files.hh>
-#include <ost/mol/mol.hh>
-#include <ost/io/mol/entity_io_sdf_handler.hh>
-#include <ost/io/save_entity.hh>
-#include <ost/io/io_exception.hh>
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 #include <boost/test/floating_point_comparison.hpp>
@@ -29,6 +24,12 @@
 #include <boost/algorithm/string.hpp>
 using boost::unit_test_framework::test_suite;
 
+#include <ost/test_utils/compare_files.hh>
+#include <ost/mol/mol.hh>
+#include <ost/io/mol/entity_io_sdf_handler.hh>
+#include <ost/io/save_entity.hh>
+#include <ost/io/io_exception.hh>
+
 using namespace ost;
 using namespace ost::io;
 
diff --git a/modules/io/tests/test_iomanager.cc b/modules/io/tests/test_iomanager.cc
index fc4cc0366b2a640aafbd8f569951886b78adef9f..b6e79f1fc6cda5ffc73a4990e23def87d2c5c96d 100644
--- a/modules/io/tests/test_iomanager.cc
+++ b/modules/io/tests/test_iomanager.cc
@@ -16,11 +16,11 @@
 // along with this library; if not, write to the Free Software Foundation, Inc.,
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 //------------------------------------------------------------------------------
-#include <ost/io/io_manager.hh>
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 #include <boost/test/auto_unit_test.hpp>
 using boost::unit_test_framework::test_suite;
+#include <ost/io/io_manager.hh>
 
 
 using namespace ost;
diff --git a/modules/io/tests/test_mmcif_info.cc b/modules/io/tests/test_mmcif_info.cc
index 65e4fdaecb42ec54fb50d3c579f24ba8b7ae8adb..74fca9b43f5d63beeb884c12a51698c13efffa97 100644
--- a/modules/io/tests/test_mmcif_info.cc
+++ b/modules/io/tests/test_mmcif_info.cc
@@ -17,14 +17,14 @@
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 //------------------------------------------------------------------------------
 
-#include <ost/io/io_exception.hh>
-#include <ost/io/mol/mmcif_info.hh>
-
-#define BOOST_AUTO_TEST_DYN_LINK
+#define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 #include <boost/test/auto_unit_test.hpp>
 #include <boost/test/floating_point_comparison.hpp>
 
+#include <ost/io/io_exception.hh>
+#include <ost/io/mol/mmcif_info.hh>
+
 using namespace ost;
 using namespace ost::io;
 
@@ -187,6 +187,31 @@ BOOST_AUTO_TEST_CASE(mmcif_info_structdetails)
   BOOST_MESSAGE("  done.");
 }
 
+BOOST_AUTO_TEST_CASE(mmcif_info_revisions)
+{
+  BOOST_MESSAGE("  Running mmcif_info_revisions tests...");
+
+  MMCifInfoRevisions rev = MMCifInfoRevisions();
+
+  BOOST_CHECK(rev.GetDateOriginal() == "?");
+
+  rev.SetDateOriginal("2012-05-04");
+  rev.AddRevision(1, "2012-05-04", "in preparation");
+  rev.AddRevision(2, "2012-05-05", "full release");
+
+  BOOST_CHECK(rev.GetSize() == 2);
+  BOOST_CHECK(rev.GetDateOriginal() == "2012-05-04");
+  BOOST_CHECK(rev.GetDate(0) == "2012-05-04");
+  BOOST_CHECK(rev.GetNum(0) == 1);
+  BOOST_CHECK(rev.GetStatus(0) == "in preparation");
+  BOOST_CHECK(rev.GetDate(1) == rev.GetLastDate());
+  BOOST_CHECK(rev.GetFirstRelease() == 2);
+  BOOST_CHECK(rev.GetNum(1) == 2);
+  BOOST_CHECK(rev.GetStatus(1) == "full release");  
+
+  BOOST_MESSAGE("  done.");
+}
+
 BOOST_AUTO_TEST_CASE(mmcif_info)
 {
   BOOST_MESSAGE("  Running mmcif_info tests...");
@@ -213,6 +238,8 @@ BOOST_AUTO_TEST_CASE(mmcif_info)
   BOOST_CHECK("B" == info.GetPDBMMCifChainTr("A"));
   BOOST_CHECK("" == info.GetPDBMMCifChainTr("C"));
 
+  BOOST_CHECK(info.GetRevisions().GetSize() == 0);
+
   BOOST_MESSAGE("  done.");
 }
 
diff --git a/modules/io/tests/test_mmcif_reader.cc b/modules/io/tests/test_mmcif_reader.cc
index 4c4c7cf2c572a2cafa4318b55b827b4fe3827ed1..0b9e94b5868815cb514d48c6a710711b49cf63c9 100644
--- a/modules/io/tests/test_mmcif_reader.cc
+++ b/modules/io/tests/test_mmcif_reader.cc
@@ -17,16 +17,17 @@
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 //------------------------------------------------------------------------------
 
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+#include <boost/test/auto_unit_test.hpp>
+#include <boost/test/floating_point_comparison.hpp>
+
 #include <fstream>
 #include <ost/platform.hh>
 #include <ost/io/io_exception.hh>
 #include <ost/io/mol/mmcif_reader.hh>
 #include <ost/conop/conop.hh>
 
-#define BOOST_AUTO_TEST_DYN_LINK
-#include <boost/test/unit_test.hpp>
-#include <boost/test/auto_unit_test.hpp>
-#include <boost/test/floating_point_comparison.hpp>
 
 
 using namespace ost;
diff --git a/modules/io/tests/test_star_parser.cc b/modules/io/tests/test_star_parser.cc
index 5561dd89203f14d29c45c0ba3655c1fb15919aed..4d611807830aabf0b7b24725a708f3f99d81af04 100644
--- a/modules/io/tests/test_star_parser.cc
+++ b/modules/io/tests/test_star_parser.cc
@@ -19,16 +19,17 @@
 /*
   Author: Marco Biasini
  */
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+#include <boost/test/auto_unit_test.hpp>
+#include <boost/test/floating_point_comparison.hpp>
+
 #include <fstream>
 #include <math.h>
 #include <ost/mol/mol.hh>
 #include <ost/io/io_exception.hh>
 #include <ost/io/mol/star_parser.hh>
 
-#define BOOST_AUTO_TEST_DYN_LINK
-#include <boost/test/unit_test.hpp>
-#include <boost/test/auto_unit_test.hpp>
-#include <boost/test/floating_point_comparison.hpp>
 
 
 using namespace ost;
diff --git a/modules/io/tests/testfiles/mmcif/3hqv.cif.gz b/modules/io/tests/testfiles/mmcif/3hqv.cif.gz
new file mode 100644
index 0000000000000000000000000000000000000000..c7f6bcf78e4eef0b9b0e3f27b203263a2f7c56a7
Binary files /dev/null and b/modules/io/tests/testfiles/mmcif/3hqv.cif.gz differ
diff --git a/modules/mol/alg/doc/lddt.rst b/modules/mol/alg/doc/lddt.rst
new file mode 100644
index 0000000000000000000000000000000000000000..4e36560f4ff11b16c8585fb87856b9492627ce3c
--- /dev/null
+++ b/modules/mol/alg/doc/lddt.rst
@@ -0,0 +1,158 @@
+
+===========================
+How to use the lDDT program 
+===========================
+
+-----------
+Basic Usage
+-----------
+
+To calculate the lDDT for two PDB files (mdl1.pdb and mdl2.pdb) against the reference structure stored in ref.pdb, use the following command:
+
+.. code-block:: bash
+
+    lddt mdl1.pdb mdl2.pdb ref.pdb
+
+The local and global lDDT scores for each model are printed to the terminal.
+  
+--------------------
+Model Quality Checks
+--------------------
+
+When the lddt executable is called with the -f option, the program performs some 
+stereo-chemical and steric clashing checks before computing the lDDT scores. When 
+using this option, the user must also provide a text file containing average bond 
+lengths,angle widths and minimum clashing distances. lddt ships with a default 
+parameter file based on Engh and Huber parameters, and on the atomic radii as 
+defined in the Cambridge Structural Database. This file is human readable and can 
+be modified with a text editor. The location of the file must be passed to the 
+lddt executable using the -p parameter. 
+
+For example:
+
+.. code-block:: bash
+
+    lddt -f -p stereo_chemical_params.txt mdl1.pdb mdl2.pdb ref.pdb
+
+When the model quality checks are performed, the global and local lDDT scores are 
+preceded in the output text by some information on the outcome of the tests. The 
+number of serious stereo-chemical violations and steric-clashes in the structure 
+is reported, along with some statistics on the global model quality. The local and
+global lDDT scores are also adjusted according to the outcome of the tests.  When 
+stereochemical violations or steric clashes happen in the side-chain of a residue, 
+all distances involving atoms of that side-chain are automatically considered 
+non-conserved. When the violations involve backbone atoms of a residue, all 
+distances containing atoms of the residue are considered non-conserved. 
+
+
+-----------------------
+Custom Inclusion Radius
+-----------------------
+
+The lDDT score evaluates distances between atoms lying closer than a predermined 
+inclusion radius. By default the radius is set to 15 Angstroms, but the user can 
+override this value by passing a new one to the lddt executable through the -r 
+parameter (in Angstroms):
+
+For example:
+
+.. code-block:: bash
+
+    lddt -r 10.0 mdl1.pdb mdl2.pdb ref.pdb
+
+------------------
+Consistency Checks
+------------------
+
+When comparing structures, the lddt executable does not perform any chain name 
+checks. It only processes the first chain in each structure, irrespective of the 
+name. It does, however, perform a check on residue names, to make sure that the 
+structures are correctly aligned. The lddt executable will stop with an error if 
+the names of the residues being compared do not match. If the user needs for 
+specific reasons to override this behavior and skip the check, the lddt executable 
+can be called using the -x option. For example:
+
+For example:
+
+.. code-block:: bash
+
+    lddt -x mdl1.pdb mdl2.pdb ref.pdb
+
+-------------------------
+Custom Quality Parameters
+-------------------------
+
+The lddt executable uses several thresholds to determine how serious stereo-
+chemical violations and steric clashes are. For Bonds and Angles, the parameter 
+file contains typical average lengths and widths, together with expected standard 
+deviations for their measurements in protein structures. A violation is flagged as 
+serious by lDDT when the measured value deviates from the expected one by more 
+than a predefined number of standard deviations. By default this value is 12, but 
+the user can override the default tolerance thresholds using the -b and -a flags, 
+for bonds and angles respectively. 
+
+For steric clashes, the lddt executable recovers atomic radii and clashing 
+tolerance distances from the parameter file, depending on the atomic element under 
+investigation. When an atomic element cannot be determined, the lddt executable 
+uses a default atomic radius of 1.5 Angstrom. This value can be overriden using 
+the -m value, passing a new radius (in Ansgstroms) to the program.
+
+For example:
+
+.. code-block:: bash
+
+    lddt -f -p stereo_chemical_params.txt -b 8 -a 8 -m 1.0 mdl1.pdb ref.pdb
+
+
+
+-----------------------------
+Multiple Reference Structures
+-----------------------------
+
+lDDT allows the use of multiple reference structures at the same time (please see 
+the manuscript referenced above for details). In order to use multiple references, 
+simply add them to the first ref.pdb file, separated by a comma.  
+
+For example:
+
+.. code-block:: bash
+
+    lddt mdl1.pdb mdl2.pdb ref1.pdb,ref2.pdb,ref3.pdb
+
+----------------
+Output Verbosity
+----------------
+
+By default the lddt executable only outputs the values of the global and local 
+scores. However, users can tweak the verbosity of the output using the -v 
+parameters. The devault verbosity level is 0 (scores only). Other available 
+levels are: 1 (print information about non conserved distances and failed 
+quality checks, if performed) and 2 (print information on all distances and 
+all quality checks if performed)
+
+For example:
+
+.. code-block:: bash
+
+    lddt -v 1 -f -p stereo_chemical_params.txt mdl1.pdb mdl2.pdb ref.pdb
+
+WARNING: Verbosity levels 1 and 2 can generate a large amount of output text, 
+especially with large structures and multiple models being evaluated. 
+
+
+
+
+-------------
+Other Options
+-------------
+
+The lddt executable supports several other command line options. Some can be used 
+to select subsets of atoms in the input structures, others to exclude from the 
+calculation distances between residues that are too close in the amino-acid chain, 
+and many more. In order to see a complete list, just call the program without any 
+input parameters.
+
+.. code-block:: bash
+
+    lddt
+
diff --git a/modules/mol/alg/doc/molalg.rst b/modules/mol/alg/doc/molalg.rst
index 66b14294022870a6dfe967ce407994388ef6679d..5a3e5e7c9ac93646263e05e18b45e198bcb734b3 100644
--- a/modules/mol/alg/doc/molalg.rst
+++ b/modules/mol/alg/doc/molalg.rst
@@ -276,7 +276,7 @@ The following function detects steric clashes in atomic structures. Two atoms ar
     :param clash_distance: minimum clashing distance (in Angstroms)
     :param tolerance: tolerance threshold (in Angstroms)
 
-  .. method GetClashingDistance()
+  .. method:: GetClashingDistance()
 
      Recovers a reference distance and a tolerance threshold from the list
 
@@ -285,6 +285,15 @@ The following function detects steric clashes in atomic structures. Two atoms ar
 
     :returns: a tuple containing the minimum clashing distance and the tolerance threshold
 
+  .. method:: GetAdjustedClashingDistance()
+
+     Recovers a reference distance from the list, already adjusted by the tolerance threshold
+
+    :param ele1: string containing the first element's name
+    :param ele2: string containing the second element's name
+
+    :returns: the adjusted minimum clashing distance
+
   .. method::  GetMaxAdjustedDistance()
  
     Returns the longest clashing distance in the list, after adjustment with tolerance threshold    
diff --git a/modules/mol/alg/pymod/__init__.py b/modules/mol/alg/pymod/__init__.py
index 126d0196f2d6ff25148a6724df5dd63a1e764d6a..b8c09d51d67b99b606ddc9c99af55afe37823dd4 100644
--- a/modules/mol/alg/pymod/__init__.py
+++ b/modules/mol/alg/pymod/__init__.py
@@ -6,11 +6,11 @@ import ost.mol.alg.structure_analysis
 import ost.mol.alg.helix_kinks
 
 # Fills a list of reference clashing distances from a file (requires a path to the file)
-def FillClashingDistancesFromFile(filename,default_clashing_distance,default_tolerance):
+def FillClashingDistancesFromFile(filename):
   fh=open(filename,'r')
   lines=fh.readlines()
   fh.close()
-  return FillClashingDistances(lines,default_clashing_distance,default_tolerance)
+  return FillClashingDistances(lines)
 
 # Fills a list of bond stereo-chemical statistics from a file (requires a path to the file)
 def FillBondStereoChemicalParamsFromFile(filename):
@@ -33,7 +33,7 @@ def DefaultClashingDistances():
   fh=open(filename,'r')
   lines=fh.readlines()
   fh.close()
-  return FillClashingDistances(lines,1.5,0.0)
+  return FillClashingDistances(lines)
 
 # Returns the default list of bond stereo-chemical statistics (from the default OpenStructure parameter file)
 def DefaultBondStereoChemicalParams():
diff --git a/modules/mol/alg/pymod/export_structure_analysis.cc b/modules/mol/alg/pymod/export_structure_analysis.cc
index 85fbc230d34a1a568b1565672278b61a85a1b5b6..f9f58347d1313d30d7a6d71f20e9733c2df243bc 100644
--- a/modules/mol/alg/pymod/export_structure_analysis.cc
+++ b/modules/mol/alg/pymod/export_structure_analysis.cc
@@ -31,5 +31,5 @@ void export_StructureAnalysis()
   def("CalculateAverageAgreementWithDensityMap",&CalculateAverageAgreementWithDensityMap,(arg("pos_list"),arg("density_map")));
   def("CalculateAgreementWithDensityMap",&CalculateAgreementWithDensityMap,(arg("pos_list"),arg("density_map")));
 #endif
-  def("WrapEntityInPeriodicCell",&WrapEntityInPeriodicCell,(arg("Entity"),arg("cell_center"),arg("nasis_vec")));
+  def("WrapEntityInPeriodicCell",&WrapEntityInPeriodicCell,(arg("Entity"),arg("cell_center"),arg("basis_vec"),arg("group_res")=true));
 }
diff --git a/modules/mol/alg/pymod/structure_analysis.py b/modules/mol/alg/pymod/structure_analysis.py
index 7cbd0dd4b32bb7e6f4093ed23bbbb52a700fc320..dbbc1d9df707d04c0e89e89f753ad9ed449c2292 100644
--- a/modules/mol/alg/pymod/structure_analysis.py
+++ b/modules/mol/alg/pymod/structure_analysis.py
@@ -129,3 +129,33 @@ def CalculateHelixAxis(sele1):
   f=GetFrameFromEntity(eh)
   return f.FitCylinder(sele1)
 
+
+def CalculateDistanceDifferenceMatrix(sele1,sele2):
+  """
+  This function calculates the pairwise distance differences between two EntityViews.
+  The two EntityViews should have the same number of atoms
+  It returns an NxN DistanceDifferenceMatrix M (where N is the number of atoms in sele1)
+  where M[i,j]=(sele2.atoms[i].pos-sele2.atoms[j].pos)-(sele1.atoms[i].pos-sele1.atoms[j].pos)
+  """
+  try:import numpy as npy
+  except ImportError:
+    LogError("Function needs numpy, but I could not import it.")
+    raise
+  if not sele1.IsValid() and sele2.IsValid():
+    print 'invalid view'
+    return
+  if not sele1.GetAtomCount()==sele2.GetAtomCount():
+    print 'The two views must have the same number of atoms'
+    return
+  n_atoms=sele1.GetAtomCount()
+  M=npy.zeros([n_atoms,n_atoms])
+  for i,a1 in enumerate(sele1.atoms):
+    for j,a2 in enumerate(sele2.atoms):
+      if i>=j:continue
+      d1=geom.Distance(a1.pos,a2.pos)
+      d2=geom.Distance(sele2.atoms[i].pos,sele2.atoms[j].pos)
+      M[i,j]=d2-d1
+      M[j,i]=d2-d1
+  return M
+
+
diff --git a/modules/mol/alg/pymod/trajectory_analysis.py b/modules/mol/alg/pymod/trajectory_analysis.py
index b445b02351775b92ba66cf80655f63610999569f..064135c32684bf0fcb6cc068e38673ae432fcb02 100644
--- a/modules/mol/alg/pymod/trajectory_analysis.py
+++ b/modules/mol/alg/pymod/trajectory_analysis.py
@@ -196,4 +196,20 @@ def DistRMSDFromTraj(t,sele,ref_sele,radius=7.0,average=False,seq_sep=4,first=0,
     LogError("Function needs numpy, but I could not import it.")
     raise
     
+def AverageDistanceMatrixFromTraj(t,sele,first=0,last=-1):
+  try:
+    import numpy as npy
+  except ImportError:
+    LogError("Function needs numpy, but I could not import it.")
+    raise
+  n_atoms=sele.GetAtomCount()
+  M=npy.zeros([n_atoms,n_atoms])
+  for i,a1 in enumerate(sele.atoms):
+    for j,a2 in enumerate(sele.atoms):
+      d=ost.mol.alg.AnalyzeDistanceBetwAtoms(t,a1.GetHandle(),a2.GetHandle())[first:last]
+      M[i,j]=npy.mean(d)
+      M[j,i]=npy.mean(d)
+  return M
+
+
     
\ No newline at end of file
diff --git a/modules/mol/alg/pymod/wrap_mol_alg.cc b/modules/mol/alg/pymod/wrap_mol_alg.cc
index 08ad6631efe89ce483e9cc653c2baec321db6927..bdf141aa55b89e2a3a28235f8432c87b21702045 100644
--- a/modules/mol/alg/pymod/wrap_mol_alg.cc
+++ b/modules/mol/alg/pymod/wrap_mol_alg.cc
@@ -24,6 +24,7 @@
 #include <ost/mol/alg/superpose_frames.hh>
 #include <ost/mol/alg/filter_clashes.hh>
 #include <ost/mol/alg/consistency_checks.hh>
+#include <ost/export_helper/pair_to_tuple_conv.hh>
 
 using namespace boost::python;
 using namespace ost;
@@ -60,7 +61,7 @@ ost::mol::alg::StereoChemicalParams fill_stereochemical_params_wrapper (const St
   return ost::mol::alg::FillStereoChemicalParams(header,stereo_chemical_props_file_vector);
 }
 
-ost::mol::alg::ClashingDistances fill_clashing_distances_wrapper (const list& stereo_chemical_props_file, Real min_default_distance, Real min_distance_tolerance)  
+ost::mol::alg::ClashingDistances fill_clashing_distances_wrapper (const list& stereo_chemical_props_file)
 {
   int stereo_chemical_props_file_length = boost::python::extract<int>(stereo_chemical_props_file.attr("__len__")());
   std::vector<String> stereo_chemical_props_file_vector(stereo_chemical_props_file_length);
@@ -103,6 +104,9 @@ BOOST_PYTHON_MODULE(_ost_mol_alg)
   export_entity_to_density();
   #endif
   
+  to_python_converter<std::pair<Real,Real>,
+                      PairToTupleConverter<Real, Real> >();
+
   def("LocalDistDiffTest", lddt_a, (arg("sequence_separation")=0,arg("local_lddt_property_string")=""));
   def("LocalDistDiffTest", lddt_c, (arg("local_lddt_property_string")=""));
   def("LocalDistDiffTest", lddt_b, (arg("ref_index")=0, arg("mdl_index")=1));
@@ -124,6 +128,7 @@ BOOST_PYTHON_MODULE(_ost_mol_alg)
   class_<mol::alg::ClashingDistances> ("ClashingDistances",init<>())
     .def("SetClashingDistance",&mol::alg::ClashingDistances::SetClashingDistance)
     .def("GetClashingDistance",&mol::alg::ClashingDistances::GetClashingDistance)
+    .def("GetAdjustedClashingDistance",&mol::alg::ClashingDistances::GetAdjustedClashingDistance)
     .def("GetMaxAdjustedDistance",&mol::alg::ClashingDistances::GetMaxAdjustedDistance)    
     .def("IsEmpty",&mol::alg::ClashingDistances::IsEmpty)  
     
diff --git a/modules/mol/alg/src/entity_to_density.cc b/modules/mol/alg/src/entity_to_density.cc
index a01bd49c173f2f9c6ad2a76ac7c0465df49edfe2..118653ccedcfefb53b66be9f1e420d3926ae1d5f 100644
--- a/modules/mol/alg/src/entity_to_density.cc
+++ b/modules/mol/alg/src/entity_to_density.cc
@@ -123,7 +123,7 @@ public:
     uint y_limit = ceil(falloff_end_frequency_ / frequency_sampling[1]);
     uint z_limit = ceil(falloff_end_frequency_ / frequency_sampling[2]);
      img::Extent reduced_extent = img::Extent
-             (img::Point(-x_limit,-y_limit,0),
+             (img::Point(-static_cast<int>(x_limit),-static_cast<int>(y_limit),0),
               img::Point(x_limit,y_limit,z_limit));
 
     mol::AtomViewIter iterator_end = entity_view_.AtomsEnd();
diff --git a/modules/mol/alg/src/filter_clashes.cc b/modules/mol/alg/src/filter_clashes.cc
index 27ffb844853f7d68821d3356ec6895ef4389b4f1..e37728879304aa5abd1fb094848b34b9b05f83d9 100644
--- a/modules/mol/alg/src/filter_clashes.cc
+++ b/modules/mol/alg/src/filter_clashes.cc
@@ -19,6 +19,7 @@
 #include <ost/log.hh>
 #include <ost/mol/mol.hh>
 #include <sstream>
+#include <iomanip>
 #include <math.h>
 #include "filter_clashes.hh"
 #include <ost/units.hh>
@@ -107,6 +108,12 @@ std::pair<Real,Real> ClashingDistances::GetClashingDistance(const String& ele1,c
   return find_ci->second;
 }
 
+Real ClashingDistances::GetAdjustedClashingDistance(const String& ele1,const String& ele2) const
+{
+  std::pair <Real,Real> clash_dist = GetClashingDistance(ele1,ele2);
+  return clash_dist.first-clash_dist.second;
+}
+
 void ClashingDistances::PrintAllDistances() const
 {
    for (std::map <String,std::pair<float,float> >::const_iterator index = min_distance_.begin();index != min_distance_.end();++index) {
@@ -460,6 +467,7 @@ EntityView CheckStereoChemistry(const EntityView& ent, const StereoChemicalParam
     
     if (remove_bb) {
       LOG_INFO("ACTION: removing whole residue " << res);
+      res.SetBoolProp("stereo_chemical_violation_backbone",true);
       continue;
     }
     if (remove_sc) {
@@ -472,13 +480,14 @@ EntityView CheckStereoChemistry(const EntityView& ent, const StereoChemicalParam
          filtered.AddAtom(atom);
        }
       }
+      res.SetBoolProp("stereo_chemical_violation_sidechain",true);
       continue;
     }
     filtered.AddResidue(res, ViewAddFlag::INCLUDE_ATOMS);
   }
   Real avg_zscore_bonds = running_sum_zscore_bonds/static_cast<float>(bond_count);
   Real avg_zscore_angles = running_sum_zscore_angles/static_cast<float>(angle_count);
-  LOG_SCRIPT("Average Z-Score for bond lengths: " << avg_zscore_bonds);
+  LOG_SCRIPT("Average Z-Score for bond lengths: " << std::fixed << std::setprecision(5) << avg_zscore_bonds);
   LOG_SCRIPT("Bonds outside of tolerance range: " << bad_bond_count << " out of " << bond_count);
   LOG_SCRIPT("Bond\tAvg Length\tAvg zscore\tNum Bonds")
 
@@ -489,9 +498,9 @@ EntityView CheckStereoChemistry(const EntityView& ent, const StereoChemicalParam
     Real sum_bond_zscore=bond_zscore_sum[key];
     Real avg_length=sum_bond_length/static_cast<Real>(counter);
     Real avg_zscore=sum_bond_zscore/static_cast<Real>(counter);
-    LOG_SCRIPT(key << "\t" << avg_length << "\t" << avg_zscore << "\t" << counter);
+    LOG_SCRIPT(key << "\t" << std::fixed << std::setprecision(5) << std::left << std::setw(10) << avg_length << "\t" << std::left << std::setw(10) << avg_zscore << "\t" << counter);
   }
-  LOG_SCRIPT("Average Z-Score angle widths: " << avg_zscore_angles);
+  LOG_SCRIPT("Average Z-Score angle widths: " << std::fixed << std::setprecision(5) << avg_zscore_angles);
   LOG_SCRIPT("Angles outside of tolerance range: " << bad_angle_count << " out of " << angle_count);
   return filtered;
 }
@@ -575,6 +584,7 @@ EntityView FilterClashes(const EntityView& ent, const ClashingDistances& min_dis
     
     if (remove_bb) {
       LOG_VERBOSE("ACTION: removing whole residue " << res);
+      res.SetBoolProp("steric_clash",true);
       continue;
     }
     if (remove_sc) {
@@ -587,6 +597,7 @@ EntityView FilterClashes(const EntityView& ent, const ClashingDistances& min_dis
          filtered.AddAtom(atom);
        }
       }
+      res.SetBoolProp("steric_clash",true);
       continue;
     }
     filtered.AddResidue(res, ViewAddFlag::INCLUDE_ATOMS);
@@ -596,7 +607,7 @@ EntityView FilterClashes(const EntityView& ent, const ClashingDistances& min_dis
     average_offset = average_offset_sum / static_cast<Real>(bad_distance_count);
   }
   LOG_SCRIPT(bad_distance_count << " non-bonded short-range distances shorter than tolerance distance");
-  LOG_SCRIPT("Distances shorter than tolerance are on average shorter by: " << average_offset);
+  LOG_SCRIPT("Distances shorter than tolerance are on average shorter by: " << std::fixed << std::setprecision(5) << average_offset);
   return filtered;
 }
 
diff --git a/modules/mol/alg/src/filter_clashes.hh b/modules/mol/alg/src/filter_clashes.hh
index f9d7473b6ce1eb0d5044c6f46a4bebadc86bff83..e294cd4895ad9790a3b001a73873f8b7b4812cc8 100644
--- a/modules/mol/alg/src/filter_clashes.hh
+++ b/modules/mol/alg/src/filter_clashes.hh
@@ -40,6 +40,9 @@ public:
   /// \brief Recovers a reference distance and a tolerance threshold (respectively) from the list
   std::pair<Real,Real> GetClashingDistance(const String& ele1,const String& ele2) const;
 
+  /// \brief Recovers a reference distance already adjusted by the tolerance threshold from the list
+  Real GetAdjustedClashingDistance(const String& ele1,const String& ele2) const;
+
   /// \brief Recovers the longest distance in the list, corrected by tolerance
   Real GetMaxAdjustedDistance() const;
 
diff --git a/modules/mol/alg/src/lddt.cc b/modules/mol/alg/src/lddt.cc
index 15add8e111bf49eb1aa2cee6a00d3e7c7723d7eb..4a82818dc47e1aa5850bc0b5791a71498dbac9f4 100644
--- a/modules/mol/alg/src/lddt.cc
+++ b/modules/mol/alg/src/lddt.cc
@@ -66,7 +66,7 @@ EntityHandle load(const String& file, const IOProfile& profile)
       }
 
       if (ent.GetChainList().size()!=1) {
-        std::cout << "WARNING: File " << file << "has more than one chain" << std::endl; 
+        std::cout << "WARNING: File " << file << " has more than one chain" << std::endl;
       }    
       return ent;
     }
@@ -164,6 +164,17 @@ CompoundLibPtr load_compound_lib(const String& custom_path)
   }
   return CompoundLibPtr();
 }
+bool is_resnum_in_globalrdmap(const ResNum& resnum, const GlobalRDMap& glob_dist_list)
+{
+  for (GlobalRDMap::const_iterator i=glob_dist_list.begin(), e=glob_dist_list.end(); i!=e; ++i) {
+    ResNum rn = i->first;
+    if (rn==resnum) {
+      return true;
+    }
+  }
+  return false;
+}
+
 int main (int argc, char **argv)
 {
   // sets some default values for parameters
@@ -302,8 +313,9 @@ int main (int argc, char **argv)
     if (!ref) {
       exit(-1);
     }  
-    ref_list.push_back(ref.CreateFullView());
-    glob_dist_list = CreateDistanceList(ref.CreateFullView(),radius);  
+    EntityView refview=ref.GetChainList()[0].Select("peptide=true");
+    ref_list.push_back(refview);
+    glob_dist_list = CreateDistanceList(refview,radius);
   } else {
     std::cout << "Multi-reference mode: On" << std::endl;  
     for (std::vector<StringRef>::const_iterator ref_file_split_sr_it = ref_file_split_sr.begin();
@@ -313,12 +325,13 @@ int main (int argc, char **argv)
       if (!ref) {
         exit(-1);
       }
-      if (ref_list.size()>0) {
+      if (! ref_list.empty()) {
         if (ref_list[0].GetChainList()[0].GetName()!=ref.GetChainList()[0].GetName()) {
           std::cout << "ERROR: First chains in the reference structures have different names" << std::endl;
           exit(-1);  
         }    
       }
+      EntityView refview=ref.GetChainList()[0].Select("peptide=true");
       ref_list.push_back(ref.CreateFullView());
     } 
     glob_dist_list = CreateDistanceListFromMultipleReferences (ref_list,cutoffs,sequence_separation,radius);  
@@ -354,8 +367,8 @@ int main (int argc, char **argv)
       }
       continue;
     }
-    EntityView v=model.CreateFullView();
-
+    EntityView v=model.GetChainList()[0].Select("peptide=true");
+    EntityView outv=model.GetChainList()[0].Select("peptide=true");
     for (std::vector<EntityView>::const_iterator ref_list_it = ref_list.begin();
          ref_list_it != ref_list.end(); ++ref_list_it) {
       bool cons_check = ResidueNamesMatch(v,*ref_list_it);
@@ -416,8 +429,6 @@ int main (int argc, char **argv)
         std::cout << e.what() << std::endl;
         exit(-1);
       }
-      cov = compute_coverage(v,glob_dist_list);
-      std::cout << "Coverage after stereo-chemical checks: " << (float(cov.first)/float(cov.second)) << " (" << cov.first << " out of " << cov.second << " residues)" << std::endl;
       try {
         v=alg::FilterClashes(v,nonbonded_table);
       } catch (std::exception& e) {       
@@ -425,8 +436,6 @@ int main (int argc, char **argv)
         std::cout << e.what() << std::endl;
         exit(-1);
       }
-      cov = compute_coverage(v,glob_dist_list);
-      std::cout << "Coverage after clashing checks: " << (float(cov.first)/float(cov.second)) << " (" << cov.first << " out of " << cov.second << " residues)" << std::endl;
     }
     if (cov.first==0) {
       std::cout << "Global LDDT score: 0.0" << std::endl;
@@ -442,20 +451,67 @@ int main (int argc, char **argv)
               << " checked, over " << cutoffs.size() << " thresholds)" << std::endl;
 
     // prints the residue-by-residue statistics  
-    std::cout << "Local LDDT Score:" << std::endl;
-    std::cout << "Chain\tResName\tResNum\tScore\t(Conserved/Total, over " << cutoffs.size() << " thresholds)" << std::endl;
-    for (ResidueViewIter rit=v.ResiduesBegin();rit!=v.ResiduesEnd();++rit){
-      ResidueView ritv = *rit;
-      Real lddt_local = 0;
-      int conserved_dist = 0;
-      int total_dist = 0;      
-      if (ritv.HasProp(label)) {
+    if (structural_checks) {
+      std::cout << "Local LDDT Scores:" << std::endl;
+      std::cout << "(A 'Yes' in the 'Quality Problems' column stands for problems" << std::endl;
+      std::cout << "in the side-chain of a residue, while a 'Yes+' for problems" << std::endl;
+      std::cout << "in the backbone)" << std::endl;
+    } else {
+      std::cout << "Local LDDT Scores:" << std::endl;
+    }
+    if (structural_checks) {
+      std::cout << "Chain\tResName\tResNum\tAsses.\tQ.Prob.\tScore\t(Conserved/Total, over " << cutoffs.size() << " thresholds)" << std::endl;
+    } else {
+      std::cout << "Chain\tResName\tResNum\tAsses.\tScore\t(Conserved/Total, over " << cutoffs.size() << " thresholds)" << std::endl;
+    }
+    for (ResidueViewIter rit=outv.ResiduesBegin();rit!=outv.ResiduesEnd();++rit){
+      ResidueView ritv=*rit;
+      ResNum rnum = ritv.GetNumber();
+      bool assessed = false;
+      String assessed_string="No";
+      bool quality_problems = false;
+      String quality_problems_string="No";
+      Real lddt_local = -1;
+      String lddt_local_string="-";
+      int conserved_dist = -1;
+      int total_dist = -1;
+      String dist_string = "-";
+      if (is_resnum_in_globalrdmap(rnum,glob_dist_list)) {
+        assessed = true;
+        assessed_string="Yes";
+      }
+      if (ritv.HasProp("stereo_chemical_violation_sidechain") || ritv.HasProp("steric_clash_sidechain")) {
+        quality_problems = true;
+        quality_problems_string="Yes";
+      }
+      if (ritv.HasProp("stereo_chemical_violation_backbone") || ritv.HasProp("steric_clash_backbone")) {
+        quality_problems = true;
+        quality_problems_string="Yes+";
+      }
+
+      if (assessed==true) {
+        if (ritv.HasProp(label)) {
           lddt_local=ritv.GetFloatProp(label);
+          std::stringstream stkeylddt;
+          stkeylddt <<  std::fixed << std::setprecision(4) << lddt_local;
+          lddt_local_string=stkeylddt.str();
           conserved_dist=ritv.GetIntProp(label+"_conserved");
-      total_dist=ritv.GetIntProp(label+"_total");
+          total_dist=ritv.GetIntProp(label+"_total");
+          std::stringstream stkeydist;
+          stkeydist << "("<< conserved_dist << "/" << total_dist << ")";
+          dist_string=stkeydist.str();
+        } else {
+          lddt_local = 0;
+          lddt_local_string="0.0000";
+          conserved_dist = 0;
+          total_dist = 0;
+          dist_string="(0/0)";
+        }
       }
-      if (lddt_local!=0) {
-        std::cout << ritv.GetChain() << "\t" << ritv.GetName() << "\t" << ritv.GetNumber() << '\t' << std::setprecision(4) << lddt_local << "\t" << "("<< conserved_dist << "/" << total_dist << ")" <<std::endl;
+      if (structural_checks) {
+        std::cout << ritv.GetChain() << "\t" << ritv.GetName() << "\t" << ritv.GetNumber() << '\t' << assessed_string  << '\t' << quality_problems_string << '\t' << lddt_local_string << "\t" << dist_string << std::endl;
+      } else {
+        std::cout << ritv.GetChain() << "\t" << ritv.GetName() << "\t" << ritv.GetNumber() << '\t' << assessed_string  << '\t' << lddt_local_string << "\t" << dist_string << std::endl;
       }
     }
     std::cout << std::endl;
diff --git a/modules/mol/alg/src/structure_analysis.cc b/modules/mol/alg/src/structure_analysis.cc
index 50689dfca3a27c1a62ef999e5ce9a048baeeffda..de7a176b13a98c7a0257dea47df463530bb01904 100644
--- a/modules/mol/alg/src/structure_analysis.cc
+++ b/modules/mol/alg/src/structure_analysis.cc
@@ -61,12 +61,21 @@ Real CalculateAverageAgreementWithDensityMap(const geom::Vec3List& vl, img::MapH
 }
 
 #endif
-void DLLEXPORT_OST_MOL_ALG WrapEntityInPeriodicCell(EntityHandle eh, const geom::Vec3 cell_center, const geom::Vec3 basis_vec){
+void DLLEXPORT_OST_MOL_ALG WrapEntityInPeriodicCell(EntityHandle eh, const geom::Vec3 cell_center, const geom::Vec3 basis_vec, bool group_residues){
   mol::XCSEditor edi=eh.EditXCS(mol::BUFFERED_EDIT);
   geom::Vec3 cm,wrapped_cm,shift;
-  edi=eh.EditXCS();
   ResidueHandleList residues=eh.GetResidueList();
   unsigned int n_residues=eh.GetResidueCount();
+  if (group_residues) {
+    for (unsigned int i=0; i<n_residues; ++i) {
+      ResidueHandle r=residues[i];
+      AtomHandleList atoms=r.GetAtomList();
+      geom::Vec3 ref_pos=atoms[0].GetPos();
+      for (AtomHandleList::iterator a=atoms.begin(), e=atoms.end(); a!=e; ++a) {
+        edi.SetAtomPos((*a),geom::WrapVec3((*a).GetPos(),ref_pos,basis_vec));
+      }
+    }
+  }
   for (unsigned int i=0; i<n_residues; ++i) {
     ResidueHandle r=residues[i];
     cm=r.GetCenterOfMass();
diff --git a/modules/mol/alg/src/structure_analysis.hh b/modules/mol/alg/src/structure_analysis.hh
index 45cb601f8b32ba80656d031a211f5672202f4aed..7ad8ad575cb0ebdb448e800748408f251fd69c49 100644
--- a/modules/mol/alg/src/structure_analysis.hh
+++ b/modules/mol/alg/src/structure_analysis.hh
@@ -37,6 +37,6 @@ namespace ost { namespace mol { namespace alg {
   std::vector<Real> DLLEXPORT_OST_MOL_ALG CalculateAgreementWithDensityMap(const geom::Vec3List& vl, img::MapHandle& density_map);
   Real DLLEXPORT_OST_MOL_ALG CalculateAverageAgreementWithDensityMap(const geom::Vec3List& vl, img::MapHandle& density_map);
 #endif
-  void DLLEXPORT_OST_MOL_ALG WrapEntityInPeriodicCell(EntityHandle eh, const geom::Vec3 cell_center, const geom::Vec3 basis_vec);
+  void DLLEXPORT_OST_MOL_ALG WrapEntityInPeriodicCell(EntityHandle eh, const geom::Vec3 cell_center, const geom::Vec3 basis_vec, bool group_res=true);
 }}}//ns
 #endif
diff --git a/modules/mol/alg/src/trajectory_analysis.cc b/modules/mol/alg/src/trajectory_analysis.cc
index a4ce2026b2248fd2ea8144c170e13b2cca46198f..96dd5fabb0599b77fb68fa4d9ca8dea94a8de313 100644
--- a/modules/mol/alg/src/trajectory_analysis.cc
+++ b/modules/mol/alg/src/trajectory_analysis.cc
@@ -159,10 +159,10 @@ std::vector<Real>  AnalyzeMinDistance(const CoordGroupHandle& traj, const Entity
 // each frame in a trajectory and returns it as a vector.
   {
   CheckHandleValidity(traj);
-  if (view1.GetAtomCount()==0){
+  if (!view1.HasAtoms()){
     throw Error("first EntityView is empty");
   }
-  if (view2.GetAtomCount()==0){
+  if (!view2.HasAtoms()){
     throw Error("second EntityView is empty");
   }  
   std::vector<Real> dist;
@@ -183,10 +183,10 @@ std::vector<Real> AnalyzeMinDistanceBetwCenterOfMassAndView(const CoordGroupHand
   // of a second set of atoms (view_cm) for each frame in a trajectory and returns it as a vector.
   {
   CheckHandleValidity(traj);
-  if (view_cm.GetAtomCount()==0){
+  if (!view_cm.HasAtoms()){
     throw Error("first EntityView is empty");
   }
-  if (view_atoms.GetAtomCount()==0){
+  if (!view_atoms.HasAtoms()){
     throw Error("second EntityView is empty");
   } 
   std::vector<Real> dist, masses_cm;
@@ -210,10 +210,10 @@ std::vector<Real> AnalyzeAromaticRingInteraction(const CoordGroupHandle& traj, c
   // center of mass - heavy atom distance betweent he two rings
   {
   CheckHandleValidity(traj);
-  if (view_ring1.GetAtomCount()==0){
+  if (!view_ring1.HasAtoms()){
     throw Error("first EntityView is empty");
   }
-  if (view_ring2.GetAtomCount()==0){
+  if (!view_ring2.HasAtoms()){
     throw Error("second EntityView is empty");
   } 
   std::vector<Real> dist, masses_ring1,masses_ring2;
@@ -238,7 +238,7 @@ std::vector<Real> AnalyzeAromaticRingInteraction(const CoordGroupHandle& traj, c
   //the last residue of the selection, usually the direction of the alpha-helix
   {
     CheckHandleValidity(traj);
-    if (prot_seg.GetAtomCount()==0){
+    if (!prot_seg.HasAtoms()){
       throw Error("EntityView is empty");
     }
     std::vector<unsigned long> indices_ca;
@@ -265,7 +265,7 @@ std::vector<Real> AnalyzeAromaticRingInteraction(const CoordGroupHandle& traj, c
                           geom::Vec3List& centers, unsigned int stride)
   {
     CheckHandleValidity(traj);
-    if (prot_seg.GetAtomCount()==0){
+    if (!prot_seg.HasAtoms()){
       throw Error("EntityView is empty");
     }
     std::vector<unsigned long> indices_ca;
@@ -286,7 +286,7 @@ std::vector<Real> AnalyzeAromaticRingInteraction(const CoordGroupHandle& traj, c
                           geom::Vec3List& origins, unsigned int stride)
   {
     CheckHandleValidity(traj);
-    if (prot_seg.GetAtomCount()==0){
+    if (!prot_seg.HasAtoms()){
       throw Error("EntityView is empty");
     }
     std::vector<unsigned long> indices_ca;
@@ -307,7 +307,7 @@ std::vector<Real> AnalyzeAromaticRingInteraction(const CoordGroupHandle& traj, c
                                     unsigned int stride)
   {
     CheckHandleValidity(traj);
-    if (prot_seg.GetAtomCount()==0){
+    if (!prot_seg.HasAtoms()){
       throw Error("EntityView is empty");
     }
     std::vector<unsigned long> indices_c,indices_o, indices_n, indices_ca;
@@ -331,7 +331,7 @@ std::vector<Real> AnalyzeAromaticRingInteraction(const CoordGroupHandle& traj, c
     if (to<from) {
       throw Error("to smaller than from");
     }
-    unsigned int n_frames=ceil((to-from)/stride);
+    unsigned int n_frames=ceil((to-from)/static_cast<Real>(stride));
     if (n_atoms==0){
       throw Error("EntityView is empty");
     }
@@ -370,7 +370,7 @@ std::vector<Real> AnalyzeAromaticRingInteraction(const CoordGroupHandle& traj, c
     if (to<from) {
       throw Error("to smaller than from");
     }
-    unsigned int n_frames=ceil((to-from)/stride);
+    unsigned int n_frames=ceil((to-from)/static_cast<Real>(stride));
     if (n_atoms==0){
       throw Error("EntityView is empty");
     }
diff --git a/modules/mol/alg/tests/test_consistency_checks.cc b/modules/mol/alg/tests/test_consistency_checks.cc
index aad198febf3decc69d591cb16058cfe9d6e07a24..b7e3d3e4cc4742fb7df7bf28ec87287396b93a4a 100644
--- a/modules/mol/alg/tests/test_consistency_checks.cc
+++ b/modules/mol/alg/tests/test_consistency_checks.cc
@@ -20,7 +20,7 @@
 /*
  * Author Valerio Mariani
  */
-#define BOOST_TEST_MODULE ost_mol_alg
+#define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 #include <boost/test/auto_unit_test.hpp>
 
diff --git a/modules/mol/alg/tests/test_convenient_superpose.py b/modules/mol/alg/tests/test_convenient_superpose.py
index eb4331ca3e8e6b65b0201197e5755cb2e5fcab15..728f315dea87ccca22f99e399669fbf9591d35c6 100644
--- a/modules/mol/alg/tests/test_convenient_superpose.py
+++ b/modules/mol/alg/tests/test_convenient_superpose.py
@@ -1,3 +1,4 @@
+from ost import io,mol,geom
 import unittest
 import os
 import random
diff --git a/modules/mol/base/pymod/export_editors.cc b/modules/mol/base/pymod/export_editors.cc
index 68f48cb910663590c2112408f4203891bedbaf19..864cf8b2c834b1e8a33bd32fcc1466f4f43827a0 100644
--- a/modules/mol/base/pymod/export_editors.cc
+++ b/modules/mol/base/pymod/export_editors.cc
@@ -80,6 +80,8 @@ void (ICSEditor::*rotate_torsion_b)(const AtomHandle&, const AtomHandle&,
                                     const AtomHandle&, const AtomHandle&,
                                     Real, bool)=&ICSEditor::RotateTorsionAngle;
 
+void (EditorBase::*renumber_chain_a)(ChainHandle,const ResNumList&)=&EditorBase::RenumberChain;
+void (EditorBase::*renumber_chain_b)(const ChainHandle&,int, bool)=&EditorBase::RenumberChain;
 #if OST_NUMPY_SUPPORT_ENABLED
 template<typename T, bool O>
 void set_pos2_nc_t(XCSEditor& e, const AtomHandleList& alist, PyArrayObject* na)
@@ -248,7 +250,9 @@ void export_Editors()
     .def("AddTorsion", &EditorBase::AddTorsion)
     .def("ReorderResidues",&EditorBase::ReorderResidues)
     .def("ReorderAllResidues",&EditorBase::ReorderAllResidues)
-    .def("RenumberChain",&EditorBase::RenumberChain)
+    .def("RenumberAllResidues",&EditorBase::RenumberAllResidues)
+    .def("RenumberChain",renumber_chain_a)
+    .def("RenumberChain",renumber_chain_b)
   ;
   
   void (XCSEditor::*apply_transform1)(const geom::Mat4&) = &XCSEditor::ApplyTransform;
@@ -265,7 +269,9 @@ void export_Editors()
     .def("SetTransform", set_transform1)
     .def("SetTransform", set_transform2)
     .def("UpdateICS", &XCSEditor::UpdateICS)
-    .def("__exit__", &XCSEditor::UpdateICS)    
+    .def("ForceUpdate", &XCSEditor::ForceUpdate)
+    .def("__exit__", &XCSEditor::ForceUpdate)    
+    .def("__del__", &XCSEditor::ForceUpdate)    
   ;
   
   class_<ICSEditor, bases<EditorBase> >("ICSEditor", no_init)
diff --git a/modules/mol/base/pymod/export_entity.cc b/modules/mol/base/pymod/export_entity.cc
index bb55d9bd68234616da9d4bf69d646adccf559d71..0373b2590e3ea66f3067b2ae0234df9891783fbb 100644
--- a/modules/mol/base/pymod/export_entity.cc
+++ b/modules/mol/base/pymod/export_entity.cc
@@ -197,6 +197,7 @@ void export_Entity()
     .add_property("transform",&EntityHandle::GetTransform,&EntityHandle::SetTransform)
     .def("HasTransform",&EntityHandle::HasTransform)
     .def("ClearTransform",&EntityHandle::ClearTransform)
+    .def("FixTransform",&EntityHandle::FixTransform)
     .def("EditXCS", &EntityHandle::EditXCS, arg("mode")=UNBUFFERED_EDIT)
     .def("EditICS", &EntityHandle::EditICS, arg("mode")=UNBUFFERED_EDIT)
     .def("RequestXCSEditor", &depr_request_xcs_editor, arg("mode")=UNBUFFERED_EDIT)
diff --git a/modules/mol/base/pymod/export_entity_view.cc b/modules/mol/base/pymod/export_entity_view.cc
index 4ce29c03b4be50ba28d895fa957b25a626fbe690..fd97572869e6f935b0a3ab7b7b6226f8d850dcd9 100644
--- a/modules/mol/base/pymod/export_entity_view.cc
+++ b/modules/mol/base/pymod/export_entity_view.cc
@@ -215,4 +215,6 @@ void export_EntityView()
   class_<EntityViewList>("EntityViewList", init<>())
     .def(vector_indexing_suite<EntityViewList>())
   ;
+  to_python_converter<std::pair<EntityView, EntityView>,
+                      PairToTupleConverter<EntityView, EntityView> >();
 }
diff --git a/modules/mol/base/src/CMakeLists.txt b/modules/mol/base/src/CMakeLists.txt
index 8bb7187ebe9d229fe4aad338a71e53674e22ae3f..8d206d3c61b193deb48942e563baadb31c4c5aa4 100644
--- a/modules/mol/base/src/CMakeLists.txt
+++ b/modules/mol/base/src/CMakeLists.txt
@@ -83,6 +83,7 @@ sec_structure.hh
 spatial_organizer.hh
 surface.hh
 surface_builder.hh
+builder.hh
 surface_handle.hh
 surface_prop.hh
 torsion_handle.hh
diff --git a/modules/mol/base/src/builder.hh b/modules/mol/base/src/builder.hh
new file mode 100644
index 0000000000000000000000000000000000000000..0a652a8b010ac97182a50e79591c00f6c3c6b81d
--- /dev/null
+++ b/modules/mol/base/src/builder.hh
@@ -0,0 +1,77 @@
+
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+#ifndef OST_MOL_BASE_BUILDER_HH
+#define OST_MOL_BASE_BUILDER_HH
+
+#include "module_config.hh"
+
+#include "atom_handle.hh"
+#include "residue_handle.hh"
+#include "chain_handle.hh"
+#include "entity_handle.hh"
+#include "xcs_editor.hh"
+
+
+namespace ost { namespace mol {
+
+// a helper class to easily create entities
+class DLLEXPORT Builder {
+public:
+   Builder(): ent_(CreateEntity()), edi_(ent_.EditXCS(BUFFERED_EDIT)) {
+   }
+
+   // conversion to entity handle
+   operator EntityHandle() { return ent_; }
+
+   Builder& Chain(const String& name) {
+     chain_ = edi_.InsertChain(name);
+     res_ = ResidueHandle();
+     atom_ = AtomHandle();
+     return *this;
+   }
+
+   Builder& Residue(const String& name) {
+     res_ = edi_.AppendResidue(chain_, name);
+     atom_ = AtomHandle();
+     return *this;
+   }
+
+   Builder& OneLetterCode(char olc) {
+     res_.SetOneLetterCode(olc);
+     return *this;
+   }
+
+   Builder& Atom(const String& name, const geom::Vec3& pos=geom::Vec3()) {
+     edi_.InsertAtom(res_, name, pos);
+     return *this;
+   }
+private:
+   EntityHandle  ent_;
+   ChainHandle   chain_;
+   ResidueHandle res_;
+   AtomHandle    atom_;
+   XCSEditor     edi_;
+
+
+};
+
+}}
+#endif
+
diff --git a/modules/mol/base/src/chain_type.hh b/modules/mol/base/src/chain_type.hh
index 513cb1d51b3c295376d4b7094844b58967091336..82d9115f9d1653c579ec49d5538dc29399eb0551 100644
--- a/modules/mol/base/src/chain_type.hh
+++ b/modules/mol/base/src/chain_type.hh
@@ -19,6 +19,7 @@
 #ifndef OST_CHAIN_TYPE_HH
 #define OST_CHAIN_TYPE_HH
 
+#include <ost/mol/module_config.hh>
 #include <ost/base.hh>
 #include <ost/string_ref.hh>
 
diff --git a/modules/mol/base/src/chain_view.cc b/modules/mol/base/src/chain_view.cc
index 355bd6cf5963f68a3a42fdf587c7ec60f2ed9c80..b8fc1b55b23ffc281df02cd52efc104dbd7cd260 100644
--- a/modules/mol/base/src/chain_view.cc
+++ b/modules/mol/base/src/chain_view.cc
@@ -383,16 +383,18 @@ geom::Vec3 ChainView::GetCenterOfAtoms() const
 {
   this->CheckValidity();
   geom::Vec3 center;
-  if(this->GetAtomCount() > 0) {
+  if(this->HasAtoms()) {
+    int atom_count = 0;
     ResidueViewList::const_iterator i;
     for (i=data_->residues.begin(); i!=data_->residues.end(); ++i) {
       ResidueView r=*i;
       for (AtomViewList::const_iterator j=r.GetAtomList().begin(),
            e2=r.GetAtomList().end(); j!=e2; ++j) {
         center+=j->GetPos();
+        atom_count+=1;
       }
     }
-    center/=this->GetAtomCount();
+    center/=atom_count;
   }
   return center;
 }
@@ -402,7 +404,7 @@ geom::Vec3 ChainView::GetCenterOfMass() const
   this->CheckValidity();
   geom::Vec3 center;
   Real mass = this->GetMass();
-  if(this->GetAtomCount() > 0 && mass > 0) {
+  if(this->HasAtoms() && mass > 0) {
     ResidueViewList::const_iterator i;
     for (i=data_->residues.begin(); i!=data_->residues.end(); ++i) {
       ResidueView r=*i;
@@ -451,5 +453,18 @@ EntityView ChainView::Select(const String& q, QueryFlags flags) const {
   }
   else return this->GetEntity().Select(Query("cname='"+Impl()->GetName()+"'"), flags);
 }
+
+
+bool ChainView::HasAtoms() const {
+  this->CheckValidity();  
+  for (ResidueViewList::const_iterator it=data_->residues.begin(), 
+       e=data_->residues.end(); it!=e; ++it) {
+    if ((*it).HasAtoms()) {
+      return true;
+    }
+  }
+  return false;
+}
+
 }} // ns
 
diff --git a/modules/mol/base/src/chain_view.hh b/modules/mol/base/src/chain_view.hh
index 70bd305aa1c17884f062a2b0721c97cb1cea7340..3f9ea30bab6d8db628a2152bc8a8a08fccfd4691 100644
--- a/modules/mol/base/src/chain_view.hh
+++ b/modules/mol/base/src/chain_view.hh
@@ -199,6 +199,7 @@ public:
     
   bool operator==(const ChainView& rhs) const;
   bool operator!=(const ChainView& rhs) const;
+  bool HasAtoms() const;
   //@}
 private:
   ChainViewDataPtr  data_;
diff --git a/modules/mol/base/src/coord_frame.hh b/modules/mol/base/src/coord_frame.hh
index b7cce0661ef615db5799e0dfe287d0d0187cb74c..e624ebf87065849c87c169249f7994a892e1bf75 100644
--- a/modules/mol/base/src/coord_frame.hh
+++ b/modules/mol/base/src/coord_frame.hh
@@ -22,6 +22,7 @@
 /*
   Authors: Marco Biasini, Niklaus Johner, Ansgar Philippsen
  */
+#include <ost/mol/module_config.hh>
 #include <boost/shared_ptr.hpp>
 #include <ost/geom/geom.hh>
 #include <ost/mol/module_config.hh>
diff --git a/modules/mol/base/src/editor_base.cc b/modules/mol/base/src/editor_base.cc
index 4d4111c8014b9934fa3321f3984cff606465daf1..b6cc4ab455036672b612e2d37f4ccfa93414b9c5 100644
--- a/modules/mol/base/src/editor_base.cc
+++ b/modules/mol/base/src/editor_base.cc
@@ -216,6 +216,15 @@ void EditorBase::RenumberAllResidues(int start, bool keep_spacing)
   ent_.Impl()->RenumberAllResidues(start, keep_spacing);
 }
 
+void EditorBase::RenumberChain(const ChainHandle& chain, int start, bool keep_spacing)
+{
+  CheckHandleValidity(chain);
+  if(chain.GetEntity()!=ent_){
+    throw Error("Chain does not belong to the editors entity!");
+  }
+  chain.Impl()->RenumberAllResidues(start, keep_spacing);
+}
+
 void EditorBase::RenameAtom(AtomHandle atom, const String& new_name)
 {
   CheckHandleValidity(atom);
diff --git a/modules/mol/base/src/editor_base.hh b/modules/mol/base/src/editor_base.hh
index 5e1fbcdef596675758332fcc0477dfc69f85c6e7..255390c29dc3f3e7e286ad5ea966748b75ab72b2 100644
--- a/modules/mol/base/src/editor_base.hh
+++ b/modules/mol/base/src/editor_base.hh
@@ -284,6 +284,21 @@ public:
 
 
   void RenumberChain(ChainHandle chain, const ResNumList& new_numbers);
+
+  /// \brief renumber residues of one chain
+  ///
+  /// \param name
+  ///           All residues of this chain will be renumbered according to the
+  ///           parameters start and keep_spacing
+  ///
+  /// \param start
+  ///           Residues of given chain will be renumbered, whereas the first
+  ///           residue gets the residue number start.
+  ///
+  /// \param keep_spacing
+  ///           If set to false, residues will continously be renumbered ongoing from start.
+  ///           Otherwise the spacings between the residues are kept.
+  void RenumberChain(const ChainHandle& chain, int start, bool keep_spacing);
     
   /// \brief Get edit mode of editor
   EditMode GetMode() const {return mode_;}
diff --git a/modules/mol/base/src/entity_handle.cc b/modules/mol/base/src/entity_handle.cc
index e34e11d2e233ab4a60da62e20c3e085c4ece1f58..eaa348914fec1595be83283c10358cc81df7ea0c 100644
--- a/modules/mol/base/src/entity_handle.cc
+++ b/modules/mol/base/src/entity_handle.cc
@@ -295,6 +295,12 @@ void EntityHandle::ClearTransform()
   Impl()->ClearTransform();  
 }
 
+void EntityHandle::FixTransform()
+{
+  this->CheckValidity();
+  Impl()->FixTransform();  
+}
+
 ResidueHandle EntityHandle::FindResidue(const String& chain_name,
                                         const ResNum& residue) const {
   this->CheckValidity();
diff --git a/modules/mol/base/src/entity_handle.hh b/modules/mol/base/src/entity_handle.hh
index fe2a439135306d6f2a7c080ed91f1e15604faea0..63a2bc6be27c10908072c5ea72ff6106e315d541 100644
--- a/modules/mol/base/src/entity_handle.hh
+++ b/modules/mol/base/src/entity_handle.hh
@@ -279,6 +279,8 @@ public:
   bool HasTransform() const;
   /// \brief remove transform
   void ClearTransform();
+  /// \brief write transformed pos to orig, and the clear tf
+  void FixTransform();
 
   /// \brief get complete list of residues
   /// \sa #ResiduesBegin, #ResiduesEnd
diff --git a/modules/mol/base/src/entity_view.cc b/modules/mol/base/src/entity_view.cc
index d81940ee1bfc89228a9db78163ac410b95a96738..0c2d6db4177c6259fc3e39b3de91afd81ae7ad58 100644
--- a/modules/mol/base/src/entity_view.cc
+++ b/modules/mol/base/src/entity_view.cc
@@ -161,7 +161,7 @@ int EntityView::GetResidueCount() const
 geom::Vec3 EntityView::GetCenterOfAtoms() const 
 {
   geom::Vec3 center;
-  if (this->GetAtomCount()>0) {
+  if (this->HasAtoms()) {
     unsigned int counter=0;
     AtomViewIter it=this->AtomsBegin();
     for(; it!=this->AtomsEnd(); ++it, ++counter) {
@@ -176,7 +176,7 @@ geom::Vec3 EntityView::GetCenterOfMass() const
 {
   geom::Vec3 center;
   Real mass = this->GetMass();
-  if (this->GetAtomCount()>0 && mass>0) {
+  if (this->HasAtoms() && mass>0) {
     AtomViewIter it=this->AtomsBegin();
     for(; it!=this->AtomsEnd(); ++it) {
       center+=(*it).GetPos()*(*it).GetMass();
@@ -252,7 +252,7 @@ ChainView EntityView::FindChain(const String& chain_name) const{
   this->CheckValidity();
   ChainViewList::const_iterator i;
   i=std::find_if(data_->chains.begin(), data_->chains.end(),
-                 bind(&ChainView::GetName, _1)==chain_name);
+                 boost::bind(&ChainView::GetName, _1)==chain_name);
   return (i!=data_->chains.end()) ? *i : ChainView();
 }
 
@@ -755,7 +755,7 @@ geom::AlignedCuboid EntityView::GetBounds() const
   this->CheckValidity();
   geom::Vec3 mmin( std::numeric_limits<Real>::max());
   geom::Vec3 mmax(-std::numeric_limits<Real>::max());
-  if (this->GetAtomCount()) {
+  if (this->HasAtoms()) {
     for(AtomViewIter it=AtomsBegin(); it!=this->AtomsEnd(); ++it) {
       mmax=geom::Max(mmax, (*it).GetPos());
       mmin=geom::Min(mmin, (*it).GetPos());
@@ -912,5 +912,18 @@ AtomView EntityView::FindAtom(const AtomHandle& atom) const
   return this->ViewForHandle(atom);
 }
 
+bool EntityView::HasAtoms() const 
+{
+  this->CheckValidity();
+  for (ChainViewList::const_iterator it=data_->chains.begin(), 
+       e=data_->chains.end();
+       it!=e; ++it) {
+    if ((*it).HasAtoms()) {
+      return true;
+    }
+  }
+  return false;
+}
+
 }} // ns
 
diff --git a/modules/mol/base/src/entity_view.hh b/modules/mol/base/src/entity_view.hh
index 56136733b06abfca2abc5bf12c3f299f6de9e002..458e6d40fac928ac1c93b381a4fc1f2e1777d45f 100644
--- a/modules/mol/base/src/entity_view.hh
+++ b/modules/mol/base/src/entity_view.hh
@@ -341,6 +341,9 @@ public:
   EntityView CreateFullView() const;
   /// \brief create empty view
   EntityView CreateEmptyView() const;
+  
+  /// \brief true if view contains at least one atom
+  bool HasAtoms() const;
 #ifdef _MSC_VER
   // alternative routines for msvc
   AtomView AddXAtom(const AtomHandle& ah, ViewAddFlags flags=0);
diff --git a/modules/mol/base/src/impl/entity_impl.cc b/modules/mol/base/src/impl/entity_impl.cc
index db9460a01cd68b16a91cdaa30f7e1dba3963591d..865ef7172ebf5452e9acdc737ea170f068ad01f3 100644
--- a/modules/mol/base/src/impl/entity_impl.cc
+++ b/modules/mol/base/src/impl/entity_impl.cc
@@ -750,8 +750,20 @@ void EntityImpl::SetTransform(const geom::Transform& tf)
 
 void EntityImpl::ClearTransform()
 {
-  has_transform_=false;
   SetTransform(geom::Transform());
+  has_transform_=false;
+}
+
+void EntityImpl::FixTransform()
+{
+  if(!has_transform_) return;
+  for(AtomImplMap::iterator it = atom_map_.begin();it!=atom_map_.end();++it) {
+    it->second->OriginalPos()=it->second->TransformedPos();
+  }
+  transform_=geom::Transform();
+  has_transform_=false;
+  this->UpdateTransformedPos();
+  this->MarkOrganizerDirty();
 }
 
 void EntityImpl::AttachObserver(const EntityObserverPtr& o)
@@ -1204,4 +1216,16 @@ void EntityImpl::RenumberAllResidues(int start, bool keep_spacing)
 
 }
 
+void EntityImpl::RenumberChain(const String& name, int start, bool keep_spacing)
+{
+  ChainImplPtr ch=this->FindChain(name);
+
+  if(!ch) {
+    throw Error("Could not find chain with name "+name);
+  }
+
+  ch->RenumberAllResidues(start, keep_spacing);
+
+}
+
 }}} // ns
diff --git a/modules/mol/base/src/impl/entity_impl.hh b/modules/mol/base/src/impl/entity_impl.hh
index c95bef408db5c911b40b71b6ae460baa5890b827..6862e5e27f2d827c17aee720725b9b0ebda97100 100644
--- a/modules/mol/base/src/impl/entity_impl.hh
+++ b/modules/mol/base/src/impl/entity_impl.hh
@@ -151,6 +151,7 @@ public:
   const geom::Transform& GetTransform() const {return transform_;}
   bool HasTransform() const {return has_transform_;}
   void ClearTransform();
+  void FixTransform();
 
   void AttachObserver(const EntityObserverPtr& o);
   void DetachObserver(const EntityObserverPtr& o);
@@ -251,6 +252,8 @@ public:
 
   void RenumberAllResidues(int start, bool keep_spacing);
 
+  void RenumberChain(const String& name, int start, bool keep_spacing);
+
 private:
   void DoCopy(EntityImplPtr dest);
   
diff --git a/modules/mol/base/src/impl/residue_impl.cc b/modules/mol/base/src/impl/residue_impl.cc
index 29fee9883e5a8381eac4c12d3d75a194f007de44..3b44d844fb244d96fa9793a181de72f5aa9d9fbe 100644
--- a/modules/mol/base/src/impl/residue_impl.cc
+++ b/modules/mol/base/src/impl/residue_impl.cc
@@ -88,7 +88,7 @@ Real ResidueImpl::GetAverageBFactor() const
        e=atom_list_.end(); i!=e; ++i) {
     sum+=(*i)->GetBFactor();
   }
-  return atom_list_.size()>0 ? sum/atom_list_.size() : 0.0;
+  return ! atom_list_.empty() ? sum/atom_list_.size() : 0.0;
 }
 
 void ResidueImpl::AddAltAtom(const String& group, const AtomImplPtr& atom,
@@ -509,7 +509,7 @@ geom::AlignedCuboid ResidueImpl::GetBounds() const
   geom::Vec3 mmin( std::numeric_limits<Real>::infinity());
   geom::Vec3 mmax(-std::numeric_limits<Real>::infinity());  
 
-  if (atom_list_.size()>0) {
+  if (! atom_list_.empty()) {
     AtomImplList::const_iterator i=atom_list_.begin();
     mmin=mmax=(*i)->TransformedPos();
     for (++i; i!=atom_list_.end(); ++i) {
diff --git a/modules/mol/base/src/query_state.cc b/modules/mol/base/src/query_state.cc
index 63a4be69387dd7a3e6aaf3865b8737fe8a5b58d6..5f4ef1295abc63c07943227848b3b46bf043ceca 100644
--- a/modules/mol/base/src/query_state.cc
+++ b/modules/mol/base/src/query_state.cc
@@ -33,9 +33,10 @@ namespace ost { namespace mol {
 using namespace impl;
 
 struct LazilyBoundRef {
+  LazilyBoundRef(): points(5.0) { }
   LazilyBoundRef& operator=(const LazilyBoundRef& rhs);
-  //EntityView for now, will be generalized to a point cloud later on.
-  EntityView  view;
+  // Stores the points in the lazily bound reference for efficient within calculation.
+  SpatialOrganizer<bool> points;
 };
   
 struct LazilyBoundData {
@@ -67,17 +68,8 @@ bool QueryState::do_within(const geom::Vec3& pos, const WithinParam& p,
       return geom::Dot(d, d) > p.GetRadiusSquare();
   } else {
     const LazilyBoundRef& r=this->GetBoundObject(p.GetRef());
-    for (AtomViewIter i=r.view.AtomsBegin(), e=r.view.AtomsEnd(); i!=e; ++i) {
-      geom::Vec3 d=pos-(*i).GetPos();
-      if (op==COP_LE) {
-        if (geom::Dot(d, d) <= p.GetRadiusSquare()) {
-          return true;
-        }
-      } else if (geom::Dot(d, d) < p.GetRadiusSquare()) {
-        return false;
-      }
-    }
-    return op!=COP_LE;
+    bool has_within = r.points.HasWithin(pos, sqrt(p.GetRadiusSquare()));
+    return op==COP_LE ? has_within : !has_within;
   }
 }
 
@@ -109,30 +101,35 @@ QueryState::~QueryState()
 QueryState::QueryState(const QueryImpl& query, const EntityHandle& ref)
   : q_(query) {
   s_.resize(query.sel_values_.size(),boost::logic::indeterminate);
-  if (query.bracketed_expr_.size()>0) {
+  if (! query.bracketed_expr_.empty()) {
     r_.reset(new LazilyBoundData);
     r_->refs.resize(query.bracketed_expr_.size());
     for (size_t i=0;i<query.bracketed_expr_.size(); ++i) {
-      r_->refs[i].view=ref.Select(Query(query.bracketed_expr_[i]));
+      EntityView view=ref.Select(Query(query.bracketed_expr_[i]));
+      for (AtomViewIter j=view.AtomsBegin(), e=view.AtomsEnd(); j!=e; ++j) {
+        r_->refs[i].points.Add(true, (*j).GetPos());
+      }
     }    
   }
-
 }
 
 LazilyBoundRef& LazilyBoundRef::operator=(const LazilyBoundRef& rhs) {
-  view=rhs.view;
+  points=rhs.points;
   return *this;
 }
 
 QueryState::QueryState(const QueryImpl& query, const EntityView& ref)
   : q_(query) {
   s_.resize(query.sel_values_.size(),boost::logic::indeterminate);
-  if (query.bracketed_expr_.size()>0) {
+  if (! query.bracketed_expr_.empty()) {
     r_.reset(new LazilyBoundData);
     r_->refs.resize(query.bracketed_expr_.size());
     for (size_t i=0;i<query.bracketed_expr_.size(); ++i) {
-      r_->refs[i].view=ref.Select(Query(query.bracketed_expr_[i]));
-    }    
+      EntityView view=ref.Select(Query(query.bracketed_expr_[i]));
+      for (AtomViewIter j=view.AtomsBegin(), e=view.AtomsEnd(); j!=e; ++j) {
+        r_->refs[i].points.Add(true, (*j).GetPos());
+      }
+    }
   }
 }
 
@@ -154,9 +151,8 @@ boost::logic::tribool QueryState::EvalChain(const ChainImplPtr& c) {
     float float_value;
     switch (ss.sel_id) {
       case Prop::CNAME:
-        value = c->GetName();
-        s_[*i] = cmp_string(ss.comp_op,
-                            value,boost::get<StringOrRegexParam>(ss.param));
+        s_[*i] = cmp_string(ss.comp_op, c->GetName(),
+                            boost::get<StringOrRegexParam>(ss.param));
         continue;
       default:
         if (ss.sel_id>=Prop::CUSTOM) {
@@ -190,8 +186,7 @@ boost::logic::tribool QueryState::EvalResidue(const ResidueImplPtr& r) {
     Real float_value;
     switch (ss.sel_id) {
       case Prop::RNAME:
-        str_value = r->GetKey();
-        s_[*i] = cmp_string(ss.comp_op,str_value,
+        s_[*i] = cmp_string(ss.comp_op,r->GetName(),
                             boost::get<StringOrRegexParam>(ss.param));
         continue;
       case Prop::RNUM:
@@ -237,7 +232,7 @@ boost::logic::tribool QueryState::EvalResidue(const ResidueImplPtr& r) {
           }
           s_[*i]=ss.comp_op==COP_EQ ? b : !b;          
         } else {
-          str_value= String(1, (char)r->GetSecStructure());
+          str_value = String(1, (char)r->GetSecStructure());
           s_[*i]=cmp_string(ss.comp_op,str_value,
                             boost::get<StringOrRegexParam>(ss.param));          
         }
@@ -268,19 +263,18 @@ boost::logic::tribool QueryState::EvalResidue(const ResidueImplPtr& r) {
 boost::logic::tribool QueryState::EvalStack(Prop::Level level) {
   const SelStack& stack = q_.sel_stacks_[(int)level];
   SelStack::const_reverse_iterator i = stack.rbegin();
-  std::vector<boost::logic::tribool> value_stack;
-
+  value_stack_.clear();
   while (i!=stack.rend()) {
     const SelItem& si = *i;
     if (si.type==VALUE) {
-      value_stack.push_back(s_[si.value]);
+      value_stack_.push_back(s_[si.value]);
       ++i;
       continue;
     } else {
-      boost::logic::tribool lhs = value_stack.back();
-      value_stack.pop_back();
-      boost::logic::tribool rhs = value_stack.back();
-      value_stack.pop_back();      
+      boost::logic::tribool lhs = value_stack_.back();
+      value_stack_.pop_back();
+      boost::logic::tribool rhs = value_stack_.back();
+      value_stack_.pop_back();      
       LogicOP lop = (LogicOP)si.value;
       boost::logic::tribool result;
       switch(lop) {
@@ -291,12 +285,12 @@ boost::logic::tribool QueryState::EvalStack(Prop::Level level) {
           result = lhs || rhs;
           break;              
       }      
-      value_stack.push_back(result);
+      value_stack_.push_back(result);
       ++i;
     }
   }
-  assert(value_stack.size()==1);
-  return value_stack.back();
+  assert(value_stack_.size()==1);
+  return value_stack_.back();
 }
 
 namespace {
@@ -305,6 +299,7 @@ QueryImpl dummy_query_impl;
 }
 QueryState::QueryState()
   : s_(), q_(dummy_query_impl) {
+ value_stack_.reserve(20);
 }
 
 boost::logic::tribool QueryState::EvalAtom(const AtomImplPtr& a) {
@@ -319,8 +314,7 @@ boost::logic::tribool QueryState::EvalAtom(const AtomImplPtr& a) {
     int int_value;
     switch (ss.sel_id) {
       case Prop::ANAME:
-        str_value = a->Name();
-        s_[*i] = cmp_string(ss.comp_op,str_value,
+        s_[*i] = cmp_string(ss.comp_op,a->GetName(),
                             boost::get<StringOrRegexParam>(ss.param));
         break;
       case Prop::AINDEX:
@@ -348,8 +342,7 @@ boost::logic::tribool QueryState::EvalAtom(const AtomImplPtr& a) {
                              boost::get<float>(ss.param));
         break;                        
       case Prop::ELE:
-        str_value = a->GetElement();
-        s_[*i] = cmp_string(ss.comp_op,str_value,
+        s_[*i] = cmp_string(ss.comp_op,a->GetElement(),
                             boost::get<StringOrRegexParam>(ss.param));                          
         break;
       case Prop::ABFAC:
diff --git a/modules/mol/base/src/query_state.hh b/modules/mol/base/src/query_state.hh
index ad6feffd277af599affe3f4f4745610e5991bbf9..f2d8edfdd39762be70100a58751473c32cb4ccfb 100644
--- a/modules/mol/base/src/query_state.hh
+++ b/modules/mol/base/src/query_state.hh
@@ -82,6 +82,7 @@ private:
   bool do_within(const geom::Vec3& pos, const impl::WithinParam& p, 
                  impl::CompOP op);
   std::vector<boost::logic::tribool>   s_;
+  std::vector<boost::logic::tribool>   value_stack_;
   boost::shared_ptr<LazilyBoundData>   r_;
   const impl::QueryImpl&               q_;
 };
diff --git a/modules/mol/base/src/residue_view.cc b/modules/mol/base/src/residue_view.cc
index 406854a1f0f077c61080c320320e82577765e625..15caa6bd5e0acfc00c691d5042ea0fb77aafa5a7 100644
--- a/modules/mol/base/src/residue_view.cc
+++ b/modules/mol/base/src/residue_view.cc
@@ -114,7 +114,7 @@ AtomView ResidueView::FindAtom(const String& atom_name) const {
   this->CheckValidity();
   const AtomViewList& l=data_->atoms;
   AtomViewList::const_iterator i;
-  i=std::find_if(l.begin(), l.end(), bind(&AtomView::GetName, _1)==atom_name);
+  i=std::find_if(l.begin(), l.end(), boost::bind(&AtomView::GetName, _1)==atom_name);
   return i==data_->atoms.end() ? AtomView() : *i;
 }
 
@@ -281,4 +281,9 @@ AtomView ResidueView::FindAtom(const AtomHandle& handle) const
   return this->ViewForHandle(handle);
 }
 
+bool ResidueView::HasAtoms() const {
+  this->CheckValidity();
+  return data_->atoms.size()>0;
+}
+
 }} //ns
diff --git a/modules/mol/base/src/residue_view.hh b/modules/mol/base/src/residue_view.hh
index 1727e87719c93b1d437352d861e8674c6cd72963..289096413eccb5392fd895c2c99b3a0fc7e87435 100644
--- a/modules/mol/base/src/residue_view.hh
+++ b/modules/mol/base/src/residue_view.hh
@@ -183,6 +183,7 @@ public:
   
   bool operator!=(const ResidueView& rhs) const;
 
+  bool HasAtoms() const;
 protected:
   /// \brief set the index of residiue view in chain
   /// should be called from chainview whenever indexes change
diff --git a/modules/mol/base/src/spatial_organizer.hh b/modules/mol/base/src/spatial_organizer.hh
index af7fd6c9738e2935cdcec6385c3e59b1843de616..e0a3813fbf1fa28e8482b466e1138b6024044523 100644
--- a/modules/mol/base/src/spatial_organizer.hh
+++ b/modules/mol/base/src/spatial_organizer.hh
@@ -89,54 +89,35 @@ public:
     }
   }
 
-  ITEM FindClosest(const VEC& pos) {
-
-    // find closest index with non-empty itemlist
-    Real best_dist2=std::numeric_limits<Real>::max();
-    Index i0;
-    bool found_i0=false;
-    for(typename ItemMap::const_iterator map_it = map_.begin();
-        map_it!=map_.end();++map_it) {
-      Real dist2=geom::Length2(pos-gen_middle(map_it->first));
-      if(dist2<best_dist2 && !map_it->second.empty()) {
-        best_dist2=dist2;
-        i0 = map_it->first;
-        found_i0=true;
-      }
-    }
-
-    if(!found_i0) return ITEM();
-
-    // now find the closest item in the 3x3x3 items centered on i0
-    best_dist2=std::numeric_limits<Real>::max();
-    ITEM* best_item=NULL;
-
-    for(int wc=i0.w-1;wc<=i0.w+1;++wc) {
-      for(int vc=i0.v-1;wc<=i0.v+1;++vc) {
-        for(int uc=i0.u-1;wc<=i0.u+1;++uc) {
-	  typename ItemMap::const_iterator map_it = map_.find(Index(uc,vc,wc));
-
-	  if(map_it!=map_.end()) {
-	    for(typename EntryList::iterator entry_it = map_it->second.begin();
-		entry_it != map_it->second.end(); ++entry_it) {
-	      Real delta_x = entry_it->pos[0]-pos[0];
-              Real delta_y = entry_it->pos[1]-pos[1];
-              Real delta_z = entry_it->pos[2]-pos[2];
-              Real dist2=delta_x*delta_x+delta_y*delta_y+delta_z*delta_z;
-              if(dist2<best_dist2) {
-                best_dist2=dist2;
-                best_item=entry_it;
-	      }
-	    }
-	  }
-	}
+  bool HasWithin(const VEC& pos, Real dist) const {
+    Real dist2=dist*dist;
+    Index imin = gen_index(pos-VEC(dist,dist,dist));
+    Index imax = gen_index(pos+VEC(dist,dist,dist));
+    for(int wc=imin.w;wc<=imax.w;++wc) {
+      for(int vc=imin.v;vc<=imax.v;++vc) {
+        for(int uc=imin.u;uc<=imax.u;++uc) {
+          typename ItemMap::const_iterator map_it = map_.find(Index(uc,vc,wc));
+          if(map_it!=map_.end()) {
+            for(typename EntryList::const_iterator entry_it = map_it->second.begin();
+                entry_it != map_it->second.end(); ++entry_it) {
+                    /*
+                      speed tests indicate that pre-calculating dx2 or dy2
+                      and pre-checking them with an additional if gives little
+                      speed improvement for very specific circumstances only,
+                      but most of the time the performance is worse.
+                    */
+                Real delta_x = entry_it->pos[0]-pos[0];
+                Real delta_y = entry_it->pos[1]-pos[1];
+                Real delta_z = entry_it->pos[2]-pos[2];
+                if(delta_x*delta_x+delta_y*delta_y+delta_z*delta_z<=dist2) {
+                  return true;
+              }
+            }
+          }
+        }
       }
     }
-    if(best_item) {
-      return &best_item;
-    } else {
-      return ITEM();
-    }
+    return false;
   }
 
   ItemList FindWithin(const VEC& pos, Real dist) const {
@@ -148,27 +129,27 @@ public:
 
     for(int wc=imin.w;wc<=imax.w;++wc) {
       for(int vc=imin.v;vc<=imax.v;++vc) {
-	for(int uc=imin.u;uc<=imax.u;++uc) {
-	  typename ItemMap::const_iterator map_it = map_.find(Index(uc,vc,wc));
-
-	  if(map_it!=map_.end()) {
-	    for(typename EntryList::const_iterator entry_it = map_it->second.begin();
-		entry_it != map_it->second.end(); ++entry_it) {
-              /*
-                speed tests indicate that pre-calculating dx2 or dy2
-                and pre-checking them with an additional if gives little
-                speed improvement for very specific circumstances only,
-                but most of the time the performance is worse. 
-              */
-	      Real delta_x = entry_it->pos[0]-pos[0];
-              Real delta_y = entry_it->pos[1]-pos[1];
-              Real delta_z = entry_it->pos[2]-pos[2];
-              if(delta_x*delta_x+delta_y*delta_y+delta_z*delta_z<=dist2) {
-                item_list.push_back(entry_it->item);
-	      }
-	    }
-	  }
-	}
+        for(int uc=imin.u;uc<=imax.u;++uc) {
+          typename ItemMap::const_iterator map_it = map_.find(Index(uc,vc,wc));
+
+          if(map_it!=map_.end()) {
+            for(typename EntryList::const_iterator entry_it = map_it->second.begin();
+          entry_it != map_it->second.end(); ++entry_it) {
+                    /*
+                      speed tests indicate that pre-calculating dx2 or dy2
+                      and pre-checking them with an additional if gives little
+                      speed improvement for very specific circumstances only,
+                      but most of the time the performance is worse.
+                    */
+              Real delta_x = entry_it->pos[0]-pos[0];
+                    Real delta_y = entry_it->pos[1]-pos[1];
+                    Real delta_z = entry_it->pos[2]-pos[2];
+                    if(delta_x*delta_x+delta_y*delta_y+delta_z*delta_z<=dist2) {
+                      item_list.push_back(entry_it->item);
+              }
+            }
+          }
+        }
       }
     }
     return item_list;
diff --git a/modules/mol/base/src/xcs_editor.cc b/modules/mol/base/src/xcs_editor.cc
index 5596e3962d1479921f2c5b8ae5108d0c92ee9b38..4b793d33e4cba2e03526dd3a307a61d0edfdb7ab 100644
--- a/modules/mol/base/src/xcs_editor.cc
+++ b/modules/mol/base/src/xcs_editor.cc
@@ -205,6 +205,11 @@ void XCSEditor::SetTransform(const geom::Transform& transform)
   this->Update();
 }
 
+void XCSEditor::FixTransform()
+{
+  ent_.Impl()->FixTransform();
+}
+
 void XCSEditor::Update()
 {
   if (GetMode()==UNBUFFERED_EDIT) {
@@ -213,6 +218,12 @@ void XCSEditor::Update()
   }
 }
 
+void XCSEditor::ForceUpdate()
+{
+  ent_.Impl()->UpdateICSIfNeeded();
+  ent_.Impl()->UpdateOrganizerIfNeeded();
+}
+
 void XCSEditor::UpdateICS()
 {
   ent_.Impl()->UpdateICSIfNeeded();
diff --git a/modules/mol/base/src/xcs_editor.hh b/modules/mol/base/src/xcs_editor.hh
index a7cc317b2e5273b62211b03a8d04559de97f0fff..fc992d8c9d86e53bc834a73147ddf2f70d1b748d 100644
--- a/modules/mol/base/src/xcs_editor.hh
+++ b/modules/mol/base/src/xcs_editor.hh
@@ -104,9 +104,16 @@ public:
   void SetTransform(const geom::Mat4& transform);
   void SetTransform(const geom::Transform& transform);
 
+  /// \brief set transformed pos to new original pos
+  void FixTransform();
+
   /// \brief immediately update internal coordinate system
   void UpdateICS();  
 
+  /// \brief force spatial organizer and ics update
+  /// workaround for delayed dtor call from Python garbage collection
+  void ForceUpdate();
+
 protected:
    XCSEditor(const EntityHandle& ent, EditMode mode);
    
diff --git a/modules/mol/base/tests/CMakeLists.txt b/modules/mol/base/tests/CMakeLists.txt
index 5085b0b10b257fab18361001a1cb7a55b796769d..176f6ad2421f1d381eaf4800c4f2ec3ad2419325 100644
--- a/modules/mol/base/tests/CMakeLists.txt
+++ b/modules/mol/base/tests/CMakeLists.txt
@@ -3,6 +3,7 @@ set(OST_MOL_BASE_UNIT_TESTS
   test_chain.cc
   test_conn.cc
   test_coord_group.cc
+  test_builder.cc
   test_delete.cc
   test_entity.cc
   test_ics.cc
diff --git a/modules/mol/base/tests/test_atom_groups.cc b/modules/mol/base/tests/test_atom_groups.cc
index fd55845fe2fb550df4545842f0ac92bdf53f3b1c..7514f57acfd0242a20ecfb64aba55cb6f9b79e3f 100644
--- a/modules/mol/base/tests/test_atom_groups.cc
+++ b/modules/mol/base/tests/test_atom_groups.cc
@@ -19,11 +19,11 @@
 /*
  *  Authors: Marco Biasini, Juergen Haas
  */
-#include <ost/mol/mol.hh>
-#include <ost/message.hh>
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 #include <boost/test/auto_unit_test.hpp>
+#include <ost/mol/mol.hh>
+#include <ost/message.hh>
 #include "dummy_ent.hh"
 
 
diff --git a/modules/mol/base/tests/test_builder.cc b/modules/mol/base/tests/test_builder.cc
new file mode 100644
index 0000000000000000000000000000000000000000..f9128bca409ca2df578c9829eb1acb2fea99615a
--- /dev/null
+++ b/modules/mol/base/tests/test_builder.cc
@@ -0,0 +1,74 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+/*
+ *  Authors: Marco Biasini, Juergen Haas
+ */
+#include <ost/mol/builder.hh>
+
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+#include <boost/test/auto_unit_test.hpp>
+
+using namespace ost;
+using namespace ost::mol;
+
+BOOST_AUTO_TEST_SUITE( mol_base_builder );
+
+BOOST_AUTO_TEST_CASE(inserts_chains)
+{
+  EntityHandle ent = Builder()
+                       .Chain("A")
+                       .Chain("B");
+
+  BOOST_CHECK_EQUAL(2, ent.GetChainCount());
+  BOOST_CHECK(ent.FindChain("A").IsValid());
+  BOOST_CHECK(ent.FindChain("B").IsValid());
+}
+
+
+BOOST_AUTO_TEST_CASE(appends_residues) {
+  EntityHandle ent = Builder()
+                        .Chain("A")
+                           .Residue("GLY")
+                           .Residue("GLN");
+
+  BOOST_CHECK_EQUAL(1, ent.GetChainCount());
+  BOOST_CHECK_EQUAL(ent.GetResidueCount(), 2);
+  BOOST_CHECK(ent.FindResidue("A", 1).IsValid());
+  BOOST_CHECK(ent.FindResidue("A", 2).IsValid());
+}
+
+BOOST_AUTO_TEST_CASE(inserts_atoms) {
+  EntityHandle ent = Builder()
+                        .Chain("A")
+                           .Residue("GLY")
+                               .Atom("N")
+                               .Atom("CA")
+                               .Atom("C")
+                               .Atom("O")
+                      ;
+
+  BOOST_CHECK_EQUAL(ent.GetAtomCount(), 4);
+  BOOST_CHECK(ent.FindAtom("A", 1, "N").IsValid());
+  BOOST_CHECK(ent.FindAtom("A", 1, "CA").IsValid());
+  BOOST_CHECK(ent.FindAtom("A", 1, "C").IsValid());
+  BOOST_CHECK(ent.FindAtom("A", 1, "O").IsValid());
+}
+
+BOOST_AUTO_TEST_SUITE_END();
diff --git a/modules/mol/base/tests/test_chain.cc b/modules/mol/base/tests/test_chain.cc
index 39ffd35e205cd320cc926af7e4a440f838109b2c..c857cce0989b9a75b65c0c191e8c57cbe63a687c 100644
--- a/modules/mol/base/tests/test_chain.cc
+++ b/modules/mol/base/tests/test_chain.cc
@@ -19,13 +19,14 @@
 /*
  *  Authors: Marco Biasini, Juergen Haas
  */
-#include <ost/mol/mol.hh>
-#include <ost/message.hh>
-#include <ost/integrity_error.hh>
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 #include <boost/test/auto_unit_test.hpp>
 
+#include <ost/mol/mol.hh>
+#include <ost/message.hh>
+#include <ost/integrity_error.hh>
+
 using namespace ost;
 using namespace ost::mol;
 
diff --git a/modules/mol/base/tests/test_conn.cc b/modules/mol/base/tests/test_conn.cc
index e9c5bcfe10b2fd7196fbcd0c1f4ed5a178587bb0..be08f357a89b718027fbd4039d8719489b8cbbb5 100644
--- a/modules/mol/base/tests/test_conn.cc
+++ b/modules/mol/base/tests/test_conn.cc
@@ -19,10 +19,10 @@
 /*
  *  Authors: Marco Biasini, Juergen Haas
  */
-#include <ost/mol/mol.hh>
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 #include <boost/test/auto_unit_test.hpp>
+#include <ost/mol/mol.hh>
 
 using namespace ost;
 using namespace ost::mol;
diff --git a/modules/mol/base/tests/test_delete.cc b/modules/mol/base/tests/test_delete.cc
index 20799d4ddff3c07b9cf5cd2d72dd55f828d340a0..2d5f2339ce7f6d0072d654840d3fed814e7301b1 100644
--- a/modules/mol/base/tests/test_delete.cc
+++ b/modules/mol/base/tests/test_delete.cc
@@ -19,11 +19,11 @@
 /*
  *  Authors: Marco Biasini, Juergen Haas
  */
-#include <ost/mol/mol.hh>
-#include <ost/log.hh>
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 #include <boost/test/auto_unit_test.hpp>
+#include <ost/mol/mol.hh>
+#include <ost/log.hh>
 #include <ost/message.hh>
 #include <ost/geom/geom.hh>
 
diff --git a/modules/mol/base/tests/test_entity.cc b/modules/mol/base/tests/test_entity.cc
index 767b68bb3ba14f55eca9afde0a3158c5fcab06eb..89b6349bea4682f27d5f9aa148de7d3a1f63913f 100644
--- a/modules/mol/base/tests/test_entity.cc
+++ b/modules/mol/base/tests/test_entity.cc
@@ -20,14 +20,14 @@
  *  Authors: Marco Biasini, Juergen Haas
  */
  
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+#include <boost/test/auto_unit_test.hpp>
 #include <ost/geom/vec_mat_predicates.hh>
 #include <ost/mol/chem_class.hh>
 #include <ost/mol/mol.hh>
 #include <ost/mol/property_id.hh>
 #include <cmath>
-#define BOOST_TEST_DYN_LINK
-#include <boost/test/unit_test.hpp>
-#include <boost/test/auto_unit_test.hpp>
 
 #define CHECK_TRANSFORMED_ATOM_POSITION(ATOM,TARGET) \
    BOOST_CHECK(vec3_is_close(ATOM.GetPos(), TARGET,Real(0.1)))
diff --git a/modules/mol/base/tests/test_ics.cc b/modules/mol/base/tests/test_ics.cc
index c2285ee1b0464ce64e7372e041b760317b0a04fb..231df43cd79d7d4b8217a83eaa91f24b8213ed76 100644
--- a/modules/mol/base/tests/test_ics.cc
+++ b/modules/mol/base/tests/test_ics.cc
@@ -19,12 +19,12 @@
 /*
  *  Authors: Marco Biasini, Juergen Haas
  */
-#include <ost/mol/mol.hh>
-#include <ost/log.hh>
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 #include <boost/test/floating_point_comparison.hpp>
 #include <boost/test/auto_unit_test.hpp>
+#include <ost/mol/mol.hh>
+#include <ost/log.hh>
 #include <ost/message.hh>
 #include <ost/geom/geom.hh>
 
diff --git a/modules/mol/base/tests/test_iterators.cc b/modules/mol/base/tests/test_iterators.cc
index 829b15c96c218bb6630b013f9be1584edd48bc6c..47b24bb11f6f002dded9b8e3a15fbb2899d82898 100644
--- a/modules/mol/base/tests/test_iterators.cc
+++ b/modules/mol/base/tests/test_iterators.cc
@@ -19,11 +19,11 @@
 /*
  *  Authors: Marco Biasini, Juergen Haas
  */
-#include <ost/mol/mol.hh>
-#include <ost/message.hh>
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 #include <boost/test/auto_unit_test.hpp>
+#include <ost/mol/mol.hh>
+#include <ost/message.hh>
 #include <iostream>
 
 using namespace ost;
diff --git a/modules/mol/base/tests/test_residue.cc b/modules/mol/base/tests/test_residue.cc
index 7dca39081915d4e7f49a29765a98920e4926ae00..89e8da33914110dc1d50150fb9dc19e2ab3dd50e 100644
--- a/modules/mol/base/tests/test_residue.cc
+++ b/modules/mol/base/tests/test_residue.cc
@@ -19,12 +19,12 @@
 /*
  *  Authors: Marco Biasini, Juergen Haas
  */
-#include <ost/mol/mol.hh>
-
-#include <ost/message.hh>
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 #include <boost/test/auto_unit_test.hpp>
+#include <ost/mol/mol.hh>
+
+#include <ost/message.hh>
 
 
 using namespace ost;
diff --git a/modules/mol/base/tests/test_surface.cc b/modules/mol/base/tests/test_surface.cc
index 18ab12a8887993bad36afcc5fabe0df2a447f6b9..d48b79843a88f80ce5f69cdf957c5c05fd3a3492 100644
--- a/modules/mol/base/tests/test_surface.cc
+++ b/modules/mol/base/tests/test_surface.cc
@@ -17,12 +17,13 @@
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 //------------------------------------------------------------------------------
  
-#include <ost/mol/surface_handle.hh>
-#include <cmath>
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 #include <boost/test/auto_unit_test.hpp>
 
+#include <ost/mol/surface_handle.hh>
+#include <cmath>
+
 using namespace ost;
 using namespace ost::mol;
 
diff --git a/modules/seq/alg/src/impl/align_impl.hh b/modules/seq/alg/src/impl/align_impl.hh
index 2df545dbd156cf9c3b0bb5c7b922b28d10d60573..33c1afe760f8a70f5b6cdadff69bb26e9e2353f9 100644
--- a/modules/seq/alg/src/impl/align_impl.hh
+++ b/modules/seq/alg/src/impl/align_impl.hh
@@ -98,6 +98,15 @@ inline void DLLEXPORT StoreStrAsAln(String& aln_str1, String& aln_str2,
   AlignmentHandle aln=CreateAlignment();
   aln.AddSequence(CreateSequence(s1.GetName(), aln_str1));
   aln.AddSequence(CreateSequence(s2.GetName(), aln_str2));  
+
+  if (s1.GetAttachedView()) {
+    aln.AttachView(0, s1.GetAttachedView());
+  }
+
+  if (s2.GetAttachedView()) {
+    aln.AttachView(1, s2.GetAttachedView());
+  }
+
   aln.SetSequenceOffset(0, i);
   aln.SetSequenceOffset(1, j);
   alignments.push_back(aln);
diff --git a/modules/seq/alg/tests/test_renumber.py b/modules/seq/alg/tests/test_renumber.py
index 4a39420af9a938c8ab3a3e44d47bcca76403711a..0309f5a1b9166f1a2e4a2febd947832c06487218 100644
--- a/modules/seq/alg/tests/test_renumber.py
+++ b/modules/seq/alg/tests/test_renumber.py
@@ -1,3 +1,4 @@
+import sys
 import unittest
 from ost import *
 from ost import settings
diff --git a/modules/seq/base/pymod/export_sequence.cc b/modules/seq/base/pymod/export_sequence.cc
index 269ce3a7cb584704d5074505180d653ffe93539c..6cdf081cd35740fa1f4a543ef341e37f3e0974f6 100644
--- a/modules/seq/base/pymod/export_sequence.cc
+++ b/modules/seq/base/pymod/export_sequence.cc
@@ -80,6 +80,9 @@ ConstSequenceList do_slice_a(ConstSequenceList& t, slice sl)
 {
   return do_slice<ConstSequenceList>(t, sl);
 }
+String aln_to_str(const AlignmentHandle& aln) {
+  return aln.ToString();
+}
 
 SequenceList do_slice_b(SequenceList& t, slice sl)
 {
@@ -334,9 +337,6 @@ void export_sequence()
   class_<SeqListIter>("SeqListIter", no_init)
     .def("next", &SeqListIter::next)
   ;
-  to_python_converter<std::pair<mol::EntityView, mol::EntityView>, 
-                      PairToTupleConverter<mol::EntityView, mol::EntityView> >();
-  
   class_<AlignmentHandle>("AlignmentHandle", init<>())
     .def("GetCount", &AlignmentHandle::GetCount)
     .add_property("sequence_count", &AlignmentHandle::GetCount)
@@ -345,10 +345,13 @@ void export_sequence()
     .def("GetResidueIndex", &AlignmentHandle::GetResidueIndex)
     .def("GetResidue", &AlignmentHandle::GetResidue)
     .def("AddSequence", &AlignmentHandle::AddSequence)
+    .def("GetMatchingBackboneViews", &AlignmentHandle::GetMatchingBackboneViews,
+         (arg("idx_a")=0, arg("idx_b")=1))
     .def("FindSequence", &AlignmentHandle::FindSequence)
     .def("FindSequenceIndex", &AlignmentHandle::FindSequenceIndex)
     .def("Copy", &AlignmentHandle::Copy)
-    .def("ToString", &AlignmentHandle::ToString)
+    .def("ToString", &AlignmentHandle::ToString, (arg("width")=80))
+    .def("__str__", aln_to_str)
     .def("GetLength", &AlignmentHandle::GetLength)
     .def("__len__", &AlignmentHandle::GetLength)
     .def("GetSequences", &AlignmentHandle::GetSequences)
diff --git a/modules/seq/base/src/sequence_op.cc b/modules/seq/base/src/sequence_op.cc
index c502367f14c2e0addadcc72121542b1cb4c57cb4..17e36da506a6a2e7db955e902153c11854dbff72 100644
--- a/modules/seq/base/src/sequence_op.cc
+++ b/modules/seq/base/src/sequence_op.cc
@@ -41,7 +41,9 @@ SequenceHandle SequenceFromChain(const String& name,
        e=residues.end(); i!=e; ++i) {
     sequence+=(*i).GetOneLetterCode();
   }
-  return CreateSequence(name, sequence);
+  SequenceHandle s = CreateSequence(name, sequence);
+  s.AttachView(chain.Select(""));
+  return s;
 }
 
 
@@ -54,7 +56,9 @@ SequenceHandle SequenceFromChain(const String& name,
        e=chain.GetResidueList().end(); i!=e; ++i) {
     sequence+=(*i).GetOneLetterCode();
   }
-  return CreateSequence(name, sequence);
+  SequenceHandle s = CreateSequence(name, sequence);
+  s.AttachView(chain.Select(""));
+  return s;
 } 
  
 }}
diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt
index 12b81a310b570f6888852d04864af183022ce4f3..0c8f2c68098025afbdf45b95f433c59ec93945e7 100644
--- a/scripts/CMakeLists.txt
+++ b/scripts/CMakeLists.txt
@@ -18,7 +18,6 @@ if (NOT ENABLE_STATIC)
            TARGET ost_scripts)
     script(NAME ost.bat INPUT ost.bat.in SUBSTITUTE ${SUBST_DICT}
            TARGET ost_scripts)
-    script(NAME gipltng.bat INPUT gipltng.bat.in SUBSTITUTE ${SUBST_DICT})
   else()
     script(NAME ost_config INPUT ost_config.in SUBSTITUTE ${SUBST_DICT}
            TARGET ost_scripts OUTPUT_DIR ${LIBEXEC_PATH})
@@ -31,11 +30,11 @@ if (NOT ENABLE_STATIC)
   endif()
 
   set(INIT_SCRIPTS 
-    init_cl.py
+    ost_startup.py
   )
-  set(SPD "${LIB_DIR}/python${PYTHON_VERSION}/site-packages")
+  set(SPD "${LIB_DIR}/python${PYTHON_VERSION}/site-packages/ost")
   if (ENABLE_GUI)
-    list(APPEND INIT_SCRIPTS init.py)
+    list(APPEND INIT_SCRIPTS dng_startup.py)
   endif()
   copy_if_different("${CMAKE_CURRENT_SOURCE_DIR}" "${STAGE_DIR}/${SPD}" 
                   "${INIT_SCRIPTS}" "python init scripts" ost_scripts)
diff --git a/scripts/dng.bat.in b/scripts/dng.bat.in
index fba653b9389f646f6ebac54f3c62b38851658808..e6c2c7c7a85d30411f6de75a34830424d59fb08c 100644
--- a/scripts/dng.bat.in
+++ b/scripts/dng.bat.in
@@ -27,5 +27,4 @@ echo Starting DNG in %BIN_DIR%
 
 set DNG_ROOT=%BIN_DIR%\..
 set PATH=%BIN_DIR%;%DNG_ROOT%\@LIBDIR@\@BUILD_TYPE@;%DNG_ROOT%\@LIBDIR@;%DNG_ROOT%\bin\@BUILD_TYPE@;%PATH%
-REM "%BIN_DIR%\@BUILD_TYPE@\gosty.exe" %DNG_ROOT%\@LIBDIR@\openstructure\init.py ost %*
-"%BIN_DIR%\@BUILD_TYPE@\gosty.exe" "%DNG_ROOT%\@LIBDIR@\openstructure\init.py" ost %*
+"%BIN_DIR%\@BUILD_TYPE@\gosty.exe" "%DNG_ROOT%\@LIBDIR@\openstructure\dng_startup" ost %*
diff --git a/scripts/dng.in b/scripts/dng.in
index d1d7096fca8c777e211d61e462b9d5709844f5f4..d431535382c1b077fa2517f0e0d809dc887df526 100755
--- a/scripts/dng.in
+++ b/scripts/dng.in
@@ -28,4 +28,4 @@ fi
 BIN_DIR=`dirname "$SCRIPT_NAME"`
 source "$BIN_DIR/../@LIBEXEC_PATH@/ost_config"
 
-$BIN_DIR/../@LIBEXEC_PATH@/gosty $DNG_INITDIR/init.py dng $opts
+$BIN_DIR/../@LIBEXEC_PATH@/gosty $DNG_INITDIR/dng_startup.py dng $opts
diff --git a/scripts/init.py b/scripts/dng_startup.py
similarity index 100%
rename from scripts/init.py
rename to scripts/dng_startup.py
diff --git a/scripts/ost.bat.in b/scripts/ost.bat.in
index 27fb91247bebdd5327d5cf9c6855b3c29570fd8b..006fffe522ce9ef072e3283ee87361e309e8a11e 100644
--- a/scripts/ost.bat.in
+++ b/scripts/ost.bat.in
@@ -50,6 +50,6 @@ if "%1" == "" (
   echo passing commandline options %opts% to ost
 )
 
-call "%pyexec%" %interact_% "%DNG_ROOT%\@LIBDIR@\openstructure\init_cl.py" %opts%
+call "%pyexec%" %interact_% "%DNG_ROOT%\@LIBDIR@\openstructure\ost_startup.py" %opts%
 
 
diff --git a/scripts/ost.in b/scripts/ost.in
index bea69d9ec23a36cc1912b9457938c31e8d898ea6..dcbe81d4e86773c4d165b36666d9b8e9a8545d9d 100755
--- a/scripts/ost.in
+++ b/scripts/ost.in
@@ -31,6 +31,6 @@ BIN_DIR=`dirname "$SCRIPT_NAME"`
 
 source "$BIN_DIR/../@LIBEXEC_PATH@/ost_config"
 
-$pyexec $interactive "$DNG_ROOT/@LIBDIR@/python@PYTHON_VERSION@/site-packages/init_cl.py" $opts
+$pyexec $interactive "$DNG_ROOT/@LIBDIR@/python@PYTHON_VERSION@/site-packages/ost/ost_startup.py" $opts
 RC=$?
 exit $RC
diff --git a/scripts/ost_config.in b/scripts/ost_config.in
index f756d7cd30c29db720aeba659643c18bb872e4c9..99dd87b0faa8136f49591f206673d4b49d19b592 100644
--- a/scripts/ost_config.in
+++ b/scripts/ost_config.in
@@ -24,7 +24,7 @@
 export DNG_ROOT=`cd "$BIN_DIR/..";pwd`
 export DNG_BINDIR="$DNG_ROOT/bin"
 export DNG_LIBDIR="$DNG_ROOT/@LIBDIR@"
-export DNG_INITDIR="$DNG_LIBDIR/python@PYTHON_VERSION@/site-packages"
+export DNG_INITDIR="$DNG_LIBDIR/python@PYTHON_VERSION@/site-packages/ost/"
 
 export PATH="$DNG_BINDIR:${PATH}"
 export DYLD_FRAMEWORK_PATH="$DNG_LIBDIR:${DYLD_FRAMEWORK_PATH}"
@@ -50,6 +50,18 @@ if [ -n "$DNG_ATTACH_VALGRIND" ]; then
   pyexec="`which valgrind`#--leak-check=full#$pyexec"
 fi
 
+if [ -n "$DNG_PROFILE" ]; then
+  if [[ "$DNG_PROFILE" == "yep" ]]; then
+    echo "Profiling activated using yep"
+    pyexec="$pyexec#-m#yep#-v#--"
+  elif [[ "$DNG_PROFILE" == "cProfile" ]]; then
+    echo "Profiling activated using cProfile"
+    pyexec="$pyexec#-m#cProfile#-s#cumulative#--"
+  else 
+    echo "Profiling deactivated due to unkown profiler"
+  fi
+fi
+
 
 set -o noglob
 
diff --git a/scripts/init_cl.py b/scripts/ost_startup.py
similarity index 88%
rename from scripts/init_cl.py
rename to scripts/ost_startup.py
index e9251dc9b0363710c25f77606e737ae8979d1ff1..98a4022637cf9c571a2a779aed1c4d4094d98f8c 100644
--- a/scripts/init_cl.py
+++ b/scripts/ost_startup.py
@@ -27,17 +27,19 @@ parser.disable_interspersed_args()
 (options, args) = parser.parse_args()
 
 _site_packs='python%d.%d/site-packages' % sys.version_info[0:2]
+_base_dir=os.getenv('DNG_ROOT')
 if platform.machine()=='x86_64':
-  sys.path.insert(0, os.path.join(os.getenv('DNG_ROOT'), 'lib64', _site_packs))
+  sys.path.insert(0, os.path.join(_base_dir, 'lib64', _site_packs))
 else:
-  sys.path.insert(0,os.path.join(os.getenv('DNG_ROOT'), 'lib', _site_packs))
+  sys.path.insert(0,os.path.join(_base_dir, 'lib', _site_packs))
      
 from ost import *
 import ost
 
-ost.SetPrefixPath(os.getenv('DNG_ROOT'))
+ost.SetPrefixPath(_base_dir)
 
 def _InitRuleBasedProcessor():
+def _InitRuleBasedBuilder():
   compound_lib_path=os.path.join(ost.GetSharedDataPath(), 'compounds.chemlib')
   if os.path.exists(compound_lib_path):
     compound_lib=conop.CompoundLib.Load(compound_lib_path)
@@ -49,9 +51,7 @@ _InitRuleBasedProcessor()
 import os.path
 HistoryFile=os.path.expanduser('~/.ost_history')
 
-# this is a silly name...
-InGUIMode=False
-# ... lets be more pythonic
+# we are not in GUI mode. 
 gui_mode=False
 
 sys.ps1='ost> '
@@ -75,6 +75,7 @@ else:
 
 PushVerbosityLevel(options.vlevel)
 
+# this should probably only be added when running an interactive shell
 sys.path.append(".")
 
 if len(parser.rargs)>0 :
diff --git a/tools/molck/CMakeLists.txt b/tools/molck/CMakeLists.txt
index 346f3466a7f728d411b418968fab7f8ed94a7bca..4e1dc2fb79b73e90022dd2f546a5011c98eca118 100644
--- a/tools/molck/CMakeLists.txt
+++ b/tools/molck/CMakeLists.txt
@@ -1,3 +1,4 @@
-executable(NAME molck SOURCES main.cc 
+if (NOT WIN32)
+executable(NAME molck SOURCES main.cc
            DEPENDS_ON ost_io STATIC)
-
+endif(NOT WIN32)
diff --git a/tools/molck/main.cc b/tools/molck/main.cc
index 2a5e8e7eac780c856d3345464c93339f28a0c2df..f1a805513933457c84e6e87f1c17fb681f49b7e2 100644
--- a/tools/molck/main.cc
+++ b/tools/molck/main.cc
@@ -366,7 +366,7 @@ int main(int argc, char *argv[])
     }
     if (write_to_file) {
       fs::path input_file_path(files[i]);
-      fs::path input_filename = input_file_path.stem();
+      fs::path input_filename = BFPathStem(input_file_path);
       String input_filename_string=BFPathToString(input_filename);
       size_t replstart =output_blueprint_string.find('%');	
       String output_blueprint_string_copy = output_blueprint_string;