diff --git a/.gitignore b/.gitignore
index 999865f42d6427ffadb3da685ee7fee4c340848d..68136f8be070c507f06fc835f6b646660bdffdb7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -57,6 +57,8 @@ Debug
 *.cxx_parameters
 /deployment/win/create_archive.bat
 /install_manifest.txt
+/modules/gui/src/module_config.hh
+/modules/gui/src/dngr.qrc.depends
 *_out.csv
 *_out.tab
 *_out.pickle
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 4151f7269f101d4cc37d7d97d5bafff65945cc65..af007259420189de595538d71a69c4e3aea0bde0 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,3 +1,8 @@
+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.
 
 Changes in Release 1.2.1
 --------------------------------------------------------------------------------
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c8651ec834cfe3a60a435c603e234a1c6dcaf615..346da8a262f31c8093787c5a933e9aca18c63aa5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -152,7 +152,7 @@ add_definitions(-DEIGEN2_SUPPORT)
 if (COMPOUND_LIB)
   set(_COMP_LIB "${COMPOUND_LIB}")
   if (NOT IS_ABSOLUTE "${COMPOUND_LIB}")
-    set(COMPOUND_LIB "${CMAKE_CURRENT_SOURCE_DIR}/${COMPOUND_LIB}")
+    set(COMPOUND_LIB "${CMAKE_CURRENT_BINARY_DIR}/${COMPOUND_LIB}")
   endif()
 else()
   set(_COMP_LIB "NONE")
diff --git a/cmake_support/OST.cmake b/cmake_support/OST.cmake
index 902619dd345b360595f97de19053c7393e09dcb8..e6dfb2ae0d4fb748a455f89e0ed51524acab4ba9 100644
--- a/cmake_support/OST.cmake
+++ b/cmake_support/OST.cmake
@@ -1,10 +1,48 @@
 #-------------------------------------------------------------------------------
-# Author: Marco Biasini, Juergen Haas
+# Authors: Marco Biasini, Juergen Haas, Andreas Schenk
 #
 # This file contains a bunch of useful macros to facilitate the build-system
 # configuration for the modules.
 #-------------------------------------------------------------------------------
 
+#-------------------------------------------------------------------------------
+# map macro
+#
+# this function emulates a map/dict data type
+#-------------------------------------------------------------------------------
+
+function(map COMMAND MAPNAME)
+  set (_KEYS ${MAPNAME}_MAP_KEYS )
+  set (_VALUES ${MAPNAME}_MAP_VALUES)
+  if(${COMMAND} STREQUAL SET)
+    list(REMOVE_AT ARGN 0)
+    list(FIND ${_KEYS} ${ARGV2} _MAP_INDEX)
+    if(_MAP_INDEX EQUAL -1)
+      list(APPEND ${_KEYS} ${ARGV2})
+      set(${_KEYS} ${${_KEYS}} PARENT_SCOPE)
+      set(${_VALUES}_${ARGV2}  ${ARGN} PARENT_SCOPE)
+    else()
+      set(${_VALUES}_${ARGV2}  ${ARGN} PARENT_SCOPE)
+    endif()
+  elseif(${COMMAND} STREQUAL GET)
+    list(FIND ${_KEYS} ${ARGV2} _MAP_INDEX)
+    if(_MAP_INDEX EQUAL -1)
+      MESSAGE(FATAL_ERROR "Unknown key: " ${ARGV2})
+    endif()
+    set(${ARGV3} ${${_VALUES}_${ARGV2}} PARENT_SCOPE)
+  elseif(${COMMAND} STREQUAL KEYS)
+    set(${ARGV2} ${${_KEYS}} PARENT_SCOPE)
+  elseif(${COMMAND} STREQUAL CREATE)
+    set(${_KEYS}  "" PARENT_SCOPE)
+  elseif(${COMMAND} STREQUAL LENGTH)
+    list(LENGTH ${_KEYS} _L)
+    set(${ARGV2} ${_L} PARENT_SCOPE)
+  else()
+    MESSAGE(FATAL_ERROR "Unknown map command:" ${COMMAND})
+  endif()
+endfunction()
+
+
 #-------------------------------------------------------------------------------
 # check_architecture
 #
@@ -89,32 +127,36 @@ macro(copy_if_different FROM_DIR TO_DIR FILES TARGETS TARGET)
   endforeach()
 endmacro()
 
+
 #-------------------------------------------------------------------------------
-# stage_headers
-#-------------------------------------------------------------------------------
-macro(stage_headers HEADERS HEADER_INSTALL_DIR TARGET SUB)
-  set(FROM_DIR "./")
-  set(_HDR_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${SUB}")
-  foreach(_HDR ${HEADERS})
-    list(APPEND _ABS_HEADER_NAMES ${_HDR_SOURCE_DIR}/${_HDR})
+# parse_file_list
+#
+# this macro splits a list of files with IN_DIR statements and fills them into a map
+# where the key is the directory name
+#-------------------------------------------------------------------------------
+macro(parse_file_list FILELIST FILEMAP)
+  set(_EXPECT_IN_DIR FALSE)
+  map(CREATE ${FILEMAP})
+  set(_CURRENT_LIST)
+  foreach(_ITEM ${FILELIST})
+    if (_ITEM STREQUAL "IN_DIR")
+      set(_EXPECT_IN_DIR TRUE)
+    else()
+      if (_EXPECT_IN_DIR)
+        set(_EXPECT_IN_DIR FALSE)
+        map(SET ${FILEMAP} ${_ITEM} ${_CURRENT_LIST})
+        set(_CURRENT_LIST)
+      else()
+        list(APPEND _CURRENT_LIST "${_ITEM}")
+      endif()
+    endif()
   endforeach()
-  # introduce a helper target to make sure the headers are staged before
-  # building the library
-  string(REPLACE "/" "_" _SUB_NO_SLASH "${SUB}")
-  string(REPLACE "${PREFIX}_" "" _TARGET "${TARGET}")
-  set(_TARGET_NAME ${_TARGET}_${_SUB_NO_SLASH}_headers)
-  set(_SUB ${SUB})
-  if (NOT _SUB)
-    set(_TARGET_NAME ${_TARGET}_headers)
-  endif()
-  add_custom_target("${_TARGET_NAME}" COMMENT "")
-  set(HEADER_DIR "${HEADER_STAGE_PATH}/${HEADER_INSTALL_DIR}")
-  copy_if_different("" "${HEADER_DIR}"
-                    "${_ABS_HEADER_NAMES}" ""
-                    "${_TARGET_NAME}")
-  add_dependencies(${TARGET} ${_TARGET_NAME})
+  if(_CURRENT_LIST)
+    map(SET ${FILEMAP} "." ${_CURRENT_LIST})
+  endif()
 endmacro()
 
+
 #-------------------------------------------------------------------------------
 # Synopsis:
 #   module(NAME name SOURCES source1 source2 HEADERS header1 header2 
@@ -142,17 +184,9 @@ macro(module)
   if (_ARG_HEADER_OUTPUT_DIR)
     set(_HEADER_OUTPUT_DIR ${_ARG_HEADER_OUTPUT_DIR})
   else()
-    if (_ARG_PREFIX)
-      set(_HEADER_OUTPUT_DIR "${_ARG_PREFIX}/${_ARG_NAME}")
-    else()
-      set(_HEADER_OUTPUT_DIR "${_ARG_NAME}")
-    endif()
-  endif()
-  if (_ARG_PREFIX)
-    set(_LIB_NAME ${_ARG_PREFIX}_${_ARG_NAME})
-  else()
-    set(_LIB_NAME ${_ARG_NAME})
+    set(_HEADER_OUTPUT_DIR "${_ARG_PREFIX}/${_ARG_NAME}")
   endif()
+  set(_LIB_NAME ${_ARG_PREFIX}_${_ARG_NAME})
   string(TOUPPER ${_LIB_NAME} _UPPER_LIB_NAME)  
   #-----------------------------------------------------------------------------
   # create library  
@@ -161,17 +195,11 @@ macro(module)
   file(MAKE_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
   file(MAKE_DIRECTORY ${LIBEXEC_STAGE_PATH})
   file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/tests")
-  if (NOT TARGET make_stage_lib_dir)
-    add_custom_target(make_stage_lib_dir COMMAND ${CMAKE_COMMAND} -E make_directory ${LIB_STAGE_PATH})
-  endif()
-  if (NOT TARGET make_executable_output_dir)
-    add_custom_target(make_executable_output_dir COMMAND ${CMAKE_COMMAND} -E make_directory ${EXECUTABLE_OUTPUT_PATH})
-  endif()
-  if (NOT TARGET make_libexec_dir)
-    add_custom_target(make_libexec_dir COMMAND ${CMAKE_COMMAND} -E make_directory ${LIBEXEC_STAGE_PATH})
-  endif()
-  if (NOT TARGET make_tests_dir)
-    add_custom_target(make_tests_dir COMMAND ${CMAKE_COMMAND} -E 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 ${LIBEXEC_STAGE_PATH}
+                                   COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/tests")
   endif()
   if (WIN32)
     set(_ABS_FILE_PATTERN "^[A-Z]:/")
@@ -199,10 +227,7 @@ macro(module)
                                      EchoString   ${_ARG_NAME}
                                      MODULE_DEPS "${_ARG_DEPENDS_ON}")
     get_target_property(_DEFS ${_LIB_NAME} COMPILE_DEFINITIONS)
-    add_dependencies(${_LIB_NAME} make_stage_lib_dir)
-    add_dependencies(${_LIB_NAME} make_executable_output_dir)
-    add_dependencies(${_LIB_NAME} make_libexec_dir)
-    add_dependencies(${_LIB_NAME} make_tests_dir)
+    add_dependencies(${_LIB_NAME} create_stage)
     set_target_properties(${_LIB_NAME} PROPERTIES
                           COMPILE_DEFINITIONS OST_MODULE_${_UPPER_LIB_NAME})
     set_target_properties(${_LIB_NAME} PROPERTIES
@@ -236,7 +261,6 @@ macro(module)
     if (ENABLE_STATIC)
       target_link_libraries(${_LIB_NAME} ${STATIC_LIBRARIES})
     endif()
-  
   else()
     add_custom_target("${_LIB_NAME}" ALL)
     set_target_properties("${_LIB_NAME}" PROPERTIES HEADER_ONLY 1 
@@ -246,47 +270,33 @@ macro(module)
   # stage headers  
   #-----------------------------------------------------------------------------
   if (_ARG_HEADERS)
-    set(_HEADERS)
-    set(_EXPECT_IN_DIR FALSE)
-    foreach(_HEADER ${_ARG_HEADERS})
-      if (_HEADER STREQUAL "IN_DIR")
-        set(_EXPECT_IN_DIR TRUE)
-      else()
-        if (_EXPECT_IN_DIR)
-          set(_EXPECT_IN_DIR FALSE)
-          set(_DIR ${_HEADER})
-          set(_ABS_HEADER_NAMES)
-          set(_HDR_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${_DIR}")
-          foreach(_HDR ${_HEADERS})
-            list(APPEND _ABS_HEADER_NAMES "${_HDR_SOURCE_DIR}/${_HDR}")
-          endforeach()
-          install(FILES ${_ABS_HEADER_NAMES} DESTINATION
-                  "include/${_HEADER_OUTPUT_DIR}/${_DIR}")
-          set(_HDR_STAGE_DIR "${_HEADER_OUTPUT_DIR}/${_DIR}")
-          stage_headers("${_HEADERS}" "${_HDR_STAGE_DIR}" 
-                        "${_LIB_NAME}" "${_DIR}")
-          set(_HEADERS)
-        else()
-          list(APPEND _HEADERS "${_HEADER}")
-        endif()
-      endif()
-    endforeach()
-    list(LENGTH _HEADERS _HEADER_LIST_LENGTH)
-    if (_HEADER_LIST_LENGTH GREATER 0)    
-      set(_ABS_HEADER_NAMES)   
-      set(_HDR_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")       
-      foreach(_HDR ${_HEADERS})
-        list(APPEND _ABS_HEADER_NAMES "${_HDR_SOURCE_DIR}/${_HDR}")
-      endforeach()      
-      install(FILES ${_ABS_HEADER_NAMES} DESTINATION
-              "include/${_HEADER_OUTPUT_DIR}")
-      set(_HDR_STAGE_DIR "${_HEADER_OUTPUT_DIR}")
-      stage_headers("${_HEADERS}" "${_HDR_STAGE_DIR}" 
-                    "${_LIB_NAME}" "")
-    endif()
+    stage_and_install_headers("${_ARG_HEADERS}" "${_HEADER_OUTPUT_DIR}" "${_LIB_NAME}")
   endif()
 endmacro()
 
+#-------------------------------------------------------------------------------
+# macro stage_and_install_headers
+#-------------------------------------------------------------------------------
+macro(stage_and_install_headers HEADERLIST HEADER_OUTPUT_DIR TARGET)
+  add_custom_target("${TARGET}_headers" COMMENT "")
+  add_dependencies("${TARGET}" "${TARGET}_headers")
+  add_dependencies("${TARGET}_headers" create_stage)
+  parse_file_list("${HEADERLIST}" _HEADER_MAP)
+  map(KEYS _HEADER_MAP _HEADER_MAP_KEYS)
+  foreach(_DIR ${_HEADER_MAP_KEYS})
+    map(GET _HEADER_MAP ${_DIR} _HEADERS)
+    set(_HDR_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${_DIR}")
+    set(_ABS_HEADER_NAMES)
+    foreach(_HDR ${_HEADERS})
+      list(APPEND _ABS_HEADER_NAMES ${_HDR_SOURCE_DIR}/${_HDR})
+    endforeach()
+    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}")
+  endforeach()
+endmacro()
+
 
 #-------------------------------------------------------------------------------
 # Synopsis
@@ -422,13 +432,14 @@ endmacro()
 
 #-------------------------------------------------------------------------------
 # Synopsis:
-#   ui_to_python(module out_files [input_file1 ...])
+#   ui_to_python(libname stagedir[input_file1 ...])
 # Description:
 #   Calls pyuic on every input file. The resulting python files are stored in
 #   the variable with name out_files.
 #-------------------------------------------------------------------------------
-macro(ui_to_python module out_files)
+macro(ui_to_python LIBNAME STAGEDIR)
   set(_input_files ${ARGN})
+  add_custom_target("${LIBNAME}_ui" ALL)
   find_program(_PYUIC_EXECUTABLE
     NAMES pyuic4-${PYTHON_VERSION} pyuic4 pyuic
     PATHS  ENV PATH 
@@ -436,17 +447,19 @@ macro(ui_to_python module out_files)
   if(NOT _PYUIC_EXECUTABLE)
     message(FATAL_ERROR "Could not find pyuic command in " ${QT_BINARY_DIR} " for python version " ${PYTHON_VERSION})
   endif(NOT _PYUIC_EXECUTABLE)
-
+  set(out_files)
   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 ${CMAKE_CURRENT_SOURCE_DIR}/${_out_file}_ui.py)
-    add_custom_command(TARGET ${module}
-                       COMMAND ${_PYUIC_EXECUTABLE} -o ${_out_file} ${_in_file}
+    set(_out_file ${_out_file}_ui.py)
+    set(_abs_out_file ${STAGEDIR}/${_out_file})
+    add_custom_command(TARGET ${LIBNAME}_ui
+                       COMMAND ${_PYUIC_EXECUTABLE} -o ${_abs_out_file} ${_in_file}
                        VERBATIM DEPENDS ${input_file}
                        )
-    list(APPEND ${out_files} ${_out_file})
+    list(APPEND ${out_files} ${_abs_out_file})
   endforeach()
+  compile_py_files(_${LIBNAME} ${STAGEDIR} ${out_files})
 endmacro()
 
 #-------------------------------------------------------------------------------
@@ -502,6 +515,7 @@ macro(pymod)
   set(_LIB_NAME ${_ARG_PREFIX}_${_ARG_NAME})
   set(PYMOD_STAGE_DIR "${LIB_STAGE_PATH}/${PYMOD_DIR}")
   file(MAKE_DIRECTORY ${PYMOD_STAGE_DIR})
+  include_directories(${PYTHON_INCLUDE_PATH})
   #-----------------------------------------------------------------------------
   # compile and link C++ wrappers
   #-----------------------------------------------------------------------------
@@ -556,56 +570,35 @@ macro(pymod)
   else()
     add_custom_target("_${_LIB_NAME}" ALL)
   endif()
-  set(_PY_FILES)  
+  #-----------------------------------------------------------------------------
+  # build ui files
+  #-----------------------------------------------------------------------------
   if (_ARG_UI)
-    add_custom_target("${_LIB_NAME}_ui")    
-    ui_to_python("${_LIB_NAME}_ui" _PY_FILES ${_ARG_UI})
+    ui_to_python(${_LIB_NAME} ${PYMOD_STAGE_DIR} ${_ARG_UI})
   endif()  
-  if (_ARG_PY OR _PY_FILES)
-    set(_EXPECT_IN_DIR FALSE)
-    foreach(_PY_FILE ${_ARG_PY})
-      if (_PY_FILE STREQUAL "IN_DIR")
-        set(_EXPECT_IN_DIR TRUE)
-      else()
-        if (_EXPECT_IN_DIR)
-          set(_EXPECT_IN_DIR FALSE)
-          set(_DIR ${_PY_FILE})
-          set(_ABS_PY_FILES)
-          set(_PY_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${_DIR}")
-          foreach(_PY ${_PY_FILES})
-            list(APPEND _ABS_PY_FILES "${_PY_SOURCE_DIR}/${_PY}")
-          endforeach()
-          install(FILES ${_ABS_PY_FILES} DESTINATION
-                  "${LIB_DIR}/${PYMOD_DIR}/${_DIR}")
-          string(REPLACE "/" "_" _DIR_NO_SLASH "${_DIR}")
-          add_custom_target("${_ARG_NAME}_${_DIR_NO_SLASH}_pymod" ALL)
-          copy_if_different("./" "${PYMOD_STAGE_DIR}/${_DIR}"
-                            "${_ABS_PY_FILES}" "TARGETS"
-                            "${_ARG_NAME}_${_DIR_NO_SLASH}_pymod")
-          compile_py_files(_${_LIB_NAME} ${PYMOD_STAGE_DIR}/${_DIR} ${_ABS_PY_FILES})
-          set(_PY_FILES)
-        else()
-          list(APPEND _PY_FILES "${_PY_FILE}")
-        endif()
-      endif()
-    endforeach()
-    if (_PY_FILES)
-      add_custom_target("${_LIB_NAME}_pymod" ALL)
-      if (_ARG_UI)
-        add_dependencies("${_LIB_NAME}_pymod" "${_LIB_NAME}_ui"})
-      endif()
+  #-----------------------------------------------------------------------------
+  # compile python files
+  #-----------------------------------------------------------------------------
+  if (_ARG_PY)
+    parse_file_list("${_ARG_PY}" _PYFILE_MAP)
+    map(KEYS _PYFILE_MAP _PYFILE_MAP_KEYS)
+    foreach(_DIR ${_PYFILE_MAP_KEYS})
+      map(GET _PYFILE_MAP ${_DIR} _PY_FILES)
       set(_ABS_PY_FILES)
-      set(_PY_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
+      set(_PY_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${_DIR}")
       foreach(_PY ${_PY_FILES})
         list(APPEND _ABS_PY_FILES "${_PY_SOURCE_DIR}/${_PY}")
       endforeach()
-      copy_if_different("./" "${PYMOD_STAGE_DIR}" "${_ABS_PY_FILES}" "TARGETS"
-                        "${_LIB_NAME}_pymod")
-      add_dependencies("_${_LIB_NAME}" "${_LIB_NAME}_pymod")
-      compile_py_files(_${_LIB_NAME} ${PYMOD_STAGE_DIR} ${_PY_FILES})
-      include_directories(${PYTHON_INCLUDE_PATH})
-      install(FILES ${_PY_FILES} DESTINATION "${LIB_DIR}/${PYMOD_DIR}")
-      endif()
+      install(FILES ${_ABS_PY_FILES} DESTINATION "${LIB_DIR}/${PYMOD_DIR}/${_DIR}")
+      string(REPLACE "/" "_" _DIR_NO_SLASH "${_DIR}")
+      set(_PYMOD_TARGET "${_LIB_NAME}_${_DIR_NO_SLASH}_pymod")
+      string(REPLACE "_." "" _PYMOD_TARGET "${_PYMOD_TARGET}")
+      add_custom_target(${_PYMOD_TARGET} ALL)
+      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})
+    endforeach()
   endif()  
   get_target_property(_MOD_DEPS "${_PARENT_NAME}" MODULE_DEPS)
   if(_MOD_DEPS)
diff --git a/examples/gfx/solid.py b/examples/gfx/solid.py
new file mode 100644
index 0000000000000000000000000000000000000000..1840068d410410c1b0394ae2becab4ba2dfe6c99
--- /dev/null
+++ b/examples/gfx/solid.py
@@ -0,0 +1,18 @@
+s=io.LoadSurface("../demos/data/sh2","msms")
+scene.Add(gfx.Surface("s",s))
+
+# alternative shading mode
+scene.SetShadingMode("hf")
+
+# add outlines to surface
+scene["s"].SetOutline(True)
+scene["s"].SetOutlineMode(3)
+
+# turn on solid rendering
+scene["s"].solid=True
+scene["s"].solid_color=gfx.RGB(0.8,0.8,0.7)
+
+scene.AutoAutoslab(False)
+scene.far=170
+scene.near=100
+scene.fog=False
diff --git a/modules/base/pymod/settings.py b/modules/base/pymod/settings.py
index 56bf46b4aeedf36cfcd471390cf361860608682e..34afdc0b2c9bd0db42619ab898b83a544dc48d7f 100644
--- a/modules/base/pymod/settings.py
+++ b/modules/base/pymod/settings.py
@@ -1,6 +1,18 @@
 import os, platform
 import __main__
  
+def GetPlatform():
+  """
+  Returns platform.system(). If the system call is interrupted, it is repeated.
+  This function is a workaround for the buggy system call handling in Python.
+  """
+  system=None
+  while not system:
+    try:
+      system=platform.system()
+    except IOError:
+      pass
+  return system
 
 def GetValue(val_key,val_default=None,prefix='OST'):
   """
@@ -89,7 +101,7 @@ def Locate(file_name, explicit_file_name=None, search_paths=[],
 
   if search_system_paths:
     paths=os.getenv('PATH')
-    if platform.system() == "Windows":
+    if GetPlatform() == "Windows":
       searched+=paths.split(';')
     else:
       searched+=paths.split(':')
diff --git a/modules/base/pymod/table.py b/modules/base/pymod/table.py
index 8af2ab6cc20f088401c9e80038d8bc98e31f8561..37c45feb9f9c6589dd4b9eba45bc70852322c796 100644
--- a/modules/base/pymod/table.py
+++ b/modules/base/pymod/table.py
@@ -90,6 +90,9 @@ class BinaryColExpr:
   def __mul__(self, rhs):
     return BinaryColExpr(operator.mul, self, rhs)
 
+  def __div__(self, rhs):
+    return BinaryColExpr(operator.div, self, rhs)
+
 class TableCol:
   def __init__(self, table, col):
     self._table=table
@@ -119,6 +122,7 @@ class TableCol:
 
   def __mul__(self, rhs):
     return BinaryColExpr(operator.mul, self, rhs)
+
   def __div__(self, rhs):
     return BinaryColExpr(operator.div, self, rhs)
 
@@ -271,6 +275,19 @@ class Table(object):
     '''
     return self.name
 
+  def RenameCol(self, old_name, new_name):
+    """
+    Rename column *old_name* to *new_name*.
+
+    :param old_name: Name of the old column
+    :param new_name: Name of the new column
+    :raises: :exc:`ValueError` when *old_name* is not a valid column
+    """
+    if old_name==new_name:
+      return
+    self.AddCol(new_name, self.col_types[self.GetColIndex(old_name)],
+                self[old_name])
+    self.RemoveCol(old_name)
   def _Coerce(self, value, ty):
     '''
     Try to convert values (e.g. from :class:`str` type) to the specified type
@@ -314,6 +331,22 @@ class Table(object):
     '''
     return self.col_names
   
+  def SearchColNames(self, regex):
+    '''
+    Returns a list of column names matching the regex
+
+    :param regex: regex pattern
+    :type regex: :class:`str`
+
+    :returns: :class:`list` of column names (:class:`str`)
+    '''
+    matching_names = []
+    for name in self.col_names:
+      matches = re.search(regex, name)
+      if matches:
+        matching_names.append(name)
+    return matching_names
+
   def HasCol(self, col):
     '''
     Checks if the column with a given name is present in the table.
@@ -395,6 +428,31 @@ class Table(object):
   def __str__(self):
     return self.ToString()
   
+  def Stats(self, col):
+     idx  = self.GetColIndex(col)
+     text ='''
+Statistics for column %(col)s
+
+  Number of Rows         : %(num)d
+  Number of Rows Not None: %(num_non_null)d 
+  Mean                   : %(mean)f
+  Median                 : %(median)f
+  Standard Deviation     : %(stddev)f
+  Min                    : %(min)f
+  Max                    : %(max)f
+'''
+     data = {
+       'col' : col,
+       'num' : len(self.rows),
+       'num_non_null' : self.Count(col),
+       'median' : self.Median(col),
+       'mean' : self.Mean(col),
+       'stddev' : self.StdDev(col),
+       'min' : self.Min(col),
+       'max' : self.Max(col),
+     }
+     return text % data
+
   def _AddRowsFromDict(self, d, overwrite=None):
     '''
     Add one or more rows from a :class:`dictionary <dict>`.
@@ -453,6 +511,27 @@ class Table(object):
       if not overwrite or not added:
         self.rows.append(new_row)
       
+  def PairedTTest(self, col_a, col_b):
+    """
+    Two-sided test for the null-hypothesis that two related samples 
+    have the same average (expected values)
+    
+    :param col_a: First column
+    :param col_b: Second column
+
+    :returns: P-value  between 0 and 1 that the two columns have the 
+       same average. The smaller the value, the less related the two
+       columns are.
+    """
+    from scipy.stats import ttest_rel
+    xs = []
+    ys = []
+    for x, y in self.Zip(col_a, col_b):
+      if x!=None and y!=None:
+        xs.append(x)
+        ys.append(y)
+    result = ttest_rel(xs, ys)
+    return result[1]
 
   def AddRow(self, data, overwrite=None):
     """
@@ -629,6 +708,10 @@ class Table(object):
     As a special case, if there are no previous rows, and data is not 
     None, rows are added for every item in data.
     """
+
+    if col_name in self.col_names:
+      raise ValueError('Column with name %s already exists'%col_name)
+
     col_type = self._ParseColTypes(col_type, exp_num=1)[0]
     self.col_names.append(col_name)
     self.col_types.append(col_type)
@@ -638,10 +721,15 @@ class Table(object):
         for row in self.rows:
           row.append(data)
       else:
+        if hasattr(data, '__len__') and len(data)!=len(self.rows):
+          self.col_names.pop()
+          self.col_types.pop()
+          raise ValueError('Length of data (%i) must correspond to number of '%len(data) +\
+                           'existing rows (%i)'%len(self.rows))
         for row, d in zip(self.rows, data):
           row.append(d)
 
-    elif data!=None:
+    elif data!=None and len(self.col_names)==1:
       if IsScalar(data):
         self.AddRow({col_name : data})
       else:
@@ -668,7 +756,7 @@ class Table(object):
     args are unary callables returning true if the row should be included in the
     result and false if not.
     """
-    filt_tab=Table(self.col_names, self.col_types)
+    filt_tab=Table(list(self.col_names), list(self.col_types))
     for row in self.rows:
       matches=True
       for func in args:
@@ -897,8 +985,9 @@ class Table(object):
   def Plot(self, x, y=None, z=None, style='.', x_title=None, y_title=None,
            z_title=None, x_range=None, y_range=None, z_range=None,
            color=None, plot_if=None, legend=None,
-           num_z_levels=10, diag_line=False, labels=None, max_num_labels=None,
-           title=None, clear=True, save=False, **kwargs):
+           num_z_levels=10, z_contour=True, z_interpol='nn', diag_line=False,
+           labels=None, max_num_labels=None, title=None, clear=True, save=False,
+           **kwargs):
     """
     Function to plot values from your table in 1, 2 or 3 dimensions using
     `Matplotlib <http://matplotlib.sourceforge.net>`__
@@ -971,6 +1060,13 @@ class Table(object):
     :param save: filename for saving plot
     :type save: :class:`str`
 
+    :param z_contour: draw contour lines
+    :type z_contour: :class:`bool`
+
+    :param z_interpol: interpolation method for 3-dimensional plot (one of 'nn',
+                       'linear')
+    :type z_interpol: :class:`str`
+
     :param \*\*kwargs: additional arguments passed to matplotlib
     
     :returns: the ``matplotlib.pyplot`` module 
@@ -1009,12 +1105,12 @@ class Table(object):
       if clear:
         plt.figure(figsize=[8, 6])
       
-      if x_title:
+      if x_title!=None:
         nice_x=x_title
       else:
         nice_x=MakeTitle(x)
       
-      if y_title:
+      if y_title!=None:
         nice_y=y_title
       else:
         if y:
@@ -1022,7 +1118,7 @@ class Table(object):
         else:
           nice_y=None
       
-      if z_title:
+      if z_title!=None:
         nice_z = z_title
       else:
         if z:
@@ -1063,11 +1159,13 @@ class Table(object):
           levels.append(l)
           l += z_spacing
   
-        xi = np.linspace(min(xs)-0.1,max(xs)+0.1,len(xs)*10)
-        yi = np.linspace(min(ys)-0.1,max(ys)+0.1,len(ys)*10)
-        zi = mlab.griddata(xs, ys, zs, xi, yi)
+        xi = np.linspace(min(xs),max(xs),len(xs)*10)
+        yi = np.linspace(min(ys),max(ys),len(ys)*10)
+        zi = mlab.griddata(xs, ys, zs, xi, yi, interp=z_interpol)
   
-        plt.contour(xi,yi,zi,levels,linewidths=0.5,colors='k')
+        if z_contour:
+          plt.contour(xi,yi,zi,levels,linewidths=0.5,colors='k')
+
         plt.contourf(xi,yi,zi,levels,cmap=plt.cm.jet)
         plt.colorbar(ticks=levels)
             
@@ -1269,7 +1367,208 @@ class Table(object):
         max_val = self.rows[i][idx]
         max_idx = i
     return max_val, max_idx
+
+  def PlotBar(self, col, xlabels=None, ylabel=None, title=None, 
+              color=None, yerr=None, width=0.8, bottom=0, 
+              legend=True, save=False):
+    
+    try:
+      import numpy as np
+      import matplotlib.pyplot as plt
+    except:
+      raise ImportError('PlotBar relies on numpy and matplotlib, but I could not import it!')
+      
+    if len(col)>7:
+      raise ValueError('More than seven bars at one position looks rather meaningless...')
+      
+    standard_colors=['b','g','y','c','m','r','k']
+    data=[]
+  
+    if not isinstance(col,list):
+      col=[col]
+    if not isinstance(yerr,list):
+      yerr=[yerr]*len(self.rows)
+      
+    if not color:
+      color=standard_colors[:len(col)]
+      
+    for c in col:
+      cid=self.GetColIndex(c)
+      temp=list()
+      for r in self.rows:
+        temp.append(r[cid])
+      data.append(temp)
+      
+    if len(yerr)!=len(data[0]):
+      raise RuntimeError('Number of elements in yerr must be consistent with number of elements in each column!')
+      
+    ind=np.arange(len(data[0]))
+    single_bar_width=float(width)/len(data)
+    
+    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,color=color[i],yerr=yerr[i])[0])
+      
+    if title!=None:
+      nice_title=x_title
+    else:
+      nice_title="coolest barplot on earth"
+    ax.set_title(nice_title, size='x-large', fontweight='bold')  
+    
+    if ylabel!=None:
+      nice_y=ylabel
+    else:
+      nice_y="score" 
+    ax.set_ylabel(nice_y)
+    
+    if xlabels:
+      if len(data[0])!=len(xlabels):
+        raise ValueError('Number of xlabels is not consistent with number of rows!')
+    else:
+      xlabels=list()
+      for i in range(1,len(data[0])+1):
+        xlabels.append('Row '+str(i))
+      
+    ax.set_xticks(ind+width*0.5)
+    ax.set_xticklabels(xlabels)
+      
+    if legend:
+      ax.legend(legend_data, col)   
+      
+    if save:
+      plt.savefig(save)
+    
+    return plt
+      
+  def PlotHexbin(self, x, y, title=None, x_title=None, y_title=None, x_range=None, y_range=None, binning='log',
+                 colormap='jet', show_scalebar=False, scalebar_label=None, clear=True, save=False, show=False):
+
+    """
+    Create a heatplot of the data in col x vs the data in col y using matplotlib
+
+    :param x: column name with x data
+    :type x: :class:`str`
+
+    :param y: column name with y data
+    :type y: :class:`str`
+
+    :param title: title of the plot, will be generated automatically if set to None
+    :type title: :class:`str`
+
+    :param x_title: label of x-axis, will be generated automatically if set to None
+    :type title: :class:`str`
+
+    :param y_title: label of y-axis, will be generated automatically if set to None
+    :type title: :class:`str`
+
+    :param x_range: start and end value for first dimension (e.g. [start_x, end_x])
+    :type x_range: :class:`list` of length two
+
+    :param y_range: start and end value for second dimension (e.g. [start_y, end_y])
+    :type y_range: :class:`list` of length two
+
+    :param binning: type of binning. If set to None, the value of a hexbin will
+                    correspond to the number of datapoints falling into it. If
+                    set to 'log', the value will be the log with base 10 of the above
+                    value (log(i+1)). If an integer is provided, the number of a 
+                    hexbin is equal the number of datapoints falling into it divided 
+                    by the integer. If a list of values is provided, these values
+                    will be the lower bounds of the bins.
+    
+    :param colormap: colormap, that will be used. Value can be every colormap defined
+                     in matplotlib or an own defined colormap. You can either pass a
+                     string with the name of the matplotlib colormap or a colormap
+                     object.
+
+    :param show_scalebar: If set to True, a scalebar according to the chosen colormap is shown
+    :type show_scalebar: :class:`bool`
+
+    :param scalebar_label: Label of the scalebar
+    :type scalebar_label: :class:`str`
+
+    :param clear: clear old data from plot
+    :type clear: :class:`bool`
+
+    :param save: filename for saving plot
+    :type save: :class:`str`
+
+    :param show: directly show plot
+    :type show: :class:`bool`
+    
+    """
+
+    try:
+      import matplotlib.pyplot as plt
+      import matplotlib.cm as cm
+    except:
+      raise ImportError('PlotHexbin relies on matplotlib, but I could not import it')
+
+    idx=self.GetColIndex(x)
+    idy=self.GetColIndex(y)
+    xdata=[]
+    ydata=[]
+
+    for r in self.rows:
+      if r[idx]!=None and r[idy]!=None:
+        xdata.append(r[idx])
+        ydata.append(r[idy])
+
+    if clear:
+      plt.clf()
+      
+    if x_title!=None:
+      nice_x=x_title
+    else:
+      nice_x=MakeTitle(x)
+      
+    if y_title!=None:
+      nice_y=y_title
+    else:
+      nice_y=MakeTitle(y)
+
+    if title==None:
+      title = '%s vs. %s' % (nice_x, nice_y)
   
+    if IsStringLike(colormap):
+      colormap=getattr(cm, colormap)
+
+    if x_range and (IsScalar(x_range) or len(x_range)!=2):
+      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')
+    if x_range:
+      plt.xlim((x_range[0], 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)
+
+    plt.title(title, size='x-large', fontweight='bold',
+              verticalalignment='bottom')
+
+    plt.xlabel(nice_x)
+    plt.ylabel(nice_y)
+        
+    if show_scalebar:
+      cb=plt.colorbar()
+      if scalebar_label:
+        cb.set_label(scalebar_label)
+
+    if save:
+      plt.savefig(save)
+
+    if show:
+      plt.show()
+
+    return plt
+        
   def MaxRow(self, col):
     """
     Returns the row containing the cell with the maximal value in col. If 
@@ -1278,9 +1577,12 @@ class Table(object):
 
     :param col: column name
     :type col: :class:`str`
+
+    :returns: row with maximal col value or None if the table is empty
     """
     val, idx = self._Max(col)
-    return self.rows[idx]
+    if idx!=None:
+      return self.rows[idx]
   
   def Max(self, col):
     """
@@ -1342,9 +1644,12 @@ class Table(object):
 
     :param col: column name
     :type col: :class:`str`
+
+    :returns: row with minimal col value or None if the table is empty
     """
     val, idx = self._Min(col)
-    return self.rows[idx]
+    if idx!=None:
+      return self.rows[idx]
   
   def MinIdx(self, col):
     """
@@ -1480,6 +1785,45 @@ class Table(object):
     
     self.AddCol(mean_col_name, 'f', mean_rows)
     
+  def Percentiles(self, col, nths):
+    """
+    returns the percentiles of column *col* given in *nths*.
+
+    The percentils are calculated as 
+    
+    .. code-block:: python
+
+      values[min(len(values), int(round(len(values)*p/100+0.5)-1))]
+
+    where values are the sorted values of *col* not equal to none
+    :param: nths: list of percentiles to be calculated. Each percentil is a number
+        between 0 and 100.
+
+    :raises: :class:`TypeError` if column type is ``string``
+    :returns: List of percentils in the same order as given in *nths*
+    """
+    idx = self.GetColIndex(col)
+    col_type = self.col_types[idx]
+    if col_type!='int' and col_type!='float' and col_type!='bool':
+      raise TypeError("Median can only be used on numeric column types")
+    
+    for nth in nths:
+      if nth < 0 or nth > 100:
+        raise ValueError("percentiles must be between 0 and 100")
+    vals=[]
+    for v in self[col]:
+      if v!=None:
+        vals.append(v)
+    vals=sorted(vals)
+    if len(vals)==0:
+      return [None]*len(nths)
+    percentiles=[]
+    
+    for nth in nths:
+      p=vals[min(len(vals)-1, int(round(len(vals)*nth/100.0+0.5)-1))]
+      percentiles.append(p)
+    return percentiles
+
   def Median(self, col):
     """
     Returns the median of the given column. Cells with None are ignored. Returns 
@@ -1625,6 +1969,8 @@ class Table(object):
     ost             ost-specific format (human readable)
     csv             comma separated values (human readable)
     pickle          pickled byte stream (binary)
+    html            HTML table
+    context         ConTeXt table
     =============   =======================================
 
     :param stream_or_filename: filename or stream for writing output
@@ -1642,6 +1988,10 @@ class Table(object):
       return self._SaveCSV(stream_or_filename, sep=sep)
     if format=='pickle':
       return self._SavePickle(stream_or_filename)
+    if format=='html':
+      return self._SaveHTML(stream_or_filename)
+    if format=='context':
+      return self._SaveContext(stream_or_filename)
     raise ValueError('unknown format "%s"' % format)
 
   def _SavePickle(self, stream):
@@ -1649,6 +1999,79 @@ class Table(object):
       stream=open(stream, 'wb')
     cPickle.dump(self, stream, cPickle.HIGHEST_PROTOCOL)
 
+  def _SaveHTML(self, stream_or_filename):
+    def _escape(s):
+      return s.replace('&', '&amp;').replace('>', '&gt;').replace('<', '&lt;')
+
+    file_opened = False
+    if not hasattr(stream_or_filename, 'write'):
+      stream = open(stream_or_filename, 'w')
+      file_opened = True
+    else:
+      stream = stream_or_filename
+    stream.write('<table>') 
+    stream.write('<tr>')
+    for col_name in self.col_names:
+      stream.write('<th>%s</th>' % _escape(col_name)) 
+    stream.write('</tr>')
+    for row in self.rows:
+      stream.write('<tr>')
+      for i, col in enumerate(row):
+        val = ''
+        if col != None:
+           if self.col_types[i] == 'float':
+             val = '%.3f' % col
+           elif self.col_types[i] == 'int':
+             val = '%d' % col
+           elif self.col_types[i] == 'bool':
+             val = col and 'true' or 'false'
+           else:
+             val  = str(col)
+        stream.write('<td>%s</td>' % _escape(val))
+      stream.write('</tr>')
+    stream.write('</table>')
+    if file_opened:
+      stream.close()
+  def _SaveContext(self, stream_or_filename):
+    file_opened = False
+    if not hasattr(stream_or_filename, 'write'):
+      stream = open(stream_or_filename, 'w')
+      file_opened = True
+    else:
+      stream = stream_or_filename
+    stream.write('\\starttable[') 
+    for col_type in self.col_types:
+      if col_type =='string':
+        stream.write('l|')
+      elif col_type=='int':
+        stream.write('r|')
+      elif col_type =='float':
+        stream.write('i3r|')
+      else:
+        stream.write('l|')
+    stream.write(']\n\\HL\n')
+    for col_name in self.col_names:
+      stream.write('\\NC \\bf %s' % col_name) 
+    stream.write(' \\AR\\HL\n')
+    for row in self.rows:
+      for i, col in enumerate(row):
+        val = '---'
+        if col != None:
+           if self.col_types[i] == 'float':
+             val = '%.3f' % col
+           elif self.col_types[i] == 'int':
+             val = '%d' % col
+           elif self.col_types[i] == 'bool':
+             val = col and 'true' or 'false'
+           else:
+             val  = str(col)
+        stream.write('\\NC %s' % val)
+      stream.write(' \\AR\n')
+    stream.write('\\HL\n')
+    stream.write('\\stoptable')
+    if file_opened:
+      stream.close()
+
   def _SaveCSV(self, stream, sep):
     if not hasattr(stream, 'write'):
       stream=open(stream, 'wb')
@@ -1712,7 +2135,7 @@ class Table(object):
     
 
 
-  def GaussianSmooth(self, col, std=1.0, na_value=0.0):
+  def GaussianSmooth(self, col, std=1.0, na_value=0.0, padding='reflect', c=0.0):
 
     '''
     In place gaussian smooth of a column in the table with a given standard deviation.
@@ -1727,13 +2150,22 @@ class Table(object):
     :param na_value: all na (None) values of the speciefied column are set to na_value before smoothing
     :type na_value: `scalar`
 
+    :param padding: allows to handle padding behaviour see scipy ndimage.gaussian_filter1d documentation for more information. standard is reflect
+    :type padding: :class:`str`
+
+    :param c: constant value used for padding if padding mode is constant
+    :type c: `scalar`
+
+
+
     :warning: The function depends on *scipy*
     ''' 
 
     try:
       from scipy import ndimage
+      import numpy as np
     except ImportError:
-      LogError("Function needs scipy.ndimage, but I could no import it")
+      LogError("I need scipy.ndimage and numpy, but could not import it")
       raise
       
     idx = self.GetColIndex(col)
@@ -1748,7 +2180,8 @@ class Table(object):
       else:
         vals.append(na_value)
 
-    smoothed_values_ndarray=ndimage.gaussian_filter1d(vals,std)
+    
+    smoothed_values_ndarray=ndimage.gaussian_filter1d(vals,std, mode=padding, cval=c)
 
     result=[]
 
@@ -1905,6 +2338,8 @@ class Table(object):
     where a '-' values means smallest values first and therefore, the smaller
     the value, the better.
     
+    :warning: If either the value of *class_col* or *score_col* is *None*, the
+              data in this row is ignored.
     '''
     
     ALLOWED_DIR = ['+','-']
@@ -1927,17 +2362,35 @@ class Table(object):
     x = [0]
     y = [0]
     enr = 0
-    for i,row in enumerate(self.rows):
+    old_score_val = None
+    i = 0
+
+    for row in self.rows:
       class_val = row[class_idx]
+      score_val = row[score_idx]
+      if class_val==None or score_val==None:
+        continue
       if class_val!=None:
+        if old_score_val==None:
+          old_score_val = score_val
+        if score_val!=old_score_val:
+          x.append(i)
+          y.append(enr)
+          old_score_val = score_val
+        i+=1
         if class_type=='bool':
           if class_val==True:
             enr += 1
         else:
           if (class_dir=='-' and class_val<=class_cutoff) or (class_dir=='+' and class_val>=class_cutoff):
             enr += 1
-      x.append(i+1)
-      y.append(enr)
+    x.append(i)
+    y.append(enr)
+
+    # if no false positives or false negatives values are found return None
+    if x[-1]==0 or y[-1]==0:
+      return None
+
     x = [float(v)/x[-1] for v in x]
     y = [float(v)/y[-1] for v in y]
     return x,y
@@ -1956,10 +2409,12 @@ class Table(object):
     try:
       import numpy as np
       
-      enrx, enry = self.ComputeEnrichment(score_col, class_col, score_dir,
+      enr = self.ComputeEnrichment(score_col, class_col, score_dir,
                                           class_dir, class_cutoff)
       
-      return np.trapz(enry, enrx)
+      if enr==None:
+        return None
+      return np.trapz(enr[1], enr[0])
     except ImportError:
       LogError("Function needs numpy, but I could not import it.")
       raise
@@ -1990,6 +2445,9 @@ class Table(object):
     is of type bool) or evaluated to True (if column is of type int or float
     (depending on *class_dir* and *class_cutoff*))) the ROC is not defined and
     the function will return *None*.
+
+    :warning: If either the value of *class_col* or *score_col* is *None*, the
+              data in this row is ignored.
     '''
 
     ALLOWED_DIR = ['+','-']
@@ -2018,6 +2476,8 @@ class Table(object):
     for i,row in enumerate(self.rows):
       class_val = row[class_idx]
       score_val = row[score_idx]
+      if class_val==None or score_val==None:
+        continue
       if class_val!=None:
         if old_score_val==None:
           old_score_val = score_val
@@ -2374,4 +2834,3 @@ def Merge(table1, table2, by, only_matching=False):
       new_tab.AddRow(row)
   return new_tab
 
-  
diff --git a/modules/base/src/CMakeLists.txt b/modules/base/src/CMakeLists.txt
index 6bc47461f8c012949e77afe150d9f996caca1730..e6691bc1de9af1dccafbaebad7b6b399b0fa81e4 100644
--- a/modules/base/src/CMakeLists.txt
+++ b/modules/base/src/CMakeLists.txt
@@ -8,6 +8,7 @@ string_ref.cc
 platform.cc
 message.cc
 test_utils/compare_files.cc
+boost_filesystem_helper.cc
 )
 
 set(OST_BASE_HEADERS
@@ -30,6 +31,7 @@ string_ref.hh
 pod_vector.hh
 fixed_string.hh
 tri_matrix.hh
+boost_filesystem_helper.hh
 )
 
 set(OST_EXPORT_HELPERS
diff --git a/modules/base/src/boost_filesystem_helper.cc b/modules/base/src/boost_filesystem_helper.cc
new file mode 100644
index 0000000000000000000000000000000000000000..b235b0498dbb26fee19814e41692d254c2304f87
--- /dev/null
+++ b/modules/base/src/boost_filesystem_helper.cc
@@ -0,0 +1,22 @@
+//------------------------------------------------------------------------------
+// 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: Valerio Mariani
+*/
+
diff --git a/modules/base/src/boost_filesystem_helper.hh b/modules/base/src/boost_filesystem_helper.hh
new file mode 100644
index 0000000000000000000000000000000000000000..5418253fd7553f7f715e8259d1f6f08615080ca1
--- /dev/null
+++ b/modules/base/src/boost_filesystem_helper.hh
@@ -0,0 +1,44 @@
+//------------------------------------------------------------------------------
+// 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: Valerio Mariani
+*/
+
+#ifndef OST_BOOST_FILESYSTEM_HELPER_HH
+#define OST_BOOST_FILESYSTEM_HELPER_HH
+
+#include <boost/filesystem/path.hpp>
+
+namespace {
+
+inline
+String BFPathToString(const boost::filesystem::path& path)
+{
+#if BOOST_FILESYSTEM_VERSION==3 || BOOST_VERSION<103400
+  return path.string();
+#else
+  return path.file_string();
+#endif
+}
+
+}
+
+
+
+#endif // OST_BOOST_FILESYSTEM_HELPER
diff --git a/modules/base/tests/test_string_ref.cc b/modules/base/tests/test_string_ref.cc
index 8d69f0ce80ff297a7dd27149fdffad9548982cbe..05b9bd84416d083d7b9c178914550305fb922d95 100644
--- a/modules/base/tests/test_string_ref.cc
+++ b/modules/base/tests/test_string_ref.cc
@@ -30,7 +30,22 @@ using namespace ost;
 
 BOOST_AUTO_TEST_SUITE( base );
 
-BOOST_AUTO_TEST_CASE( test_string_ref)
+
+BOOST_AUTO_TEST_CASE(test_whitespace_split)
+{
+  std::string s=" 1 2  \r\n 3  4\t5 "; 
+  StringRef sr(s.c_str(), s.size());
+  std::vector<StringRef> srl=sr.split();
+  BOOST_CHECK_EQUAL(srl.size(), static_cast<size_t>(5));
+  BOOST_CHECK_EQUAL(srl[0], StringRef("1", 1));
+  BOOST_CHECK_EQUAL(srl[1], StringRef("2", 1));
+  BOOST_CHECK_EQUAL(srl[2], StringRef("3", 1));
+  BOOST_CHECK_EQUAL(srl[3], StringRef("4", 1));
+  BOOST_CHECK_EQUAL(srl[4], StringRef("5", 1));
+}
+
+
+BOOST_AUTO_TEST_CASE(test_string_ref)
 {
   StringRef sr("12345", 5);
   BOOST_CHECK_EQUAL(sr.length(), size_t(5));
diff --git a/modules/base/tests/test_table.py b/modules/base/tests/test_table.py
index 21fd58a679df759d4824c20c3a1104e3879bb652..cd11bd729623d9b5463f4cc8a67daf43a0f10cd6 100644
--- a/modules/base/tests/test_table.py
+++ b/modules/base/tests/test_table.py
@@ -163,6 +163,10 @@ class TestTable(unittest.TestCase):
     diff = ImageChops.difference(img1, img2)
     self.assertEqual(diff.getbbox(),None)
 
+  def testSearchColNames(self):
+    tab = self.CreateTestTable()
+    self.assertEquals(tab.SearchColNames('d$'), ['second', 'third'])
+    self.assertEquals(tab.SearchColNames('(first|third)'), ['first','third'])
 
   def testZip(self):
     tab=Table(['col1', 'col2', 'col3', 'col4'], 'sssi')
@@ -192,7 +196,14 @@ class TestTable(unittest.TestCase):
     self.assertEquals(type(z[0][1]),int)
     self.assertEquals(type(z[1][1]),int)
     self.assertRaises(ValueError, tab.Zip, 'col5', 'col3')
-
+  def testPercentiles(self):
+    tab = Table(['nums'], 'i')
+    self.assertEqual(tab.Percentiles('nums', [0,100]), [None, None])
+    self.assertRaises(ValueError, tab.Percentiles, 'nums', [101])
+    self.assertRaises(ValueError, tab.Percentiles, 'nums', [-1])
+    for i in (35,15,50,40,20):
+      tab.AddRow([i])
+    self.assertEqual(tab.Percentiles('nums', [0,30,40,100]), [15,20,35,50])
   def testTableInitEmpty(self):
     '''
     empty table
@@ -304,6 +315,24 @@ class TestTable(unittest.TestCase):
     self.CompareColNames(tab, ['x'])
     self.CompareColTypes(tab, 'x', 'f')
     
+  def testTableFilterColNamesTypes(self):
+    """
+    make sure the col_names and col_types are copied. 
+    We don't want them to be referenced to the original table.
+    This leads to strange surprises.
+    """
+    t = Table(['a', 'b'], 'ii')
+    t.AddRow([1,2])
+    t.AddRow([2,3])
+    t.AddRow([2,3])
+    t.AddRow([3,3])
+    t.AddRow([4,3])
+    t.AddRow([5,3])
+    filt = t.Filter(a=2)
+    filt.AddCol('c', 'i')
+    self.assertEqual(len(t.col_names), 2)
+    self.assertEqual(len(t.col_types), 2)
+
   def testTableInitMultiColMultiValueNonEmpty(self):
     '''
     table with two column and four rows:
@@ -588,6 +617,15 @@ class TestTable(unittest.TestCase):
                                    'foo': [True, None, True],
                                    'bar': [1, 2, 3]})
 
+  def testRaiseErrorOnWrongDataLengthAddCol(self):
+    tab = Table()
+    tab.AddCol('a','f',[4.2,4.2,4.2])
+    self.assertRaises(ValueError, tab.AddCol, 'b', 'f', [4.2,4.2])
+
+  def testRaiseErrorColNameAlreadyExists(self):
+    tab = Table()
+    tab.AddCol('awesome','f')
+    self.assertRaises(ValueError, tab.AddCol, 'awesome', 'f')
 
   def testRaiseErrorOnWrongColumnTypes(self):
     # wrong columns types in init
@@ -849,6 +887,19 @@ class TestTable(unittest.TestCase):
     # read from disc
     tab_loaded_fname = Table.Load('saveloadtable_withspaces_filename_out.tab')
     self.CompareDataFromDict(tab_loaded_fname, {'first': ['x','foo',None,'hello spaces'], 'second': [3,None,9,10], 'third': [None,2.2,3.3,10.1]})
+  def testSaveTableHTML(self):
+    import StringIO
+    tab = self.CreateTestTable()
+    stream = StringIO.StringIO()
+    tab.Save(stream, format='html')
+    self.assertEqual(stream.getvalue(), '<table><tr><th>first</th><th>second</th><th>third</th></tr><tr><td>x</td><td>3</td><td></td></tr><tr><td>foo</td><td></td><td>2.200</td></tr><tr><td></td><td>9</td><td>3.300</td></tr></table>')
+  def testSaveTableContext(self):
+    import StringIO
+    tab = self.CreateTestTable()
+    stream = StringIO.StringIO()
+    tab.Save(stream, format='context')
+    self.assertEqual(stream.getvalue(), 
+                     '\\starttable[l|r|i3r|]\n\\HL\n\\NC \\bf first\\NC \\bf second\\NC \\bf third \\AR\\HL\n\\NC x\\NC 3\\NC --- \\AR\n\\NC foo\NC ---\NC 2.200 \\AR\n\\NC ---\\NC 9\\NC 3.300 \\AR\n\\HL\n\\stoptable')
 
   def testSaveLoadTableCSV(self):
     tab = self.CreateTestTable()
@@ -1137,6 +1188,13 @@ class TestTable(unittest.TestCase):
     self.assertRaises(ValueError, tab.Plot, x='second', y='third', y_range=[1,2,3])
     self.assertRaises(ValueError, tab.Plot, x='second', y='third', z_range='st')
 
+  def testHexbin(self):
+    if not HAS_MPL or not HAS_NUMPY:
+      return
+    tab = self.CreateTestTable()
+    self.assertRaises(ValueError, tab.PlotHexbin, x='second', y='third', x_range=1)
+    self.assertRaises(ValueError, tab.PlotHexbin, x='second', y='third', x_range=[1,2,3])
+
   def testPlotEnrichment(self):
     if not HAS_MPL or not HAS_PIL:
       return
@@ -1154,6 +1212,24 @@ class TestTable(unittest.TestCase):
     #self.CompareImages(img1, img2)
     #pl.show()
     
+  def testCalcEnrichmentAUCwithNone(self):
+    if not HAS_NUMPY:
+      return
+    tab = Table(['pred_bfactors','ref_distances'], 'ff',
+                ref_distances=[None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, 2.445, 2.405, 2.361, 2.124, 1.957, 1.897, 1.422, 1.348, 1.247, 1.165, 1.153, 1.011, 0.992, 0.885, 0.852, 0.775, 0.757, 0.755, 0.735, 0.71, 0.656, 0.636, 0.609, 0.607, 0.604, 0.595, 0.572, 0.549, 0.458, 0.438, 0.41, 0.345, 0.304, 0.254, 0.241, 0.227, 2.68, 1.856, 1.312, 0.453],
+                pred_bfactors=[1.85000,  2.01000,  2.12000,  2.14000,  2.15000,  2.18000,  2.20000,  2.26000,  2.28000,  2.31000,  2.37000,  2.38000,  2.39000,  2.39000,  2.43000,  2.43000,  2.49000,  2.51000,  2.56000,  2.58000,  2.65000,  2.67000,  2.72000,  2.75000,  2.77000,  2.81000,  2.91000,  2.95000,  3.09000,  3.12000,  3.25000,  3.30000,  3.33000,  3.38000,  3.39000,  3.41000,  3.41000,  3.45000,  3.57000,  3.59000,  3.64000,  3.76000,  3.76000,  3.92000,  3.95000,  3.95000,  4.05000,  4.06000,  4.07000,  4.14000,  4.14000,  4.18000,  4.24000,  4.28000,  4.40000,  4.43000,  4.43000,  4.48000,  4.50000,  4.51000,  4.54000,  4.63000,  4.64000,  4.79000,  4.93000,  5.07000,  5.12000,  5.20000,  5.41000,  5.42000,  5.44000,  5.52000,  5.68000,  5.78000,  5.80000,  5.93000,  6.11000,  6.31000,  6.50000,  6.53000,  6.55000,  6.60000,  6.73000,  6.79000,  6.81000,  7.44000,  8.45000,  8.81000,  9.04000,  9.29000,  9.30000, 10.99000, 11.42000, 12.55000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 99.99000, 99.99000, 99.99000, 99.99000])
+
+    auc = tab.ComputeEnrichmentAUC(score_col='pred_bfactors', class_col='ref_distances')
+    self.assertAlmostEqual(auc, 0.50714285714285)
+
+    # when removing all None lines, no true positive is left
+    auc = tab.ComputeEnrichmentAUC(score_col='ref_distances', class_col='pred_bfactors')
+    self.assertEqual(auc, None)
+
+    # when increasing the cutoff, we have again true positives
+    auc = tab.ComputeEnrichmentAUC(score_col='ref_distances', class_col='pred_bfactors', class_cutoff=60)
+    self.assertAlmostEqual(auc, 0.52013888888)
+
   def testCalcEnrichmentAUC(self):
     if not HAS_NUMPY:
       return
@@ -1205,6 +1281,24 @@ class TestTable(unittest.TestCase):
     #self.CompareImages(img1, img2)
     #pl.show()
 
+  def testCalcROCAUCwithNone(self):
+    if not HAS_NUMPY:
+      return
+    tab = Table(['pred_bfactors','ref_distances'], 'ff',
+                ref_distances=[None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, 2.445, 2.405, 2.361, 2.124, 1.957, 1.897, 1.422, 1.348, 1.247, 1.165, 1.153, 1.011, 0.992, 0.885, 0.852, 0.775, 0.757, 0.755, 0.735, 0.71, 0.656, 0.636, 0.609, 0.607, 0.604, 0.595, 0.572, 0.549, 0.458, 0.438, 0.41, 0.345, 0.304, 0.254, 0.241, 0.227, 2.68, 1.856, 1.312, 0.453],
+                pred_bfactors=[1.85000,  2.01000,  2.12000,  2.14000,  2.15000,  2.18000,  2.20000,  2.26000,  2.28000,  2.31000,  2.37000,  2.38000,  2.39000,  2.39000,  2.43000,  2.43000,  2.49000,  2.51000,  2.56000,  2.58000,  2.65000,  2.67000,  2.72000,  2.75000,  2.77000,  2.81000,  2.91000,  2.95000,  3.09000,  3.12000,  3.25000,  3.30000,  3.33000,  3.38000,  3.39000,  3.41000,  3.41000,  3.45000,  3.57000,  3.59000,  3.64000,  3.76000,  3.76000,  3.92000,  3.95000,  3.95000,  4.05000,  4.06000,  4.07000,  4.14000,  4.14000,  4.18000,  4.24000,  4.28000,  4.40000,  4.43000,  4.43000,  4.48000,  4.50000,  4.51000,  4.54000,  4.63000,  4.64000,  4.79000,  4.93000,  5.07000,  5.12000,  5.20000,  5.41000,  5.42000,  5.44000,  5.52000,  5.68000,  5.78000,  5.80000,  5.93000,  6.11000,  6.31000,  6.50000,  6.53000,  6.55000,  6.60000,  6.73000,  6.79000,  6.81000,  7.44000,  8.45000,  8.81000,  9.04000,  9.29000,  9.30000, 10.99000, 11.42000, 12.55000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 50.00000, 99.99000, 99.99000, 99.99000, 99.99000])
+
+    auc = tab.ComputeROCAUC(score_col='pred_bfactors', class_col='ref_distances')
+    self.assertAlmostEqual(auc, 0.55714285714285705)
+
+    # when removing all None lines, no true positive is left
+    auc = tab.ComputeROCAUC(score_col='ref_distances', class_col='pred_bfactors')
+    self.assertEqual(auc, None)
+
+    # when increasing the cutoff, we have again true positives
+    auc = tab.ComputeROCAUC(score_col='ref_distances', class_col='pred_bfactors', class_cutoff=60)
+    self.assertAlmostEqual(auc, 0.701388888888888)
+
   def testCalcROCAUC(self):
     if not HAS_NUMPY:
       return
@@ -1354,7 +1448,52 @@ class TestTable(unittest.TestCase):
     
     self.assertRaises(RuntimeError, tab.GetOptimalPrefactors, 'c','a','b',weight='d')
     self.assertRaises(RuntimeError, tab.GetOptimalPrefactors, 'c',weights='d')
-    
+
+  def testGaussianSmooth(self):
+    tab = Table(['a','b','c','d','e','f'],'fffffi',
+                a=[0.5,1.0,2.0,3.0,2.5,1.0,0.5,2.3,1.0],
+                b=[0.5,1.0,2.0,3.0,2.5,1.0,0.5,2.3,1.0],
+                c=[0.5,1.0,2.0,3.0,2.5,1.0,0.5,2.3,1.0],
+                d=[0.5,1.0,2.0,3.0,2.5,1.0,0.5,2.3,1.0],
+                e=[0.5,1.0,2.0,3.0,2.5,1.0,0.5,2.3,1.0],
+                f=[2,6,5,3,8,7,4,4,4])
+
+    tab.GaussianSmooth('a')
+    tab.GaussianSmooth('b', std=2.0)
+    tab.GaussianSmooth('c', padding='wrap')
+    tab.GaussianSmooth('d', padding='constant')
+    tab.GaussianSmooth('e', padding='constant',c=3.0)
+    tab.GaussianSmooth('f')
+
+    ref_list=[]
+
+    ref_list.append([0.74729766,1.20875404,1.93459464,2.39849076,2.11504816,
+                     1.42457403,1.20524937,1.41025075,1.3557406])
+    ref_list.append([1.23447249,1.41295267,1.65198705,1.79959835,1.78131778,
+                     1.64501718,1.49728102,1.40589715,1.37147629])
+    ref_list.append([0.9315564,1.24131027,1.93698455,2.39855767,2.11504816,
+                     1.42450711,1.20285946,1.37769451,1.17148186])
+    ref_list.append([0.5630556,1.17705895,1.93224488,2.39842384,2.11504816,
+                     1.4244402,1.2005097,1.34599942,0.9872398 ])
+    ref_list.append([1.46464039,1.35272941,1.94594196,2.39882533,2.11504816,
+                     1.42484169,1.21420677,1.52166988,1.88882459])
+    ref_list.append([3,4,4,5,6,6,4,4,4])
+
+    tab_list=[[],[],[],[],[],[]]
+    
+    for row in tab.rows:
+      for i,v in enumerate(row):
+        tab_list[i].append(v)
+
+    for i in range(len(ref_list[0])):
+      self.assertAlmostEquals(tab_list[0][i],ref_list[0][i])
+      self.assertAlmostEquals(tab_list[1][i],ref_list[1][i])
+      self.assertAlmostEquals(tab_list[2][i],ref_list[2][i])
+      self.assertAlmostEquals(tab_list[3][i],ref_list[3][i])
+      self.assertAlmostEquals(tab_list[4][i],ref_list[4][i])
+      self.assertAlmostEquals(tab_list[5][i],ref_list[5][i])
+     
+
   def testIsEmpty(self):
     tab = Table()
     self.assertTrue(tab.IsEmpty())
diff --git a/modules/config/CMakeLists.txt b/modules/config/CMakeLists.txt
index c7cdc9468303279890c5a9a84ce2d9aae4fae4ad..4f7e645ae21730204495c46ce91bc624bf4b28bb 100644
--- a/modules/config/CMakeLists.txt
+++ b/modules/config/CMakeLists.txt
@@ -74,6 +74,4 @@ set(VERSION_HH_FILE "${CMAKE_CURRENT_SOURCE_DIR}/version.hh")
 configure_file(config.hh.in ${CONFIG_HH_FILE})
 configure_file(version.hh.in ${VERSION_HH_FILE})
 add_custom_target(ost_config)
-stage_headers("${OST_CONFIG_HEADERS}" "ost" 
-              "ost_config" "" "ost")
-install(FILES ${OST_CONFIG_HEADERS} DESTINATION include/ost)
+stage_and_install_headers("${OST_CONFIG_HEADERS}" "ost" "ost_config")
diff --git a/modules/doc/table.rst b/modules/doc/table.rst
index 19d9c3c278a08f908fe7c8d712d4881ac4774aab..f3af1277017dc3d8a20639362e32174a673734c7 100644
--- a/modules/doc/table.rst
+++ b/modules/doc/table.rst
@@ -59,11 +59,13 @@ Functions You Might be Interested In
 :meth:`~ost.table.Table.AddRow`               add a row to the table
 :meth:`~ost.table.Table.AddCol`               add a column to the table
 :meth:`~ost.table.Table.RemoveCol`            remove a column from the table
+:meth:`~ost.table.Table.RenameCol`            rename a column
 :meth:`~ost.table.Table.Extend`               append a table to the end of another table
 :meth:`~ost.table.Merge`                      merge two tables together
 :meth:`~ost.table.Table.Sort`                 sort table by column
 :meth:`~ost.table.Table.Filter`               filter table by values
 :meth:`~ost.table.Table.Zip`                  extract multiple columns at once
+:meth:`~ost.table.Table.SearchColNames`       search for matching column names
 
 **Input/Output**
 :meth:`~ost.table.Table.Save`                 save a table to a file
@@ -93,6 +95,8 @@ Functions You Might be Interested In
 :meth:`~ost.table.Table.PlotHistogram`        Plot data as histogram
 :meth:`~ost.table.Table.PlotROC`              Plot receiver operating characteristics (ROC)
 :meth:`~ost.table.Table.PlotEnrichment`       Plot enrichment
+:meth:`~ost.table.Table.PlotHexbin`           Hexagonal density plot
+:meth:`~ost.table.Table.PlotBar`              Bar plot
 
 
 ============================================= ============================================
@@ -105,4 +109,4 @@ The Table class
   :members:
   :undoc-members: SUPPORTED_TYPES
 
-.. autofunction:: ost.table.Merge
\ No newline at end of file
+.. autofunction:: ost.table.Merge
diff --git a/modules/geom/src/transform.cc b/modules/geom/src/transform.cc
index d2a07f6ab0a701d0194bdcd1a4d300f039017f1f..9c00d5e8c4fc2aa1cc3b5b71e498e99585aa0ee0 100644
--- a/modules/geom/src/transform.cc
+++ b/modules/geom/src/transform.cc
@@ -18,7 +18,6 @@
 //------------------------------------------------------------------------------
 
 #include <ost/config.hh>
-#include <ost/log.hh>
 
 #include "transform.hh"
 #include "vecmat3_op.hh"
@@ -40,6 +39,13 @@ void Transform::SetMatrix(const Mat4& m)
 {
   tm_=m;
   ttm_ = Transpose(tm_);
+  try {
+    itm_ = Invert(tm_);
+  } catch (GeomException& e) {
+    std::cerr << "caught GeomException in Transform::SetMatrix: " << e.what() << std::endl;
+    std::cerr << m << std::endl;
+    itm_=geom::Mat4();
+  }
   update_components();
 }
 
@@ -151,6 +157,18 @@ Vec4 Transform::Apply(const Vec4& v) const
   return nrvo;
 }
 
+Vec3 Transform::ApplyInverse(const Vec3& v) const
+{
+  Vec3 nrvo(itm_*Vec4(v));
+  return nrvo;
+}
+
+Vec4 Transform::ApplyInverse(const Vec4& v) const
+{
+  Vec4 nrvo=itm_*v;
+  return nrvo;
+}
+
 geom::AlignedCuboid Transform::Apply(const geom::AlignedCuboid& c) const
 {
   geom::Vec3 cmin=c.GetMin();
@@ -168,6 +186,13 @@ geom::AlignedCuboid Transform::Apply(const geom::AlignedCuboid& c) const
   return geom::AlignedCuboid(minc,maxc);
 }
 
+Transform Transform::Apply(const Transform& tf) const
+{
+  Transform nrvo(*this);
+  nrvo.SetMatrix(tf.GetMatrix()*nrvo.GetMatrix());
+  return nrvo;
+}
+
 /*
   The order of the transformations given herein is conceptually
   "backward" as they are applied to a vertex, because the left-right
@@ -189,14 +214,14 @@ void Transform::update_tm()
 {
   tm_ =
     Mat4(1.0,0.0,0.0,trans_[0],
-               0.0,1.0,0.0,trans_[1],
-               0.0,0.0,1.0,trans_[2],
-               0.0,0.0,0.0,1.0) *
+         0.0,1.0,0.0,trans_[1],
+         0.0,0.0,1.0,trans_[2],
+         0.0,0.0,0.0,1.0) *
     Mat4(rot_) *
     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);
+         0.0,1.0,0.0,-cen_[1],
+         0.0,0.0,1.0,-cen_[2],
+         0.0,0.0,0.0,1.0);
   ttm_ = Transpose(tm_);
   // TODO: calculate from rot, cen and trans
   try {
@@ -209,11 +234,11 @@ void Transform::update_tm()
 
 void Transform::update_components()
 {
+  // there is no way to extract the centering component
+  // so we just get a rotation and translation
   rot_ = tm_.ExtractRotation();
-  cen_ = tm_.ExtractTranslation();
-  trans_[0] = tm_(3,0);
-  trans_[1] = tm_(3,1);
-  trans_[2] = tm_(3,2);
+  trans_ = tm_.ExtractTranslation();
+  cen_ = Vec3(0,0,0);
 }
 
 } // ns
diff --git a/modules/geom/src/transform.hh b/modules/geom/src/transform.hh
index 997f763950d7f94a7f7c6df35ea11f210b40847d..6965c48437dd5b4c041aabf46eb705ec87bd9ec4 100644
--- a/modules/geom/src/transform.hh
+++ b/modules/geom/src/transform.hh
@@ -39,7 +39,10 @@ namespace geom {
 class DLLEXPORT_OST_GEOM Transform {
 public:
   Transform();
-
+  
+  /// \brief reset to identity
+  void Reset() {*this=Transform();}
+  
   /// \brief retrieve transformation matrix
   Mat4 GetMatrix() const {return tm_;}
   /// \brief retrieve transposed transformation matrix
@@ -78,10 +81,18 @@ public:
   void SetTrans(const Vec3& t);
   Vec3 GetTrans() const;  
   //@}
-  
+
+  // apply to a vec3 and return result
   Vec3 Apply(const Vec3& v) const;
+  // apply to a vec4 and return result
   Vec4 Apply(const Vec4& v) const;
+  // apply inverse to a vec3 and return result
+  Vec3 ApplyInverse(const Vec3& v) const;
+  // apply inverse to a vec4 and return result
+  Vec4 ApplyInverse(const Vec4& v) const;
+  // apply to an aligned cuboid and return result
   AlignedCuboid Apply(const AlignedCuboid& c) const;
+  Transform Apply(const Transform& tf) const;
 
 private:
   Mat3 rot_;
diff --git a/modules/geom/src/vec3.hh b/modules/geom/src/vec3.hh
index 7b4bb5b33fd33cccfe285f6d602bfa8d968bb687..c1cde046c0174c7571701ca6ee82e9645ccc41c8 100644
--- a/modules/geom/src/vec3.hh
+++ b/modules/geom/src/vec3.hh
@@ -239,11 +239,15 @@ namespace geom {
   inline Vec3::Vec3(const Vec4& v): x(v.x), y(v.y), z(v.z) 
   { 
     if (std::fabs(v.w)<1e-10) {
-      throw DivideByZeroException();
+      // it is better to ignore very small w and to simply assume
+      // that this is not a homogeneous coordinate rather than
+      // throwing an exception
+      //throw DivideByZeroException();
+    } else {
+      x/=v.w;
+      y/=v.w;
+      z/=v.w;
     }
-    x/=v.w;
-    y/=v.w;
-    z/=v.w;
   }
 } // namespace geom
 
diff --git a/modules/geom/tests/test_transform.cc b/modules/geom/tests/test_transform.cc
index 5f4a543fd8ecfa21c3a3ac78a0a4b88d24ee36f9..ae27fd594b71432bfa271fbcf5fecce52c9e5594 100644
--- a/modules/geom/tests/test_transform.cc
+++ b/modules/geom/tests/test_transform.cc
@@ -28,7 +28,7 @@ using namespace geom;
 
 BOOST_AUTO_TEST_SUITE( geom_base );
 
-BOOST_AUTO_TEST_CASE(test_transform)
+BOOST_AUTO_TEST_CASE(test_transform_essentials)
 {
   Transform tf;
 
@@ -37,12 +37,55 @@ BOOST_AUTO_TEST_CASE(test_transform)
   BOOST_CHECK_EQUAL(tf.GetTrans(), geom::Vec3());
   BOOST_CHECK_EQUAL(tf.GetCenter(), geom::Vec3());
 
-  geom::Mat4 mat = geom::Mat4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);
-  tf.SetMatrix(mat);
-  BOOST_CHECK_EQUAL(tf.GetMatrix(), mat);
-  BOOST_CHECK_EQUAL(tf.GetRot(), geom::Mat3(1,2,3,5,6,7,9,10,11));
-  BOOST_CHECK_EQUAL(tf.GetCenter(), geom::Vec3(4,8,12));
-  BOOST_CHECK_EQUAL(tf.GetTrans(), geom::Vec3(13,14,15));
+  Mat3 rot=AxisRotation(Vec3(0.4,1.0,-0.8),2.13253);
+  Vec3 cen(0.5,1.0,2.2);
+  Vec3 tra(10,20,30);
+  tf.SetRot(rot);
+  tf.SetTrans(tra);
+  tf.SetCenter(cen);
+
+  Mat4 tmat = 
+    geom::Mat4(1.0,0.0,0.0,tra[0],
+               0.0,1.0,0.0,tra[1],
+               0.0,0.0,1.0,tra[2],
+               0.0,0.0,0.0,1.0) *
+    geom::Mat4(rot) *
+    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);
+
+  BOOST_CHECK_EQUAL(tf.GetRot(), rot);
+  BOOST_CHECK_EQUAL(tf.GetCenter(), cen);
+  BOOST_CHECK_EQUAL(tf.GetTrans(), tra);
+
+  Transform tf2;
+  tf2.SetMatrix(tf.GetMatrix());
+  BOOST_CHECK_EQUAL(tf2.GetRot(), rot);
+  BOOST_CHECK_EQUAL(tf2.GetCenter(), Vec3(0,0,0));
+  BOOST_CHECK_EQUAL(tf2.GetTrans(), rot*-cen+tra);
+}
+
+BOOST_AUTO_TEST_CASE(test_transform_apply_transform)
+{
+  Transform t1,t2;
+  Mat3 rm1=AxisRotation(Vec3(0.4,1.0,-0.8),2.13253);
+  Mat3 rm2=AxisRotation(Vec3(2.4,-0.1,3.8),-1.123);
+  t1.SetRot(rm1);
+  t1.SetCenter(Vec3(0.5,1.0,2.2));
+  t1.SetTrans(Vec3(10,20,30));
+  t2.SetRot(rm2);
+  t2.SetCenter(Vec3(1.3,2.7,-1.1));
+  t2.SetTrans(Vec3(-40,-60,80));
+
+  Mat4 mat1=t1.GetMatrix();
+  Mat4 mat2=t2.GetMatrix();
+  Mat4 mat12=mat2*mat1;
+  
+  Transform t3 = t1.Apply(t2);
+  Mat4 mat3=t3.GetMatrix();
+  for(int i=0;i<16;++i) BOOST_CHECK_CLOSE(mat3.Data()[i],mat12.Data()[i],1e-6);
+            
 }
 
 BOOST_AUTO_TEST_SUITE_END();
diff --git a/modules/geom/tests/test_vec3.cc b/modules/geom/tests/test_vec3.cc
index 9e3e4d9485c379293b59bf454d0befce87181737..3964daf007ade2efcb4db4b0d97547761135fbd5 100644
--- a/modules/geom/tests/test_vec3.cc
+++ b/modules/geom/tests/test_vec3.cc
@@ -58,8 +58,8 @@ BOOST_AUTO_TEST_CASE(init_vec3)
   // conversion from vec4
   Vec3 v6(Vec4(0.4,1.2,4.0,2.0));
   BOOST_CHECK(match(v6,0.2,0.6,2.0));
-  BOOST_CHECK_THROW( Vec3(Vec4(1.0,1.0,1.0,0.0)), DivideByZeroException);
 
+  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)
diff --git a/modules/gfx/pymod/CMakeLists.txt b/modules/gfx/pymod/CMakeLists.txt
index 0ee14167c4f19232a7e4ecbdda746ab6c1b6a2a9..cdc4abb2158de61e9639cc50d839fc760c28e30d 100644
--- a/modules/gfx/pymod/CMakeLists.txt
+++ b/modules/gfx/pymod/CMakeLists.txt
@@ -15,6 +15,7 @@ set(OST_GFX_PYMOD_SOURCES
   export_color_ops.cc
   export_glwin_base.cc
   export_exporter.cc
+  export_bitmap.cc
 )
 
 if (ENABLE_IMG)
@@ -29,4 +30,4 @@ set(GRADIENT_FILE
 copy_if_different("${CMAKE_CURRENT_SOURCE_DIR}" "${STAGE_DIR}/share/openstructure/scene" 
                   "${GRADIENT_FILE}" "PRESET GRADIENTS" _ost_gfx)
                   
-install(FILES ${GRADIENT_FILE} DESTINATION "share/openstructure/scene")
\ No newline at end of file
+install(FILES ${GRADIENT_FILE} DESTINATION "share/openstructure/scene")
diff --git a/modules/gfx/pymod/export_bitmap.cc b/modules/gfx/pymod/export_bitmap.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d8e944d21462cfaa90d72b7c99920882c6887722
--- /dev/null
+++ b/modules/gfx/pymod/export_bitmap.cc
@@ -0,0 +1,46 @@
+//------------------------------------------------------------------------------
+// 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 <boost/python.hpp>
+using namespace boost::python;
+
+#include <ost/gfx/bitmap_io.hh>
+using namespace ost;
+using namespace ost::gfx;
+
+namespace {
+  unsigned int get_width(const Bitmap& bm) {return bm.width;}
+  void set_width(Bitmap& bm, unsigned int w) {bm.width=w;}
+  unsigned int get_height(const Bitmap& bm) {return bm.height;}
+  void set_height(Bitmap& bm, unsigned int w) {bm.height=w;}
+
+  Bitmap import1(const std::string& n) {return ImportBitmap(n);}
+  Bitmap import2(const std::string& n, std::string e) {return ImportBitmap(n,e);}
+}
+
+void export_bitmap()
+{
+  class_<Bitmap>("Bitmap",init<>())
+    .add_property("width",get_width,set_width)
+    .add_property("height",get_height,set_height)
+    ;
+
+  def("ExportBitmap",ExportBitmap);
+  def("ImportBitmap",import1);
+  def("ImportBitmap",import2);
+}
diff --git a/modules/gfx/pymod/export_gfx_obj.cc b/modules/gfx/pymod/export_gfx_obj.cc
index 5f9ad7d1a4ecfc29a4b1aadf18b42c4d4f81e6e0..07d845636676fbd2c381ee1bbab25a4bf8aa0ca4 100644
--- a/modules/gfx/pymod/export_gfx_obj.cc
+++ b/modules/gfx/pymod/export_gfx_obj.cc
@@ -155,6 +155,8 @@ void export_GfxObj()
     .def("SetOpacity",&GfxObjBase::SetOpacity)
     .def("GetOpacity",&GfxObjBase::GetOpacity)
     .add_property("opacity",&GfxObjBase::GetOpacity,&GfxObjBase::SetOpacity)
+    .add_property("solid",&GfxObjBase::GetSolid,&GfxObjBase::SetSolid)
+    .add_property("solid_color",&GfxObjBase::GetSolidColor,&GfxObjBase::SetSolidColor)
     COLOR_BY_DEF()
    ;
 
diff --git a/modules/gfx/pymod/export_scene.cc b/modules/gfx/pymod/export_scene.cc
index 39d1fde6bde504a407dea60247b7cadf01fb5b8a..23ff9d687b497960588b169884690ff6a071243e 100644
--- a/modules/gfx/pymod/export_scene.cc
+++ b/modules/gfx/pymod/export_scene.cc
@@ -65,6 +65,10 @@ geom::AlignedCuboid scene_get_bb3(Scene* scene, const geom::Transform& tf)
   return scene->GetBoundingBox(tf);
 }
 
+void (Scene::*scene_set_bg1)(const Color&) = &Scene::SetBackground;
+void (Scene::*scene_set_bg2)(const Gradient&) = &Scene::SetBackground;
+void (Scene::*scene_set_bg3)(const Bitmap&) = &Scene::SetBackground;
+
 } // anon ns
 
 
@@ -124,10 +128,12 @@ void export_Scene()
     .def("Resize", &Scene::Resize)
     .def("HasNode", &Scene::HasNode)
     .def("GetBackground", &Scene::GetBackground)
-    .def("SetBackground", &Scene::SetBackground)
+    .def("SetBackground", scene_set_bg1)
+    .def("SetBackground", scene_set_bg2)
+    .def("SetBackground", scene_set_bg3)
     .add_property("bg",
                   &Scene::GetBackground, 
-                  &Scene::SetBackground)
+                  scene_set_bg1)
     .def("GetProjection",&Scene::GetProjection)
     .add_property("projection",&Scene::GetProjection)
     .def("GetInvertedProjection",&Scene::GetInvertedProjection)
diff --git a/modules/gfx/pymod/gradients.xml b/modules/gfx/pymod/gradients.xml
index e3e1fbd0cad68995f30fa7b445f108b05eb31210..bd79d60947eefc96fcf343f930990cca004d4b9d 100644
--- a/modules/gfx/pymod/gradients.xml
+++ b/modules/gfx/pymod/gradients.xml
@@ -70,6 +70,10 @@
 <Gradient hsv_color="1" hsv_mode="1" Name="RED_TO_BLUE_HSV">2
 0.0 1 1 1 1
 1.0 0.66666667 1 1 1
+</Gradient>
+<Gradient Name="BIOZENTRUM">2
+  0.0 0.901960784314 0.0 0.392156862745 1
+  1.0 0.352941176471 0.176470588235 0.529411764706 1
 </Gradient>
  </Gradients>
 </EMDataInfo>
diff --git a/modules/gfx/pymod/wrap_gfx.cc b/modules/gfx/pymod/wrap_gfx.cc
index 28229edf12ada259a25443f363d43db51199291d..b28c496597e9ae55489a1a0930fdfe2b00fcc620 100644
--- a/modules/gfx/pymod/wrap_gfx.cc
+++ b/modules/gfx/pymod/wrap_gfx.cc
@@ -37,6 +37,7 @@ extern void export_primlist();
 extern void export_primitives();
 extern void export_color();
 extern void export_gradient();
+extern void export_bitmap();
 extern void export_Exporter();
 
 #if OST_IMG_ENABLED
@@ -73,6 +74,7 @@ BOOST_PYTHON_MODULE(_ost_gfx)
   export_primlist();
   export_color();
   export_gradient();
+  export_bitmap();
 
   enum_<RenderMode::Type>("RenderMode")
     .value("SIMPLE",RenderMode::SIMPLE)
diff --git a/modules/gfx/src/bitmap_io.cc b/modules/gfx/src/bitmap_io.cc
index 6d36daaa1c339f8c4e995e90dc07f81c0cb10bf7..ab42f9de5a67242ee9edf51a705c6cec4a078121 100644
--- a/modules/gfx/src/bitmap_io.cc
+++ b/modules/gfx/src/bitmap_io.cc
@@ -21,15 +21,19 @@
 */
 
 #include <vector>
+#include <sstream>
 #define ZLIB_WINAPI
 #include <png.h>
 
 #include <ost/log.hh>
+#include <ost/message.hh>
 
 #include "bitmap_io.hh"
 
 namespace ost { namespace gfx {
 
+namespace {
+
 void export_png(const String& filename, unsigned int width, unsigned int height, unsigned char* data)
 {
   FILE *fp;
@@ -181,15 +185,38 @@ Bitmap import_png(const String& filename)
   return bm;
 }
 
-void BitmapExport(const String& fname, const String& ext, unsigned int width, unsigned int height,unsigned char* data)
+std::string get_ext(const std::string& fname)
 {
-  if(ext==".png") export_png(fname,width,height,data);
+  int d_index=fname.rfind('.');
+  if (d_index==-1) {
+    return "";
+  }
+  return fname.substr(d_index+1);
+}
+
+}
+    
+void ExportBitmap(const String& fname, std::string ext, unsigned int width, unsigned int height,unsigned char* data)
+{
+  if(ext.empty()) ext=get_ext(fname);
+  if(ext=="png") {
+    export_png(fname,width,height,data);
+  } else {
+    std::ostringstream msg;
+    msg << "unsupported bitmap format [" << ext << "]";
+    throw Error(msg.str());
+  }
 }
 
-Bitmap BitmapImport(const String& fname, const String& ext)
+Bitmap ImportBitmap(const String& fname, std::string ext)
 {
-  if(ext==".png") {
+  if(ext.empty()) ext=get_ext(fname);
+  if(ext=="png") {
     return import_png(fname);
+  } else {
+    std::ostringstream msg;
+    msg << "unsupported bitmap format [" << ext << "]";
+    throw Error(msg.str());
   }
   return Bitmap();
 }
diff --git a/modules/gfx/src/bitmap_io.hh b/modules/gfx/src/bitmap_io.hh
index afddc220bc6f91f3d60507b1d8fe1d47341292cf..dacb9dbe36b95a32c6d9b8273999ebbac7efe8eb 100644
--- a/modules/gfx/src/bitmap_io.hh
+++ b/modules/gfx/src/bitmap_io.hh
@@ -32,6 +32,7 @@
 namespace ost { namespace gfx {
 
 // very rudimentary bitmap support
+// TODO: gl tex mapping association
 struct Bitmap
 {
   /*
@@ -46,9 +47,9 @@ struct Bitmap
   boost::shared_array<unsigned char> data;
 };
 
-void BitmapExport(const String& fname, const String& ext, unsigned int width, unsigned int height,unsigned char* data);
+void DLLEXPORT_OST_GFX ExportBitmap(const String& fname, std::string ext, unsigned int width, unsigned int height,unsigned char* data);
 
-Bitmap BitmapImport(const String& fname, const String& ext);
+Bitmap DLLEXPORT_OST_GFX ImportBitmap(const String& fname, std::string ext="");
 
 
 }} // ns
diff --git a/modules/gfx/src/entity.hh b/modules/gfx/src/entity.hh
index 112a7ac4d8f5b5dbdd6db517a673b9ded7180a34..d3fe0ad928855e1c6fe41b40943a8439b50996fe 100644
--- a/modules/gfx/src/entity.hh
+++ b/modules/gfx/src/entity.hh
@@ -90,7 +90,7 @@ public:
          RenderMode::Type m,
          const mol::EntityView& ev);
 
-  virtual geom::AlignedCuboid GetBoundingBox(bool use_global=false) const;
+  virtual geom::AlignedCuboid GetBoundingBox(bool use_tf=false) const;
 
   // ProcessLimits uses the default implementation of bounding box
   
diff --git a/modules/gfx/src/gfx_object.cc b/modules/gfx/src/gfx_object.cc
index f7e3b06a5af9a5b1962156db728b4556e331c98c..63003cd5bce9481772ed5d8f3f1e8aa919e2e7c8 100644
--- a/modules/gfx/src/gfx_object.cc
+++ b/modules/gfx/src/gfx_object.cc
@@ -64,6 +64,8 @@ GfxObj::GfxObj(const String& name):
 #else
   outline_mode_(1),
 #endif
+  solid_(false),
+  solid_color_(RGB(0.7,0.7,0.7)),
   c_ops_(),
   labels_(),
   use_occlusion_(false)
@@ -128,6 +130,8 @@ void GfxObj::RenderGL(RenderPass pass)
       // there really needs to be a central place
       // where the va attributes are re-applied
       va_.SetOpacity(opacity_);
+      va_.SetSolid(solid_);
+      va_.SetSolidColor(solid_color_);
     }
   }
   if(IsVisible()) {
@@ -375,6 +379,20 @@ void GfxObj::SetOpacity(float o)
   Scene::Instance().RequestRedraw();
 }
 
+void GfxObj::SetSolid(bool f)
+{
+  solid_=f;
+  va_.SetSolid(solid_);
+  Scene::Instance().RequestRedraw();
+}
+
+void GfxObj::SetSolidColor(const Color& c)
+{
+  solid_color_=c;
+  va_.SetSolidColor(solid_color_);
+  Scene::Instance().RequestRedraw();
+}
+
 void GfxObj::ColorBy(const mol::EntityView& ev, 
                       const String& prop,
                       const Gradient& g, float minv, float maxv)
diff --git a/modules/gfx/src/gfx_object.hh b/modules/gfx/src/gfx_object.hh
index fc906c35c9fdb7c563417c6785e5023d2dabe594..0b70065d7f820ca924ef07b3d2ad3005fe4e71b2 100644
--- a/modules/gfx/src/gfx_object.hh
+++ b/modules/gfx/src/gfx_object.hh
@@ -88,6 +88,11 @@ public:
   virtual Color GetOutlineExpandColor() const;
   virtual void SetOpacity(float f);
   virtual float GetOpacity() const {return opacity_;}
+  virtual void SetSolid(bool f);
+  virtual bool GetSolid() const {return solid_;}
+  virtual void SetSolidColor(const Color& c);
+  virtual Color GetSolidColor() const {return solid_color_;}
+  
   virtual void ColorBy(const mol::EntityView& ev, 
                        const String& prop,
                        const Gradient& g, float minv, float maxv);
@@ -242,6 +247,9 @@ public:
   bool outline_flag_;
   int outline_mode_;
 
+  bool solid_;
+  Color solid_color_;
+
   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 eb6c7c21743805e237377bc64e15ced0d61f3885..448de0cf2687781045e7b59bc72b145be0ee1c2d 100644
--- a/modules/gfx/src/gfx_object_base.hh
+++ b/modules/gfx/src/gfx_object_base.hh
@@ -117,6 +117,11 @@ class DLLEXPORT_OST_GFX GfxObjBase: public GfxNode
   /// \brief returns a value smaller than 1.0 if transparency is used in this object
   virtual float GetOpacity() const = 0;
 
+  virtual void SetSolid(bool f) = 0;
+  virtual bool GetSolid() const = 0;
+  virtual void SetSolidColor(const Color& c) = 0;
+  virtual Color GetSolidColor() const = 0;
+  
   /// \brief color each component based on the gradient-mapped property of 
   ///    the given entity
   virtual void ColorBy(const mol::EntityView& ev, 
diff --git a/modules/gfx/src/gfx_test_object.cc b/modules/gfx/src/gfx_test_object.cc
index 5b238473055efe537db846838267fc842a85844f..7e60ab6d8657d35b44d2eb0840a0c0f7640ad76a 100644
--- a/modules/gfx/src/gfx_test_object.cc
+++ b/modules/gfx/src/gfx_test_object.cc
@@ -61,7 +61,7 @@ GfxTestObj::GfxTestObj():
   bf::path ost_root_dir(ost_root);
   bf::path tex_file(ost_root_dir / "textures/test_texture.png");
 
-  Texture tex(BitmapImport(tex_file.string(),".png"));
+  Texture tex(ImportBitmap(tex_file.string()));
   if(!tex.IsValid()) {
     LOG_ERROR("error loading " << tex_file.string());
   } else {
diff --git a/modules/gfx/src/gl_helper.hh b/modules/gfx/src/gl_helper.hh
index dac567894edea06c8c6156dae1497dcd52c65f81..77346056346c4ec937b90dba4bebaedd9fe5fb59 100644
--- a/modules/gfx/src/gl_helper.hh
+++ b/modules/gfx/src/gl_helper.hh
@@ -39,12 +39,16 @@ Author: Juergen Haas
 
 #include <ost/log.hh>
 
-inline void check_gl_error()
+inline void check_gl_error(const std::string& m="")
 {
+  #ifndef NDEBUG
   GLenum error_code;
   if((error_code=glGetError())!=GL_NO_ERROR) {
-    LOG_VERBOSE("GL error: " << gluErrorString(error_code));
+    if(!m.empty()) {
+      LOG_VERBOSE("GL error in [" << m << "]: " << gluErrorString(error_code));
+    }
   }
+  #endif
 }
 
 inline void glVertex3v(double* v){
diff --git a/modules/gfx/src/gradient.cc b/modules/gfx/src/gradient.cc
index c65261b16a60eb2deac7ecfcf41def8be63239f5..f1c93ffbbbfa7ff799073a49a3da5210fc688eb7 100644
--- a/modules/gfx/src/gradient.cc
+++ b/modules/gfx/src/gradient.cc
@@ -70,7 +70,7 @@ Color Gradient::GetColorAt(float t) const
   }
   
   uint c=0;
-  while (t>=stops_[c].t && c<stops_.size()) {
+  while (c<stops_.size() && t>=stops_[c].t) {
     ++c;
   }
   if (c==0) {
diff --git a/modules/gfx/src/impl/fast_spheres.hh b/modules/gfx/src/impl/fast_spheres.hh
index 2cef93d6561407b768586537851e5a5b83f7011a..72402ef9b36f81fca897f0a2484b39def3a7a932 100644
--- a/modules/gfx/src/impl/fast_spheres.hh
+++ b/modules/gfx/src/impl/fast_spheres.hh
@@ -30,7 +30,7 @@
 
 namespace ost { namespace gfx { namespace impl {
 
-  class FastSphereRenderer {
+  class DLLEXPORT_OST_GFX FastSphereRenderer {
   public:
     struct VData
     {
diff --git a/modules/gfx/src/impl/scene_fx.cc b/modules/gfx/src/impl/scene_fx.cc
index de0000484bf41a13d91220a312e54013ac643922..a9ddbc4cd9f8fc7e7d235efae0c8ce390c422d71 100644
--- a/modules/gfx/src/impl/scene_fx.cc
+++ b/modules/gfx/src/impl/scene_fx.cc
@@ -224,6 +224,11 @@ void SceneFX::Preprocess()
   }
 }
 
+bool SceneFX::WillPostprocess() const
+{
+  return shadow_flag || amb_occl_flag || depth_dark_flag || use_beacon;
+}
+
 void SceneFX::Postprocess()
 {
   if(!OST_GL_VERSION_2_0) return;
@@ -235,10 +240,7 @@ void SceneFX::Postprocess()
 #endif
   }
 
-  if(!shadow_flag && !amb_occl_flag && !depth_dark_flag && !use_beacon) {
-    // no postprocessing is needed
-    return;
-  }
+  if(!WillPostprocess()) return;
 
   Viewport vp=Scene::Instance().GetViewport();
 
@@ -329,6 +331,18 @@ void SceneFX::Postprocess()
     glUniform1i(glGetUniformLocation(cpr,"dark_flag"),0);
   }
 
+  GLint fog;
+  glGetIntegerv(GL_FOG,&fog);
+  float znear=Scene::Instance().GetNear();
+  float zfar=Scene::Instance().GetFar();
+  float fnear=znear+Scene::Instance().GetFogNearOffset();
+  float ffar=zfar+Scene::Instance().GetFogFarOffset();
+  glUniform1i(glGetUniformLocation(cpr,"fog_flag"),fog);
+  glUniform1f(glGetUniformLocation(cpr,"depth_near"),znear);
+  glUniform1f(glGetUniformLocation(cpr,"depth_far"),zfar);
+  glUniform1f(glGetUniformLocation(cpr,"fog_far"),ffar);
+  glUniform1f(glGetUniformLocation(cpr,"fog_scale"),1.0f/(ffar-fnear));
+
   if(use_beacon) {
     prep_beacon();
   }
@@ -480,7 +494,11 @@ void SceneFX::prep_shadow_map()
     are first reverted, and then the light modelview and projection are applied, resulting (with the
     bias) in the proper 2D lookup into the shadow map
   */
-  shadow_tex_mat_ = bias*pmat*ltrans.GetMatrix()*geom::Invert(Scene::Instance().GetTransform().GetMatrix())*geom::Invert(pmat2);
+  try {
+    shadow_tex_mat_ = bias*pmat*ltrans.GetMatrix()*geom::Invert(Scene::Instance().GetTransform().GetMatrix())*geom::Invert(pmat2);
+  } catch (geom::GeomException& e) {
+    LOG_DEBUG("SceneFX: caught matrix inversion exception in prep_shadow_map()");
+  }
 }
 
 void SceneFX::prep_amb_occlusion()
@@ -516,7 +534,12 @@ void SceneFX::prep_amb_occlusion()
 
   glMatrixMode(GL_TEXTURE);
   glPushMatrix();
-  geom::Mat4 ipm(geom::Transpose(geom::Invert(geom::Transpose(geom::Mat4(pm)))));
+  geom::Mat4 ipm;
+  try {
+    ipm=(geom::Transpose(geom::Invert(geom::Transpose(geom::Mat4(pm)))));
+  } catch (geom::GeomException& e) {
+    LOG_DEBUG("SceneFX: caught matrix inversion exception in prep_amb_occlusion()");
+  }
   glLoadMatrix(ipm.Data());
   glMatrixMode(GL_MODELVIEW);
 
@@ -638,7 +661,11 @@ void SceneFX::prep_beacon()
 
   glGetv(GL_PROJECTION_MATRIX, glpmat);
   geom::Mat4 pmat2(geom::Transpose(geom::Mat4(glpmat)));
-  beacon.mat = geom::Invert(Scene::Instance().GetTransform().GetMatrix())*geom::Invert(pmat2);
+  try {
+    beacon.mat = geom::Invert(Scene::Instance().GetTransform().GetMatrix())*geom::Invert(pmat2);
+  } catch (geom::GeomException& e) {
+    beacon.mat=geom::Mat4();
+  }
 }
 
 void SceneFX::draw_beacon()
diff --git a/modules/gfx/src/impl/scene_fx.hh b/modules/gfx/src/impl/scene_fx.hh
index 3b8e1fa388b67ea0c51be27676b437875c0e7aa6..ad8d2a787c57a7b4e9eb1433fd5d8e1f4c63d173 100644
--- a/modules/gfx/src/impl/scene_fx.hh
+++ b/modules/gfx/src/impl/scene_fx.hh
@@ -53,6 +53,9 @@ public:
   void Preprocess();
   // assumes scene has been drawn in the active framebuffer
   void Postprocess();
+  
+  // returns true if the post-processing will run
+  bool WillPostprocess() const;
 
   void DrawTex(unsigned int w, unsigned int h, GLuint texid);
 
diff --git a/modules/gfx/src/map_slab.cc b/modules/gfx/src/map_slab.cc
index ae4a08629b4950c1836bd19fe2d53742e326a9ae..3af16f422257a6a1dea44aa2dd0da13bb20fd7b7 100644
--- a/modules/gfx/src/map_slab.cc
+++ b/modules/gfx/src/map_slab.cc
@@ -84,11 +84,12 @@ MapSlab::MapSlab(const String& name, const img::MapHandle& mh, const geom::Plane
   maxv_ = stat.GetMaximum();
 }
 
-geom::AlignedCuboid MapSlab::GetBoundingBox() const
+geom::AlignedCuboid MapSlab::GetBoundingBox(bool use_tf) const
 {
   geom::Vec3 minc = plane_.At(-1.0,-1.0);
   geom::Vec3 maxc = plane_.At(1.0,1.0);
-  return geom::AlignedCuboid(minc,maxc);
+  geom::AlignedCuboid bb(minc,maxc);
+  return use_tf ? transform_.Apply(bb) : bb;
 }
 
 geom::Vec3 MapSlab::GetCenter() const
diff --git a/modules/gfx/src/map_slab.hh b/modules/gfx/src/map_slab.hh
index 8d27b975c3fc72bcc52d4ba5031e92b14a135e76..c38a88864a5fc129733571c2be34971ce73339fd 100644
--- a/modules/gfx/src/map_slab.hh
+++ b/modules/gfx/src/map_slab.hh
@@ -62,7 +62,7 @@ public:
   MapSlab(const String& name, const img::MapHandle& mh, 
           const geom::Plane& p);
 
-  virtual geom::AlignedCuboid GetBoundingBox() const;
+  virtual geom::AlignedCuboid GetBoundingBox(bool use_tf=true) const;
 
   virtual geom::Vec3 GetCenter() const;
   virtual void CustomRenderGL(RenderPass pass);
diff --git a/modules/gfx/src/prim_list.cc b/modules/gfx/src/prim_list.cc
index e07820e6bc6c15af276b8a7012baa21b00545eb3..0c8589ea29837485a979443287b31f6be137fe74 100644
--- a/modules/gfx/src/prim_list.cc
+++ b/modules/gfx/src/prim_list.cc
@@ -54,7 +54,7 @@ void PrimList::Clear()
   this->FlagRebuild();
 }
 
-geom::AlignedCuboid PrimList::GetBoundingBox() const
+geom::AlignedCuboid PrimList::GetBoundingBox(bool use_tf) const
 {
   if(points_.empty() && lines_.empty() && spheres_.empty() && cyls_.empty() && texts_.empty() && vas_.empty()) {
     return geom::AlignedCuboid(geom::Vec3(-1,-1,-1),geom::Vec3(1,1,1));
@@ -66,7 +66,8 @@ geom::AlignedCuboid PrimList::GetBoundingBox() const
                   -std::numeric_limits<float>::max(),
                   -std::numeric_limits<float>::max());
   ProcessLimits(minc,maxc,geom::Transform());
-  return geom::AlignedCuboid(minc,maxc);
+  geom::AlignedCuboid bb(minc,maxc);
+  return use_tf ? transform_.Apply(bb) : bb;
 }
 
 void PrimList::ProcessLimits(geom::Vec3& minc, geom::Vec3& maxc, 
diff --git a/modules/gfx/src/prim_list.hh b/modules/gfx/src/prim_list.hh
index afc999a7febc930495d2f7620c7795295293be42..80eabe333a1b9264da03f015d1f423905aa36f56 100644
--- a/modules/gfx/src/prim_list.hh
+++ b/modules/gfx/src/prim_list.hh
@@ -61,7 +61,7 @@ class DLLEXPORT_OST_GFX PrimList: public GfxObj
   /// \brief create new prim list
   PrimList(const String& name);
 
-  virtual geom::AlignedCuboid GetBoundingBox() const;
+  virtual geom::AlignedCuboid GetBoundingBox(bool use_tf=true) const;
 
   virtual void ProcessLimits(geom::Vec3& minc, geom::Vec3& maxc, 
                              const geom::Transform& tf) const;
diff --git a/modules/gfx/src/scene.cc b/modules/gfx/src/scene.cc
index 2650eea5b09f5169bee74a9e984437573619aa3c..9212d8eab37f015b5019c25438efe75d162fb268 100644
--- a/modules/gfx/src/scene.cc
+++ b/modules/gfx/src/scene.cc
@@ -135,7 +135,12 @@ Scene::Scene():
   stereo_iod_(4.0),
   stereo_distance_(0.0),
   scene_left_tex_(),
-  scene_right_tex_()
+  scene_right_tex_(),
+  bg_mode_(0),
+  update_bg_(false),
+  bg_grad_(),
+  bg_bm_(),
+  bg_tex_()
 {
   transform_.SetTrans(Vec3(0,0,-100));
 }
@@ -394,6 +399,8 @@ void Scene::InitGL(bool full)
 {
   LOG_VERBOSE("Scene: initializing GL state");
 
+  check_gl_error(); // clear error flag
+
   if(full) {
     LOG_INFO(glGetString(GL_RENDERER) << ", openGL version " << glGetString(GL_VERSION)); 
 
@@ -506,8 +513,10 @@ void Scene::InitGL(bool full)
   }
 
   if(full) {
+    LOG_DEBUG("Scene: initalizing textures");
     glGenTextures(1,&scene_left_tex_);
     glGenTextures(1,&scene_right_tex_);
+    glGenTextures(1,&bg_tex_);
   }
 
   glEnable(GL_TEXTURE_2D);
@@ -531,6 +540,14 @@ void Scene::InitGL(bool full)
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
   glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE, GL_REPLACE);
 
+  glBindTexture(GL_TEXTURE_2D, bg_tex_);
+  glPixelStorei(GL_UNPACK_ALIGNMENT,1);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+  glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
   LOG_DEBUG("Scene: calling gl init for all objects");
   GfxObjInitGL initgl;
   this->Apply(initgl);
@@ -539,6 +556,8 @@ void Scene::InitGL(bool full)
   gl_init_=true;
   
   if(!def_shading_mode_.empty()) SetShadingMode(def_shading_mode_);
+  
+  check_gl_error("InitGL()");
 }
 
 void Scene::RequestRedraw()
@@ -556,6 +575,7 @@ void Scene::StatusMessage(const String& s)
 void Scene::SetBackground(const Color& c)
 {
   background_=c;
+  bg_mode_=0;
   if(gl_init_) {
     glClearColor(c.Red(),c.Green(),c.Blue(),c.Alpha());
     SetFogColor(c);
@@ -563,6 +583,65 @@ void Scene::SetBackground(const Color& c)
   }
 }
 
+namespace {
+  void c2d(const Color& c, unsigned char* d) {
+    d[0]=static_cast<unsigned char>(c.GetRed()*255.0);
+    d[1]=static_cast<unsigned char>(c.GetGreen()*255.0);
+    d[2]=static_cast<unsigned char>(c.GetBlue()*255.0);
+  }
+}
+
+void Scene::set_bg()
+{
+  static std::vector<unsigned char> data;
+  static const unsigned int grad_steps=64;
+  if(bg_mode_==1) {
+    LOG_DEBUG("Scene: setting background gradient");
+    // gradient
+    glBindTexture(GL_TEXTURE_2D, bg_tex_);
+    data.resize(3*grad_steps);
+    float tf=1.0/static_cast<float>(grad_steps-1);
+    for(size_t i=0;i<grad_steps;++i) {
+      Color col=bg_grad_.GetColorAt(static_cast<float>(i)*tf);
+      c2d(col,&data[i*3]);
+    }
+    glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,1,grad_steps,0,GL_RGB,GL_UNSIGNED_BYTE,&data[0]);
+  } else if(bg_mode_==2) {
+    LOG_DEBUG("Scene: setting background bitmap");
+    // bitmap
+    glBindTexture(GL_TEXTURE_2D, bg_tex_);
+    if(bg_bm_.channels==1) {
+      glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,bg_bm_.width,bg_bm_.height,0,GL_LUMINANCE,GL_UNSIGNED_BYTE,bg_bm_.data.get());
+    } else if(bg_bm_.channels==3) {
+      glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,bg_bm_.width,bg_bm_.height,0,GL_RGB,GL_UNSIGNED_BYTE,bg_bm_.data.get());
+    } else if(bg_bm_.channels==4) {
+      glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,bg_bm_.width,bg_bm_.height,0,GL_RGBA,GL_UNSIGNED_BYTE,bg_bm_.data.get());
+    } else {
+      LOG_ERROR("Scene::SetBackground: unsupported bitmap channel count of " << bg_bm_.channels);
+    }
+  }
+}
+
+void Scene::SetBackground(const Gradient& g)
+{
+  bg_grad_=g;
+  bg_mode_=1;
+  update_bg_=true;
+  RequestRedraw();
+}
+
+void Scene::SetBackground(const Bitmap& bm)
+{
+  if(bm.width==0 || bm.height==0) {
+    LOG_WARNING("Scene: background bitmap has invalid size (" << bm.width << "x" << bm.height << "), ignoring");
+    return;
+  }
+  bg_bm_=bm;
+  bg_mode_=2;
+  update_bg_=true;
+  RequestRedraw();
+}
+
 Color Scene::GetBackground() const
 {
   return background_;
@@ -579,8 +658,8 @@ Viewport Scene::GetViewport() const
 
 void Scene::SetViewport(int w, int h)
 {
-  vp_width_=w;
-  vp_height_=h;
+  vp_width_=std::max<unsigned int>(1,w);
+  vp_height_=std::max<unsigned int>(1,h);
   aspect_ratio_=static_cast<float>(w)/static_cast<float>(h);
   if(!gl_init_) return;
   glViewport(0,0,w,h);
@@ -726,6 +805,7 @@ void draw_lightdir(const Vec3& ldir, const geom::Transform& tf)
 
 void Scene::RenderGL()
 {
+  check_gl_error(); // clear error flag
   if(auto_autoslab_ || do_autoslab_) {
     do_autoslab();
     do_autoslab_=false;
@@ -738,7 +818,7 @@ void Scene::RenderGL()
   } else {
     render_scene();
   }
-  check_gl_error();
+  check_gl_error("RenderGL()");
 }
 
 void Scene::Register(GLWinBase* win)
@@ -1566,9 +1646,9 @@ void Scene::Export(const String& fname, unsigned int width,
     LOG_ERROR("Scene: no file extension specified");
     return;
   }
-  String ext = fname.substr(d_index);
-  if(!(ext==".png")) {
-    LOG_ERROR("Scene: unknown file format (" << ext << ")");
+  String ext = fname.substr(d_index+1);
+  if(ext!="png") {
+    LOG_ERROR("Scene::Export: unknown file format (" << ext << ")");
     return;
   }
 
@@ -1602,7 +1682,7 @@ void Scene::Export(const String& fname, unsigned int width,
   glReadBuffer(GL_BACK);
 
   LOG_DEBUG("Scene: calling bitmap export");
-  BitmapExport(fname,ext,width,height,img_data.get());
+  ExportBitmap(fname,ext,width,height,img_data.get());
 
   // only switch back if it was not on to begin with
   if(of_flag) {
@@ -1621,8 +1701,8 @@ void Scene::Export(const String& fname, bool transparent)
     LOG_ERROR("Scene: no file extension specified");
     return;
   }
-  String ext = fname.substr(d_index);
-  if(ext!=".png") {
+  String ext = fname.substr(d_index+1);
+  if(ext!="png") {
     LOG_ERROR("Scene: unknown file format (" << ext << ")");
     return;
   }
@@ -1644,7 +1724,7 @@ void Scene::Export(const String& fname, bool transparent)
   boost::shared_array<uchar> img_data(new uchar[vp[2]*vp[3]*4]);
   glReadPixels(0,0,vp[2],vp[3],GL_RGBA,GL_UNSIGNED_BYTE,img_data.get());
   glFinish();
-  BitmapExport(fname,ext,vp[2],vp[3],img_data.get());
+  ExportBitmap(fname,ext,vp[2],vp[3],img_data.get());
   glPixelTransferf(GL_ALPHA_BIAS, 0.0);  
 }
 
@@ -1867,7 +1947,7 @@ void Scene::prep_glyphs()
   String ost_root =GetSharedDataPath();
   bf::path ost_root_dir(ost_root);
   bf::path tex_file(ost_root_dir / "textures/glyph_texture.png");
-  Bitmap bm = BitmapImport(tex_file.string(),".png");
+  Bitmap bm = ImportBitmap(tex_file.string());
   if(!bm.data) return;
 
   LOG_DEBUG("Scene: importing glyph tex with id " << glyph_tex_id_);
@@ -1908,6 +1988,75 @@ void Scene::prep_blur()
   glFlush();
 }
 
+void Scene::render_bg()
+{
+  if(!gl_init_) return;
+  if(bg_mode_!=1 && bg_mode_!=2) return;
+  if(update_bg_) {
+    set_bg();
+    check_gl_error("set_bg()");
+    update_bg_=false;
+  }
+
+  // setup state for simple texture quad
+#if OST_SHADER_SUPPORT_ENABLED
+  Shader::Instance().PushProgram();
+  Shader::Instance().Activate("");
+#endif
+  glPushAttrib(GL_ALL_ATTRIB_BITS);
+  glPushClientAttrib(GL_ALL_ATTRIB_BITS);
+
+  glDisable(GL_DEPTH_TEST);
+  glDisable(GL_LIGHTING);
+  glDisable(GL_COLOR_MATERIAL);
+  glDisable(GL_FOG);
+  glDisable(GL_CULL_FACE);
+  glDisable(GL_BLEND);
+  glDisable(GL_LINE_SMOOTH);
+  glDisable(GL_POINT_SMOOTH);
+#if defined(OST_GL_VERSION_2_0)
+  glDisable(GL_MULTISAMPLE);
+#endif
+  glMatrixMode(GL_PROJECTION);
+  glPushMatrix();
+  glLoadIdentity();
+  glOrtho(0,vp_width_,0,vp_height_,-1,1);
+  glMatrixMode(GL_MODELVIEW);
+  glPushMatrix();
+  glLoadIdentity();
+
+  // draw bg texture quad
+  glEnable(GL_TEXTURE_2D);
+#if OST_SHADER_SUPPORT_ENABLED
+  if(OST_GL_VERSION_2_0) {
+    glActiveTexture(GL_TEXTURE0);
+  }
+#endif
+  glBindTexture(GL_TEXTURE_2D, bg_tex_);
+  // draw
+  glColor3f(0.0,0.0,0.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 all settings
+  glBindTexture(GL_TEXTURE_2D, 0);
+  glDisable(GL_TEXTURE_2D);
+  glMatrixMode(GL_PROJECTION);
+  glPopMatrix();
+  glMatrixMode(GL_MODELVIEW);
+  glPopMatrix();
+  glPopClientAttrib();
+  glPopAttrib();
+#if OST_SHADER_SUPPORT_ENABLED
+  Shader::Instance().PopProgram();
+#endif
+  check_gl_error("render_bg()");
+}
+
 void Scene::render_scene()
 {
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -1915,6 +2064,8 @@ void Scene::render_scene()
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
 
+  render_bg();
+
   glMultMatrix(transform_.GetTransposedMatrix().Data());
 
 #if OST_SHADER_SUPPORT_ENABLED
diff --git a/modules/gfx/src/scene.hh b/modules/gfx/src/scene.hh
index 4edc6663770bbdb3c047382f04e925474bd06baf..f6f4c87f1544b091d0e51777b7b254501ae4d22b 100644
--- a/modules/gfx/src/scene.hh
+++ b/modules/gfx/src/scene.hh
@@ -43,6 +43,8 @@
 #include "gfx_prim.hh"
 #include "povray_fw.hh"
 #include "exporter_fw.hh"
+#include "gradient.hh"
+#include "bitmap_io.hh"
 
 namespace ost { namespace gfx {
 
@@ -172,6 +174,8 @@ class DLLEXPORT_OST_GFX Scene {
   // \brief get the field of view
   float GetFOV() const;
 
+  float GetAspect() const {return aspect_ratio_;}
+
   /// \brief offset between near clipping plane and start of fog
   void SetFogNearOffset(float o);
 
@@ -333,6 +337,12 @@ class DLLEXPORT_OST_GFX Scene {
   /// \brief set background color
   void SetBackground(const Color& c);
 
+  /// \brief set background gradient
+  void SetBackground(const Gradient& g);
+
+  /// \brief set background image
+  void SetBackground(const Bitmap& bm);
+
   /// \brief get background color
   Color GetBackground() const;
 
@@ -498,6 +508,7 @@ protected:
   void NodeAdded(const GfxNodeP& node);
   void RenderModeChanged(const String& name);
 
+
 private:  
 
   template <typename ACTION>
@@ -568,6 +579,13 @@ private:
   Real stereo_iod_,stereo_distance_;
   unsigned int scene_left_tex_;
   unsigned int scene_right_tex_;
+  unsigned int bg_mode_;
+  bool update_bg_;
+  Gradient bg_grad_;
+  Bitmap bg_bm_;
+  unsigned int bg_tex_;
+  
+  
 
   void set_near(float n);
   void set_far(float f);
@@ -576,10 +594,11 @@ private:
   void prep_glyphs();
   void prep_blur();
   void stereo_projection(int view);
+  void render_bg();
   void render_scene();
   void render_glow();
   void render_stereo();
-
+  void set_bg();
   void do_autoslab();
 
   bool IsNameAvailable(const String& name) const;
diff --git a/modules/gfx/src/shader.cc b/modules/gfx/src/shader.cc
index 2a5e91ce25fa41c121ae12ecca5a6a2f08a82e68..3ed15cac334785fbb45e4d1b63fb91d62c70f599 100644
--- a/modules/gfx/src/shader.cc
+++ b/modules/gfx/src/shader.cc
@@ -28,6 +28,7 @@
 #include <ost/platform.hh>
 #include <ost/log.hh>
 
+#include "impl/scene_fx.hh"
 #include "glext_include.hh"
 
 #include "shader.hh"
@@ -366,7 +367,11 @@ void Shader::UpdateState()
     glGetBooleanv(GL_LIGHT_MODEL_TWO_SIDE,&bresult);
     LOG_TRACE("setting two_sided flag to " << bresult);
     glUniform1i(glGetUniformLocation(current_program_,"two_sided_flag"),bresult);
-    glGetIntegerv(GL_FOG,&result);
+    if(impl::SceneFX::Instance().WillPostprocess()) {
+      result=0;
+    } else {
+      glGetIntegerv(GL_FOG,&result);
+    }
     LOG_TRACE("setting fog flag to " << result);
     glUniform1i(glGetUniformLocation(current_program_,"fog_flag"),result);
     glDisable(GL_COLOR_MATERIAL);
diff --git a/modules/gfx/src/shader/scenefx_fs.glsl b/modules/gfx/src/shader/scenefx_fs.glsl
index cb5c2313c77dced05f81fdd4854704ebbb4b9a6c..e328d2d086842e680c79329ab1fdaafd204d9cea 100644
--- a/modules/gfx/src/shader/scenefx_fs.glsl
+++ b/modules/gfx/src/shader/scenefx_fs.glsl
@@ -13,6 +13,11 @@ uniform float occl_mult;
 uniform bool dark_flag;
 uniform sampler2D dark_map;
 uniform float dark_mult;
+uniform bool fog_flag;
+uniform float depth_near;
+uniform float depth_far;
+uniform float fog_far;
+uniform float fog_scale;
 
 // gl_TexCoord[0] comes from scenefx_vs, i.e. from post processing
 
@@ -55,6 +60,15 @@ void main()
   if(dark_flag) {
     dark_factor=max(0.0,1.0-dark_mult*(1.0-texture2D(dark_map,gl_TexCoord[0].xy).r));
   }
-    
-  gl_FragColor.rgb = shadow_factor*occl_factor*dark_factor*scene_color.rgb;
+
+  float fog=1.0;
+  if(fog_flag) {
+    float z = 2.0*depth_near*depth_far/(-(depth*2.0-1.0)*(depth_far-depth_near)+depth_far+depth_near);
+    fog = clamp((fog_far-z) * fog_scale, 0.0, 1.0);
+  }
+
+  gl_FragColor.rgb = mix(gl_Fog.color.rgb, 
+                         shadow_factor*occl_factor*dark_factor*scene_color.rgb,
+                         fog);
 }
+
diff --git a/modules/gfx/src/vertex_array.cc b/modules/gfx/src/vertex_array.cc
index b9c45e5a7ce54f274b2b1e0b029f100fd81772ec..155417b65e2cb2080bd6a5230ee30b936c3f5134 100644
--- a/modules/gfx/src/vertex_array.cc
+++ b/modules/gfx/src/vertex_array.cc
@@ -141,7 +141,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,
@@ -494,7 +493,7 @@ void IndexedVertexArray::RenderGL()
     } else {
       glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
     }
-    if(cull_face_) {
+    if(cull_face_ && !solid_) {
       glEnable(GL_CULL_FACE);
     } else { 
       glDisable(GL_CULL_FACE); 
@@ -699,6 +698,8 @@ void IndexedVertexArray::Reset()
   outline_mat_update_=true;
   outline_exp_factor_=0.1;
   outline_exp_color_=Color(0,0,0);
+  solid_=false;
+  solid_color_=RGB(1,1,1);
   draw_normals_=false;
   use_tex_=false;
 }
@@ -1095,6 +1096,8 @@ void IndexedVertexArray::copy(const IndexedVertexArray& va)
   outline_mat_update_=true;
   outline_exp_factor_=va.outline_exp_factor_;
   outline_exp_color_=va.outline_exp_color_;
+  solid_=va.solid_;
+  solid_color_=va.solid_color_;
   draw_normals_=va.draw_normals_;
   use_tex_=va.use_tex_;
 }
@@ -1174,6 +1177,14 @@ bool IndexedVertexArray::prep_buff()
 
 void IndexedVertexArray::draw_ltq(bool use_buff)
 {
+  if(solid_) {
+    glClearStencil(0x0);
+    glClear(GL_STENCIL_BUFFER_BIT);
+    glEnable(GL_STENCIL_TEST);
+    glStencilFunc(GL_ALWAYS,0x0,0x1);
+    glStencilOp(GL_KEEP,GL_INVERT,GL_INVERT);
+  }
+
   if(use_buff && !Scene::Instance().InOffscreenMode()) {
 #if OST_SHADER_SUPPORT_ENABLED
 #if 0
@@ -1230,8 +1241,35 @@ void IndexedVertexArray::draw_ltq(bool use_buff)
       glDrawElements(GL_LINES,line_index_list_.size(),GL_UNSIGNED_INT,&line_index_list_[0]);
     }
   }
+
+  if(solid_) {
+    glStencilFunc(GL_EQUAL,0x1,0x1);
+    glMatrixMode(GL_MODELVIEW);
+    glPushMatrix();
+    glLoadIdentity();
+
+    float fov=Scene::Instance().GetFOV()*M_PI/180.0;
+    float znear=Scene::Instance().GetNear();
+    float aspect=Scene::Instance().GetAspect();
+    float rh=2.0*fabs(tan(fov)*znear);
+    float rw=rh*aspect;
+    float rz=-znear-0.1;
+
+    glDisable(GL_LIGHTING);
+  
+    glBegin(GL_TRIANGLE_STRIP);
+    glColor3fv(solid_color_);
+    glNormal3f(0,0,1);
+    glVertex3f(-rw,-rh,rz);
+    glVertex3f(rw,-rh,rz);
+    glVertex3f(-rw,rh,rz);
+    glVertex3f(rw,rh,rz);
+    glEnd();
+    glDisable(GL_STENCIL_TEST);
+    glPopMatrix();
+  }
 }
-    
+
 void IndexedVertexArray::draw_p(bool use_buff)
 {
   if(use_buff && !Scene::Instance().InOffscreenMode()) {
@@ -1254,115 +1292,115 @@ void IndexedVertexArray::draw_p(bool use_buff)
 
 namespace {
 
-struct AALineEntry {
-  float p0[3], p1[3];
-  float edge0[3],edge1[3],edge2[3],edge3[3];
-  float c0[4], c1[4];
-  float z;
-};
+  struct AALineEntry {
+    float p0[3], p1[3];
+    float edge0[3],edge1[3],edge2[3],edge3[3];
+    float c0[4], c1[4];
+    float z;
+  };
 
-typedef std::vector<AALineEntry> AALineList;
+  typedef std::vector<AALineEntry> AALineList;
 
-struct AALineEntryLess
-{
-  bool operator()(const AALineEntry& e1, const AALineEntry& e2)
+  struct AALineEntryLess
   {
-    return e1.z<e2.z;
-  }
-};
+    bool operator()(const AALineEntry& e1, const AALineEntry& e2)
+    {
+      return e1.z<e2.z;
+    }
+  };
 
-/*
-  Adapted after Chan and Durand, "Fast Prefiltered Lines",
-  in GPU Gems 2
-*/
-void render_aalines(AALineList& line_list, float w, float r)
-{
+  /*
+     Adapted after Chan and Durand, "Fast Prefiltered Lines",
+     in GPU Gems 2
+     */
+  void render_aalines(AALineList& line_list, float w, float r)
+  {
 #if OST_SHADER_SUPPORT_ENABLED
-  static GLuint table_tex_id=0;
-  std::vector<unsigned char> tex_table(32);
+    static GLuint table_tex_id=0;
+    std::vector<unsigned char> tex_table(32);
 
-  if(table_tex_id==0) {
-    for(int i=0;i<32;++i) {
-      float x=static_cast<float>(i)/31.0;
-      tex_table[31-i]=static_cast<unsigned char>(255.0*exp(-4.0*x*x));
+    if(table_tex_id==0) {
+      for(int i=0;i<32;++i) {
+        float x=static_cast<float>(i)/31.0;
+        tex_table[31-i]=static_cast<unsigned char>(255.0*exp(-4.0*x*x));
+      }
+      glGenTextures(1,&table_tex_id);
+      glBindTexture(GL_TEXTURE_1D,table_tex_id);
+      glPixelStorei(GL_UNPACK_ALIGNMENT,1);
+      glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+      glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+      glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+      glTexImage1D(GL_TEXTURE_1D,0,GL_LUMINANCE,32,0,GL_LUMINANCE,GL_UNSIGNED_BYTE,&tex_table[0]);
     }
-    glGenTextures(1,&table_tex_id);
-    glBindTexture(GL_TEXTURE_1D,table_tex_id);
-    glPixelStorei(GL_UNPACK_ALIGNMENT,1);
-    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP);
-    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexImage1D(GL_TEXTURE_1D,0,GL_LUMINANCE,32,0,GL_LUMINANCE,GL_UNSIGNED_BYTE,&tex_table[0]);
-  }
-  std::sort(line_list.begin(),line_list.end(),AALineEntryLess());
-  
-  Shader::Instance().PushProgram();
-  Shader::Instance().Activate("aaline");
+    std::sort(line_list.begin(),line_list.end(),AALineEntryLess());
 
-  glLineWidth(ceil((2.0f*r+w)*1.5));
+    Shader::Instance().PushProgram();
+    Shader::Instance().Activate("aaline");
 
-  glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT);
-  glDisable(GL_NORMALIZE);
-  glDisable(GL_CULL_FACE);
-  glDisable(GL_LIGHTING);
-  glDisable(GL_COLOR_MATERIAL);
-  //glDisable(GL_DEPTH_TEST);
-  glDisable(GL_LINE_SMOOTH);
-  glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
-  glEnable(GL_BLEND);
-  glDepthMask(0);
-  Shader::Instance().UpdateState();
-  
-  GLuint cpr = Shader::Instance().GetCurrentProgram();
-  GLint edge0_id = glGetUniformLocation(cpr,"edge0");
-  GLint edge1_id = glGetUniformLocation(cpr,"edge1");
-  GLint edge2_id = glGetUniformLocation(cpr,"edge2");
-  GLint edge3_id = glGetUniformLocation(cpr,"edge3");
-  GLint table_id = glGetUniformLocation(cpr,"table");
-
-  glActiveTexture(GL_TEXTURE0);
-  glDisable(GL_TEXTURE_2D);
-  glEnable(GL_TEXTURE_1D);
-  glBindTexture(GL_TEXTURE_1D,table_tex_id);
-  glUniform1i(table_id,0);
-
-  for(AALineList::iterator it=line_list.begin();
-      it!=line_list.end();++it) {
-    glUniform3fv(edge0_id,1,it->edge0);
-    glUniform3fv(edge1_id,1,it->edge1);
-    glUniform3fv(edge2_id,1,it->edge2);
-    glUniform3fv(edge3_id,1,it->edge3);
-    // glUniform cannot be inside a glBegin / glEnd
-    glBegin(GL_LINES);
-    glColor4fv(it->c0);
-    glVertex3fv(it->p0);
-    glColor4fv(it->c1);
-    glVertex3fv(it->p1); 
-    glEnd();
-  }
+    glLineWidth(ceil((2.0f*r+w)*1.5));
 
-  glPopAttrib();
+    glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT);
+    glDisable(GL_NORMALIZE);
+    glDisable(GL_CULL_FACE);
+    glDisable(GL_LIGHTING);
+    glDisable(GL_COLOR_MATERIAL);
+    //glDisable(GL_DEPTH_TEST);
+    glDisable(GL_LINE_SMOOTH);
+    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+    glEnable(GL_BLEND);
+    glDepthMask(0);
+    Shader::Instance().UpdateState();
+
+    GLuint cpr = Shader::Instance().GetCurrentProgram();
+    GLint edge0_id = glGetUniformLocation(cpr,"edge0");
+    GLint edge1_id = glGetUniformLocation(cpr,"edge1");
+    GLint edge2_id = glGetUniformLocation(cpr,"edge2");
+    GLint edge3_id = glGetUniformLocation(cpr,"edge3");
+    GLint table_id = glGetUniformLocation(cpr,"table");
 
-  Shader::Instance().PopProgram();
+    glActiveTexture(GL_TEXTURE0);
+    glDisable(GL_TEXTURE_2D);
+    glEnable(GL_TEXTURE_1D);
+    glBindTexture(GL_TEXTURE_1D,table_tex_id);
+    glUniform1i(table_id,0);
+
+    for(AALineList::iterator it=line_list.begin();
+        it!=line_list.end();++it) {
+      glUniform3fv(edge0_id,1,it->edge0);
+      glUniform3fv(edge1_id,1,it->edge1);
+      glUniform3fv(edge2_id,1,it->edge2);
+      glUniform3fv(edge3_id,1,it->edge3);
+      // glUniform cannot be inside a glBegin / glEnd
+      glBegin(GL_LINES);
+      glColor4fv(it->c0);
+      glVertex3fv(it->p0);
+      glColor4fv(it->c1);
+      glVertex3fv(it->p1); 
+      glEnd();
+    }
+
+    glPopAttrib();
+
+    Shader::Instance().PopProgram();
 #endif
-}
+  }
 
-Vec3 make_aaline_edge(const Vec2& c1, const Vec2& c0, float s)
-{
-  Vec3 nrvo(c1[1]-c0[1],c0[0]-c1[0],c1[0]*c0[1]-c0[0]*c1[1]);
-  nrvo*=1.0/(s*Length(c1-c0));
-  return nrvo;
-}
+  Vec3 make_aaline_edge(const Vec2& c1, const Vec2& c0, float s)
+  {
+    Vec3 nrvo(c1[1]-c0[1],c0[0]-c1[0],c1[0]*c0[1]-c0[0]*c1[1]);
+    nrvo*=1.0/(s*Length(c1-c0));
+    return nrvo;
+  }
 
 }
-    
+
 void IndexedVertexArray::draw_aalines()
 {
 #if OST_SHADER_SUPPORT_ENABLED
   float w=0.5*line_width_;
   float r=w;
   float hwr = 0.5*w+r;
-  
+
   AALineList line_list;
   for(unsigned int i=0;i<line_index_list_.size();i+=2) {
     Entry& ve0 = entry_list_[line_index_list_[i]];
@@ -1381,26 +1419,26 @@ void IndexedVertexArray::draw_aalines()
     Vec3 e1=make_aaline_edge(c1,c2,r);
     Vec3 e2=make_aaline_edge(c2,c3,r);
     Vec3 e3=make_aaline_edge(c3,c0,r);
-    
+
     // TODO: it should be possible to avoid the unproject and
     // pass the projected coordinates directly to GL, setting
     // modelview and projection to unity; requires handling of
     // the viewport though!
     Vec3 np1=Scene::Instance().UnProject(q0-Vec3(hwr*d),false);
     Vec3 np2=Scene::Instance().UnProject(q1+Vec3(hwr*d),false);
-    
+
     AALineEntry le={{np1[0],np1[1],np1[2]},
-                    {np2[0],np2[1],np2[2]},
-                    {e0[0],e0[1],e0[2]},
-                    {e1[0],e1[1],e1[2]},
-                    {e2[0],e2[1],e2[2]},
-                    {e3[0],e3[1],e3[2]},
-                    {ve0.c[0],ve0.c[1],ve0.c[2],ve0.c[3]},
-                    {ve1.c[0],ve1.c[1],ve1.c[2],ve1.c[3]},
-                    -0.5*(q0[2]+q1[2])};
+      {np2[0],np2[1],np2[2]},
+      {e0[0],e0[1],e0[2]},
+      {e1[0],e1[1],e1[2]},
+      {e2[0],e2[1],e2[2]},
+      {e3[0],e3[1],e3[2]},
+      {ve0.c[0],ve0.c[1],ve0.c[2],ve0.c[3]},
+      {ve1.c[0],ve1.c[1],ve1.c[2],ve1.c[3]},
+      -0.5*(q0[2]+q1[2])};
     line_list.push_back(le);
   }
-  
+
   render_aalines(line_list,w,r);
 #endif
 }
@@ -1434,11 +1472,11 @@ geom::AlignedCuboid IndexedVertexArray::GetBoundingBox() const
     return geom::AlignedCuboid(geom::Vec3(0,0,0),geom::Vec3(0,0,0));
   } else {
     geom::Vec3 minc(std::numeric_limits<float>::max(),
-                    std::numeric_limits<float>::max(),
-                    std::numeric_limits<float>::max());
+        std::numeric_limits<float>::max(),
+        std::numeric_limits<float>::max());
     geom::Vec3 maxc(-std::numeric_limits<float>::max(),
-                    -std::numeric_limits<float>::max(),
-                    -std::numeric_limits<float>::max());
+        -std::numeric_limits<float>::max(),
+        -std::numeric_limits<float>::max());
     for(EntryList::const_iterator it=entry_list_.begin();it!=entry_list_.end();++it) {
       geom::Vec3 p(it->v[0],it->v[1],it->v[2]);
       minc=geom::Min(minc,p);
diff --git a/modules/gfx/src/vertex_array.hh b/modules/gfx/src/vertex_array.hh
index ee63c939aae475959cfa12963b730f7326392df6..539d871b775c6219a397c0ca4795a23baa8c402b 100644
--- a/modules/gfx/src/vertex_array.hh
+++ b/modules/gfx/src/vertex_array.hh
@@ -117,6 +117,11 @@ class DLLEXPORT_OST_GFX IndexedVertexArray {
   void SetOutlineExpandColor(const Color& c);
   Color GetOutlineExpandColor() const {return outline_exp_color_;}
 
+  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_;}
+
   // 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());
 
@@ -233,7 +238,8 @@ class DLLEXPORT_OST_GFX IndexedVertexArray {
   unsigned int outline_mat_dlist_;
   float outline_exp_factor_;
   Color outline_exp_color_;
-
+  bool solid_;
+  Color solid_color_;
   bool draw_normals_;
 
   bool use_tex_;
diff --git a/modules/gui/pymod/init_spacenav.py b/modules/gui/pymod/init_spacenav.py
index c05a59a2dbee5d372870ec12db1090bb485c5e46..f94b569f97d8c943fc2fd2ee5f369fd5c976961e 100644
--- a/modules/gui/pymod/init_spacenav.py
+++ b/modules/gui/pymod/init_spacenav.py
@@ -46,10 +46,11 @@ class SpacenavControl(QtCore.QObject):
   def Toggle(self, button):
     if button == 0:
       self.trans = not self.trans
-      ost.LogVerbose("SpaceNav: translation %s "%("enabled" if self.trans else "disabled"))
+      ost.LogVerbose("SpaceNav: translation %s" % (self.strans and "enabled" or "disabled"))
     elif button == 1:
       self.rot = not self.rot
-      ost.LogVerbose("SpaceNav: rotation %s"%("enabled" if self.rot else "disabled"))
+      #ost.LogVerbose("SpaceNav: rotation %s"%("enabled" if self.rot else "disabled"))
+      ost.LogVerbose("SpaceNav: rotation %s"%(self.rot and "enabled" or "disabled"))
     elif button == 12:
       if self.speed > 20:
         self.speed *= 0.8
diff --git a/modules/gui/src/gosty.cc b/modules/gui/src/gosty.cc
index 670c454c1886f0c1c2013954d3996a38060781b6..a0be0fae0762c45d1ae9596cdf57f65c168d8d5a 100644
--- a/modules/gui/src/gosty.cc
+++ b/modules/gui/src/gosty.cc
@@ -117,7 +117,7 @@ void setup_python_search_path(const String& root, PythonInterpreter& pi)
 #  if (defined(__ppc64__) || defined(__x86_64__)) && !defined(__APPLE__)
   pi.AppendModulePath(QString::fromStdString(root+"/lib64/"+
                                              site_pkgs.str()+
-                                             "site-packages"));
+                                             "/site-packages"));
 #  else
   pi.AppendModulePath(QString::fromStdString(root+"/lib/"+
                                              site_pkgs.str()+
@@ -200,6 +200,23 @@ void prepare_scripts(int argc, char** argv, PythonInterpreter& py)
   py.RunScript(argv[1]);
 }
 
+class MyApplication : public QApplication
+{
+public:
+    MyApplication(int argc, char** argv) : QApplication(argc, argv) {}
+    virtual ~MyApplication() {}
+    virtual bool notify(QObject *rec, QEvent *ev)
+    {
+      try {
+        return QApplication::notify(rec, ev);
+      } catch( std::runtime_error& e) {
+        std::cerr << "runtime_error in Qt main loop: " << e.what() << std::endl;
+        exit(0);
+      }
+      return false;
+    }
+};
+
 
 }
 
@@ -208,7 +225,7 @@ int main(int argc, char** argv)
 {
   int dummy_argc=1;
   
-  QApplication app(dummy_argc,argv);
+  MyApplication app(dummy_argc,argv);
   QCoreApplication::setOrganizationName("OpenStructure");
   QCoreApplication::setOrganizationDomain("openstructure.org");
   QCoreApplication::setApplicationName(QString(argv[2]));
diff --git a/modules/gui/src/sequence_viewer/sequence_model.cc b/modules/gui/src/sequence_viewer/sequence_model.cc
index 0a98033c703cef68d0cd0c49fee8b8dd85f065c2..d64020ad925ca9307ca3fafd423f7de027d4684c 100644
--- a/modules/gui/src/sequence_viewer/sequence_model.cc
+++ b/modules/gui/src/sequence_viewer/sequence_model.cc
@@ -50,7 +50,8 @@ SequenceModel::SequenceModel(QObject *parent)
   this->endInsertRows();
 }
 
-void SequenceModel::InsertSequence(QString& name, seq::SequenceHandle& seq){
+void SequenceModel::InsertSequence(QString& name, seq::SequenceHandle& seq)
+{
   int cols = this->columnCount();
   int new_cols = seq.GetLength();
   this->beginInsertRows(QModelIndex(),this->rowCount(),this->rowCount());
@@ -63,7 +64,7 @@ void SequenceModel::InsertSequence(QString& name, seq::SequenceHandle& seq){
   this->endInsertRows();
 }
 
-void SequenceModel::InsertChain(QString& name, mol::ChainView& view){
+void SequenceModel::InsertChain(QString& name, mol::ChainView& view) {
   int cols = this->columnCount();
   int new_cols = view.GetResidueCount();
   this->beginInsertRows(QModelIndex(),this->rowCount(),this->rowCount());
@@ -89,8 +90,10 @@ void SequenceModel::InsertAlignment(const seq::AlignmentHandle& alignment){
   this->endInsertRows();
 }
 
-void SequenceModel::InsertSequences(const QList<QString>& names, seq::SequenceList& list){
-  this->beginInsertRows(this->index(this->rowCount(),0),this->rowCount(),this->rowCount()+list.GetCount());
+void SequenceModel::InsertSequences(const QList<QString>& names, 
+                                    seq::SequenceList& list){
+  this->beginInsertRows(this->index(this->rowCount(),0),
+                        this->rowCount(),this->rowCount()+list.GetCount());
   objects_.append(new SequenceViewObject(list, names, this));
   this->endInsertRows();
 }
@@ -143,7 +146,7 @@ void SequenceModel::RemoveAlignment(const seq::AlignmentHandle& alignment){
   }
 }
 
-int SequenceModel::GetColumnCount() const{
+int SequenceModel::GetColumnCount() const {
   int cols = 0;
   for(int i = 0; i<objects_.size();i++){
     int ob_cols = objects_[i]->GetMaxColumnCount();
@@ -154,7 +157,8 @@ int SequenceModel::GetColumnCount() const{
   return cols;
 }
 
-SequenceViewObject* SequenceModel::GetItem(const gfx::EntityP& entity){
+SequenceViewObject* SequenceModel::GetItem(const gfx::EntityP& entity)
+{
   if(entity != NULL){
     for (int i = 0 ; i< objects_.size(); i++){
       if(SequenceViewObject* seq_view_object = qobject_cast<SequenceViewObject*>(objects_[i])){
@@ -167,7 +171,8 @@ SequenceViewObject* SequenceModel::GetItem(const gfx::EntityP& entity){
   return NULL;
 }
 
-AlignmentViewObject* SequenceModel::GetItem(const seq::AlignmentHandle& alignment){
+AlignmentViewObject* SequenceModel::GetItem(const seq::AlignmentHandle& alignment)
+{
   for (int i = 0 ; i< objects_.size(); i++){
     if(AlignmentViewObject* alignment_object = qobject_cast<AlignmentViewObject*>(objects_[i])){
       if(alignment == alignment_object->GetAlignment()){
@@ -178,7 +183,8 @@ AlignmentViewObject* SequenceModel::GetItem(const seq::AlignmentHandle& alignmen
   return NULL;
 }
 
-const PainterList& SequenceModel::GetPainters(const QModelIndex& index) const{
+const PainterList& SequenceModel::GetPainters(const QModelIndex& index) const
+{
   QPair<int, BaseViewObject*> pair = this->GetRowWithItem(index);
   if(pair.second){
     return pair.second->GetRow(pair.first)->GetPainters();
@@ -255,7 +261,8 @@ int SequenceModel::GetGlobalRow(BaseViewObject* obj, int row) const
   return glob_row;
 }
 
-QModelIndexList SequenceModel::GetModelIndexes(gfx::EntityP& entity, const mol::EntityView& view)
+QModelIndexList SequenceModel::GetModelIndexes(gfx::EntityP& entity, 
+                                               const mol::EntityView& view)
 {
   QModelIndexList list;
   if(BaseViewObject* object = this->GetItem(entity)){
@@ -275,7 +282,8 @@ QModelIndexList SequenceModel::GetModelIndexes(gfx::EntityP& entity, const mol::
   return list;
 }
 
-QModelIndexList SequenceModel::GetModelIndexes(const QString& subject, const QString& sequence_name)
+QModelIndexList SequenceModel::GetModelIndexes(const QString& subject, 
+                                               const QString& sequence_name)
 {
   QModelIndexList list;
   for (int i = 0; i<objects_.size(); i++){
@@ -295,7 +303,8 @@ QModelIndexList SequenceModel::GetModelIndexes(const QString& subject, const QSt
   return list;
 }
 
-void SequenceModel::SelectionChanged(const QItemSelection& sel, const QItemSelection& desel)
+void SequenceModel::SelectionChanged(const QItemSelection& sel, 
+                                     const QItemSelection& desel)
 {
   QMap<int,QPair<QSet<int>,QSet<int> > > sel_map;
   const QModelIndexList& sel_indexes = sel.indexes();
diff --git a/modules/gui/src/sequence_viewer/sequence_row.cc b/modules/gui/src/sequence_viewer/sequence_row.cc
index 30199dd6f7c69c0653064f0259f5870590a60adf..1d431cbae8bc0998d00e0e3281429aaf8bbaacbf 100644
--- a/modules/gui/src/sequence_viewer/sequence_row.cc
+++ b/modules/gui/src/sequence_viewer/sequence_row.cc
@@ -34,13 +34,18 @@
 #include <QtGui>
 namespace ost { namespace gui {
 
-SequenceRow::SequenceRow(const QString& name, seq::ConstSequenceHandle sequence, SequenceViewObject* parent) : BaseRow(QFont("Courier",11),parent), name_(name), name_font_(QFont("Courier",11)), sequence_(sequence)
+SequenceRow::SequenceRow(const QString& name, seq::ConstSequenceHandle sequence, 
+                         SequenceViewObject* parent) : 
+  BaseRow(QFont("Courier",11),parent), name_(name), 
+  name_font_(QFont("Courier",11)), sequence_(sequence)
 {
   name_font_.setBold(true);
   name_font_.setItalic(true);
 }
 
-SequenceRow::SequenceRow(const QString& name, SequenceViewObject* parent) : BaseRow(QFont("Courier",11),parent), name_(name), name_font_(QFont("Courier",11))
+SequenceRow::SequenceRow(const QString& name, SequenceViewObject* parent) : 
+  BaseRow(QFont("Courier",11),parent), name_(name), 
+  name_font_(QFont("Courier",11))
 {
   name_font_.setBold(true);
   name_font_.setItalic(true);
diff --git a/modules/gui/src/sequence_viewer/sequence_table_view.cc b/modules/gui/src/sequence_viewer/sequence_table_view.cc
index 90b4baa5bc4ef8ce742a006ab5b38227409e059a..68eb7d2d8766a8204987f7aae0e641e1980cd9f3 100644
--- a/modules/gui/src/sequence_viewer/sequence_table_view.cc
+++ b/modules/gui/src/sequence_viewer/sequence_table_view.cc
@@ -60,8 +60,10 @@ SequenceTableView::SequenceTableView(QAbstractItemModel * model)
   this->setHorizontalScrollMode(ScrollPerPixel);
   this->setVerticalScrollMode(ScrollPerPixel);
 
-  connect(this->horizontalHeader(),SIGNAL(sectionResized(int,int,int)), this, SLOT(ResizeWidth(int,int,int)));
-  connect(this->verticalHeader(),SIGNAL(sectionResized(int,int,int)), this, SLOT(ResizeHeight(int,int,int)));
+  connect(this->horizontalHeader(),SIGNAL(sectionResized(int,int,int)), 
+          this, SLOT(ResizeWidth(int,int,int)));
+  connect(this->verticalHeader(),SIGNAL(sectionResized(int,int,int)), 
+          this, SLOT(ResizeHeight(int,int,int)));
 
   delegate_ = new SequenceDelegate(qobject_cast<SequenceModel*>(this->model()),this);
 
@@ -140,8 +142,10 @@ void SequenceTableView::InitStaticRow()
 
   static_row_->setItemDelegate(delegate_);
 
-  connect(static_row_->horizontalScrollBar(), SIGNAL(valueChanged(int)), this->horizontalScrollBar(), SLOT(setValue(int)));
-  connect(horizontalScrollBar(), SIGNAL(valueChanged(int)), static_row_->horizontalScrollBar(), SLOT(setValue(int)));
+  connect(static_row_->horizontalScrollBar(), SIGNAL(valueChanged(int)), 
+          this->horizontalScrollBar(), SLOT(setValue(int)));
+  connect(horizontalScrollBar(), SIGNAL(valueChanged(int)), 
+          static_row_->horizontalScrollBar(), SLOT(setValue(int)));
 
   this->updateStaticRow();
 }
@@ -179,10 +183,14 @@ void SequenceTableView::InitStaticField(){
   static_field_->setHorizontalScrollMode(ScrollPerPixel);
   static_field_->setVerticalScrollMode(ScrollPerPixel);
 
-  connect(static_field_->horizontalScrollBar(), SIGNAL(valueChanged(int)), this->horizontalScrollBar(), SLOT(setValue(int)));
-  connect(horizontalScrollBar(), SIGNAL(valueChanged(int)), static_field_->horizontalScrollBar(), SLOT(setValue(int)));
-  connect(static_field_->verticalScrollBar(), SIGNAL(valueChanged(int)), this->verticalScrollBar(), SLOT(setValue(int)));
-  connect(verticalScrollBar(), SIGNAL(valueChanged(int)), static_field_->verticalScrollBar(), SLOT(setValue(int)));
+  connect(static_field_->horizontalScrollBar(), SIGNAL(valueChanged(int)), 
+          this->horizontalScrollBar(), SLOT(setValue(int)));
+  connect(horizontalScrollBar(), SIGNAL(valueChanged(int)), 
+          static_field_->horizontalScrollBar(), SLOT(setValue(int)));
+  connect(static_field_->verticalScrollBar(), SIGNAL(valueChanged(int)), 
+          this->verticalScrollBar(), SLOT(setValue(int)));
+  connect(verticalScrollBar(), SIGNAL(valueChanged(int)), 
+          static_field_->verticalScrollBar(), SLOT(setValue(int)));
 
   this->updateStaticField();
 }
@@ -222,7 +230,8 @@ void SequenceTableView::resizeEvent(QResizeEvent * event)
 #endif  
 }
 
-QModelIndex SequenceTableView::moveCursor(CursorAction action, Qt::KeyboardModifiers modifiers)
+QModelIndex SequenceTableView::moveCursor(CursorAction action, 
+                                          Qt::KeyboardModifiers modifiers)
 {
   QModelIndex current = QTableView::moveCursor(action, modifiers);
 
diff --git a/modules/gui/src/sequence_viewer/sequence_viewer.cc b/modules/gui/src/sequence_viewer/sequence_viewer.cc
index a34e917b6c20e86e2ba752c08d3b5e2ced3a2c29..29314805cad9465325bad4281f8e670a3e8bb2ad 100644
--- a/modules/gui/src/sequence_viewer/sequence_viewer.cc
+++ b/modules/gui/src/sequence_viewer/sequence_viewer.cc
@@ -132,7 +132,8 @@ void SequenceViewer::InitSearchBar()
   seq_search_bar_ = new SeqSearchBar(this);
   seq_search_bar_->hide();
   layout()->addWidget(seq_search_bar_);
-  connect(seq_search_bar_, SIGNAL(Changed(const QString&, bool, const QString&)), this, SLOT(OnSearchBarUpdate(const QString&, bool, const QString&)));
+  connect(seq_search_bar_, SIGNAL(Changed(const QString&, bool, const QString&)), 
+         this, SLOT(OnSearchBarUpdate(const QString&, bool, const QString&)));
 }
 
 void SequenceViewer::InitView()
diff --git a/modules/gui/src/sequence_viewer/tick_painter.cc b/modules/gui/src/sequence_viewer/tick_painter.cc
index eee4143d692c2e38ebc1a925543307fc3ec59dff..4c1558a5a5c02469670cddeaf8c31e77aa67d2ba 100644
--- a/modules/gui/src/sequence_viewer/tick_painter.cc
+++ b/modules/gui/src/sequence_viewer/tick_painter.cc
@@ -32,7 +32,8 @@ TickPainter::TickPainter(QObject* parent)
     : Painter(parent), pen_(QPen(Qt::darkGray))
 {}
 
-void TickPainter::Paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index){
+void TickPainter::Paint(QPainter* painter, const QStyleOptionViewItem& option, 
+                        const QModelIndex& index){
   painter->save();
   painter->setPen(pen_);
   QVariant value = index.data(Qt::DisplayRole);
diff --git a/modules/gui/src/sequence_viewer/title_row.cc b/modules/gui/src/sequence_viewer/title_row.cc
index ba7aaf280a761b9a91c39f9d26dbf02013171974..d4dd16fa5757f5ea4f43e1d5a971f1802c4381e4 100644
--- a/modules/gui/src/sequence_viewer/title_row.cc
+++ b/modules/gui/src/sequence_viewer/title_row.cc
@@ -41,29 +41,30 @@ QVariant TitleRow::GetData(int column, int role) const
   if(column<0){
     return QVariant();
   }
-  else if(role==Qt::DisplayRole && column%10==9){
-    return QVariant(QString::number(column+1));
-  }
-  else if(role==Qt::DisplayRole && column%10==0){
-      return QVariant(QString::number(column));
-  }
-  else if (role==Qt::FontRole){
-    if(column < 999){
-      return QVariant(font_);
-    }
-    else{
+  switch (role) {
+    case Qt::DisplayRole:
+      if (column % 10 == 9) { 
+        return QVariant(QString::number(column+1));
+      }
+      if (column % 10 == 0) {
+        return QVariant(QString::number(column));
+      }
+      return QVariant();
+    case Qt::FontRole:
+      if(column < 999){
+        return QVariant(font_);
+      }
       return QVariant(small_font_);
-    }
-  }
-  else if (role==Qt::TextAlignmentRole){
-    return QVariant(Qt::AlignHCenter|Qt::AlignBottom);
-  }
-  else if (role==Qt::SizeHintRole){
+    case Qt::TextAlignmentRole:
+      return QVariant(Qt::AlignHCenter|Qt::AlignBottom);
+    case Qt::SizeHintRole: {
       QSize size = this->GetCellSize();
       size.setHeight(10);
       return QVariant(size);
+    }
+    default:
+      return BaseRow::GetData(column, role);
   }
-  return BaseRow::GetData(column, role);
 }
 
 Qt::ItemFlags TitleRow::Flags(int column) const
@@ -79,7 +80,8 @@ void TitleRow::DoubleClicked(int column)
  if(this->parent()){
    if(SequenceModel* model = qobject_cast<SequenceModel*>(this->parent()->parent())){
      int rows = model->rowCount()-1;
-     QItemSelection add = QItemSelection(model->index(1,column),model->index(rows,column));
+     QItemSelection add = QItemSelection(model->index(1,column),
+                                         model->index(rows,column));
      model->SelectionChanged(add,QItemSelection());
    }
  }
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 b601345196af9c1daec20fc6ec486846aa2d015a..e5546583a2208bd600c66d73667783aa3acb8338 100644
--- a/modules/img/base/src/image_state/image_state_algorithm.hh
+++ b/modules/img/base/src/image_state/image_state_algorithm.hh
@@ -34,7 +34,7 @@ namespace ost { namespace img { namespace image_state {
 
 /*
   one-time definition of the constructor adapters, allowing
-  zero to 10 ctor parameters to be automagically used. There
+  zero to 12 ctor parameters to be automagically used. There
   is probably a recursive way to do this more elegantly...
 
   this version includes a call to a base class to allow a name
@@ -52,14 +52,14 @@ namespace ost { namespace img { namespace image_state {
   template <class P0,                            \
             class P1>                            \
   CLASS (const P0& p0,                           \
-	 const P1& p1):                          \
+         const P1& p1):                          \
     FNC(p0,p1), BASE (FNC::GetAlgorithmName()) {}                                \
   /* 3 params */                                 \
   template <class P0,                            \
             class P1,                            \
             class P2>                            \
   CLASS (const P0& p0,                           \
-	 const P1& p1,                           \
+         const P1& p1,                           \
          const P2& p2):                          \
     FNC(p0,p1,p2), BASE (FNC::GetAlgorithmName()) {}                             \
   /* 4 params */                                 \
@@ -68,7 +68,7 @@ namespace ost { namespace img { namespace image_state {
             class P2,                            \
             class P3>                            \
   CLASS (const P0& p0,                           \
-	 const P1& p1,                           \
+         const P1& p1,                           \
          const P2& p2,                           \
          const P3& p3):                          \
     FNC(p0,p1,p2,p3), BASE (FNC::GetAlgorithmName()) {}                          \
@@ -79,7 +79,7 @@ namespace ost { namespace img { namespace image_state {
             class P3,                            \
             class P4>                            \
   CLASS (const P0& p0,                           \
-	 const P1& p1,                           \
+         const P1& p1,                           \
          const P2& p2,                           \
          const P3& p3,                           \
          const P4& p4):                          \
@@ -92,7 +92,7 @@ namespace ost { namespace img { namespace image_state {
             class P4,                            \
             class P5>                            \
   CLASS (const P0& p0,                           \
-	 const P1& p1,                           \
+         const P1& p1,                           \
          const P2& p2,                           \
          const P3& p3,                           \
          const P4& p4,                           \
@@ -107,7 +107,7 @@ namespace ost { namespace img { namespace image_state {
             class P5,                            \
             class P6>                            \
   CLASS (const P0& p0,                           \
-	 const P1& p1,                           \
+         const P1& p1,                           \
          const P2& p2,                           \
          const P3& p3,                           \
          const P4& p4,                           \
@@ -124,7 +124,7 @@ namespace ost { namespace img { namespace image_state {
             class P6,                            \
             class P7>                            \
   CLASS (const P0& p0,                           \
-	 const P1& p1,                           \
+         const P1& p1,                           \
          const P2& p2,                           \
          const P3& p3,                           \
          const P4& p4,                           \
@@ -143,7 +143,7 @@ namespace ost { namespace img { namespace image_state {
             class P7,                            \
             class P8>                            \
   CLASS (const P0& p0,                           \
-	 const P1& p1,                           \
+         const P1& p1,                           \
          const P2& p2,                           \
          const P3& p3,                           \
          const P4& p4,                           \
@@ -164,7 +164,7 @@ namespace ost { namespace img { namespace image_state {
             class P8,                            \
             class P9>                            \
   CLASS (const P0& p0,                           \
-	 const P1& p1,                           \
+         const P1& p1,                           \
          const P2& p2,                           \
          const P3& p3,                           \
          const P4& p4,                           \
@@ -187,7 +187,7 @@ namespace ost { namespace img { namespace image_state {
             class P9,                            \
             class PA>                            \
   CLASS (const P0& p0,                           \
-	 const P1& p1,                           \
+         const P1& p1,                           \
          const P2& p2,                           \
          const P3& p3,                           \
          const P4& p4,                           \
@@ -212,7 +212,7 @@ namespace ost { namespace img { namespace image_state {
             class PA,                            \
             class PB>                            \
   CLASS (const P0& p0,                           \
-	 const P1& p1,                           \
+         const P1& p1,                           \
          const P2& p2,                           \
          const P3& p3,                           \
          const P4& p4,                           \
@@ -221,8 +221,8 @@ namespace ost { namespace img { namespace image_state {
          const P7& p7,                           \
          const P8& p8,                           \
          const P9& p9,                           \
-         const P9& pa,                           \
-         const PA& pb):                          \
+         const PA& pa,                           \
+         const PB& pb):                          \
     FNC(p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,pa,pb), BASE (FNC::GetAlgorithmName()) {}
 
 
@@ -356,8 +356,8 @@ private:
 */
 template <class FNC>
 class TEMPLATE_EXPORT ImageStateConstModIPAlgorithm: public FNC, 
-				     public ConstModIPAlgorithm,
-				     public ImageStateConstModIPVisitorBase {
+             public ConstModIPAlgorithm,
+             public ImageStateConstModIPVisitorBase {
 public:
   IMAGE_STATE_VISITOR_CTOR_ADAPTERS(ImageStateConstModIPAlgorithm, ConstModIPAlgorithm)
 
@@ -409,8 +409,8 @@ private:
 //! out-of-place modifying image state const visitor plus op algorithm
 template <class FNC>
 class TEMPLATE_EXPORT ImageStateConstModOPAlgorithm: public FNC, 
-				     public ConstModOPAlgorithm, 
-				     public ImageStateConstModOPVisitorBase {
+                                                     public ConstModOPAlgorithm,
+                                                     public ImageStateConstModOPVisitorBase {
 public:
 
   IMAGE_STATE_VISITOR_CTOR_ADAPTERS(ImageStateConstModOPAlgorithm, ConstModOPAlgorithm)
diff --git a/modules/io/pymod/__init__.py b/modules/io/pymod/__init__.py
index 6df260a86ccd23e4a9b2b77094cef6ae85379c6d..616f04c087feb24b1347353f69f161464b0ea194 100644
--- a/modules/io/pymod/__init__.py
+++ b/modules/io/pymod/__init__.py
@@ -388,19 +388,19 @@ def _PDBize(biounit, asu, seqres=None, min_polymer_size=10):
       tr = geom.Mat4()
       tr = trans * rot
       trans_matrices.append(tr)
-      for op_n in range(1, len(operations)):
-        tmp_ops = list()
-        for o in operations[op_n]:
-          rot = geom.Mat4()
-          rot.PasteRotation(o.rotation)
-          trans = geom.Mat4()
-          trans.PasteTranslation(o.translation)
-          tr = geom.Mat4()
-          tr = trans * rot
-          for t_o in trans_matrices:
-            tp = t_o * tr
-            tmp_ops.append(tp)
-        trans_matrices = tmp_ops
+    for op_n in range(1, len(operations)):
+      tmp_ops = list()
+      for o in operations[op_n]:
+        rot = geom.Mat4()
+        rot.PasteRotation(o.rotation)
+        trans = geom.Mat4()
+        trans.PasteTranslation(o.translation)
+        tr = geom.Mat4()
+        tr = trans * rot
+        for t_o in trans_matrices:
+          tp = t_o * tr
+          tmp_ops.append(tp)
+      trans_matrices = tmp_ops
   # select chains into a view as basis for each transformation
   assu = asu.Select('cname=' + ','.join(biounit.GetChainList()))
   # use each transformation on the view, store as entity and transform, PDBize
@@ -426,6 +426,9 @@ def _PDBize(biounit, asu, seqres=None, min_polymer_size=10):
         edi.SetChainDescription(new_chain, chain.description)
         edi.SetChainType(new_chain, chain.type)
         new_chain.SetStringProp('original_name', chain.name)
+        if chain.HasProp("pdb_auth_chain_name"):
+          new_chain.SetStringProp("pdb_auth_chain_name", 
+                                  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)
@@ -456,6 +459,10 @@ def _PDBize(biounit, asu, seqres=None, min_polymer_size=10):
                                       mol.ResNum(last_rnum+1, ins_code))
           new_res.SetStringProp('description', chain.description)
           new_res.SetStringProp('type', mol.StringFromChainType(chain.type))
+          new_res.SetStringProp("original_name", chain.name)
+          if chain.HasProp("pdb_auth_chain_name"):
+            new_res.SetStringProp("pdb_auth_chain_name",
+                                  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...
diff --git a/modules/io/src/img/map_io_mrc_handler.cc b/modules/io/src/img/map_io_mrc_handler.cc
index bdde9d1e1701bb7180874db98d9bf9f7f8dc47a1..55d4f69138c1e48b90d797f2c3aefe31b2b8efe2 100644
--- a/modules/io/src/img/map_io_mrc_handler.cc
+++ b/modules/io/src/img/map_io_mrc_handler.cc
@@ -585,13 +585,13 @@ void real_filler(img::image_state::RealSpatialImageState& isi,
   img::Progress::Instance().Register(&this_dummy,header.ns*header.nr,100);
   for(int is=0;is<header.ns;++is) {
     pnt[maps]=header.nsstart+is;
+    std::vector<B> buffer(header.nr*header.nc);
+    f.read(&buffer[0],header.nr*header.nc);
     for(int ir=0;ir<header.nr;++ir) {
       pnt[mapr]=header.nrstart+ir;
       for(int ic=0;ic<header.nc;++ic) {
         pnt[mapc]=header.ncstart+ic;
-        B tmp;
-        f >> tmp;
-        isi.Value(pnt) = static_cast<Real>(tmp);
+        isi.Value(pnt) = img::Val2Val<B,Real>(buffer[header.nc*ir+ic]);
       }
       img::Progress::Instance().AdvanceProgress(&this_dummy);
     }
diff --git a/modules/io/src/img/map_io_png_handler.cc b/modules/io/src/img/map_io_png_handler.cc
index 571cecfa907547716b6997e9397dccb04313b4bd..d77db114b4d20c72d026d10e3f6e2435a8737b06 100644
--- a/modules/io/src/img/map_io_png_handler.cc
+++ b/modules/io/src/img/map_io_png_handler.cc
@@ -226,12 +226,12 @@ void MapIOPngHandler::Export(const img::MapHandle& image, std::ostream& f,const
 
   info_ptr = png_create_info_struct(png_ptr);
   if (info_ptr == NULL) {
-    png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
+    png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
     throw IOException("png: error creating info_struct");
   }
 
   if (setjmp(png_jmpbuf(png_ptr))) {
-    png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+    png_destroy_write_struct(&png_ptr, &info_ptr);
     throw IOException("png: error setting jmpbuf");
   }
 
@@ -293,7 +293,7 @@ void MapIOPngHandler::Export(const img::MapHandle& image, std::ostream& f,const
 
   png_write_end(png_ptr, info_ptr);
 
-  png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
+  png_destroy_write_struct(&png_ptr, &info_ptr);
 
 }
 
diff --git a/modules/io/src/img/map_io_spi_handler.cc b/modules/io/src/img/map_io_spi_handler.cc
index 6f5e1798b4674ed037884719036eeeda30323f6e..ad261daf908ec2bc0294f9b52e56a0d345d8553f 100644
--- a/modules/io/src/img/map_io_spi_handler.cc
+++ b/modules/io/src/img/map_io_spi_handler.cc
@@ -106,7 +106,7 @@ public:
     }
   }
 
-  float fNslice;  // nr of slices (1 for an image, negative nr of slices for new long label format
+  float fNslice;  // nr of slices (1 for an image, negative nr of slices indicates very old 2d image
   float fNrow;    // nr row per slice (Y)
   float fNrec;    // total nr of records (unused).
   float fNlabel;  // obsolete, unused
@@ -255,6 +255,9 @@ void header_filler(std::istream& in,  spider_header& header)
 {
   BinaryIStream<CONVERSIONTYPE> f(in);
   f >> header.fNslice;  
+  if(header.fNslice<1.0){
+    header.fNslice=1.0; // fix for very old 2d images with Nslice=-1
+  }
   f >> header.fNrow;  
   f >> header.fNrec;    
   f >> header.fNlabel; 
@@ -387,9 +390,8 @@ template <typename B >
 void real_dumper(std::ostream& f,  const spider_header& header, const img::ImageHandle& mh,const img::alg::Normalizer& norm, bool swap_flag)
 {
   int padding = header.fLabbyt-f.tellp();
-  char* buffer=new char[padding];
-  f.write(buffer,padding);
-  delete[] buffer;
+  std::vector<char> buffer(padding,0);
+  f.write(&buffer[0],padding);
   int slice_size=static_cast<int>(header.fNcol) * static_cast<int>(header.fNrow);
   boost::scoped_array<B> rawp(new B[slice_size]);
 
diff --git a/modules/io/src/img/map_io_tiff_handler.cc b/modules/io/src/img/map_io_tiff_handler.cc
index 0f418bc896c6f0563a5a3a0d38d1e5aecfe6495e..e6144315b78e3c2c13ddd7669f68ca841b983d0d 100644
--- a/modules/io/src/img/map_io_tiff_handler.cc
+++ b/modules/io/src/img/map_io_tiff_handler.cc
@@ -51,7 +51,8 @@ String TIF::FORMAT_STRING="defined_tiff";
   normalize_on_save_(normalize_on_save),
   bit_depth_(bit_depth),
   signed_(sign),
-  phasecolor_(phasecolor)
+  phasecolor_(phasecolor),
+  subimage_(subimage)
 {
 }
 
@@ -60,7 +61,8 @@ TIF::TIF(String format_string, boost::logic::tribool  normalize_on_save, Format
   normalize_on_save_(normalize_on_save),
   bit_depth_(bit_depth),
   signed_(sign),
-  phasecolor_(phasecolor)
+  phasecolor_(phasecolor),
+  subimage_(subimage)
 {
 }
 
diff --git a/modules/io/src/mol/entity_io_crd_handler.cc b/modules/io/src/mol/entity_io_crd_handler.cc
index 7820aba23f6715da589a4987475e0f5f9601e75c..d16358cc8029dd6b9dad17cf5e7beb039d159dd3 100644
--- a/modules/io/src/mol/entity_io_crd_handler.cc
+++ b/modules/io/src/mol/entity_io_crd_handler.cc
@@ -33,6 +33,7 @@
 #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/mol/io_profile.hh>
@@ -245,11 +246,7 @@ CRDWriter::CRDWriter(std::ostream& ostream, bool ext) :
 {}
 
 CRDWriter::CRDWriter(const boost::filesystem::path& filename, bool ext) :
-#if BOOST_FILESYSTEM_VERSION==3 || BOOST_VERSION<103400
-  outfile_(filename.string().c_str()),
-#else
-  outfile_(filename.file_string().c_str()),
-#endif
+  outfile_(BFPathToString(filename).c_str()),
   outstream_(outfile_), ext_(ext), atom_count_(0), res_count_(0)
 {}
 
diff --git a/modules/io/src/mol/entity_io_mae_handler.cc b/modules/io/src/mol/entity_io_mae_handler.cc
index b21407458c4422f105834152444f91215f6e2060..3c68d9964323a2b37df8636320d797f88fb93751 100644
--- a/modules/io/src/mol/entity_io_mae_handler.cc
+++ b/modules/io/src/mol/entity_io_mae_handler.cc
@@ -296,7 +296,23 @@ void MAEReader::parse_and_add_atom(mol::EntityHandle ent,
 
   if(update_residue) {
     if (!(curr_residue_=curr_chain_.FindResidue(rnum))) {
-      curr_residue_=editor.AppendResidue(curr_chain_, rkey, rnum);
+      if(curr_chain_.GetResidueCount()>0) {
+        int loc=curr_chain_.GetResidueCount()-1;
+        for(;loc>=0;--loc) {
+          if(curr_chain_.GetResidueByIndex(loc).GetNumber()<rnum) break;
+        }
+        if(loc<0) {
+          curr_residue_=editor.InsertResidueBefore(curr_chain_,0,rnum,rkey);
+        } else {
+          curr_residue_=editor.InsertResidueAfter(curr_chain_,loc,rnum,rkey);
+        }
+        if(!curr_residue_) {
+          // this should not happen...
+          curr_residue_=editor.AppendResidue(curr_chain_, rkey, rnum);
+        }
+      } else {
+        curr_residue_=editor.AppendResidue(curr_chain_, rkey, rnum);
+      }
       assert(curr_residue_.IsValid());
       LOG_TRACE(" new residue " << curr_residue_);
       ++residue_count_;
diff --git a/modules/io/src/mol/pdb_reader.cc b/modules/io/src/mol/pdb_reader.cc
index 739bf6bd34e5363447409c26c0822f09b594403a..13638576106be52ab3e75ac8c640b0f3a18ad3a3 100644
--- a/modules/io/src/mol/pdb_reader.cc
+++ b/modules/io/src/mol/pdb_reader.cc
@@ -41,23 +41,23 @@ using boost::format;
 
 namespace {
 
-bool IEquals(const StringRef& a, const StringRef& b)
-{
-  if (a.size()!=b.size()) {
-    return false;
-  }
-  for (size_t i=0; i<a.size(); ++i) {
-    if (toupper(a[i])!=b[i]) {
+  bool IEquals(const StringRef& a, const StringRef& b)
+  {
+    if (a.size()!=b.size()) {
       return false;
     }
+    for (size_t i=0; i<a.size(); ++i) {
+      if (toupper(a[i])!=b[i]) {
+        return false;
+      }
+    }
+    return true;
   }
-  return true;
-}
 
-mol::ResNum to_res_num(int num, char ins_code)
-{
-  return mol::ResNum(num, ins_code==' ' ? '\0' : ins_code);
-}
+  mol::ResNum to_res_num(int num, char ins_code)
+  {
+    return mol::ResNum(num, ins_code==' ' ? '\0' : ins_code);
+  }
 
 }
 
@@ -775,8 +775,25 @@ void PDBReader::ParseAndAddAtom(const StringRef& line, int line_num,
       curr_residue_=curr_chain_.FindResidue(res_num);
     }
     if (!curr_residue_.IsValid()) {
-      LOG_DEBUG("new residue " << res_name << " " << res_num);
-      curr_residue_=editor.AppendResidue(curr_chain_, res_name.str(), res_num);
+      if(curr_chain_.GetResidueCount()>0 && profile_.join_spread_atom_records) {
+        int loc=curr_chain_.GetResidueCount()-1;
+        for(;loc>=0;--loc) {
+          if(curr_chain_.GetResidueByIndex(loc).GetNumber()<res_num) break;
+        }
+        if(loc<0) {
+          curr_residue_=editor.InsertResidueBefore(curr_chain_,0,res_num,res_name.str());
+        } else {
+          curr_residue_=editor.InsertResidueAfter(curr_chain_,loc,res_num,res_name.str());
+        }
+        if(!curr_residue_) {
+          // this should not happen...
+          curr_residue_=editor.AppendResidue(curr_chain_, res_name.str(), res_num);
+        }
+        LOG_DEBUG("inserted new residue " << res_name << " " << res_num << " after " << loc);
+      } else {
+        curr_residue_=editor.AppendResidue(curr_chain_, res_name.str(), res_num);
+        LOG_DEBUG("appended new residue " << res_name << " " << res_num);
+      }
       warned_name_mismatch_=false;
       ++residue_count_; 
     }
diff --git a/modules/io/src/mol/pdb_writer.cc b/modules/io/src/mol/pdb_writer.cc
index d06a5228c5890f593c40c86ac9ceb4617f6ee379..3df6a4917db7901bbc4cb246d8346cd3f7c25f19 100644
--- a/modules/io/src/mol/pdb_writer.cc
+++ b/modules/io/src/mol/pdb_writer.cc
@@ -28,6 +28,8 @@
 #include <boost/filesystem/convenience.hpp>
 #include <boost/algorithm/string.hpp>
 
+#include <ost/base.hh>
+#include <ost/boost_filesystem_helper.hh>
 #include <ost/io/io_exception.hh>
 #include <ost/mol/atom_handle.hh>
 #include <ost/mol/residue_handle.hh>
@@ -154,8 +156,10 @@ void write_atom(std::ostream& ostr, FormattedLine& line,
   } else {
     for (std::vector<String>::const_iterator
          i=names.begin(), e=names.end(); i!=e; ++i) {
-      geom::Mat4 tf=atom.GetEntity().GetTransformationMatrix();
-      p=geom::Vec3(tf*geom::Vec4(atom.GetAltPos(*i)));
+      // GetAltPos always return orig pos, i.e. does not honor
+      // transformations like GetPos does - so apply it here
+      // seems like a FIXME...
+      p=atom.GetEntity().GetTransform().Apply(atom.GetAltPos(*i));
       line(30, 50).Clear();
 
       if (i->size()>1) {
@@ -347,11 +351,7 @@ PDBWriter::PDBWriter(std::ostream& stream, const IOProfile& profile):
 
 PDBWriter::PDBWriter(const boost::filesystem::path& filename, 
                      const IOProfile& profile):
-#if BOOST_FILESYSTEM_VERSION==3  || BOOST_VERSION<103400
-  outfile_(filename.string().c_str()), outstream_(outfile_), 
-#else
-  outfile_(filename.file_string().c_str()), outstream_(outfile_), 
-#endif  
+  outfile_(BFPathToString(filename).c_str()), outstream_(outfile_),
   mol_count_(0), line_(80), multi_model_(false), 
   charmm_style_(profile.dialect=="CHARMM"), is_pqr_(false),
   profile_(profile), filename_("")
diff --git a/modules/io/src/mol/sdf_writer.cc b/modules/io/src/mol/sdf_writer.cc
index 973224e48aff879b099aacd5fbd0f85002071b1b..45bc1867a1d6083601189c2c149ff75c9eaebf64 100644
--- a/modules/io/src/mol/sdf_writer.cc
+++ b/modules/io/src/mol/sdf_writer.cc
@@ -22,6 +22,7 @@
 
 #include "sdf_writer.hh"
 
+#include <ost/boost_filesystem_helper.hh>
 #include <ost/mol/atom_view.hh>
 #include <ost/mol/residue_view.hh>
 #include <ost/mol/chain_view.hh>
@@ -140,11 +141,7 @@ SDFWriter::SDFWriter(const String& filename)
 }
 
 SDFWriter::SDFWriter(const boost::filesystem::path& filename): 
-#if BOOST_FILESYSTEM_VERSION==3 || BOOST_VERSION<103400
-  outfile_(filename.string().c_str()), 
-#else
-  outfile_(filename.file_string().c_str()), 
-#endif
+  outfile_(BFPathToString(filename).c_str()),
   ostr_(outfile_), counter_(0), atom_indices_() {}
 
 void SDFWriter::Write(const mol::EntityView& ent) {
diff --git a/modules/io/tests/test_io_pdb.cc b/modules/io/tests/test_io_pdb.cc
index 561e91576b565d77dc6e9701bbc803f225167f56..09e0b44748e26d70659c5d43ceb7c32a92ed35be 100644
--- a/modules/io/tests/test_io_pdb.cc
+++ b/modules/io/tests/test_io_pdb.cc
@@ -852,7 +852,13 @@ BOOST_AUTO_TEST_CASE(res_name_mismatch_tolerant)
 
 BOOST_AUTO_TEST_CASE(seqres_import)
 {
-  SetPrefixPath(getenv("OST_ROOT"));
+  char * ost_root=getenv("OST_ROOT");
+  if(!ost_root){
+    std::cout << "WARNING: skipping SEQRES import unit test. " 
+              << "Rule-based builder is required" << std::endl;
+    return;
+  }
+  SetPrefixPath(ost_root);
   String lib_path=GetSharedDataPath()+"/compounds.chemlib";
   conop::CompoundLibPtr compound_lib=conop::CompoundLib::Load(lib_path);  
   if (!compound_lib) {
diff --git a/modules/io/tests/test_mmcif_reader.cc b/modules/io/tests/test_mmcif_reader.cc
index b66b9edde259be5d00a70e27bea0d8e4c982edce..9ae371699a9dba2da8da18ae5bca795951def935 100644
--- a/modules/io/tests/test_mmcif_reader.cc
+++ b/modules/io/tests/test_mmcif_reader.cc
@@ -138,7 +138,13 @@ BOOST_AUTO_TEST_CASE(mmcif_trystoreidx)
 
 BOOST_AUTO_TEST_CASE(mmcif_convert_seqres)
 {
-  SetPrefixPath(getenv("OST_ROOT"));
+  char * ost_root=getenv("OST_ROOT");
+  if(!ost_root){
+    std::cout << "WARNING: skipping SEQRES import unit test. " 
+              << "Rule-based builder is required" << std::endl;
+    return;
+  }
+  SetPrefixPath(ost_root);
   String lib_path=GetSharedDataPath()+"/compounds.chemlib";
   conop::CompoundLibPtr compound_lib=conop::CompoundLib::Load(lib_path);  
   if (!compound_lib) {
@@ -395,7 +401,13 @@ BOOST_AUTO_TEST_CASE(mmcif_entity_tests)
 
 BOOST_AUTO_TEST_CASE(mmcif_entity_poly_tests)
 {
-  SetPrefixPath(getenv("OST_ROOT"));
+  char * ost_root=getenv("OST_ROOT");
+  if(!ost_root){
+    std::cout << "WARNING: skipping SEQRES import unit test. " 
+              << "Rule-based builder is required" << std::endl;
+    return;
+  }
+  SetPrefixPath(ost_root);
   String lib_path=GetSharedDataPath()+"/compounds.chemlib";
   conop::CompoundLibPtr compound_lib=conop::CompoundLib::Load(lib_path);
   if (!compound_lib) {
diff --git a/modules/mol/alg/src/lddt.cc b/modules/mol/alg/src/lddt.cc
index 75eec8005263a6854319a158d10be07648cee03b..321ae803e14f6b166813cd36b75e987dc40ebf20 100644
--- a/modules/mol/alg/src/lddt.cc
+++ b/modules/mol/alg/src/lddt.cc
@@ -23,6 +23,8 @@
 #include <boost/program_options.hpp>
 #include <boost/filesystem/fstream.hpp>
 #include <boost/filesystem/convenience.hpp>
+#include <ost/base.hh>
+#include <ost/boost_filesystem_helper.hh>
 #include <ost/mol/alg/local_dist_diff_test.hh>
 #include <ost/mol/alg/filter_clashes.hh>
 #include <ost/io/mol/pdb_reader.hh>
@@ -286,11 +288,7 @@ int main (int argc, char **argv)
 
     boost::filesystem::path pathstring(files[i]);
 
-    #if BOOST_FILESYSTEM_VERSION==3 || BOOST_VERSION<103400
-    String filestring=pathstring.string();
-    #else
-    String filestring=pathstring.file_string();
-    #endif      
+    String filestring=BFPathToString(pathstring);
     std::cout << "File: " << files[i] << std::endl; 
     std::pair<int,int> cov = compute_coverage(v,glob_dist_list);
     std::cout << "Coverage: " << (float(cov.first)/float(cov.second)) << " (" << cov.first << " out of " << cov.second << " residues)" << std::endl;
diff --git a/modules/mol/alg/src/local_dist_diff_test.cc b/modules/mol/alg/src/local_dist_diff_test.cc
index 74c6278e2075882cf2a35d32b97d75b742ebb678..8f936411652c58d407fe70706f17c09e6d087a05 100644
--- a/modules/mol/alg/src/local_dist_diff_test.cc
+++ b/modules/mol/alg/src/local_dist_diff_test.cc
@@ -390,6 +390,9 @@ bool IsStandardResidue(String rn)
 GlobalRDMap CreateDistanceList(const EntityView& ref,Real max_dist)
 {
  GlobalRDMap dist_list; 
+ if (!ref.GetChainCount()) {
+   return dist_list;
+ }
  ResidueViewList ref_residues=ref.GetChainList()[0].GetResidueList(); 
  for (ResidueViewList::iterator i=ref_residues.begin(), e=ref_residues.end(); i!=e; ++i) {
    if (IsStandardResidue(i->GetName())) {
diff --git a/modules/mol/base/pymod/__init__.py b/modules/mol/base/pymod/__init__.py
index c51905578ce1f422598c5769f2717f69c4039e0f..512e4daf082ef7e17f8c019dc92021ff799b6ccc 100644
--- a/modules/mol/base/pymod/__init__.py
+++ b/modules/mol/base/pymod/__init__.py
@@ -20,17 +20,17 @@ from _ost_mol import *
 import ost.geom as _geom
 from ost.mol import alg
 
-__transform_warning_flag=True
 
 def Transform(tf=None):
   from ost import LogWarning
-  if __transform_warning_flag:
+  if Transform.mol_transform_warning_flag:
     LogWarning("mol.Transform is deprecated, please use geom.Transform instead")
-    __transform_warning_flag=False
+    Transform.mol_transform_warning_flag=False
   if tf:
     return _geom.Transform(tf)
   else:
     return _geom.Transform()
+Transform.mol_transform_warning_flag=True
 
 def MergeCoordGroups(*coord_groups):
   """
diff --git a/modules/mol/base/pymod/export_editors.cc b/modules/mol/base/pymod/export_editors.cc
index e53a02d35ffc39d35e826c9f34938dfd2821c4a1..aae903f7d276721545a60af51cd1ed0dff227263 100644
--- a/modules/mol/base/pymod/export_editors.cc
+++ b/modules/mol/base/pymod/export_editors.cc
@@ -42,11 +42,33 @@ BondHandle (EditorBase::*connect_b)(const AtomHandle&, const AtomHandle&,
 BondHandle (EditorBase::*connect_d)(const AtomHandle&, const AtomHandle&, 
                                     Real, Real, Real,
                                     unsigned char)=&EditorBase::Connect;
+
+ChainHandle (EditorBase::*insert_chain_a)(const String& chain_name)=&EditorBase::InsertChain;
+ChainHandle (EditorBase::*insert_chain_b)(const String& chain_name,
+                                          ChainHandle chain, bool deep)=&EditorBase::InsertChain;
                                     
 ResidueHandle (EditorBase::*append_a)(ChainHandle ch, 
                                       const ResidueKey&)=&EditorBase::AppendResidue;
 ResidueHandle (EditorBase::*append_b)(ChainHandle ch, const ResidueKey&, 
                                       const ResNum&)=&EditorBase::AppendResidue;
+ResidueHandle (EditorBase::*append_c)(ChainHandle ch, ResidueHandle residue,
+                                      bool deep)=&EditorBase::AppendResidue;
+
+AtomHandle (EditorBase::*insert_atom_a)(ResidueHandle residue, const String& name,
+                                        const geom::Vec3& pos, const String& ele,
+                                        Real occupancy, Real b_factor,
+                                        bool is_hetatm)=&EditorBase::InsertAtom;
+AtomHandle (EditorBase::*insert_atom_b)(ResidueHandle residue, AtomHandle atom)=&EditorBase::InsertAtom;
+
+
+AtomHandle (EditorBase::*insert_alt_atom_a)(ResidueHandle residue, const String& name,
+                                            const String& alt_group, const geom::Vec3& pos,
+                                            const String& ele, Real occ,
+                                            Real b_factor)=&EditorBase::InsertAltAtom;
+AtomHandle (EditorBase::*insert_alt_atom_b)(ResidueHandle residue, AtomHandle atom,
+                                            const String& alt_group)=&EditorBase::InsertAltAtom;
+
+
 
 void (ICSEditor::*set_torsion_a)(TorsionHandle, Real, bool)=&ICSEditor::SetTorsionAngle;
 void (ICSEditor::*set_torsion_b)(const AtomHandle&, const AtomHandle&,
@@ -194,19 +216,25 @@ void export_Editors()
   import_array();
 #endif
 
+
   class_<EditorBase>("EditorBase", no_init)
-    .def("InsertChain", &EditorBase::InsertChain)
-    .def("InsertAtom", &EditorBase::InsertAtom,
+    .def("InsertChain", insert_chain_a)
+    .def("InsertChain", insert_chain_b,(arg("chain_name"),arg("chain"), arg("deep")=false))
+    .def("InsertAtom", insert_atom_a,
          (arg("residue"), arg("name"), arg("pos"), arg("element")="", 
           arg("occupancy")=1.0, arg("b_factor")=0.0, arg("is_hetatm")=false))
-    .def("InsertAltAtom", &EditorBase::InsertAltAtom)
+    .def("InsertAtom", insert_atom_b)
+    .def("InsertAltAtom", insert_alt_atom_a)
+    .def("InsertAltAtom", insert_alt_atom_b)
     .def("DeleteResidue", &EditorBase::DeleteResidue)
     .def("DeleteChain", &EditorBase::DeleteChain)
     .def("DeleteAtom", &EditorBase::DeleteAtom)
     .def("InsertResidueBefore", &EditorBase::InsertResidueBefore)
-    .def("InsertResidueAfter", &EditorBase::InsertResidueAfter)    
+    .def("InsertResidueAfter", &EditorBase::InsertResidueAfter)
     .def("AppendResidue", append_a)
-    .def("AppendResidue", append_b)    
+    .def("AppendResidue", append_b)
+    .def("AppendResidue", append_c, (arg("chain"), arg("residue"),
+                                     arg("deep")=false))
     .def("Connect", connect_a)
     .def("Connect", connect_b)    
     .def("Connect", connect_c)
@@ -223,12 +251,19 @@ void export_Editors()
     .def("RenumberAllResidues",&EditorBase::RenumberAllResidues)
   ;
   
+  void (XCSEditor::*apply_transform1)(const geom::Mat4&) = &XCSEditor::ApplyTransform;
+  void (XCSEditor::*apply_transform2)(const geom::Transform&) = &XCSEditor::ApplyTransform;
+  void (XCSEditor::*set_transform1)(const geom::Mat4&) = &XCSEditor::SetTransform;
+  void (XCSEditor::*set_transform2)(const geom::Transform&) = &XCSEditor::SetTransform;
+
   class_<XCSEditor, bases<EditorBase> >("XCSEditor", no_init)
     .def("SetAtomPos", set_t_pos)
     .def("SetAtomTransformedPos", set_t_pos)
     .def("SetAtomOriginalPos", set_o_pos)
-    .def("ApplyTransform", &XCSEditor::ApplyTransform)
-    .def("SetTransform", &XCSEditor::SetTransform)
+    .def("ApplyTransform", apply_transform1)
+    .def("ApplyTransform", apply_transform2)
+    .def("SetTransform", set_transform1)
+    .def("SetTransform", set_transform2)
     .def("UpdateICS", &XCSEditor::UpdateICS)
     .def("__exit__", &XCSEditor::UpdateICS)    
   ;
diff --git a/modules/mol/base/pymod/export_entity.cc b/modules/mol/base/pymod/export_entity.cc
index adf2c83b7621420f1000aafa96439f90d34a203f..bb55d9bd68234616da9d4bf69d646adccf559d71 100644
--- a/modules/mol/base/pymod/export_entity.cc
+++ b/modules/mol/base/pymod/export_entity.cc
@@ -100,9 +100,18 @@ PyObject* get_pos1(EntityHandle& entity)
   return get_pos2(entity,true);
 }
 
+#endif
 
+geom::Mat4 depr_get_transformation_matrix(const EntityHandle& eh)
+{
+  return eh.GetTransformationMatrix();
+}
+
+bool depr_is_transformation_identity(const EntityHandle& eh)
+{
+  return eh.IsTransformationIdentity();
+}
 
-#endif
 } // ns
 
 void export_Entity()
@@ -181,17 +190,17 @@ void export_Entity()
     .add_property("bonds", &EntityHandle::GetBondList)
     .def("GetBounds", &EntityHandle::GetBounds)
     .add_property("bounds", &EntityHandle::GetBounds)
-    .def("GetTransformationMatrix", &EntityHandle::GetTransformationMatrix,
-         return_value_policy<copy_const_reference>())
-    .add_property("transform", 
-                   make_function(&EntityHandle::GetTransformationMatrix, 
-                                 return_value_policy<copy_const_reference>()))    
-
+    .def("GetTransformationMatrix", depr_get_transformation_matrix)
+    .def("IsTransformationIdentity",depr_is_transformation_identity)
+    .def("GetTransform",&EntityHandle::GetTransform)
+    .def("SetTransform",&EntityHandle::SetTransform)
+    .add_property("transform",&EntityHandle::GetTransform,&EntityHandle::SetTransform)
+    .def("HasTransform",&EntityHandle::HasTransform)
+    .def("ClearTransform",&EntityHandle::ClearTransform)
     .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)
     .def("RequestICSEditor", &depr_request_ics_editor, arg("mode")=UNBUFFERED_EDIT)  
-    .def("IsTransformationIdentity",&EntityHandle::IsTransformationIdentity)
     .def(self==self)
     .def(self!=self)
 #if OST_NUMPY_SUPPORT_ENABLED
diff --git a/modules/mol/base/src/editor_base.cc b/modules/mol/base/src/editor_base.cc
index c358a020475c36fb90b44aa48464b21dabc64342..be1b3f6d18b4ca84ad603a9a29867de6b32065a6 100644
--- a/modules/mol/base/src/editor_base.cc
+++ b/modules/mol/base/src/editor_base.cc
@@ -40,6 +40,13 @@ ChainHandle EditorBase::InsertChain(const String& chain_name)
   return ent_.Impl()->InsertChain(chain_name);
 }
 
+ChainHandle EditorBase::InsertChain(const String& chain_name, ChainHandle chain, bool deep)
+{
+  impl::ChainImplPtr inserted_chain=ent_.Impl()->InsertChain(chain.Impl(), deep);
+  inserted_chain->SetName(chain_name);
+  return inserted_chain;
+}
+
 ResidueHandle EditorBase::AppendResidue(ChainHandle chain, const ResidueKey& k)
 {
   CheckHandleValidity(chain);  
@@ -54,6 +61,12 @@ ResidueHandle EditorBase::AppendResidue(ChainHandle chain, const ResidueKey& k,
   return ResidueHandle(chain.Impl()->AppendResidue(k, num));
 }
 
+ResidueHandle EditorBase::AppendResidue(ChainHandle chain, ResidueHandle residue, bool deep)
+{
+  CheckHandleValidity(chain);
+  return ResidueHandle(chain.Impl()->AppendResidue(residue.Impl(), deep));
+}
+
 ResidueHandle EditorBase::InsertResidueBefore(ChainHandle chain, int index, 
                                               const ResNum& num,
                                               const ResidueKey& k)
@@ -116,6 +129,14 @@ AtomHandle EditorBase::InsertAtom(ResidueHandle res, const String& name,
   return atom;
 }
 
+AtomHandle EditorBase::InsertAtom(ResidueHandle res, AtomHandle atom)
+{
+  CheckHandleValidity(res);
+  ent_.Impl()->MarkTraceDirty();
+  AtomHandle a(res.Impl()->InsertAtom(atom.Impl()));
+  return a;
+}
+
 AtomHandle EditorBase::InsertAltAtom(ResidueHandle res, const String& name,
                                      const String& alt_group,
                                      const geom::Vec3& pos,
@@ -130,6 +151,18 @@ AtomHandle EditorBase::InsertAltAtom(ResidueHandle res, const String& name,
   return atom;
 }
 
+AtomHandle EditorBase::InsertAltAtom(ResidueHandle res, AtomHandle atom,
+                                     const String& alt_group)
+{
+  CheckHandleValidity(res);
+  ent_.Impl()->MarkTraceDirty();
+  AtomHandle a(res.Impl()->InsertAltAtom(atom.GetName(), alt_group,
+                                         atom.GetPos(), atom.GetElement(),
+                                         atom.GetOccupancy(), atom.GetBFactor()));
+  this->UpdateTrace();
+  return a;
+}
+
 void EditorBase::AddAltAtomPos(const String& group,
                                const AtomHandle& atom,
                                const geom::Vec3& position, Real occ,
diff --git a/modules/mol/base/src/editor_base.hh b/modules/mol/base/src/editor_base.hh
index 576b3cdb7867bafb0191c642f8b891bc4af4d86b..d1674a68a9d2cde585b04e07c8ac2c5e6d58b1f8 100644
--- a/modules/mol/base/src/editor_base.hh
+++ b/modules/mol/base/src/editor_base.hh
@@ -57,6 +57,25 @@ public:
   /// \return  The newly created chain handle
   ChainHandle InsertChain(const String& chain_name);
 
+  /// \brief create new chain
+  ///
+  /// create new chain with properties of a provided chain handle and attach it to entity.
+  ///
+  /// \param chain_name
+  ///          The chain name. Can be an arbitrary String. However, if you
+  ///          intend to use the PDB export funtionality, the \c chain_name
+  ///          should be a single letter, preferably in the range A-Z.
+  /// \param chain
+  ///          The newly created chain will take over all generic
+  ///          attached to this handle.
+  /// \param deep
+  ///          If set to true, all residues and atoms of chain will be
+  ///          completely copied into the created chain. No bonds and angles
+  ///          are added.
+  ///
+  /// \return  The newly created chain handle
+  ChainHandle InsertChain(const String& chain_name, ChainHandle chain, bool deep=false);
+
   /// \name Inserting, removing and modifying order of residues
   ///@{
   /// \brief Append residue to the end of the chain
@@ -76,6 +95,24 @@ public:
   
   ResidueHandle AppendResidue(ChainHandle chain, const ResidueKey& k, 
                               const ResNum& num); 
+
+  /// \brief Append residue to the ent of the chain
+  ///
+  /// Append residue with all properties of provided residue into chain.
+  ///
+  /// \param residue
+  ///          All properties of this residue will be copied into the newly created
+  ///          residue. The newly created residue will not contain any atoms, except
+  ///          you set \var deep to true.
+  ///
+  /// \param deep
+  ///          if set to true, all atoms from the source residue will be copied into
+  ///          the newly created residue. No bonds and angles are added.
+  ///
+  /// \return  The newly created residue handle
+
+  ResidueHandle AppendResidue(ChainHandle chain, ResidueHandle residue, bool deep=false);
+
   /// \brief  Insert residue into chain
   /// 
   /// Insert residue with residue number \var num and key \var k into the
@@ -94,6 +131,7 @@ public:
   ResidueHandle InsertResidueBefore(ChainHandle chain, int index, 
                                     const ResNum& num,
                                     const ResidueKey& k);
+
   /// \brief insert residue into chain
   /// 
   /// This method is identical to InsertResidueBefore() but inserts the
@@ -120,12 +158,33 @@ public:
                         Real occupancy=1.0, Real b_factor=0.0, 
                         bool is_hetatm=false);
 
+  /// \brief Insert new atom
+  ///
+  /// Inserts new atom with all properties from the provided atom handle.
+  ///
+  /// \param residue is the parent residue
+  /// \param atom from which all informations will be copied over to the
+  ///        newly created atom
+  ///
+  /// \return the newly created AtomHandle
+
+  AtomHandle InsertAtom(ResidueHandle residue, AtomHandle atom);
+
   /// \brief Insert new atom with alternative position indicator
   /// \sa EditorBase::AddAltAtomPos(), ResidueHandle
   AtomHandle InsertAltAtom(ResidueHandle residue, const String& name, 
                            const String& alt_group, const geom::Vec3& pos,
                            const String& ele="", Real occ=1.0,
                            Real b_factor=0.0);
+
+  /// \brief Insert new atom with alternative position indicator
+  ///
+  /// All informations will be copied over from atom, except bonds
+
+  AtomHandle InsertAltAtom(ResidueHandle residue, AtomHandle atom,
+                           const String& alt_group);
+
+
   /// \brief  Add alternative atom position
   /// \param group is the name of the alternative atom position group. If no 
   ///     group of that name exists, it will be created.
diff --git a/modules/mol/base/src/entity_handle.cc b/modules/mol/base/src/entity_handle.cc
index 0abad5ede1b3241f05300b5768cf0b7c332f4c12..e34e11d2e233ab4a60da62e20c3e085c4ece1f58 100644
--- a/modules/mol/base/src/entity_handle.cc
+++ b/modules/mol/base/src/entity_handle.cc
@@ -17,6 +17,8 @@
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 //------------------------------------------------------------------------------
 
+#include <ost/log.hh>
+
 #include "impl/entity_impl.hh"
 #include "bond_handle.hh"
 #include "torsion_handle.hh"
@@ -235,24 +237,62 @@ Real EntityHandle::GetAngle(const AtomView& a1, const AtomView& a2,
   return GetAngle(a1.GetHandle(), a2.GetHandle(), a3.GetHandle());
 }
 
-const geom::Mat4& EntityHandle::GetTransformationMatrix() const
-
+geom::Mat4 EntityHandle::GetTransformationMatrix() const
 {
+  static bool warn=true;
+  if(warn) {
+    LOG_WARNING("Entity::GetTransformationMatrix is deprecated, use GetTransform instead");
+    warn=false;
+  }
   this->CheckValidity();
-  return Impl()->GetTransfMatrix();
+  return Impl()->GetTransform().GetMatrix();
 }
 
 
-const geom::Mat4& EntityHandle::GetInvTransformationMatrix() const
+geom::Mat4 EntityHandle::GetInvTransformationMatrix() const
 {
+  static bool warn=true;
+  if(warn) {
+    LOG_WARNING("Entity::GetInvTransformationMatrix is deprecated, use GetTransform instead");
+    warn=false;
+  }
   this->CheckValidity();
-  return Impl()->GetInvTransfMatrix();
+  return Impl()->GetTransform().GetInvertedMatrix();
 }
 
 bool EntityHandle::IsTransformationIdentity() const
+{
+  static bool warn=true;
+  if(warn) {
+    LOG_WARNING("Entity::IsTransformationIdentity is deprecated, use HasTransform instead");
+    warn=false;
+  }
+  this->CheckValidity();
+  return !Impl()->HasTransform();
+}
+
+geom::Transform EntityHandle::GetTransform() const
+{
+  this->CheckValidity();
+  return Impl()->GetTransform();  
+}
+
+void EntityHandle::SetTransform(const geom::Transform& tf)
+{
+  this->CheckValidity();
+  Impl()->SetTransform(tf);  
+}
+
+bool EntityHandle::HasTransform() const
+{
+  this->CheckValidity();
+  return Impl()->HasTransform();  
+}
+
+void EntityHandle::ClearTransform()
 {
   this->CheckValidity();
-  return Impl()->IsTransfIdentity();
+  Impl()->ClearTransform();  
 }
 
 ResidueHandle EntityHandle::FindResidue(const String& chain_name,
diff --git a/modules/mol/base/src/entity_handle.hh b/modules/mol/base/src/entity_handle.hh
index 2783b404b75b11a1e31127017d8461b740752cf5..fe2a439135306d6f2a7c080ed91f1e15604faea0 100644
--- a/modules/mol/base/src/entity_handle.hh
+++ b/modules/mol/base/src/entity_handle.hh
@@ -264,13 +264,22 @@ public:
   Real GetAngle(const AtomView& a1, const AtomView& a2,
                 const AtomView& a3) const;
 
-  const geom::Mat4& GetTransformationMatrix() const;
-
-
-  const geom::Mat4& GetInvTransformationMatrix() const;
-
+  /// \brief DEPRECATED
+  geom::Mat4 GetTransformationMatrix() const;
+  /// \brief DEPRECATED
+  geom::Mat4 GetInvTransformationMatrix() const;
+  /// \brief DEPRECATED
   bool IsTransformationIdentity() const;
 
+  /// \brief retrieve transformation of this entity
+  geom::Transform GetTransform() const;
+  /// \brief set transformation that will affect this entity
+  void SetTransform(const geom::Transform& t);
+  /// \brief checks whether a transform has been set
+  bool HasTransform() const;
+  /// \brief remove transform
+  void ClearTransform();
+
   /// \brief get complete list of residues
   /// \sa #ResiduesBegin, #ResiduesEnd
   ResidueHandleList GetResidueList() const;
diff --git a/modules/mol/base/src/impl/atom_impl.cc b/modules/mol/base/src/impl/atom_impl.cc
index 4f7f059b818eda692de6447a9b3d2b5d547037e7..3a2b4d013f2c14e82f345e55241aa911d0809ffe 100644
--- a/modules/mol/base/src/impl/atom_impl.cc
+++ b/modules/mol/base/src/impl/atom_impl.cc
@@ -56,10 +56,8 @@ AtomImpl::AtomImpl(const EntityImplPtr& e,
   state_(0),
   index_(index)
 {
-  EntityHandle ent = this->GetEntity();
-  geom::Mat4 transf_matrix = ent.GetTransformationMatrix();
-  geom::Vec3 transf_pos = geom::Vec3(transf_matrix*geom::Vec4(p));
-  tf_pos_ = transf_pos;
+  EntityImplPtr eip = GetEntity();
+  tf_pos_ = eip->HasTransform() ? eip->GetTransform().Apply(p) : p;
   prop_=AtomProp::GetDefaultProps(element_);
 }
 
diff --git a/modules/mol/base/src/impl/chain_impl.cc b/modules/mol/base/src/impl/chain_impl.cc
index 009f436a5406a42caeda27605574587d48decbe3..8b3cbe271eef0e860d78ea5039ac7f00a35e191e 100644
--- a/modules/mol/base/src/impl/chain_impl.cc
+++ b/modules/mol/base/src/impl/chain_impl.cc
@@ -61,7 +61,7 @@ bool ChainImpl::InSequence() const {
   return in_sequence_;
 }
 
-ResidueImplPtr ChainImpl::AppendResidue(const ResidueImplPtr& res)
+ResidueImplPtr ChainImpl::AppendResidue(const ResidueImplPtr& res, bool deep)
 {
   ResidueImplPtr dst_res=this->AppendResidue(res->GetKey(), res->GetNumber());
   dst_res->Assign(*res.get());                                                
@@ -70,6 +70,16 @@ ResidueImplPtr ChainImpl::AppendResidue(const ResidueImplPtr& res)
   dst_res->SetChemClass(res->GetChemClass());  
   dst_res->SetProtein(res->IsProtein());
   dst_res->SetIsLigand(res->IsLigand());
+  if(deep)
+  {
+    AtomImplList::iterator it=res->GetAtomList().begin(),
+                             it_end=res->GetAtomList().end();
+      for(;it!=it_end;++it)
+      {
+        AtomHandle atom=*it;
+        dst_res->InsertAtom(atom.Impl());
+      }
+  }
   return dst_res;
 }
 
@@ -520,5 +530,12 @@ void ChainImpl::SetInSequence(const int index)
     this->UpdateShifts();
   }
 }
+
+void ChainImpl::UpdateTransformedPos()
+{
+  for (ResidueImplList::iterator rit=residue_list_.begin(); rit!=residue_list_.end(); ++rit) {
+    (*rit)->UpdateTransformedPos();
+  }
+}
   
 }}} // ns
diff --git a/modules/mol/base/src/impl/chain_impl.hh b/modules/mol/base/src/impl/chain_impl.hh
index bcb3436e2bc463dadcfe1ca6af4e1bbac48af24b..a2c607ec4e2df3cca3783a8a14532e795536593e 100644
--- a/modules/mol/base/src/impl/chain_impl.hh
+++ b/modules/mol/base/src/impl/chain_impl.hh
@@ -105,7 +105,9 @@ public:
 
   /// \brief append new residue with exactly the same parameters as res, but 
   ///     no atoms and bonds                               
-  ResidueImplPtr AppendResidue(const ResidueImplPtr& res);
+  // force deep to be set explicitely, because it is better than implicit
+  // (and since we are on the impl level interface consistency isn't that critical)
+  ResidueImplPtr AppendResidue(const ResidueImplPtr& res, bool deep);
   
   ResidueImplPtr InsertResidueBefore(int index, const ResNum& n, 
                                      const ResidueKey& k);
@@ -119,6 +121,7 @@ public:
 
   /// \brief  Append residue at end of chain.
   ResidueImplPtr AppendResidue(const ResidueKey& k, const ResNum& n);
+
   
   // next residue, not necessarily in sequence
   ResidueImplPtr GetPrev(const ResidueImplPtr& r) const;
@@ -181,6 +184,8 @@ public:
   ///       property and updates it accordingly      
   void SetInSequence(int index);
 
+  void UpdateTransformedPos();
+
 private:
   int GetIndexForResNumInSequence(const ResNum& number) const;
   void UpdateShifts();
diff --git a/modules/mol/base/src/impl/entity_impl.cc b/modules/mol/base/src/impl/entity_impl.cc
index 3019a0806e0dc3f8838157e09fcd69d93fb2888a..db9460a01cd68b16a91cdaa30f7e1dba3963591d 100644
--- a/modules/mol/base/src/impl/entity_impl.cc
+++ b/modules/mol/base/src/impl/entity_impl.cc
@@ -68,9 +68,8 @@ EntityImpl::EntityImpl():
   chain_list_(),
   connector_map_(),
   torsion_map_(),
-  transformation_matrix_(),
-  inverse_transformation_matrix_(),
-  identity_transf_(true),
+  transform_(),
+  has_transform_(false),
   atom_organizer_(5.0),
   fragment_list_(),
   observer_map_(),
@@ -127,10 +126,19 @@ EntityImplPtr EntityImpl::Copy()
   return ent_p;
 }
 
-ChainImplPtr EntityImpl::InsertChain(const ChainImplPtr& chain)
+ChainImplPtr EntityImpl::InsertChain(const ChainImplPtr& chain, bool deep)
 {
   ChainImplPtr dst_chain=this->InsertChain(chain->GetName());
   dst_chain->Assign(*chain.get());
+  if(deep)
+  {
+      ResidueImplList::iterator it=chain->GetResidueList().begin(),
+                                it_end=chain->GetResidueList().end();
+      for(;it!=it_end;++it){
+        ResidueImplPtr res=*it;
+        dst_chain->AppendResidue(res, true);
+      }
+  }
   return dst_chain;
 }
 
@@ -139,20 +147,7 @@ void EntityImpl::ReplicateHierarchy(EntityImplPtr dest)
   for (ChainImplList::const_iterator i=chain_list_.begin(), 
        e1=chain_list_.end(); i!=e1; ++i) {
     ChainImplPtr src_chain=*i;
-    ChainImplPtr dst_chain=dest->InsertChain(src_chain);
-    // copy generic properties
-    dst_chain->Assign(*src_chain.get());
-    for (ResidueImplList::iterator j=src_chain->GetResidueList().begin(),
-         e2=src_chain->GetResidueList().end(); j!=e2; ++j) {
-      ResidueImplPtr src_res=*j;
-      ResidueImplPtr dst_res=dst_chain->AppendResidue(src_res);
-      for (AtomImplList::iterator k=src_res->GetAtomList().begin(),
-           e3=src_res->GetAtomList().end(); k!=e3; ++k) {
-        AtomImplPtr src_atom=*k;
-        AtomImplPtr dst_atom=dst_res->InsertAtom(src_atom);
-        dst_atom->SetIndex(src_atom->GetIndex());
-      }
-    }
+    dest->InsertChain(src_chain,true);
   }
 }
 
@@ -244,21 +239,6 @@ int EntityImpl::GetChainCount() const
   return static_cast<int>(chain_list_.size());
 }
 
-const geom::Mat4& EntityImpl::GetTransfMatrix() const
-{
-  return transformation_matrix_;
-}
-
-const geom::Mat4& EntityImpl::GetInvTransfMatrix() const
-{
-  return inverse_transformation_matrix_;
-}
-
-bool EntityImpl::IsTransfIdentity() const
-{
-  return identity_transf_;
-}
-
 EntityImpl::~EntityImpl()
 {
   // notify all observers of pending destruct
@@ -322,23 +302,18 @@ Real EntityImpl::GetMass() const {
 
 AtomImplPtr EntityImpl::CreateAtom(const ResidueImplPtr& rp,
                                    const String& name,
-                                   const geom::Vec3& pos,
+                                   const geom::Vec3& pos2,
                                    const String& ele)
 {
 #if MAKE_SHARED_AVAILABLE
   AtomImplPtr ap=boost::make_shared<AtomImpl>(shared_from_this(), rp, name, 
-                                              pos, ele,next_index_++);
+                                              pos2, ele,next_index_++);
 #else
-  AtomImplPtr ap(new AtomImpl(shared_from_this(), rp, name, pos, ele, next_index_++));
+  AtomImplPtr ap(new AtomImpl(shared_from_this(), rp, name, pos2, ele, next_index_++));
 #endif
-  if (!identity_transf_) {
-    geom::Vec3 transformed_pos = geom::Vec3(transformation_matrix_*geom::Vec4(pos));
-    ap->TransformedPos()=transformed_pos;
-    atom_organizer_.Add(ap,transformed_pos);
-  } else {
-    ap->TransformedPos()=pos;
-    atom_organizer_.Add(ap,pos);
-  }
+  geom::Vec3 pos = has_transform_ ? transform_.Apply(pos2) : pos2;
+  ap->TransformedPos()=pos;
+  atom_organizer_.Add(ap,pos);
   atom_map_.insert(AtomImplMap::value_type(ap.get(),ap));
   return ap;
 }
@@ -760,21 +735,25 @@ void EntityImpl::Apply(EntityVisitor& v)
   v.OnExit();
 }
 
-void EntityImpl::ApplyTransform(const geom::Mat4 transfmat)
+void EntityImpl::ApplyTransform(const geom::Transform& tf)
 {
-  geom::Mat4 updated_transformation_matrix=transfmat*transformation_matrix_;
-  this->SetTransform(updated_transformation_matrix);
+  SetTransform(transform_.Apply(tf));
 }
 
-void EntityImpl::SetTransform(const geom::Mat4 transfmat)
+void EntityImpl::SetTransform(const geom::Transform& tf)
 {
-  transformation_matrix_=transfmat;
-  inverse_transformation_matrix_=Invert(transformation_matrix_);
-  identity_transf_ = (transformation_matrix_==geom::Mat4());
+  transform_=tf;
+  has_transform_=true;
   this->UpdateTransformedPos();
   this->MarkOrganizerDirty();
 }
 
+void EntityImpl::ClearTransform()
+{
+  has_transform_=false;
+  SetTransform(geom::Transform());
+}
+
 void EntityImpl::AttachObserver(const EntityObserverPtr& o)
 {
   observer_map_.insert(EntityObserverMap::value_type(o.get(),o));
@@ -798,7 +777,8 @@ void EntityImpl::Swap(EntityImpl& impl)
   chain_list_.swap(impl.chain_list_);
   connector_map_.swap(impl.connector_map_);
   torsion_map_.swap(impl.torsion_map_);
-  std::swap(transformation_matrix_,impl.transformation_matrix_);
+  std::swap(transform_,impl.transform_);
+  std::swap(has_transform_,impl.has_transform_);
   atom_organizer_.Swap(impl.atom_organizer_);
   fragment_list_.swap(impl.fragment_list_);
   observer_map_.swap(impl.observer_map_);
@@ -1194,7 +1174,10 @@ void EntityImpl::RenameChain(ChainImplPtr chain, const String& new_name)
 
 void EntityImpl::UpdateTransformedPos(){
   for(AtomImplMap::iterator it = atom_map_.begin();it!=atom_map_.end();++it) {
-    it->second->TransformedPos()=geom::Vec3(transformation_matrix_*geom::Vec4(it->second->OriginalPos()));
+    it->second->TransformedPos()=has_transform_ ? transform_.Apply(it->second->OriginalPos()) : it->second->OriginalPos();
+  }
+  for(ChainImplList::iterator cit=chain_list_.begin();cit!=chain_list_.end();++cit) {
+    (*cit)->UpdateTransformedPos();
   }
 }
 
diff --git a/modules/mol/base/src/impl/entity_impl.hh b/modules/mol/base/src/impl/entity_impl.hh
index ccbf85b449cdf035493096c73157a485dc9baea8..c95bef408db5c911b40b71b6ae460baa5890b827 100644
--- a/modules/mol/base/src/impl/entity_impl.hh
+++ b/modules/mol/base/src/impl/entity_impl.hh
@@ -109,7 +109,9 @@ public:
   /// \brief insert a new chain based on parameters of the given chain
   /// 
   /// The chain will have no residues and atoms
-  ChainImplPtr InsertChain(const ChainImplPtr& chain);
+  // force deep to be set explicitely, because it is better than implicit
+  // (and since we are on the impl level interface consistency isn't that critical)
+  ChainImplPtr InsertChain(const ChainImplPtr& chain, bool deep);
   ConnectorImplP Connect(const AtomImplPtr& first, const AtomImplPtr& second,
                          Real len, Real theta, Real phi,
                          unsigned char bond_order);
@@ -143,9 +145,12 @@ public:
   void UpdateFromXCS();
 
   void Apply(EntityVisitor& v);
-  void ApplyTransform(const geom::Mat4 transfmat);
+  void ApplyTransform(const geom::Transform& t);
 
-  void SetTransform(const geom::Mat4 transfmat);
+  void SetTransform(const geom::Transform& t);
+  const geom::Transform& GetTransform() const {return transform_;}
+  bool HasTransform() const {return has_transform_;}
+  void ClearTransform();
 
   void AttachObserver(const EntityObserverPtr& o);
   void DetachObserver(const EntityObserverPtr& o);
@@ -198,14 +203,6 @@ public:
   //! Get number of chains
   int GetChainCount() const;
 
-  //! Get transformation matrix
-  const geom::Mat4& GetTransfMatrix() const;
-
-  //! Get inverse transformation matrix
-  const geom::Mat4& GetInvTransfMatrix() const;
-
-  bool IsTransfIdentity() const;
-
   const ChainImplList& GetChainList() const { return chain_list_; }
 
   ChainImplList& GetChainList() { return chain_list_; }
@@ -266,10 +263,8 @@ private:
   ConnectorImplMap connector_map_;
   TorsionImplMap torsion_map_;
 
-  geom::Mat4 transformation_matrix_;
-  geom::Mat4 inverse_transformation_matrix_;
-  bool identity_transf_;
-
+  geom::Transform transform_;
+  bool has_transform_;
 
   SpatialAtomOrganizer atom_organizer_;
   FragmentImplList fragment_list_;
diff --git a/modules/mol/base/src/impl/residue_impl.cc b/modules/mol/base/src/impl/residue_impl.cc
index 1e0fa1d461662e1895f6d8dd5bbeb7d8a58479f6..29fee9883e5a8381eac4c12d3d75a194f007de44 100644
--- a/modules/mol/base/src/impl/residue_impl.cc
+++ b/modules/mol/base/src/impl/residue_impl.cc
@@ -69,7 +69,8 @@ AtomImplPtr ResidueImpl::InsertAtom(const AtomImplPtr& atom)
   dst_atom->SetState(atom->GetState());
   dst_atom->SetBFactor(atom->GetBFactor());
   dst_atom->SetOccupancy(atom->GetOccupancy());
-  dst_atom->SetHetAtom(atom->IsHetAtom());  
+  dst_atom->SetHetAtom(atom->IsHetAtom());
+  dst_atom->SetIndex(atom->GetIndex());
 
   if (!atom->HasDefaultProps()) {
     dst_atom->SetRadius(atom->GetRadius());
@@ -118,9 +119,16 @@ geom::Vec3 ResidueImpl::GetAltAtomPos(const AtomImplPtr& atom,
     throw Error("No alt atom group '"+group+"'");
   }
   const AtomGroup& g=i->second;
+  EntityImplPtr eip=GetEntity();
   for (AtomGroupEntryList::const_iterator j=g.atoms.begin(), 
        e=g.atoms.end(); j!=e; ++j) {
     if (atom==j->atom.lock()) {
+      // the alternate entry positions are stored as original, and
+      // are returned as original as well ?! at least that is what
+      // the unit test seems to require
+      // also, the PDB writer currently expects this behavior, so
+      // if it is changed here, it must be changed there as well
+      //return eip->HasTransform() ? eip->GetTransform().Apply(j->pos) : j->pos;
       return j->pos;
     }
   }
@@ -626,14 +634,11 @@ bool ResidueImpl::SwitchAtomPos(const String& group) {
   AtomGroup& agr=i->second;
   AtomGroupEntryList::iterator j=agr.atoms.begin();
   for (; j!=agr.atoms.end(); ++j) {
-
     AtomGroupEntry& entry=*j;
     assert(!entry.atom.expired());
     entry.atom.lock()->OriginalPos()=entry.pos;
-    EntityHandle ent = entry.atom.lock()->GetEntity();
-    geom::Mat4 transf_matrix = ent.GetTransformationMatrix();
-    geom::Vec3 transf_pos = geom::Vec3(transf_matrix*geom::Vec4(entry.pos));
-    entry.atom.lock()->TransformedPos()=transf_pos;
+    EntityImplPtr eip = entry.atom.lock()->GetEntity();
+    entry.atom.lock()->TransformedPos() = eip->GetTransform().Apply(entry.pos);
     entry.atom.lock()->SetBFactor(j->b_factor);
     entry.atom.lock()->SetOccupancy(j->occ);
   }
@@ -671,4 +676,25 @@ String ResidueImpl::GetStringProperty(Prop::ID prop_id) const
   }
 }
 
+void ResidueImpl::UpdateTransformedPos()
+{
+  /*
+    the alt atom positions always store the original pos; hence the below code
+    is not necessary; however, it isn't clear (at least to me (AP)) if the
+    AtomImplPtr in the alt group is supposed to be modified here, or if this is
+    already taken care of in EntityImpl::UpdateTransformedPos()
+   */
+#if 0
+  geom::Transform tf = GetEntity()->GetTransform();
+  for(AtomEntryGroups::iterator git=alt_groups_.begin(); git!=alt_groups_.end();++git) {
+    for(AtomGroupEntryList::iterator lit=git->second.atoms.begin(); lit!=git->second.atoms.end();++lit) {
+      AtomImplPtr atom=lit->atom.lock().get();
+      geom::Vec3 tpos=tf.Apply(atom->OriginalPos());
+      atom->TransformedPos()=tpos;
+      lit->pos=atom->tpos;
+    }
+  }
+#endif
+}
+
 }}} // ns
diff --git a/modules/mol/base/src/impl/residue_impl.hh b/modules/mol/base/src/impl/residue_impl.hh
index 24f829c6922bdbfdcc0ee8645cbec80e4ff49f88..91b6843e78ab8de6ab7034302aea3708595487a0 100644
--- a/modules/mol/base/src/impl/residue_impl.hh
+++ b/modules/mol/base/src/impl/residue_impl.hh
@@ -223,6 +223,9 @@ public:
   
   bool IsLigand() const { return ligand_; }
   void SetIsLigand(bool flag) { ligand_=flag; }
+
+  void UpdateTransformedPos();
+
 private:
   void AddAltAtom(const String& group, const AtomImplPtr& atom,
                   const geom::Vec3& position, Real occ, Real b_factor);
diff --git a/modules/mol/base/src/view_op.cc b/modules/mol/base/src/view_op.cc
index 6e4227e741d0faa02d5b1a902b1d63be0050aee2..6b8aebad85b78a9600e354b774cd512e990ccf54 100644
--- a/modules/mol/base/src/view_op.cc
+++ b/modules/mol/base/src/view_op.cc
@@ -296,7 +296,7 @@ public:
   
   virtual bool VisitResidue(const ResidueHandle& res)
   {
-    res_=chain_->AppendResidue(res.Impl());
+    res_=chain_->AppendResidue(res.Impl(),false);
     return true;
   }
   
diff --git a/modules/mol/base/src/xcs_editor.cc b/modules/mol/base/src/xcs_editor.cc
index 0c2454b187c8d29902b8380e4caf3b7969db3fe5..5596e3962d1479921f2c5b8ae5108d0c92ee9b38 100644
--- a/modules/mol/base/src/xcs_editor.cc
+++ b/modules/mol/base/src/xcs_editor.cc
@@ -74,14 +74,11 @@ void XCSEditor::SetAtomTransformedPos(const AtomHandle& atom,
                                       const geom::Vec3& position)
 {
   CheckHandleValidity(atom);
+  impl::EntityImplPtr eip=ent_.Impl();
   atom.Impl()->TransformedPos()=position;
-  if(ent_.Impl()->IsTransfIdentity()) {
-    atom.Impl()->OriginalPos()=position;
-  } else {
-    atom.Impl()->OriginalPos() = geom::Vec3(ent_.Impl()->GetInvTransfMatrix()*geom::Vec4(position));
-  }
-  ent_.Impl()->MarkICSDirty();
-  ent_.Impl()->MarkOrganizerDirty();
+  atom.Impl()->OriginalPos() = eip->HasTransform() ? eip->GetTransform().ApplyInverse(position) : position;
+  eip->MarkICSDirty();
+  eip->MarkOrganizerDirty();
   this->Update();
 }
 
@@ -89,17 +86,14 @@ namespace {
   template<typename T>
   void set_transformed_pos(impl::EntityImpl* ent, const AtomHandleList& alist, T *positions)
   {
-    bool has_tf=ent->IsTransfIdentity();
+    bool has_tf=ent->HasTransform();
     for(AtomHandleList::const_iterator ait=alist.begin();ait!=alist.end();++ait) {
       if(ait->IsValid()) {
-        ait->Impl()->TransformedPos()[0]=static_cast<Real>(positions[0]);
-        ait->Impl()->TransformedPos()[1]=static_cast<Real>(positions[1]);
-        ait->Impl()->TransformedPos()[2]=static_cast<Real>(positions[2]);
-        if(has_tf) {
-          ait->Impl()->OriginalPos()=ait->Impl()->TransformedPos();
-        } else {
-          ait->Impl()->OriginalPos() = geom::Vec3(ent->GetInvTransfMatrix()*geom::Vec4(ait->Impl()->TransformedPos()));
-        }
+        geom::Vec3& tpos=ait->Impl()->TransformedPos();
+        tpos[0]=static_cast<Real>(positions[0]);
+        tpos[1]=static_cast<Real>(positions[1]);
+        tpos[2]=static_cast<Real>(positions[2]);
+        ait->Impl()->OriginalPos()=has_tf ? ent->GetTransform().ApplyInverse(tpos) : tpos;
       }
       positions+=3;
     }
@@ -124,14 +118,11 @@ void XCSEditor::SetAtomOriginalPos(const AtomHandle& atom,
                                    const geom::Vec3& position)
 {
   CheckHandleValidity(atom);
+  impl::EntityImplPtr eip=ent_.Impl();
   atom.Impl()->OriginalPos()=position;
-  if(ent_.Impl()->IsTransfIdentity()) {
-    atom.Impl()->TransformedPos()=position;
-  } else {
-    atom.Impl()->TransformedPos() = geom::Vec3(ent_.Impl()->GetTransfMatrix()*geom::Vec4(position));
-  }
-  ent_.Impl()->MarkICSDirty();
-  ent_.Impl()->MarkOrganizerDirty();
+  atom.Impl()->TransformedPos() = eip->HasTransform() ? eip->GetTransform().Apply(position) : position;
+  eip->MarkICSDirty();
+  eip->MarkOrganizerDirty();
   this->Update();
 }
 
@@ -139,17 +130,14 @@ namespace {
   template<typename T>
   void set_original_pos(impl::EntityImpl* ent, const AtomHandleList& alist, T *positions)
   {
-    bool has_tf=ent->IsTransfIdentity();
+    bool has_tf=ent->HasTransform();
     for(AtomHandleList::const_iterator ait=alist.begin();ait!=alist.end();++ait) {
       if(ait->IsValid()) {
-        ait->Impl()->OriginalPos()[0]=static_cast<Real>(positions[0]);
-        ait->Impl()->OriginalPos()[1]=static_cast<Real>(positions[1]);
-        ait->Impl()->OriginalPos()[2]=static_cast<Real>(positions[2]);
-        if(has_tf) {
-          ait->Impl()->TransformedPos()=ait->Impl()->OriginalPos();
-        } else {
-          ait->Impl()->TransformedPos() = geom::Vec3(ent->GetTransfMatrix()*geom::Vec4(ait->Impl()->OriginalPos()));
-        }
+        geom::Vec3& opos=ait->Impl()->OriginalPos();
+        opos[0]=static_cast<Real>(positions[0]);
+        opos[1]=static_cast<Real>(positions[1]);
+        opos[2]=static_cast<Real>(positions[2]);
+        ait->Impl()->TransformedPos()= has_tf ? ent->GetTransform().Apply(opos) : opos;
       }
       positions+=3;
     }
@@ -186,6 +174,13 @@ void XCSEditor::SetAtomPos(const AtomHandleList& alist, double *positions)
 }
 
 void XCSEditor::ApplyTransform(const geom::Mat4& transform)
+{
+  geom::Transform tf;
+  tf.SetMatrix(transform);
+  this->ApplyTransform(tf);
+}
+
+void XCSEditor::ApplyTransform(const geom::Transform& transform)
 {
   ent_.Impl()->ApplyTransform(transform);
   ent_.Impl()->UpdateTransformedPos();
@@ -194,8 +189,14 @@ void XCSEditor::ApplyTransform(const geom::Mat4& transform)
   this->Update();
 }
 
-
 void XCSEditor::SetTransform(const geom::Mat4& transform)
+{
+  geom::Transform tf;
+  tf.SetMatrix(transform);
+  this->SetTransform(tf);
+}
+
+void XCSEditor::SetTransform(const geom::Transform& transform)
 {
   ent_.Impl()->SetTransform(transform);
   ent_.Impl()->UpdateTransformedPos();
@@ -204,7 +205,6 @@ void XCSEditor::SetTransform(const geom::Mat4& transform)
   this->Update();
 }
 
-
 void XCSEditor::Update()
 {
   if (GetMode()==UNBUFFERED_EDIT) {
diff --git a/modules/mol/base/src/xcs_editor.hh b/modules/mol/base/src/xcs_editor.hh
index 73d96a652829932c469a6a0382093de7fd53b5f4..a7cc317b2e5273b62211b03a8d04559de97f0fff 100644
--- a/modules/mol/base/src/xcs_editor.hh
+++ b/modules/mol/base/src/xcs_editor.hh
@@ -98,10 +98,11 @@ public:
   /// This transformation is applied \em after the transformation
   /// already stored in the entity
   void ApplyTransform(const geom::Mat4& transform); 
+  void ApplyTransform(const geom::Transform& transform); 
 
   /// \brief apply a new transformation to all atoms
-
   void SetTransform(const geom::Mat4& transform);
+  void SetTransform(const geom::Transform& transform);
 
   /// \brief immediately update internal coordinate system
   void UpdateICS();  
diff --git a/modules/mol/base/tests/test_chain.cc b/modules/mol/base/tests/test_chain.cc
index ee4d933d0c095766079bb4278774d41d97a74ae3..39ffd35e205cd320cc926af7e4a440f838109b2c 100644
--- a/modules/mol/base/tests/test_chain.cc
+++ b/modules/mol/base/tests/test_chain.cc
@@ -87,16 +87,38 @@ BOOST_AUTO_TEST_CASE(test_comparison)
   BOOST_CHECK(cc==ch1);
 }
 
-
 BOOST_AUTO_TEST_CASE(throw_invalid_chain_handle)
 {
   EntityHandle ent=CreateEntity();
-  ChainHandle chain=ent.FindChain("A");
-  BOOST_CHECK_THROW(CheckHandleValidity(chain), InvalidHandle);
+  ChainHandle ch=ent.FindChain("A");
+  BOOST_CHECK_THROW(CheckHandleValidity(ch), InvalidHandle);
   XCSEditor edi=ent.EditXCS();
   edi.InsertChain("A");
-  chain=ent.FindChain("A");
-  BOOST_CHECK_NO_THROW(CheckHandleValidity(chain));
+  ch=ent.FindChain("A");
+  BOOST_CHECK_NO_THROW(CheckHandleValidity(ch));
+
+
+  EntityHandle eh1 = CreateEntity();
+  XCSEditor e1=eh1.EditXCS();
+  ChainHandle chain = e1.InsertChain("C");
+  ResidueHandle res1 = e1.AppendResidue(chain, "FOO", ResNum(13));
+  AtomHandle atom1 = e1.InsertAtom(res1, "X1",geom::Vec3());
+  AtomHandle atom2 = e1.InsertAtom(res1, "X2",geom::Vec3());
+  ResidueHandle res2 = e1.AppendResidue(chain, "FOO", ResNum(42));
+  e1.InsertAtom(res2, "X1",geom::Vec3());
+  e1.InsertAtom(res2, "X2",geom::Vec3());
+
+  EntityHandle eh2=CreateEntity();
+  XCSEditor e2=eh2.EditXCS();
+  ChainHandle inserted_chain1 = e2.InsertChain("Q",chain);
+  res1.SetIntProp("amazing",42);
+  ResidueHandle inserted_residue1 = e2.AppendResidue(inserted_chain1,res1);
+  BOOST_CHECK(inserted_residue1!=res1);
+  BOOST_CHECK(eh2.GetResidueCount()==1);
+  BOOST_CHECK(eh2.GetAtomCount()==0);
+  BOOST_CHECK(inserted_residue1.HasProp("amazing"));
+  ResidueHandle inserted_residue2 = e2.AppendResidue(inserted_chain1,res2,true);
+  BOOST_CHECK(eh2.GetAtomCount()==2);
 }
 
 BOOST_AUTO_TEST_CASE(throw_invalid_chain_view)
diff --git a/modules/mol/base/tests/test_entity.cc b/modules/mol/base/tests/test_entity.cc
index d8ecd8f3b9a9007e84549d6b4a20e302a1a5fe67..767b68bb3ba14f55eca9afde0a3158c5fcab06eb 100644
--- a/modules/mol/base/tests/test_entity.cc
+++ b/modules/mol/base/tests/test_entity.cc
@@ -136,8 +136,24 @@ BOOST_AUTO_TEST_CASE(entity_creator)
   BOOST_CHECK(eh.GetAtomCount()==2);
   
   BOOST_CHECK(eh.GetAtomCount()==chain.GetAtomCount());
-  BOOST_CHECK(eh.GetResidueCount()==chain.GetResidueCount());    
-  
+  BOOST_CHECK(eh.GetResidueCount()==chain.GetResidueCount());
+
+  chain.SetIntProp("amazing",42);
+  EntityHandle eh2 = CreateEntity();
+  XCSEditor e2 = eh2.EditXCS();
+  ChainHandle inserted_chain=e2.InsertChain("Q",chain);
+  BOOST_CHECK(eh2.GetChainCount()==1);
+  BOOST_CHECK(eh2.GetResidueCount()==0);
+  BOOST_CHECK(eh2.GetAtomCount()==0);
+  BOOST_CHECK(inserted_chain.HasProp("amazing"));
+  BOOST_CHECK(eh2.FindChain("Q").IsValid());
+
+  EntityHandle eh3 = CreateEntity();
+  XCSEditor e3 = eh3.EditXCS();
+  e3.InsertChain("Q",chain,true);
+  BOOST_CHECK(eh3.GetResidueCount()==1);
+  BOOST_CHECK(eh3.GetAtomCount()==2);
+
   EntityVisitor v;
   eh.Apply(v);
 }
@@ -179,14 +195,12 @@ BOOST_AUTO_TEST_CASE(transformation)
   BOOST_CHECK(within_list1[0]==atom1);
   BOOST_CHECK(within_list1[1]==atom2);
 
-  BOOST_CHECK(eh.IsTransformationIdentity()==true);
+  BOOST_CHECK(eh.HasTransform()==false);
 
   geom::Transform trans;
   trans.ApplyZAxisRotation(90.0);
-  geom::Mat4 mat = trans.GetMatrix();
-
-  e.ApplyTransform(mat);
-  BOOST_CHECK(eh.IsTransformationIdentity()==false);
+  e.ApplyTransform(trans);
+  BOOST_CHECK(eh.HasTransform()==true);
 
   geom::Vec3 orig_atom1=geom::Vec3(1.0,0.0,0.0);
   geom::Vec3 orig_atom2=geom::Vec3(0.0,2.0,0.0);
@@ -205,11 +219,9 @@ BOOST_AUTO_TEST_CASE(transformation)
 
   geom::Transform trans2;
   trans2.ApplyXAxisTranslation(3.5);
-  geom::Mat4 mat2 = trans2.GetMatrix();
+  e.ApplyTransform(trans2);
 
-  e.ApplyTransform(mat2);
-
-  BOOST_CHECK(eh.IsTransformationIdentity()==false);
+  BOOST_CHECK(eh.HasTransform()==true);
 
   tr_atom1=geom::Vec3(3.5,-1.0,0.0);
   tr_atom2=geom::Vec3(5.5,0.0,0.0);
@@ -253,7 +265,7 @@ BOOST_AUTO_TEST_CASE(transformation)
 
   geom::Mat4 identity;
   e.SetTransform(identity);
-  BOOST_CHECK(eh.IsTransformationIdentity()==true);
+  //BOOST_CHECK(eh.HasTransform()==false);
 
   BondHandle bond1 = e.Connect(atom1,atom2);
   BondHandle bond2 = e.Connect(atom1,atom3);
@@ -261,9 +273,9 @@ BOOST_AUTO_TEST_CASE(transformation)
   BOOST_CHECK(bond1.GetLength()==1.5);
   BOOST_CHECK(bond2.GetLength()==2.0);
 
-  e.SetTransform(mat);
-
-  BOOST_CHECK(eh.IsTransformationIdentity()==false);
+  e.SetTransform(trans);
+  
+  //BOOST_CHECK(eh.HasTransform()==true);
 
   BOOST_CHECK(bond1.GetLength()==1.5);
   BOOST_CHECK(bond2.GetLength()==2.0);
diff --git a/scripts/ost_config.in b/scripts/ost_config.in
index 5894bdb12c62241d556e04fb909eb9f83a17c5ef..f756d7cd30c29db720aeba659643c18bb872e4c9 100644
--- a/scripts/ost_config.in
+++ b/scripts/ost_config.in
@@ -30,9 +30,8 @@ export PATH="$DNG_BINDIR:${PATH}"
 export DYLD_FRAMEWORK_PATH="$DNG_LIBDIR:${DYLD_FRAMEWORK_PATH}"
 export DYLD_LIBRARY_PATH="$DNG_LIBDIR:${DYLD_LIBRARY_PATH}"
 export LD_LIBRARY_PATH="$DNG_LIBDIR:${LD_LIBRARY_PATH}"
-# set QT_PLUGIN_PATH and PYTHONPATH for bundle (commented except in linux bundles)
+# set QT_PLUGIN_PATH for bundle (commented except in linux bundles)
 #export QT_PLUGIN_PATH="$BIN_DIR/plugins"
-#export PYTHONPATH="$DNG_ROOT/@LIBDIR@/python@PYTHON_VERSION@:$OST_ADDITIONAL_PYTHONPATH"
 
 # retrieve absolute path to python executable
 pyexec="@PYTHON_BINARY@"
diff --git a/tools/molck/main.cc b/tools/molck/main.cc
index 9dd212a51c9dd2bc616f5f9e24a88c4015ff2533..2a5e8e7eac780c856d3345464c93339f28a0c2df 100644
--- a/tools/molck/main.cc
+++ b/tools/molck/main.cc
@@ -2,6 +2,8 @@
 #include <boost/program_options.hpp>
 #include <boost/filesystem/path.hpp>
 #include <boost/filesystem/convenience.hpp>
+#include <ost/base.hh>
+#include <ost/boost_filesystem_helper.hh>
 #include <ost/platform.hh>
 #include <ost/conop/model_check.hh>
 #include <ost/conop/conop.hh>
@@ -73,11 +75,7 @@ CompoundLibPtr load_compound_lib(const String& custom_path)
     fs::path share_path = path_only.branch_path();
     share_path = share_path / "share" / "openstructure" / "compounds.chemlib";
 
-    #if BOOST_FILESYSTEM_VERSION==3 || BOOST_VERSION<103400
-    String share_path_string=share_path.string();
-    #else
-    String share_path_string=share_path.file_string();
-    #endif       
+    String share_path_string=BFPathToString(share_path);
       
     if (fs::exists(share_path_string)) {
       return CompoundLib::Load(share_path_string);
@@ -369,11 +367,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();
-      #if BOOST_FILESYSTEM_VERSION==3 || BOOST_VERSION<103400
-      String input_filename_string=input_filename.string();
-      #else
-      String input_filename_string=input_filename.file_string();
-      #endif       
+      String input_filename_string=BFPathToString(input_filename);
       size_t replstart =output_blueprint_string.find('%');	
       String output_blueprint_string_copy = output_blueprint_string;
       if (replstart != String::npos) {