diff --git a/.gitignore b/.gitignore
index 05c992e3f9ddc3fb38323fbdc356c996822989a0..ae5ec6bffbcb2ec43587ee1e400c83dcc2758019 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,6 +26,8 @@ pov_*test.inc
 *-out.crd
 *-out.pqr
 *-out.png
+*_out.dcd
+*_out.pdb
 CMakeLists.txt.user
 OpenStructure.cbp
 DartConfiguration.tcl
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
new file mode 100644
index 0000000000000000000000000000000000000000..4151f7269f101d4cc37d7d97d5bafff65945cc65
--- /dev/null
+++ b/CHANGELOG.txt
@@ -0,0 +1,52 @@
+
+Changes in Release 1.2.1
+--------------------------------------------------------------------------------
+
+  * Use RPATH for linux bundles. No longer requires LD_LIBRARY_PATH to be set for
+    chemdict_tool and lddt [BZDNG-385]
+  * "install command line tools" also symlinks lddt, and chemdict_tool [BZDNG-386]
+  * Fixed broken the_hammer.py example [BZDNG-387]
+  * MacOS X: Make sure to use python2.6, not python as pyexec [BZDNG-388]
+  * Fix example directory path for MacOS X bundle [BZDNG-389]
+  * PDBWriter: Insert newline after END [BZDNG-391]
+  * Added missing documentation for a few AlignmentHandle methods
+  * Workaround for naccess which was failing when directory contains dots.
+  * Fixed superposition dialog for unnamed chains
+  * Fixed byte-swapping issue for DCD trajectories
+  * Fixed FFT panel update after switching data in main viewer
+  * Added missing pdbx_struct_assembly.id export
+  * lDDT: Updated default angle and bond tolerance parameters from 8 stddev to 12 
+    stddev.
+
+Changes in Release 1.2 (since 1.1)
+--------------------------------------------------------------------------------
+
+ * added mmCIF parser to enable loading of mmCIF files. The following categories
+   are currently understood:
+   atom_site, entity, entity_poly, citation, citation_author, exptl, refine,
+   pdbx_struct_assembly, pdbx_struct_assembly_gen, pdbx_struct_oper_list,
+   struct, struct_conf, struct_sheet_range, pdbx_database_PDB_obs_spr,
+   struct_ref, struct_ref_seq, struct_ref_seq_dif
+
+ * trajectory analysis support
+
+ * better intergration with numpy
+
+ * added Smith-Waterman local align and Needleman-Wunsch global align algorithms
+
+ * static linking of C++ executables
+
+ * support for building OST library with no gfx, gui, info libraries. This leads
+   to a compact application bundle that can easily be deployed
+
+ * work around compiler bugs in gcc-4.1 enabling compilation with CentOS 5.5's
+   default compiler and libraries
+
+ * introducing the new table class, supporting all kinds of analyses on tabular
+   data, including plotting and statistical analyses.
+
+ * added stereochemical plausibility checks and support for multiple references
+   to lDDT
+
+ * new superposition dialog in DNG
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 03496411dcccee60289cb1a4b407abc9a6f0040e..91c10973b898cdd817a83dc486916c342d406d38 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 2.6.4 FATAL_ERROR)
 project(OpenStructure CXX C)
 set (OST_VERSION_MAJOR 1)
 set (OST_VERSION_MINOR 2)
-set (OST_VERSION_PATCH 0)
+set (OST_VERSION_PATCH 1)
 set (OST_VERSION_STRING ${OST_VERSION_MAJOR}.${OST_VERSION_MINOR}.${OST_VERSION_PATCH} )
 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake_support)
 include(OST)
@@ -50,6 +50,7 @@ option(DEPLOYMENT "switch on deployment settings" OFF)
 option(COMPILE_TESTS "whether unit tests should be compiled by default" OFF)
 option(ENABLE_STATIC "whether static libraries should be compiled" OFF)
 option(DEBIAN_STYLE_LIBEXEC "whether 'libexec' should be put under 'lib/openstructure" OFF)
+option(HIDDEN_VISIBILITY "on gcc, use -fvisibility=hidden" OFF)
 
 if (CXX)
   set(CMAKE_CXX_COMPILER ${CXX})
@@ -239,7 +240,23 @@ if (ENABLE_GUI)
 endif()
 
 if (ENABLE_SPNAV)
-  find_package(SpNav REQUIRED)
+  #find_package(SpNav REQUIRED)
+  set(_SPNAV ON)
+else()
+  set(_SPNAV OFF)
+endif()
+
+if (CMAKE_COMPILER_IS_GNUCXX)
+  # do not write back into cache, otherwise the compile command line gets expanded
+  # with multiple -fno-strict-aliasing flags, triggering a complete rebuild whenever
+  # cmake is run
+  set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-strict-aliasing")
+  if(HIDDEN_VISIBILITY) 
+    set (CMAKE_CXX_FLAGS "-fvisibility=hidden")
+    set (_HIDDEN_VIS ON)
+  else(HIDDEN_VISIBILITY)
+    set (_HIDDEN_VIS OFF)
+  endif(HIDDEN_VISIBILITY)
 endif()
 
 # basic environment
@@ -247,7 +264,6 @@ include_directories(${Boost_INCLUDE_DIRS}
                     ${FFTW_INCLUDE_PATH} 
                     ${EIGEN2_INCLUDE_DIR}
                     ${TIFF_INCLUDE_DIR}
-                    ${SPNAV_INCLUDE_DIR}
                     ${PNG_INCLUDE_DIR}
                     )
 if(USE_NUMPY)
@@ -259,7 +275,7 @@ if (UNIX)
   SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
   if(USE_RPATH)
     set(_USE_RPATH ON)
-    SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${LIB_DIR}")
+    SET(CMAKE_INSTALL_RPATH "$ORIGIN/../${LIB_DIR}")
     SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
   else()
     set(_USE_RPATH OFF)
@@ -276,8 +292,8 @@ endif()
 add_subdirectory(modules)
 add_subdirectory(scripts)
 add_subdirectory(deployment)
-
 set(FILES_TO_BE_REMOVED ${CMAKE_SOURCE_DIR}/stage tests)
+add_subdirectory(tools)
 set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES
                              "${FILES_TO_BE_REMOVED}")
 
@@ -295,11 +311,13 @@ message(STATUS
         "   Image Processing support         (-DENABLE_IMG) : ${_IMG}\n"
         "   Shader support                   (-DUSE_SHADER) : ${_SHADER}\n"
         "   Numpy support                     (-DUSE_NUMPY) : ${_NUMPY}\n"
+        "   SpaceNav Device support        (-DENABLE_SPNAV) : ${_SPNAV}\n"
         "   Optimize                           (-DOPTIMIZE) : ${_OPT}\n"
         "   Profiling support                   (-DPROFILE) : ${_PROFILE}\n"
         "   Double Precision       (-DUSE_DOUBLE_PRECISION) : ${_DOUBLE_PREC}\n"
         "   Compound Lib                   (-DCOMPOUND_LIB) : ${_COMP_LIB}\n"
         "   TMAlign and TMScore         (-DCOMPILE_TMTOOLS) : ${_TM_TOOLS}\n"
         "   Static Libraries              (-DENABLE_STATIC) : ${ENABLE_STATIC}\n"
-        "   Debian-style 'libexec' (-DDEBIAN_STYLE_LIBEXEC) : ${_DEBIAN_STYLE_LIBEXEC}" )
+        "   Debian-style 'libexec' (-DDEBIAN_STYLE_LIBEXEC) : ${_DEBIAN_STYLE_LIBEXEC}\n"
+        "   Hidden object visibility  (-DHIDDEN_VISIBILITY) : ${_HIDDEN_VIS}")
 
diff --git a/cmake_support/FindMesa.cmake b/cmake_support/FindMesa.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..6b1c33d79271caa0ba33bec3f1fafe011c2267d8
--- /dev/null
+++ b/cmake_support/FindMesa.cmake
@@ -0,0 +1,37 @@
+set(OPENGL_FOUND FALSE)
+
+if (OPENGL_INCLUDE_DIR)
+
+  # in cache already
+  set(OPENGL_FOUND TRUE)
+
+else (OPENGL_INCLUDE_DIR)
+
+  if(DEFINED MESA_PREFIX)
+    set(_MESA_PREFIX ${MESA_PREFIX})
+  elseif(DEFINED ENV{MESA_PREFIX})
+    set(_MESA_PREFIX $ENV{MESA_PREFIX})
+  else()
+    message(FATAL_ERROR "no MESA_PREFIX given or found in environment")
+  endif()
+
+  if(DEFINED _MESA_PREFIX)
+    set(OPENGL_INCLUDE_DIR "${_MESA_PREFIX}/include" CACHE PATH "Mesa include")
+    set(OPENGL_LIBRARY_DIR "${_MESA_PREFIX}/lib" CACHE PATH "Mesa lib")
+    set(OPENGL_gl_LIBRARY "${_MESA_PREFIX}/lib/libGL.so" CACHE PATH "Mesa gl lib")
+    set(OPENGL_glu_LIBRARY "${_MESA_PREFIX}/lib/libGLU.so" CACHE PATH "Mesa glu lib")
+
+    set(OPENGL_LIBRARIES ${_MESA_PREFIX}/lib/libGL.so ${_MESA_PREFIX}/lib/libGLU.so ${_MESA_PREFIX}/lib/libOSMesa.so CACHE PATH "Mesa libs")
+    set(OPENGL_FOUND TRUE)
+    message(STATUS "Found Mesa include dir: ${OPENGL_INCLUDE_DIR}")
+    message(STATUS "Found Mesa lib dir: ${OPENGL_LIBRARY_DIR}")
+    message(STATUS "Using Mesa libs: ${OPENGL_LIBRARIES}")
+  endif()
+
+endif()
+
+if(NOT OPENGL_FOUND)
+    message(FATAL_ERROR "no Mesa found, please provide the correct location with MESA_PREFIX")
+endif()
+
+mark_as_advanced (OPENGL_INCLUDE_DIR)
diff --git a/cmake_support/OST.cmake b/cmake_support/OST.cmake
index 53b0d8025ab8896640e69f75986dd3096b0804ba..5ce0f0ee33667bc8f629dc019ac74f1e6fc10ea9 100644
--- a/cmake_support/OST.cmake
+++ b/cmake_support/OST.cmake
@@ -166,6 +166,7 @@ macro(module)
   file(MAKE_DIRECTORY ${LIB_STAGE_PATH})
   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()
@@ -175,6 +176,9 @@ macro(module)
   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")
+  endif()
   if (WIN32)
     set(_ABS_FILE_PATTERN "^[A-Z]:/")
   else()
@@ -204,6 +208,7 @@ macro(module)
     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)
     set_target_properties(${_LIB_NAME} PROPERTIES
                           COMPILE_DEFINITIONS OST_MODULE_${_UPPER_LIB_NAME})
     set_target_properties(${_LIB_NAME} PROPERTIES
diff --git a/deployment/linux/README.txt b/deployment/linux/README.txt
index 2f1ab3010a1c0854b08e58e45337296f3fe4938a..02beeb3f36f18f170a6b1c4768120552ff2c1c70 100644
--- a/deployment/linux/README.txt
+++ b/deployment/linux/README.txt
@@ -3,4 +3,5 @@ HOW TO USE THE BUNDLE SCRIPTS:
 1. Checkout a copy of the OpenStructure repository.
 2. Move to the <OpenStructure folder>/deployment/linux folder and start the create_bundle.py script using python
 3. In <OpenStructure> you'll find a tar.gz file. That's the bundle!
-4. If the process stops without completing, run the reset_repository.py script or delete the <OpenStructure Folder> and restart from scratch
+4. If the process stops without completing, reset the repository with 'git
+reset --hard HEAD' from the top level directory
diff --git a/deployment/linux/create_bundle_alt.py b/deployment/linux/create_bundle_alt.py
deleted file mode 100755
index 6e5cf9bcf26311b4d7e1acd2ee61a18b9fc36a9f..0000000000000000000000000000000000000000
--- a/deployment/linux/create_bundle_alt.py
+++ /dev/null
@@ -1,183 +0,0 @@
-import os,os.path
-import shutil
-import sys
-import tarfile
-import subprocess
-import re
-
-def get_libdir():
-  machine=os.uname()[4]
-  if machine.find('x86_64') !=-1:
-    return 'lib64'
-  else: 
-    return 'lib'
-    
-def get_arch():
-  machine=os.uname()[4]
-  if machine.find('x86_64') !=-1:
-    return '64bit'
-  else: 
-    return '32bit'
-
-def clean(standalonedir):
-  if os.path.exists(standalonedir):
-    shutil.rmtree(standalonedir)
-
-def copy_stage(stagedir,standalonedir):
-  libdir=get_libdir()
-  copytree_ex(os.path.join(stagedir,'bin'),os.path.join(standalonedir,'bin'))
-  copytree_ex(os.path.join(stagedir,libdir),os.path.join(standalonedir,libdir))
-  if os.path.exists(os.path.join(stagedir,'share')):
-    copytree_ex(os.path.join(stagedir,'share'),os.path.join(standalonedir,'share'))
-
-def collect_deps(binaries,exclude_list):
-  dependencies=set()
-  for binary in binaries:
-    collect_deps_recursive_(binary,dependencies,exclude_list)
-  return dependencies
-  
-def collect_deps_recursive_(binary,collected,exclude_list):
-  ldd_stdout=subprocess.Popen(['ldd',binary],stdout=subprocess.PIPE).stdout
-  output=ldd_stdout.readlines()
-  new_dependencies=set()
-  for entry in output:
-    if entry.find("statically linked")!=-1:
-      continue
-    sp=entry.split('(0x')
-    if len(sp)>0: # only continue if line is dependency
-     sp2=sp[0].split('=>',1)[-1].split()
-     if sp2: #ensure libname exists (fix for virtual linux-gate)
-       text=sp2[0]
-       if not text.split('.')[0].split('/')[-1] in exclude_list and not text in collected:
-         collect_deps_recursive_(text,collected,exclude_list)
-         collected.add(text) 
-  
-
-def copy_deps(binaries,standalonedir,exclude_list):
-  dependencies=set()
-  walk_list=os.walk(standalonedir)
-  binaries_list=[]
-  for dir_entry in walk_list:
-    for file_entry in dir_entry[2]:
-      if file_entry.endswith('.so') or file_entry in binaries:
-        filepath=os.path.join(dir_entry[0],file_entry)
-        binaries_list.append(filepath)  
-  dependencies=collect_deps(binaries_list,exclude_list)
-  for dep in dependencies:
-    shutil.copy2(dep,os.path.join(standalonedir,get_libdir()))
-
-def copy_examples(stagedir):
-  #todo
-  pass
-def copy_qt_plugins():
-  #todo
-  pass
-
-def process_scripts(scripts,standalonedir):
-  for script in scripts:
-    fp=open(os.path.join(standalonedir,'bin',script),'r')
-    text=fp.read()
-    fp.close()
-    text=re.sub('#export PYTHONPATH','export PYTHONPATH',text)
-    fp=open(os.path.join(standalonedir,'bin',script),'w')
-    fp.write(text)
-    fp.close()
-
-def create_package(name,standalonedir):
-  try:
-    import pysvn
-    try:
-      client=pysvn.Client()
-      svn_info=client.info('.')
-      revstring='-rev'+str(svn_info['revision'.number])
-    except pysvn.ClientError:
-      print 'No svn directory found. Addin no revision number.'
-      revstring=''
-  except ImportError:
-    print 'Pysvn not installed. Adding no revision number.'
-    revstring=''
-  tar_name=name+'-linux-'+get_arch()+revstring+'.tgz'
-  if os.path.exists(tar_name):
-    os.remove(tar_name)
-  tar = tarfile.open(tar_name, "w:gz")
-  tar.add(standalonedir,name+'-linux-'+get_arch()+revstring)
-  tar.close()
-
-def ignorer(dirpath,files):
-  ignores=[]
-  for f in files:
-    base=os.path.splitext(f)[0]
-    if f.endswith('.py'):
-      if base+'.pyc' in files or base+'.pyo' in files:
-        ignores.append(f)
-    elif f.endswith('.pyc'):
-      if base+'.pyo' in files:
-        ignores.append(f)
-  return ignores
-
-def copy_python_dirs(standalonedir):
-  dirs=sys.path[1:]
-  dirs.sort() #get toplevel dir to the beginning
-  toplevel=dirs[0]
-  shutil.copytree(toplevel,os.path.join(standalonedir,get_libdir(),'python'),ignore=ignorer)
-  for d in dirs[1:]:
-    if not d.startswith(toplevel) and os.path.isdir(d):
-      toplevel=d
-      copytree_ex(toplevel,os.path.join(standalonedir,get_libdir(),'python'),ignore=ignorer)
-
-
-def copytree_ex(source,destination, symlinks=False,ignore=None):
-  if not os.path.exists(destination):
-   shutil.copytree(source,destination,symlinks,ignore)
-  elif os.path.isdir(destination):
-    files=os.listdir(source)
-    if ignore:
-      ignores=ignore(source,files)
-    else:
-      ignores=[]
-    for f in files:
-      srcname=os.path.join(source,f)
-      dstname=os.path.join(destination,f)
-      if os.path.isdir(os.path.join(source,f)):
-        copytree_ex(srcname,dstname,symlinks,ignore=ignorer)
-      elif f not in ignores:
-        if symlinks and os.path.islink(srcname):
-          linkto = os.readlink(srcname)
-          os.symlink(linkto, dstname)
-        else:
-          shutil.copy2(srcname, dstname)
-  else:
-    raise IOError("destination is not a directory")
-    
-
-       
-############   main script ####################
-
-stagedir='../../stage'
-ost_stagedir='../../../openstructure/stage'
-standalonedir=os.path.join(os.getcwd(),'standalone')
-binaries=['gosty']
-exclude_list=['ld-linux','libexpat','libgcc_s','libglib','cmov','libice','libSM','libX','libg','libGL','libfontconfig','libfreetype','libdrm','libxcb','libICE']
-scripts=['dng','ost']
-
-#compile_stage()
-
-clean(standalonedir)
-print 'copying stage'
-copy_stage(stagedir,standalonedir)
-print 'copying ost stage'
-copy_stage(ost_stagedir,standalonedir)
-print 'copying python'
-shutil.copy(sys.executable,os.path.join(stagedir,'bin'))
-copy_python_dirs(standalonedir)
-print 'copying dependencies'
-binaries.append(sys.executable)
-copy_deps(binaries,standalonedir,exclude_list)
-print 'copying examples'
-copy_examples(stagedir)
-print 'copying plugins'
-copy_qt_plugins()
-print 'processing scripts'
-process_scripts(scripts,standalonedir)
-print 'creating package'
-create_package('openstructure','standalone')
diff --git a/deployment/linux/create_bundle.py b/deployment/linux/create_bundle_lucid.py
similarity index 58%
rename from deployment/linux/create_bundle.py
rename to deployment/linux/create_bundle_lucid.py
index 3f04533f0c4d6c3f84e907a0f73099bdf5988929..aec419bd5d17043c6a273044ad14e20abacec3f7 100644
--- a/deployment/linux/create_bundle.py
+++ b/deployment/linux/create_bundle_lucid.py
@@ -4,31 +4,56 @@ import subprocess
 import string
 import sys
 import datetime
+import sip
+import PyQt4
 
 
-# custom parameters
+# parameters that can be modified
+qt4_plugins_location='/usr/lib/qt4/plugins'
+ssl_crypto_location='/lib/'
+chemlib_dictionary_location='/home/bundler/compounds.chemlib'
+list_of_excluded_libraries=[
+'ld-linux',
+'libexpat',
+'libgcc_s',
+'libglib',
+'cmov',
+'libice',
+'libSM',
+'libX',
+'libg',
+'libGL.so',
+'libfontconfig',
+'libfreetype',
+'libdrm',
+'libxcb',
+'libICE',
+'libnvidia',
+'libc'
+]
 
-if len(sys.argv) < 3:
-  print 'usage: create_bundle.py  additional_label system_python_version'
+if len(sys.argv) < 2:
+  print 'usage: create_bundle.py  additional_label'
   sys.exit()
 
-system_python_version='python'+sys.argv[2]
-system_python_bin='/usr/bin/'+system_python_version
-system_python_libs='/usr/lib/'+system_python_version
-second_system_python_libs_flag=True
-second_system_python_libs='/usr/lib/pymodules/'+system_python_version
-python_bin_in_bundle='python'
-qt4_plugins='/usr/lib/qt4/plugins'
 additional_label=sys.argv[1]
-list_of_excluded_libraries=['ld-linux','libexpat','libgcc_s','libglib','cmov','libice','libSM','libX','libg','libGL.so','libfontconfig','libfreetype','libdrm','libxcb','libICE','libnvidia','libc']
+
 currdir=os.getcwd()
 if currdir.find('deployment')==-1 or currdir.find('linux')==-1:
   print '\n'
   print 'ERROR: Please run this script from the deployment/linux directory'
   print '\n'
   sys.exit()
+
+print "WARNING: If this script does not run to completion, please run 'git reset --hard HEAD' in the main directory (two up from here) before restarting"
+
+system_python_version=sys.version_info
+system_python_executable='python'+str(system_python_version[0])+'.'+str(system_python_version[1])
+system_python_bin='/usr/bin/'+system_python_executable
+system_python_libs='/usr/lib/'+system_python_executable
+qt4_module_location=os.path.dirname(PyQt4.__file__)
+sip_module_location=os.path.dirname(sip.__file__)
 print '\n'
-print 'WARNING: If this script does not run to completion, please run the reset_repository.py script before restarting'
 print '\n'
 print 'Detecting architecture and revision'
 uname_output=subprocess.Popen('uname -a', shell=True, cwd='../../',stdout=subprocess.PIPE).stdout
@@ -39,26 +64,16 @@ if uname_line[0].find('x86_64') !=-1:
 else: 
   libdir='lib'
   archstring='32bit'
-date_pattern='%Y-%b-%d'
-build=datetime.date.today()
-directory_name='openstructure-linux-'+archstring+'-'+additional_label+'-'+str(build)
+directory_name='openstructure-linux-'+archstring+'-'+additional_label
 print 'Hardcoding package python binary path in openstructure executables'
+subprocess.call('rm -f scripts/ost_config.in.pre* scripts/ost_config.in.backup',shell=True,cwd='../../')
 subprocess.call('mv scripts/ost_config.in scripts/ost_config.in.backup',shell=True,cwd='../../')
-subprocess.call('sed "s/@PYTHON_BINARY@/\$DNG_ROOT\/bin\/'+python_bin_in_bundle+'/g" scripts/ost_config.in.backup > scripts/ost_config.in.preprepre',shell=True,cwd='../../')
+subprocess.call('sed "s/@PYTHON_BINARY@/\$DNG_ROOT\/bin\/python/g" scripts/ost_config.in.backup > scripts/ost_config.in.preprepre',shell=True,cwd='../../')
 subprocess.call('sed "s/\#export PYTHONHOME/ export PYTHONHOME/g" scripts/ost_config.in.preprepre > scripts/ost_config.in.prepre',shell=True,cwd='../../')
 subprocess.call('sed "s/\#export PYTHONPATH/ export PYTHONPATH/g" scripts/ost_config.in.prepre > scripts/ost_config.in.pre',shell=True,cwd='../../')
 subprocess.call('sed "s/\#export QT_PLUGIN_PATH/ export QT_PLUGIN_PATH/g" scripts/ost_config.in.pre > scripts/ost_config.in',shell=True,cwd='../../')
-#print 'Downloading Chemlib dictionary'
-#subprocess.call('wget ftp://ftp.wwpdb.org/pub/pdb/data/monomers/components.cif', shell=True, cwd='../../')
-#print 'Compiling Openstructure'
-#subprocess.call('cmake ./ -DCMAKE_BUILD_TYPE=Release -DPREFIX='+directory_name+' -DBoost_COMPILER='+boost_string+'-DENABLE_IMG=OFF -DENABLE_UI=OFF -DENABLE_GFX=OFF', shell=True,cwd='../../')
-#subprocess.call('cmake ./ -DCMAKE_BUILD_TYPE=Release -DPREFIX='+directory_name+' s-DENABLE_IMG=OFF -DENABLE_UI=OFF -DENABLE_GFX=OFF', shell=True,cwd='../../')
-#subprocess.call('make -j5',shell=True,cwd='../../')
-##print 'Converting Chemlib dictionary'
-##subprocess.call('stage/bin/chemdict_tool create components.cif compounds.chemlib', shell=True, cwd='../../')
-print '\nStaging Chemlib dictionary'
 print 'Compiling Openstructure'
-subprocess.call('cmake ./ -DCMAKE_BUILD_TYPE=Release -DPREFIX='+directory_name+' -DCOMPOUND_LIB=ChemLib/compounds.chemlib -DENABLE_IMG=ON -DENABLE_UI=ON -DENABLE_GFX=ON -DOPTIMIZE=ON',shell=True,cwd='../../')
+subprocess.call('cmake ./ -DCMAKE_BUILD_TYPE=Release -DPREFIX='+directory_name+' -DCOMPOUND_LIB='+chemlib_dictionary_location+' -DENABLE_IMG=ON -DUSE_RPATH=ON -DENABLE_GUI=ON -DENABLE_GFX=ON -DOPTIMIZE=ON',shell=True,cwd='../../')
 subprocess.call('make -j2',shell=True,cwd='../../')
 print 'Removing obsolete packages and package directory'
 subprocess.call('rm -fr openstructure-linux*',shell=True,cwd='../../')
@@ -66,14 +81,14 @@ print 'Creating new package directory'
 subprocess.call('mkdir '+directory_name,shell=True,cwd='../../')
 subprocess.call('mkdir '+directory_name+'/bin',shell=True,cwd='../../')
 print 'Copy python executable into stage for dependency detection'
-print system_python_bin
 subprocess.call('cp '+system_python_bin+ ' stage/bin/python',shell=True,cwd='../../')
 print 'Copy python libraries into the stage for dependency detection'
-subprocess.call('cp -pRL '+system_python_libs+' stage/'+libdir+'/python',shell=True,cwd='../../')
-subprocess.call('rm -fr stage/'+libdir+'/python/dist-packages',shell=True,cwd='../../')
-if second_system_python_libs_flag==True:
-  subprocess.call('cp -pRL '+second_system_python_libs+'/sip* stage/'+libdir+'/python/',shell=True,cwd='../../')
-  subprocess.call('cp -pRL '+second_system_python_libs+'/PyQt* stage/'+libdir+'/python/',shell=True,cwd='../../')
+subprocess.call('cp -pRL '+system_python_libs+' stage/'+libdir+'/',shell=True,cwd='../../')
+subprocess.call('rm -fr stage/'+libdir+'/'+system_python_executable+'/dist-packages',shell=True,cwd='../../')
+subprocess.call('cp -pRL '+sip_module_location+'/sip* stage/'+libdir+'/'+system_python_executable+'/',shell=True,cwd='../../')
+subprocess.call('cp -pRL '+qt4_module_location+' stage/'+libdir+'/'+system_python_executable+'/',shell=True,cwd='../../')
+print 'Copy boost program option libraries into the stage for dependency detection'
+subprocess.call('cp -pRL /usr/lib/libboost_program_options.so* stage/'+libdir+'/',shell=True,cwd='../../')
 print 'Creating new dependency list'
 so_list=[]
 walk_list=os.walk('../../stage')
@@ -106,13 +121,12 @@ for entry in filtered_dep_list:
 print 'Copy python executable into package directory structure'
 subprocess.call('cp '+system_python_bin+ ' '+directory_name+'/bin/python',shell=True,cwd='../../')
 print 'Copy python libraries into package directory structure'
-subprocess.call('cp -pRL '+system_python_libs+' '+directory_name+'/'+libdir+'/python',shell=True,cwd='../../')
-subprocess.call('rm -fr '+directory_name+'/'+libdir+'/python/dist-packages',shell=True,cwd='../../')
-if second_system_python_libs_flag==True:
-  subprocess.call('cp -pRL '+second_system_python_libs+'/sip* '+directory_name+'/'+libdir+'/python/',shell=True,cwd='../../')
-  subprocess.call('cp -pRL '+second_system_python_libs+'/PyQt* '+directory_name+'/'+libdir+'/python/',shell=True,cwd='../../')
+subprocess.call('cp -pRL '+system_python_libs+' '+directory_name+'/'+libdir+'/'+system_python_executable+'/',shell=True,cwd='../../')
+subprocess.call('rm -fr '+directory_name+'/'+libdir+'/'+system_python_executable+'/dist-packages',shell=True,cwd='../../')
+subprocess.call('cp -pRL '+sip_module_location+'/sip* '+directory_name+'/'+libdir+'/'+system_python_executable+'/',shell=True,cwd='../../')
+subprocess.call('cp -pRL '+qt4_module_location+' '+directory_name+'/'+libdir+'/'+system_python_executable+'/',shell=True,cwd='../../')
 print 'Copy Qt 4 plugins into package directory structure'
-subprocess.call('cp -pRL '+qt4_plugins+' '+directory_name+'/bin/',shell=True,cwd='../../')
+subprocess.call('cp -pRL '+qt4_plugins_location+' '+directory_name+'/bin/',shell=True,cwd='../../')
 print 'Copying supplementary material into package directory structure'
 subprocess.call('cp -pRL  stage/share/openstructure  '+directory_name+'/share/',shell=True,cwd='../../')
 print 'Copying examples into package directory structure'
@@ -122,19 +136,20 @@ subprocess.call('cp deployment/README.html '+directory_name,shell=True,cwd='../.
 print 'Creating executables at the top level of the package directory structure'
 subprocess.call('ln -sf bin/dng ./dng',shell=True,cwd='../../'+directory_name)
 subprocess.call('ln -sf bin/ost ./ost',shell=True,cwd='../../'+directory_name)
+subprocess.call('ln -sf bin/lddt ./lddt',shell=True,cwd='../../'+directory_name)
 print 'Copying additional libraries in the package directory structure'
-subprocess.call('cp /usr/lib/libssl.so.0.9.8   '+directory_name+'/'+libdir,shell=True,cwd='../../')
-subprocess.call('cp /usr/lib/libcrypto.so.0.9.8   '+directory_name+'/'+libdir,shell=True,cwd='../../')
-print 'Removing headers from package directory structure'
-subprocess.call('rm -fr   '+directory_name+'/include',shell=True,cwd='../../')
+subprocess.call('cp '+ssl_crypto_location+'/libssl.so* '+directory_name+'/'+libdir,shell=True,cwd='../../')
+subprocess.call('cp '+ssl_crypto_location+'/libcrypto.so* '+directory_name+'/'+libdir,shell=True,cwd='../../')
+subprocess.call('cp -pRL /usr/lib/libboost_program_options.so* '+directory_name+'/'+libdir+'/',shell=True,cwd='../../')
+print 'Copying python headers in the package directory structure'
+subprocess.call('mkdir -p '+directory_name+'/local/include/',shell=True,cwd='../../')
+subprocess.call('cp -r /usr/include/'+system_python_executable+' '+directory_name+'/local/include/',shell=True,cwd='../../')
 print 'Stripping pyc files from bundle'
 subprocess.call('rm -rf $(find . -name *.pyc)',shell=True,cwd='../../')
 print 'removing dokk and harmony examples from bundle'
 subprocess.call('rm -rf '+directory_name+'/share/openstructure/examples/code_fragments/dokk',shell=True,cwd='../../')
 subprocess.call('rm -rf '+directory_name+'/share/openstructure/examples/code_fragments/harmony',shell=True,cwd='../../')
-print 'De-hardcoding package python binary path from openstructure executables'
-subprocess.call('rm scripts/ost_config.in',shell=True,cwd='../../')
-subprocess.call('rm scripts/ost_config.in.pre*',shell=True,cwd='../../')
-subprocess.call('mv scripts/ost_config.in.backup scripts/ost_config.in',shell=True,cwd='../../')
+print 'Compressing the bundle'
 subprocess.call('tar cfz '+directory_name+'.tgz '+directory_name,shell=True,cwd='../../')
+print "Done. Please run 'git reset --hard HEAD' in the top directory before restarting."
 
diff --git a/deployment/linux/create_bundle_precise.py b/deployment/linux/create_bundle_precise.py
new file mode 100644
index 0000000000000000000000000000000000000000..9ffeff82463112f79e857ecc8f7bf202deef91da
--- /dev/null
+++ b/deployment/linux/create_bundle_precise.py
@@ -0,0 +1,155 @@
+import os
+import shutil
+import subprocess
+import string
+import sys
+import datetime
+import sip
+import PyQt4
+
+
+# parameters that can be modified
+qt4_plugins_location='/usr/lib/i386-linux-gnu/qt4/plugins'
+ssl_crypto_location='/lib/i386-linux-gnu/'
+chemlib_dictionary_location='/home/bundler/compounds.chemlib'
+list_of_excluded_libraries=[
+'ld-linux',
+'libexpat',
+'libgcc_s',
+'libglib',
+'cmov',
+'libice',
+'libSM',
+'libX',
+'libg',
+'libGL.so',
+'libfontconfig',
+'libfreetype',
+'libdrm',
+'libxcb',
+'libICE',
+'libnvidia',
+'libc'
+]
+
+if len(sys.argv) < 2:
+  print 'usage: create_bundle.py  additional_label'
+  sys.exit()
+
+additional_label=sys.argv[1]
+
+currdir=os.getcwd()
+if currdir.find('deployment')==-1 or currdir.find('linux')==-1:
+  print '\n'
+  print 'ERROR: Please run this script from the deployment/linux directory'
+  print '\n'
+  sys.exit()
+
+print "WARNING: If this script does not run to completion, please run 'git reset --hard HEAD' in the main directory (two up from here) before restarting"
+
+system_python_version=sys.version_info
+system_python_executable='python'+str(system_python_version[0])+'.'+str(system_python_version[1])
+system_python_bin='/usr/bin/'+system_python_executable
+system_python_libs='/usr/lib/'+system_python_executable
+qt4_module_location=os.path.dirname(PyQt4.__file__)
+sip_module_location=os.path.dirname(sip.__file__)
+print '\n'
+print '\n'
+print 'Detecting architecture and revision'
+uname_output=subprocess.Popen('uname -a', shell=True, cwd='../../',stdout=subprocess.PIPE).stdout
+uname_line=uname_output.readlines()
+if uname_line[0].find('x86_64') !=-1:
+  libdir='lib64'
+  archstring='64bit'
+else: 
+  libdir='lib'
+  archstring='32bit'
+directory_name='openstructure-linux-'+archstring+'-'+additional_label
+print 'Hardcoding package python binary path in openstructure executables'
+subprocess.call('rm -f scripts/ost_config.in.pre* scripts/ost_config.in.backup',shell=True,cwd='../../')
+subprocess.call('mv scripts/ost_config.in scripts/ost_config.in.backup',shell=True,cwd='../../')
+subprocess.call('sed "s/@PYTHON_BINARY@/\$DNG_ROOT\/bin\/python/g" scripts/ost_config.in.backup > scripts/ost_config.in.preprepre',shell=True,cwd='../../')
+subprocess.call('sed "s/\#export PYTHONHOME/ export PYTHONHOME/g" scripts/ost_config.in.preprepre > scripts/ost_config.in.prepre',shell=True,cwd='../../')
+subprocess.call('sed "s/\#export PYTHONPATH/ export PYTHONPATH/g" scripts/ost_config.in.prepre > scripts/ost_config.in.pre',shell=True,cwd='../../')
+subprocess.call('sed "s/\#export QT_PLUGIN_PATH/ export QT_PLUGIN_PATH/g" scripts/ost_config.in.pre > scripts/ost_config.in',shell=True,cwd='../../')
+print 'Compiling Openstructure'
+subprocess.call('cmake ./ -DCMAKE_BUILD_TYPE=Release -DPREFIX='+directory_name+' -DCOMPOUND_LIB='+chemlib_dictionary_location+' -DUSE_RPATH=ON -DENABLE_IMG=ON -DENABLE_GUI=ON -DENABLE_GFX=ON -DOPTIMIZE=ON',shell=True,cwd='../../')
+subprocess.call('make -j2',shell=True,cwd='../../')
+print 'Removing obsolete packages and package directory'
+subprocess.call('rm -fr openstructure-linux*',shell=True,cwd='../../')
+print 'Creating new package directory'
+subprocess.call('mkdir '+directory_name,shell=True,cwd='../../')
+subprocess.call('mkdir '+directory_name+'/bin',shell=True,cwd='../../')
+print 'Copy python executable into stage for dependency detection'
+subprocess.call('cp '+system_python_bin+ ' stage/bin/python',shell=True,cwd='../../')
+print 'Copy python libraries into the stage for dependency detection'
+subprocess.call('cp -pRL '+system_python_libs+' stage/'+libdir+'/',shell=True,cwd='../../')
+subprocess.call('rm -fr stage/'+libdir+'/'+system_python_executable+'/dist-packages',shell=True,cwd='../../')
+subprocess.call('cp -pRL '+sip_module_location+'/sip* stage/'+libdir+'/'+system_python_executable+'/',shell=True,cwd='../../')
+subprocess.call('cp -pRL '+qt4_module_location+' stage/'+libdir+'/'+system_python_executable+'/',shell=True,cwd='../../')
+print 'Copy boost program option libraries into the stage for dependency detection'
+subprocess.call('cp -pRL /usr/lib/libboost_program_options.so* stage/'+libdir+'/',shell=True,cwd='../../')
+print 'Creating new dependency list'
+so_list=[]
+walk_list=os.walk('../../stage')
+for dir_entry in walk_list:
+  for file_entry in dir_entry[2]:
+    if file_entry.find('.so')==len(file_entry)-3 or file_entry=='gosty':
+      filepath=os.path.join(dir_entry[0],file_entry)
+      so_list.append(filepath)  
+dep_list=[]
+for so_entry in so_list:
+   dep=subprocess.Popen('perl ./ldd-rec.pl '+so_entry,shell=True,stdout=subprocess.PIPE,cwd='./').stdout
+   dep_so_entry=dep.readlines()
+   for dep_entry in dep_so_entry:
+     dep_list.append(dep_entry[:-1]) 
+sorted_dep_list=sorted(list(set(dep_list)))
+print 'Filtering system libraries from depenedency list'
+filtered_dep_list=[]
+for entry in sorted_dep_list:
+   exclude=False
+   for exclusion in list_of_excluded_libraries:
+     if entry.find(exclusion)!=-1:
+       exclude=True
+   if exclude==False: 
+     filtered_dep_list.append(entry)
+print 'Installing OpenStructure into package directory structure'
+subprocess.call('make install',shell=True,cwd='../../')
+print 'Copy libraries in the package directory structure'
+for entry in filtered_dep_list:
+  subprocess.call('cp '+entry+' '+directory_name+'/'+libdir,shell=True,cwd='../../')
+print 'Copy python executable into package directory structure'
+subprocess.call('cp '+system_python_bin+ ' '+directory_name+'/bin/python',shell=True,cwd='../../')
+print 'Copy python libraries into package directory structure'
+subprocess.call('cp -pRL '+system_python_libs+' '+directory_name+'/'+libdir+'/'+system_python_executable+'/',shell=True,cwd='../../')
+subprocess.call('rm -fr '+directory_name+'/'+libdir+'/'+system_python_executable+'/dist-packages',shell=True,cwd='../../')
+subprocess.call('cp -pRL '+sip_module_location+'/sip* '+directory_name+'/'+libdir+'/'+system_python_executable+'/',shell=True,cwd='../../')
+subprocess.call('cp -pRL '+qt4_module_location+' '+directory_name+'/'+libdir+'/'+system_python_executable+'/',shell=True,cwd='../../')
+print 'Copy Qt 4 plugins into package directory structure'
+subprocess.call('cp -pRL '+qt4_plugins_location+' '+directory_name+'/bin/',shell=True,cwd='../../')
+print 'Copying supplementary material into package directory structure'
+subprocess.call('cp -pRL  stage/share/openstructure  '+directory_name+'/share/',shell=True,cwd='../../')
+print 'Copying examples into package directory structure'
+subprocess.call('cp -pRL  examples  '+directory_name+'/share/openstructure/',shell=True,cwd='../../')
+print 'Copying ReadMe file into package directory structure'
+subprocess.call('cp deployment/README.html '+directory_name,shell=True,cwd='../../')
+print 'Creating executables at the top level of the package directory structure'
+subprocess.call('ln -sf bin/dng ./dng',shell=True,cwd='../../'+directory_name)
+subprocess.call('ln -sf bin/ost ./ost',shell=True,cwd='../../'+directory_name)
+subprocess.call('ln -sf bin/lddt ./lddt',shell=True,cwd='../../'+directory_name)
+print 'Copying additional libraries in the package directory structure'
+subprocess.call('cp '+ssl_crypto_location+'/libssl.so* '+directory_name+'/'+libdir,shell=True,cwd='../../')
+subprocess.call('cp '+ssl_crypto_location+'/libcrypto.so* '+directory_name+'/'+libdir,shell=True,cwd='../../')
+subprocess.call('cp -pRL /usr/lib/libboost_program_options.so* '+directory_name+'/'+libdir+'/',shell=True,cwd='../../')
+print 'Copying python headers in the package directory structure'
+subprocess.call('mkdir -p '+directory_name+'/local/include/',shell=True,cwd='../../')
+subprocess.call('cp -r /usr/include/'+system_python_executable+' '+directory_name+'/local/include/',shell=True,cwd='../../')
+print 'Stripping pyc files from bundle'
+subprocess.call('rm -rf $(find . -name *.pyc)',shell=True,cwd='../../')
+print 'removing dokk and harmony examples from bundle'
+subprocess.call('rm -rf '+directory_name+'/share/openstructure/examples/code_fragments/dokk',shell=True,cwd='../../')
+subprocess.call('rm -rf '+directory_name+'/share/openstructure/examples/code_fragments/harmony',shell=True,cwd='../../')
+print 'Compressing the bundle'
+subprocess.call('tar cfz '+directory_name+'.tgz '+directory_name,shell=True,cwd='../../')
+print "Done. Please run 'git reset --hard HEAD' in the top directory before restarting."
+
diff --git a/deployment/linux/debian/README b/deployment/linux/debian/README
deleted file mode 100644
index c3a5a886f2754202845d533c5399e6eeb416ae86..0000000000000000000000000000000000000000
--- a/deployment/linux/debian/README
+++ /dev/null
@@ -1,8 +0,0 @@
-1. Checkout OpenStructure into a directory called strictly:'openstructure-<version>' (currently is 1.1d - 1.1 develop)
-2. Remove all the .git* files and directories from the source
-3. Create a compressed file with the source directory called strictly 'openstructure_<version>.orig.tar.gz' 
-   (At the same level as the source directory)
-4. Copy the 'debian' directory into the top level of the source directory
-5. Go into the top level of the source directory
-6. Build package with 'debuilder -uc -us'
-7. You can find the built package at the same level as the source directory and the source zipped file
diff --git a/deployment/linux/debian/debian/README.source b/deployment/linux/debian/debian/README.source
deleted file mode 100644
index c6c09893537f7e95bd2a01b7fe343ed65798ecf3..0000000000000000000000000000000000000000
--- a/deployment/linux/debian/debian/README.source
+++ /dev/null
@@ -1,18 +0,0 @@
-===============OPENSTRUCTURE molecular modelling framework ===============
-
-
-OpenStructure is the next generation molecular modelling tailored at anybody
- using 3D Structures or electron density maps.
-
-Please refer to www.openstructure.org for more information or try out
- directly one of the binary packages available for download.
-
-Thank you for you interest and enjoy the straightforward way of handling 
-protein structure data!
-
-Please do not hesitate to contact us for feedback or troubleshooting:
-
-ost-users@maillist.unibas.ch 
-
-
-=============== The OpenStructure Team ===================================
diff --git a/deployment/linux/debian/debian/changelog b/deployment/linux/debian/debian/changelog
deleted file mode 100644
index 9ecfb662316dd8c2d6a8e6ddcc17e4cf3573e526..0000000000000000000000000000000000000000
--- a/deployment/linux/debian/debian/changelog
+++ /dev/null
@@ -1,5 +0,0 @@
-openstructure (1.1d-0ubuntu1) natty; urgency=low
-
-  * Initial release 
-
- -- Valerio Mariani <valerio.mariani@unibas.ch>  Wed, 13 Jul 2011 15:41:35 +0200
diff --git a/deployment/linux/debian/debian/chemdict_tool.1 b/deployment/linux/debian/debian/chemdict_tool.1
deleted file mode 100644
index 7cbb4e805d2f7e52bf0ae16701d208cc5946fff1..0000000000000000000000000000000000000000
--- a/deployment/linux/debian/debian/chemdict_tool.1
+++ /dev/null
@@ -1,33 +0,0 @@
-.\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.38.4.
-.TH CHEMDICT_TOOL: "1" "July 2011" "User Commands"
-.SH NAME
-chemdict_tool \- compound libary creation tool for OpenStructure
-.SH SYNOPSIS
-chemdict_tool action <compound\-dict> <db> (pdb|charmm|amber|opls)
-.SH OPTIONS
-Supported actions are:
-.TP
-create
-\- creates a new db
-.TP
-update
-\- update existing db
-.SS "supported actions are:"
-.TP
-create
-\- creates a new db
-.TP
-update
-\- update existing db
-.SH "SEE ALSO"
-The full documentation for
-.B usage:
-is maintained as a Texinfo manual.  If the
-.B info
-and
-.B usage:
-programs are properly installed at your site, the command
-.IP
-.B info usage:
-.PP
-should give you access to the complete manual.
diff --git a/deployment/linux/debian/debian/compat b/deployment/linux/debian/debian/compat
deleted file mode 100644
index 7f8f011eb73d6043d2e6db9d2c101195ae2801f2..0000000000000000000000000000000000000000
--- a/deployment/linux/debian/debian/compat
+++ /dev/null
@@ -1 +0,0 @@
-7
diff --git a/deployment/linux/debian/debian/control b/deployment/linux/debian/debian/control
deleted file mode 100644
index 43a9f02fdda663dcf358819cf3bb92381c501311..0000000000000000000000000000000000000000
--- a/deployment/linux/debian/debian/control
+++ /dev/null
@@ -1,23 +0,0 @@
-Source: openstructure
-Section: science
-Priority: extra
-Maintainer: Valerio Mariani <valerio.mariani@unibas.ch>
-Build-Depends: debhelper (>= 7.0.50~),cmake,desktop-file-utils,libboost-all-dev,libeigen2-dev,qt4-dev-tools,libqt4-dev,libqt4-opengl-dev,python-qt4-dev,pyqt4-dev-tools,libfftw3-dev,libpng12-dev,libtiff4-dev,python-dev
-Standards-Version: 3.9.1
-Homepage: http://www.openstructure.org
-          
-Package: openstructure
-Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, python-sip, python-qt4
-Description: Open-source computational structural biology framework
- The Openstructure  project aims to provide an open-source, modular, flexible, 
- molecular modelling and visualization environment. It is targeted at 
- interested method developers in the field of structural bioinformatics.
-
-Package: openstructure-dev
-Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, openstructure
-Description: Open-source computational structural biology framework
- The Openstructure  project aims to provide an open-source, modular, flexible, 
- molecular modelling and visualization environment. It is targeted at 
- interested method developers in the field of structural bioinformatics.
diff --git a/deployment/linux/debian/debian/copyright b/deployment/linux/debian/debian/copyright
deleted file mode 100644
index b93d7503fb504646b3023bcc25817335d2579868..0000000000000000000000000000000000000000
--- a/deployment/linux/debian/debian/copyright
+++ /dev/null
@@ -1,40 +0,0 @@
-Format: http://dep.debian.net/deps/dep5
-Upstream-Name: openstructure
-Source: http://www.openstructure.org
-
-Files: *
-Copyright: 2008-2011 Torsten Schwede <torsten.schwede@unibas.ch>
-License: LGPL-3.0
-
-Files: debian/*
-Copyright: 2011 Valerio Mariani <valerio.mariani@unibas.ch>
-License: LGPL-3.0
-
-License: LGPL-3.0
- This package 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 of the License, or (at your option) any later version.
- .
- This package 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 General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- .
- On Debian systems, the complete text of the GNU Lesser General
- Public License can be found in "/usr/share/common-licenses/LGPL-3".
-
-Files: modules/db/src/sqlite3.h, modules/db/src/sqlite.c
-Copyright: 2011 Valerio Mariani <valerio.mariani@unibas.ch>
-License: None
- 2001 September 15
- .
- The author disclaims copyright to this source code.  In place of
- a legal notice, here is a blessing:
- .
-    May you do good and not evil.
-    May you find forgiveness for yourself and forgive others.
-    May you share freely, never taking more than you give.
diff --git a/deployment/linux/debian/debian/dng.1 b/deployment/linux/debian/debian/dng.1
deleted file mode 100644
index dbc68330d425affad81420e25645719ac07c8b24..0000000000000000000000000000000000000000
--- a/deployment/linux/debian/debian/dng.1
+++ /dev/null
@@ -1,39 +0,0 @@
-.\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.38.4.
-.TH DNG "1" "July 2011" "User Commands"
-.SH NAME
-dng \- GUI for OpenStructure
-.SH SYNOPSIS
-.B dng
-[\fIoptions\fR] [\fIfiles to load\fR]
-.SH OPTIONS
-.TP
-\fB\-h\fR, \fB\-\-help\fR
-show this help message and exit
-.TP
-\fB\-v\fR VLEVEL, \fB\-\-verbosity_level\fR=\fIVLEVEL\fR
-sets the verbosity level [default: 2]
-.TP
-\fB\-s\fR SCRIPT, \fB\-\-script\fR=\fISCRIPT\fR
-executes a script (syntax: \fB\-s\fR SCRIPT [options] [args])
-Anything that follows this option is passed to the
-script
-.TP
-\fB\-p\fR PDB_IDS, \fB\-\-pdb_id\fR=\fIPDB_IDS\fR
-PDB file ID. The file will be retrieved from PDB
-.TP
-\fB\-b\fR BUILDER, \fB\-\-builder\fR=\fIBUILDER\fR
-Type of builder used by the progam (either RULE_BASED
-or HEURISTIC) [default: HEURISTIC]
-.TP
-\fB\-c\fR COMPLIB, \fB\-\-compound_library\fR=\fICOMPLIB\fR
-Compound library for the RULE_BASED builder (only used
-if \fB\-\-builder\fR option is set to RULE_BASED, otherwise
-ignored [default: compounds.chemlib]
-.TP
-\fB\-q\fR QUERY, \fB\-\-query\fR=\fIQUERY\fR
-Selection query to be highlighted automatically upon
-loading (only used together with \fB\-p\fR option or when a
-PDB file is loaded, otherwise ignored [default: None]
-.TP
-\fB\-S\fR, \fB\-\-stereo\fR
-try to get a quad\-buffer stereo visual
diff --git a/deployment/linux/debian/debian/openstructure.desktop b/deployment/linux/debian/debian/openstructure.desktop
deleted file mode 100644
index b5ae761af421073b92e3ce58fa0c5100417a3ae8..0000000000000000000000000000000000000000
--- a/deployment/linux/debian/debian/openstructure.desktop
+++ /dev/null
@@ -1,8 +0,0 @@
-[Desktop Entry]
-Name=OpenStructure
-GenericName=Open-Source Computational Structural Biology Framework
-Exec=dng
-Icon=openstructure
-Terminal=false
-Type=Application
-Categories=Education;Science;
diff --git a/deployment/linux/debian/debian/openstructure.manpages b/deployment/linux/debian/debian/openstructure.manpages
deleted file mode 100644
index e73d09dbbec1bf1adaed4065f926ecbe8e872771..0000000000000000000000000000000000000000
--- a/deployment/linux/debian/debian/openstructure.manpages
+++ /dev/null
@@ -1,3 +0,0 @@
-debian/ost.1
-debian/dng.1
-debian/chemdict_tool.1
diff --git a/deployment/linux/debian/debian/ost.1 b/deployment/linux/debian/debian/ost.1
deleted file mode 100644
index afd5f75dcb8eadc27a09ecacb147138c3451ac7a..0000000000000000000000000000000000000000
--- a/deployment/linux/debian/debian/ost.1
+++ /dev/null
@@ -1,18 +0,0 @@
-.\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.38.4.
-.TH OST "1" "July 2011" "User Commands"
-.SH NAME
-ost: \- command-line console for OpenStructure
-.SH SYNOPSIS
-.B ost
-[\fIost options\fR] [\fIscript to execute\fR] [\fIscript parameters\fR]
-.SH OPTIONS
-.TP
-\fB\-i\fR, \fB\-\-interactive\fR
-start interpreter interactively (must be first
-parameter, ignored otherwise)
-.TP
-\fB\-h\fR, \fB\-\-help\fR
-show this help message and exit
-.TP
-\fB\-v\fR VLEVEL, \fB\-\-verbosity_level\fR=\fIVLEVEL\fR
-sets the verbosity level [default: 2]
diff --git a/deployment/linux/debian/debian/postinst b/deployment/linux/debian/debian/postinst
deleted file mode 100644
index a448189622f2efd26b94eb33f2759706a6d7bdbd..0000000000000000000000000000000000000000
--- a/deployment/linux/debian/debian/postinst
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/bin/sh
-# postinst script for openstructure
-#
-# see: dh_installdeb(1)
-
-set -e
-
-# summary of how this script can be called:
-#        * <postinst> `configure' <most-recently-configured-version>
-#        * <old-postinst> `abort-upgrade' <new version>
-#        * <conflictor's-postinst> `abort-remove' `in-favour' <package>
-#          <new-version>
-#        * <postinst> `abort-remove'
-#        * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
-#          <failed-install-package> <version> `removing'
-#          <conflicting-package> <version>
-# for details, see http://www.debian.org/doc/debian-policy/ or
-# the debian-policy package
-
-
-case "$1" in
-    configure)
-    ldconfig
-    ;;
-
-    abort-upgrade|abort-remove|abort-deconfigure)
-    ;;
-
-    *)
-        echo "postinst called with unknown argument \`$1'" >&2
-        exit 1
-    ;;
-esac
-
-# dh_installdeb will replace this with shell code automatically
-# generated by other debhelper scripts.
-
-#DEBHELPER#
-
-exit 0
diff --git a/deployment/linux/debian/debian/rules b/deployment/linux/debian/debian/rules
deleted file mode 100755
index 7b9d18ba98b725099155c5f3d87a78f20e2cba5c..0000000000000000000000000000000000000000
--- a/deployment/linux/debian/debian/rules
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/make -f
-# -*- makefile -*-
-# Sample debian/rules that uses debhelper.
-# This file was originally written by Joey Hess and Craig Small.
-# As a special exception, when this file is copied by dh-make into a
-# dh-make output file, you may use that output file without restriction.
-# This special exception was added by Craig Small in version 0.37 of dh-make.
-
-# Uncomment this to turn on verbose mode.
-export DH_VERBOSE=1
-
-%:
-	dh $@ --buildsystem cmake 
-override_dh_auto_configure:
-	cmake ./ -DPREFIX=debian/openstructure/usr -DOPTIMIZE=ON -DCOMPOUND_LIB=compounds.chemlib
-override_dh_auto_build:
-	make -j6
-override_dh_auto_install:
-	make install
-	rm debian/openstructure/usr/bin/ldt
-	mkdir -p debian/openstructure-dev/usr
-	mv debian/openstructure/usr/include debian/openstructure-dev/usr/
-	mkdir -p debian/openstructure/usr/share/pixmaps/
-	cp modules/gui/share/images/logo-small.png debian/openstructure/usr/share/pixmaps/openstructure.png
-	mkdir -p debian/openstructure/usr/share/applications/
-	cp debian/openstructure.desktop debian/openstructure/usr/share/applications/
-	desktop-file-validate debian/openstructure/usr/share/applications/openstructure.desktop
diff --git a/deployment/linux/debian/debian/source/format b/deployment/linux/debian/debian/source/format
deleted file mode 100644
index c3d9f2407417795889250717d7b519eadd8373e6..0000000000000000000000000000000000000000
--- a/deployment/linux/debian/debian/source/format
+++ /dev/null
@@ -1,2 +0,0 @@
-3.0 (quilt)
-
diff --git a/deployment/linux/debian/debian/source/include-binaries b/deployment/linux/debian/debian/source/include-binaries
deleted file mode 100644
index e2a64033aea5f1dda66b509afe7ee03c8d40095e..0000000000000000000000000000000000000000
--- a/deployment/linux/debian/debian/source/include-binaries
+++ /dev/null
@@ -1 +0,0 @@
-compounds.chemlib
diff --git a/deployment/linux/fedora/openstructure.desktop b/deployment/linux/fedora/openstructure.desktop
deleted file mode 100644
index 5da5cfab6fa466c91de1e5be5cf5073448ad72dd..0000000000000000000000000000000000000000
--- a/deployment/linux/fedora/openstructure.desktop
+++ /dev/null
@@ -1,8 +0,0 @@
-[Desktop Entry]
-Name=OpenStructure
-GenericName=Open-Source Computational Structural Biology Framework
-Exec=dng
-Icon=openstructure
-Terminal=false
-Type=Application
-Categories=Science;
diff --git a/deployment/linux/fedora/openstructure.spec b/deployment/linux/fedora/openstructure.spec
deleted file mode 100644
index 3d27b5deac2b8e299e1ab1406900a722347866be..0000000000000000000000000000000000000000
--- a/deployment/linux/fedora/openstructure.spec
+++ /dev/null
@@ -1,82 +0,0 @@
-Name:           openstructure
-Version:        1.1 
-Release:        0.1d%{?dist}
-Summary:        Open-source computational structural biology framework
-
-
-# The entire source code is LGPLv3 except the following files:
-# modules/db/src/sqlite3.h, modules/db/src/sqlite.c
-# which have no license
-License:        LGPLv3 and unlicensed    
-URL:            www.openstructure.org 
-# The source for this package was pulled from upstream's git.  Use the
-# following commands to generate the tarball:
-#  git clone https://dng.biozentrum.unibas.ch/git/ost.git openstructure-1.1d
-#  cp /import/bc2/home/schwede/GROUP/OpenStructure/compounds.chemlib \
-#     openstructure-1.1d/
-#  tar -cJvf openstructure-1.1d.tar.xz openstructure-1.1d
-Source0: %{name}-%{version}d.tar.xz       
-Source1: %{name}.desktop
-
-BuildRequires: boost-devel,fftw-devel,eigen2-devel,libtiff-devel,libpng-devel,sip-devel,PyQt4-devel,cmake,desktop-file-utils
-Requires: sip,PyQt4     
-
-%description
-The Openstructure  project aims to provide an open-source, modular, flexible,
-molecular modelling and visualization environment. It is targeted at
-interested method developers in the field of structural bioinformatics.
-
-%prep
-%setup -n openstructure-1.1d
-
-%build
-%cmake . -DPREFIX=%{buildroot}/usr -DOPTIMIZE=ON -DCOMPOUND_LIB=compounds.chemlib
-make %{?_smp_mflags}
-
-%install
-rm -rf %{buildroot}
-make install 
-mkdir -p %{buildroot}/%{_defaultdocdir}/%{name}-%{version}
-mkdir -p %{buildroot}/%{_datadir}/pixmaps
-cp LICENSE.txt %{buildroot}/%{_defaultdocdir}/%{name}-%{version}/
-cp ReadMe.txt %{buildroot}/%{_defaultdocdir}/%{name}-%{version}/
-cp modules/gui/share/images/logo-small.png %{buildroot}/%{_datadir}/pixmaps/openstructure.png
-rm %{buildroot}/%{_bindir}/ldt
-desktop-file-install --dir=%{buildroot}/%{_datadir}/applications %{SOURCE1}
-
-%post -p /sbin/ldconfig
-
-%postun -p /sbin/ldconfig
-
-%files
-%defattr(-,root,root,-)
-%{_bindir}/*
-%{_libdir}/libost*
-%{_libdir}/openstructure
-%{_datadir}/openstructure
-%{_datadir}/applications/*
-%{_datadir}/pixmaps/*
-
-%doc
-%{_defaultdocdir}/%{name}-%{version}/LICENSE.txt
-%{_defaultdocdir}/%{name}-%{version}/ReadMe.txt
-
-%changelog
-* Wed Jul 20 2011 Valerio Mariani <valerio.mariani@unibas.ch> 1.1-1d
-- Initial release
-
-
-
-
-%package devel
-Summary:        Open-source computational structural biology framework
-Requires:       openstructure
-
-%description devel
-The Openstructure  project aims to provide an open-source, modular, flexible,
-molecular modelling and visualization environment. It is targeted at
-interested method developers in the field of structural bioinformatics.
-
-%files devel
-%{_includedir}/*
-
diff --git a/deployment/linux/reset_repository.py b/deployment/linux/reset_repository.py
deleted file mode 100644
index 6ac0809e34a767ff7ff16febd6d392b95e31861f..0000000000000000000000000000000000000000
--- a/deployment/linux/reset_repository.py
+++ /dev/null
@@ -1,13 +0,0 @@
-import subprocess
-import os
-
-currdir=os.getcwd()
-if currdir.find('deployment')==-1 or currdir.find('linux')==-1:
-  print '\n'
-  print 'ERROR: Please run this script from the deployment/linux directory'
-  print '\n'
-  sys.exit()
-
-subprocess.call('rm -fr scripts/ost_config.in.pre*',shell=True,cwd='../../')
-subprocess.call('mv scripts/ost_config.in.backup scripts/ost_config.in',shell=True,cwd='../../')
-
diff --git a/deployment/macos/deploy.py b/deployment/macos/deploy.py
index de10ec84cfcce14a8a158f15338b7366caad9a05..611cad64698dd8b3730a63585abb7300c77279c2 100644
--- a/deployment/macos/deploy.py
+++ b/deployment/macos/deploy.py
@@ -29,6 +29,7 @@ if opts.bundle:
   shutil.copytree('../../examples', 'DNG.app/Contents/examples')
   os.system('rm `find DNG.app/Contents/examples/ -name "*.pyc"` 2> /dev/null')
   os.system('rm -rf DNG.app/Contents/examples/code_fragments/')
+  os.system('rm -rf DNG.app/Contents/examples/gfx/')
   if opts.dmg:
     os.system('rm -rf openstructure-%s.dmg' % ost.VERSION)
     os.system('hdiutil create -srcFolder DNG.app openstructure-%s.dmg' % ost.VERSION)
diff --git a/deployment/macos/deps.py b/deployment/macos/deps.py
index 6c699b92eaee6f96a0a9028cfdd98b3a5c04c08c..91ef55c9ada53c569dcf76fde350f57f8161f9e6 100644
--- a/deployment/macos/deps.py
+++ b/deployment/macos/deps.py
@@ -50,7 +50,7 @@ def collect_deps(stage_dir, components, binaries, libexec_binaries,
     if bin_name not in pool:
       _deps_for_lib(bin_name, pool)
   for bin in libexec_binaries:
-    bin_name=os.path.abspath(os.path.join(stage_dir, 'libexec', libexec_path,
+    bin_name=os.path.abspath(os.path.join(stage_dir, 'libexec/openstructure',
                                           bin))
     if not os.path.exists(bin_name):
       print 'WARNING:', bin_name, 'does not exist'
@@ -71,7 +71,7 @@ def collect_deps(stage_dir, components, binaries, libexec_binaries,
 LIBEXEC_SCRIPTS=['ost_config']
 LIBEXEC_BINARIES=[]
 GUI_LIBEXEC_BINARIES=['gosty']
-BINARIES=['ldt', 'chemdict_tool', 'tmalign', 'tmscore']
+BINARIES=['lddt', 'chemdict_tool', 'tmalign', 'tmscore']
 GUI_BINARIES=[]
 GUI_COMPONENTS=['gfx', 'gui', 'info']
 COMPONENTS=['mol', 'geom', 'conop', 'seq_alg', 'seq',
diff --git a/doc/make.py b/doc/make.py
index 8fb157390b4e6635dde1d68e890b2fe2d8be868b..71f2dc1bc3cf004cd56fe7f3229434438122a5ab 100644
--- a/doc/make.py
+++ b/doc/make.py
@@ -1,14 +1,22 @@
+'''Documentation build on sphinx - please run from root dir by calling ost doc/make.py'''
+
 import os, sys, re
 import shutil
 from ost import settings
 from optparse import OptionParser
-
+import subprocess
 
 if len(sys.argv)==2:
   root_dir=sys.argv[1]
 else:
   root_dir='.'
 
+def _CheckCall(cmd, shell):
+  r = subprocess.call(cmd, shell=True)
+  if r != 0:
+    sys.stderr.write("Command '%s' returned non-zero exit status %d\n"%(cmd, r))
+    sys.exit(-1)
+
 def _OutputPath(inpath, outdir):
   parts=inpath.split(os.path.sep)
   filtered_parts=[outdir]
@@ -86,17 +94,24 @@ if opts.quiet:
 
 for sub_dir in ('modules',):
   os.path.walk(sub_dir, _CollectRstDocs, 'doc/source')
-sphinx_bin=settings.Locate(['sphinx-build', 'sphinx-build-2.6'])
+sphinx_bin=settings.Locate(['sphinx-build', 'sphinx-build-2.6','sphinx-build-2.7'])
 
 if opts.html:
-  os.system('%s %s -b html -c %s %s %s' % (sphinx_bin, opt_str, 'doc/conf', 'doc/source', 
-                                      'doc/build/html'))
+  cmd='%s %s -b html -c %s %s %s' % (sphinx_bin, opt_str, 
+                                     'doc/conf', 'doc/source', 'doc/build/html')
+  print cmd
+  _CheckCall(cmd, shell=True)
+
 if opts.doctest:
-  os.system('%s %s -b doctest -c %s %s %s' % (sphinx_bin, opt_str, 'doc/conf', 'doc/source', 
-                                      'doc/build/doctest'))
+  cmd='%s %s -b doctest -c %s %s %s' % (sphinx_bin, opt_str, 
+                                        'doc/conf', 'doc/source', 
+                                        'doc/build/doctest')
+  _CheckCall(cmd, shell=True)
 if opts.build_json:
-  os.system('%s %s -b json -c %s %s %s' % (sphinx_bin, opt_str, 'doc/conf', 'doc/source',
-                                      'doc/build/json'))
+  cmd='%s %s -b json -c %s %s %s' % (sphinx_bin, opt_str, 'doc/conf', 
+                                     'doc/source', 'doc/build/json')
+  _CheckCall(cmd, shell=True)
 if opts.linkcheck:
-  os.system('%s %s -b linkcheck -c %s %s %s' % (sphinx_bin, opt_str, 'doc/conf', 'doc/source', 
-                                      'doc/build/check'))
+  cmd='%s %s -b linkcheck -c %s %s %s' % (sphinx_bin, opt_str, 'doc/conf', 
+                                          'doc/source', 'doc/build/check')
+  _CheckCall(cmd, shell=True)
diff --git a/doxygen/Doxyfile b/doxygen/Doxyfile
index 9a12a6fd10e192dba8e333bd3ff0f0ede284ca5c..064ced94d988ffc3424b71c1da9572582860fa4c 100644
--- a/doxygen/Doxyfile
+++ b/doxygen/Doxyfile
@@ -252,4 +252,4 @@ DOT_CLEANUP            = YES
 #---------------------------------------------------------------------------
 # Configuration::additions related to the search engine   
 #---------------------------------------------------------------------------
-SEARCHENGINE           = NO
+SEARCHENGINE           = YES
diff --git a/examples/code_fragments/entity/gfx_symmetry.py b/examples/code_fragments/entity/gfx_symmetry.py
index a0d795ece75923058688a6a3ebabc2c9a3f8012e..c45e4d7507ff44bcba936da559a3e894ec10f98a 100644
--- a/examples/code_fragments/entity/gfx_symmetry.py
+++ b/examples/code_fragments/entity/gfx_symmetry.py
@@ -6,9 +6,9 @@ if len(sys.argv)>1:
   filename=sys.argv[1]
 ent=io.LoadEntity(filename)
 
-edi=ent.RequestXCSEditor()
+edi=ent.EditXCS()
 m=geom.Mat4()
-m.PasteTranslation(-ent.GetGeometricStart())
+m.PasteTranslation(-ent.bounds.min)
 edi.ApplyTransform(m)
 edi.UpdateICS()
 frag=gfx.Entity('frag', ent)
diff --git a/examples/code_fragments/entity/superpose.py b/examples/code_fragments/entity/superpose.py
index 78dfb87e2440a4d109937e4d9e1e36ff6e3ad4e0..02ea214bc1c83fa02489b33e2ab7e363536e7500 100644
--- a/examples/code_fragments/entity/superpose.py
+++ b/examples/code_fragments/entity/superpose.py
@@ -20,7 +20,7 @@ g=gfx.Entity("second", ev_b)
 scene.Add(g)
 h=gfx.Entity("first",ev_a)
 scene.Add(h)
-h.SetColor(gfx.Color(0x0000ff), '')
-g.SetColor(gfx.Color(0xff0000), '')
+h.SetColor(gfx.RED)
+g.SetColor(gfx.BLUE)
 scene.CenterOn(g)
 
diff --git a/examples/code_fragments/misc/roll_helix.py b/examples/code_fragments/misc/roll_helix.py
index 482a89c2205027121ecb3199172d63cf3f0475a7..cd8eb9d4170b0d4572176ae86a58f61c5951d832 100644
--- a/examples/code_fragments/misc/roll_helix.py
+++ b/examples/code_fragments/misc/roll_helix.py
@@ -3,7 +3,7 @@ import math
 e=io.LoadEntity('../entity/sdh.pdb')
 c=e.FindChain('A')
 
-edi=e.RequestICSEditor(mol.EditMode.BUFFERED_EDIT)
+edi=e.EditXCS(mol.EditMode.BUFFERED_EDIT)
 for r in c.GetResidueList():
   phi=r.GetPhiTorsion()
   psi=r.GetPsiTorsion()
diff --git a/examples/code_fragments/misc/strip_sidechains.py b/examples/code_fragments/misc/strip_sidechains.py
index 4359ba1f7a830e34f7b90b591e7895c2efa2eb86..e86e345e2f0de1719dbbceeeb312c5ffdf0d7585 100644
--- a/examples/code_fragments/misc/strip_sidechains.py
+++ b/examples/code_fragments/misc/strip_sidechains.py
@@ -9,7 +9,7 @@ def StripSidechain(edi, residue):
       edi.DeleteAtom(atom)
 
 def StripSidechains(entity):
-  edi=entity.RequestXCSEditor(mol.EditMode.BUFFERED_EDIT)
+  edi=entity.EditXCS(mol.EditMode.BUFFERED_EDIT)
   for c in e.GetChainList():
     residues=c.GetResidueList()
     for residue in residues:
diff --git a/examples/code_fragments/seq/sh2.aln b/examples/code_fragments/seq/sh2.aln
new file mode 100644
index 0000000000000000000000000000000000000000..98002530eb12d258e805b3bf64a1902fc05d9008
--- /dev/null
+++ b/examples/code_fragments/seq/sh2.aln
@@ -0,0 +1,209 @@
+CLUSTAL 2.0.12 multiple sequence alignment
+
+
+SH2                         -------------------------KP-HPWFFGKIPRAKAEEMLSKQR- 23
+UniRef90_UPI0000EB201F      KAELNGKDGFIPKN-------YIEMKP-HPWFFGKIPRAKAEEMLSKQR- 45
+UniRef90_P62993             KAELNGKDGFIPKN-------YIEMKP-HPWFFGKIPRAKAEEMLSKQR- 78
+UniRef90_P87379             KAELNGKDGFIPKN-------YIEMKA-HPWFFGKIPRAKAEEMLGKQR- 78
+UniRef90_UPI00016E653C      KAELRGKDGFIPKN-------YIEMKA-HPWFYGKIPRAKAEEILNKQR- 78
+UniRef90_UPI00016E653B      KAELRGKDGFIPKN-------YIEMKA-HPWFYGKIPRAKAEEILNKQR- 78
+UniRef90_Q4T656             DQALS-FASLLPVS-------FSAC---CRWFYGKIPRAKAEEILNKQR- 75
+UniRef90_UPI0001555716      KAELNGKDGFIPKN-------YIEMKP-HLWFFGKIPRAYAEEMLGKQL- 388
+UniRef90_UPI000180AF26      KAEQDGKEGLVPMN-------YIQMKP-CEWFARNMTRANAELRL-KNA- 52
+UniRef90_UPI000180AF37      KAEQDGKEGLVPMN-------YIEIKE-CEWFARNMTRANAELRL-KNT- 77
+UniRef90_A8XPY6             KAELDGTEGFIPSN-------YIRMGD-CSWYLGKITRNDAEVLLKKSNV 79
+UniRef90_P29355             KAELDGNEGFIPSN-------YIRMTE-CNWYLGKITRNDAEVLLKKPTV 79
+UniRef90_UPI000186E6C5      RAELDSKEGLIPSN-------YIEMKN-HDWYYGRITRADAEKLLMNK-- 77
+UniRef90_Q08012             RAELDGKEGLIPSN-------YIEMKN-HDWYYGRITRADAEKLLSNK-- 77
+UniRef90_B7P0R2             RAELDSKEGLIPSN-------YIEMKK-HDWYYGRITRADAEKLLSNK-- 77
+UniRef90_D3PIQ8             RAESGGKEGLIPSN-------YIDMKP-HDWYYSRMTRATAEKLLSNK-- 77
+UniRef90_C4WWT7             RAEFEGKEGLIPSN-------YIEMKN-HDWYYGKITRADAEKLLDQQ-- 77
+UniRef90_UPI0000586DB6      -------------------------------------RDGAEELLKND-- 40
+UniRef90_UPI0001CBA623      KAELDGREGFIPKN-------YITMRP-HDWFHGKISRAKAEELLQLQP- 78
+UniRef90_UPI0001CBA624      NAELDGREGLIPKN-------YIEMKP-HEWFHGKISREKAEELLQLQS- 77
+UniRef90_UPI000192619C      KAEQNGKEGFVPKN-------YIQMKP-HSWYYGKIRRSEAEQLLLQEP- 52
+UniRef90_UPI0000521DDC      RAEIDGRMGLVPKN-------YIELKA-HDWYHGKISRVKAEQSLNKPHY 79
+UniRef90_C1LZF7             LAEQEGRTGLIPCN-------YITMRP-HPWYIRHCSRMEAEERLQEIDQ 79
+UniRef90_UPI0000E478D2      LAHQGAKQGLVPEN-------YLKIEKSHPWYVGKISRKVAEEYLMSMP- 80
+UniRef90_UPI0000E49A1C      ----------MGPK-------HTYPEIAMAWFFPTITRKNAELLLMQE-- 31
+UniRef90_A8E5T1             KAELFGREGYIPKN-------YIKVKP-HPWYAGRISRQVAEEILLKRNF 79
+UniRef90_C1C3T6             KAELKGQEGYIPKN-------YIKVKP-HPWYAGRISRQVAEEILLKKRF 79
+UniRef90_Q13588             KAELRGVEGFIPKN-------YIRVKP-HPWYSGRISRQLAEEILMKRNH 79
+UniRef90_UPI0001C606E3      KAELRGAEGFVPKN-------YIHIKP-HPWYSGRISRQLAEEILMKRNQ 79
+UniRef90_Q9CX99             KAELRGAEGFVPKN-------YIRVKP-HPWYSGRISRQLAEETLMKRNH 79
+UniRef90_UPI0000DA3575      GVGLKPIEGMRPTNRTXRIPADIVPSP-HRWYSGRISRQLAEETLMKRNH 86
+UniRef90_UPI0000D9440A      KAELRGAEGFIPKN-------YIQVKP-HPWFAGRISRQFAEEILLRRNH 79
+UniRef90_UPI000155C0E1      RTSLLGGESFFYKN-------IQKLSP-SPWYAGRISRQLAEEVLLKRNH 79
+UniRef90_UPI0000E80FCB      KAELYGCEGFVPKN-------YIKVKP-HPWYAGRISRHVAEELLLKRRY 79
+UniRef90_UPI00016E4BE7      TAELHNRKGFVPKN-------YINLRP-HAWFAGRISRSVAESRLRQRE- 78
+UniRef90_Q503S8             TAEFVNRKGYVPKN-------YISLRP-HAWFAGRISRHVAENRLHQRD- 78
+UniRef90_Q4V9Q1             TAELLGRRGYVPKN-------YINVRP-HTWFVGGISRQAAENRLRPLE- 78
+UniRef90_UPI00017B202F      TAEIQGKRGYIPQN-------YISLLP-YPWFVGRVSRLEAEKRLRWQD- 78
+UniRef90_UPI0000E25B42      KAELGSQEGYVPKN-------FIDIQF-PEWFHEGLSRHQAENLLMGKE- 149
+UniRef90_O75791             KAELGSQEGYVPKN-------FIDIQF-PKWFHEGLSRHQAENLLMGKE- 76
+UniRef90_B7Z8F8             RHKLNP---FSSK----------------RWFHEGLSRHQAENLLMGKE- 50
+UniRef90_UPI00005BC6B6      KAELGSQEGYVPKN-------FIEIEF-PEWFHEGLSRHQAESLLMGKE- 76
+UniRef90_O89100             KAELGSQEGYVPKN-------FIDIEF-PEWFHEGLSRHQAENLLMGKD- 76
+UniRef90_UPI0000EDE7DF      KAELKSHEGYVPKN-------FIDIHI-PGWFHEGISRHEAESLLMGKE- 76
+UniRef90_UPI0000F2E19C      KAELGSQEGYVPKN-------FIDIQF-PSWFHEDISRHDAESLLMGKD- 241
+UniRef90_UPI0000E7F8B9      KAELRSQEGYVPKN-------FIDFHV-PPWFDEKISRHEAESILMNKG- 76
+UniRef90_UPI0000ECD2B7      KAELRSQEGYVPKN-------FIDFHV-PPWFDEKISRHEAESILMNKG- 76
+UniRef90_UPI000194E163      KAELRSHEGYVPKN-------FIDFHV-PHWFDEKISRHEAENLLMSKG- 91
+UniRef90_B5X487             KAELHGQEGFVPQN-------YIERQT-PSWFKETASRSSAEELLMSRE- 76
+UniRef90_Q567F1             KAELHGHEGYVPKN-------YVDRQI-PSWFKESASRGSAEETLMSRE- 76
+
+
+SH2                         -------HDGAFLIRESESA--PGDFSL----SVKFGNDVQHFKVLR--D 58
+UniRef90_UPI0000EB201F      -------HDGAFLIRESESA--PGDFSL----SVKFGNDVQHFKVLR--D 80
+UniRef90_P62993             -------HDGAFLIRESESA--PGDFSL----SVKFGNDVQHFKVLR--D 113
+UniRef90_P87379             -------HDGAFLIRESESA--PGDFSL----SVKFGNDVQHFKVLR--D 113
+UniRef90_UPI00016E653C      -------RDGAFLIRESESA--PGDFSL----SVKYGNDVQHFKVLR--D 113
+UniRef90_UPI00016E653B      -------RDGAFLIRESESA--PGDFSL----SVKYGNDVQHFKVLR--D 113
+UniRef90_Q4T656             -------RDGAFLIRESESA--PGDFSL----SVKYGNDVQHFKVLR--D 110
+UniRef90_UPI0001555716      -------NYGSFFILXXXXP--PGDALTGARSTPRFGNDVQHFKVLR--D 427
+UniRef90_UPI000180AF26      -------LDESFLVRESEST--PGDFSL----SVKTNSGVQHFKVLR--D 87
+UniRef90_UPI000180AF37      -------LDGSFLVRESEST--PGEFSV----SVKTNSGVQHFKVLR--D 112
+UniRef90_A8XPY6             -------RDGHFLVRQCESS--PGEFSI----SVRFQDSVQHFKVLR--D 114
+UniRef90_P29355             -------RDGHFLVRQCESS--PGEFSI----SVRFQDSVQHFKVLR--D 114
+UniRef90_UPI000186E6C5      -------HEGAFLIRVSESS--PGDFSL----SVKCSDGVQHFKVLR--D 112
+UniRef90_Q08012             -------HEGAFLIRISESS--PGDFSL----SVKCPDGVQHFKVLR--D 112
+UniRef90_B7P0R2             -------HEGAFLIRVSESS--PGDFSL----SVRCGDGVQHFKVLR--D 112
+UniRef90_D3PIQ8             -------HEGAFVIRVSESS--PGDFSL----SVKCGDGVQHFKVLR--D 112
+UniRef90_C4WWT7             -------PEGCFLVRISESS--PGDFSL----SVKCGDGVQHFKVLR--D 112
+UniRef90_UPI0000586DB6      -------GDGAFLIRESEGT--PGDYSL----SVKFVDGVQHFKVLR--D 75
+UniRef90_UPI0001CBA623      -------HDGAFLIRESESA--PGDFSL----SVKFKDEVQHFKVLR--D 113
+UniRef90_UPI0001CBA624      -------YDGAFLIRESEST--PGDFSL----SVKFKDGVQNFKILR--D 112
+UniRef90_UPI000192619C      -------HDGAYLIRDSEST--AGDFSL----SVKFNNQVQHFKVLR--D 87
+UniRef90_UPI0000521DDC      -------PDGAFLIRESESS--PGDFSL----SVKYGSAVQHFKVLR--D 114
+UniRef90_C1LZF7             ETAQHLQPDGAFILRQSEAD--GKGFSL----SVKQGCEVLHFKVLQ--D 121
+UniRef90_UPI0000E478D2      -------SDGAFMIRDSESNPDSGNFSL----SVKFRDQVQHFKILT--D 117
+UniRef90_UPI0000E49A1C      -------RNGAFLVRRSESS--EGLYSL----SVKYNESVQHFRILQ--D 66
+UniRef90_A8E5T1             --------VGAFLIRDSESS--PGDFSI----SVNYGHHVQHFKVLRDTE 115
+UniRef90_C1C3T6             --------LGAFLIRDSESS--PGEFSI----SVNYGHHVQHFKVLR--E 113
+UniRef90_Q13588             --------LGAFLIRESESS--PGEFSV----SVNYGDQVQHFKVLR--E 113
+UniRef90_UPI0001C606E3      --------LGAFLIRESESS--PGEFSV----SVNYGDQVQHFKVLR--E 113
+UniRef90_Q9CX99             --------LGAFLIRESESS--PGEFSV----SVNYGDQVQHFKVLR--E 113
+UniRef90_UPI0000DA3575      --------LGAFLIRESESS--PGEFSV----SVNYGDQVQHFKVLR--E 120
+UniRef90_UPI0000D9440A      --------LGAFLIRESESS--PGEFSV----SVNYGNQVQHFKVLR--E 113
+UniRef90_UPI000155C0E1      --------LGAFLIRESESS--PGEFSV----SVNYGDQVQHFKVLR--E 113
+UniRef90_UPI0000E80FCB      --------VGAFLIRESESA--PGEFSI----SVNYGQHVQHFKVLR--E 113
+UniRef90_UPI00016E4BE7      --------CGAFLVRESESA--PGEFSM----SVSYGDHVQHFKVLQD-- 112
+UniRef90_Q503S8             --------CGSFLVRESESA--PGEFSM----SVSYGDHVQHFKVLKD-- 112
+UniRef90_Q4V9Q1             --------CGAFLIRESEST--PGEFSV----SVSYGDHVQHFKVLKD-- 112
+UniRef90_UPI00017B202F      --------PGVFLVRESESA--PGEFSV----SVSYGNRVEHFRVLE--- 111
+UniRef90_UPI0000E25B42      --------VGFFIIRASQSS--PGDFSI----SVRHEDDVQHFKVMR--D 183
+UniRef90_O75791             --------VGFFIIRASQSS--PGDFSI----SVRHEDDVQHFKVMR--D 110
+UniRef90_B7Z8F8             --------VGFFIIRASQSS--PGDFSI----SVRHEDDVQHFKVMR--D 84
+UniRef90_UPI00005BC6B6      --------LGCFIIRASQSS--PGDFSI----SVRHEDDVQHFKVMR--D 110
+UniRef90_O89100             --------IGFFIIRASQSS--PGDFSI----SVRHEDDVQHFKVMR--D 110
+UniRef90_UPI0000EDE7DF      --------VGSFIIRASQSS--PGDFSI----SVRHEDDVQHFKVMR--D 110
+UniRef90_UPI0000F2E19C      --------VGSFIIRASQSS--PGDFSI----SVRHEDDVQHFKVMR--D 275
+UniRef90_UPI0000E7F8B9      --------VGSFIVRASQNS--HGDFSI----SVRHEDDVQHFKVMR--D 110
+UniRef90_UPI0000ECD2B7      --------VGSFIVRASQNS--HGDFSI----SVRHEDDVQHFKVMR--D 110
+UniRef90_UPI000194E163      --------VGCFVVRASQNS--HGDFSI----SVRHEDDVQHFKVMR--D 125
+UniRef90_B5X487             --------VGGFLIRGSQSS--PGEFSI----SVRHEFDVQHFKVMK--D 110
+UniRef90_Q567F1             --------VGAFLIRGSQSS--PGDFSI----SVRHDYDVQHFKVMK--D 110
+                                                                   * :*:::
+
+SH2                         GAGKYFLWVVKFNSLNELVDYHRSTSVSR---------------NQQIFL 93
+UniRef90_UPI0000EB201F      GAGKYFLWVVKFNSLNELVDYHRSTSVSR---------------NQQIFL 115
+UniRef90_P62993             GAGKYFLWVVKFNSLNELVDYHRSTSVSR---------------NQQIFL 148
+UniRef90_P87379             GAGKYFLWVVKFNSLNELVDYHRSTSVSR---------------NQQIFL 148
+UniRef90_UPI00016E653C      GAGKYFLWVVKFNSLNELVEYHRTTSVSR---------------NQQIFL 148
+UniRef90_UPI00016E653B      GAGKYFLWVVKFNSLNELVEYHRTTSVSR---------------NQQIFL 148
+UniRef90_Q4T656             GAGKYFLWVVKFTSLNELVEYHRTTSVSR---------------NQQIFL 145
+UniRef90_UPI0001555716      GAGKYFLWVVKFNSLNELVDYHRSTSVSR---------------NQQIFL 462
+UniRef90_UPI000180AF26      GAGKYFIWLVKFKSLNQLVDYHRTSSVSR---------------SEQILL 122
+UniRef90_UPI000180AF37      GAGKYFIWVVKFSSLNELVVYHRVMTVSG---------------SERIFL 147
+UniRef90_A8XPY6             QNGKYYLWAVKFNSLNELVAYHRTASVSR---------------THTILL 149
+UniRef90_P29355             QNGKYYLWAVKFNSLNELVAYHRTASVSR---------------THTILL 149
+UniRef90_UPI000186E6C5      AQGKFFLWVVKFSSLNELVEYHRTSSVSR---------------SQHVKL 147
+UniRef90_Q08012             AQSKFFLWVVKFNSLNELVEYHRTASVSR---------------SQDVKL 147
+UniRef90_B7P0R2             TLGKFFLWVVKFASLNELVEYHRSASVSR---------------SQDIKL 147
+UniRef90_D3PIQ8             GQGKFFLWVVKFNSLNELVEYHHSASVSR---------------SQDIKL 147
+UniRef90_C4WWT7             AQAKFFLWVVKFDSLNELVDYHRESSVSR---------------SQDVRL 147
+UniRef90_UPI0000586DB6      GAGKYFLWVVKFNSLNQLVEYHRTSSVSR---------------SQTIYL 110
+UniRef90_UPI0001CBA623      GAGKYFLWVVKFNSLNELVEYHRSSSVSR---------------TQTIYL 148
+UniRef90_UPI0001CBA624      GAGKYFLWVVKFNSLNQLVDYHRTSSVSR---------------SEQIFL 147
+UniRef90_UPI000192619C      GAGKYFLWVVKFNSLNQLVEYHRAASVSR---------------SQTIYL 122
+UniRef90_UPI0000521DDC      GAGKYFLWVVKFSSLNELIKYHREQSISR---------------TQQIML 149
+UniRef90_C1LZF7             EAGKYFFWLSKFDSINQLIDHHRKTSISR---------------NRLLTL 156
+UniRef90_UPI0000E478D2      LAGKYFLWVVKFTSINDLVDYHKDNSVSRTQEIVLNEPCVPIEDANQRPQ 167
+UniRef90_UPI0000E49A1C      TAGKFHLWIVKFPSLDALVDYYRTTSVTR---------------ENQVST 101
+UniRef90_A8E5T1             SNGKYYLWEAKFNSLNELVDYYRRHSIAK---------------FHEVFL 150
+UniRef90_C1C3T6             KSGTYFLWETKFGSLNELVEFYRSSSIAK---------------THPVLL 148
+UniRef90_Q13588             ASGKYFLWEEKFNSLNELVDFYRTTTIAK---------------KRQIFL 148
+UniRef90_UPI0001C606E3      ASGKYFLWEEKFNSLNELVDFYRTTTIAK---------------KRQIFL 148
+UniRef90_Q9CX99             ASGKYFLWEEKFNSLNELVDFYRTTTIAK---------------RRQIFL 148
+UniRef90_UPI0000DA3575      ASGKYFLWEEKFNSLNELVDFYRTTTIAK---------------RRQIFL 155
+UniRef90_UPI0000D9440A      NMGKYFLWEEKFNSLNELVDFYRTTTIAK---------------KKQIFL 148
+UniRef90_UPI000155C0E1      RIGKYYLWEEKFNSLNELVDFYRTTTIAK---------------KKQIFL 148
+UniRef90_UPI0000E80FCB      RNGKYFLWEEKFNSLNELVDFYRTTTIAK---------------KQQIFL 148
+UniRef90_UPI00016E4BE7      RGGQYYVWDELFPSLNELVEFYHCNSIAR---------------ERTVLL 147
+UniRef90_Q503S8             REGYYFVWEEIFPSLNQLVDFYKTNSIAK---------------ERTVFL 147
+UniRef90_Q4V9Q1             GLGQYFIWDEVFSSLNQLVDFYRINSIAK---------------ERTVFL 147
+UniRef90_UPI00017B202F      GGGQYCIWEESFCSLNRLVDFYRTHSIAM---------------DKVVCL 146
+UniRef90_UPI0000E25B42      NKGNYFLWTEKFPSLNKLVDYYRTNSISR---------------QKQIFL 218
+UniRef90_O75791             NKGNYFLWTEKFPSLNKLVDYYRTNSISR---------------QKQIFL 145
+UniRef90_B7Z8F8             NKGNYFLWTEKFPSLNKLVDYYRTNSISR---------------QKQIFL 119
+UniRef90_UPI00005BC6B6      NKGNYFLWTEKFPSLNKLVDYYRKNSISK---------------QKQIFL 145
+UniRef90_O89100             TKGNYFLWTEKFPSLNKLVDYYRTTSISK---------------QKQVFL 145
+UniRef90_UPI0000EDE7DF      AKGHYFLWTEKFQSLNRLVEFYKTSSISR---------------QKQIFL 145
+UniRef90_UPI0000F2E19C      AKGHYFLWTEKFQSLNQLVNFYRTSSISK---------------QKQIYL 310
+UniRef90_UPI0000E7F8B9      SKGNYYLWTEKFYSLNKLVDYYRTSTISR---------------QKQILL 145
+UniRef90_UPI0000ECD2B7      SKGNYYLWTEKFYSLNKLVDYYRTSTISR---------------QKQILL 145
+UniRef90_UPI000194E163      SKGSYYLWTEKFHSLNKLVDYYKTSSISR---------------QKQIFL 160
+UniRef90_B5X487             SKGHYFLWSEKFTSLNKLVDFYKNTSISK---------------QRDIYL 145
+UniRef90_Q567F1             KSGHYYLWTEKFTSLNKLVDFYKTTSISK---------------QKEIFL 145
+                              . : .*   * *:: *: .::  :::                 .
+
+SH2                         RDIEQVP------------------------------------------- 100
+UniRef90_UPI0000EB201F      RDIEQVPQQNSIFSLCQR----TSLTLCSIVSLEASEEENPVVREWSPHS 161
+UniRef90_P62993             RDIEQVP------------------------------------------- 155
+UniRef90_P87379             RDIEQVPQVHGGDRATS--------------------------------- 165
+UniRef90_UPI00016E653C      REIEQ--------------------------------------------- 153
+UniRef90_UPI00016E653B      REIEQVTQVNVGTHYIN--------------------------------- 165
+UniRef90_Q4T656             RDIEQVTQV----------------------------------------- 154
+UniRef90_UPI0001555716      RDIEQMPQQKSPVCDRLS----FLFCAVNCRACSDGVFHG---------- 498
+UniRef90_UPI000180AF26      RHPIIS-------------------------------------------- 128
+UniRef90_UPI000180AF37      LHPIS--------------------------------------------- 152
+UniRef90_A8XPY6             ADMNV--------------------------------------------- 154
+UniRef90_P29355             SDMNV--------------------------------------------- 154
+UniRef90_UPI000186E6C5      RDMVP--------------------------------------------- 152
+UniRef90_Q08012             RDMIP--------------------------------------------- 152
+UniRef90_B7P0R2             RDMHP--------------------------------------------- 152
+UniRef90_D3PIQ8             KEIIC--------------------------------------------- 152
+UniRef90_C4WWT7             RDMPAATQNG---------------------------------------- 157
+UniRef90_UPI0000586DB6      KDRKS--------------------------------------------- 115
+UniRef90_UPI0001CBA623      LKMHV--------------------------------------------- 153
+UniRef90_UPI0001CBA624      KDKQ---------------------------------------------- 151
+UniRef90_UPI000192619C      KDMTN--------------------------------------------- 127
+UniRef90_UPI0000521DDC      VDLPV--------------------------------------------- 154
+UniRef90_C1LZF7             VDLVPSKRFPTN-------------------------------------- 168
+UniRef90_UPI0000E478D2      PAMQQSR------------------------------------------- 174
+UniRef90_UPI0000E49A1C      QSVEQWS------------------------------------------- 108
+UniRef90_A8E5T1             CDEEQ--------------------------------------------- 155
+UniRef90_C1C3T6             RDEEE--------------------------------------------- 153
+UniRef90_Q13588             RDEEP--------------------------------------------- 153
+UniRef90_UPI0001C606E3      RDEEP--------------------------------------------- 153
+UniRef90_Q9CX99             CDEQP--------------------------------------------- 153
+UniRef90_UPI0000DA3575      CDEQP--------------------------------------------- 160
+UniRef90_UPI0000D9440A      RDEEP--------------------------------------------- 153
+UniRef90_UPI000155C0E1      RDEEQ--------------------------------------------- 153
+UniRef90_UPI0000E80FCB      RDDEQ--------------------------------------------- 153
+UniRef90_UPI00016E4BE7      RDPEQ--------------------------------------------- 152
+UniRef90_Q503S8             RDLDH--------------------------------------------- 152
+UniRef90_Q4V9Q1             RDPEG--------------------------------------------- 152
+UniRef90_UPI00017B202F      RDPPS--------------------------------------------- 151
+UniRef90_UPI0000E25B42      RDRTREDQGHRGNSLDR---RSQGGPHLSGAVGEEIRPSMNRKLSDHPPT 265
+UniRef90_O75791             RDRTREDQGHRGNSLDR---RSQGGPHLSGAVGEEIRPSMNRKLSDHPPT 192
+UniRef90_B7Z8F8             RDRTREDQGHRGNSLDR---RSQGGPHLSGAVGEEIRPSMNRKLSDHPPT 166
+UniRef90_UPI00005BC6B6      RDRTREEQGQRGNSLDR---RSQGGHPLSGAVGEEIRPSMNRKPSDHP-L 191
+UniRef90_O89100             RDGTQ-DQGHRGNSLDR---RSQGGPHPSGTVGEEIRPSVNRKLSDHLPL 191
+UniRef90_UPI0000EDE7DF      RDGTREDQERRGGSLDR---RAQEGLGLGGACGEEIRVPMNRKMSDLHPP 192
+UniRef90_UPI0000F2E19C      RDGGREEQDRWGGSLER---RLQEGLHISGGVGEETRPSTNRKQSDHPPA 357
+UniRef90_UPI0000E7F8B9      RDDSREEKERRGGSLER---MSRDGLHVGGAAAEAHS-SMSKRYVDHP-- 189
+UniRef90_UPI0000ECD2B7      RDDSREEKERRGGSLER---MSRDGLHVGGAAAEAHS-SMSKRYVDHPVP 191
+UniRef90_UPI000194E163      RDNSQEEKERHGGSLER---IGREGFHMGGAAGEDHS-SISKRYVEYPIP 206
+UniRef90_B5X487             RDGSRDDQSPSTPQPLKRGSLPEERS-----YGAPTAATSHRRASDLP-- 188
+UniRef90_Q567F1             RDGSGDE--PRAPPPIK--SQPEVRPPPGGGYGSPQTSSQNRSTTDPT-- 189
diff --git a/examples/code_fragments/trj/test_trj.py b/examples/code_fragments/trj/test_trj.py
index 0c3ed1f310eacb6e6e2a2dcc03af26a3aa077258..a1625996c109ed4272a2d8439219b9e7d583db61 100644
--- a/examples/code_fragments/trj/test_trj.py
+++ b/examples/code_fragments/trj/test_trj.py
@@ -16,9 +16,8 @@ class Anim(QtCore.QTimer):
         go.UpdatePositions()
 
 
-# old-style CHARMM format, requires flag bit 0 set
-cg = io.LoadCHARMMTraj("mpor_trj.crd","mpor_trj_short.trj",1)
-eh=cg.GetEntity()
+eh = io.LoadCRD("mpor_trj.crd")
+cg = io.LoadCHARMMTraj(eh,"mpor_trj_short.trj")
 go=gfx.Entity("test",eh.CreateFullView())
 
 scene.Add(go)
diff --git a/examples/dssp_sa.py b/examples/dssp_sa.py
deleted file mode 100644
index 23369a99e7d18b74c2623150773687823666827a..0000000000000000000000000000000000000000
--- a/examples/dssp_sa.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from ost.bindings import dssp
-ent=io.LoadMMCIF('1ake.cif')
-dssp.AssignDSSP(ent, extract_burial_status=True)
-for chain in ent.chains:
-  if chain.is_polypeptide:
-    for res in chain.residues:
-      print res.GetFloatProp('relative_solvent_accessibility')
diff --git a/modules/base/pymod/export_logger.cc b/modules/base/pymod/export_logger.cc
index 446d041166e3695c7a63578ff223ef966e78f2fb..3b8b4b6615495c03bc809aaa013bc11d505b10ed 100644
--- a/modules/base/pymod/export_logger.cc
+++ b/modules/base/pymod/export_logger.cc
@@ -132,7 +132,16 @@ object log_verbose(tuple args, dict kwargs)
   LOG_VERBOSE(args_to_string(args, kwargs));
   return object();  
 }
-
+object log_debug(tuple args, dict kwargs) 
+{
+  LOG_DEBUG(args_to_string(args, kwargs));
+  return object();  
+}
+object log_trace(tuple args, dict kwargs) 
+{
+  LOG_TRACE(args_to_string(args, kwargs));
+  return object();  
+}
 
 void reset_sinks()
 {
@@ -177,6 +186,8 @@ void export_Logger()
   def("LogInfo", raw_function(log_info, 1));
   def("LogScript", raw_function(log_script, 1));
   def("LogVerbose", raw_function(log_verbose, 1));
+  def("LogDebug", raw_function(log_debug, 1));
+  def("LogTrace", raw_function(log_trace, 1));
   
   // this relatively ugly construct is required to work around a problem with
   // the "ost" command-line interpreter. If we don't remove all the sinks from
diff --git a/modules/base/pymod/table.py b/modules/base/pymod/table.py
index 4bd1a9999738a8814554997a7e7ceb6d4e7c6cfe..8af2ab6cc20f088401c9e80038d8bc98e31f8561 100644
--- a/modules/base/pymod/table.py
+++ b/modules/base/pymod/table.py
@@ -258,12 +258,30 @@ class Table(object):
     return type_list
 
   def SetName(self, name):
+    '''
+    Set name of the table
+    :param name: name
+    :type name: :class:`str`
+    '''
     self.name = name
     
   def GetName(self):
+    '''
+    Get name of table
+    '''
     return self.name
 
   def _Coerce(self, value, ty):
+    '''
+    Try to convert values (e.g. from :class:`str` type) to the specified type
+
+    :param value: the value
+    :type value: any type
+
+    :param ty: name of type to convert it to (i.e. *int*, *float*, *string*,
+               *bool*)
+    :type ty: :class:`str`
+    '''
     if value=='NA' or value==None:
       return None
     if ty=='int':
@@ -320,11 +338,23 @@ class Table(object):
   def ToString(self, float_format='%.3f', int_format='%d', rows=None):
     '''
     Convert the table into a string representation.
+
     The output format can be modified for int and float type columns by
     specifying a formatting string for the parameters 'float_format' and
     'int_format'.
+
     The option 'rows' specify the range of rows to be printed. The parameter
-    must be a iterable containing two elements, e.g. [start_row, end_row].
+    must be a type that supports indexing (e.g. a :class:`list`) containing the 
+    start and end row *index*, e.g. [start_row_idx, end_row_idx].
+
+    :param float_format: formatting string for float columns
+    :type float_format: :class:`str`
+
+    :param int_format: formatting string for int columns
+    :type int_format: :class:`str`
+
+    :param rows: iterable containing start and end row *index*
+    :type rows: iterable containing :class:`ints <int>`
     '''
     widths=[len(cn) for cn in self.col_names]
     sel_rows=self.rows
@@ -365,7 +395,26 @@ class Table(object):
   def __str__(self):
     return self.ToString()
   
-  def _AddRowsFromDict(self, d, overwrite=False):
+  def _AddRowsFromDict(self, d, overwrite=None):
+    '''
+    Add one or more rows from a :class:`dictionary <dict>`.
+    
+    If *overwrite* is not None and set to an existing column name, the specified 
+    column in the table is searched for the first occurrence of a value matching
+    the value of the column with the same name in the dictionary. If a matching
+    value is found, the row is overwritten with the dictionary. If no matching
+    row is found, a new row is appended to the table.
+
+    :param d: dictionary containing the data
+    :type d: :class:`dict`
+
+    :param overwrite: column name to overwrite existing row if value in
+                      column *overwrite* matches
+    :type overwrite: :class:`str`
+
+    :raises: :class:`ValueError` if multiple rows are added but the number of
+             data items is different for different columns.
+    '''
     # get column indices
     idxs = [self.GetColIndex(k) for k in d.keys()]
     
@@ -373,13 +422,13 @@ class Table(object):
     old_len = None
     for k,v in d.iteritems():
       if IsScalar(v):
-        d[k] = [v]
-      else:
-        if not old_len:
-          old_len = len(v)
-        elif old_len!=len(v):
-          raise ValueError("Cannot add rows: length of data must be equal " + \
-                           "for all columns in %s"%str(d))
+        v = [v]
+        d[k] = v
+      if not old_len:
+        old_len = len(v)
+      elif old_len!=len(v):
+        raise ValueError("Cannot add rows: length of data must be equal " + \
+                         "for all columns in %s"%str(d))
     
     # convert column based dict to row based dict and create row and add data
     for i,data in enumerate(zip(*d.values())):
@@ -409,18 +458,78 @@ class Table(object):
     """
     Add a row to the table.
     
-    *row* may either be a dictionary or a list-like object.
-    In the case of a dictionary the keys in the dictionary must match the column
-    names. Columns not found in the dict will be initialized to None.
-    Alternatively, if data is a list-like object, the row is initialized from
-    the values in data. The number of items in data must match the number of
-    columns in the table. A :class:`ValuerError` is raised otherwise. The values
-    are added in the order specified in the list, thus, the order of the data
-    must match the columns.
-       
-    If *overwrite* is set and not None (must be set to an existing column name),
-    an existing row is overwritten if the value of column *overwrite* matches.
-    If no matching row is found, a new row is appended to the table.
+    *data* may either be a dictionary or a list-like object:
+
+     - If *data* is a dictionary the keys in the dictionary must match the
+       column names. Columns not found in the dict will be initialized to None.
+       If the dict contains list-like objects, multiple rows will be added, if
+       the number of items in all list-like objects is the same, otherwise a
+       :class:`ValueError` is raised.
+
+     - If *data* is a list-like object, the row is initialized from the values
+       in *data*. The number of items in *data* must match the number of
+       columns in the table. A :class:`ValuerError` is raised otherwise. The
+       values are added in the order specified in the list, thus, the order of
+       the data must match the columns.
+          
+    If *overwrite* is not None and set to an existing column name, the specified 
+    column in the table is searched for the first occurrence of a value matching
+    the value of the column with the same name in the dictionary. If a matching
+    value is found, the row is overwritten with the dictionary. If no matching
+    row is found, a new row is appended to the table.
+
+    :param data: data to add
+    :type data: :class:`dict` or *list-like* object
+
+    :param overwrite: column name to overwrite existing row if value in
+                      column *overwrite* matches
+    :type overwrite: :class:`str`
+
+    :raises: :class:`ValueError` if *list-like* object is used and number of
+             items does *not* match number of columns in table.
+
+    :raises: :class:`ValueError` if *dict* is used and multiple rows are added
+             but the number of data items is different for different columns.
+
+    **Example:** add multiple data rows to a subset of columns using a dictionary
+
+    .. code-block:: python
+
+      # create table with three float columns
+      tab = Table(['x','y','z'], 'fff')
+
+      # add rows from dict
+      data = {'x': [1.2, 1.6], 'z': [1.6, 5.3]}
+      tab.AddRow(data)
+      print tab
+
+      '''
+      will produce the table
+
+      ====  ====  ====
+      x     y     z
+      ====  ====  ====
+      1.20  NA    1.60
+      1.60  NA    5.30
+      ====  ====  ====
+      '''
+
+      # overwrite the row with x=1.2 and add row with x=1.9
+      data = {'x': [1.2, 1.9], 'z': [7.9, 3.5]}
+      tab.AddRow(data, overwrite='x')
+      print tab
+
+      '''
+      will produce the table
+
+      ====  ====  ====
+      x     y     z
+      ====  ====  ====
+      1.20  NA    7.90
+      1.60  NA    5.30
+      1.90  NA    3.50
+      ====  ====  ====
+      '''
     """
     if type(data)==dict:
       self._AddRowsFromDict(data, overwrite)
@@ -448,6 +557,9 @@ class Table(object):
   def RemoveCol(self, col):
     """
     Remove column with the given name from the table
+
+    :param col: name of column to remove
+    :type col: :class:`str`
     """
     idx = self.GetColIndex(col)
     del self.col_names[idx]
@@ -459,38 +571,82 @@ class Table(object):
     """
     Add a column to the right of the table.
     
+    :param col_name: name of new column
+    :type col_name: :class:`str`
+
+    :param col_type: type of new column (long versions: *int*, *float*, *bool*,
+                     *string* or short versions: *i*, *f*, *b*, *s*)
+    :type col_type: :class:`str`
+
+    :param data: data to add to new column.
+    :type data: scalar or iterable
+
+    **Example:**
+
     .. code-block:: python
     
       tab=Table(['x'], 'f', x=range(5))
       tab.AddCol('even', 'bool', itertools.cycle([True, False]))
       print tab
     
-    will produce the table
-    
-    ====  ====
-    x     even
-    ====  ====
-      0   True
-      1   False
-      2   True
-      3   False
-      4   True
-    ====  ====
-      
-    if data is a constant instead of an iterable object, it's value
-    will be written into each row 
+      '''
+      will produce the table
+
+      ====  ====
+      x     even
+      ====  ====
+        0   True
+        1   False
+        2   True
+        3   False
+        4   True
+      ====  ====
+      '''
+
+    If data is a constant instead of an iterable object, it's value
+    will be written into each row:
+
+    .. code-block:: python
+
+      tab=Table(['x'], 'f', x=range(5))
+      tab.AddCol('num', 'i', 1)
+      print tab
+
+      '''
+      will produce the table
+
+      ====  ====
+      x     num
+      ====  ====
+        0   1
+        1   1
+        2   1
+        3   1
+        4   1
+      ====  ====
+      '''
+    
+    As a special case, if there are no previous rows, and data is not 
+    None, rows are added for every item in data.
     """
     col_type = self._ParseColTypes(col_type, exp_num=1)[0]
     self.col_names.append(col_name)
     self.col_types.append(col_type)
-    if IsScalar(data):
-      for row in self.rows:
-        row.append(data)
-    else:
-      for row, d in zip(self.rows, data):
-        row.append(d)
 
+    if len(self.rows)>0:
+      if IsScalar(data):
+        for row in self.rows:
+          row.append(data)
+      else:
+        for row, d in zip(self.rows, data):
+          row.append(d)
 
+    elif data!=None:
+      if IsScalar(data):
+        self.AddRow({col_name : data})
+      else:
+        for v in data:
+          self.AddRow({col_name : v})
 
   def Filter(self, *args, **kwargs):
     """
@@ -601,13 +757,38 @@ class Table(object):
     return cPickle.load(stream)
 
   @staticmethod
-  def Load(stream_or_filename, format='ost', sep=','):
+  def _GuessFormat(filename):
+    try:
+      filename = filename.name
+    except AttributeError, e:
+      pass
+    if filename.endswith('.csv'):
+      return 'csv'
+    elif filename.endswith('.pickle'):
+      return 'pickle'
+    else:
+      return 'ost'
+    
+    
+  @staticmethod
+  def Load(stream_or_filename, format='auto', sep=','):
     """
     Load table from stream or file with given name.
 
-    By default, the file format is *ost* (see below) and is *not* automatically
-    determined (e.g. from file extension). Thus, it *format* must be specified
-    for reading other file formats.
+    By default, the file format is set to *auto*, which tries to guess the file
+    format from the file extension. The following file extensions are
+    recognized:
+    
+    ============    ======================
+    extension       recognized format
+    ============    ======================
+    .csv            comma separated values
+    .pickle         pickled byte stream
+    <all others>    ost-specific format
+    ============    ======================
+    
+    Thus, *format* must be specified for reading file with different filename
+    extensions.
 
     The following file formats are understood:
 
@@ -643,6 +824,9 @@ class Table(object):
     :returns: A new :class:`Table` instance
     """
     format=format.lower()
+    if format=='auto':
+      format = Table._GuessFormat(stream_or_filename)
+      
     if format=='ost':
       return Table._LoadOST(stream_or_filename)
     if format=='csv':
@@ -653,7 +837,13 @@ class Table(object):
 
   def Sort(self, by, order='+'):
     """
-    Performs an in-place sort of the table, based on column.
+    Performs an in-place sort of the table, based on column *by*.
+
+    :param by: column name by which to sort
+    :type by: :class:`str`
+
+    :param order: ascending (``-``) or descending (``+``) order
+    :type order: :class:`str` (i.e. *+*, *-*)
     """
     sign=-1
     if order=='-':
@@ -666,6 +856,12 @@ class Table(object):
   def GetUnique(self, col, ignore_nan=True):
     """
     Extract a list of all unique values from one column
+
+    :param col: column name
+    :type col: :class:`str`
+
+    :param ignore_nan: ignore all *None* values
+    :type ignore_nan: :class:`bool`
     """
     idx = self.GetColIndex(col)
     seen = {}
@@ -704,7 +900,102 @@ class Table(object):
            num_z_levels=10, diag_line=False, labels=None, max_num_labels=None,
            title=None, clear=True, save=False, **kwargs):
     """
-    Plot x against y using matplot lib
+    Function to plot values from your table in 1, 2 or 3 dimensions using
+    `Matplotlib <http://matplotlib.sourceforge.net>`__
+
+    :param x: column name for first dimension
+    :type x: :class:`str`
+
+    :param y: column name for second dimension
+    :type y: :class:`str`
+
+    :param z: column name for third dimension
+    :type z: :class:`str`
+
+    :param style: symbol style (e.g. *.*, *-*, *x*, *o*, *+*, *\**). For a
+                  complete list check (`matplotlib docu <http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.plot>`__).
+    :type style: :class:`str`
+
+    :param x_title: title for first dimension, if not specified it is
+                    automatically derived from column name
+    :type x_title: :class:`str`
+
+    :param y_title: title for second dimension, if not specified it is
+                    automatically derived from column name
+    :type y_title: :class:`str`
+
+    :param z_title: title for third dimension, if not specified it is
+                    automatically derived from column name
+    :type z_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 z_range: start and end value for third dimension (e.g. [start_z, end_z])
+    :type z_range: :class:`list` of length two
+
+    :param color: color for data (e.g. *b*, *g*, *r*). For a complete list check
+                  (`matplotlib docu <http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.plot>`__).
+    :type color: :class:`str`
+
+    :param plot_if: callable which returnes *True* if row should be plotted. Is
+                    invoked like ``plot_if(self, row)``
+    :type plot_if: callable
+
+    :param legend: legend label for data series
+    :type legend: :class:`str`
+
+    :param num_z_levels: number of levels for third dimension
+    :type num_z_levels: :class:`int`
+
+    :param diag_line: draw diagonal line
+    :type diag_line: :class:`bool`
+
+    :param labels: column name containing labels to put on x-axis for one
+                   dimensional plot
+    :type labels: :class:`str`
+
+    :param max_num_labels: limit maximum number of labels
+    :type max_num_labels: :class:`int`
+
+    :param title: plot title, if not specified it is automatically derived from
+                  plotted column names
+    :type title: :class:`str`
+
+    :param clear: clear old data from plot
+    :type clear: :class:`bool`
+
+    :param save: filename for saving plot
+    :type save: :class:`str`
+
+    :param \*\*kwargs: additional arguments passed to matplotlib
+    
+    :returns: the ``matplotlib.pyplot`` module 
+
+    **Examples:** simple plotting functions
+
+    .. code-block:: python
+
+      tab=Table(['a','b','c','d'],'iffi', a=range(5,0,-1),
+                                          b=[x/2.0 for x in range(1,6)],
+                                          c=[math.cos(x) for x in range(0,5)],
+                                          d=range(3,8))
+
+      # one dimensional plot of column 'd' vs. index
+      plt=tab.Plot('d')
+      plt.show()
+
+      # two dimensional plot of 'a' vs. 'c'
+      plt=tab.Plot('a', y='c', style='o-')
+      plt.show()
+
+      # three dimensional plot of 'a' vs. 'c' with values 'b'
+      plt=tab.Plot('a', y='c', z='b')
+      # manually save plot to file
+      plt.savefig("plot.png")
     """
     try:
       import matplotlib.pyplot as plt
@@ -714,7 +1005,7 @@ class Table(object):
       xs = []
       ys = []
       zs = []
-           
+
       if clear:
         plt.figure(figsize=[8, 6])
       
@@ -738,6 +1029,14 @@ class Table(object):
           nice_z = MakeTitle(z)
         else:
           nice_z = None
+
+      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 z_range and (IsScalar(z_range) or len(z_range)!=2):
+        raise ValueError('parameter z_range must contain exactly two elements')
+
       if color:
         kwargs['color']=color
       if legend:
@@ -843,10 +1142,67 @@ class Table(object):
     
   def PlotHistogram(self, col, x_range=None, num_bins=10, normed=False,
                     histtype='stepfilled', align='mid', x_title=None,
-                    y_title=None, title=None, clear=True, save=False):
+                    y_title=None, title=None, clear=True, save=False,
+                    color=None, y_range=None):
     """
     Create a histogram of the data in col for the range *x_range*, split into
-    *num_bins* bins and plot it using matplot lib.
+    *num_bins* bins and plot it using Matplotlib.
+
+    :param col: column name with data
+    :type col: :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 num_bins: number of bins in range
+    :type num_bins: :class:`int`
+
+    :param color: Color to be used for the histogram. If not set, color will be 
+        determined by matplotlib
+    :type color: :class:`str`
+
+    :param normed: normalize histogram
+    :type normed: :class:`bool`
+
+    :param histtype: type of histogram (i.e. *bar*, *barstacked*, *step*,
+                     *stepfilled*). See (`matplotlib docu <http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.hist>`__).
+    :type histtype: :class:`str`
+
+    :param align: style of histogram (*left*, *mid*, *right*). See
+                  (`matplotlib docu <http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.hist>`__).
+    :type align: :class:`str`
+
+    :param x_title: title for first dimension, if not specified it is
+                    automatically derived from column name
+    :type x_title: :class:`str`
+
+    :param y_title: title for second dimension, if not specified it is
+                    automatically derived from column name
+    :type y_title: :class:`str`
+
+    :param title: plot title, if not specified it is automatically derived from
+                  plotted column names
+    :type title: :class:`str`
+
+    :param clear: clear old data from plot
+    :type clear: :class:`bool`
+
+    :param save: filename for saving plot
+    :type save: :class:`str`
+
+    **Examples:** simple plotting functions
+
+    .. code-block:: python
+
+      tab=Table(['a'],'f', a=[math.cos(x*0.01) for x in range(100)])
+
+      # one dimensional plot of column 'd' vs. index
+      plt=tab.PlotHistogram('a')
+      plt.show()
+
     """
     try:
       import matplotlib.pyplot as plt
@@ -854,7 +1210,9 @@ class Table(object):
       
       if len(self.rows)==0:
         return None
-      
+      kwargs={}
+      if color:
+        kwargs['color']=color
       idx = self.GetColIndex(col)
       data = []
       for r in self.rows:
@@ -865,21 +1223,23 @@ class Table(object):
         plt.clf()
         
       n, bins, patches = plt.hist(data, bins=num_bins, range=x_range,
-                                  normed=normed, histtype=histtype, align=align)
+                                  normed=normed, histtype=histtype, align=align,
+                                  **kwargs)
       
-      if x_title:
+      if x_title!=None:
         nice_x=x_title
       else:
         nice_x=MakeTitle(col)
       plt.xlabel(nice_x, size='x-large')
-      
-      if y_title:
+      if y_range:
+        plt.ylim(y_range) 
+      if y_title!=None:
         nice_y=y_title
       else:
         nice_y="bin count"  
       plt.ylabel(nice_y, size='x-large')
       
-      if title:
+      if title!=None:
         nice_title=title
       else:
         nice_title="Histogram of %s"%nice_x
@@ -915,6 +1275,9 @@ class Table(object):
     Returns the row containing the cell with the maximal value in col. If 
     several rows have the highest value, only the first one is returned.
     None values are ignored.
+
+    :param col: column name
+    :type col: :class:`str`
     """
     val, idx = self._Max(col)
     return self.rows[idx]
@@ -923,6 +1286,9 @@ class Table(object):
     """
     Returns the maximum value in col. If several rows have the highest value,
     only the first one is returned. None values are ignored.
+
+    :param col: column name
+    :type col: :class:`str`
     """
     val, idx = self._Max(col)
     return val
@@ -932,6 +1298,9 @@ class Table(object):
     Returns the row index of the cell with the maximal value in col. If
     several rows have the highest value, only the first one is returned.
     None values are ignored.
+
+    :param col: column name
+    :type col: :class:`str`
     """
     val, idx = self._Max(col)
     return idx
@@ -958,6 +1327,9 @@ class Table(object):
     """
     Returns the minimal value in col. If several rows have the lowest value,
     only the first one is returned. None values are ignored.
+
+    :param col: column name
+    :type col: :class:`str`
     """
     val, idx = self._Min(col)
     return val
@@ -967,6 +1339,9 @@ class Table(object):
     Returns the row containing the cell with the minimal value in col. If 
     several rows have the lowest value, only the first one is returned.
     None values are ignored.
+
+    :param col: column name
+    :type col: :class:`str`
     """
     val, idx = self._Min(col)
     return self.rows[idx]
@@ -976,6 +1351,9 @@ class Table(object):
     Returns the row index of the cell with the minimal value in col. If
     several rows have the lowest value, only the first one is returned.
     None values are ignored.
+
+    :param col: column name
+    :type col: :class:`str`
     """
     val, idx = self._Min(col)
     return idx
@@ -985,6 +1363,11 @@ class Table(object):
     Returns the sum of the given column. Cells with None are ignored. Returns 
     0.0, if the column doesn't contain any elements. Col must be of numeric
     column type ('float', 'int') or boolean column type.
+
+    :param col: column name
+    :type col: :class:`str`
+
+    :raises: :class:`TypeError` if column type is ``string``
     """
     idx = self.GetColIndex(col)
     col_type = self.col_types[idx]
@@ -1004,6 +1387,11 @@ class Table(object):
 
     If column type is *bool*, the function returns the ratio of
     number of 'Trues' by total number of elements.
+
+    :param col: column name
+    :type col: :class:`str`
+
+    :raises: :class:`TypeError` if column type is ``string``
     """
     idx = self.GetColIndex(col)
     col_type = self.col_types[idx]
@@ -1021,13 +1409,21 @@ class Table(object):
     
   def RowMean(self, mean_col_name, cols):
     """
-    Adds a new column of type 'float' with a specified name (mean_col),
+    Adds a new column of type 'float' with a specified name (*mean_col_name*),
     containing the mean of all specified columns for each row.
     
     Cols are specified by their names and must be of numeric column
-    type ('float', 'int') or boolean column type.. Cells with None are ignored.
+    type ('float', 'int') or boolean column type. Cells with None are ignored.
     Adds None if the row doesn't contain any values.
     
+    :param mean_col_name: name of new column containing mean values
+    :type mean_col_name: :class:`str`
+
+    :param cols: name or list of names of columns to include in computation of
+                 mean
+    :type cols: :class:`str` or :class:`list` of strings
+
+    :raises: :class:`TypeError` if column type of columns in *col* is ``string``
     
     == Example ==
    
@@ -1045,7 +1441,7 @@ class Table(object):
     
     .. code-block::python
     
-      tab.RowMean('mean', 'x', 'u')
+      tab.RowMean('mean', ['x', 'u'])
     
     
     ==== ==== ==== ===== 
@@ -1089,6 +1485,11 @@ class Table(object):
     Returns the median of the given column. Cells with None are ignored. Returns 
     None, if the column doesn't contain any elements. Col must be of numeric
     column type ('float', 'int') or boolean column type.
+
+    :param col: column name
+    :type col: :class:`str`
+
+    :raises: :class:`TypeError` if column type is ``string``
     """
     idx = self.GetColIndex(col)
     col_type = self.col_types[idx]
@@ -1110,6 +1511,11 @@ class Table(object):
     Returns the standard deviation of the given column. Cells with None are
     ignored. Returns None, if the column doesn't contain any elements. Col must
     be of numeric column type ('float', 'int') or boolean column type.
+
+    :param col: column name
+    :type col: :class:`str`
+
+    :raises: :class:`TypeError` if column type is ``string``
     """
     idx = self.GetColIndex(col)
     col_type = self.col_types[idx]
@@ -1128,6 +1534,12 @@ class Table(object):
   def Count(self, col, ignore_nan=True):
     """
     Count the number of cells in column that are not equal to None.
+
+    :param col: column name
+    :type col: :class:`str`
+
+    :param ignore_nan: ignore all *None* values
+    :type ignore_nan: :class:`bool`
     """
     count=0
     idx=self.GetColIndex(col)
@@ -1141,10 +1553,16 @@ class Table(object):
 
   def Correl(self, col1, col2):
     """
-    Calculate the Pearson correlation coefficient between col1 and col2, only 
-    taking rows into account where both of the values are not equal to None. If 
-    there are not enough data points to calculate a correlation coefficient, 
-    None is returned.
+    Calculate the Pearson correlation coefficient between *col1* and *col2*, only
+    taking rows into account where both of the values are not equal to *None*.
+    If there are not enough data points to calculate a correlation coefficient,
+    *None* is returned.
+
+    :param col1: column name for first column
+    :type col1: :class:`str`
+
+    :param col2: column name for second column
+    :type col2: :class:`str`
     """
     if IsStringLike(col1) and IsStringLike(col2):
       col1 = self.GetColIndex(col1)
@@ -1166,7 +1584,13 @@ class Table(object):
     there are not enough data points to calculate a correlation coefficient, 
     None is returned.
     
-    The function depends on the following module: *scipy.stats.mstats*
+    :warning: The function depends on the following module: *scipy.stats.mstats*
+
+    :param col1: column name for first column
+    :type col1: :class:`str`
+
+    :param col2: column name for second column
+    :type col2: :class:`str`
     """
     try:
       import scipy.stats.mstats
@@ -1194,8 +1618,22 @@ class Table(object):
 
   def Save(self, stream_or_filename, format='ost', sep=','):
     """
-    Save the table to stream or filename. For supported file formats, see
-    :meth:`Load`
+    Save the table to stream or filename. The following three file formats
+    are supported (for more information on file formats, see :meth:`Load`):
+
+    =============   =======================================
+    ost             ost-specific format (human readable)
+    csv             comma separated values (human readable)
+    pickle          pickled byte stream (binary)
+    =============   =======================================
+
+    :param stream_or_filename: filename or stream for writing output
+    :type stream_or_filename: :class:`str` or :class:`file`
+
+    :param format: output format (i.e. *ost*, *csv*, *pickle*)
+    :type format: :class:`str`
+
+    :raises: :class:`ValueError` if format is unknown
     """
     format=format.lower()
     if format=='ost':
@@ -1245,8 +1683,12 @@ class Table(object):
     '''
     Returns a numpy matrix containing the selected columns from the table as 
     columns in the matrix.
-    Only columns of type int or float are supported. NA values in the table
-    will be converted to None values.
+    Only columns of type *int* or *float* are supported. *NA* values in the
+    table will be converted to *None* values.
+
+    :param \*args: column names to include in numpy matrix
+
+    :warning: The function depends on *numpy*
     '''
     try:
       import numpy as np
@@ -1268,6 +1710,54 @@ class Table(object):
       LogError("Function needs numpy, but I could not import it.")
       raise
     
+
+
+  def GaussianSmooth(self, col, std=1.0, na_value=0.0):
+
+    '''
+    In place gaussian smooth of a column in the table with a given standard deviation.
+    All nan are set to nan_value before smoothing.
+
+    :param col: column name
+    :type col: :class:`str`
+
+    :param std: standard deviation for gaussian kernel
+    :type std: `scalar` 
+
+    :param na_value: all na (None) values of the speciefied column are set to na_value before smoothing
+    :type na_value: `scalar`
+
+    :warning: The function depends on *scipy*
+    ''' 
+
+    try:
+      from scipy import ndimage
+    except ImportError:
+      LogError("Function needs scipy.ndimage, but I could no import it")
+      raise
+      
+    idx = self.GetColIndex(col)
+    col_type = self.col_types[idx]
+    if col_type!='int' and col_type!='float':
+      raise TypeError("GaussianSmooth can only be used on numeric column types")
+
+    vals=[]
+    for v in self[col]:
+      if v!=None:
+        vals.append(v)
+      else:
+        vals.append(na_value)
+
+    smoothed_values_ndarray=ndimage.gaussian_filter1d(vals,std)
+
+    result=[]
+
+    for v in smoothed_values_ndarray:
+      result.append(v)
+
+    self[col]=result
+
+
   def GetOptimalPrefactors(self, ref_col, *args, **kwargs):
     '''
     This returns the optimal prefactor values (i.e. a, b, c, ...) for the
@@ -1352,11 +1842,14 @@ class Table(object):
                      style='-', title=None, x_title=None, y_title=None,
                      clear=True, save=None):
     '''
-    Plot an enrichment curve using matplotlib.
+    Plot an enrichment curve using matplotlib of column *score_col* classified
+    according to *class_col*.
     
-    For more information about parameters, see :meth:`ComputeEnrichment`
-    '''
+    For more information about parameters of the enrichment, see
+    :meth:`ComputeEnrichment`, and for plotting see :meth:`Plot`.
     
+    :warning: The function depends on *matplotlib*
+    '''
     try:
       import matplotlib.pyplot as plt
     
@@ -1392,24 +1885,23 @@ class Table(object):
   def ComputeEnrichment(self, score_col, class_col, score_dir='-', 
                         class_dir='-', class_cutoff=2.0):
     '''
-    Computes the enrichment of one column (e.g. score) over all data points.
+    Computes the enrichment of column *score_col* classified according to
+    *class_col*.
     
     For this it is necessary, that the datapoints are classified into positive
     and negative points. This can be done in two ways:
     
-     - by using one 'bool' column which contains True for positives and False
-       for negatives
-     - by specifying an additional column, a cutoff value and the columns
-       direction. This will generate the classification on the fly
+     - by using one 'bool' type column (*class_col*) which contains *True* for
+       positives and *False* for negatives
        
-       * if class_dir=='-': values in the classification column that are 
-                            less than or equal to class_cutoff will be counted
-                            as positives
-       * if class_dir=='+': values in the classification column that are 
-                            larger than or equal to class_cutoff will be counted
-                            as positives
-
-    During the calculation, the table will be sorted according to score_dir,
+     - by specifying a classification column (*class_col*), a cutoff value
+       (*class_cutoff*) and the classification columns direction (*class_dir*).
+       This will generate the classification on the fly
+
+       * if ``class_dir=='-'``: values in the classification column that are less than or equal to class_cutoff will be counted as positives
+       * if ``class_dir=='+'``: values in the classification column that are larger than or equal to class_cutoff will be counted as positives
+
+    During the calculation, the table will be sorted according to *score_dir*,
     where a '-' values means smallest values first and therefore, the smaller
     the value, the better.
     
@@ -1456,7 +1948,10 @@ class Table(object):
     Computes the area under the curve of the enrichment using the trapezoidal
     rule.
     
-    For more information about parameters, see :meth:`ComputeEnrichment`
+    For more information about parameters of the enrichment, see
+    :meth:`ComputeEnrichment`.
+
+    :warning: The function depends on *numpy*
     '''
     try:
       import numpy as np
@@ -1472,8 +1967,8 @@ class Table(object):
   def ComputeROC(self, score_col, class_col, score_dir='-',
                  class_dir='-', class_cutoff=2.0):
     '''
-    Computes the receiver operating characteristics of one column (e.g. score)
-    over all data points.
+    Computes the receiver operating characteristics (ROC) of column *score_col*
+    classified according to *class_col*.
 
     For this it is necessary, that the datapoints are classified into positive
     and negative points. This can be done in two ways:
@@ -1484,12 +1979,8 @@ class Table(object):
        and the classification columns direction (*class_dir*). This will generate
        the classification on the fly
 
-       - if *class_dir* =='-': values in the classification column that are
-                            less than or equal to *class_cutoff* will be counted
-                            as positives
-       - if *class_dir* =='+': values in the classification column that are
-                            larger than or equal to *class_cutoff* will be
-                            counted as positives
+       - if ``class_dir=='-'``: values in the classification column that are less than or equal to *class_cutoff* will be counted as positives
+       - if ``class_dir=='+'``: values in the classification column that are larger than or equal to *class_cutoff* will be counted as positives
 
     During the calculation, the table will be sorted according to *score_dir*,
     where a '-' values means smallest values first and therefore, the smaller
@@ -1561,7 +2052,10 @@ class Table(object):
     Computes the area under the curve of the receiver operating characteristics
     using the trapezoidal rule.
     
-    For more information about parameters, see :meth:`ComputeROC`
+    For more information about parameters of the ROC, see
+    :meth:`ComputeROC`.
+
+    :warning: The function depends on *numpy*
     '''
     try:
       import numpy as np
@@ -1583,7 +2077,10 @@ class Table(object):
     '''
     Plot an ROC curve using matplotlib.
     
-    For more information about parameters, see :meth:`ComputeROC`
+    For more information about parameters of the ROC, see
+    :meth:`ComputeROC`, and for plotting see :meth:`Plot`.
+
+    :warning: The function depends on *matplotlib*
     '''
 
     try:
@@ -1640,14 +2137,8 @@ class Table(object):
      - by using 'float' or 'int' columns and specifying a cutoff value and the
        columns direction. This will generate the classification on the fly
        
-       * if *class_dir*/*score_dir*=='-': values in the classification column 
-                                    that are less than or equal to 
-                                    *class_cutoff*/*score_cutoff* will be
-                                    counted as positives
-       * if *class_dir*/*score_dir*=='+': values in the classification column 
-                                    that are larger than or equal to
-                                    *class_cutoff*/*score_cutoff* will be
-                                    counted as positives
+       * if ``class_dir``/``score_dir=='-'``: values in the classification column that are less than or equal to *class_cutoff*/*score_cutoff* will be counted as positives
+       * if ``class_dir``/``score_dir=='+'``: values in the classification column that are larger than or equal to *class_cutoff*/*score_cutoff* will be counted as positives
                                     
     The two possibilities can be used together, i.e. 'bool' type for one column
     and 'float'/'int' type and cutoff/direction for the other column.
@@ -1754,9 +2245,11 @@ class Table(object):
     If the type of any column in *tab* is not the same as in the current table
     a *TypeError* is raised.
     
-    If *overwrite* is set and not None (must be set to an existing column name),
-    an existing row is overwritten if the value of column *overwrite* matches.
-    If no matching row is found, a new row is appended to the table.
+    If *overwrite* is not None and set to an existing column name, the specified 
+    column in the table is searched for the first occurrence of a value matching
+    the value of the column with the same name in the dictionary. If a matching
+    value is found, the row is overwritten with the dictionary. If no matching
+    row is found, a new row is appended to the table.
     """
     # add column to current table if it doesn't exist
     for name,typ in zip(tab.col_names, tab.col_types):
diff --git a/modules/base/src/export_helper/pair_to_tuple_conv.hh b/modules/base/src/export_helper/pair_to_tuple_conv.hh
index 90eccdb49c49c16629b69b822b9ec1cac0d0cbbb..e187b0a92e5854541b94c717f917269ee2e36c09 100644
--- a/modules/base/src/export_helper/pair_to_tuple_conv.hh
+++ b/modules/base/src/export_helper/pair_to_tuple_conv.hh
@@ -34,4 +34,5 @@ struct PairToTupleConverter {
     return boost::python::incref(t.ptr());
   }
 };
-}
\ No newline at end of file
+}
+
diff --git a/modules/base/src/generic_property.hh b/modules/base/src/generic_property.hh
index a7ea0782510763ec3849a4f28fb880a60afb2d99..5220d7741d2df6aff1356dec25603ac41ff036eb 100644
--- a/modules/base/src/generic_property.hh
+++ b/modules/base/src/generic_property.hh
@@ -28,7 +28,6 @@
   setter and getter methods for String, Real, int and bool mapping
 */
 
-#include <exception>
 #include <sstream>
 #include <map>
 #include <vector>
@@ -36,19 +35,15 @@
 
 #include <ost/module_config.hh>
 #include <ost/invalid_handle.hh>
+#include <ost/message.hh>
 
 namespace ost {
 
-struct  TEMPLATE_EXPORT GenericPropError: public std::exception
+struct  DLLEXPORT GenericPropError: public Error
 {
   GenericPropError(const String& m):
-    m_(m)
+    Error(m)
   {}
-  virtual ~GenericPropError() throw() {}
-  virtual const char* what() const throw() {
-    return m_.c_str();
-  }
-  String m_;
 };
   
 typedef boost::variant<String, Real, int, bool> GenericPropValue;
diff --git a/modules/base/src/message.cc b/modules/base/src/message.cc
index eff6b1c68374bb95caa6418f2c8d378cfd668a3f..572480206588eaf96cbe29e7f748d8c68c8952d2 100644
--- a/modules/base/src/message.cc
+++ b/modules/base/src/message.cc
@@ -20,7 +20,7 @@
 /*
   messages and logs
 
-  Authors: Ansgar Philippsen, Andteas Schenk
+  Authors: Ansgar Philippsen, Andreas Schenk
 */
 
 #include "message.hh"
@@ -28,16 +28,7 @@
 namespace ost {
 
 Error::Error(const String& m):
-  mesg_(m)
+  std::runtime_error(m)
 {}
 
-Error::~Error() throw()
-{
 }
-
-const char* Error::what() const throw()
-{
-  return mesg_.c_str();
-}
-
-}
\ No newline at end of file
diff --git a/modules/base/src/message.hh b/modules/base/src/message.hh
index 6a98dbc2bdc3a7983d3654b2c3759d2d6b3eecbc..5dd148264d3f6a867be593fcd0a5725dde377b31 100644
--- a/modules/base/src/message.hh
+++ b/modules/base/src/message.hh
@@ -20,25 +20,21 @@
 /*
   messages and logs
 
-  Authors: Ansgar Philippsen, Andteas Schenk
+  Authors: Ansgar Philippsen, Andreas Schenk
 */
 
 #ifndef OST_MESSAGE_HH
 #define OST_MESSAGE_HH
 
-#include <exception>
+#include <stdexcept>
 #include <ost/module_config.hh>
 
 namespace ost {
 
 
-class DLLEXPORT Error: virtual public std::exception {
+class DLLEXPORT Error: public std::runtime_error {
 public:
   Error(const String& m);
-  ~Error() throw();
-  virtual const char* what() const throw();
-protected:
-  String mesg_;
 };
 
 } // namespace
diff --git a/modules/base/src/ptr_observer.hh b/modules/base/src/ptr_observer.hh
index a5f9cfbb10799cbb2ff8df11cd80a678db36f174..4b98e1fd52b972deea02b6207dcb0f1bfedb48bc 100644
--- a/modules/base/src/ptr_observer.hh
+++ b/modules/base/src/ptr_observer.hh
@@ -29,7 +29,7 @@
   Author: Ansgar Philippsen
 */
 
-class DLLEXPORT_OST_BASE InvalidatedPointer: public ost::Error {
+class DLLEXPORT InvalidatedPointer: public ost::Error {
 public:
   InvalidatedPointer():
     ost::Error("access attempt on invalidated Pointer")
diff --git a/modules/base/src/stdint.h b/modules/base/src/stdint.h
index 59d067302fcfe1f5ec82cd7534f89c18167dd895..666e23080351623987e4993a085372cab10d9d06 100644
--- a/modules/base/src/stdint.h
+++ b/modules/base/src/stdint.h
@@ -245,3 +245,4 @@ typedef uint64_t  uintmax_t;
 
 
 #endif // _MSC_STDINT_H_ ]
+
diff --git a/modules/base/src/stdint.hh b/modules/base/src/stdint.hh
index be11eb9e18b3e3d4d6ba796d8c38c8de223cd4b9..282a564d9c618918f46a2b8d93f63c8bf5d8299e 100644
--- a/modules/base/src/stdint.hh
+++ b/modules/base/src/stdint.hh
@@ -2,4 +2,5 @@
 #include <ost/stdint_msc.hh>
 #else
 #include <stdint.h>
-#endif
\ No newline at end of file
+#endif
+
diff --git a/modules/base/src/stdint_msc.hh b/modules/base/src/stdint_msc.hh
index 59d067302fcfe1f5ec82cd7534f89c18167dd895..666e23080351623987e4993a085372cab10d9d06 100644
--- a/modules/base/src/stdint_msc.hh
+++ b/modules/base/src/stdint_msc.hh
@@ -245,3 +245,4 @@ typedef uint64_t  uintmax_t;
 
 
 #endif // _MSC_STDINT_H_ ]
+
diff --git a/modules/base/tests/test_generic_property.cc b/modules/base/tests/test_generic_property.cc
index 025630e08b34606d8aae547cca63d3ae8db8ba52..83f4aef79ad30a04542f7f63b8442aac299189de 100644
--- a/modules/base/tests/test_generic_property.cc
+++ b/modules/base/tests/test_generic_property.cc
@@ -55,8 +55,8 @@ BOOST_AUTO_TEST_CASE( test_generic_property )
 
   EntityView ev = eh.CreateFullView();
   ChainView chv = ev.FindChain("A");
-  ResidueView resv = ev.FindResidue(res);
-  AtomView atomv = ev.FindAtom(atom);
+  ResidueView resv = ev.ViewForHandle(res);
+  AtomView atomv = ev.ViewForHandle(atom);
 
   BOOST_CHECK(ev.GetStringProp("a")=="123");
   BOOST_CHECK(chv.GetFloatProp("b")==1.5);
diff --git a/modules/base/tests/test_table.py b/modules/base/tests/test_table.py
index 7b6b3be222600a86e534eb12c1b3d02cfe1da654..21fd58a679df759d4824c20c3a1104e3879bb652 100644
--- a/modules/base/tests/test_table.py
+++ b/modules/base/tests/test_table.py
@@ -6,6 +6,7 @@ Author: Tobias Schmidt
 
 import os
 import unittest
+import glob
 from ost.table import *
 import ost
 
@@ -41,6 +42,10 @@ except ImportError:
 
 class TestTable(unittest.TestCase):
 
+  def tearDown(self):
+    for filename in glob.glob('*_out.*'):
+      os.remove(filename)
+
   def setUp(self):
     ost.PushVerbosityLevel(3)
 
@@ -58,7 +63,7 @@ class TestTable(unittest.TestCase):
     tab = Table()
     tab.AddCol('first', 'string')
     tab.AddCol('second', 'int')
-    tab.AddCol('third', 'float', 3.141)
+    tab.AddCol('third', 'float')
     self.CompareColCount(tab, 3)
     self.CompareRowCount(tab, 0)
     self.CompareColTypes(tab, ['first','second', 'third'], 'sif')
@@ -358,7 +363,7 @@ class TestTable(unittest.TestCase):
     tab = Table()
     self.CompareColCount(tab, 0)
     self.CompareRowCount(tab, 0)
-    tab.AddCol('first', 'string', 'AB C')
+    tab.AddCol('first', 'string')
     self.CompareColCount(tab, 1)
     self.CompareRowCount(tab, 0)
     self.CompareColNames(tab, ['first'])
@@ -437,7 +442,7 @@ class TestTable(unittest.TestCase):
     tab = Table()
     tab.AddCol('first', 'string')
     tab.AddCol('second', 'int')
-    tab.AddCol('third', 'float', 3.141)
+    tab.AddCol('third', 'float')
     self.CompareColCount(tab, 3)
     self.CompareRowCount(tab, 0)
     self.CompareColTypes(tab, ['first','second', 'third'], 'sif')
@@ -462,7 +467,7 @@ class TestTable(unittest.TestCase):
     tab = Table()
     tab.AddCol('first', 'string')
     tab.AddCol('second', 'int')
-    tab.AddCol('aaa', 'float', 3.141)
+    tab.AddCol('aaa', 'float')
     self.CompareColCount(tab, 3)
     self.CompareRowCount(tab, 0)
     self.CompareColTypes(tab, ['first','second', 'aaa'], 'sif')
@@ -501,6 +506,35 @@ class TestTable(unittest.TestCase):
                                    'first': ['x','foo','bar'],
                                    'third': [3.141, 3.141, 3.141]})
 
+  def testAddMultiRowFromDict(self):
+    tab = Table(['x','y','z'], 'fff')
+    data = {'x': [1.2, 1.5], 'z': [1.6, 2.4]}
+    tab.AddRow(data)
+    self.CompareDataFromDict(tab, {'x': [1.2, 1.5],
+                                   'y': [None, None],
+                                   'z': [1.6, 2.4]})
+
+    data = {'y': [5.1, 3.4, 1.5]}
+    tab.AddRow(data)
+    self.CompareDataFromDict(tab, {'x': [1.2, 1.5, None, None, None],
+                                   'y': [None, None, 5.1, 3.4, 1.5],
+                                   'z': [1.6, 2.4, None, None, None]})
+
+    # must raise since length of data is not the same
+    data = {'x': [1.2, 1.5], 'y': 1.2, 'z': [1.6, 2.4]}
+    self.assertRaises(ValueError, tab.AddRow, data)
+
+    # must raise since length of data is not the same
+    data = {'x': [1.2, 1.5], 'y': [1.2], 'z': [1.6, 2.4]}
+    self.assertRaises(ValueError, tab.AddRow, data)
+
+    # overwrite certain rows
+    data = {'x': [1.2, 1.9], 'z': [7.9, 3.5]}
+    tab.AddRow(data, overwrite='x')
+    self.CompareDataFromDict(tab, {'x': [1.2, 1.5, None, None, None, 1.9],
+                                   'y': [None, None, 5.1, 3.4, 1.5, None],
+                                   'z': [7.9, 2.4, None, None, None, 3.5]})
+
   def testAddRowFromDictWithOverwrite(self):
     '''
     add rows from dictionary with overwrite (i.e. overwrite third row with additional data)
@@ -720,6 +754,53 @@ class TestTable(unittest.TestCase):
     tab.Sort('third', '+')
     self.CompareDataFromDict(tab, {'first': [None,'foo','x'], 'second': [9,None,3], 'third': [3.3,2.2,None]})
 
+  def testGuessFormat(self):
+    self.assertEqual(Table._GuessFormat('table_test.csv'), 'csv')
+    self.assertEqual(Table._GuessFormat('table_test.pickle'), 'pickle')
+    self.assertEqual(Table._GuessFormat('table_test.tab'), 'ost')
+    self.assertEqual(Table._GuessFormat('table_test.ost'), 'ost')
+    self.assertEqual(Table._GuessFormat('table_test.xyz'), 'ost')
+    
+  def testSaveLoadTableAutoFormat(self):   
+    tab = self.CreateTestTable()
+    self.CompareDataFromDict(tab, {'first': ['x','foo',None], 'second': [3,None,9], 'third': [None,2.2,3.3]})
+
+    # write to disc
+    tab.Save("saveloadtable_filename_out.csv", format='csv')
+    tab.Save("saveloadtable_filename_out.tab", format='ost')
+    tab.Save("saveloadtable_filename_out.pickle", format='pickle')
+    
+    # read from disc: csv
+    in_stream_csv = open("saveloadtable_filename_out.csv", 'r')
+    tab_loaded_stream_csv = Table.Load(in_stream_csv)
+    in_stream_csv.close()
+    tab_loaded_fname_csv = Table.Load('saveloadtable_filename_out.csv')
+
+    # check content: csv
+    self.CompareDataFromDict(tab_loaded_stream_csv, {'first': ['x','foo',None], 'second': [3,None,9], 'third': [None,2.2,3.3]})
+    self.CompareDataFromDict(tab_loaded_fname_csv, {'first': ['x','foo',None], 'second': [3,None,9], 'third': [None,2.2,3.3]})
+  
+    # read from disc: pickle
+    in_stream_pickle = open("saveloadtable_filename_out.pickle", 'rb')
+    tab_loaded_stream_pickle = Table.Load(in_stream_pickle)
+    in_stream_pickle.close()
+    tab_loaded_fname_pickle = Table.Load('saveloadtable_filename_out.pickle')
+
+    # check content: pickle
+    self.CompareDataFromDict(tab_loaded_stream_pickle, {'first': ['x','foo',None], 'second': [3,None,9], 'third': [None,2.2,3.3]})
+    self.CompareDataFromDict(tab_loaded_fname_pickle, {'first': ['x','foo',None], 'second': [3,None,9], 'third': [None,2.2,3.3]})
+
+    # read from disc: ost
+    in_stream_ost = open("saveloadtable_filename_out.tab", 'rb')
+    tab_loaded_stream_ost = Table.Load(in_stream_ost)
+    in_stream_ost.close()
+    tab_loaded_fname_ost = Table.Load('saveloadtable_filename_out.tab')
+
+    # check content: ost
+    self.CompareDataFromDict(tab_loaded_stream_ost, {'first': ['x','foo',None], 'second': [3,None,9], 'third': [None,2.2,3.3]})
+    self.CompareDataFromDict(tab_loaded_fname_ost, {'first': ['x','foo',None], 'second': [3,None,9], 'third': [None,2.2,3.3]})
+  
+
   def testLoadTableOSTUnknownType(self):
     self.assertRaises(ValueError, Table.Load, os.path.join('testfiles','ost-table-unknown-type.tab'))
 
@@ -1048,6 +1129,14 @@ class TestTable(unittest.TestCase):
                       score_dir='+', class_col='rmsd', class_cutoff=2.0,
                       class_dir='y')
     
+  def testPlot(self):
+    if not HAS_MPL or not HAS_NUMPY:
+      return
+    tab = self.CreateTestTable()
+    self.assertRaises(ValueError, tab.Plot, 'second', x_range=1)
+    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 testPlotEnrichment(self):
     if not HAS_MPL or not HAS_PIL:
       return
@@ -1147,6 +1236,8 @@ class TestTable(unittest.TestCase):
     self.assertEquals(auc, None)
 
   def testCalcROCFromFile(self):
+    if not HAS_NUMPY:
+      return
     tab = Table.Load(os.path.join('testfiles','roc_table.dat'))
     auc = tab.ComputeROCAUC(score_col='prediction', class_col='reference', class_cutoff=0.4)
     self.assertEquals(auc, 1.0)
@@ -1195,6 +1286,8 @@ class TestTable(unittest.TestCase):
     self.assertAlmostEquals(mcc, 0.882089673321)
 
   def testTableAsNumpyMatrix(self):
+    if not HAS_NUMPY:
+      return
 
     '''
     checks numpy matrix 
diff --git a/modules/bindings/pymod/blast.py b/modules/bindings/pymod/blast.py
index 8f14d64dc27f259c7bd7756d27c7d9313b5e6731..30784713f3990df9802f8292204c38dfe8d027a1 100644
--- a/modules/bindings/pymod/blast.py
+++ b/modules/bindings/pymod/blast.py
@@ -125,6 +125,20 @@ def ParseBlastOutput(string):
     hits.append(BlastHit(hit_id, aligned_patches))
   return hits
 
+def BlastVersion(blast_location=None):
+  """
+  Returns the version of the BLAST executable, e.g. 2.2.24 as a string
+  """
+  blastall_exe=settings.Locate('blastall', explicit_file_name=blast_location)
+  blast_pipe=subprocess.Popen(blastall_exe, stdout=subprocess.PIPE,
+                              stderr=subprocess.PIPE)
+  lines=blast_pipe.stdout.readlines()
+  pattern=re.compile(r'blastall (\d+\.\d+\.\d+)\s+arguments:\s*')
+  for line in lines:
+    m=pattern.match(line)
+    if m:
+      return m.group(1)
+  raise IOError("could not determine blast version for '%s'" % blastall_exe)
 
 def Blast(query, database, gap_open=11, gap_ext=1, matrix='BLOSUM62',
          blast_location=None):
diff --git a/modules/bindings/pymod/clustalw.py b/modules/bindings/pymod/clustalw.py
index 0204cd8ccc9a51962ccbef257676341c43b4cd7c..084fe8d3337acd235fcd6fe9453ac56af63292aa 100644
--- a/modules/bindings/pymod/clustalw.py
+++ b/modules/bindings/pymod/clustalw.py
@@ -44,6 +44,30 @@ def ClustalW(seq1, seq2=None, clustalw=None, keep_files=False, nopgap=False,
   :type clustalw_option_string: :class:`str`
   :param keep_files: do not delete temporary files
   :type keep_files: :class:`bool`
+
+  Note: ClustalW will convert lowercase to uppercase, and change all '.' to '-'. 
+  OST will convert and '?' to 'X' before aligning sequences with Clustalw.
+
+  ClustalW will accept only IUB/IUPAC amino acid and nucleic acid codes:
+
+  ======= ======================= ======= ============================ 
+  Residue  Name                   Residue  Name 
+  ======= ======================= ======= ============================
+     A    alanine                    P    proline
+     B    aspartate or asparagine    Q    glutamine
+     C    cystine                    R    arginine
+     D    aspartate                  S    serine
+     E    glutamate                  T    threonine
+     F    phenylalanine              U    selenocysteine
+     G    glycine                    V    valine
+     H    histidine                  W    tryptophan
+     I    isoleucine                 Y    tyrosine
+     K    lysine                     Z    glutamate or glutamine
+     L    leucine                    X    any
+     M    methionine                 \*   translation stop
+     N    asparagine                 \-   gap of indeterminate length
+  ======= ======================= ======= ============================ 
+
   '''
   clustalw_path=settings.Locate(('clustalw', 'clustalw2'), 
                                 explicit_file_name=clustalw)
@@ -67,6 +91,16 @@ def ClustalW(seq1, seq2=None, clustalw=None, keep_files=False, nopgap=False,
   else:
     LogError("WARNING: Specify either two SequenceHandles or one SequenceList")
     return
+
+  new_list = seq.CreateSequenceList()
+  for s in seq_list:
+    ss = s.Copy()
+    for i,c in enumerate(ss):
+      if c=='?':
+        ss[i]='X'
+    new_list.AddSequence(ss)
+
+  seq_list = new_list
   
   temp_dir=utils.TempDirWithFiles((seq_list,))
   out=os.path.join(temp_dir.dirname, 'out.fasta')
diff --git a/modules/bindings/pymod/naccess.py b/modules/bindings/pymod/naccess.py
index afb58c4bac3c59190ff4c5a3a1c880dfb1be2455..f9f2e5703e99cf9a12740c89a192ce95119338a3 100644
--- a/modules/bindings/pymod/naccess.py
+++ b/modules/bindings/pymod/naccess.py
@@ -35,16 +35,22 @@ def _GetExecutable(naccess_exe):
 #
 # \param entity      EntityHandle or EntityView to calculate surface
 # \param selection   Calculate surface for subset of entity 
+# \param scratch_dir Directory for temporary files (NACCESS is sensitive to "." in directory names
+# \param max_number_of_atoms Max Number of atoms in the entity (i.e. is limited in the default NACCESS version to 50 000)
 # \return            array containing temporary directory, input filename for naccess and directory of the input file
 # \exception         RuntimeError if selection is not valid
-def _SetupFiles(entity, selection):
+def _SetupFiles(entity, selection, scratch_dir, max_number_of_atoms):
   # create temporary directory
-  tmp_dir_name=tempfile.mkdtemp()
+  tmp_dir_name=""
+  if scratch_dir!=None:
+    tmp_dir_name=tempfile.mkdtemp(dir=scratch_dir)
+  else:
+    tmp_dir_name=tempfile.mkdtemp()
 
   # select only heavy atoms if no_hydrogens is true
   entity_view=entity.Select(selection)
-  if len(entity_view.atoms) > 50000:
-    raise RuntimeError, "Too much atoms for NACCESS (> 50 000)"
+  if len(entity_view.atoms) > max_number_of_atoms:
+    raise RuntimeError, "Too much atoms for NACCESS (> %s)" % max_number_of_atoms
   if not entity_view.IsValid():
     raise RuntimeError, "Could not create view for selection (%s)"%(selection)
   
@@ -184,11 +190,14 @@ def _RunNACCESS(command, temp_dir):
 # \param asa_abs            Attaches per residue absolute SASA to specified FloatProp on residue level
 # \param asa_rel            Attaches per residue relative SASA to specified FloatProp on residue level
 # \param asa_atom           Attaches per atom SASA to specified FloatProp at atom level
+# \param scratch_dir        Directory for temporary files (NACCESS is sensitive to "." in directory names
+# \param max_number_of_atoms Max Number of atoms in the entity (i.e. is limited in the default NACCESS version to 50 000)
+
 # \return                   absolute SASA calculated using asa_atom 
 def CalculateSurfaceArea(entity,  radius=1.4,  
                          include_hydrogens=False, include_hetatm = False, 
                          include_water = False, selection="",
-                         naccess_exe=None, keep_files=False , asa_abs= "asaAbs", asa_rel="asaRel", asa_atom="asaAtom"):
+                         naccess_exe=None, keep_files=False , asa_abs= "asaAbs", asa_rel="asaRel", asa_atom="asaAtom", scratch_dir = None, max_number_of_atoms=50000):
   import re 
   
   # check if msms executable is specified
@@ -196,7 +205,7 @@ def CalculateSurfaceArea(entity,  radius=1.4,
   # parse selection
   
   # setup files for msms
-  (naccess_data_dir, naccess_data_file,naccess_data_base )=_SetupFiles(entity, selection)
+  (naccess_data_dir, naccess_data_file,naccess_data_base )=_SetupFiles(entity, selection, scratch_dir)
 
   # set command line
   command="%s %s -p %f " % \
diff --git a/modules/bindings/tests/test_blast.py b/modules/bindings/tests/test_blast.py
index 8b4215faa45d71660a7799f3211885f519745a56..707f5c93b3bc49a71d0059dbfc74252768626373 100644
--- a/modules/bindings/tests/test_blast.py
+++ b/modules/bindings/tests/test_blast.py
@@ -26,11 +26,20 @@ class TestBlastBindings(unittest.TestCase):
   
   def testParseBlastOutput(self):
     hits=blast.Blast(self.query, 'testfiles/seqdb')
-    expected_output=[{'evalue':2.366130E-59,'bitscore':211.460,'score':537}, 
-                     {'evalue':4.808930E-59,'bitscore':210.305,'score':534}, 
-                     {'evalue':5.361450E-58,'bitscore':206.838,'score':525}, 
-                     {'evalue':3.277500E+00,'bitscore':15.0086,'score':27}, 
-                     {'evalue':9.696520E+00,'bitscore':13.4678,'score':23}]
+    blast_version=blast.BlastVersion()
+    if blast_version=='2.2.16':
+      expected_output=[{'evalue':4.808930E-59,'bitscore':210.305,'score':534}, 
+                       {'evalue':2.366130E-59,'bitscore':210.305,'score':534}, 
+                       {'evalue':5.361450E-58,'bitscore':206.068,'score':523}, 
+                       {'evalue':2.965230E+00,'bitscore':15.0086,'score':27}, 
+                       {'evalue':9.696520E+00,'bitscore':13.4678,'score':23}]
+ 
+    else:
+      expected_output=[{'evalue':2.366130E-59,'bitscore':211.460,'score':537}, 
+                       {'evalue':4.808930E-59,'bitscore':210.305,'score':534}, 
+                       {'evalue':5.361450E-58,'bitscore':206.838,'score':525}, 
+                       {'evalue':3.277500E+00,'bitscore':15.0086,'score':27}, 
+                       {'evalue':9.696520E+00,'bitscore':13.4678,'score':23}]
     self.assertEqual(len(hits), 4)
     for expected, hit in zip(expected_output, hits):
       patch=hit.aligned_patches[0]
diff --git a/modules/config/CMakeLists.txt b/modules/config/CMakeLists.txt
index a95554b40456f3339bbbea2a7ef6833e829b5592..c7cdc9468303279890c5a9a84ce2d9aae4fae4ad 100644
--- a/modules/config/CMakeLists.txt
+++ b/modules/config/CMakeLists.txt
@@ -52,11 +52,6 @@ if (_STATICPROPS)
 else()
   set(static_props 0)
 endif()
-if (ENABLE_SPNAV)
-  set(spnav_enabled 1)
-else()
-  set(spnav_enabled 0)
-endif()
 if (FFTW_USE_THREADS)
   set(fftw_use_threads 1)
 else()
diff --git a/modules/config/config.hh.in b/modules/config/config.hh.in
index 3268ebab4144946b5d78fcd83f2b0f3d816a4832..23027e24848ca02388701f86b32bc68530829840 100644
--- a/modules/config/config.hh.in
+++ b/modules/config/config.hh.in
@@ -30,7 +30,6 @@
 #define OST_IMG_ENABLED @img_enabled@
 #define OST_DOUBLE_PRECISION @double_prec@
 #define OST_STATIC_PROPERTY_WORKAROUND @static_props@
-#define OST_SPNAV_ENABLED @spnav_enabled@
 #define OST_FFT_USE_THREADS @fftw_use_threads@
 #define OST_NUMPY_SUPPORT_ENABLED @numpy_support@
 #define OST_DEBIAN_STYLE_LIBEXEC @debian_style_libexec@
diff --git a/modules/conop/doc/aminoacid.rst b/modules/conop/doc/aminoacid.rst
index 2dd39c057b33a3ea04c83c82052e9e552b99eab2..9751631723150af30d849154f03f253ee4ba2c26 100644
--- a/modules/conop/doc/aminoacid.rst
+++ b/modules/conop/doc/aminoacid.rst
@@ -67,4 +67,62 @@ Converter functions
   .. method:: Empty()
   
     Whether the set is empty, i.e. doesn't contain any amino acids.
-    
+
+
+Mapping functions
+--------------------------------------------------------------------------------
+
+The following functions help to convert one residue into another by reusing as
+much as possible from the present atoms. They are mainly meant to map from
+standard amino acid to other standard amino acids or from modified amino acids
+to standard amino acids.
+
+.. function:: CopyResidue(src_res, dst_res, editor)
+
+  Copies the atoms of ``src_res`` to ``dst_res`` using the residue names
+  as guide to decide which of the atoms should be copied. If ``src_res`` and
+  ``dst_res`` have the same name, or ``src_res`` is a modified version of
+  ``dst_res`` (i.e. have the same single letter code), CopyConserved will be
+  called, otherwise CopyNonConserved will be called.
+
+  :param src_res: The source residue
+  :type src_res: :class:`~mol.ResidueHandle`
+  :param dst_res: The destination residue
+  :type dst_res: :class:`~mol.ResidueHandle`
+
+  :returns: true if the residue could be copied, false if not.
+
+.. function:: CopyConserved(src_res, dst_res, editor)
+
+  Copies the atoms of ``src_res`` to ``dst_res`` assuming that the parent
+  amino acid of ``src_res`` (or ``src_res`` itself) are identical to ``dst_res``.
+
+  If ``src_res`` and ``dst_res`` are identical, all heavy atoms are copied
+  to ``dst_res``. If ``src_res`` is a modified version of ``dst_res`` and the
+  modification is a pure addition (e.g. the phosphate group of phosphoserine),
+  the modification is stripped off and all other heavy atoms are copied to
+  ``dst_res``. If the modification is not a pure addition, only the backbone
+  heavy atoms are copied to ``dst_res``.
+
+  Additionally, the selenium atom of ``MSE`` is converted to sulphur.
+
+  :param src_res: The source residue
+  :type src_res: :class:`~mol.ResidueHandle`
+  :param dst_res: The destination residue
+  :type dst_res: :class:`~mol.ResidueHandle`
+
+  :returns: a tuple of bools stating whether the residue could be copied and
+    whether the Cbeta atom was inserted into the ``dst_res``.
+
+.. function:: CopyNonConserved(src_res, dst_res, editor)
+
+  Copies the heavy backbone atoms and Cbeta (except for ``GLY``) of ``src_res``
+  to ``dst_res``.
+
+  :param src_res: The source residue
+  :type src_res: :class:`~mol.ResidueHandle`
+  :param dst_res: The destination residue
+  :type dst_res: :class:`~mol.ResidueHandle`
+
+  :returns: a tuple of bools stating whether the residue could be copied and
+    whether the Cbeta atom was inserted into the ``dst_res``.
diff --git a/modules/conop/doc/compoundlib.rst b/modules/conop/doc/compoundlib.rst
index 48ee192df54ff33cbd826273a2375e42beeafbdd..3e0e70d41bc5484965f7e2e0fed8e9870c6e7186 100644
--- a/modules/conop/doc/compoundlib.rst
+++ b/modules/conop/doc/compoundlib.rst
@@ -62,6 +62,26 @@ build the compound library manually.
   
     Clear the compound cache.
 
+  .. method:: SetChemLibInfo()
+
+     When creating the new library the current date and the Version of OST used
+     are stored into the table chemlib_info.
+
+  .. method:: GetOSTVersionUsed()
+
+     reads out ost_version_used from the table chemlib_info.
+
+     :returns: a version string
+
+     :rtype: :class:`String`
+
+  .. method:: GetCreationDate()
+
+     reads out creation_date from the table chemlib_info.
+
+     :returns: a date string (Py), a Date (C++)
+
+     :rtype: :class:`String` (Py), :class:`Date`
 .. class:: Compound
 
   Holds the description of a chemical compound, such as three-letter-code, and
diff --git a/modules/conop/doc/connectivity.rst b/modules/conop/doc/connectivity.rst
index 9b56d65662df21b3350d7ce7cdb080bb984263a8..98270b1aff31b7fa6d0f15f526e4dde56e8ef735 100644
--- a/modules/conop/doc/connectivity.rst
+++ b/modules/conop/doc/connectivity.rst
@@ -258,3 +258,15 @@ The RuleBasedBuilder class
      
      :rtype: list of :class:`~ost.mol.AtomHandle` instances
 
+Changing the default builder
+---------------------------------------------------------------------------------
+
+The default builder can be specified with :func:`SetDefaultBuilder`. Before being
+able to set a builder, it needs to be registered with :func:`RegisterBuilder`.
+By default, there is always a builder called "HEURISTIC" registered. If, for some
+reason your are currently using the :class:`RuleBasedBuilder` and you would like
+to switch to that builder, call
+
+.. code-block:: python
+
+  conop.SetDefaultBuilder("HEURISTIC")
diff --git a/modules/conop/pymod/__init__.py b/modules/conop/pymod/__init__.py
index a534ea808bf883c616c7eb7165af5b71155fdc5b..a24f5d2ec21b9333c7548cce372739a3c1753e6d 100644
--- a/modules/conop/pymod/__init__.py
+++ b/modules/conop/pymod/__init__.py
@@ -64,7 +64,12 @@ def RegisterBuilder(builder, name):
   
 def SetDefaultBuilder(builder_name):
   '''
-  Set the builder with the given name as the default.
+  Set the builder with the given name as the default. You will have to register
+  a builder with :func:`RegisterBuilder` before you will be able to set it as
+  the default.
+
+  :raises: :exc:`RuntimeError` when trying to set a builder as the default that
+    has not been registered yet.
   '''
   conop_inst=Conopology.Instance()
   conop_inst.SetDefaultBuilder(builder_name)
diff --git a/modules/conop/pymod/export_compound.cc b/modules/conop/pymod/export_compound.cc
index 0b7e0dde8d24422a0758d91019aebf0d1252701b..6b8196e6768a608745c9c83608a7ddffc6ef50d3 100644
--- a/modules/conop/pymod/export_compound.cc
+++ b/modules/conop/pymod/export_compound.cc
@@ -21,6 +21,7 @@
 #include <boost/python/suite/indexing/vector_indexing_suite.hpp>
 using namespace boost::python;
 
+#include <ost/message.hh>
 #include <ost/conop/compound.hh>
 #include <ost/conop/compound_lib.hh>
 using namespace ost::mol;
@@ -44,7 +45,7 @@ Compound::Dialect tr_dialect(const String& dialect)
   }
   std::stringstream ss;
   ss << "unknown compound dialect '" << dialect << "'";
-  throw std::runtime_error(ss.str());
+  throw ost::Error(ss.str());
 }
 
 void set_dialect(CompoundPtr compound, const String& dialect)
@@ -74,6 +75,11 @@ CompoundPtr find_compound(CompoundLibPtr comp_lib,
   return comp_lib->FindCompound(tlc, tr_dialect(dialect));
 }
 
+String get_creation_date(CompoundLibPtr comp_lib)
+{
+  return comp_lib->GetCreationDate().ToString();
+}
+
 }
 void export_Compound() {
 
@@ -84,6 +90,9 @@ void export_Compound() {
     .def("GetOneLetterCode", &Compound::GetOneLetterCode)
 
     .add_property("three_letter_code", make_function(&Compound::GetID, return_value_policy<copy_const_reference>()))
+    .add_property("name", 
+                  make_function(&Compound::GetName, 
+                 return_value_policy<copy_const_reference>()))
     .add_property("id", make_function(&Compound::GetID, return_value_policy<copy_const_reference>()))    
     .add_property("one_letter_code", &Compound::GetOneLetterCode, 
                   &Compound::SetOneLetterCode)                  
@@ -127,6 +136,8 @@ void export_Compound() {
     .def("FindCompound", &find_compound, 
          (arg("tlc"), arg("dialect")="PDB"))
     .def("ClearCache", &CompoundLib::ClearCache)
+    .def("GetOSTVersionUsed", &CompoundLib::GetOSTVersionUsed)
+    .def("GetCreationDate", &get_creation_date, (arg("comp_lib")))
   ;
   
   class_<AtomSpecList>("AtomSpecList", init<>())
diff --git a/modules/conop/pymod/export_non_standard.cc b/modules/conop/pymod/export_non_standard.cc
index 025d2819a100584c85f3b088ce5320fdf02d0762..50b1fd2d6e169e31ff5e192e03b19b98541bf89d 100644
--- a/modules/conop/pymod/export_non_standard.cc
+++ b/modules/conop/pymod/export_non_standard.cc
@@ -39,12 +39,15 @@ object copy_non_conserved_handle(ResidueHandle src_res, ResidueHandle dst_res,
   return make_tuple(ret, has_cbeta);
 }
 
+bool (*copy_residue_handle)(ost::mol::ResidueHandle,
+                            ost::mol::ResidueHandle,
+                            ost::mol::XCSEditor&)=&CopyResidue;
 
 
 void export_NonStandard()
 {
   def("CopyNonConserved",&copy_non_conserved_handle);
   def("CopyConserved", copy_conserved_handle);
-  def("CopyResidue", &CopyResidue);
+  def("CopyResidue", copy_residue_handle);
  }
 
diff --git a/modules/conop/src/CMakeLists.txt b/modules/conop/src/CMakeLists.txt
index 344f5e00755d3ba733f1d6a877840037c8da802b..8f493e83e2a8daea025925fce3ac64b33cd7ea7a 100644
--- a/modules/conop/src/CMakeLists.txt
+++ b/modules/conop/src/CMakeLists.txt
@@ -4,6 +4,8 @@ builder_fw.hh
 conop.hh
 heuristic_builder.hh
 amino_acids.hh
+diag.hh
+model_check.hh
 compound.hh
 compound_lib.hh
 module_config.hh
@@ -16,6 +18,8 @@ set(OST_CONOP_SOURCES
 builder.cc
 amino_acids.cc
 conop.cc
+diag.cc
+model_check.cc
 heuristic_builder.cc
 compound.cc
 compound_lib.cc
diff --git a/modules/conop/src/chemdict_tool.cc b/modules/conop/src/chemdict_tool.cc
index 6e5720675c912198e53fb0c0260d3514ecb91004..9cd043f00fd6a76875447a4908d73401f8d709fe 100644
--- a/modules/conop/src/chemdict_tool.cc
+++ b/modules/conop/src/chemdict_tool.cc
@@ -72,9 +72,11 @@ int main(int argc, char const *argv[])
   filtered_istream.push(istream);  
   io::ChemdictParser cdp(filtered_istream, dialect);
   conop::CompoundLibPtr compound_lib;
-  if (!strcmp(argv[1], "create")) {
-    compound_lib=conop::CompoundLib::Create(argv[3]);
-  } else if (!strcmp(argv[1], "update")) {
+  bool in_mem=false;
+  if (!strncmp(argv[1], "create", 6)) {
+    compound_lib=conop::CompoundLib::Create(":memory:");
+    in_mem=true;
+  } else if (!strncmp(argv[1], "update", 6)) {
     compound_lib=conop::CompoundLib::Load(argv[3]);
   } else {
     PrintUsage();
@@ -84,10 +86,12 @@ int main(int argc, char const *argv[])
     return 0;
   }
   assert(compound_lib);
-  conop::CompoundLibPtr in_mem_lib=compound_lib->Copy(":memory:");  
-  compound_lib.reset();  
+  conop::CompoundLibPtr in_mem_lib=in_mem ? compound_lib :
+                                   compound_lib->Copy(":memory:");
+  compound_lib.reset();
   cdp.SetCompoundLib(in_mem_lib);
   cdp.Parse();
+  in_mem_lib->SetChemLibInfo();
   in_mem_lib->Copy(argv[3]);  
   return 0;
-}
\ No newline at end of file
+}
diff --git a/modules/conop/src/compound.cc b/modules/conop/src/compound.cc
index dfa1a69f92677cb163fd1826313dfd09c8e255e5..dc6ff57c85239de34ab48c18025a9c2215a21670 100644
--- a/modules/conop/src/compound.cc
+++ b/modules/conop/src/compound.cc
@@ -23,10 +23,29 @@ namespace ost { namespace conop {
 
 int Compound::GetAtomSpecIndex(const String& name) const {
   AtomSpecList::const_iterator i=atom_specs_.begin();
+  // BZDNG-261: first search all primary atom names before falling back to
+  // alternative names. There are some files where alternative atom names are 
+  // used as primary names for other atoms
   for (; i!=atom_specs_.end(); ++i) {
-    if ((*i).name==name || (*i).alt_name==name)
+    if ((*i).name==name)
+      return std::distance(atom_specs_.begin(), i);
+  } 
+  for (; i!=atom_specs_.end(); ++i) {
+    if ((*i).alt_name==name)
       return std::distance(atom_specs_.begin(), i);
   }
-  return -1;
+ return -1;
+}
+String Date::ToString() const
+{
+  std::stringstream ss;
+  ss << year << "-";
+  ss.fill('0');
+  ss.width(2);
+  ss << month << "-";
+  ss.fill('0');
+  ss.width(2);
+  ss << day;
+  return ss.str();
 }
 }}
diff --git a/modules/conop/src/compound.hh b/modules/conop/src/compound.hh
index e33a7e38cfb840ebc5e5e050fbd7da55073e2c68..7e8c424571967ea5a7b0e339323561488b598d1e 100644
--- a/modules/conop/src/compound.hh
+++ b/modules/conop/src/compound.hh
@@ -29,7 +29,7 @@
 
 namespace ost { namespace conop {
 
-struct Date {
+struct DLLEXPORT_OST_CONOP Date {
   Date(int y, int m, int d):
     year(y), month(m), day(d)
   { }
@@ -52,21 +52,23 @@ struct Date {
   
   static Date FromString(const StringRef& str)
   {
-    assert(str[4]=='-');
-    assert(str[7]=='-');
-    std::pair<bool, int> year=str.substr(0,4).to_int();
-    std::pair<bool, int> month=str.substr(5,2).to_int();
-    std::pair<bool, int> day=str.substr(8, 2).to_int();
+    std::vector<StringRef> parts=str.split('-');
+    assert(parts.size()==3);
+    std::pair<bool, int> year=parts[0].to_int();
+    std::pair<bool, int> month=parts[1].to_int();
+    std::pair<bool, int> day=parts[2].to_int();
     assert(year.first); assert(month.first); assert(day.first);
     return Date(year.second, month.second, day.second);
   }
   
+  String ToString() const;
+
   int year;
   int month;
   int day;  
 };
 
-struct AtomSpec {
+struct DLLEXPORT_OST_CONOP AtomSpec {
   AtomSpec()
     : ordinal(0), is_leaving(false) {
   }
@@ -86,7 +88,7 @@ struct AtomSpec {
   }
 };
 
-struct BondSpec {
+struct DLLEXPORT_OST_CONOP BondSpec {
   BondSpec()
     : atom_one(0), atom_two(0), order(1) {
 
@@ -201,9 +203,13 @@ public:
   
   int GetAtomSpecIndex(const String& name) const;
   
-  const String& GetFormula() { return formula_; }
+  const String& GetName() { return name_; }
+  
+  void SetName(const String& name) { name_=name; }
   
   void SetFormula(const String& formula) { formula_=formula; }
+
+  const String& GetFormula() { return formula_; }
   
   const BondSpecList& GetBondSpecs() const {
     return bond_specs_;
@@ -231,6 +237,7 @@ private:
   char                         olc_;
   String                       tlc_;
   String                       formula_;
+  String                       name_;
   AtomSpecList                 atom_specs_;
   BondSpecList                 bond_specs_;
   mol::ChemClass               chem_class_;
diff --git a/modules/conop/src/compound_lib.cc b/modules/conop/src/compound_lib.cc
index c05e60fb6d2ce72343e6ab44d637526c16639707..63fd58bcf5094df4a908ff5c7ff14f63d15d875a 100644
--- a/modules/conop/src/compound_lib.cc
+++ b/modules/conop/src/compound_lib.cc
@@ -26,7 +26,8 @@
 #include <boost/format.hpp>
 #include <ost/log.hh>
 #include "compound_lib.hh"
-
+#include <ost/version.hh>
+#include <ost/string_ref.hh>
 
 using boost::format;
 
@@ -34,40 +35,44 @@ namespace ost { namespace conop {
 
 namespace {
 
-const char* CREATE_CMD[]={                                                         
+const char* CREATE_CMD[]={
+"CREATE TABLE IF NOT EXISTS chemlib_info (                                      "
+"  creation_date     TIMESTAMP,                                                 "
+"  ost_version_used  VARCHAR(64) NOT NULL);",
 "CREATE TABLE IF NOT EXISTS chem_compounds (                                    "
-"  id              INTEGER PRIMARY KEY AUTOINCREMENT,                           "
-"  tlc             VARCHAR(3) NOT NULL,                                         "
-"  olc             VARCHAR(1) NOT NULL,                                         "
-"  dialect         VARCHAR(1) NOT NULL,                                         "
-"  chem_class      VARCHAR(1),                                                  "
-"  chem_type       VARCHAR(1),                                                  "
-"  formula         VARCHAR(64) NOT NULL,                                        "
-"  pdb_initial     TIMESTAMP,                                                   "
-"  pdb_modified    TIMESTAMP                                                    "
+"  id                INTEGER PRIMARY KEY AUTOINCREMENT,                         "
+"  tlc               VARCHAR(3) NOT NULL,                                       "
+"  olc               VARCHAR(1) NOT NULL,                                       "
+"  dialect           VARCHAR(1) NOT NULL,                                       "
+"  chem_class        VARCHAR(1),                                                "
+"  chem_type         VARCHAR(1),                                                "
+"  formula           VARCHAR(64) NOT NULL,                                      "
+"  pdb_initial       TIMESTAMP,                                                 "
+"  pdb_modified      TIMESTAMP,                                                 "
+"  name              VARCHAR(256)                                               " 
 ");",
 " CREATE UNIQUE INDEX IF NOT EXISTS commpound_tlc_index ON chem_compounds       "
 "                                  (tlc, dialect)",
 "CREATE TABLE IF NOT EXISTS atoms (                                             "
-" id              INTEGER PRIMARY KEY AUTOINCREMENT,                            "
-" compound_id     INTEGER REFERENCES chem_compounds (id) ON DELETE CASCADE,     "
-" name            VARCHAR(4) NOT NULL,                                          "
-" alt_name        VARCHAR(4) NOT NULL,                                          "
-" element         VARCHAR(2) NOT NULL,                                          "
-" is_aromatic     VARCHAR(1) NOT NULL,                                          "
-" stereo_conf     VARCHAR(1) NOT NULL,                                          "
-" is_leaving      VARCHAR(1) NOT NULL,                                          "
-" ordinal         INT                                                           "
+" id                 INTEGER PRIMARY KEY AUTOINCREMENT,                         "
+" compound_id        INTEGER REFERENCES chem_compounds (id) ON DELETE CASCADE,  "
+" name               VARCHAR(4) NOT NULL,                                       "
+" alt_name           VARCHAR(4) NOT NULL,                                       "
+" element            VARCHAR(2) NOT NULL,                                       "
+" is_aromatic        VARCHAR(1) NOT NULL,                                       "
+" stereo_conf        VARCHAR(1) NOT NULL,                                       "
+" is_leaving         VARCHAR(1) NOT NULL,                                       "
+" ordinal            INT                                                        "
 ");",
 " CREATE INDEX IF NOT EXISTS atom_name_index ON atoms                           "
 "                                  (compound_id, name, alt_name)",
 " CREATE TABLE IF NOT EXISTS bonds  (                                           "
-"   id              INTEGER PRIMARY KEY AUTOINCREMENT,                          "
-"   compound_id     INTEGER REFERENCES chem_compounds (id) ON DELETE CASCADE,   "
-"   atom_one        INTEGER REFERENCES atoms (id) ON DELETE CASCADE,            "
-"   atom_two        INTEGER REFERENCES atoms (id) ON DELETE CASCADE,            "
-"   bond_order      INT,                                                        "
-"   stereo_conf     VARCHAR(1) NOT NULL                                         "
+"   id               INTEGER PRIMARY KEY AUTOINCREMENT,                         "
+"   compound_id      INTEGER REFERENCES chem_compounds (id) ON DELETE CASCADE,  "
+"   atom_one         INTEGER REFERENCES atoms (id) ON DELETE CASCADE,           "
+"   atom_two         INTEGER REFERENCES atoms (id) ON DELETE CASCADE,           "
+"   bond_order       INT,                                                       "
+"   stereo_conf      VARCHAR(1) NOT NULL                                        "
 " );",
 " CREATE INDEX IF NOT EXISTS bond_index ON bonds (compound_id)",
 " CREATE TRIGGER delete_related_objects                                         "
@@ -80,8 +85,8 @@ const char* CREATE_CMD[]={
 
 
 const char* INSERT_COMPOUND_STATEMENT="INSERT INTO chem_compounds               "
-"        (tlc, olc, dialect, chem_class, chem_type, formula, pdb_initial, pdb_modified) "
-" VALUES (?, ?, ?, ?, ?, ?, DATE(?), DATE(?))";
+"        (tlc, olc, dialect, chem_class, chem_type, formula, pdb_initial, pdb_modified, name) "
+" VALUES (?, ?, ?, ?, ?, ?, DATE(?), DATE(?), ?)";
 
 const char* INSERT_ATOM_STATEMENT="INSERT INTO atoms                            "
 "        (compound_id, name, alt_name, element, is_aromatic, stereo_conf,       "
@@ -92,8 +97,104 @@ const char* INSERT_BOND_STATEMENT="insert into bonds
 "        (compound_id, atom_one, atom_two, bond_order, stereo_conf)             "
 " VALUES (?, ?, ?, ?, ?)";
 
+const char* INSERT_CHEMLIB_INFO_STATEMENT="insert into chemlib_info             "
+"        (creation_date, ost_version_used)                                      "
+" VALUES (DATE(?), ?)";
+
+}
 
 
+void CompoundLib::SetChemLibInfo(void){
+  sqlite3_stmt* stmt=NULL;
+  //~ if (!conn_) {
+    //~ LOG_ERROR(sqlite3_errmsg("Connection to DB not made"));
+  //~ }
+  int retval=sqlite3_prepare_v2(conn_, INSERT_CHEMLIB_INFO_STATEMENT, 
+                                strlen(INSERT_CHEMLIB_INFO_STATEMENT), &stmt, NULL);
+  time_t rawtime;
+  struct tm * timeinfo;
+  time ( &rawtime );
+  timeinfo = localtime ( &rawtime );
+  Date date = Date(1900+timeinfo->tm_year, 1+timeinfo->tm_mon, timeinfo->tm_mday);
+  String date_str=date.ToString();
+  if (SQLITE_OK==retval) {
+
+    sqlite3_bind_text(stmt, 1, date_str.c_str(), 
+                      strlen(date_str.c_str()), NULL);
+    const char* ost_version = OST_VERSION_STRING;
+    sqlite3_bind_text(stmt, 2, ost_version, 
+                      strlen(ost_version), NULL);
+  } else {
+    std::cout << "failed" <<std::endl;
+  }
+  retval=sqlite3_step(stmt);
+  if (SQLITE_DONE!=retval) {
+    if (sqlite3_errcode(conn_)==SQLITE_CONSTRAINT) {
+      LOG_ERROR("chemlib info already exists");
+    } else {
+      LOG_ERROR(sqlite3_errmsg(conn_));
+    }
+  }
+  sqlite3_finalize(stmt);  
+}
+
+Date CompoundLib::GetCreationDate(void){
+  
+  String query="SELECT creation_date FROM chemlib_info";
+  sqlite3_stmt* stmt;
+  int retval=sqlite3_prepare_v2(conn_, query.c_str(), 
+                                static_cast<int>(query.length()),
+                                &stmt, NULL);
+  if (SQLITE_OK==retval) {
+    int ret=sqlite3_step(stmt);
+    if (SQLITE_DONE==ret) {
+      sqlite3_finalize(stmt);        
+      return Date();
+    }
+    if (SQLITE_ROW==ret) {
+      const char* strr = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
+      Date date = Date::FromString(StringRef(strr, strlen(strr))); 
+      sqlite3_finalize(stmt);
+      return date;   
+    }
+    assert(SQLITE_DONE==sqlite3_step(stmt));
+  } else {
+    LOG_ERROR("ERROR: " << sqlite3_errmsg(conn_));
+    sqlite3_finalize(stmt);      
+    return Date();
+  }
+  sqlite3_finalize(stmt);    
+  return Date();
+}
+
+
+String CompoundLib::GetOSTVersionUsed(){
+  String query="SELECT ost_version_used FROM chemlib_info";
+  sqlite3_stmt* stmt;
+  String version;
+
+  int retval=sqlite3_prepare_v2(conn_, query.c_str(), 
+                                static_cast<int>(query.length()),
+                                &stmt, NULL);
+  if (SQLITE_OK==retval) {
+    int ret=sqlite3_step(stmt);
+    if (SQLITE_DONE==ret) {
+      sqlite3_finalize(stmt);        
+      return String();
+    }
+    if (SQLITE_ROW==ret) {
+      version = String(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0))); 
+      sqlite3_finalize(stmt);
+      return version;   
+    }
+    assert(SQLITE_DONE==sqlite3_step(stmt));
+  } else {
+    LOG_ERROR("ERROR: " << sqlite3_errmsg(conn_) << " - your compound library might be outdated!");
+    sqlite3_finalize(stmt);      
+    return String();
+  }
+  sqlite3_finalize(stmt);    
+  return String();
 }
 
 
@@ -102,6 +203,7 @@ void CompoundLib::AddCompound(const CompoundPtr& compound)
   sqlite3_stmt* stmt=NULL;  
   int retval=sqlite3_prepare_v2(conn_, INSERT_COMPOUND_STATEMENT, 
                                 strlen(INSERT_COMPOUND_STATEMENT), &stmt, NULL);
+  String crea_date_str, modi_date_str;
   if (SQLITE_OK==retval) {
     sqlite3_bind_text(stmt, 1, compound->GetID().c_str(), 
                       compound->GetID().length(), NULL);
@@ -115,21 +217,15 @@ void CompoundLib::AddCompound(const CompoundPtr& compound)
     sqlite3_bind_text(stmt, 5, &chem_type, 1, NULL);
     sqlite3_bind_text(stmt, 6, compound->GetFormula().c_str(),
                       compound->GetFormula().length(), NULL);
-    std::stringstream ss;
-    ss << compound->GetCreationDate().year << "-" 
-       << compound->GetCreationDate().month << "-" 
-       << compound->GetCreationDate().day;
-    String date=ss.str();
-    ss.str("");
-    ss << compound->GetModificationDate().year << "-" 
-       << compound->GetModificationDate().month << "-" 
-       << compound->GetModificationDate().day;
-    sqlite3_bind_text(stmt, 7, date.c_str(), date.length(), NULL);
-    date=ss.str();
-    sqlite3_bind_text(stmt, 8, date.c_str(), date.length(), NULL);
+    Date crea_date=compound->GetCreationDate();
+    Date modi_date=compound->GetModificationDate();
+    crea_date_str=crea_date.ToString();
+    modi_date_str=modi_date.ToString();
+    sqlite3_bind_text(stmt, 7, crea_date_str.c_str(), crea_date_str.length(), NULL);
+    sqlite3_bind_text(stmt, 8, modi_date_str.c_str(), modi_date_str.length(), NULL);
   } else {
     LOG_ERROR(sqlite3_errmsg(conn_));
-    sqlite3_finalize(stmt);    
+    sqlite3_finalize(stmt);
     return;
   }
   retval=sqlite3_step(stmt);
@@ -256,6 +352,14 @@ CompoundLibPtr CompoundLib::Load(const String& database, bool readonly)
                             static_cast<int>(aq.length()),
                             &stmt, NULL);
   lib->chem_type_available_ = retval==SQLITE_OK;
+  aq="SELECT name FROM chem_compounds LIMIT 1";
+  retval=sqlite3_prepare_v2(lib->conn_, aq.c_str(),
+                            static_cast<int>(aq.length()),
+                            &stmt, NULL);
+  lib->name_available_ = retval==SQLITE_OK;
+
+  lib->creation_date_ = lib->GetCreationDate();
+  lib->ost_version_used_ = lib->GetOSTVersionUsed();
   return lib;
 }
 
@@ -321,7 +425,11 @@ CompoundPtr CompoundLib::FindCompound(const String& id,
   String query="SELECT id, tlc, olc, chem_class, dialect, formula";
   if(chem_type_available_) {
     query+=", chem_type";
+    if(name_available_) {
+      query+=", name";
+    }
   }
+
   query+=" FROM chem_compounds"
          " WHERE tlc='"+id+"' AND dialect='"+String(1, char(dialect))+"'";
   sqlite3_stmt* stmt;
@@ -346,6 +454,12 @@ CompoundPtr CompoundLib::FindCompound(const String& id,
       if(chem_type_available_) {
         compound->SetChemType(mol::ChemType(sqlite3_column_text(stmt, 6)[0]));
       }
+      if (name_available_) {
+        const char* name=reinterpret_cast<const char*>(sqlite3_column_text(stmt, 7));
+        if (name) {
+          compound->SetName(name);
+        }
+      }
       // Load atoms and bonds      
       this->LoadAtomsFromDB(compound, pk);
       this->LoadBondsFromDB(compound, pk);
diff --git a/modules/conop/src/compound_lib.hh b/modules/conop/src/compound_lib.hh
index a552c5aee7754aea6a6759911389a4931c3ec3d0..c79463a6f28857e813c7c0e57050d4459a7714f9 100644
--- a/modules/conop/src/compound_lib.hh
+++ b/modules/conop/src/compound_lib.hh
@@ -42,17 +42,24 @@ public:
   ~CompoundLib();
   
   CompoundPtr FindCompound(const String& id, Compound::Dialect dialect);
+  Date GetCreationDate(void);
+  String GetOSTVersionUsed(void);
   void AddCompound(const CompoundPtr& compound);
   CompoundLibPtr Copy(const String& filename) const;
   void ClearCache();
+  void SetChemLibInfo(void);
 private:
     CompoundLib();
+
     void LoadAtomsFromDB(CompoundPtr comp, int pk);
     void LoadBondsFromDB(CompoundPtr comp, int pk);    
 private:
-  CompoundMap  compound_cache_;
-  sqlite3*     conn_;
-  bool         chem_type_available_; // weather pdbx_type is available in db
+  CompoundMap       compound_cache_;
+  sqlite3*          conn_;
+  bool              chem_type_available_; // weather pdbx_type is available in db
+  bool              name_available_; // weather name is available in db
+  Date              creation_date_;
+  String            ost_version_used_;
 };
 
 }}
diff --git a/modules/conop/src/conop.cc b/modules/conop/src/conop.cc
index 138d62c7c988e11c6393cca79d6b222fd9c9c239..e48b3444e16c4ac7bf1ba5ef70ea28ff8341f93a 100644
--- a/modules/conop/src/conop.cc
+++ b/modules/conop/src/conop.cc
@@ -16,6 +16,7 @@
 // along with this library; if not, write to the Free Software Foundation, Inc.,
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 //------------------------------------------------------------------------------
+#include <ost/message.hh>
 #include <ost/mol/mol.hh>
 #include <ost/log.hh>
 
@@ -161,7 +162,8 @@ void Conopology::SetDefaultBuilder(const String& default_name) {
   if (builder)
     builder_map_["DEFAULT"]=builder;
   else
-    assert(0 && "what is this?");
+    throw ost::Error("trying to set unknown builder '"+
+                             default_name+"' as the default");
 }
 
 BuilderP Conopology::GetBuilder(const String& name)
diff --git a/modules/conop/src/diag.cc b/modules/conop/src/diag.cc
new file mode 100644
index 0000000000000000000000000000000000000000..75245fc93aa9414b0a8e1229a3b106957dd8ec30
--- /dev/null
+++ b/modules/conop/src/diag.cc
@@ -0,0 +1,98 @@
+//------------------------------------------------------------------------------
+// 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 "diag.hh"
+
+namespace ost { namespace conop {
+
+String Diag::Format(bool colored) const
+{
+  std::stringstream ss;
+  std::vector<String> strings;
+  for (std::vector<ArgDesc>::const_iterator
+       i=args_.begin(), e=args_.end(); i!=e; ++i) {
+   switch (i->type) {
+     case DIAG_ARG_TYPE_ATOM:
+       if (colored) {
+         strings.push_back("\033[0;30m"+
+                           atoms_[i->index].GetQualifiedName()+"\033[0m");
+       } else {
+         strings.push_back(atoms_[i->index].GetQualifiedName());
+       }
+       break;
+     case DIAG_ARG_TYPE_RESIDUE:
+        if (colored) {  
+          strings.push_back("\033[0;30m"+
+                            residues_[i->index].GetQualifiedName()+"\033[0m");
+       } else {
+          strings.push_back(residues_[i->index].GetQualifiedName());
+       }
+       break;
+     case DIAG_ARG_TYPE_CHAIN:
+        if (colored) {    
+          strings.push_back("\033[0;30m"+
+                            chains_[i->index].GetName()+"\033[0m");
+       } else {
+         strings.push_back(chains_[i->index].GetName());
+       }
+       break;
+     case DIAG_ARG_TYPE_STRING:
+       strings.push_back(strings_[i->index]);
+       break;
+     case DIAG_ARG_TYPE_INT:
+       ss << ints_[i->index];
+       strings.push_back(ss.str());
+       ss.str("");
+       break;
+   }
+  }
+  for (size_t i=0; i<format_.size(); ++i) {
+    if (format_[i]=='%') {
+      // scan for number
+      ++i;
+      assert(i<format_.size());
+      if (format_[i]=='%' ) {
+        ss << '%';
+        continue;
+      }
+      bool plural_s=false;
+      if (format_[i]=='s') {
+        plural_s=true;
+        ++i;
+      }
+      const char *start=&format_[i];
+      char *end=NULL;
+      long int id=strtol(start, &end, 10);
+      assert(start!=end);
+      assert(id>=0 && id<strings.size());
+      if (plural_s) {
+        if (ints_[args_[id].index]!=1) {
+          ss << "s";
+        }
+      } else {
+        ss << strings[id];
+      }
+      i+=end-start-1;
+      continue;
+    } 
+    ss << format_[i];
+  }
+  return ss.str();
+}
+
+}} /* ost::conop */
diff --git a/modules/conop/src/diag.hh b/modules/conop/src/diag.hh
new file mode 100644
index 0000000000000000000000000000000000000000..58f4765543c389b27c5925c9df7068bc2708e9dd
--- /dev/null
+++ b/modules/conop/src/diag.hh
@@ -0,0 +1,134 @@
+#//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+#ifndef OST_CONOP_DIAG_HH
+#define OST_CONOP_DIAG_HH
+#include <ost/mol/atom_handle.hh>
+#include <ost/mol/residue_handle.hh>
+#include <ost/mol/chain_handle.hh>
+#include <ost/conop/module_config.hh>
+
+namespace ost { namespace conop {
+
+typedef enum {
+	DIAG_ARG_TYPE_ATOM,
+	DIAG_ARG_TYPE_RESIDUE,
+	DIAG_ARG_TYPE_CHAIN,
+	DIAG_ARG_TYPE_STRING,
+	DIAG_ARG_TYPE_INT
+} DiagArgType;
+
+typedef enum {
+  DIAG_UNK_ATOM,
+  DIAG_UNK_RESIDUE,
+  DIAG_MISSING_ATOM,
+  DIAG_NONSTD_RESIDUE
+} DiagType;
+
+class DLLEXPORT_OST_CONOP Diag {
+public:
+	Diag(DiagType typ, const char* fmt): type_(typ), format_(fmt) {}
+  DiagType GetType() const { return type_; }
+	Diag& AddAtom(mol::AtomHandle atom)
+	{
+		atoms_.push_back(atom);
+		args_.push_back(ArgDesc(atoms_.size()-1, DIAG_ARG_TYPE_ATOM));
+		return *this;
+	}
+
+	Diag& AddResidue(mol::ResidueHandle res)
+	{
+		residues_.push_back(res);
+		args_.push_back(ArgDesc(residues_.size()-1, DIAG_ARG_TYPE_RESIDUE));
+		return *this;
+	}
+	Diag& AddChain(mol::ChainHandle chain)
+	{
+		chains_.push_back(chain);
+		args_.push_back(ArgDesc(chains_.size()-1, DIAG_ARG_TYPE_CHAIN));
+		return *this;
+	}
+	Diag& AddInt(int int_val)
+	{
+		ints_.push_back(int_val);
+		args_.push_back(ArgDesc(ints_.size()-1, DIAG_ARG_TYPE_INT));
+		return *this;
+	}
+	Diag& AddString(const String& str)
+	{
+		strings_.push_back(str);
+		args_.push_back(ArgDesc(strings_.size()-1, DIAG_ARG_TYPE_STRING));
+		return *this;
+	}
+  mol::AtomHandle GetAtom(size_t index) const
+  {
+    assert(index<args_.size());
+    return atoms_[args_[index].index];
+  }
+  mol::ResidueHandle GetResidue(size_t index) const
+  {
+    assert(index<args_.size());
+    return residues_[args_[index].index];
+  }
+  mol::ChainHandle GetChain(size_t index) const
+  {
+    assert(index<args_.size());
+    return chains_[args_[index].index];
+  }
+	String Format(bool colored=true) const;
+private:
+	struct ArgDesc {
+		ArgDesc(size_t i, DiagArgType t): index(i), type(t) { }
+		size_t      index;
+		DiagArgType type;
+	};
+	DiagType               type_;
+	String                 format_;
+	mol::AtomHandleList    atoms_;
+	mol::ResidueHandleList residues_;
+  mol::ChainHandleList   chains_;
+	std::vector<String>    strings_;
+	std::vector<int>       ints_;
+	std::vector<ArgDesc>   args_;
+};
+
+class DLLEXPORT_OST_CONOP DiagEngine {
+public:
+	DiagEngine() {}
+
+	~DiagEngine()
+	{
+		for(std::vector<Diag*>::iterator
+				i=diags_.begin(), e=diags_.end(); i!=e;++i) {
+		  delete *i;
+		}
+	}
+
+	Diag& AddDiag(DiagType type, const char* fmt)
+	{
+		diags_.push_back(new Diag(type, fmt));
+		return *diags_.back();
+	}
+
+	const std::vector<Diag*>& GetDiags() const { return diags_; }
+private:
+	std::vector<Diag*> diags_;
+};
+
+}} /* ost::conop */
+#endif
diff --git a/modules/conop/src/heuristic_builder.cc b/modules/conop/src/heuristic_builder.cc
index 458370078ea9171766bee2013506a170d0ac869d..07922d6a2dab0aa5fd162323749ebb4c9a4efaaa 100644
--- a/modules/conop/src/heuristic_builder.cc
+++ b/modules/conop/src/heuristic_builder.cc
@@ -187,6 +187,7 @@ HeuristicBuilder::HeuristicBuilder():
       emap_[def_entry.abbrev]=entry;
     }
   }
+  default_nucleotide_=LookupResEntry("G").first;
   LOG_DEBUG("done importing internal tables");
 }
 
@@ -321,6 +322,10 @@ void ConnectPrevNext(HeuristicBuilder* builder,mol::ResidueHandle res0,
       res0_ret.first=builder->DefaultPeptide();
       res0_ret.second=true;
     }
+    if (res0.FindAtom("C3'") && res0.FindAtom("P")) {
+      res0_ret.first=builder->DefaultNucleotide();
+      res0_ret.second=true;
+    }
   }
 
   if(!res1_ret.second) {
@@ -329,6 +334,10 @@ void ConnectPrevNext(HeuristicBuilder* builder,mol::ResidueHandle res0,
       res1_ret.first=builder->DefaultPeptide();
       res1_ret.second=true;
     }
+    if (res1.FindAtom("C3'") && res1.FindAtom("P")) {
+      res1_ret.first=builder->DefaultNucleotide();
+      res1_ret.second=true;
+    }
   }
 
   if(res0_ret.second && res1_ret.second) {
@@ -348,16 +357,19 @@ void ConnectPrevNext(HeuristicBuilder* builder,mol::ResidueHandle res0,
       if(flag) {
         if (builder->DoesPeptideBondExist(res0_atom, res1_atom)) {
           editor.Connect(res0_atom,res1_atom);
-          res0.SetIsProtein(true);
-          res1.SetIsProtein(true);
+          if (res0_ret.first.GetChemClass().IsPeptideLinking()) {
+            res0.SetIsProtein(true);
+            res1.SetIsProtein(true);
+          }
         }
       } else {
         if (builder->DoesPeptideBondExist(res1_atom, res0_atom)) {
           editor.Connect(res1_atom, res0_atom);
-          res0.SetIsProtein(true);
-          res1.SetIsProtein(true);
+          if (res0_ret.first.GetChemClass().IsPeptideLinking()) {
+            res0.SetIsProtein(true);
+            res1.SetIsProtein(true);
+          }
         }
-
       }
     }
   } else {
diff --git a/modules/conop/src/heuristic_builder.hh b/modules/conop/src/heuristic_builder.hh
index bc3930bcaf37a29d2cda545eca0cbc40bf2fb5c6..09a991345264b6031265c9bf2505a874f730daac 100644
--- a/modules/conop/src/heuristic_builder.hh
+++ b/modules/conop/src/heuristic_builder.hh
@@ -110,6 +110,7 @@ public:
   virtual void FillAtomProps(mol::AtomHandle atom);
 
   const detail::ConnResEntry& DefaultPeptide() const {return default_peptide_;}
+  const detail::ConnResEntry& DefaultNucleotide() const {return default_nucleotide_;}
 protected:
   void ConnectivityFromAtomNames(const mol::ResidueHandle& res,
                                  detail::ConnResEntry& centry,
@@ -117,6 +118,7 @@ protected:
 private:
   detail::ConnResEntryMap emap_;
   detail::ConnResEntry default_peptide_;
+  detail::ConnResEntry default_nucleotide_;
 };
 
 
diff --git a/modules/conop/src/heuristic_connect_table.hh b/modules/conop/src/heuristic_connect_table.hh
index aa5c0b651a5d2d13364946146d5a49f603d3528b..15e0f1a25eeada4159f10cc60140eeaa4bea55fc 100644
--- a/modules/conop/src/heuristic_connect_table.hh
+++ b/modules/conop/src/heuristic_connect_table.hh
@@ -267,31 +267,31 @@ CONN_DEF_ENTRY def_entry_table[]={
    {{0,0,0,0,""}},1,
    {0},1
   },
-  {"Adenosin","A",'?', mol::ChemClass(mol::ChemClass::DNA_LINKING),
+  {"Adenosin","DA",'?', mol::ChemClass(mol::ChemClass::DNA_LINKING),
    {"P","O5'","C5'","C4'","O4'","C3'","O3'","C2'","C1'","O1P","O2P","N9","C8","N7","C5","C6","N6","N1","C2","N3","C4","O2'"},12,
    {{-2,1},{1,2},{2,3},{3,4},{4,5},{4,6},{6,7},{6,8},{8,9},{5,9},{1,10},{1,11},{8,22},{9,12},{7,-3}},15,
    {{0,0,0,0,""}},1,
    {0},1
   },
-  {"Cytosin","C",'?', mol::ChemClass(mol::ChemClass::DNA_LINKING),
+  {"Cytosin","DC",'?', mol::ChemClass(mol::ChemClass::DNA_LINKING),
    {"P","O5'","C5'","C4'","O4'","C3'","O3'","C2'","C1'","O1P","O2P","O2'"},12,
    {{-2,1},{1,2},{2,3},{3,4},{4,5},{4,6},{6,7},{6,8},{8,9},{5,9},{1,10},{1,11},{8,12},{7,-3}},14,
    {{0,0,0,0,""}},1,
    {0},1
   },
-  {"Guanidin","G",'?', mol::ChemClass(mol::ChemClass::DNA_LINKING),
+  {"Guanidin","DG",'?', mol::ChemClass(mol::ChemClass::DNA_LINKING),
    {"P","O5'","C5'","C4'","O4'","C3'","O3'","C2'","C1'","O1P","O2P","O2'"},12,
    {{-2,1},{1,2},{2,3},{3,4},{4,5},{4,6},{6,7},{6,8},{8,9},{5,9},{7,-3},{1,10},{1,11},{8,12}},14,
    {{0,0,0,0,""}},1,
    {0},1
   },
-  {"Thymidin","T",'?', mol::ChemClass(mol::ChemClass::DNA_LINKING),
+  {"Thymidin","DT",'?', mol::ChemClass(mol::ChemClass::DNA_LINKING),
    {"P","O5'","C5'","C4'","O4'","C3'","O3'","C2'","C1'","O1P","O2P","O2'"},12,
    {{-2,1},{1,2},{2,3},{3,4},{4,5},{4,6},{6,7},{6,8},{8,9},{5,9},{7,-3},{1,10},{8,12},{1,11}},15,
    {{0,0,0,0,""}},1,
    {0},1
   },
-  {"Uracil","U",'?', mol::ChemClass(mol::ChemClass::DNA_LINKING),
+  {"Uracil","DU",'?', mol::ChemClass(mol::ChemClass::DNA_LINKING),
    {"P","O5'","C5'","C4'","O4'","C3'","O3'","C2'","C1'","O1P","O2P","O2'"},12,
    {{-2,1},{1,2},{2,3},{3,4},{4,5},{4,6},{6,7},{6,8},{8,9},{5,9},{7,-3},{1,10},{1,11},{8,12}},14,
    {{0,0,0,0,""}},1,
diff --git a/modules/conop/src/model_check.cc b/modules/conop/src/model_check.cc
new file mode 100644
index 0000000000000000000000000000000000000000..cb5d710b66ed1a6596903437dfde896e0da1593d
--- /dev/null
+++ b/modules/conop/src/model_check.cc
@@ -0,0 +1,150 @@
+#include <ost/mol/iterator.hh>
+#include "model_check.hh"
+#include "amino_acids.hh"
+
+using namespace ost::mol;
+
+namespace ost { namespace conop {
+
+void Checker::CheckForCompleteness(bool require_hydrogens)
+{
+  for (ResidueHandleIter i=ent_.ResiduesBegin(), e=ent_.ResiduesEnd();
+    i!=e; ++i) {
+    ResidueHandle res=*i;
+    String anames="";
+    CompoundPtr compound=lib_->FindCompound(res.GetName(),Compound::PDB);
+    if (!compound) {
+      if (checked_unk_res_) {
+        continue;
+      }
+      diags_.AddDiag(DIAG_UNK_RESIDUE, "unknown residue %0")
+            .AddResidue(res);
+      continue;
+    }
+    int missing_atoms=0;
+    const AtomSpecList& atom_specs=compound->GetAtomSpecs();
+    for (AtomSpecList::const_iterator
+         j=atom_specs.begin(), e2=atom_specs.end(); j!=e2; ++j) {
+      if (j->is_leaving) {
+        continue;
+      }
+      if (!require_hydrogens && (j->element=="H" || j->element=="D")) {
+         continue;
+      }
+      if (!res.FindAtom(j->name) && !res.FindAtom(j->alt_name)) {
+        if (!anames.empty()) {
+          anames+=", ";
+        }
+        anames+="'"+j->name+"'";
+        missing_atoms+=1;
+      }
+    }
+    if (missing_atoms>0) {
+      diags_.AddDiag(DIAG_MISSING_ATOM, "residue %0 is missing %1 atom%s1: %2")
+            .AddResidue(res)
+            .AddInt(missing_atoms)
+            .AddString(anames);
+    }
+  }
+  checked_unk_res_=true;
+}
+
+mol::AtomHandleList Checker::GetHydrogens()
+{
+  AtomHandleList hydlist;
+  for (ResidueHandleIter i=ent_.ResiduesBegin(), e=ent_.ResiduesEnd();
+       i!=e; ++i) {
+    ResidueHandle res=*i;
+    CompoundPtr compound=lib_->FindCompound(res.GetName(),Compound::PDB);
+    if (!compound) {
+      continue;
+    }
+    AtomHandleList atoms=res.GetAtomList();
+    for (AtomHandleList::const_iterator
+         j=atoms.begin(), e2=atoms.end(); j!=e2; ++j) {
+      int specindx=compound->GetAtomSpecIndex(j->GetName());
+      if (specindx!=-1) {  
+        if (compound->GetAtomSpecs()[specindx].element=="H" || compound->GetAtomSpecs()[specindx].element=="D") {
+           hydlist.push_back(*j);
+        }
+      }
+    }
+  }
+  return hydlist;
+}
+
+mol::AtomHandleList Checker::GetZeroOccupancy()
+{
+  AtomHandleList zerolist;
+  for (ResidueHandleIter i=ent_.ResiduesBegin(), e=ent_.ResiduesEnd();
+       i!=e; ++i) {
+    ResidueHandle res=*i;
+    AtomHandleList atoms=res.GetAtomList();
+    for (AtomHandleList::const_iterator j=atoms.begin(), e2=atoms.end(); j!=e2; ++j) {
+      if (j->GetOccupancy()==0.0) {
+        zerolist.push_back(*j);
+      }
+    }
+  }
+  return zerolist;
+}
+
+void Checker::CheckForNonStandard()
+{
+  for (ResidueHandleIter i=ent_.ResiduesBegin(), e=ent_.ResiduesEnd();
+       i!=e; ++i) {
+    ResidueHandle res=*i;
+    CompoundPtr compound=lib_->FindCompound(res.GetName(),Compound::PDB);
+    if (!compound) {
+      if (checked_unk_res_) {
+        continue;
+      }
+      diags_.AddDiag(DIAG_UNK_RESIDUE, "unknown residue %0")            
+            .AddResidue(res);
+      continue;
+    }
+    if (ResidueToAminoAcid(res)==XXX) {
+      diags_.AddDiag(DIAG_NONSTD_RESIDUE, "%0 is not a standard amino acid")            
+            .AddResidue(res);
+    }
+  }
+  checked_unk_res_=true;
+}
+
+void Checker::CheckForUnknownAtoms()
+{
+  for (ResidueHandleIter i=ent_.ResiduesBegin(), e=ent_.ResiduesEnd();
+       i!=e; ++i) {
+    ResidueHandle res=*i;
+    String anames="";
+    CompoundPtr compound=lib_->FindCompound(res.GetName(),Compound::PDB);
+    if (!compound) {
+      if (checked_unk_res_) {
+        continue;
+      }
+      diags_.AddDiag(DIAG_UNK_RESIDUE, "unknown residue %0")            
+            .AddResidue(res);
+      continue;
+    }
+    AtomHandleList atoms=res.GetAtomList();
+    const AtomSpecList& atom_specs=compound->GetAtomSpecs();
+    for (AtomHandleList::const_iterator
+         j=atoms.begin(), e2=atoms.end(); j!=e2; ++j) {
+      bool found=false;
+      for (AtomSpecList::const_iterator
+           k=atom_specs.begin(), e3=atom_specs.end(); k!=e3; ++k) {
+       if (k->name==j->GetName() || k->alt_name==j->GetName()) {
+         found=true;
+         break;
+       }
+      }
+      if (!found) {
+        diags_.AddDiag(DIAG_UNK_ATOM, "residue %0 contains unknown atom %1")
+              .AddResidue(res)
+              .AddAtom(*j);
+      }
+    }
+  }
+  checked_unk_res_=true;
+}
+}} /* ost::conop */
diff --git a/modules/conop/src/model_check.hh b/modules/conop/src/model_check.hh
new file mode 100644
index 0000000000000000000000000000000000000000..25bdfb88b85e92094e28c717bcf3840d78d64ce2
--- /dev/null
+++ b/modules/conop/src/model_check.hh
@@ -0,0 +1,30 @@
+#ifndef OST_CONOP_MODEL_CHECK_HH
+#define OST_CONOP_MODEL_CHECK_HH
+
+#include <ost/mol/entity_handle.hh>
+#include <ost/conop/diag.hh>
+#include <ost/conop/compound_lib.hh>
+namespace ost { namespace conop {
+
+class DLLEXPORT_OST_CONOP Checker {
+public:
+	Checker(CompoundLibPtr lib, const mol::EntityHandle& ent,
+			    DiagEngine& diags): lib_(lib), ent_(ent), diags_(diags),
+	                            checked_unk_res_(false)
+  {}
+  void CheckForUnknownAtoms();
+  void CheckForCompleteness(bool require_hydrogens=false);
+  void CheckForNonStandard();
+  mol::AtomHandleList GetHydrogens();
+  mol::AtomHandleList GetZeroOccupancy();
+  
+  const std::vector<Diag*>& GetDiags() const {  return diags_.GetDiags(); }
+private:
+	CompoundLibPtr      lib_;
+	mol::EntityHandle   ent_;
+	DiagEngine&         diags_;
+	bool                checked_unk_res_;
+};
+
+}} /* ost::conop */
+#endif
diff --git a/modules/conop/src/nonstandard.cc b/modules/conop/src/nonstandard.cc
index 5effd8d9014ca886d63bb50f5457cc487fa782f0..eeccdb60d16425dd1107629e41fb075100a7c0c3 100644
--- a/modules/conop/src/nonstandard.cc
+++ b/modules/conop/src/nonstandard.cc
@@ -35,57 +35,24 @@ using namespace ost::conop;
 
 namespace ost { namespace conop {
 
-namespace {
 
-bool CheckBackboneAtoms(ResidueHandle res)
-{
-  String atom_names[]={"N", "CA", "C", "O"};
-  std::vector<String> missing;
-  for (int i =0; i<4; ++i) {
-    if (!res.FindAtom(atom_names[i])) {
-      missing.push_back(atom_names[i]);
-    }
-  }
-  if (!missing.empty()) {
-    std::stringstream ss;
-    ss << "residue " << res.GetQualifiedName() << " is missing atoms ";
-    for (std::vector<String>::const_iterator
-         i=missing.begin(), e=missing.end(); i!=e; ++i) {
-      if (i!=missing.begin()) {
-        ss << ", ";
-      }
-      ss << *i;
-    }
-    LOG_WARNING(ss.str());
-    return false;
-  }
-  return true;
-}
-
-bool CheckCalphaAtom(ResidueHandle res)
+bool CopyResidue(ResidueHandle src_res, ResidueHandle dst_res, XCSEditor& edi)
 {
-  String atom_names[]={"N", "CA", "C", "O"};
-  std::vector<String> missing;
-  for (int i =0; i<4; ++i) {
-    if (!res.FindAtom(atom_names[i])) {
-      missing.push_back(atom_names[i]);
-    }
-  }
-  if (!res.FindAtom("CA")) {
-    LOG_WARNING("residue " << res.GetQualifiedName() << " is missing CA atom");
-    return false;
-  }
-  return true;
-}
-
+  // first let's get our hands on the component library
+  conop::BuilderP builder=conop::Conopology::Instance().GetBuilder("DEFAULT");
+  conop::RuleBasedBuilderPtr rbb=dyn_cast<conop::RuleBasedBuilder>(builder);
+  conop::CompoundLibPtr comp_lib=rbb->GetCompoundLib(); 
+  return CopyResidue(src_res, dst_res, edi, comp_lib); 
 }
 
-bool CopyResidue(ResidueHandle src_res, ResidueHandle dst_res, XCSEditor& edi)
+bool CopyResidue(ResidueHandle src_res, ResidueHandle dst_res, XCSEditor& edi, CompoundLibPtr comp_lib)
 {
   bool has_cbeta = false;
   bool ret;
-  if (src_res.GetName()==dst_res.GetName()) {
-    ret = CopyConserved(src_res, dst_res, edi, has_cbeta);
+  char parent_src = (comp_lib->FindCompound(src_res.GetName(),Compound::PDB))->GetOneLetterCode ();  
+  char parent_dst = (comp_lib->FindCompound(dst_res.GetName(),Compound::PDB))->GetOneLetterCode ();  
+  if (parent_src==parent_dst) {
+    ret = CopyConserved(src_res, dst_res, edi, has_cbeta, comp_lib);
   } else {
     ret = CopyNonConserved(src_res, dst_res, edi, has_cbeta);
   }
@@ -97,8 +64,19 @@ bool CopyResidue(ResidueHandle src_res, ResidueHandle dst_res, XCSEditor& edi)
   return ret;
 }
 
+
 bool CopyConserved(ResidueHandle src_res, ResidueHandle dst_res, XCSEditor& edi,
                    bool& has_cbeta)
+{
+  // first let's get our hands on the component library
+  conop::BuilderP builder=conop::Conopology::Instance().GetBuilder("DEFAULT");
+  conop::RuleBasedBuilderPtr rbb=dyn_cast<conop::RuleBasedBuilder>(builder);
+  conop::CompoundLibPtr comp_lib=rbb->GetCompoundLib(); 
+  return CopyConserved(src_res,dst_res,edi,has_cbeta,comp_lib);
+}
+
+bool CopyConserved(ResidueHandle src_res, ResidueHandle dst_res, XCSEditor& edi,
+                   bool& has_cbeta, CompoundLibPtr comp_lib)
 {
   // check if the residue name of dst and src are the same. In the easy 
   // case, the two residue names match and we just copy over all atoms.
@@ -111,10 +89,11 @@ bool CopyConserved(ResidueHandle src_res, ResidueHandle dst_res, XCSEditor& edi,
   } else if (src_res.GetName()=="MSE") {
     return CopyMSE(src_res, dst_res, edi, has_cbeta);
   } else {
-    return CopyModified(src_res, dst_res, edi, has_cbeta);
+    return CopyModified(src_res, dst_res, edi, has_cbeta, comp_lib);
   }
 }
 
+
 bool CopyIdentical(ResidueHandle src_res, ResidueHandle dst_res, XCSEditor& edi, 
                    bool& has_cbeta)
 {
@@ -161,7 +140,7 @@ bool CopyMSE(ResidueHandle src_res, ResidueHandle dst_res, XCSEditor& edi,
 }
 
 bool CopyModified(ResidueHandle src_res, ResidueHandle dst_res, 
-                  XCSEditor& edi, bool& has_cbeta)
+                  XCSEditor& edi, bool& has_cbeta, CompoundLibPtr comp_lib)
 {
   // FIXME: for now this functions ignores chirality changes of sidechain 
   //        chiral atoms. To detect those changes, we would need to store the 
@@ -172,11 +151,6 @@ bool CopyModified(ResidueHandle src_res, ResidueHandle dst_res,
   // doesn't have. If these two requirements are not met, we fall back to
   // CopyNonConserved.
   
-  // first let's get our hands on the component library
-  conop::BuilderP builder=conop::Conopology::Instance().GetBuilder("DEFAULT");
-  conop::RuleBasedBuilderPtr rbb=dyn_cast<conop::RuleBasedBuilder>(builder);
-  conop::CompoundLibPtr comp_lib=rbb->GetCompoundLib(); 
-
   CompoundPtr src_compound=comp_lib->FindCompound(src_res.GetName(), 
                                                   Compound::PDB);
   if (!src_compound) {
diff --git a/modules/conop/src/nonstandard.hh b/modules/conop/src/nonstandard.hh
index f8ad1cfa33d07b8d4c51db0b9019de340a882163..374694303e1d5d0f05626e7cc43d2f9c53139c5a 100644
--- a/modules/conop/src/nonstandard.hh
+++ b/modules/conop/src/nonstandard.hh
@@ -23,34 +23,55 @@
   Author: Marco Biasini, Juergen Haas
  */
 #include "module_config.hh"
-
+#include "compound_lib.hh"
 
 
 
 namespace ost { namespace conop {
 
 
-/// \brief copies all atom of src_res to dst_res 
+/// \brief copies all atom of src_res to dst_res, gets compound lib from builder
 /// \param has_cbeta will be set to true if the src_res has a cbeta and the 
 ///      dst_residue is not a glycine, it will be inserted if in the dst should
 ///      be one and in src it was not present
 
                              
 bool DLLEXPORT_OST_CONOP CopyResidue(ost::mol::ResidueHandle src_res,
-                             ost::mol::ResidueHandle dst_res, 
-                             ost::mol::XCSEditor& edi);
+                                     ost::mol::ResidueHandle dst_res,
+                                     ost::mol::XCSEditor& edi);
+
+/// \brief copies all atom of src_res to dst_res, requires a compound lib 
+/// \param has_cbeta will be set to true if the src_res has a cbeta and the 
+///      dst_residue is not a glycine, it will be inserted if in the dst should
+///      be one and in src it was not present
+bool DLLEXPORT_OST_CONOP CopyResidue(ost::mol::ResidueHandle src_res,
+                                     ost::mol::ResidueHandle dst_res,
+                                     ost::mol::XCSEditor& edi, CompoundLibPtr lib);
+
                              
 /// \brief copies all atom of src_res to dst_res
 /// \param has_cbeta will be set to true if the src_res has a cbeta and the 
-///      dst_residue is not a glycine
+///      dst_residue is not a glycine                             
+bool DLLEXPORT_OST_CONOP CopyIdentical(ost::mol::ResidueHandle src_res,
+                                       ost::mol::ResidueHandle dst_res,
+                                       ost::mol::XCSEditor& edi,
+                                       bool& has_cbeta);
+
+/// \brief copies atoms of src_res to dst_res, gets compound lib from builder
+///
+/// src_res and dst_res are thought to be conserved, e.g. the parent standard 
+/// amino acid of both residues is the same. This includes cases where e.g. the 
+/// src_rs is and MSE and the dst_res is a MET. This function automatically 
+/// tries to do the right thing an keep as many atoms as possible from src_res
+
 
                              
-bool DLLEXPORT_OST_CONOP CopyIdentical(ost::mol::ResidueHandle src_res,
-                             ost::mol::ResidueHandle dst_res, 
-                             ost::mol::XCSEditor& edi, 
-                             bool& has_cbeta);
+bool DLLEXPORT_OST_CONOP CopyConserved(ost::mol::ResidueHandle src_res, 
+                                       ost::mol::ResidueHandle dst_res,
+                                       ost::mol::XCSEditor& edi,
+                                       bool& has_cbeta, CompoundLibPtr lib);
 
-/// \brief copies atoms of src_res to dst_res
+/// \brief copies atoms of src_res to dst_res, requires compound lib
 ///
 /// src_res and dst_res are thought to be conserved, e.g. the parent standard 
 /// amino acid of both residues is the same. This includes cases where e.g. the 
@@ -60,9 +81,10 @@ bool DLLEXPORT_OST_CONOP CopyIdentical(ost::mol::ResidueHandle src_res,
 
                              
 bool DLLEXPORT_OST_CONOP CopyConserved(ost::mol::ResidueHandle src_res, 
-                             ost::mol::ResidueHandle dst_res, 
-                             ost::mol::XCSEditor& edi,
-                             bool& has_cbeta);
+                                       ost::mol::ResidueHandle dst_res,
+                                       ost::mol::XCSEditor& edi,
+                                       bool& has_cbeta);
+
 
 /// \brief construct dst_res in case src_res and dst_res are not conserved.
 /// 
@@ -71,24 +93,24 @@ bool DLLEXPORT_OST_CONOP CopyConserved(ost::mol::ResidueHandle src_res,
 
 
 bool DLLEXPORT_OST_CONOP CopyNonConserved(ost::mol::ResidueHandle src_res, 
-                                ost::mol::ResidueHandle dst_res, 
-                                ost::mol::XCSEditor& edi, 
-                                bool& has_cbeta);
+                                          ost::mol::ResidueHandle dst_res,
+                                          ost::mol::XCSEditor& edi,
+                                          bool& has_cbeta);
 
 /// \brief construct dst_res from src_res when src_res is an MSE
 
 bool DLLEXPORT_OST_CONOP CopyMSE(ost::mol::ResidueHandle src_res, 
-                       ost::mol::ResidueHandle dst_res, 
-                       ost::mol::XCSEditor& edi, 
-                       bool& has_cbeta);
+                                 ost::mol::ResidueHandle dst_res,
+                                 ost::mol::XCSEditor& edi,
+                                 bool& has_cbeta);
                        
 /// \brief construct a dst_res with only atoms matching the standard aminoacid
 /// from src_res when src_res is an is modified
                             
 bool DLLEXPORT_OST_CONOP CopyModified(ost::mol::ResidueHandle src_res, 
-                            ost::mol::ResidueHandle dst_res, 
-                            ost::mol::XCSEditor& edi, 
-                            bool& has_cbeta);
+                                      ost::mol::ResidueHandle dst_res,
+                                      ost::mol::XCSEditor& edi,
+                                      bool& has_cbeta, CompoundLibPtr lib);
 
 
 
diff --git a/modules/conop/src/rule_based_builder.cc b/modules/conop/src/rule_based_builder.cc
index 33d33c667faebb47593eebe53f28285c448b1956..529fbcbc65f29be69c4b6391b346e45d9f382e3a 100644
--- a/modules/conop/src/rule_based_builder.cc
+++ b/modules/conop/src/rule_based_builder.cc
@@ -238,18 +238,20 @@ void RuleBasedBuilder::ConnectAtomsOfResidue(mol::ResidueHandle rh)
       mol::AtomHandle a1=this->LocateAtom(atoms, bond.atom_one);
       mol::AtomHandle a2=this->LocateAtom(atoms, bond.atom_two);
       if (a1.IsValid() && a2.IsValid()) { 
-	if (this->GetBondFeasibilityCheck()==false) {
-          if (this->GetStrictHydrogenMode() && (a1.GetElement()=="H" || a2.GetElement()=="D")) {
+        if (this->GetBondFeasibilityCheck()==false) {
+          if (this->GetStrictHydrogenMode() && (a1.GetElement()=="H" || 
+                                                a2.GetElement()=="D")) {
             continue;
           }
           e.Connect(a1, a2, bond.order);
-	} else { 
-	  if (IsBondFeasible(a1, a2)) {
-	    if (this->GetStrictHydrogenMode() && (a1.GetElement()=="H" || a2.GetElement()=="D")) {
+        } else { 
+          if (IsBondFeasible(a1, a2)) {
+            if (this->GetStrictHydrogenMode() && (a1.GetElement()=="H" || 
+                                                  a2.GetElement()=="D")) {
               continue;
-	    }
+            }
             e.Connect(a1, a2, bond.order);
-	  }
+          }
         }
       }
   }
diff --git a/modules/conop/tests/test_rule_based_builder.cc b/modules/conop/tests/test_rule_based_builder.cc
index 364ebf387be1b5bd6cd10bd4b721a56e85a1ceef..bc89d94a5a297f1e3c690d8ddcc05a0a643e5dda 100644
--- a/modules/conop/tests/test_rule_based_builder.cc
+++ b/modules/conop/tests/test_rule_based_builder.cc
@@ -20,7 +20,7 @@
 #include <ost/mol/mol.hh>
 #include <ost/platform.hh>
 #include <ost/conop/rule_based_builder.hh>
-
+#include <ost/conop/conop.hh>
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 #include <boost/test/auto_unit_test.hpp>
@@ -149,6 +149,139 @@ ResidueHandle make_defective_uracil2(ChainHandle chain)
   return res;
 }
 
+ResidueHandle make_1zk(ChainHandle chain)
+{
+  XCSEditor edi=chain.GetEntity().EditXCS();
+  ResidueHandle r=edi.AppendResidue(chain, "1ZK");
+  edi.InsertAtom(r, "C", geom::Vec3(3.946, 3.520, 10.861),"C");
+  edi.InsertAtom(r, "C1", geom::Vec3(6.308, 3.824, 8.036),"C");
+  edi.InsertAtom(r, "CA", geom::Vec3(4.856, 4.282, 9.931),"C");
+  edi.InsertAtom(r, "C2", geom::Vec3(6.770, 5.099, 8.019),"C");
+  edi.InsertAtom(r, "C3", geom::Vec3(7.805, 5.484, 7.142),"C");
+  edi.InsertAtom(r, "C4", geom::Vec3(8.363, 4.590, 6.284),"C");
+  edi.InsertAtom(r, "C5", geom::Vec3(8.469, 2.345, 5.318),"C");
+  edi.InsertAtom(r, "C6", geom::Vec3(7.986, 1.072, 5.322),"C");
+  edi.InsertAtom(r, "C4A", geom::Vec3(7.885, 3.277, 6.208),"C");
+  edi.InsertAtom(r, "C7", geom::Vec3(6.949, 0.682, 6.190),"C");
+  edi.InsertAtom(r, "C8", geom::Vec3(6.398, 1.548, 7.074),"C");
+  edi.InsertAtom(r, "C9", geom::Vec3(4.018, 0.269, 12.183),"C");
+  edi.InsertAtom(r, "C1A", geom::Vec3(6.824, 2.882, 7.117),"C");
+  edi.InsertAtom(r, "O", geom::Vec3(3.224, 4.213, 11.565),"O");
+  edi.InsertAtom(r, "O1", geom::Vec3(5.331, 3.476, 8.904),"O");
+  edi.InsertAtom(r, "O3", geom::Vec3(5.748, -4.044, 14.612),"O");
+  edi.InsertAtom(r, "N", geom::Vec3(3.855, 2.201, 10.790),"N");
+  edi.InsertAtom(r, "N1", geom::Vec3(4.814, 0.719, 13.173),"N");
+  edi.InsertAtom(r, "CA1", geom::Vec3(3.077, 1.346, 11.644),"C");
+  edi.InsertAtom(r, "O2", geom::Vec3(4.203, -0.810, 11.651),"O");
+  edi.InsertAtom(r, "O4", geom::Vec3(7.311, -5.667, 18.880),"O");
+  edi.InsertAtom(r, "CB", geom::Vec3(1.856, 0.712, 11.049),"C");
+  edi.InsertAtom(r, "CG", geom::Vec3(1.015, 1.845, 10.511),"C");
+  edi.InsertAtom(r, "ND1", geom::Vec3(1.467, 2.439, 9.321),"N");
+  edi.InsertAtom(r, "N2", geom::Vec3(6.478, -3.958, 16.751),"N");
+  edi.InsertAtom(r, "CD2", geom::Vec3(-0.105, 2.479, 10.887),"C");
+  edi.InsertAtom(r, "CE1", geom::Vec3(0.638, 3.428, 9.002),"C");
+  edi.InsertAtom(r, "NE2", geom::Vec3(-0.372, 3.461, 9.881),"N");
+  edi.InsertAtom(r, "N3", geom::Vec3(6.871, -7.136, 17.332),"N");
+  edi.InsertAtom(r, "CA2", geom::Vec3(5.881, -0.001, 13.808),"C");
+  edi.InsertAtom(r, "CB1", geom::Vec3(7.140, 0.860, 13.743),"C");
+  edi.InsertAtom(r, "CG1", geom::Vec3(7.503, 1.324, 12.299),"C");
+  edi.InsertAtom(r, "C21", geom::Vec3(5.126, -8.557, 18.179),"C");
+  edi.InsertAtom(r, "CD1", geom::Vec3(8.185, 0.142, 11.507),"C");
+  edi.InsertAtom(r, "CD21", geom::Vec3(8.420, 2.537, 12.325),"C");
+  edi.InsertAtom(r, "CE11", geom::Vec3(8.381, 0.689, 10.066),"C");
+  edi.InsertAtom(r, "CE2", geom::Vec3(8.907, 2.979, 10.922),"C");
+  edi.InsertAtom(r, "CZ", geom::Vec3(9.409, 1.807, 10.075),"C");
+  edi.InsertAtom(r, "CH", geom::Vec3(5.592, -0.511, 15.204),"C");
+  edi.InsertAtom(r, "OH", geom::Vec3(5.225, 0.377, 16.238),"O");
+  edi.InsertAtom(r, "CB11", geom::Vec3(4.426, -1.543, 15.170),"C");
+  edi.InsertAtom(r, "CA'", geom::Vec3(4.451, -2.730, 16.152),"C");
+  edi.InsertAtom(r, "CB'", geom::Vec3(3.124, -3.441, 16.281),"C");
+  edi.InsertAtom(r, "CG11", geom::Vec3(2.553, -3.986, 14.933),"C");
+  edi.InsertAtom(r, "C31", geom::Vec3(4.413, -7.811, 19.117),"C");
+  edi.InsertAtom(r, "CG2", geom::Vec3(3.204, -4.586, 17.345),"C");
+  edi.InsertAtom(r, "OB1", geom::Vec3(3.249, -0.875, 15.134),"O");
+  edi.InsertAtom(r, "CC", geom::Vec3(5.603, -3.655, 15.782),"C");
+  edi.InsertAtom(r, "CA3", geom::Vec3(7.592, -4.867, 16.603),"C");
+  edi.InsertAtom(r, "CD", geom::Vec3(7.274, -5.947, 17.691),"C");
+  edi.InsertAtom(r, "CB2", geom::Vec3(8.986, -4.351, 16.803),"C");
+  edi.InsertAtom(r, "CG12", geom::Vec3(9.488, -3.108, 16.016),"C");
+  edi.InsertAtom(r, "CG21", geom::Vec3(10.000, -5.461, 16.472),"C");
+  edi.InsertAtom(r, "CD11", geom::Vec3(9.099, -3.257, 14.571),"C");
+  edi.InsertAtom(r, "CM", geom::Vec3(6.587, -8.286, 18.106),"C");
+  edi.InsertAtom(r, "C41", geom::Vec3(3.045, -7.980, 19.287),"C");
+  edi.InsertAtom(r, "C51", geom::Vec3(2.423, -8.911, 18.456),"C");
+  edi.InsertAtom(r, "C61", geom::Vec3(3.164, -9.631, 17.518),"C");
+  edi.InsertAtom(r, "N11", geom::Vec3(4.497, -9.459, 17.386),"N");
+  return r;
+}
+
+void verify_1zk_connectivity(const ResidueHandle& r1) 
+{
+  BOOST_CHECK(BondExists(r1.FindAtom("C"), r1.FindAtom("CA")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C"), r1.FindAtom("O")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CA"), r1.FindAtom("O1")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C1"), r1.FindAtom("C2")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C1"), r1.FindAtom("C1A")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C1"), r1.FindAtom("O1")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C2"), r1.FindAtom("C3")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C3"), r1.FindAtom("C4")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C4"), r1.FindAtom("C4A")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C4A"), r1.FindAtom("C5")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C4A"), r1.FindAtom("C1A")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C5"), r1.FindAtom("C6")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C6"), r1.FindAtom("C7")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C7"), r1.FindAtom("C8")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C8"), r1.FindAtom("C1A")));
+  BOOST_CHECK(BondExists(r1.FindAtom("N"), r1.FindAtom("CA1")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CA1"), r1.FindAtom("C9")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CA1"), r1.FindAtom("CB")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C9"), r1.FindAtom("O2")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CB"), r1.FindAtom("CG")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CG"), r1.FindAtom("ND1")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CG"), r1.FindAtom("CD2")));
+  BOOST_CHECK(BondExists(r1.FindAtom("ND1"), r1.FindAtom("CE1")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CD2"), r1.FindAtom("NE2")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CE1"), r1.FindAtom("NE2")));
+  BOOST_CHECK(BondExists(r1.FindAtom("N1"), r1.FindAtom("CA2")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CA2"), r1.FindAtom("CB1")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CA2"), r1.FindAtom("CH")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CB1"), r1.FindAtom("CG1")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CG1"), r1.FindAtom("CD1")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CG1"), r1.FindAtom("CD21")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CD1"), r1.FindAtom("CE11")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CD21"), r1.FindAtom("CE2")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CE11"), r1.FindAtom("CZ")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CE2"), r1.FindAtom("CZ")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CH"), r1.FindAtom("OH")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CH"), r1.FindAtom("CB11")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CB11"), r1.FindAtom("CA'")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CB11"), r1.FindAtom("OB1")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CA'"), r1.FindAtom("CB'")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CA'"), r1.FindAtom("CC")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CB'"), r1.FindAtom("CG11")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CB'"), r1.FindAtom("CG2")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CC"), r1.FindAtom("O3")));
+  BOOST_CHECK(BondExists(r1.FindAtom("N2"), r1.FindAtom("CA3")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CA3"), r1.FindAtom("CD")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CA3"), r1.FindAtom("CB2")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CD"), r1.FindAtom("O4")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CB2"), r1.FindAtom("CG12")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CB2"), r1.FindAtom("CG21")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CG12"), r1.FindAtom("CD11")));
+  BOOST_CHECK(BondExists(r1.FindAtom("N3"), r1.FindAtom("CM")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CM"), r1.FindAtom("C21")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C21"), r1.FindAtom("C31")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C21"), r1.FindAtom("N11")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C31"), r1.FindAtom("C41")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C41"), r1.FindAtom("C51")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C51"), r1.FindAtom("C61")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C61"), r1.FindAtom("N11")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C"), r1.FindAtom("N")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C9"), r1.FindAtom("N1")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CC"), r1.FindAtom("N2")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CD"), r1.FindAtom("N3")));
+}
+
 void verify_nucleotide_connectivity(const ResidueHandle& res) 
 {
   BOOST_CHECK(BondExists(res.FindAtom("P"),
@@ -297,4 +430,27 @@ BOOST_AUTO_TEST_CASE(nucleotide_based_connect)
   
 }
 
+BOOST_AUTO_TEST_CASE(rule_based_connect_1zk) 
+{
+  SetPrefixPath(getenv("OST_ROOT"));
+  String lib_path=GetSharedDataPath()+"/compounds.chemlib";
+  CompoundLibPtr compound_lib=CompoundLib::Load(lib_path);  
+  if (!compound_lib) {
+    std::cout << "WARNING: skipping NUCLEOTIDE_BASED connect unit test. " 
+              << "Rule-based builder is required" << std::endl;
+    return;    
+  }
+
+  boost::shared_ptr<RuleBasedBuilder> drb_builder(new RuleBasedBuilder(compound_lib));
+  Conopology::Instance().RegisterBuilder(drb_builder, "RBB");
+  Conopology::Instance().SetDefaultBuilder("RBB");
+  drb_builder->SetBondFeasibilityCheck(false);
+  EntityHandle e=CreateEntity();
+  ChainHandle c=e.EditXCS().InsertChain("A");
+  ResidueHandle r1=make_1zk(c);
+  Conopology::Instance().ConnectAll(drb_builder, e);
+  Conopology::Instance().SetDefaultBuilder("HEURISTIC");
+  verify_1zk_connectivity(r1);
+}
+
 BOOST_AUTO_TEST_SUITE_END( );
diff --git a/modules/doc/install.rst b/modules/doc/install.rst
index 5b6693fefbb3e4a23a999b68e9738fbf0383c7e2..b92727bed28fe9e9885ac5f940f8b92ab3a768b5 100644
--- a/modules/doc/install.rst
+++ b/modules/doc/install.rst
@@ -48,7 +48,7 @@ If you would like to use the graphical user interface, also install:
  * `PyQt4 <http://www.riverbankcomputing.co.uk/software/pyqt/download>`_.
 
 In case you are compiling under Windows you have to install `Visualstudio
-2008 <http://www.microsoft.com/express/Downloads>`_. to compile the dependecies 
+2008 <http://www.microsoft.com/express/Downloads>`_. to compile the dependencies 
 and OpenStructure. We recommend to compile the dependecies manually. Enter the 
 directories where the dependencies are located in Tools->Options->Projects and 
 Solutions->VC++ directories. Choose 'bin' directories to enter program paths to 
@@ -68,11 +68,11 @@ OpenStructure uses `git` as the revision control system. The main repository can
 
   git clone https://dng.biozentrum.unibas.ch/git/ost.git <directory-name>
   
-The above command will clone OpenStructre into the directory called `directory-name`. If omitted, the directory will be called ost. Alternatively, you might consider getting one of the nightly source code snapshots from the `downloads section <http://www.openstructure.org/downloads/>`_.
+The above command will clone OpenStructure into the directory called `directory-name`. If omitted, the directory will be called ost. 
 
 .. note::
 
-  Some version of curl have have trouble with the certificate of the 
+  Some versions of curl have have trouble with the certificate of the 
   OpenStructure git server and fail to clone the repository. To work around 
   this, disable the SSL certificate verification with the following command:
   
@@ -103,14 +103,14 @@ OpenStructure uses `CMake <http://cmake.org>`_ for compiling and building the pr
 
 There are two kinds of options: Options that let you control the building behaviour, enabling and disabling the compilation of certain modules and options that let you tell CMake where to find the dependencies. All of them are passed to CMake with via `-D<opt>=<value>`.
 
-On Windows, use Tools -> VisualStudio commandline prompt from within VisualStudio)
+On Windows, use Tools -> VisualStudio -> commandline prompt from within VisualStudio
 
 Flag to choose build generator
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-CMake supports different build generators. On UNIX, that is MacOS X and Linux, the default build generator is Makefiles, but it is also possible to use other programs. For a list of supported build generators on your platform, start cmake without parameters. 
+CMake supports different build generators. On UNIX, i.e. MacOS X and Linux, the default build generator is Makefiles, but it is also possible to use other programs. For a list of supported build generators on your platform, start cmake without parameters. 
 
-On Windows you have to explicitly set the buil generator to "Visual Studio 9 2008":
+On Windows you have to explicitly set the build generator to "Visual Studio 9 2008"(or a later version):
 
 .. code-block:: bash
 
@@ -133,12 +133,28 @@ By default, `CMake <http://cmake.org>`_ searches the standard directories for de
 
  * `SYS_ROOT` controls the general prefix for searching libraries and headers.
    By default, it is set to `/`.
+   
+ * `COMPOUND_LIB` specifies the location of the compound library and
+   activates the rule-based-builder. The compound library is based on 
+   the component dictionary released by the PDB, and it specifies atoms
+   of a certain residue or connectivities between atoms etc. The 
+   :doc:`conop/compoundlib` compound library itself is created from the 
+   component dictionary by calling the OpenStructure chemdict_tool. 
+   By default this is switched off.
+
+ * `COMPILE_TMTOOLS` will activate bindings for TMAlign and TMScore, which are 
+   then available at python level. This option requires a Fortran compiler. 
+   By default this option is switched off.
+
+ * `USE_NUMPY` allows OpenStructure to pass back data in NumPy format. By 
+   default this is switched off.
 
 Build Options
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
- * `ENABLE_UI` controls whether to build the graphical user interface module. By
+ * `ENABLE_GUI` controls whether to build the graphical user interface module. By
    default it is set to true. 
+
  * `ENABLE_IMG` controls whether to build the image processing module. This will
    enable support for density maps, and general image processing in 1, 2 an 3
    dimensions. By default it is set to true. 
@@ -151,6 +167,17 @@ Build Options
    
  * If `OPTIMIZE` is set to 1, an optimized version of OpenStructure is built.
 
+ * `PREFIX` specifies the location on the file system where to install 
+   OpenStructure
+
+ * `USE_DOUBLE_PRECISION` will switch on double precision within OpenStructure. 
+   By default this is switched off.
+
+ * `ENABLE_STATIC` allows some parts of OpenStructure to be statically linked 
+   and thus can be used more easily across a heterogeneous setup, e.g. older 
+   systems and newer systems.
+
+
 Example Configurations
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
@@ -209,3 +236,4 @@ To get the newest changes from the central git repository, enter
   git pull
 
 in your terminal. This will fetch the newest changes.
+
diff --git a/modules/doc/intro-01.rst b/modules/doc/intro-01.rst
index 8534e9b55889b1b555191fbb9d33c98e506382c1..f7d791d6fadcb1f12717e542bd3307230b28bc13 100644
--- a/modules/doc/intro-01.rst
+++ b/modules/doc/intro-01.rst
@@ -16,6 +16,15 @@ stored in a PDB file is an *entity* and we decided to follow this convention
 in OpenStructure. You will hear this word all the time, but you can replace 
 the word entity with molecule (or most of the time even protein) in your head.
 
+Loading a PDB file leaves you with an :class:`~ost.mol.EntityHandle`. This is
+the central class holding together :class:`chains <ost.mol.ChainHandle>`,
+:class:`residues <ost.mol.ResidueHandle>` and
+:class:`atoms <ost.mol.AtomHandle>` in a straight-forward hierarchy. This
+hierarchy will always be intact: there are no atoms without a residue they
+belong to and no residues without chains which have to belong to an entity.
+Beside the molecule itself, there are a lot of additional attributes stored in
+the entity, like the
+:attr:`centre of mass <ost.mol.EntityHandle.center_of_mass>`.
 
 To load a PDB file, simply type
 
@@ -73,13 +82,6 @@ what bonds we have in there:
   for bond in fragment.bonds:
     print bond
     
-From these short code examples we already see how the entity is structured: On 
-one hand we have a hierarchy of chains, residues and atoms. On the other hand, 
-we have bonds that form a network overlayed on the hierarchy. An important 
-feature of entities is that we can always assume that the hierarchy is intact. 
-You will never find an atom without residues, no residue can exist without a 
-parent chain and chains belong always to an entity. 
-
 Let There Be Shiny Graphics
 --------------------------------------------------------------------------------
 
@@ -104,24 +106,24 @@ Introduction to Views
 --------------------------------------------------------------------------------
 
 Often during processing and visualisation of data, only parts of a protein 
-structure are of interest. This realisation has had a major impact on the design 
-of OpenStructure and is tied very deeply into the core of the framework. 
+structure are of interest. This realisation has had a major impact on the
+design of OpenStructure and is tied very deeply into the core of the framework. 
 Subparts of structure are modelled as so-called :class:`EntityViews 
-<ost.mol.EntityView>`. You can think of them as a selection of chains, residues, 
-atoms and bonds of an entity. A views has almost the same interface as the 
-underlying entity, making it very easy to mix entity views with handles in 
-Python due to the dynamic nature of the language. An algorithm that is written 
-for entities will almost always (with some care) also work for 
+<ost.mol.EntityView>`. You can think of them as a selection of chains,
+residues, atoms and bonds of an entity stored in a variable. A view has almost
+the same interface as the underlying entity, making it very easy to mix entity
+views with handles in Python due to the dynamic nature of the language. An
+algorithm that is written for entities will almost always (with some care) also
+work for 
 :class:`EntityHandles <ost.mol.EntityHandle>`. This is referred to as 
 `duck-typing <http://en.wikipedia.org/wiki/Duck_typing>`_ (I don' t care if it 
-is a duck as long as it looks like a duck), a concept used all over the place in Python. 
-
-The view consists of one chain, one residue and two atoms. Again the same rule 
-applies: No atom can be part of the view without it's residue. In this example, 
-no bonds are included, since there is at most one atom per bond in the original structure.
+is a duck as long as it looks like a duck), a concept used all over the place
+in Python. For views, the same rule as for
+:class:`entities <ost.mol.EntityHandle>` applies: No atom can be part of the
+view without it's residue...
 
 To familiarize yourself with the concept of views, we will use the fragment in 
-the 3D window.
+the 3D window of the last example.
 
 We will use several ways to select parts of our fragment:
  * By using a dedicated query language
@@ -223,3 +225,5 @@ select the backbone atoms and then save it:
 
 That's it for the mol module. Continue with :doc:`part two<intro-02>` of the 
 tutorial.
+
+..  LocalWords:  attr
diff --git a/modules/doc/intro-02.rst b/modules/doc/intro-02.rst
index 7dbd61172f66a7c743a932229ccf7d9839dca5e2..e4c93d62e3c8ad121c8b37beef2d8be3d04afc2f 100644
--- a/modules/doc/intro-02.rst
+++ b/modules/doc/intro-02.rst
@@ -11,10 +11,11 @@ OpenStructure features a :mod:`~ost.img` module that is dedicated to the
 manipulation of images/density maps. The images or density maps can either be 
 one-, two- or three-dimensional. The most common formats used in X-ray and 
 electron  crystallography and atomic force microscope are supported in addition 
-to several general purpose image formats. See `supported file formats` for 
-details. The :mod:`~ost.img` module was originally developed as part of the 
-Image Processing Library & Toolbox IPLT. More documentation and examples can 
-also be found on the `IPLT website <http://www.iplt.org>`_.
+to several general purpose image formats. See
+:doc:`supported file formats <io/formats>` for details. The :mod:`~ost.img`
+module was originally developed as part of the Image Processing Library &
+Toolbox IPLT. More documentation and examples can also be found on the
+`IPLT website <http://www.iplt.org>`_.
 
 To load a density map, type
 
diff --git a/modules/doc/intro.rst b/modules/doc/intro.rst
index c00c465f034eebea7b38190290cdf1fe9f503c63..9da3856631e82265e0dc301a0cea9eb71801d191 100644
--- a/modules/doc/intro.rst
+++ b/modules/doc/intro.rst
@@ -31,13 +31,13 @@ walk-through of the basic functionality you will be using in your everyday work,
 Getting ready to rumble
 --------------------------------------------------------------------------------
 
-The files we will be using in the tutorial are available in the examples folder 
-that comes with OpenStructure. Depending on your platform, the examples are 
-located at a different location:
+The files we will be using in the tutorial are available in the examples
+directory that comes with OpenStructure. Depending on your platform, the
+examples are located at a different location:
 
- * on *MacOS X* the files are located inside the application bundle. The file 
-   browser will automatically point to the examples.
- * on *Linux* and *Windows* PREFIX/share/openstructure/examples, where PREFIX is 
+ * on *MacOS X* the files are located inside the application bundle (DNG.app).
+   The file browser will automatically point to the examples.
+ * on *Linux* PREFIX/share/openstructure/examples, where PREFIX is 
    the path to the directory containing OpenStructure.
 
 Starting DNG
@@ -47,16 +47,16 @@ The graphical user interface of OpenStructure is called DNG (Dino/DeepView Next
 Generation). To start it, 
 
  * on *MacOS X* double click DNG.app
- * on *Windows* double click dng.bat inside the PREFIX/bin directory
  * on *Linux* fire up a terminal change into the OpenStructure installation 
    directory and type 'bin/dng'. If you have the binary directory in the PATH, 
    typing dng is sufficient.
 
 Interactive Python Shell
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. image:: images/100208_OpenStructure_UI_Colored.png
 
 Now we will enter commands in the Python Shell (in the screenshot above, the 
-python shell is located at the bottom of the main window). If you want to get 
+python shell (shown in green) is located at the right of the main window). If you want to get 
 more information on any object, function or class, the python help command may 
 be useful. For example:
 
diff --git a/modules/doc/table.rst b/modules/doc/table.rst
index 08beaad21d3e558db80ae2e3acee0fb425587b4d..19d9c3c278a08f908fe7c8d712d4881ac4774aab 100644
--- a/modules/doc/table.rst
+++ b/modules/doc/table.rst
@@ -4,23 +4,98 @@
 .. module:: ost.table
   :synopsis: Working with tabular data
   
-This module defines the table class that provides convenient functionality to work with tabular data. It features functions to calculate statistical moments, e.g. mean, standard deviations as well as functionality to plot the data using matplotlib.
+This module defines the table class that provides convenient functionality to
+work with tabular data. It features functions to calculate statistical moments,
+e.g. mean, standard deviations as well as functionality to plot the data using
+matplotlib.
 
 Basic Usage
 --------------------------------------------------------------------------------
 
+Populate table with data:
+
 .. code-block:: python
 
   from ost.table import *
+
   # create table with two columns, x and y both of float type
   tab=Table(['x', 'y'], 'ff')
   for x in range(1000):
     tab.AddRow([x, x**2])
+
   # create a plot
   plt=tab.Plot('x', 'y')
+
   # save resulting plot to png file
   plt.savefig('x-vs-y.png')
 
+Iterating over table items:
+
+.. code-block:: python
+
+  # load table from file
+  tab=Table.Load(...)
+
+  # get column index for col 'foo'
+  idx=tab.GetColIndex('foo')
+
+  # iterate over all rows
+  for row in tab.rows:
+    # print complete row
+    print row
+
+    # print value for column 'foo'
+    print row[idx]
+
+  # iterate over all rows of selected columns
+  for foo, bar in tab.Zip('foo','bar'):
+    print foo, bar
+
+
+Functions You Might be Interested In
+--------------------------------------------------------------------------------
+============================================= ============================================
+**Adding/Removing/Reordering data**
+: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.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
+
+**Input/Output**
+:meth:`~ost.table.Table.Save`                 save a table to a file
+:meth:`~ost.table.Table.Load`                 load a table from a file
+:meth:`~ost.table.Table.ToString`             convert a table to a string for printing
+
+**Simple Math**
+:meth:`~ost.table.Table.Min`                  compute the minimum of a column
+:meth:`~ost.table.Table.Max`                  compute the maximum of a column
+:meth:`~ost.table.Table.Sum`                  compute the sum of a column
+:meth:`~ost.table.Table.Mean`                 compute the mean of a column
+:meth:`~ost.table.Table.RowMean`              compute the mean for each row
+:meth:`~ost.table.Table.Median`               compute the median of a column
+:meth:`~ost.table.Table.StdDev`               compute the standard deviation of a column
+:meth:`~ost.table.Table.Count`                compute the number of items in a column
+
+**More Sophisticated Math**
+:meth:`~ost.table.Table.Correl`               compute Pearson's correlation coefficient
+:meth:`~ost.table.Table.SpearmanCorrel`       compute Spearman's rank correlation coefficient
+:meth:`~ost.table.Table.ComputeMCC`           compute Matthew's correlation coefficient
+:meth:`~ost.table.Table.ComputeROC`           compute receiver operating characteristics (ROC)
+:meth:`~ost.table.Table.ComputeEnrichment`    compute enrichment
+:meth:`~ost.table.Table.GetOptimalPrefactors` compute optimal coefficients for linear combination of columns
+
+**Plot**
+:meth:`~ost.table.Table.Plot`                 Plot data in 1, 2 or 3 dimensions
+: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
+
+
+============================================= ============================================
 
 The Table class
 --------------------------------------------------------------------------------
diff --git a/modules/doc/users.rst b/modules/doc/users.rst
new file mode 100644
index 0000000000000000000000000000000000000000..a24b4aad076970cf8a64abc9316f88479ce6459e
--- /dev/null
+++ b/modules/doc/users.rst
@@ -0,0 +1,20 @@
+Reporting a Problem
+==============================================================================
+
+
+When you run into a problem in OST or have question regarding it's usage, there 
+are a few things you can do to make the life of people helping you easier. If 
+you follow these simple steps, you will make sure, people understand what you are 
+after and will get a response more quickly.
+
+ * Provide a short explanation of what you tried to accomplish, the result you 
+   were expecting and what you got instead. A good example would be: **I tried 
+   to read the attached PDB file. The file looks clean to me, but OST fails with 
+   the following error: "invalid coordinate on line 4."**
+ * If possible, attach a small script that reproduces the problem.
+ * Include the relevant error message in your report
+ * Include the version of OpenStructure you are using
+ * Specify your operating system
+ * If you compiled OpenStructure manually, also include the version for Qt, 
+   Eigen, Python and Boost.
+ 
diff --git a/modules/geom/pymod/export_composite3.cc b/modules/geom/pymod/export_composite3.cc
index 47988768cc7baf28cb4560895ad43cbdddb8e544..4a37c79f70939446f4a131a1e219ce7e6dc73a21 100644
--- a/modules/geom/pymod/export_composite3.cc
+++ b/modules/geom/pymod/export_composite3.cc
@@ -33,6 +33,7 @@ void export_Composite3()
     .def("GetDirection",&Line3::GetDirection)
     .add_property("origin", &Line3::GetOrigin)
     .add_property("direction", &Line3::GetDirection)
+    .def(self_ns::str(self))
   ;
 
 { // scope
@@ -169,6 +170,7 @@ scope PlaneScope =
          return_value_policy<copy_const_reference>()))
     .add_property("center", &AlignedCuboid::GetCenter)
     .add_property("size", &AlignedCuboid::GetSize)
+    .def(self_ns::str(self))
   ;
 }
 
diff --git a/modules/geom/src/composite3.hh b/modules/geom/src/composite3.hh
index e780f8deb4d126042ae60e5ed41ee51d97f902d6..8e88050366915bac120bcaf5ccdf4c8d43164a5c 100644
--- a/modules/geom/src/composite3.hh
+++ b/modules/geom/src/composite3.hh
@@ -27,6 +27,7 @@
 #include "mat3.hh"
 #include "quat.hh"
 
+#include "module_config.hh"
 
 /*
   composite classes in 3D space
@@ -47,7 +48,7 @@ private:
   Vec3 ori_,dir_;
 };
 
-std::ostream& operator<<(std::ostream& s, const Line3& l);
+DLLEXPORT_OST_GEOM std::ostream& operator<<(std::ostream& s, const Line3& l);
 
 class DLLEXPORT_OST_GEOM Plane {
 public:
@@ -80,7 +81,7 @@ private:
   Real p_;
 };
 
-class DLLEXPORT Sphere {
+class DLLEXPORT_OST_GEOM Sphere {
 public:
   Sphere();
   Sphere(const Vec3& origin, Real r);
@@ -98,7 +99,7 @@ private:
 ///     half extent
 /// 
 /// \relates Cuboid
-class DLLEXPORT CuboidAxis {
+class DLLEXPORT_OST_GEOM CuboidAxis {
 public:
   CuboidAxis(): axis_(), half_extent_(0.0)
   { }
@@ -112,7 +113,7 @@ private:
 };
 
 /// \brief arbitrary oriented bounding cuboid
-class DLLEXPORT Cuboid {
+class DLLEXPORT_OST_GEOM Cuboid {
 public:
   Cuboid();
   Cuboid(const Vec3& center, const CuboidAxis& a, 
@@ -140,7 +141,7 @@ private:
   CuboidAxis      axes_[3];
 };
 
-class DLLEXPORT Rotation3
+class DLLEXPORT_OST_GEOM Rotation3
 {
 public:
   Rotation3();
@@ -184,8 +185,8 @@ private:
 
 typedef std::vector<Rotation3> Rotation3List;
 
-DLLEXPORT Rotation3List ImportEulerAngles (const boost::filesystem::path& loc);
-DLLEXPORT void ExportEulerAngles (const Rotation3List& rot_list,
+DLLEXPORT_OST_GEOM Rotation3List ImportEulerAngles (const boost::filesystem::path& loc);
+DLLEXPORT_OST_GEOM void ExportEulerAngles (const Rotation3List& rot_list,
                                   const boost::filesystem::path& loc);
 
 } // ns
diff --git a/modules/geom/src/exc.hh b/modules/geom/src/exc.hh
index 67eda2278e8ec380aa154dc16552e04b70a782cc..0c4390030e9d6d3c520a9876722e8ce564be4134 100644
--- a/modules/geom/src/exc.hh
+++ b/modules/geom/src/exc.hh
@@ -33,19 +33,19 @@ namespace geom {
   code may choose to catch exceptions from
   the geom library undifferentiatedly
 */
-class DLLEXPORT_OST_GEOM GeomException: public std::runtime_error {
+class DLLEXPORT GeomException: public std::runtime_error {
 public:
   GeomException(const String& m):
     std::runtime_error(m) {}
 };
 
-class DLLEXPORT_OST_GEOM DivideByZeroException: public GeomException {
+class DLLEXPORT DivideByZeroException: public GeomException {
 public:
   DivideByZeroException(const String& m="Divide By Zero"):
     GeomException(m) {}
 };
 
-class DLLEXPORT_OST_GEOM OutOfRangeException: public GeomException {
+class DLLEXPORT OutOfRangeException: public GeomException {
 public:
   OutOfRangeException(const String& m="Out Of Range"):
     GeomException(m) {}
diff --git a/modules/geom/src/vec3.cc b/modules/geom/src/vec3.cc
index 6e657081fb7ed1496d85514b29f390aa52d6028e..8909ce8b8648879741c01965ef13961614223e6b 100644
--- a/modules/geom/src/vec3.cc
+++ b/modules/geom/src/vec3.cc
@@ -28,7 +28,13 @@
 
 namespace geom {
 
+
+#if OST_DOUBLE_PRECISION
+typedef Eigen::Matrix3d EMat3;
+#else
 typedef Eigen::Matrix3f EMat3;
+#endif
+
 
 Mat3 Vec3List::GetInertia() const
 {
@@ -101,16 +107,17 @@ Line3 Vec3List::FitCylinder(const Vec3& initial_direction, const Vec3& center) c
   radius/=Real(n_res);
   res_sum=0.0;
   for (Vec3List::const_iterator i=this->begin(),e=this->end(); i!=e; ++i) {
-    res_sum+=pow(Distance(axis,(*i))-radius,2.);
+    Real r=Distance(axis,(*i))-radius;
+    res_sum+=r*r;
   }
   unsigned long k=0;
   err=2.0*prec;
-  while (err>prec and k<n_step) {
+  while (err>prec && k<n_step) {
     res_sum_old=res_sum;
     axis_old=axis;
     radius=0.0;
     if (k>50) {
-      delta=delta_0*pow((50./k),2.0);
+      delta=delta_0*50.0*50.0/(k*k);
     }
     for (Vec3List::const_iterator i=this->begin(),e=this->end(); i!=e; ++i) {
       radius+=Distance(axis,(*i));
@@ -127,7 +134,8 @@ Line3 Vec3List::FitCylinder(const Vec3& initial_direction, const Vec3& center) c
       }
       radius/=Real(n_res);
       for (Vec3List::const_iterator i=this->begin(),e=this->end(); i!=e; ++i) {
-        res_sum+=pow(Distance(axis,(*i))-radius,2.);
+        Real r=Distance(axis,(*i))-radius;
+        res_sum+=r*r;
       }
       gradient[j]=(res_sum-res_sum_old)/delta;
     }
@@ -143,7 +151,8 @@ Line3 Vec3List::FitCylinder(const Vec3& initial_direction, const Vec3& center) c
     radius/=Real(n_res);
     res_sum=0.0;
     for (Vec3List::const_iterator i=this->begin(),e=this->end(); i!=e; ++i) {
-      res_sum+=pow(Distance(axis,(*i))-radius,2.);
+      Real r=Distance(axis,(*i))-radius;
+      res_sum+=r*r;
     }
     err=fabs((res_sum-res_sum_old)/float(n_res));
     k++;
diff --git a/modules/geom/src/vecmat3_op.cc b/modules/geom/src/vecmat3_op.cc
index 50b5b612e939d66e6d8119ddced416ff87e52f99..8a1debee816113fc87d196379b6e0230a241238d 100644
--- a/modules/geom/src/vecmat3_op.cc
+++ b/modules/geom/src/vecmat3_op.cc
@@ -196,7 +196,7 @@ Real DihedralAngle(const Vec3& p1, const Vec3& p2, const Vec3& p3,
 Real MinDistance(const Vec3List& l1, const Vec3List& l2)
 { 
   // returns the minimal distance between two sets of points (Vec3List)
-  if (l1.size()==0 || l2.size()==0){throw std::runtime_error("cannot calculate minimal distance: empty Vec3List");}
+  if (l1.size()==0 || l2.size()==0){throw GeomException("cannot calculate minimal distance: empty Vec3List");}
   Real min=Length2(*l1.begin()-*l2.begin());
   Real d;
   for (Vec3List::const_iterator p1=l1.begin(),e1=l1.end(); p1!=e1; p1++) {
@@ -212,7 +212,7 @@ Real MinDistanceWithPBC(const Vec3List& l1, const Vec3List& l2, Vec3& basis_vec)
 { 
   // returns the minimal distance between two sets of points (Vec3List)
   // given the periodic boundary condition along x,y,z given in the basis_vec
-  if (l1.size()==0 || l2.size()==0){throw std::runtime_error("cannot calculate minimal distance: empty Vec3List");}
+  if (l1.size()==0 || l2.size()==0){throw GeomException("cannot calculate minimal distance: empty Vec3List");}
   Real min=Length2(*l1.begin()-*l2.begin());
   Real d;
   Vec3 v;
diff --git a/modules/geom/src/vecmat3_op.hh b/modules/geom/src/vecmat3_op.hh
index 5489ea9e8f1c48f669053fafa45f14220b52384f..49d466081cb45b913dfb9b6ae2638f9a84030dcd 100644
--- a/modules/geom/src/vecmat3_op.hh
+++ b/modules/geom/src/vecmat3_op.hh
@@ -211,15 +211,15 @@ inline Real DistanceWithPBC(const Vec3& v1, const Vec3& v2, const Vec3& basis_ve
   return sqrt(Distance2WithPBC(v1, v2, basis_vec));
 }
 //! returns the minimal distance between the points in two Vec3List
-Real MinDistance(const Vec3List& l1, const Vec3List& l2);
+DLLEXPORT_OST_GEOM Real MinDistance(const Vec3List& l1, const Vec3List& l2);
 //! returns the minimal distance between the points in two Vec3List 
 //  with periodic boundaries in x,y,z given in basis_vec
-Real MinDistanceWithPBC(const Vec3List& l1, const Vec3List& l2, Vec3& basis_vec);
+DLLEXPORT_OST_GEOM Real MinDistanceWithPBC(const Vec3List& l1, const Vec3List& l2, Vec3& basis_vec);
 
 //!wraps a vector in a box with periodic boundaries
-Vec3 WrapVec3(const Vec3& v1,const Vec3& box_center,const Vec3& basis_vec);
-//!wraps all the verctors in a Vec3List in a box with periodic boundaries
-Vec3List WrapVec3List(const Vec3List& vl,const Vec3& box_center,const Vec3& basis_vec);
+DLLEXPORT_OST_GEOM Vec3 WrapVec3(const Vec3& v1,const Vec3& box_center,const Vec3& basis_vec);
+//!wraps all the vectors in a Vec3List in a box with periodic boundaries
+DLLEXPORT_OST_GEOM Vec3List WrapVec3List(const Vec3List& vl,const Vec3& box_center,const Vec3& basis_vec);
 
   
 } // ns
diff --git a/modules/geom/tests/test_composite2.cc b/modules/geom/tests/test_composite2.cc
index 5e437a730a79a0c9ccaa0f6066210f70c22c6d94..acec86fb900f5b32460c1cfb4fdb85855474b9be 100644
--- a/modules/geom/tests/test_composite2.cc
+++ b/modules/geom/tests/test_composite2.cc
@@ -37,6 +37,17 @@ BOOST_AUTO_TEST_CASE(line_init2)
   BOOST_CHECK_EQUAL(geom::Length(line.GetDirection()), 1.0);
 }
 
+BOOST_AUTO_TEST_CASE(rectangle2)
+{
+  Rectangle2 rect;
+  try{
+    BOOST_CHECK_THROW(rect[2]=geom::Vec2(0,0), OutOfRangeException);
+  }catch(...)
+  {
+    BOOST_ERROR("Failed to catch OutOfRangeException");
+  }
+}
+
 BOOST_AUTO_TEST_CASE(is_on_line2)
 {
   Line2 line(geom::Vec2(0,0), geom::Vec2(1,0));
diff --git a/modules/geom/tests/test_composite3.cc b/modules/geom/tests/test_composite3.cc
index 092a2a354cf95ba55a303b0dcc6e64decb4a65a1..317068280dd1a761c288e88b2a45e53089929547 100644
--- a/modules/geom/tests/test_composite3.cc
+++ b/modules/geom/tests/test_composite3.cc
@@ -151,8 +151,12 @@ BOOST_AUTO_TEST_CASE(func_composite3)
   BOOST_CHECK(Equal(IntersectionPoint(l2,l3), v3));
   
   BOOST_CHECK(!AreIntersecting(l3, l4));
-  
-  BOOST_CHECK_THROW(IntersectionPoint(l3,l4), GeomException);
+  try{
+    BOOST_CHECK_THROW(IntersectionPoint(l3,l4), GeomException);
+  }catch(...)
+  {
+    BOOST_ERROR("Failed to catch GeomException");
+  }
   BOOST_CHECK(Equal(IntersectionPoint(p1,l3), v1));
   BOOST_CHECK(Equal(IntersectionPoint(l3,p1), v1));
   
@@ -202,8 +206,14 @@ BOOST_AUTO_TEST_CASE(rotation3)
   Rotation3 r(Vec3(0,1,0), 30.0*M_PI/180.0);
   Vec3 vrot=r.Apply(v);
   BOOST_CHECK_CLOSE(Real(cos(30.0*M_PI/180.0)), Real(vrot[0]), Real(1e-5));
-  BOOST_CHECK_SMALL(vrot[1],float(1e-5));
+  BOOST_CHECK_SMALL(vrot[1],Real(1e-5));
   BOOST_CHECK_CLOSE(Real(-sin(30.0*M_PI/180.0)), Real(vrot[2]), Real(1e-5));
+
+  Rotation3 r2(Vec3(0,1,0), 30.0*M_PI/180.0,Vec3(2,0,0));
+  Vec3 vrot2=r2.Apply(v);
+  BOOST_CHECK_CLOSE(Real(2.0)-Real(cos(30.0*M_PI/180.0)), Real(vrot2[0]), Real(1e-5));
+  BOOST_CHECK_SMALL(vrot2[1],Real(1e-5));
+  BOOST_CHECK_CLOSE(Real(sin(30.0*M_PI/180.0)), Real(vrot2[2]), Real(1e-5));
 }
 
 BOOST_AUTO_TEST_SUITE_END();
diff --git a/modules/geom/tests/test_op3.cc b/modules/geom/tests/test_op3.cc
index de7e74843e536b2b635d111752e1142c6cd7dcb2..1d4660b4e8cf92d2f6506bd900bad16aaf480dec 100644
--- a/modules/geom/tests/test_op3.cc
+++ b/modules/geom/tests/test_op3.cc
@@ -52,11 +52,11 @@ BOOST_AUTO_TEST_CASE(vecmat_mult3)
 BOOST_AUTO_TEST_CASE(vec3list_op)
 {
   Vec3List l1,l2;
-  BOOST_CHECK_THROW(MinDistance(l1,l2),std::runtime_error);
+  BOOST_CHECK_THROW(MinDistance(l1,l2),GeomException);
   l1.push_back(Vec3(0.0,0.0,0.0));
   l1.push_back(Vec3(1.0,0.0,0.0));
-  BOOST_CHECK_THROW(MinDistance(l1,l2),std::runtime_error);
-  BOOST_CHECK_THROW(MinDistance(l2,l1),std::runtime_error);
+  BOOST_CHECK_THROW(MinDistance(l1,l2),GeomException);
+  BOOST_CHECK_THROW(MinDistance(l2,l1),GeomException);
   l2.push_back(Vec3(4.0,4.0,0.0));
   l2.push_back(Vec3(2.0,4.0,5.0));
   l2.push_back(Vec3(0.0,3.0,6.0));
diff --git a/modules/geom/tests/test_quat.cc b/modules/geom/tests/test_quat.cc
index 209d129c7880a613d7af62a4d993e44e2a257b9c..cfd36460be4d09487e15000f2579cfdb78ed8697 100644
--- a/modules/geom/tests/test_quat.cc
+++ b/modules/geom/tests/test_quat.cc
@@ -51,7 +51,7 @@ BOOST_AUTO_TEST_CASE(quat_rotate)
   Quat q(30.0*M_PI/180.0,Vec3(0,1,0));
   Vec3 vrot=q.Rotate(v);
   BOOST_CHECK_CLOSE(Real(cos(30.0*M_PI/180.0)), Real(vrot[0]), Real(1e-5));
-  BOOST_CHECK_SMALL(vrot[1],float(1e-5));
+  BOOST_CHECK_SMALL(vrot[1],Real(1e-5));
   BOOST_CHECK_CLOSE(Real(-sin(30.0*M_PI/180.0)), Real(vrot[2]), Real(1e-5));
 }
 
diff --git a/modules/gfx/pymod/__init__.py b/modules/gfx/pymod/__init__.py
index be887c4ab071e3c4f2da12a771e7e1edad6b8b30..bd5750d32178c50d2ce7758af2a053dd2ea4c0f1 100644
--- a/modules/gfx/pymod/__init__.py
+++ b/modules/gfx/pymod/__init__.py
@@ -19,34 +19,33 @@
 from _ost_gfx import *
 from py_gfx_obj import PyGfxObj
 
-WHITE=Color(1.0,1.0,1.0)
-BLACK=Color(0.0,0.0,0.0)
-GREY=Color(0.5,0.5,0.5)
-RED=Color(1.0,0.0,0.0)
-DARKRED=Color(0.5,0.0,0.0)
-LIGHTRED=Color(1.0,0.5,0.5)
-GREEN=Color(0.0,1.0,0.0)
-DARKGREEN=Color(0.0,0.5,0.0)
-LIGHTGREEN=Color(0.5,1.0,0.5)
-BLUE=Color(0.0,0.0,1.0)
-DARKBLUE=Color(0.0,0.0,0.5)
-LIGHTBLUE=Color(0.5,0.5,1.0)
-YELLOW=Color(1.0,1.0,0.0)
-DARKYELLOW=Color(0.5,0.5,0.0)
-LIGHTYELLOW=Color(1.0,1.0,0.5)
-CYAN=Color(0.0,1.0,1.0)
-DARKCYAN=Color(0.0,0.5,0.5)
-LIGHTCYAN=Color(0.5,1.0,1.0)
-MAGENTA=Color(1.0,0.0,1.0)
-DARKMAGENTA=Color(0.5,0.0,0.5)
-LIGHTMAGENTA=Color(1.0,0.5,1.0)
+WHITE=RGB(1.0,1.0,1.0)
+BLACK=RGB(0.0,0.0,0.0)
+GREY=RGB(0.5,0.5,0.5)
+RED=RGB(1.0,0.0,0.0)
+DARKRED=RGB(0.5,0.0,0.0)
+LIGHTRED=RGB(1.0,0.5,0.5)
+GREEN=RGB(0.0,1.0,0.0)
+DARKGREEN=RGB(0.0,0.5,0.0)
+LIGHTGREEN=RGB(0.5,1.0,0.5)
+BLUE=RGB(0.0,0.0,1.0)
+DARKBLUE=RGB(0.0,0.0,0.5)
+LIGHTBLUE=RGB(0.5,0.5,1.0)
+YELLOW=RGB(1.0,1.0,0.0)
+DARKYELLOW=RGB(0.5,0.5,0.0)
+LIGHTYELLOW=RGB(1.0,1.0,0.5)
+CYAN=RGB(0.0,1.0,1.0)
+DARKCYAN=RGB(0.0,0.5,0.5)
+LIGHTCYAN=RGB(0.5,1.0,1.0)
+MAGENTA=RGB(1.0,0.0,1.0)
+DARKMAGENTA=RGB(0.5,0.0,0.5)
+LIGHTMAGENTA=RGB(1.0,0.5,1.0)
 PURPLE=MAGENTA
 DARKPURPLE=DARKMAGENTA
 LIGHTPURPLE=LIGHTMAGENTA
-ORANGE=Color(1.0,0.5,0.0)
-DARKORANGE=Color(0.5,0.25,0.0)
-LIGHTORANGE=Color(1.0,0.75,0.5)
-
+ORANGE=RGB(1.0,0.5,0.0)
+DARKORANGE=RGB(0.5,0.25,0.0)
+LIGHTORANGE=RGB(1.0,0.75,0.5)
 
 def Stereo(mode,flip=None,alg=None):
   """
diff --git a/modules/gfx/pymod/export_color.cc b/modules/gfx/pymod/export_color.cc
index 022f7669f0fae7326d58fba48d06887bf3c55c49..e673212501ffa23d1331e9682e995866857125fb 100644
--- a/modules/gfx/pymod/export_color.cc
+++ b/modules/gfx/pymod/export_color.cc
@@ -25,38 +25,6 @@ using namespace ost;
 using namespace ost::gfx;
 
 namespace {
-  float get_red(const Color& c) {
-    return c[0];
-  }
-
-  void set_red(Color& c, float v) {
-    c[0]=v;
-  }
-  
-  float get_green(const Color& c) {
-    return c[1];
-  }
-  
-  void set_green(Color& c, float v) {
-    c[1]=v;
-  }
-  
-  float get_blue(const Color& c) {
-    return c[2];
-  }
-  
-  void set_blue(Color& c, float v) {
-    c[2]=v;
-  }
-  
-  float get_alpha(const Color& c) {
-    return c[3];
-  }
-
-  void set_alpha(Color& c, float v) {
-    c[3]=v;
-  }
-
   float get(const Color& c, int i) {
     if(i<0 || i>3) {
       throw Error("Color: index out of bounds");
@@ -73,36 +41,123 @@ namespace {
 
   std::string repr(const Color& c) {
     std::ostringstream m;
-    m << "gfx.Color(" << c[0] << "," << c[1] << "," << c[2] << "," << c[3] << ")";
+    m << "gfx.RGBA(" << c.GetRed() << "," << c.GetGreen() << "," << c.GetBlue() << "," << c.GetAlpha() << ")";
+    m << " gfx.HSV(" << c.GetHue() << "," << c.GetSat() << "," << c.GetVal() << ")";
     return m.str();
   }
 
+  Color rgbh(uint rgb) {return RGB(static_cast<uchar>((rgb>>16)&0xff),
+                                    static_cast<uchar>((rgb>>8)&0xff),
+                                    static_cast<uchar>((rgb)&0xff));}
+  Color rgbah(uint rgba) {return RGBA(static_cast<uchar>((rgba>>24)&0xff),
+                                       static_cast<uchar>((rgba>>16)&0xff),
+                                       static_cast<uchar>((rgba>>8)&0xff),
+                                       static_cast<uchar>((rgba)&0xff));}
+
+  tuple get_rgb(const Color& c) {return make_tuple(c.GetRed(),c.GetGreen(),c.GetBlue());}
+  void set_rgb(Color& c, object rgb) {
+    extract<geom::Vec3&> vec3(rgb);
+    if(vec3.check()) {
+      c.SetRGB(vec3()[0],vec3()[1],vec3()[2]);
+    } else {
+      // assume sequence
+      c.SetRGB(extract<float>(rgb[0]),
+               extract<float>(rgb[1]),
+               extract<float>(rgb[2]));
+
+    }
+  }
+
+  tuple get_rgba(const Color& c) {return make_tuple(c.GetRed(),c.GetGreen(),c.GetBlue(),c.GetAlpha());}
+  void set_rgba(Color& c, object rgba) {
+    extract<geom::Vec4&> vec4(rgba);
+    if(vec4.check()) {
+      c.SetRGB(vec4()[0],vec4()[1],vec4()[2]);
+      c.SetAlpha(vec4()[3]);
+    } else {
+      // assume sequence
+      c.SetRGB(extract<float>(rgba[0]),
+               extract<float>(rgba[1]),
+               extract<float>(rgba[2]));
+      c.SetAlpha(extract<float>(rgba[3]));
+    }
+  }
+
+  tuple get_hsv(const Color& c) {return make_tuple(c.GetHue(),c.GetSat(),c.GetVal());}
+  void set_hsv(Color& c, object hsv) {
+    extract<geom::Vec3&> vec3(hsv);
+    if(vec3.check()) {
+      c.SetHSV(vec3()[0],vec3()[1],vec3()[2]);
+    } else {
+      // assume sequence
+      c.SetHSV(extract<float>(hsv[0]),
+               extract<float>(hsv[1]),
+               extract<float>(hsv[2]));
+    }
+  }
+
+  tuple get_hsva(const Color& c) {return make_tuple(c.GetHue(),c.GetSat(),c.GetVal(),c.GetAlpha());}
+  void set_hsva(Color& c, object hsva) {
+    extract<geom::Vec4&> vec4(hsva);
+    if(vec4.check()) {
+      c.SetHSV(vec4()[0],vec4()[1],vec4()[2]);
+      c.SetAlpha(vec4()[3]);
+    } else {
+      // assume sequence
+      c.SetHSV(extract<float>(hsva[0]),
+               extract<float>(hsva[1]),
+               extract<float>(hsva[2]));
+      c.SetAlpha(extract<float>(hsva[3]));
+    }
+  }
+
 }
 
 void export_color()
 {
   class_<Color>("Color",init<>())
-    .def(init<float, float, float, optional<float> >())
     .def(self_ns::str(self))
     .def("__repr__",repr)
-    .def("Red",get_red)
-    .def("Green",get_green)
-    .def("Blue",get_blue)
-    .def("Alpha",get_alpha)
+    .add_property("r",&Color::GetRed,&Color::SetRed)
+    .add_property("g",&Color::GetGreen,&Color::SetGreen)
+    .add_property("b",&Color::GetBlue,&Color::SetBlue)
+    .add_property("a",&Color::GetAlpha,&Color::SetAlpha)
+    .add_property("h",&Color::GetHue,&Color::SetHue)
+    .add_property("s",&Color::GetSat,&Color::SetSat)
+    .add_property("v",&Color::GetVal,&Color::SetVal)
+    .add_property("red",&Color::GetRed,&Color::SetRed)
+    .add_property("green",&Color::GetGreen,&Color::SetGreen)
+    .add_property("blue",&Color::GetBlue,&Color::SetBlue)
+    .add_property("alpha",&Color::GetAlpha,&Color::SetAlpha)
+    .add_property("hue",&Color::GetHue,&Color::SetHue)
+    .add_property("sat",&Color::GetSat,&Color::SetSat)
+    .add_property("val",&Color::GetVal,&Color::SetVal)
+    .add_property("rgb",get_rgb,set_rgb)
+    .add_property("rgba",get_rgba,set_rgba)
+    .add_property("hsv",get_hsv,set_hsv)
+    .add_property("hsva",get_hsva,set_hsva)
+    .def("__getitem__",get)
+    .def("__setitem__",set)
+    // DEPRECATED
+    .def(init<float, float, float, optional<float> >())
+    .def("Red",&Color::GetRed)
+    .def("Green",&Color::GetGreen)
+    .def("Blue",&Color::GetBlue)
+    .def("Alpha",&Color::GetAlpha)
     .def("ToHSV",&Color::ToHSV)
     .def("FromRGBA",&Color::FromRGB)
-    .add_property("r",get_red,set_red)
-    .add_property("g",get_green,set_green)
-    .add_property("b",get_blue,set_blue)
-    .add_property("a",get_alpha,set_alpha)
-    .add_property("red",get_red,set_red)
-    .add_property("green",get_green,set_green)
-    .add_property("blue",get_blue,set_blue)
-    .add_property("alpha",get_alpha,set_alpha)
-    .def("__getitem__",get)
-    .def("__setitem__",get)
     ;
 
+  def("RGB",RGB);
+  def("RGBh",rgbh);
+  def("RGBb",RGBb);
+  def("RGBi",RGBi);
+  def("RGBA",RGBA);
+  def("RGBAh",rgbah);
+  def("RGBAb",RGBAb);
+  def("RGBAi",RGBAi);
   def("HSV",HSV);
-  
+  def("HSVi",HSVi);
+  def("HSVA",HSVA);
+  def("HSVAi",HSVAi);
 }
diff --git a/modules/gfx/pymod/export_entity.cc b/modules/gfx/pymod/export_entity.cc
index 6202bd1cc4d353d61b673c78d68b402ecbc7b137..d8ee109298405de304b4b7e178671b1f4388141f 100644
--- a/modules/gfx/pymod/export_entity.cc
+++ b/modules/gfx/pymod/export_entity.cc
@@ -360,6 +360,8 @@ void export_Entity()
     .def("IsRenderModeEnabled", &Entity::IsRenderModeEnabled)
     .def("SetVisible", set_vis1, (arg("view"), arg("flag")=true))
     .def("SetVisible", set_vis2, (arg("sel"), arg("flag")=true))    
+    .def("ColorBy", color_by_10) // this line must be before color_by_01 because
+                                 // of boost python overload resolution
     .def("ColorBy", color_by_01)
     .def("ColorBy", color_by_02)
     .def("ColorBy", color_by_03)
@@ -369,7 +371,6 @@ void export_Entity()
     .def("ColorBy", color_by_07)
     .def("ColorBy", color_by_08)
     .def("ColorBy", color_by_09)
-    .def("ColorBy", color_by_10)
     .def("DetailColorBy", detail_color_by_02)
     COLOR_BY_DEF()
     .def("RadiusBy", radius_by_01)
diff --git a/modules/gfx/pymod/export_gfx_obj.cc b/modules/gfx/pymod/export_gfx_obj.cc
index 45093dd9bb8927e213c5af627babd19fe9d8f9ce..5f9ad7d1a4ecfc29a4b1aadf18b42c4d4f81e6e0 100644
--- a/modules/gfx/pymod/export_gfx_obj.cc
+++ b/modules/gfx/pymod/export_gfx_obj.cc
@@ -65,17 +65,17 @@ using namespace ost::gfx;
       GfxObj(name)
     {}
 
-    virtual geom::AlignedCuboid GetBoundingBox() const
+    virtual geom::AlignedCuboid GetBoundingBox(bool return_global=true) const
     {
       if(override f = this->get_override("GetBoundingBox")) {
-        return f();
+        return f(return_global);
       } else {
-        return GfxObj::GetBoundingBox();
+        return GfxObj::GetBoundingBox(return_global);
       }
     }
 
-    geom::AlignedCuboid default_GetBoundingBox() const {
-      return GfxObj::GetBoundingBox();
+    geom::AlignedCuboid default_GetBoundingBox(bool return_global) const {
+      return GfxObj::GetBoundingBox(return_global);
     }
 
     virtual void CustomRenderGL(RenderPass pass) {
@@ -175,7 +175,7 @@ void export_GfxObj()
     .def("GetAALines",&GfxObj::GetAALines)
     .def("GetLineWidth",&GfxObj::GetLineWidth)
     .def("GetLineHalo",&GfxObj::GetLineHalo)
-    .def("GetBoundingBox",&GfxObj::GetBoundingBox, &GfxObjWrap::default_GetBoundingBox)
+    .def("GetBoundingBox",&GfxObj::GetBoundingBox,&GfxObjWrap::default_GetBoundingBox)
     .def("_CustomRenderGL",&GfxObj::CustomRenderGL, &GfxObjWrap::default_CustomRenderGL)
     .def("_CustomPreRenderGL",&GfxObj::CustomPreRenderGL, &GfxObjWrap::default_CustomPreRenderGL)
     .def("_InitGL",&GfxObj::InitGL, &GfxObjWrap::default_InitGL)
diff --git a/modules/gfx/pymod/export_gradient.cc b/modules/gfx/pymod/export_gradient.cc
index 6cb26cee020a295eb56111aa4101d189470eadc3..03eeb5401314968c1dba50967224846c11aa7ad7 100644
--- a/modules/gfx/pymod/export_gradient.cc
+++ b/modules/gfx/pymod/export_gradient.cc
@@ -16,6 +16,11 @@
 // along with this library; if not, write to the Free Software Foundation, Inc.,
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 //------------------------------------------------------------------------------
+
+/*
+  Authors: Marco Biasini, Ansgar Philippsen
+*/
+
 #include <boost/python.hpp>
 #include <boost/python/suite/indexing/vector_indexing_suite.hpp>
 using namespace boost::python;
@@ -33,7 +38,7 @@ namespace {
     for(int i=0;i<len(keys);++i) {
       extract<float> fex(keys[i]);
       if(!fex.check()) {
-        throw std::runtime_error("expected floats as keys");
+        throw Error("expected floats as keys");
       }
       float mark = fex();
       Color col;
@@ -45,12 +50,12 @@ namespace {
       } else {
         // try simple sequence
         if(len(val)!=3) {
-          throw std::runtime_error("expected values of gfx.Color or float triplets");
+          throw Error("expected values of gfx.Color or float triplets");
         }
         try {
           col=gfx::Color(extract<float>(val[0]),extract<float>(val[1]),extract<float>(val[2]));
         } catch (...) {
-          throw std::runtime_error("expected values of gfx.Color or float triplets");
+          throw Error("expected values of gfx.Color or float triplets");
         }
       }
       grad->SetColorAt(mark,col);
@@ -73,18 +78,30 @@ namespace {
       } else {
         // try simple sequence
         if(len(val)!=3) {
-          throw std::runtime_error("expected values of gfx.Color or float triplets");
+          throw Error("expected values of gfx.Color or float triplets");
         }
         try {
-          col=gfx::Color(extract<float>(val[0]),extract<float>(val[1]),extract<float>(val[2]));
+          col=gfx::RGB(extract<float>(val[0]),extract<float>(val[1]),extract<float>(val[2]));
         } catch (...) {
-          throw std::runtime_error("expected values of gfx.Color or float triplets");
+          throw Error("expected values of gfx.Color float triplets");
         }
       }
       grad->SetColorAt(mark,col);
     }
     return grad.release();
   }
+
+  std::string sl_repr(const Gradient::StopList& sl) {
+    std::ostringstream m;
+    m << "[";
+    for(size_t i=0;i<sl.size();++i) {
+      Color c = sl[i].color;
+      m << "(" << sl[i].t << "," << "gfx.RGB(" << c[0] << "," << c[1] << "," << c[2] << "))";
+      if(i<sl.size()-1) m << ",";
+    }
+    m << "]";
+    return m.str();
+  }
 }
 
 void export_gradient()
@@ -96,13 +113,16 @@ void export_gradient()
     .def("SetColorAt", &Gradient::SetColorAt)
     .def("GetColorAt", &Gradient::GetColorAt)
     .def("GetStops", &Gradient::GetStops)
+    .add_property("stops", &Gradient::GetStops)
     .def("GradientToInfo", &Gradient::GradientToInfo)
     .def("GradientFromInfo", &Gradient::GradientFromInfo).staticmethod("GradientFromInfo")
+    .add_property("hsv_mode",&Gradient::GetHSVMode,&Gradient::SetHSVMode)
   ;
   implicitly_convertible<String, Gradient>();
 
   class_<Gradient::StopList>("GradientStopList", init<>())
     .def(vector_indexing_suite<Gradient::StopList>())
+    .def("__repr__",sl_repr)
   ;
 
   class_<Gradient::Stop>("GradientStop", init<>())
diff --git a/modules/gfx/pymod/export_primlist.cc b/modules/gfx/pymod/export_primlist.cc
index bb986d7e14c1580555d2bb3b4db2fb497c1c9fcc..8cdaf32303ae80ff65d787642d2e9a01b8d5bc0d 100644
--- a/modules/gfx/pymod/export_primlist.cc
+++ b/modules/gfx/pymod/export_primlist.cc
@@ -21,6 +21,7 @@ using namespace boost::python;
 
 #include <boost/shared_ptr.hpp>
 
+#include <ost/message.hh>
 #include <ost/gfx/prim_list.hh>
 using namespace ost;
 using namespace ost::gfx;
@@ -34,18 +35,18 @@ namespace {
   {
 #if OST_NUMPY_SUPPORT_ENABLED
     if(!PyArray_Check(ova.ptr())) {
-      throw std::runtime_error("ova is not a numpy array");
+      throw Error("ova is not a numpy array");
     }
     PyArrayObject* va=reinterpret_cast<PyArrayObject*>(ova.ptr());
     if(!PyArray_ISCONTIGUOUS(va)) {
-      throw std::runtime_error("expected vertex array to be contiguous");
+      throw Error("expected vertex array to be contiguous");
     }
     if(!PyArray_TYPE(va)==NPY_FLOAT) {
-      throw std::runtime_error("expected vertex array to be of dtype=float32");
+      throw Error("expected vertex array to be of dtype=float32");
     }
     size_t v_size=PyArray_SIZE(va);
     if(v_size%3!=0) {
-      throw std::runtime_error("expected vertex array size to be divisible by 3");
+      throw Error("expected vertex array size to be divisible by 3");
     }
     size_t v_count=v_size/3;
     float* vp=reinterpret_cast<float*>(PyArray_DATA(va));
@@ -53,52 +54,52 @@ namespace {
     float* cp=0;
     if(ona!=object()) {
       if(!PyArray_Check(ona.ptr())) {
-        throw std::runtime_error("ona is not a numpy array");
+        throw Error("ona is not a numpy array");
       }
       PyArrayObject* na=reinterpret_cast<PyArrayObject*>(ona.ptr());
       if(!PyArray_ISCONTIGUOUS(na)) {
-        throw std::runtime_error("expected normal array to be contiguous");
+        throw Error("expected normal array to be contiguous");
       }
       if(!PyArray_TYPE(na)==NPY_FLOAT) {
-        throw std::runtime_error("expected normal array to be of dtype=float32");
+        throw Error("expected normal array to be of dtype=float32");
       }
-      if(PyArray_SIZE(na)!=v_size) {
-        throw std::runtime_error("expected normal array size to match vertex array size");
+      if((size_t)PyArray_SIZE(na)!=v_size) {
+        throw Error("expected normal array size to match vertex array size");
       }
       np=reinterpret_cast<float*>(PyArray_DATA(na));
     }
     if(oca!=object()) {
       if(!PyArray_Check(oca.ptr())) {
-        throw std::runtime_error("oca is not a numpy array");
+        throw Error("oca is not a numpy array");
       }
       PyArrayObject* ca=reinterpret_cast<PyArrayObject*>(oca.ptr());
       if(!PyArray_ISCONTIGUOUS(ca)) {
-        throw std::runtime_error("expected color array to be contiguous");
+        throw Error("expected color array to be contiguous");
       }
       if(!PyArray_TYPE(ca)==NPY_FLOAT) {
-        throw std::runtime_error("expected color array to be of dtype=float32");
+        throw Error("expected color array to be of dtype=float32");
       }
-      if(PyArray_SIZE(ca)!=v_count*4) {
-        throw std::runtime_error("expected color array size to equal vertex-count x 4");
+      if((size_t)PyArray_SIZE(ca)!=v_count*4) {
+        throw Error("expected color array size to equal vertex-count x 4");
       }
       cp=reinterpret_cast<float*>(PyArray_DATA(ca));
     }
     if(!PyArray_Check(oia.ptr())) {
-      throw std::runtime_error("oia is not a numpy array");
+      throw Error("oia is not a numpy array");
     }
     PyArrayObject* ia=reinterpret_cast<PyArrayObject*>(oia.ptr());
     if(!PyArray_ISCONTIGUOUS(ia)) {
-      throw std::runtime_error("expected vertex array to be contiguous");
+      throw Error("expected vertex array to be contiguous");
     }
     if(!PyArray_TYPE(ia)==NPY_UINT) {
-      throw std::runtime_error("expected vertex array to be of dtype=uint32");
+      throw Error("expected vertex array to be of dtype=uint32");
     }
     size_t i_size=PyArray_SIZE(ia);
     unsigned int* ip=reinterpret_cast<unsigned int*>(PyArray_DATA(ia));
 
     p.AddMesh(vp,np,cp,v_count,ip,i_size/3);
 #else
-    throw std::runtime_error("AddMesh requires compiled-in numpy support");
+    throw Error("AddMesh requires compiled-in numpy support");
 #endif
   }
 }
diff --git a/modules/gfx/pymod/export_scene.cc b/modules/gfx/pymod/export_scene.cc
index 8b73a3391ec8a0a8ac5f4e41357b17738320d1d2..18728c2cf3feee60f5727efffd5a61c098f4151b 100644
--- a/modules/gfx/pymod/export_scene.cc
+++ b/modules/gfx/pymod/export_scene.cc
@@ -29,11 +29,12 @@ namespace {
 
 BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(scene_add_overloads, 
                                        Scene::Add, 1, 2)
-BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(scene_autoslab_overloads, 
-                                       Scene::Autoslab, 0, 2)
 BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(scene_export_pov_overloads,
                                        Scene::ExportPov, 1,2)
 void (Scene::*apply)(const InputEvent&, bool)=&Scene::Apply;
+void (Scene::*autoslab1)()=&Scene::Autoslab;
+void (Scene::*autoslab2)(bool)=&Scene::Autoslab;
+void (Scene::*autoslab3)(bool,bool)=&Scene::Autoslab;
 
 Scene* get_scene()
 {
@@ -49,6 +50,21 @@ GfxObjP scene_getitem(Scene* scene, const String& item)
   return scene->operator[](item);
 }
 
+geom::AlignedCuboid scene_get_bb1(Scene* scene)
+{
+  return scene->GetBoundingBox();
+}
+
+geom::AlignedCuboid scene_get_bb2(Scene* scene, bool use_tf)
+{
+  return scene->GetBoundingBox(use_tf);
+}
+
+geom::AlignedCuboid scene_get_bb3(Scene* scene, const mol::Transform& tf)
+{
+  return scene->GetBoundingBox(tf);
+}
+
 } // anon ns
 
 
@@ -80,12 +96,19 @@ void export_Scene()
   class_<Scene, boost::noncopyable>("SceneSingleton",no_init)
     .def("Add", &Scene::Add, 
          scene_add_overloads())
-    .def("Autoslab", &Scene::Autoslab, 
-         scene_autoslab_overloads())
+    .def("Autoslab", autoslab1)
     .def("AutoAutoslab",&Scene::AutoAutoslab)
     .def("GetAutoAutoslab",&Scene::GetAutoAutoslab)
-    .def("AutoslabMax",&Scene::AutoslabMax)
+    .add_property("auto_autoslab",&Scene::GetAutoAutoslab,&Scene::AutoAutoslab)
+    .def("SetAutoslabMode",&Scene::SetAutoslabMode)
+    .def("GetAutoslabMode",&Scene::GetAutoslabMode)
+    .add_property("autoslab_mode",&Scene::GetAutoslabMode,&Scene::SetAutoslabMode)
+    .def("Autoslab", autoslab2) // DEPRECATED
+    .def("Autoslab", autoslab3) // DEPRECATED
+    .def("AutoslabMax",&Scene::AutoslabMax) // DEPRECATED
     .def("Remove", remove1)
+    .def("Register", &Scene::Register)
+    .def("Unregister", &Scene::Unregister)
     .def("Remove", remove2)
     .add_property("viewport", &Scene::GetViewport)
     .def("RequestRedraw", &Scene::RequestRedraw)
@@ -105,6 +128,10 @@ void export_Scene()
     .add_property("bg",
                   &Scene::GetBackground, 
                   &Scene::SetBackground)
+    .def("GetProjection",&Scene::GetProjection)
+    .add_property("projection",&Scene::GetProjection)
+    .def("GetInvertedProjection",&Scene::GetInvertedProjection)
+    .add_property("inverted_projection",&Scene::GetInvertedProjection)
     .def("SetNear",&Scene::SetNear)
     .def("GetNear",&Scene::GetNear)
     .add_property("near", &Scene::GetNear, &Scene::SetNear)
@@ -192,6 +219,7 @@ void export_Scene()
     .def("SetAmbientOcclusionQuality",&Scene::SetAmbientOcclusionQuality)
     .add_property("ambient_occlusion_quality",&Scene::GetAmbientOcclusionQuality,&Scene::SetAmbientOcclusionQuality)
     .add_property("ao_quality",&Scene::GetAmbientOcclusionQuality,&Scene::SetAmbientOcclusionQuality)
+    .add_property("ao_size",&Scene::GetAmbientOcclusionSize,&Scene::SetAmbientOcclusionSize)
     .def("AttachObserver",&Scene::AttachObserver)
     .def("StartOffscreenMode",&Scene::StartOffscreenMode)
     .def("StopOffscreenMode",&Scene::StopOffscreenMode)
@@ -202,5 +230,9 @@ void export_Scene()
     .def("__getitem__",scene_getitem)
     .add_property("show_center",&Scene::GetShowCenter, &Scene::SetShowCenter)
     .add_property("fix_center",&Scene::GetFixCenter, &Scene::SetFixCenter)
+    .def("GetBoundingBox",scene_get_bb1)
+    .def("GetBoundingBox",scene_get_bb2)
+    .def("GetBoundingBox",scene_get_bb3)
+    .add_property("bounding_box",scene_get_bb1)
   ;
 }
diff --git a/modules/gfx/pymod/gradients.xml b/modules/gfx/pymod/gradients.xml
index dc3e03fd2ed56d5d5c7dee6729625d733cfbde52..e3e1fbd0cad68995f30fa7b445f108b05eb31210 100644
--- a/modules/gfx/pymod/gradients.xml
+++ b/modules/gfx/pymod/gradients.xml
@@ -17,6 +17,11 @@
 0.0615451	0.0313726	0.286275	0.501961	1
 0.502146	1	1	1	1
 0.978541	0.890105	0.075639	0.0546578	1
+</Gradient>
+  <Gradient hsv_color="1" hsv_mode="1" Name="HEAT_MAP_HSV" >3
+0.0615451	0.576389 0.9375 0.501961	1
+0.502146	0 0 1 1
+0.978541	0.00418562 0.938594 0.890105	1
 </Gradient>
   <Gradient Name="AUTUMN" >3
 0.0615451	1	0.972015	0.0132753	1
@@ -61,6 +66,10 @@
 0.748835  0 1 1 1
 0.857779  0 0.623529  1 1
 0.97541 0 0.133333  1 1
+</Gradient>
+<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>
  </Gradients>
 </EMDataInfo>
diff --git a/modules/gfx/src/CMakeLists.txt b/modules/gfx/src/CMakeLists.txt
index 6028b64f857c2fd6c25e9ef12b485cf40ae1182c..7a92969a95edb65706c9ecf012960c48eeae932e 100644
--- a/modules/gfx/src/CMakeLists.txt
+++ b/modules/gfx/src/CMakeLists.txt
@@ -84,6 +84,7 @@ connect_renderer_base.hh
 mapped_property.hh
 entity_renderer_fw.hh
 tabulated_trig.hh
+fast_spheres.hh
 )
 
 
@@ -138,6 +139,7 @@ impl/trace_renderer_base.cc
 impl/mapped_property.cc
 impl/tabulated_trig.cc
 impl/trace_renderer.cc
+impl/fast_spheres.cc
 render_options/render_options.cc
 render_options/line_render_options.cc
 render_options/custom_render_options.cc
@@ -243,16 +245,12 @@ if (USE_SHADER)
     shader/aaline_fs.glsl
     shader/amboccl_fs.glsl
     shader/basic_fs.glsl
-    shader/basic_hf_vs.glsl
-    shader/basic_lf_fs.glsl
-    shader/basic_lf_vs.glsl
     shader/basic_vs.glsl
     shader/beacon_fs.glsl
     shader/convolute1_fs.glsl
     shader/dumpnorm_fs.glsl
     shader/dumpnorm_vs.glsl
     shader/fast_sphere_fs.glsl
-    shader/fast_sphere_vs.glsl
     shader/fraglight_fs.glsl
     shader/fraglight_vs.glsl
     shader/iso_fs.glsl
@@ -264,11 +262,12 @@ if (USE_SHADER)
     shader/scenefx_vs.glsl
     shader/selfx_fs.glsl
     shader/selfx_vs.glsl
-    shader/toon2_fs.glsl
-    shader/toon_fs.glsl
-    shader/toon_vs.glsl
     shader/screenblur4_fs.glsl
     shader/test_tex_fs.glsl
+    shader/material_phong.glsl
+    shader/material_hemi.glsl
+    shader/material_toon1.glsl
+    shader/material_toon2.glsl
   )
   copy_if_different("./" "${SHARED_DATA_PATH}/shader" "${SHADER_FILES}" 
                     "SHADER_TARGETS" ost_gfx)  
diff --git a/modules/gfx/src/color.cc b/modules/gfx/src/color.cc
index f40e69c53629e136a661b380424d4e075419ae50..43316f51c455e0643c7660274d10a5177177652b 100644
--- a/modules/gfx/src/color.cc
+++ b/modules/gfx/src/color.cc
@@ -26,179 +26,418 @@
 
 namespace ost { namespace gfx {
 
-namespace {
-// maps hsv to rgb (0-1)
-geom::Vec3 HSVtoRGB(const geom::Vec3& hsv)
-{
-  geom::Vec3 rgb;
-  if (hsv[1]<1e-9){
-    rgb[0]=hsv[2];
-    rgb[1]=hsv[2];
-    rgb[2]=hsv[2];
+Color::Color()
+{
+  rgba_[0]=1.0;
+  rgba_[1]=1.0;
+  rgba_[2]=1.0;
+  rgba_[3]=1.0;
+  rgb_dirty_=false;
+  hsv_dirty_=true;
+}
+
+Color::Color(float r, float g, float b, float a) 
+{
+  rgba_[0]=r;
+  rgba_[1]=g;
+  rgba_[2]=b;
+  rgba_[3]=a;
+  rgb_dirty_=false;
+  hsv_dirty_=true;
+}
+  
+void Color::SetRGB(float r, float g, float b)
+{
+  rgba_[0]=r;
+  rgba_[1]=g;
+  rgba_[2]=b;
+  rgb_dirty_=false;
+  hsv_dirty_=true;
+}
+
+geom::Vec3 Color::GetRGB() const
+{
+  if(rgb_dirty_) to_rgb();
+  return geom::Vec3(rgba_);
+}
+
+geom::Vec4 Color::GetRGBA() const
+{
+  if(rgb_dirty_) to_rgb();
+  return geom::Vec3(rgba_);
+}
+
+float Color::GetRed() const
+{
+  if(rgb_dirty_) to_rgb();
+  return rgba_[0];
+}
+
+void Color::SetRed(float x)
+{
+  if(rgb_dirty_) to_rgb();
+  rgba_[0]=x;
+  hsv_dirty_=true;
+}
+
+float Color::GetGreen() const
+{
+  if(rgb_dirty_) to_rgb();
+  return rgba_[1];
+}
+
+void Color::SetGreen(float x)
+{
+  if(rgb_dirty_) to_rgb();
+  rgba_[1]=x;
+  hsv_dirty_=true;
+}
+
+float Color::GetBlue() const
+{
+  if(rgb_dirty_) to_rgb();
+  return rgba_[2];
+}
+
+void Color::SetBlue(float x)
+{
+  if(rgb_dirty_) to_rgb();
+  rgba_[2]=x;
+  hsv_dirty_=true;
+}
+
+void Color::SetHSV(float h, float s, float v)
+{
+  hsv_[0]=h;
+  hsv_[1]=s;
+  hsv_[2]=v;
+  hsv_dirty_=false;
+  rgb_dirty_=true;
+}
+
+geom::Vec3 Color::GetHSV() const
+{
+  if(hsv_dirty_) to_hsv();
+  return geom::Vec3(hsv_);
+}
+
+geom::Vec4 Color::GetHSVA() const
+{
+  if(hsv_dirty_) to_hsv();
+  return geom::Vec4(hsv_[0],hsv_[1],hsv_[2],rgba_[3]);
+}
+
+float Color::GetHue() const
+{
+  if(hsv_dirty_) to_hsv();
+  return hsv_[0];
+}
+
+void Color::SetHue(float x)
+{
+  if(hsv_dirty_) to_hsv();
+  hsv_[0]=x;
+  rgb_dirty_=true;
+}
+
+float Color::GetSat() const
+{
+  if(hsv_dirty_) to_hsv();
+  return hsv_[1];
+}
+
+void Color::SetSat(float x)
+{
+  if(hsv_dirty_) to_hsv();
+  hsv_[1]=x;
+  rgb_dirty_=true;
+}
+
+float Color::GetVal() const
+{
+  if(hsv_dirty_) to_hsv();
+  return hsv_[2];
+}
+
+void Color::SetVal(float x)
+{
+  if(hsv_dirty_) to_hsv();
+  hsv_[2]=x;
+  rgb_dirty_=true;
+}
+
+float Color::GetAlpha() const
+{
+  return rgba_[3];
+}
+
+void Color::SetAlpha(float x)
+{
+  rgba_[3]=x;
+}
+
+////////////////////////////////////
+// operators
+
+Color::operator const float* () const 
+{
+  if(rgb_dirty_) to_rgb();
+  return rgba_;
+}
+
+Color::operator float* () 
+{
+  if(rgb_dirty_) to_rgb();
+  hsv_dirty_=true; 
+  return rgba_;
+}
+
+Color& Color::operator*=(float rhs)
+{
+  if(rgb_dirty_) to_rgb();
+  rgba_[0]*=rhs;
+  rgba_[1]*=rhs;
+  rgba_[2]*=rhs;
+  rgba_[3]*=rhs; 
+  hsv_dirty_=true; 
+  return *this;
+}
+
+Color& Color::operator+=(float rhs)
+{
+  if(rgb_dirty_) to_rgb();
+  rgba_[0]+=rhs;
+  rgba_[1]+=rhs;
+  rgba_[2]+=rhs;
+  rgba_[3]+=rhs;
+  hsv_dirty_=true; 
+  return *this;
+}
+  
+Color& Color::operator+=(const Color& rhs)
+{
+  if(rgb_dirty_) to_rgb();
+  rgba_[0]+=rhs[0];
+  rgba_[1]+=rhs[1];
+  rgba_[2]+=rhs[2];
+  rgba_[3]+=rhs[3];  
+  hsv_dirty_=true; 
+  return *this;  
+}
+
+Color& Color::operator-=(const Color& rhs)
+{
+  if(rgb_dirty_) to_rgb();
+  rgba_[0]-=rhs[0];
+  rgba_[1]-=rhs[1];
+  rgba_[2]-=rhs[2];
+  rgba_[3]-=rhs[3];  
+  hsv_dirty_=true; 
+  return *this;
+}
+
+Color& Color::operator-=(float rhs)
+{
+  if(rgb_dirty_) to_rgb();
+  rgba_[0]-=rhs;
+  rgba_[1]-=rhs;
+  rgba_[2]-=rhs;
+  rgba_[3]-=rhs;
+  hsv_dirty_=true; 
+  return *this;
+}
+
+Color& Color::operator/=(float rhs)
+{
+  if(rgb_dirty_) to_rgb();
+  rgba_[0]/=rhs;
+  rgba_[1]/=rhs;
+  rgba_[2]/=rhs;
+  rgba_[3]/=rhs;  
+  hsv_dirty_=true; 
+  return *this;
+}
+
+//////////////////////////////////////
+// private methods
+
+void Color::to_rgb() const
+{
+  float hh=fmod(hsv_[0],1.0);
+  if(hh<0.0) hh+=1.0;
+  float ss=std::min(1.0f,std::max(0.0f,hsv_[1]));
+  float vv=std::min(1.0f,std::max(0.0f,hsv_[2]));
+  if (ss<1e-9){
+    rgba_[0]=vv;
+    rgba_[1]=vv;
+    rgba_[2]=vv;
   } else {
-    double var_h=hsv[0]*6.0<6.0?hsv[0]*6.0:0.0;
+    float var_h=hh*6.0;
     int var_i =static_cast<int>(var_h);
-    double var_1 = hsv[2]*(1-hsv[1]);
-    double var_2 = hsv[2]*(1-hsv[1]*( var_h -var_i));
-    double var_3 = hsv[2]*(1-hsv[1]*(1-(var_h-var_i)));
+    float var_1 = vv*(1-ss);
+    float var_2 = vv*(1-ss*( var_h - static_cast<float>(var_i)));
+    float var_3 = vv*(1-ss*(1-(var_h-static_cast<float>(var_i))));
     switch(var_i){
     case 0:
-      rgb[0]=hsv[2];
-      rgb[1]=var_3;
-      rgb[2]=var_1;
+      rgba_[0]=vv;
+      rgba_[1]=var_3;
+      rgba_[2]=var_1;
       break;
     case 1:
-      rgb[0] = var_2;
-      rgb[1] = hsv[2];
-      rgb[2] = var_1;
+      rgba_[0] = var_2;
+      rgba_[1] = vv;
+      rgba_[2] = var_1;
       break;
     case 2:
-      rgb[0] = var_1;
-      rgb[1] = hsv[2];
-      rgb[2] = var_3;
+      rgba_[0] = var_1;
+      rgba_[1] = vv;
+      rgba_[2] = var_3;
       break;
     case 3:
-      rgb[0] = var_1 ; 
-      rgb[1] = var_2 ; 
-      rgb[2] = hsv[2];
+      rgba_[0] = var_1 ; 
+      rgba_[1] = var_2 ; 
+      rgba_[2] = vv;
       break;
     case 4:
-      rgb[0] = var_3 ;
-      rgb[1] = var_1 ;
-      rgb[2] = hsv[2];
+      rgba_[0] = var_3 ;
+      rgba_[1] = var_1 ;
+      rgba_[2] = vv;
       break;
     case 5:
-      rgb[0] = hsv[2];
-      rgb[1] = var_1 ;
-      rgb[2] = var_2;
+      rgba_[0] = vv;
+      rgba_[1] = var_1 ;
+      rgba_[2] = var_2;
       break;
     }
   }
-  return rgb;
+  rgb_dirty_=false;
 }
 
-// maps rgb (0-1) to hsv
-geom::Vec3 RGBtoHSV(const geom::Vec3& rgb)
+void Color::to_hsv() const
 {
-  geom::Vec3 hsv;
-  double var_R = ( rgb[0] );
-  double var_G = ( rgb[1] );
-  double var_B = ( rgb[2] );
+  float rr = std::min(1.0f,std::max(0.0f,rgba_[0]));
+  float gg = std::min(1.0f,std::max(0.0f,rgba_[1]));
+  float bb = std::min(1.0f,std::max(0.0f,rgba_[2]));
 
-  double var_Min = std::min(std::min( var_R, var_G), var_B );
-  double var_Max = std::max(std::max( var_R, var_G), var_B );
-  double del_Max = var_Max - var_Min;
+  float vmin = std::min(std::min(rr, gg), bb);
+  float vmax = std::max(std::max(rr, gg), bb);
+  float vdelta = vmax - vmin;
 
-  hsv[2] = var_Max;
+  hsv_[2] = vmax;
 
-  if ( del_Max < 1.0e-9 ){
-    hsv[0] = 0.0;
-    hsv[1] = 0.0;
+  if (vdelta < 1.0e-9) {
+    hsv_[0] = 0.0;
+    hsv_[1] = 0.0;
   } else {
-    hsv[1] = del_Max / var_Max;
-    double del_R = ( ( ( var_Max - var_R ) / 6.0 ) + ( del_Max / 2.0 ) ) / del_Max;
-    double del_G = ( ( ( var_Max - var_G ) / 6.0 ) + ( del_Max / 2.0 ) ) / del_Max;
-    double del_B = ( ( ( var_Max - var_B ) / 6.0 ) + ( del_Max / 2.0 ) ) / del_Max;
+    hsv_[1] = vdelta / vmax;
+    float dr = (((vmax - rr) / 6.0) + (vdelta / 2.0)) / vdelta;
+    float dg = (((vmax - gg) / 6.0) + (vdelta / 2.0)) / vdelta;
+    float db = (((vmax - bb) / 6.0) + (vdelta / 2.0)) / vdelta;
     
-    if ( var_R == var_Max ){
-      hsv[0] = del_B - del_G;
-    } else if ( var_G == var_Max ){
-      hsv[0] = ( 1.0 / 3.0 ) + del_R - del_B;
-    } else if ( var_B == var_Max ){
-      hsv[0] = ( 2.0 / 3.0 ) + del_G - del_R;
+    if (rr == vmax) {
+      hsv_[0] = db - dg;
+    } else if (gg == vmax) {
+      hsv_[0] = (1.0 / 3.0) + dr - db;
+    } else if (bb == vmax) {
+      hsv_[0] = (2.0 / 3.0) + dg - dr;
     }
-    if ( hsv[0] < 0.0 ){
-      hsv[0] += 1.0;
+    if (hsv_[0] < 0.0) {
+      hsv_[0] += 1.0;
     }
-    if ( hsv[0] > 1.0 ){
-      hsv[0] -= 1.0;
+    if (hsv_[0] > 1.0) {
+      hsv_[0] -= 1.0;
     }
   }
+  hsv_dirty_=false;
+}
 
-  hsv[0]=hsv[0]*360.0;
-  hsv[1]=hsv[1]*100.0;
-  hsv[2]=hsv[2]*100.0;
+////////////////////////////////////
+// stand alone functions
 
-  return hsv;
+Color RGB(float r, float g, float b)
+{
+  Color nrvo;
+  nrvo.SetRGB(r,g,b);
+  return nrvo;
 }
-} // anon ns
 
-geom::Vec3 Color::ToHSV()
+Color RGBb(uchar r, uchar g, uchar b)
 {
-  return RGBtoHSV(geom::Vec3(rgba[0],rgba[1],rgba[2]));
+  static float f=1.0/255.0;
+  Color nrvo;
+  nrvo.SetRGB(static_cast<float>(r)*f,static_cast<float>(g)*f,static_cast<float>(b)*f);
+  return nrvo;
 }
 
-
-Color HSV(double h, double s, double v)
+Color RGBi(unsigned int r, unsigned int g, unsigned int b)
 {
-  if(h>1.0 || s>1.0 || v>1.0) {
-    h=h/360.0;
-    s=s/100.0;
-    v=v/100.0;
-  }
-  geom::Vec3 rgb=HSVtoRGB(geom::Vec3(h,s,v));
-  return Color(rgb[0],rgb[1],rgb[2]);
+  static float f=1.0/65535.0;
+  Color nrvo;
+  nrvo.SetRGB(static_cast<float>(r)*f,static_cast<float>(g)*f,static_cast<float>(b)*f);
+  return nrvo;
 }
 
-std::ostream& operator<<(std::ostream& s, const Color& c)
+Color RGBA(float r, float g, float b, float a)
 {
-  s << "{" << c.Red() << "," << c.Green() << "," << c.Blue() << "," << c.Alpha() << "}";
-  return s;
+  Color nrvo;
+  nrvo.SetRGB(r,g,b);
+  nrvo.SetAlpha(a);
+  return nrvo;
 }
 
+Color RGBAb(uchar r, uchar g, uchar b, uchar a)
+{
+  static float f=1.0/255.0;
+  Color nrvo;
+  nrvo.SetRGB(static_cast<float>(r)*f,static_cast<float>(g)*f,static_cast<float>(b)*f);
+  nrvo.SetAlpha(static_cast<float>(a)*f);
+  return nrvo;
+}
 
-Color& Color::operator*=(float rhs)
+Color RGBAi(unsigned int r, unsigned int g, unsigned int b, unsigned a)
 {
-  rgba[0]*=rhs;
-  rgba[1]*=rhs;
-  rgba[2]*=rhs;
-  rgba[3]*=rhs; 
-  return *this;
+  static float f=1.0/65535.0;
+  Color nrvo;
+  nrvo.SetRGB(static_cast<float>(r)*f,static_cast<float>(g)*f,static_cast<float>(b)*f);
+  nrvo.SetAlpha(static_cast<float>(a)*f);
+  return nrvo;
 }
 
-Color& Color::operator+=(float rhs)
+Color HSV(float h, float s, float v)
 {
-  rgba[0]+=rhs;
-  rgba[1]+=rhs;
-  rgba[2]+=rhs;
-  rgba[3]+=rhs;
-  return *this;
+  Color nrvo;
+  nrvo.SetHSV(h,s,v);
+  return nrvo;
 }
-  
-Color& Color::operator+=(const Color& rhs)
+
+Color HSVi(int r, int g, int b)
 {
-  rgba[0]+=rhs[0];
-  rgba[1]+=rhs[1];
-  rgba[2]+=rhs[2];
-  rgba[3]+=rhs[3];  
-  return *this;  
+  static float f=1.0/65535.0;
+  Color nrvo;
+  nrvo.SetHSV(static_cast<float>(r)*f,static_cast<float>(g)*f,static_cast<float>(b)*f);
+  return nrvo;
 }
 
-Color& Color::operator-=(const Color& rhs)
+Color HSVA(float h, float s, float v, float a)
 {
-  rgba[0]-=rhs[0];
-  rgba[1]-=rhs[1];
-  rgba[2]-=rhs[2];
-  rgba[3]-=rhs[3];  
-  return *this;
+  Color nrvo;
+  nrvo.SetHSV(h,s,v);
+  nrvo.SetAlpha(a);
+  return nrvo;
 }
 
-Color& Color::operator-=(float rhs)
+Color HSVAi(int r, int g, int b, int a)
 {
-  rgba[0]-=rhs;
-  rgba[1]-=rhs;
-  rgba[2]-=rhs;
-  rgba[3]-=rhs;
-  return *this;
+  static float f=1.0/65535.0;
+  Color nrvo;
+  nrvo.SetHSV(static_cast<float>(r)*f,static_cast<float>(g)*f,static_cast<float>(b)*f);
+  return nrvo;
 }
 
-Color& Color::operator/=(float rhs)
+std::ostream& operator<<(std::ostream& s, const Color& c)
 {
-  rgba[0]/=rhs;
-  rgba[1]/=rhs;
-  rgba[2]/=rhs;
-  rgba[3]/=rhs;  
-  return *this;
+  s << "Color(r=" << c.GetRed() << ",g=" <<c.GetGreen() << ",b=" << c.GetBlue() << ",h=" << c.GetHue() << ",s=" << c.GetSat() << ",v=" << c.GetVal() << ",a=" << c.GetAlpha() << ")";
+  return s;
 }
 
 }} // ns
diff --git a/modules/gfx/src/color.hh b/modules/gfx/src/color.hh
index 533381dbc07d06880f2f2b3ab00a2b1a3e72c0f3..6f0220bc2d2863c2744b502fee8c96dad21424ac 100644
--- a/modules/gfx/src/color.hh
+++ b/modules/gfx/src/color.hh
@@ -32,35 +32,114 @@
 
 namespace ost { namespace gfx {
 
-/// \brief color with red, green, blue and alpha component
+/*!
+  A color is defined in both RGB as well as HSV space, with an 
+  additional A component. To initialize a color use the factory
+  functions RGB(r,g,b), RGBA(r,g,b,a), HSV(h,s,v) and HSVA(h,s,v,a)
+
+  All values are defined in the range of 0.0 to 1.0, but are not clamped
+  on reading or writing, except when updating cross-domain, i.e. changes 
+  to R,G or B cause HSV to be updated accordingly, and vice versa.
+  This may cause previously out-of-bounds values to become clamped or wrapped
+  to the defined domain. An out-of-bounds H will be wrapped to be between 0 and 1, 
+  all others will be clamped.
+
+  For interaction with OpenGL, an operator float* method exists that
+  return a pointer to a float[4], in the order RGBA
+
+  Operator overloading works on the RGB components, i.e. C1+C2, C+s, C*s
+*/
 class DLLEXPORT_OST_GFX Color :   
   private boost::additive<Color>,
   private boost::additive<Color, float>,
   private boost::multiplicative<Color, float>{
+
 public:
-  Color() {
-    rgba[0]=1.0;
-    rgba[1]=1.0;
-    rgba[2]=1.0;
-    rgba[3]=1.0;
-  }
+  //! \brief initialize to white
+  Color();
+
+  //! convenience to set RGB triplet (ranges 0-1)
+  void SetRGB(float r, float g, float b);
+  //! convenience to get RGB triplet as Vec3
+  geom::Vec3 GetRGB() const;
+  //! convenience to get RGBA as Vec4
+  geom::Vec4 GetRGBA() const;
+  //! retrieve red
+  float GetRed() const;
+  //! set red
+  void SetRed(float);
+  //! retrieve green
+  float GetGreen() const;
+  //! set green
+  void SetGreen(float);
+  //! retrieve blue
+  float GetBlue() const;
+  //! set blue
+  void SetBlue(float);
+  //! convenience to set HSV triplet (ranges 0-1)
+  void SetHSV(float h, float s, float v);
+  //! convenience to get HSV triplet as Vec3
+  geom::Vec3 GetHSV() const;
+  //! convenience to get HSVA as Vec4
+  geom::Vec4 GetHSVA() const;
+  //! retrieve hue
+  float GetHue() const;
+  //! set hue
+  void SetHue(float);
+  //! retrieve saturatuin
+  float GetSat() const;
+  //! set saturation
+  void SetSat(float);
+  //! retrieve value
+  float GetVal() const;
+  //! set value
+  void SetVal(float);
+  //! retrieve alpha
+  float GetAlpha() const;
+  //! set alpha
+  void SetAlpha(float);
+
   
-  Color(float r, float g, float b, float a=1.0) {
-    rgba[0]=r;
-    rgba[1]=g;
-    rgba[2]=b;
-    rgba[3]=a;
-  }
+  /*!
+    \brief direct access to RGBA components
+
+    In the context of a OpenGL call that requires a pointer
+    to an RGB or RGBA float triplet or quadruplet, this will
+    do the automatic casting from a Color object, i.e. 
+    glColor3fv(my_color);
+
+    This will also allow access to the RGBA values
+    via the array notation, i.e. my_color[0]
+  */
+  operator const float* () const;
+  operator float* ();
+  
+  Color& operator*=(float rhs);
+  Color& operator+=(float rhs);
+    
+  Color& operator+=(const Color& rhs);  
+  Color& operator-=(const Color& rhs);    
+  Color& operator-=(float rhs);
+  Color& operator/=(float rhs);  
+
+  ////////////////////////////////////////////////////////////////
 
-  float& Red() {return rgba[0];}
-  const float& Red() const {return rgba[0];}
-  float& Green() {return rgba[1];}
-  const float& Green() const {return rgba[1];}
-  float& Blue() {return rgba[2];}
-  const float& Blue() const {return rgba[2];}
-  float& Alpha() {return rgba[3];}
-  const float& Alpha() const {return rgba[3];}
+  //! DEPRECATED
+  geom::Vec3 ToHSV() const {return GetHSV();}
 
+  //! DEPRECATED
+  Color(float r, float g, float b, float a=1.0);
+
+  //! DEPRECATED
+  float Red() const {return GetRed();}
+  //! DEPRECATED
+  float Green() const {return GetGreen();}
+  //! DEPRECATED
+  float Blue() const {return GetBlue();}
+  //! DEPRECATED
+  float Alpha() const {return GetAlpha();}
+
+  //! DEPRECATED
   static Color FromRGB(unsigned char r, unsigned char g, 
                        unsigned char b, unsigned char a = 0xff) {
     static float f=1.0/255.0;
@@ -68,32 +147,91 @@ public:
                  f*static_cast<float>(b),f*static_cast<float>(a));
   }
 
-  geom::Vec3 ToHSV();
+  ////////////////////////////////////////////////////////////////
 
-  // these also take care of operator[](uint i) !
-  operator float* () {return rgba;}
-  operator const float* () const {return rgba;}
-  
-  Color& operator*=(float rhs);
-  Color& operator+=(float rhs);
-    
-  Color& operator+=(const Color& rhs);  
-  Color& operator-=(const Color& rhs);    
-  Color& operator-=(float rhs);
-  Color& operator/=(float rhs);  
 private:
-  float rgba[4];
+  void to_hsv() const;
+  void to_rgb() const;
+
+  mutable float rgba_[4];
+  mutable float hsv_[3];
+  mutable bool rgb_dirty_;
+  mutable bool hsv_dirty_;
 };
 
+
+/// \brief RGB color spec from floats (0.0-1.0)
+Color DLLEXPORT_OST_GFX RGB(float r, float g, float b);
+
+/// \brief RGB color spec from bytes (0-255)
+Color DLLEXPORT_OST_GFX RGBb(uchar r, uchar g, uchar b);
+
+/// \brief RGB color spec from integers (0-65535)
+Color DLLEXPORT_OST_GFX RGBi(unsigned int r, unsigned int g, unsigned int b);
+
+/// \brief RGBA color spec from floats (0.0-1.0)
+Color DLLEXPORT_OST_GFX RGBA(float r, float g, float b, float a);
+
+/// \brief RGBA color spec from bytes (0-255)
+Color DLLEXPORT_OST_GFX RGBAb(uchar r, uchar g, uchar b, uchar a);
+
+/// \brief RGBA color spec from integers (0-65535)
+Color DLLEXPORT_OST_GFX RGBAi(unsigned int r, unsigned int g, unsigned int b, unsigned int a);
+
+
 /*!
-  \brief HSV color spec
+  \brief HSV color spec from floats
+
+  h: Hue from 0 to 1 (0=red, 2/6=green, 4/6=blue)
+     outside values are modulus 1, not clamped
+  s: Saturation from 0 (no color) to 1 (full color)
+     outside values are clamped
+  v: Value from 0 (no light, black) to 1 (full light)
+     outside values are clamped
 
-  h: Hue from 0 to 360 (0=red, 120=green, 240=blue)
+  out-of-bounds values are perfectly fine, as they are
+  sometimes needed in hsv gradients, e.g.
+
+  g1=gfx.Gradient([gfx.HSV(-60.0/360.0,1,1),gfx.HSV(60.0/360.0,1,1)])
+  g1.hsv_mode=True
+  g2=gfx.Gradient([gfx.HSV(300.0/360.0,1,1),gfx.HSV(420.0/360.0,1,1)])
+  g2.hsv_mode=True
+
+  both will blend from purple to yellow via red
+*/
+Color DLLEXPORT_OST_GFX HSV(float h, float s, float v);
+
+/*!
+  \brief HSV color spec from integers
+
+  h: Hue from 0 to 359 (0=red, 120=green, 240=blue)
+     outside values are modulus 360, not clamped
   s: Saturation from 0 (no color) to 100 (full color)
+     outside values are clamped
   v: Value from 0 (no light, black) to 100 (full light)
+     outside values are clamped
+
+  signed integers on purpose, allows negative values to be
+  used for hsv gradients, see comments for HSV(float,float,float)
 */
-Color DLLEXPORT_OST_GFX HSV(double h, double s, double v);
+  Color DLLEXPORT_OST_GFX HSVi(int h, int s, int v);
+
+/*!
+  \brief HSVA color spec from floats
+
+  see HSV(float,float,float); alpha from 0 to 1
+*/
+Color DLLEXPORT_OST_GFX HSVA(float h, float s, float v, float a);
+
+/*!
+  \brief HSVA color spec from integers
+
+  see HSVi(int, int, int); alpha from 0 to 100
+*/
+Color DLLEXPORT_OST_GFX HSVAi(int h, int s, int v, int a);
+
 
+//! \brief string form
 DLLEXPORT_OST_GFX std::ostream& operator<<(std::ostream&, const Color& c);
 
 }}
diff --git a/modules/gfx/src/color_ops/by_chain_color_op.cc b/modules/gfx/src/color_ops/by_chain_color_op.cc
index b2cd381a2003fb1e0262491d04c566dfc2b0a718..d2c6789f9c5b6d4b21239f490b9b29a70bad8de4 100644
--- a/modules/gfx/src/color_ops/by_chain_color_op.cc
+++ b/modules/gfx/src/color_ops/by_chain_color_op.cc
@@ -59,22 +59,37 @@ void ByChainColorOp::ApplyTo(GfxObjP& objP) const{
   }
 }
 
-gfx::Color ByChainColorOp::GetColor(String ident) const{
-  if(colors_.find(ident) == colors_.end())
-  {
-    colors_[ident] = GenerateColor(ident);
+/*
+  The first chain will be assigned a gradient stop of 0.
+  The next chain will be assigned a gradient stop of n/(N-1), where
+  n is the number of chains assigned so far, and N is the total
+  number of chains; thus for 3 total chains, the second gets a stop
+  of 0.5 (1/(3-1)), and the third gets a stop of 1.0 (2/(3-1))
+*/
+gfx::Color ByChainColorOp::GetColor(const String& ident) const
+{
+  std::map<String,Color>::const_iterator cit = colors_.find(ident);
+  if(cit == colors_.end()) {
+    float f = static_cast<float>(colors_.size())*cm_;
+    Color c = color_grad_.GetColorAt(f);
+    colors_[ident] = c;
+    return c;
+  } else {
+    return cit->second;
   }
-  return colors_[ident];
 }
 
-int ByChainColorOp::GetChainCount() const
+unsigned int ByChainColorOp::GetChainCount() const
 {
   return chain_count_;
 }
 
-void ByChainColorOp::SetChainCount(int chain_count)
+void ByChainColorOp::SetChainCount(unsigned int chain_count)
 {
   chain_count_ = chain_count;
+  cm_=chain_count>1 ? 1.0/static_cast<float>(chain_count_-1) : 0.0;
+  // invalidate all assigned colors so far
+  colors_.clear();
 }
 
 gfx::ByChainColorOp ByChainColorOp::FromInfo(info::InfoGroup& group){
@@ -84,16 +99,5 @@ gfx::ByChainColorOp ByChainColorOp::FromInfo(info::InfoGroup& group){
   return gfx::ByChainColorOp(wrapper, mask);
 }
 
-gfx::Color ByChainColorOp::GenerateColor(String& ident) const{
-  unsigned int size=colors_.size()-1;
-  if(size<=0){
-    colors_[ident] = color_grad_.GetColorAt(0.0);
-  }
-  else{
-    colors_[ident] = color_grad_.GetColorAt(float(size) / chain_count_);
-  }
-  return colors_[ident];
-}
-
 }}
 
diff --git a/modules/gfx/src/color_ops/by_chain_color_op.hh b/modules/gfx/src/color_ops/by_chain_color_op.hh
index 2b41e737fa78e3438a0d69f98d50f85199f77878..58485af37577c0d5848992020608c9a54c593fbd 100644
--- a/modules/gfx/src/color_ops/by_chain_color_op.hh
+++ b/modules/gfx/src/color_ops/by_chain_color_op.hh
@@ -38,13 +38,14 @@ public:
   ByChainColorOp(const String& selection, int mask=DETAIL_COLOR|MAIN_COLOR);
   ByChainColorOp(const mol::QueryViewWrapper& query_view, int mask=DETAIL_COLOR|MAIN_COLOR);
 
+  // Color Op interface
   virtual bool CanApplyTo(const GfxObjP& obj) const;
   virtual void ApplyTo(GfxObjP& obj) const;
 
-  virtual gfx::Color GetColor(String ident) const;
-
-  virtual int GetChainCount() const;
-  virtual void SetChainCount(int chain_count);
+  // this interface
+  Color GetColor(const String& ident) const;
+  unsigned int GetChainCount() const;
+  void SetChainCount(unsigned int chain_count);
 
   //virtual void ToInfo(info::InfoGroup& group) const;
   static gfx::ByChainColorOp FromInfo(info::InfoGroup& group);
@@ -53,8 +54,9 @@ private:
   void Init();
   gfx::Color GenerateColor(String& ident) const;
 
-  mutable int chain_count_;
-  mutable std::map<String,gfx::Color> colors_;
+  unsigned int chain_count_;
+  float cm_; // 1 over chain_count
+  mutable std::map<String,Color> colors_;
 
   gfx::Gradient color_grad_;
 };
diff --git a/modules/gfx/src/entity.cc b/modules/gfx/src/entity.cc
index dff4bfa1fb8465036438a59ebdf8f72dc2a3277b..3aec22fe5eaee632938be7b74ba4bc97342db774 100644
--- a/modules/gfx/src/entity.cc
+++ b/modules/gfx/src/entity.cc
@@ -252,39 +252,11 @@ void Entity::UpdatePositions()
 
 
 
-geom::AlignedCuboid Entity::GetBoundingBox() const
+geom::AlignedCuboid Entity::GetBoundingBox(bool use_tf) const
 {
   this->UpdateIfNeeded();
-  return bbox_;
-}
-
-void Entity::ProcessLimits(geom::Vec3& minc, geom::Vec3& maxc, 
-                           const Transform& tf) const
-{
-  try {
-    geom::AlignedCuboid coord_limits=this->GetBoundingBox();
-    // update min/max by transforming all 8 corners of the bounding box and 
-    // comparing it against the current min/max
-    geom::Vec3 mmin=coord_limits.GetMin();
-    geom::Vec3 mmax=coord_limits.GetMax();
-    geom::Vec3 t1=tf.Apply(geom::Vec3(mmin[0], mmin[1], mmin[2]));
-    geom::Vec3 t2=tf.Apply(geom::Vec3(mmin[0], mmax[1], mmin[2]));
-    geom::Vec3 t3=tf.Apply(geom::Vec3(mmax[0], mmin[1], mmin[2]));
-    geom::Vec3 t4=tf.Apply(geom::Vec3(mmax[0], mmax[1], mmin[2]));
-    geom::Vec3 t5=tf.Apply(geom::Vec3(mmin[0], mmin[1], mmax[2]));
-    geom::Vec3 t6=tf.Apply(geom::Vec3(mmin[0], mmax[1], mmax[2]));
-    geom::Vec3 t7=tf.Apply(geom::Vec3(mmax[0], mmin[1], mmax[2]));
-    geom::Vec3 t8=tf.Apply(geom::Vec3(mmax[0], mmax[1], mmax[2]));
-    minc = geom::Min(minc, geom::Min(t1, geom::Min(t2, geom::Min(t3, 
-                     geom::Min(t4, geom::Min(t5, geom::Min(t6, 
-                     geom::Min(t7, t8))))))));
-    maxc = geom::Max(maxc, geom::Max(t1, geom::Max(t2, geom::Max(t3, 
-                     geom::Max(t4, geom::Max(t5, geom::Max(t6,
-                     geom::Max(t7, t8))))))));
-  } catch(Error& e) {
-    // in case the object is empty...
-  }
-} 
+  return use_tf ? transform_.Apply(bbox_) : bbox_;
+}
 
 void Entity::SetColorForAtom(const Color& col,
                              const AtomHandle& atom) 
@@ -471,7 +443,7 @@ bool Entity::OnSelect(const geom::Line3& line, geom::Vec3& result,
         return true;
       }
       if(smode==1) {
-        AtomView av = sel_.FindAtom(sel.GetHandle());
+        AtomView av = sel_.ViewForHandle(sel.GetHandle());
         if(av.IsValid()) {
           LOG_DEBUG("de-selected atom: " << sel);
           sel_.RemoveAtom(av);
@@ -484,8 +456,8 @@ bool Entity::OnSelect(const geom::Line3& line, geom::Vec3& result,
         }
         result = sel.GetPos();
       } else if(smode==2) {
-        AtomView av=sel_.FindAtom(sel);
-        ResidueView rv=sel_.FindResidue(sel.GetResidue());
+        AtomView av=sel_.ViewForHandle(sel);
+        ResidueView rv=sel_.ViewForHandle(sel.GetResidue());
         if(av.IsValid() && rv.IsValid()) {
           LOG_DEBUG("de-selected residue: " << sel.GetResidue());
           sel_.RemoveResidue(rv);
@@ -500,7 +472,7 @@ bool Entity::OnSelect(const geom::Line3& line, geom::Vec3& result,
           return false;
         }
         ChainHandle chain=sel.GetHandle().GetResidue().GetChain();
-        ChainView cv = sel_.FindChain(chain);
+        ChainView cv = sel_.ViewForHandle(chain);
         if(cv.IsValid()) {
           LOG_DEBUG("de-selected chain: " << chain);
           sel_.RemoveChain(cv);
@@ -968,7 +940,7 @@ void Entity::ColorBy(const String& prop,
                      const Color& c1, const Color& c2,
                      mol::Prop::Level level)
 {
-  std::pair<float,float> minmax = this->GetView().GetMinMax(prop);
+  std::pair<float,float> minmax = this->GetView().GetMinMax(prop, level);
   this->ColorBy(prop,c1,c2,minmax.first, minmax.second,level);
 }
 
diff --git a/modules/gfx/src/entity.hh b/modules/gfx/src/entity.hh
index 7663fe3782fe053df4eb7f0428d6401da26905c9..112a7ac4d8f5b5dbdd6db517a673b9ded7180a34 100644
--- a/modules/gfx/src/entity.hh
+++ b/modules/gfx/src/entity.hh
@@ -90,11 +90,10 @@ public:
          RenderMode::Type m,
          const mol::EntityView& ev);
 
-  virtual geom::AlignedCuboid GetBoundingBox() const;
-  
-  virtual void ProcessLimits(geom::Vec3& minc, geom::Vec3& maxc, 
-                             const mol::Transform& tf) const;
+  virtual geom::AlignedCuboid GetBoundingBox(bool use_global=false) const;
 
+  // ProcessLimits uses the default implementation of bounding box
+  
   /// internal routine
   virtual void CustomRenderGL(RenderPass pass);
 
diff --git a/modules/gfx/src/gfx_object.cc b/modules/gfx/src/gfx_object.cc
index 1f0486017c6139adc74134f712d72409486744cd..d527ceffabf5b805535a0dc1c796cd74b82ab19b 100644
--- a/modules/gfx/src/gfx_object.cc
+++ b/modules/gfx/src/gfx_object.cc
@@ -394,7 +394,7 @@ void GfxObj::ColorBy(const img::MapHandle& mh,
 //////////////////////////////////////////////////
 // and now for the rest of the GfxObj interface
 
-geom::AlignedCuboid GfxObj::GetBoundingBox() const
+geom::AlignedCuboid GfxObj::GetBoundingBox(bool use_tf) const
 {
   return geom::AlignedCuboid(geom::Vec3(),geom::Vec3());
 }
@@ -403,25 +403,11 @@ void GfxObj::ProcessLimits(geom::Vec3& minc, geom::Vec3& maxc,
                            const mol::Transform& tf) const
 {
   try {
-    geom::AlignedCuboid coord_limits=this->GetBoundingBox();
+    geom::AlignedCuboid coord_limits=tf.Apply(this->GetBoundingBox(true));
     // update min/max by transforming all 8 corners of the bounding box and 
     // comparing it against the current min/max
-    geom::Vec3 mmin=coord_limits.GetMin();
-    geom::Vec3 mmax=coord_limits.GetMax();
-    geom::Vec3 t1=tf.Apply(geom::Vec3(mmin[0], mmin[1], mmin[2]));
-    geom::Vec3 t2=tf.Apply(geom::Vec3(mmin[0], mmax[1], mmin[2]));
-    geom::Vec3 t3=tf.Apply(geom::Vec3(mmax[0], mmax[1], mmin[2]));
-    geom::Vec3 t4=tf.Apply(geom::Vec3(mmax[0], mmin[1], mmin[2]));
-    geom::Vec3 t5=tf.Apply(geom::Vec3(mmin[0], mmin[1], mmax[2]));
-    geom::Vec3 t6=tf.Apply(geom::Vec3(mmin[0], mmax[1], mmax[2]));
-    geom::Vec3 t7=tf.Apply(geom::Vec3(mmax[0], mmax[1], mmax[2]));
-    geom::Vec3 t8=tf.Apply(geom::Vec3(mmax[0], mmin[1], mmax[2]));
-    minc = geom::Min(minc, geom::Min(t1, geom::Min(t2, geom::Min(t3, 
-                     geom::Min(t4, geom::Min(t5, geom::Min(t6, 
-                     geom::Min(t7, t8))))))));
-    maxc = geom::Max(maxc, geom::Max(t1, geom::Max(t2, geom::Max(t3, 
-                     geom::Max(t4, geom::Max(t5, geom::Max(t6,
-                     geom::Max(t7, t8))))))));
+    minc=geom::Min(minc,coord_limits.GetMin());
+    maxc=geom::Min(maxc,coord_limits.GetMax());
   } catch(Error& e) {
     // in case the object is empty...
   }
diff --git a/modules/gfx/src/gfx_object.hh b/modules/gfx/src/gfx_object.hh
index d241be75e19f15158d173554f01384b26cdab15f..8809e1046fe10d15c410bc51f86545cc1bc32cf1 100644
--- a/modules/gfx/src/gfx_object.hh
+++ b/modules/gfx/src/gfx_object.hh
@@ -101,15 +101,27 @@ public:
 
   // new gfx obj virtual interface starts here
 
-  /// \brief returns the left-bottom-front and the right-top-back corner
-  /// that encompasses all graphical elements in this object
-  /// 
-  /// the bounding box is in local coordinates. to obtain the coordinates in
-  /// the scene, multiply the bounding box by the object's transformation
-  ///  matrix.
-  virtual geom::AlignedCuboid GetBoundingBox() const;
-
-  /// \brief adjust the given limits according to the represented data
+  /*!
+    \brief returns the bounding box of this object
+
+    The bounding box, i.e. the left-bottom-front and the right-top-back corner
+    of the object, is obtained with this method. The single boolean parameter
+    denotes whether to return local coordinates or global scene coordinates; 
+    global scene coordinates are local coordinates with the object's transformation
+    (if present) applied. The default is false, i.e. return local coordinates.
+  */
+  virtual geom::AlignedCuboid GetBoundingBox(bool use_tf=false) const;
+
+  /*!
+    \brief adjust minimum and maximum extent based on graphical object
+
+    this routine will adjust the provided minimum and maximum points
+    based on the vertices of the underlying graphical representation,
+    combining the given Transform with the object transform.
+
+    If derived classes do not implement this method then the limits
+    will be adjusted based on the Cuboid returned by GetBoundingBox(true)
+  */
   virtual void ProcessLimits(geom::Vec3& minc, geom::Vec3& maxc, 
                              const mol::Transform& tf) const;
 
diff --git a/modules/gfx/src/glext_include.hh b/modules/gfx/src/glext_include.hh
index 183f6112cbd9bfb91bf57323faf759cad3e3918f..557dcb36045c75542d1fa9df5d24edecfc47a1f5 100644
--- a/modules/gfx/src/glext_include.hh
+++ b/modules/gfx/src/glext_include.hh
@@ -29,7 +29,7 @@
 #include <ost/config.hh>
 
 #if OST_SHADER_SUPPORT_ENABLED
-#ifdef OST_MESA_SUPPORT_ENABLED
+#if OST_MESA_SUPPORT_ENABLED
 #  define OST_GL_VERSION_2_0 1
 #  define GL_GLEXT_PROTOTYPES 1
 #  include <GL/gl.h>
diff --git a/modules/gfx/src/gradient.cc b/modules/gfx/src/gradient.cc
index 3414135afb8cb605ba0a3874d3a91af0748f1e89..c65261b16a60eb2deac7ecfcf41def8be63239f5 100644
--- a/modules/gfx/src/gradient.cc
+++ b/modules/gfx/src/gradient.cc
@@ -19,6 +19,9 @@
 #include "gradient.hh"
 #include <iostream>
 #include <vector>
+#include <algorithm>
+
+#include <ost/log.hh>
 
 #include <ost/info/info.hh>
 #include <ost/info/info_fw.hh>
@@ -28,13 +31,18 @@
 namespace ost { namespace gfx {
 
 
-Gradient::Gradient() 
-{
-}
+Gradient::Gradient():
+  stops_(),
+  hsv_mode_(false)
+{}
 
 Gradient::Gradient(const String& name)
 {
   Gradient gradient = GradientManager::Instance().GetGradient(name);
+  // why doesn't this work:
+  //  stops_=gradient.stops_
+  // or even better
+  //  *this = gradient
   StopList stops = gradient.GetStops();
   for(unsigned int i = 0; i < stops.size(); i++){
     Stop stop = stops[i];
@@ -55,8 +63,11 @@ void Gradient::SetColorAt(float t, const Color& c)
 
 Color Gradient::GetColorAt(float t) const
 {
-  if (stops_.empty())
-    throw Error("Can not calculate color with 0 Stops set!");
+  if (stops_.empty()) {
+    return Color();
+  } else if(stops_.size()==1) {
+    return stops_[0].color;
+  }
   
   uint c=0;
   while (t>=stops_[c].t && c<stops_.size()) {
@@ -64,16 +75,17 @@ Color Gradient::GetColorAt(float t) const
   }
   if (c==0) {
     return stops_.front().color;
-  }
-  if (c==stops_.size()) {
+  } else if (c==stops_.size()) {
     return stops_.back().color;
   }
-  float d=stops_[c].t-stops_[c-1].t;
-  float tt=0.0;
-  if (d>0.0001) {
-    tt=(t-stops_[c-1].t)/d;
-  } 
-  return stops_[c-1].color*(1.0-tt)+stops_[c].color*tt;
+  float d = stops_[c].t-stops_[c-1].t;
+  float tt = d>0.001  ? (t-stops_[c-1].t)/d : 0.0;
+  if(hsv_mode_) {
+    geom::Vec4 v=stops_[c-1].color.GetHSVA()*(1.0-tt)+stops_[c].color.GetHSVA()*tt;
+    return HSVA(v[0],v[1],v[2],v[3]);
+  } else {
+    return stops_[c-1].color*(1.0-tt)+stops_[c].color*tt;
+  }
 }
 
 void Gradient::GradientToInfo(info::InfoGroup& group) const
@@ -86,6 +98,7 @@ void Gradient::GradientToInfo(info::InfoGroup& group) const
     ss << stops_[i].t << "\t" << stops_[i].color.Red() << "\t" << stops_[i].color.Green() << "\t" << stops_[i].color.Blue() << "\t" << stops_[i].color.Alpha() << "\n";
   }
   group.SetTextData(ss.str());
+  group.SetAttribute("hsv_mode",hsv_mode_? "1" : "0");
 }
 
 Gradient::StopList Gradient::GetStops() const{
@@ -95,6 +108,16 @@ Gradient::StopList Gradient::GetStops() const{
 Gradient Gradient::GradientFromInfo(const info::InfoGroup& group)
 {
   std::istringstream ss(group.GetTextData());
+  bool hsv_color=false;
+  if(group.HasAttribute("hsv_color")) {
+    String hsv_color_s = group.GetAttribute("hsv_color");
+    std::transform(hsv_color_s.begin(), hsv_color_s.end(), hsv_color_s.begin(), ::tolower);
+    if(hsv_color_s=="0" || hsv_color_s=="false" || hsv_color_s=="no" || hsv_color_s=="off") {
+      hsv_color=false;
+    } else {
+      hsv_color=true;
+    }
+  }
   Gradient grad;
 
   StopList::size_type size = 0;
@@ -102,10 +125,19 @@ Gradient Gradient::GradientFromInfo(const info::InfoGroup& group)
   float t, r, g, b, a;
   for( StopList::size_type i = 0; i < size; i++ ) {
     ss >> t >> r >> g >> b >> a;
-    Color c = Color(r,g,b,a);
+    Color c = hsv_color ? HSVA(r,g,b,a) : RGBA(r,g,b,a);
     grad.SetColorAt(t, c);
   }
 
+  if(group.HasAttribute("hsv_mode")) {
+    String hsv_mode_s = group.GetAttribute("hsv_mode");
+    std::transform(hsv_mode_s.begin(), hsv_mode_s.end(), hsv_mode_s.begin(), ::tolower);
+    if(hsv_mode_s=="0" || hsv_mode_s=="false" || hsv_mode_s=="no" || hsv_mode_s=="off") {
+      grad.SetHSVMode(false);
+    } else {
+      grad.SetHSVMode(true);
+    }
+  }
   return grad;
 }
 
diff --git a/modules/gfx/src/gradient.hh b/modules/gfx/src/gradient.hh
index 0b220faf060cc656cf9a52dbd3bccee98f2d8821..e08a24edaf22bdc3841fed3514574a5f9cd5650b 100644
--- a/modules/gfx/src/gradient.hh
+++ b/modules/gfx/src/gradient.hh
@@ -20,8 +20,8 @@
 #define OST_GFX_GRADIENT_HH
 
 /*
-  Author: Marco Biasini
- */
+  Authors: Marco Biasini, Ansgar Philippsen
+*/
 
 #include <vector>
 
@@ -30,16 +30,32 @@
 #include <ost/info/info.hh>
 #include <ost/info/info_fw.hh>
 
-
 namespace ost { namespace gfx {
 
-/// \brief color gradient
-/// 
-/// Gradients map a scalar value in the range of 0 to 1 to a color. The 
-/// gradient consists of zero or more color stops. These stop points define the 
-/// output of GetColorAt(). New stops can be added with SetColorAt().
-/// 
-/// \sa \ref gradient.py "Gradient Example"
+/*!
+ \brief color gradient
+ 
+ Gradients map a scalar value in the range of 0 to 1 to a color. The 
+ gradient consists of zero or more color stops. These stop points define the 
+ output of GetColorAt(). New stops can be added with SetColorAt().
+
+ Usually, the gradient operates in RGB colorspace, which means a linear
+ interpolation of each color component between stops. As an alternative,
+ interpolation can also be done in HSV colorspace, by setting HSV mode
+ to true with SetHSVMode(). However, carefully using HSV colorspace will
+ yield better results, if some potential caveats are taken into consideration.
+ The best example is a simple gradient from red to blue. The half-point in RGB
+ colorspace is (0.5,0.0,0.5), so a darkish purple. Converting to HSV one can see
+ that the saturation is at 50%, which is unfortunate. Using hsv mode can circument
+ this issue, but in the above example, naively using hsv mode will give green
+ at the half-point and not purple. Why? Because red translates to HSV(0,1,1) and blue to
+ HSV(2/3,1,1), which at the half-point is HSV(1/3,1,1), or green. To interpolate
+ on the hue in the other direction, use HSV and unwrapped hue values, e.g. 
+ [HSV(0.0,1,1),HSV(-1/3,1,1)] or [HSV(1,1,1),HSV(2/3,1,1)] - both of these will
+ give a half-point or a nice purple with full saturation
+ 
+ \sa \ref gradient.py "Gradient Example"
+*/
 class DLLEXPORT_OST_GFX Gradient {
 public:
   struct Stop {
@@ -49,14 +65,14 @@ public:
     float t;
     Color color;
     
-    Color GetColor(){
+    Color GetColor() const {
       return color;
     }
     
-    float GetRel(){
+    float GetRel() const {
       return t;
     }
-    
+
     bool operator==(const Stop& ref) const
     {
       return t==ref.t && color==ref.color;
@@ -85,16 +101,26 @@ public:
   void SetColorAt(float t, const Color& color);  
   
   /// \brief convert gradient to info
+  // TODO: rename to ToInfo
+  // TODO:: add stand-alone function named GradientToInfo(Gradient, InfoGroup)
   void GradientToInfo(info::InfoGroup& group) const;
 
   /// \brief get list of color stops
   StopList GetStops() const;
   
   /// \brief create gradient from info
+  // TODO: move outside
+  // TODO: add FromInfo member function that overwrites this
   static gfx::Gradient GradientFromInfo(const info::InfoGroup& group);
+
+  /// \brief turn HSV interpolation mode on or off
+  void SetHSVMode(bool m) {hsv_mode_=m;}
+  /// \brief return the HSV interpolation mode flag
+  bool GetHSVMode() const {return hsv_mode_;}
+    
 private:
   std::vector<Stop>  stops_;
-
+  bool hsv_mode_;
 };
 
 
diff --git a/modules/gfx/src/impl/backbone_trace.cc b/modules/gfx/src/impl/backbone_trace.cc
index ad9e8c961b0cedea3073cdd8183fc636662b5397..efcd761a5304f9f6c03ffe5362d7ee976dda8d2e 100644
--- a/modules/gfx/src/impl/backbone_trace.cc
+++ b/modules/gfx/src/impl/backbone_trace.cc
@@ -85,6 +85,7 @@ public:
     mol::AtomHandle ca = res.GetCentralAtom();
     if (ca) {
       float rad=1.0;
+      // TODO: move this property to the rendering state
       if(ca.HasProp("trace_rad")) {
         rad=ca.GetFloatProp("trace_rad");
       }
@@ -253,7 +254,7 @@ BackboneTrace BackboneTrace::CreateSubset(const mol::EntityView& subview)
     NodeEntryList new_nlist;
     const NodeEntryList& nlist=*nitnit;
     for(NodeEntryList::const_iterator nit=nlist.begin();nit!=nlist.end();++nit) {
-      if(subview.FindAtom(nit->atom).IsValid()) {
+      if(subview.ViewForHandle(nit->atom).IsValid()) {
         if(!new_nlist.empty()) {
           if(!in_sequence(new_nlist.back().atom.GetResidue(),nit->atom.GetResidue(),seq_hack_)) {
             if(new_nlist.size()>1) {
diff --git a/modules/gfx/src/impl/cartoon_renderer.cc b/modules/gfx/src/impl/cartoon_renderer.cc
index 9af2bdf80e4b5e837d6ac8d0be849d700a87f365..f9eee510679686554c1f7bfac9fd6550f7e3f837 100644
--- a/modules/gfx/src/impl/cartoon_renderer.cc
+++ b/modules/gfx/src/impl/cartoon_renderer.cc
@@ -362,8 +362,9 @@ void CartoonRenderer::rebuild_spline_obj(IndexedVertexArray& va,
     if(slist.size()==2 && slist[0].type==6) {
       // make a cylinder
       va.AddCylinder(CylinderPrim(slist[0].position,slist[1].position,
-				  options_->GetHelixWidth(),
-				  slist[0].color1,slist[1].color1),
+                                  options_->GetHelixWidth(),
+                                  slist[0].color1,
+                                  slist[1].color1),
 		     options_->GetArcDetail(),true);
       continue;
     }
@@ -458,7 +459,7 @@ TraceProfile CartoonRenderer::transform_and_add_profile(const std::vector<TraceP
       norm=Normalize(norm);
     }
     tf_prof[c]=TraceProfileEntry(vec,norm);
-    Color col = se.color1;
+    RGBAColor col = se.color1;
     if(se.type==1) {
       if(se.nflip) {
         col = c<half ? se.color1 : se.color2;
@@ -523,7 +524,7 @@ void CartoonRenderer::cap_profile(const impl::TraceProfile& p,
                                   bool flipn, IndexedVertexArray& va)
 {
   geom::Vec3 norm=flipn ? -se.direction : se.direction;
-  VertexID pi0 = va.Add(se.position,norm, se.color1,geom::Vec2(0.5,0.5));
+  VertexID pi0 = va.Add(se.position,norm, se.color1, geom::Vec2(0.5,0.5));
   std::vector<VertexID> vertices(p.size());
   float fac=2.0*M_PI/static_cast<float>(p.size()-1);
   for(unsigned int i=0;i<p.size();++i) {
diff --git a/modules/gfx/src/impl/connect_renderer_base.cc b/modules/gfx/src/impl/connect_renderer_base.cc
index fd70d9968b67270d14c837de128fcbce9a003460..5f0ed4a6b8f821866eb587ac7110a0df28a307d4 100644
--- a/modules/gfx/src/impl/connect_renderer_base.cc
+++ b/modules/gfx/src/impl/connect_renderer_base.cc
@@ -145,7 +145,7 @@ inline void apply_color_op(ConnectRendererBase* rend, GfxView* v, T1 get_col, co
     view = op.GetView();
   }
   for(AtomEntryMap::iterator it=v->atom_map.begin();it!=v->atom_map.end();++it){
-    if(view.FindAtom(it->second.atom)){
+    if(view.ViewForHandle(it->second.atom)){
       it->second.color=get_col.ColorOfAtom(it->second.atom).second;
     }
   }
diff --git a/modules/gfx/src/impl/cpk_renderer.cc b/modules/gfx/src/impl/cpk_renderer.cc
index a0d286047394023c807e49b9a44c9b9346e83b27..f780647b745c51658d12fd3e97dbc05359159baf 100644
--- a/modules/gfx/src/impl/cpk_renderer.cc
+++ b/modules/gfx/src/impl/cpk_renderer.cc
@@ -32,7 +32,12 @@
 
 namespace ost { namespace gfx { namespace impl {
 
-CPKRenderer::CPKRenderer(): options_(new CPKRenderOptions()) {
+CPKRenderer::CPKRenderer(): 
+  options_(new CPKRenderOptions())
+#if OST_SHADER_SUPPORT_ENABLED
+  ,fsr_(),sel_fsr_()
+#endif  
+{
   this->SetName("Spheres");
 }
 
@@ -51,25 +56,39 @@ void CPKRenderer::PrepareRendering()
 
 void CPKRenderer::PrepareRendering(GfxView& view, IndexedVertexArray& va, bool is_sel)
 {
-  const Color& sel_clr=this->GetSelectionColor();
+  RGBAColor sel_clr=this->GetSelectionColor();
   float factor=is_sel ? 1.2 : 1.0;
   if(options_!=NULL){
     factor *= options_->GetRadiusMult();
     if(factor>0.0) {
-      va.SetLighting(true);
-      va.SetCullFace(true);
-      va.SetColorMaterial(true);
-      va.SetMode(0x4);
-      
-      // draw all spheres
-      uint det=options_->GetSphereDetail();
-      for(AtomEntryMap::const_iterator it=view.atom_map.begin();it!=view.atom_map.end();++it) {
-        va.AddSphere(SpherePrim(it->second.atom.GetPos(),
-                                it->second.vdwr*factor,
-                                is_sel? sel_clr : it->second.color),
-                     det);
+#if OST_SHADER_SUPPORT_ENABLED
+      if(options_->GetSphereMode()==1 || options_->GetSphereMode()==2) {
+        FastSphereRenderer& fsr = is_sel ? sel_fsr_ : fsr_;
+        fsr.Clear();
+        for(AtomEntryMap::const_iterator it=view.atom_map.begin();it!=view.atom_map.end();++it) {
+          fsr.Add(it->second.atom.GetPos(),
+                  is_sel? sel_clr : it->second.color,
+                  it->second.vdwr*factor);
+        }
+      } else {
+#endif
+        va.SetLighting(true);
+        va.SetCullFace(true);
+        va.SetColorMaterial(true);
+        va.SetMode(0x4);
+        
+        // draw all spheres
+        uint det=options_->GetSphereDetail();
+        for(AtomEntryMap::const_iterator it=view.atom_map.begin();it!=view.atom_map.end();++it) {
+          va.AddSphere(SpherePrim(it->second.atom.GetPos(),
+                                  it->second.vdwr*factor,
+                                  is_sel? sel_clr : it->second.color),
+                       det);
+        }
       }
+#if OST_SHADER_SUPPORT_ENABLED
     }
+#endif
   }
   sel_state_=0;
   state_=0;
@@ -79,13 +98,17 @@ void CPKRenderer::Render(RenderPass pass)
 {
   if(options_!=NULL){
 #if OST_SHADER_SUPPORT_ENABLED
-    if(pass==STANDARD_RENDER_PASS && (options_->GetSphereMode()==1 || options_->GetSphereMode()==2)) {
-      this->Render3DSprites();
+    if(options_->GetSphereMode()==1 || options_->GetSphereMode()==2) {
+      if(pass==STANDARD_RENDER_PASS) {
+        fsr_.RenderGL();
+      } else if(pass==GLOW_RENDER_PASS && this->HasSelection()) {
+        sel_fsr_.RenderGL();
+      }
       return;
     }
 #endif
   }
-  // fall back to parent if above did not fire
+  // fall back to default if above did not fire
   EntityRenderer::Render(pass);
 }
 
@@ -116,79 +139,4 @@ RenderOptionsPtr CPKRenderer::GetOptions(){
  return options_;
 }
 
-namespace {
-
-void Render3DSpritesInnerLoop(const AtomEntry* ae, const geom::Vec3& cx, 
-                              const geom::Vec3& cy, const geom::Vec3& cz, 
-                              GLdouble* gl_mmat, GLdouble* gl_pmat, GLint* gl_vp,
-                              float rmul)
-{
-  geom::Vec3 pos = ae->atom.GetPos();
-  float rad = rmul*ae->vdwr;
-  GLdouble r1[3],r2[3];
-  gluProject(pos[0],pos[1],pos[2],
-             gl_mmat,gl_pmat,gl_vp,
-             &r1[0],&r1[1],&r1[2]);
-  gluProject(pos[0]-rad*cz[0],pos[1]-rad*cz[1],pos[2]-rad*cz[2],
-             gl_mmat,gl_pmat,gl_vp,
-             &r2[0],&r2[1],&r2[2]);
-  float scale = r1[2]-r2[2];
-  glColor3fv(ae->color);
-  glTexCoord4f(0.0,0.0,-rad,scale);
-  glVertex3v((pos-rad*cx-rad*cy).Data());
-  glTexCoord4f(0.0,1.0,-rad,scale);
-  glVertex3v((pos-rad*cx+rad*cy).Data());
-  glTexCoord4f(1.0,1.0,-rad,scale);
-  glVertex3v((pos+rad*cx+rad*cy).Data());
-  glTexCoord4f(1.0,0.0,-rad,scale);
-  glVertex3v((pos+rad*cx-rad*cy).Data());
-}
-
-}
-
-void CPKRenderer::Render3DSprites()
-{
-#if OST_SHADER_SUPPORT_ENABLED
-  if(options_!=NULL){
-    float rmul= options_->GetRadiusMult();
-    if(rmul==0.0) return;
-
-    geom::Mat3 irot=geom::Transpose(Scene::Instance().GetTransform().GetRot());
-    geom::Vec3 cx=irot*geom::Vec3(1.0,0.0,0.0);
-    geom::Vec3 cy=irot*geom::Vec3(0.0,1.0,0.0);
-    geom::Vec3 cz=irot*geom::Vec3(0.0,0.0,1.0);
-
-    uint write_normals = Shader::Instance().GetCurrentName()=="dumpnorm" ? 1 : 0;
-    uint use_hemimodel = Shader::Instance().GetCurrentName()=="hemilight" ? 1 : 0;
-    Shader::Instance().PushProgram();
-    Shader::Instance().Activate("fast_sphere");
-    Shader::Instance().UpdateState();
-    glUniform1i(glGetUniformLocation(Shader::Instance().GetCurrentProgram(),"write_normals"),write_normals);
-    glUniform1i(glGetUniformLocation(Shader::Instance().GetCurrentProgram(),"use_hemimodel"),use_hemimodel);
-
-    glPushAttrib(GL_ALL_ATTRIB_BITS);
-    glDisable(GL_LIGHTING);
-    glDisable(GL_CULL_FACE);
-
-    GLdouble gl_mmat[16];
-    glGetDoublev(GL_MODELVIEW_MATRIX,gl_mmat);
-    GLdouble gl_pmat[16];
-    glGetDoublev(GL_PROJECTION_MATRIX,gl_pmat);
-    GLint gl_vp[]={0,0,1,1};
-
-    glBegin(GL_QUADS);
-    
-    for(AtomEntryMap::const_iterator it=view_.atom_map.begin();it!=view_.atom_map.end();++it) {
-      Render3DSpritesInnerLoop(&it->second,cx,cy,cz,gl_mmat,gl_pmat,gl_vp,rmul);
-    }
-    glEnd();
-
-    glPopAttrib();
-
-    Shader::Instance().PopProgram();
-    Shader::Instance().UpdateState();
-  }
-#endif
-}
-
 }}}
diff --git a/modules/gfx/src/impl/cpk_renderer.hh b/modules/gfx/src/impl/cpk_renderer.hh
index c32cb9cd11f9aa2a225f8cf22e8d495640be9339..1a6dcd2dcb12e0d811603dcf141a7203aa074aea 100644
--- a/modules/gfx/src/impl/cpk_renderer.hh
+++ b/modules/gfx/src/impl/cpk_renderer.hh
@@ -26,6 +26,10 @@
 #include <ost/gfx/impl/connect_renderer_base.hh>
 #include <ost/gfx/render_options/cpk_render_options.hh>
 
+#if OST_SHADER_SUPPORT_ENABLED
+#include "fast_spheres.hh"
+#endif
+
 namespace ost { namespace gfx { namespace impl {
 
 /// \internal
@@ -45,9 +49,11 @@ public:
 
 private:
   void PrepareRendering(GfxView& view, IndexedVertexArray& va, bool is_sel);
-  void Render3DSprites();
 
   CPKRenderOptionsPtr options_;
+#if OST_SHADER_SUPPORT_ENABLED
+  FastSphereRenderer fsr_,sel_fsr_;
+#endif
 };
 
 }}}
diff --git a/modules/gfx/src/impl/entity_detail.cc b/modules/gfx/src/impl/entity_detail.cc
index 3069077f4ea17e615aaf112742d993f1fc7a1bfa..02e40b2138edee1e989c80a6680fee04fedbc897 100644
--- a/modules/gfx/src/impl/entity_detail.cc
+++ b/modules/gfx/src/impl/entity_detail.cc
@@ -39,7 +39,7 @@ struct BlurQuadEntry
 {
   float zdist;
   geom::Vec3 p1,p2,p3,p4;
-  gfx::Color c1,c2,c3,c4;
+  RGBAColor c1,c2,c3,c4;
 };
 
 struct BlurQuadEntryLess
diff --git a/modules/gfx/src/impl/entity_detail.hh b/modules/gfx/src/impl/entity_detail.hh
index 5905d6b870ebeda937cde84a7eb9c4e85dd481bb..12412f680236afc25f67556971b76f8eac8f643d 100644
--- a/modules/gfx/src/impl/entity_detail.hh
+++ b/modules/gfx/src/impl/entity_detail.hh
@@ -39,13 +39,38 @@
 
 namespace ost { namespace gfx { namespace impl {
 
+struct RGBAColor {
+  RGBAColor() {
+    rgba[0]=1.0; rgba[1]=1.0; rgba[2]=1.0; rgba[3]=1.0;
+  }
+  RGBAColor(float r, float g, float b, float a=1.0) {
+    rgba[0]=r; rgba[1]=g; rgba[2]=b; rgba[3]=a;
+  }
+  RGBAColor(const Color& c) {
+    rgba[0]=c.GetRed(); rgba[1]=c.GetGreen(); rgba[2]=c.GetBlue(); rgba[3]=c.GetAlpha();
+  }
+
+  RGBAColor& operator=(const Color& c) {
+    rgba[0]=c.GetRed(); rgba[1]=c.GetGreen(); rgba[2]=c.GetBlue(); rgba[3]=c.GetAlpha();
+    return *this;
+  }
+
+  operator Color () const {return RGBA(rgba[0],rgba[1],rgba[2],rgba[3]);}
+
+  operator float* () {return rgba;}
+  operator const float* () const {return rgba;}
+  float rgba[4];
+};
+
 struct DLLEXPORT_OST_GFX AtomEntry 
 {
   AtomEntry() {}
   AtomEntry(const mol::AtomHandle& a, float r, float v, const Color& c):
-    atom(a),color(c),radius(r), vdwr(v) {}
+    atom(a), color(c), radius(r), vdwr(v) 
+  {
+  }
   mol::AtomHandle atom;
-  Color color;
+  RGBAColor color;
   float radius;
   float vdwr;
 };
@@ -88,7 +113,7 @@ typedef boost::shared_ptr<GfxView> GfxViewPtr;
 
 struct DLLEXPORT_OST_GFX NodeEntry {
   mol::AtomHandle atom;
-  Color color1, color2;
+  RGBAColor color1, color2;
   geom::Vec3 direction,normal;
   float rad;
   geom::Vec3 v0,v1,v2; // helper vectors
@@ -131,6 +156,16 @@ struct DLLEXPORT_OST_GFX SplineEntry {
     id(-1)
   {
   }
+  SplineEntry(const geom::Vec3& p, 
+              const geom::Vec3& d,
+              const geom::Vec3& n,
+              float r,
+              const RGBAColor& c1, const RGBAColor& c2,
+              unsigned int t, int i):
+    position(p),direction(d),normal(n),color1(c1),color2(c2),rad(r),type(t),
+    type1(t),type2(t),frac(0.0),running_length(0.0),v0(),v1(),v2(),nflip(false),id(i)
+  {
+  }
   SplineEntry(const geom::Vec3& p, 
               const geom::Vec3& d,
               const geom::Vec3& n,
@@ -143,7 +178,7 @@ struct DLLEXPORT_OST_GFX SplineEntry {
   }
 
   geom::Vec3 position,direction,normal;
-  Color color1, color2;
+  RGBAColor color1, color2;
   float rad;
   unsigned int type;
   unsigned int type1, type2;
diff --git a/modules/gfx/src/impl/fast_spheres.cc b/modules/gfx/src/impl/fast_spheres.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e10ac2d03d62fdc90a8eedc955d169b6ce1f8e55
--- /dev/null
+++ b/modules/gfx/src/impl/fast_spheres.cc
@@ -0,0 +1,133 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+
+/*
+  Author: Ansgar Philippsen
+*/
+
+#include <ost/config.hh>
+#if OST_SHADER_SUPPORT_ENABLED
+#include <ost/gfx/shader.hh>
+#endif
+#include <ost/gfx/scene.hh>
+
+#include "fast_spheres.hh"
+
+namespace ost { namespace gfx { namespace impl {
+
+  FastSphereRenderer::FastSphereRenderer(size_t reserve):
+    data_()
+  {
+    data_.reserve(reserve);
+  }
+
+  FastSphereRenderer::FastSphereRenderer(const DataList& d):
+    data_(d)
+  {}
+
+  void FastSphereRenderer::Clear()
+  {
+    data_.clear();
+  }
+
+  void FastSphereRenderer::Add(float pos[3], float col[4], float rad)
+  {
+    static VData data;
+    data.pos[0]=pos[0]; data.pos[1]=pos[1]; data.pos[2]=pos[2];
+    data.col[0]=col[0]; data.col[1]=col[1]; data.col[2]=col[2]; data.col[3]=col[3];
+    data.rad=rad;
+    data_.push_back(data);
+  }
+
+  void FastSphereRenderer::Add(const geom::Vec3& pos, const Color& col, float rad)
+  {
+    static VData data;
+    data.pos[0]=pos[0]; data.pos[1]=pos[1]; data.pos[2]=pos[2];
+    data.col[0]=col.Red(); data.col[1]=col.Green(); data.col[2]=col.Blue(); data.col[3]=col.Alpha();
+    data.rad=rad;
+    data_.push_back(data);
+  }
+
+  void FastSphereRenderer::RenderGL()
+  {
+#if OST_SHADER_SUPPORT_ENABLED
+    geom::Mat3 irot=geom::Transpose(Scene::Instance().GetTransform().GetRot());
+    geom::Vec3 cx=irot*geom::Vec3(1.0,0.0,0.0);
+    geom::Vec3 cy=irot*geom::Vec3(0.0,1.0,0.0);
+
+    uint write_normals = Shader::Instance().GetCurrentName()=="dumpnorm" ? 1 : 0;
+
+    Shader::Instance().PushProgram();
+    if(Shader::Instance().GetCurrentName()=="hemilight" ||
+       Shader::Instance().GetCurrentName()=="hf") {
+      Shader::Instance().Activate("fast_sphere_hf");
+    } else if(Shader::Instance().GetCurrentName()=="toon1") {
+      Shader::Instance().Activate("fast_sphere_toon1");
+    } else if(Shader::Instance().GetCurrentName()=="toon2") {
+      Shader::Instance().Activate("fast_sphere_toon2");
+    } else {
+      Shader::Instance().Activate("fast_sphere_phong");
+    }
+    Shader::Instance().UpdateState();
+    glUniform1i(glGetUniformLocation(Shader::Instance().GetCurrentProgram(),"write_normals"),write_normals);
+
+    glPushAttrib(GL_ALL_ATTRIB_BITS);
+    glDisable(GL_LIGHTING);
+    glDisable(GL_CULL_FACE);
+
+    GLdouble gl_mmat[16];
+    glGetDoublev(GL_MODELVIEW_MATRIX,gl_mmat);
+    GLdouble gl_pmat[16];
+    glGetDoublev(GL_PROJECTION_MATRIX,gl_pmat);
+
+    glBegin(GL_QUADS);
+    for(DataList::const_iterator it=data_.begin();it!=data_.end();++it) {
+      // eye z
+      float zz=gl_mmat[2]*it->pos[0]+gl_mmat[6]*it->pos[1]+gl_mmat[10]*it->pos[2]+gl_mmat[14];
+      // difference in z of sphere center and sphere pole
+      float scale=0.5*gl_pmat[14]*it->rad/(zz*(-it->rad+zz));
+      
+      // draw correctly scaled billboards
+      glColor3fv(it->col);
+      float px=it->rad*cx[0];
+      float py=it->rad*cx[1];
+      float pz=it->rad*cx[2];
+      float qx=it->rad*cy[0];
+      float qy=it->rad*cy[1];
+      float qz=it->rad*cy[2];
+      glTexCoord4f(0.0,0.0,-it->rad,scale);
+      glVertex3f(it->pos[0]-px-qx,it->pos[1]-py-qy,it->pos[2]-pz-qz);
+      glTexCoord4f(0.0,1.0,-it->rad,scale);
+      glVertex3f(it->pos[0]-px+qx,it->pos[1]-py+qy,it->pos[2]-pz+qz);
+      glTexCoord4f(1.0,1.0,-it->rad,scale);
+      glVertex3f(it->pos[0]+px+qx,it->pos[1]+py+qy,it->pos[2]+pz+qz);
+      glTexCoord4f(1.0,0.0,-it->rad,scale);
+      glVertex3f(it->pos[0]+px-qx,it->pos[1]+py-qy,it->pos[2]+pz-qz);
+    }
+    glEnd();
+
+    glPopAttrib();
+
+    Shader::Instance().PopProgram();
+    Shader::Instance().UpdateState();
+#endif
+  }
+
+
+}}} // ns
diff --git a/modules/geom/src/exception.hh b/modules/gfx/src/impl/fast_spheres.hh
similarity index 58%
rename from modules/geom/src/exception.hh
rename to modules/gfx/src/impl/fast_spheres.hh
index dded875655957f126b6dee28e0ff66f04c4168e4..2cef93d6561407b768586537851e5a5b83f7011a 100644
--- a/modules/geom/src/exception.hh
+++ b/modules/gfx/src/impl/fast_spheres.hh
@@ -16,22 +16,46 @@
 // along with this library; if not, write to the Free Software Foundation, Inc.,
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 //------------------------------------------------------------------------------
-#ifndef GEOM_EXCEPTION_HH
-#define GEOM_EXCEPTION_HH
+#ifndef OST_GFX_IMPL_FAST_SPHERES_HH
+#define OST_GFX_IMPL_FAST_SPHERES_HH
 
-#include <string>
-#include <ost/message.hh>
-#include "module_config.hh"
+#include <ost/geom/vec3.hh>
+#include <ost/gfx/color.hh>
 
-namespace geom {
+/*
+  Author: Ansgar Philippsen
+*/
 
-class DLLEXPORT_OST_GEOM GeomException: public Error
-{
-public:
-  GeomException(const String& m):
-    Error(m) {}
-  
-};
+#include <vector>
+
+namespace ost { namespace gfx { namespace impl {
+
+  class FastSphereRenderer {
+  public:
+    struct VData
+    {
+      float pos[3];
+      float col[4];
+      float rad;
+    };
+
+    typedef std::vector<VData> DataList;
+
+    FastSphereRenderer(size_t reserve=0);
+    FastSphereRenderer(const DataList&);
 
-}
+    void Clear();
+    void Add(float pos[3], float col[4], float rad);
+    void Add(const geom::Vec3& pos, const Color& col, float rad);
+
+    void RenderGL();
+
+    const DataList& Data() const {return data_;}
+
+  private:
+    DataList data_;
+  };
+  
+}}} // ns
 
+#endif
diff --git a/modules/gfx/src/impl/line_trace_renderer.cc b/modules/gfx/src/impl/line_trace_renderer.cc
index 8e650b9876e4ee1d065bde84962bd75a7377702f..bb6622ac84e6de1d5138c3810760975d2744dffb 100644
--- a/modules/gfx/src/impl/line_trace_renderer.cc
+++ b/modules/gfx/src/impl/line_trace_renderer.cc
@@ -92,7 +92,7 @@ void LineTraceRenderer::PrepareRendering(const BackboneTrace& trace_subset,
         if(nl.size()<1) continue;
         for(unsigned int i=0;i<nl.size();++i) {
           const NodeEntry& entry=nl[i];
-          if(sel_.FindAtom(entry.atom).IsValid()) {
+          if(sel_.ViewForHandle(entry.atom).IsValid()) {
             geom::Vec3 apos = entry.atom.GetPos();
             VertexID p0=va.Add(apos, geom::Vec3(),sel_clr);
             if(i>0) {
diff --git a/modules/gfx/src/impl/mesa_offscreen_buffer.cc b/modules/gfx/src/impl/mesa_offscreen_buffer.cc
new file mode 100644
index 0000000000000000000000000000000000000000..39ed73b5cfd090c4f451e0881364e9ba5778e05b
--- /dev/null
+++ b/modules/gfx/src/impl/mesa_offscreen_buffer.cc
@@ -0,0 +1,214 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+
+/*
+  Author: Ansgar Philippsen
+*/
+
+#include <ost/log.hh>
+#include <ost/gfx/offscreen_buffer.hh>
+#include <ost/gfx/scene.hh>
+
+namespace ost { namespace gfx {
+
+static XVisualInfo* get_visinfo(Display* dpy, bool use_accum)
+{
+  int buf[64];
+  unsigned int bufc=0;
+  int d[]={16,12,8,6,4,1};
+  int c[]={16,12,8,6,5,4,2,1};
+  int a[]={8,4};
+  XVisualInfo *vis=NULL;
+
+  buf[bufc++]=GLX_RGBA;
+  buf[bufc++]=GLX_DEPTH_SIZE;
+  unsigned int depthi=bufc++;
+  buf[bufc++]=GLX_RED_SIZE;
+  unsigned int redi=bufc++;
+  buf[bufc++]=GLX_BLUE_SIZE;
+  unsigned int bluei=bufc++;
+  buf[bufc++]=GLX_GREEN_SIZE;
+  unsigned int greeni=bufc++;
+  unsigned int accumi=0;
+  if(use_accum) {
+    buf[bufc++]=GLX_ACCUM_RED_SIZE;
+    accumi=bufc++;
+    buf[bufc++]=GLX_ACCUM_BLUE_SIZE;
+    bufc++;
+    buf[bufc++]=GLX_ACCUM_GREEN_SIZE;
+    bufc++;
+  }
+  buf[bufc++]=None;
+
+  for(unsigned int j=0;j<sizeof(c)/sizeof(int);j++) {
+    for(unsigned int i=0;i<sizeof(d)/sizeof(int);i++) {
+      buf[depthi]=d[i];
+      buf[redi]=c[j];
+      buf[bluei]=c[j];
+      buf[greeni]=c[j];
+      if(use_accum) {
+        for(unsigned int k=0;k<sizeof(a)/sizeof(int);k++) {
+          buf[accumi+0]=a[k];
+          buf[accumi+2]=a[k];
+          buf[accumi+4]=a[k];
+          vis=glXChooseVisual(dpy,DefaultScreen(dpy),buf);
+          if(vis) return vis;
+        }
+      } else {
+        vis=glXChooseVisual(dpy,DefaultScreen(dpy),buf);
+        if(vis) return vis;
+      }
+    }
+  }
+  return NULL;
+}
+
+static void create_error(const std::string& m)
+{
+  LOG_ERROR("error creating offscreen rendering context: " << m);
+}
+
+OffscreenBuffer::OffscreenBuffer(unsigned int width, unsigned int height, const OffscreenBufferFormat& f, bool shared):
+  width_(width), height_(height), valid_(false), active_(false)
+{
+  LOG_DEBUG("offscreen buffer: checking for DISPLAY");
+  if(getenv("DISPLAY")==NULL) {
+    create_error("missing DISPLAY environment variable");
+    return;
+  }
+
+  LOG_DEBUG("offscreen buffer: XOpenDisplay");
+  dpy_ = XOpenDisplay(getenv("DISPLAY"));
+  if(dpy_==NULL) {
+    create_error("XOpenDisplay() failed");
+    return;
+  }
+
+#if 0
+  std::vector<int> attrib_list;
+  attrib_list.push_back(GLX_RENDER_TYPE);
+  attrib_list.push_back(GLX_RGBA_BIT);
+  attrib_list.push_back(GLX_DRAWABLE_TYPE);
+  attrib_list.push_back(GLX_PIXMAP_BIT);
+  attrib_list.push_back(GLX_DOUBLEBUFFER);
+  attrib_list.push_back(False);
+  attrib_list.push_back(GLX_DEPTH_SIZE);
+  attrib_list.push_back(f.dbits);
+  attrib_list.push_back(GLX_RED_SIZE);
+  attrib_list.push_back(f.cbits);
+  attrib_list.push_back(GLX_GREEN_SIZE);
+  attrib_list.push_back(f.cbits);
+  attrib_list.push_back(GLX_BLUE_SIZE);
+  attrib_list.push_back(f.cbits);
+  attrib_list.push_back(GLX_ALPHA_SIZE);
+  attrib_list.push_back(f.abits);
+  attrib_list.push_back(0);
+
+  int nelem=0;
+  LOG_DEBUG("offscreen buffer: glXChooseFBConfig");
+  fbconfig_ =glXChooseFBConfig(dpy_,0,&attrib_list[0],&nelem);
+  if(fbconfig_==0 || nelem==0) {
+    create_error("glXChooseFBConfig failed");
+    return;
+  }
+
+#else
+
+  visinfo_ = get_visinfo(dpy_,true);
+  if(!visinfo_) {
+    create_error("get_visinfo() failed");
+    return;
+  }
+
+  context_=glXCreateContext(dpy_, visinfo_, 0, False);
+  if(!context_) {
+    create_error("glxCreateContext() failed");
+    return;
+  }
+
+  pm_=XCreatePixmap(dpy_,RootWindow(dpy_,DefaultScreen(dpy_)),
+                    width_,height_,visinfo_->depth);
+  if(!pm_) {
+    create_error("XCreatePixmap() failed");
+    return;
+  }
+
+  glxpm_=glXCreateGLXPixmap(dpy_, visinfo_, pm_);
+  if(!glxpm_) {
+    create_error("glXCreateGLXPixmap() failed");
+    return;
+  }
+  
+#endif
+
+  valid_=true;
+}
+    
+OffscreenBuffer::~OffscreenBuffer()
+{
+  if(valid_) {
+    glXDestroyGLXPixmap(dpy_,glxpm_);
+    XFreePixmap(dpy_,pm_);
+    glXDestroyContext(dpy_,context_);
+    valid_=false;
+  }
+}
+
+bool OffscreenBuffer::Resize(unsigned int width, unsigned int height)
+{
+  width_=width;
+  height_=height;
+
+  if(pm_) {
+    XFreePixmap(dpy_,pm_);
+  }
+  pm_=XCreatePixmap(dpy_,RootWindow(dpy_,DefaultScreen(dpy_)),
+                    width_,height_,visinfo_->depth);
+  if(!pm_) {
+    create_error("XCreatePixmap() failed");
+    return false;
+  }
+
+  if(glxpm_) {
+    glXDestroyGLXPixmap(dpy_,glxpm_);
+  }
+  glxpm_=glXCreateGLXPixmap(dpy_, visinfo_, pm_);
+  if(!glxpm_) {
+    create_error("glXCreateGLXPixmap() failed");
+    return false;
+  }
+
+  if(active_) {
+    MakeActive();
+  }
+
+  return true;
+}
+
+bool OffscreenBuffer::MakeActive()
+{
+  if(glXMakeCurrent(dpy_,glxpm_,context_)==False) {
+    LOG_ERROR("error activating offscreen rendering: glXMakeCurrent() failed");
+    return false;
+  }
+  active_=true;
+  return true;
+}
+
+}} // ns
diff --git a/modules/gfx/src/impl/mesa_offscreen_buffer.hh b/modules/gfx/src/impl/mesa_offscreen_buffer.hh
new file mode 100644
index 0000000000000000000000000000000000000000..5ed38b942e7ab7a8b5c41924d1f3f2fcb7a44e24
--- /dev/null
+++ b/modules/gfx/src/impl/mesa_offscreen_buffer.hh
@@ -0,0 +1,64 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+#ifndef OST_GFX_MESA_OFFSCREEN_BUFFER_HH
+#define OST_GFX_MESA_OFFSCREEN_BUFFER_HH
+
+#include <stack>
+#include <ost/gfx/glext_include.hh>
+#include <GL/glx.h>
+
+namespace ost { namespace gfx {
+
+/*
+  mesa implementation for offscreen buffers
+
+  Author: Ansgar Philippsen
+*/
+
+class OffscreenBuffer
+{
+public:
+  OffscreenBuffer(unsigned int width, unsigned int height, const OffscreenBufferFormat& f, bool shared=true);
+  ~OffscreenBuffer();
+
+  bool Resize(unsigned int w, unsigned int h);
+
+  bool MakeActive();
+
+  bool IsActive() {return active_;}
+
+  bool IsValid() {return valid_;}
+
+private:
+  int width_;
+  int height_;
+  bool valid_;
+  bool active_;
+
+  Display* dpy_;
+  XVisualInfo* visinfo_;
+  Pixmap pm_;
+  GLXPixmap glxpm_;
+  GLXContext context_;
+  GLXFBConfig* fbconfig_;
+};
+
+}} // ns
+
+#endif
diff --git a/modules/gfx/src/impl/scene_fx.cc b/modules/gfx/src/impl/scene_fx.cc
index f47e997ae081a06f7e95277c229a372c1e50cb32..8979d96441fc5367ec6cf223266654949683bee4 100644
--- a/modules/gfx/src/impl/scene_fx.cc
+++ b/modules/gfx/src/impl/scene_fx.cc
@@ -32,9 +32,10 @@ SceneFX::SceneFX():
   depth_dark_flag(false),
   depth_dark_factor(1.0),
   amb_occl_flag(false),
-  amb_occl_factor(1.0),
+  amb_occl_factor(0.5),
   amb_occl_mode(1),
   amb_occl_quality(1),
+  amb_occl_size(80.0),
   use_beacon(false),
   beacon(),
   scene_tex_id_(),
@@ -506,6 +507,7 @@ void SceneFX::prep_amb_occlusion()
   glUniform1i(glGetUniformLocation(cpr,"norm_map"),1);
   glUniform1i(glGetUniformLocation(cpr,"kernel"),2);
   glUniform1f(glGetUniformLocation(cpr,"step"),1.0/static_cast<float>(kernel_size_));
+  glUniform1f(glGetUniformLocation(cpr,"size"),amb_occl_size);
   glUniform2f(glGetUniformLocation(cpr,"i_vp"),1.0/static_cast<float>(width),1.0/static_cast<float>(height));
   glUniform1i(glGetUniformLocation(cpr,"mode"),amb_occl_mode);
   double pm[16];
diff --git a/modules/gfx/src/impl/scene_fx.hh b/modules/gfx/src/impl/scene_fx.hh
index 6e1f8b5968896141a58de57b1e79b163fe08634b..3b8e1fa388b67ea0c51be27676b437875c0e7aa6 100644
--- a/modules/gfx/src/impl/scene_fx.hh
+++ b/modules/gfx/src/impl/scene_fx.hh
@@ -65,6 +65,7 @@ public:
   float amb_occl_factor;
   uint amb_occl_mode;
   uint amb_occl_quality;
+  float amb_occl_size;
   bool use_beacon;
   Beacon beacon;
 
diff --git a/modules/gfx/src/impl/trace_renderer.cc b/modules/gfx/src/impl/trace_renderer.cc
index 49ee1c7ab258f9b51aa2432d019b78f809a3fd43..f901c77cdf7fa93424bcf6557e02557fd67377f3 100644
--- a/modules/gfx/src/impl/trace_renderer.cc
+++ b/modules/gfx/src/impl/trace_renderer.cc
@@ -64,7 +64,7 @@ void TraceRenderer::PrepareRendering(BackboneTrace& trace_subset,
         const NodeEntryList& nl=trace_subset.GetList(node_list);
         for(unsigned int i=0;i<nl.size();++i) {
           mol::AtomHandle ah=nl[i].atom;
-          if(sel_.FindAtom(ah).IsValid()) {
+          if(sel_.ViewForHandle(ah).IsValid()) {
             geom::Vec3 apos = ah.GetPos();
             va.AddSphere(SpherePrim(apos,
                                     options_->GetTubeRadius()+0.05,
diff --git a/modules/gfx/src/impl/trace_renderer_base.cc b/modules/gfx/src/impl/trace_renderer_base.cc
index b77b426913f5aaab3628371554d842e0d31932c6..1b4c47fe5320f3a118d8ffff66a26412640b9201 100644
--- a/modules/gfx/src/impl/trace_renderer_base.cc
+++ b/modules/gfx/src/impl/trace_renderer_base.cc
@@ -63,7 +63,7 @@ inline void apply_color_op(TraceRendererBase* rend, BackboneTrace& trace_subset,
     for (int node_list=0; node_list<trace_subset.GetListCount(); ++node_list) {
       NodeEntryList& nl=trace_subset.GetList(node_list);
       for (unsigned int i=0; i<nl.size();++i) {
-        if(view.FindAtom(nl[i].atom)){
+        if(view.ViewForHandle(nl[i].atom)){
           std::pair<bool,Color> clr =get_col.ColorOfAtom(nl[i].atom);
           if(clr.first) {
             set_node_entry_color(nl[i],mask,clr.second);
diff --git a/modules/gfx/src/map_iso.cc b/modules/gfx/src/map_iso.cc
index 8e685e524215dabd1ff12b2abe28965829c2d7b8..5dbd4d3907c57964a3b21c0d9183e3e1917ccf2e 100644
--- a/modules/gfx/src/map_iso.cc
+++ b/modules/gfx/src/map_iso.cc
@@ -93,13 +93,13 @@ MapIso::MapIso(const String& name, const img::MapHandle& mh,
   Rebuild();
 }
 
-geom::AlignedCuboid MapIso::GetBoundingBox() const
+geom::AlignedCuboid MapIso::GetBoundingBox(bool use_tf) const
 {
   if(recalc_bb_) {
     bb_=va_.GetBoundingBox();
     recalc_bb_=false;
   }
-  return bb_;
+  return use_tf ? transform_.Apply(bb_) : bb_;
 }
 
 geom::Vec3 MapIso::GetCenter() const
diff --git a/modules/gfx/src/map_iso.hh b/modules/gfx/src/map_iso.hh
index 814dfa756399c592ddf3df72d3173e5c958a73c6..bb47a129c1d0b04d223387dba693fc89031b12a0 100644
--- a/modules/gfx/src/map_iso.hh
+++ b/modules/gfx/src/map_iso.hh
@@ -54,7 +54,7 @@ public:
   MapIso(const String& name, const img::MapHandle& mh,float level, uint a=0);
 
   /// returns bounding box of iso-contour object, not overall map
-  virtual geom::AlignedCuboid GetBoundingBox() const;
+  virtual geom::AlignedCuboid GetBoundingBox(bool use_global=false) const;
 
   /// returns center of iso-contour object, not overall map
   virtual geom::Vec3 GetCenter() const;
diff --git a/modules/gfx/src/prim_list.cc b/modules/gfx/src/prim_list.cc
index a9debc0edd67dfa55d9a4057fb9ad0b77bdf4d2f..b531ba2796a597b8e8eb9d171c6a49d9d87a1e42 100644
--- a/modules/gfx/src/prim_list.cc
+++ b/modules/gfx/src/prim_list.cc
@@ -155,7 +155,7 @@ void PrimList::CustomPreRenderGL(bool flag)
 
 void PrimList::CustomRenderGL(RenderPass pass)
 {
-  if(pass==STANDARD_RENDER_PASS || pass==TRANSPARENT_RENDER_PASS) {
+  if(pass==STANDARD_RENDER_PASS) {
     va_.RenderGL();
     simple_va_.RenderGL();
     render_text();
diff --git a/modules/gfx/src/scene.cc b/modules/gfx/src/scene.cc
index 1bd5e460742f0a774bd7e7d46eba5974b4804dd7..fde6ad665d0ce3537bf9c97d5e3d26d1055bb62a 100644
--- a/modules/gfx/src/scene.cc
+++ b/modules/gfx/src/scene.cc
@@ -115,7 +115,7 @@ Scene::Scene():
   fog_color_(0.0,0.0,0.0,0.0),
   auto_autoslab_(true),
   do_autoslab_(true),
-  do_autoslab_fast_(true),
+  autoslab_mode_(0),
   offscreen_flag_(false),
   main_offscreen_buffer_(0),
   old_vp_(),
@@ -313,6 +313,24 @@ uint Scene::GetAmbientOcclusionQuality() const
 #endif
 }
 
+void Scene::SetAmbientOcclusionSize(float f)
+{
+#if OST_SHADER_SUPPORT_ENABLED
+  impl::SceneFX::Instance().amb_occl_size=f;
+  // the redraw routine will deal with the Shader
+  RequestRedraw();
+#endif
+}
+
+float Scene::GetAmbientOcclusionSize() const
+{
+#if OST_SHADER_SUPPORT_ENABLED
+  return impl::SceneFX::Instance().amb_occl_size;
+#else
+  return 1.0;
+#endif
+}
+
 void Scene::SetShadingMode(const std::string& smode)
 {
 #if OST_SHADER_SUPPORT_ENABLED
@@ -380,6 +398,7 @@ void Scene::InitGL(bool full)
     LOG_INFO(glGetString(GL_RENDERER) << ", openGL version " << glGetString(GL_VERSION)); 
 
 #if OST_SHADER_SUPPORT_ENABLED
+    LOG_INFO("shader version " << glGetString(GL_SHADING_LANGUAGE_VERSION));
     LOG_DEBUG("Scene: shader pre-gl");
     Shader::Instance().PreGLInit();
 #endif
@@ -628,11 +647,13 @@ void Scene::RenderText(const TextPrim& t)
   Shader::Instance().Activate("");
 #endif
 
-  glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);
+  glPushAttrib(GL_ALL_ATTRIB_BITS);
   glDisable(GL_NORMALIZE);
   glDisable(GL_CULL_FACE);
   glDisable(GL_LIGHTING);
   glDisable(GL_COLOR_MATERIAL);
+  glEnable(GL_ALPHA_TEST);
+  glAlphaFunc(GL_GREATER,0.5);
   glEnable(GL_TEXTURE_2D);
   glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
   glEnable(GL_BLEND);
@@ -843,7 +864,9 @@ void Scene::Add(const GfxNodeP& n, bool redraw)
     if(root_node_->GetChildCount()==0) {
       SetCenter(go->GetCenter());
     }
-    do_autoslab_=true;
+    if(auto_autoslab_) {
+      do_autoslab_=true;
+    }
   }
 
   root_node_->Add(n);
@@ -1201,18 +1224,11 @@ public:
   }
   void VisitObject(GfxObj* obj, const Stack& st) {
     if(obj->IsVisible()) {
-      geom::AlignedCuboid bb=obj->GetBoundingBox();
+      // use obj transform for BB calculation as well as provided global transform
+      geom::AlignedCuboid bb=tf.Apply(obj->GetBoundingBox(true));
       if(bb.GetVolume()>0.0) {
-        Vec3 t1 = tf.Apply(Vec3(bb.GetMin()[0],bb.GetMin()[1],bb.GetMin()[2]));
-        Vec3 t2 = tf.Apply(Vec3(bb.GetMin()[0],bb.GetMax()[1],bb.GetMin()[2]));
-        Vec3 t3 = tf.Apply(Vec3(bb.GetMax()[0],bb.GetMax()[1],bb.GetMin()[2]));
-        Vec3 t4 = tf.Apply(Vec3(bb.GetMax()[0],bb.GetMin()[1],bb.GetMin()[2]));
-        Vec3 t5 = tf.Apply(Vec3(bb.GetMin()[0],bb.GetMin()[1],bb.GetMax()[2]));
-        Vec3 t6 = tf.Apply(Vec3(bb.GetMin()[0],bb.GetMax()[1],bb.GetMax()[2]));
-        Vec3 t7 = tf.Apply(Vec3(bb.GetMax()[0],bb.GetMax()[1],bb.GetMax()[2]));
-        Vec3 t8 = tf.Apply(Vec3(bb.GetMax()[0],bb.GetMin()[1],bb.GetMax()[2]));
-        minc = Min(minc,Min(t1,Min(t2,Min(t3,Min(t4,Min(t5,Min(t6,Min(t7,t8))))))));
-        maxc = Max(maxc,Max(t1,Max(t2,Max(t3,Max(t4,Max(t5,Max(t6,Max(t7,t8))))))));
+        minc = Min(minc,bb.GetMin());
+        maxc = Max(maxc,bb.GetMax());
         valid=true;
       }
     }
@@ -1225,6 +1241,11 @@ public:
 
 }
 
+geom::AlignedCuboid Scene::GetBoundingBox(bool use_tf) const
+{
+  return GetBoundingBox(use_tf ? transform_ : mol::Transform());
+}
+
 geom::AlignedCuboid Scene::GetBoundingBox(const mol::Transform& tf) const
 {
   BBCalc bbcalc(Vec3(std::numeric_limits<float>::max(),
@@ -1380,7 +1401,7 @@ void Scene::SetStereoMode(unsigned int m)
     if(win_ && win_->HasStereo()) {
       stereo_mode_=1;
     } else {
-      LOG_INFO("Scene: No visual present for quad-buffered stereo");
+      LOG_WARNING("Scene: No visual present for quad-buffered stereo (run dng with --stereo)");
       stereo_mode_=0;
     }
   } else if(m==2) {
@@ -1706,16 +1727,30 @@ public:
 
 } // anon ns
 
+void Scene::Autoslab(bool fast)
+{
+  LOG_INFO("Autoslab(bool) is deprecated, use Autoslab() and SetAutoslabMode() instead");
+  do_autoslab_=true;
+  autoslab_mode_= fast ? 0 : 1;
+  RequestRedraw();
+}
+
 void Scene::Autoslab(bool fast, bool)
+{
+  LOG_INFO("Autoslab(bool,bool) is deprecated, use Autoslab() and SetAutoslabMode() instead");
+  Autoslab(fast);
+}
+
+void Scene::Autoslab()
 {
   do_autoslab_=true;
-  do_autoslab_fast_=fast;
   RequestRedraw();
 }
 
 void Scene::AutoslabMax()
 {
-  geom::AlignedCuboid bb =this->GetBoundingBox(transform_);
+  LOG_INFO("AutoslabMax() is deprecated, use Autoslab() and SetAutoslabMode() instead");
+  geom::AlignedCuboid bb =this->GetBoundingBox();
 
   if(bb.GetVolume()==0.0) {
     znear_=1;
@@ -1951,6 +1986,37 @@ void Scene::render_glow()
 #endif  
 }
 
+namespace {
+  geom::Mat4 frustum(float left, float right, float bot, float top, float near, float far) {
+    float rl=1.0/(right-left);
+    float tb=1.0/(top-bot);
+    float fn=1.0/(far-near);
+    float tn=2.0*near;
+    return geom::Mat4(tn*rl, 0.0f, (right+left)*rl, 0.0f,
+                      0.0f, tn*tb, (top+bot)*tb, 0.0f,
+                      0.0f, 0.0f, -(far+near)*fn, -tn*far*fn,
+                      0.0f, 0.0f, -1.0f, 0.0f);
+  }
+
+  geom::Mat4 translate(float x, float y, float z) {
+    return geom::Mat4(1.0f, 0.0f, 0.0f, x,
+                      0.0f, 1.0f, 0.0f, y,
+                      0.0f, 0.0f, 1.0f, z,
+                      0.0f, 0.0f, 0.0f, 1.0f);
+  }
+
+  geom::Mat4 rotate(float a, float x, float y, float z) {
+    float c=cos(a);
+    float d=1.0-c;
+    float s=sin(a);
+    geom::Vec3 v=geom::Normalize(geom::Vec3(x,y,z));
+    return geom::Mat4(v[0]*v[0]*d+c, v[0]*v[1]*d-v[2]*s, v[0]*v[2]*d+v[1]*s, 0.0f, 
+                      v[1]*v[0]*d+v[2]*s, v[1]*v[1]*d+c, v[1]*v[2]*d-v[0]*s, 0.0f, 
+                      v[0]*v[2]*d-v[1]*s, v[1]*v[2]*d+v[0]*s, v[2]*v[2]*d+c, 0.0f,
+                      0.0f, 0.0f, 0.0f, 1.0f);
+  }
+}
+
 void Scene::stereo_projection(int view)
 {
   if(!gl_init_) return;
@@ -1964,6 +2030,8 @@ void Scene::stereo_projection(int view)
   Real left = -top*aspect_ratio_;
   Real right = -left;
 
+  pmat_=frustum(left,right,bot,top,zn,zf);
+
   if(view!=0) {
     
     Real ff=(view<0 ? -1.0 : 1.0);
@@ -1971,19 +2039,17 @@ void Scene::stereo_projection(int view)
 
     if(stereo_alg_==1) {
       // Toe-in method, easy but wrong
-      glFrustum(left,right,bot,top,zn,zf);
       Real dist = -transform_.GetTrans()[2]+stereo_distance_;
-      glTranslated(0.0,0.0,-dist);
-      glRotated(-180.0/M_PI*atan(0.1*ff/iod),0.0,1.0,0.0);
-      glTranslated(0.0,0.0,dist);
+      pmat_=pmat_*translate(0.0,0.0,-dist)*rotate(-atan(0.1*ff/iod),0.0,1.0,0.0)*translate(0.0,0.0,dist);
+
     } else {
       // correct off-axis frustims
 
       Real fo=-transform_.GetTrans()[2]+stereo_distance_;
 
+#if 0
       // correction of near clipping plane to avoid extreme drifting
       // of left and right view
-#if 0
       if(iod*zn/fo<2.0) {
         zn=2.0*fo/iod;
         zf=std::max(zn+Real(0.2),zf);
@@ -1993,14 +2059,21 @@ void Scene::stereo_projection(int view)
       Real sd = -ff*0.5*iod*zn/fo;
       left+=sd;
       right+=sd;
-
-      glFrustum(left,right,bot,top,zn,zf);
-      glTranslated(-ff*iod*0.5,0.0,0.0);
+      pmat_=frustum(left,right,bot,top,zn,zf)*translate(-ff*iod*0.5,0.0,0.0);
     }
 
   } else { // view==0
-    // standard viewing frustum
-    glFrustum(left,right,bot,top,zn,zf);
+    // standard viewing frustum, no need to modify above call
+  }
+
+  glMultMatrix(geom::Transpose(pmat_).Data());
+
+  try {
+    ipmat_=geom::Invert(pmat_);
+  } catch (geom::GeomException& e) {
+    LOG_WARNING("caught GeomException in Scene::stereo_projection: " << e.what());
+    pmat_=geom::Mat4();
+    ipmat_=geom::Mat4();
   }
 }
 
@@ -2146,21 +2219,17 @@ void Scene::do_autoslab()
 {
   // skip autoslab if nothing to show yet
   if(root_node_->GetChildCount()==0) return;
-  if(do_autoslab_fast_) {
-    geom::AlignedCuboid bb =this->GetBoundingBox(transform_);
-    // necessary code duplication due to awkward slab limit impl
-    if(bb.GetVolume()==0.0) {
-      // skip if empty BB
-      return;
-    } else {
-      float mynear=-(bb.GetMax()[2])-1.0;
-      float myfar=-(bb.GetMin()[2])+1.0;
-      znear_=mynear;
-      zfar_=myfar;
-      set_near(mynear);
-      set_far(myfar);
+  float nnear=znear_;
+  float nfar=zfar_;
+  if(autoslab_mode_==0) {
+    // fast
+    geom::AlignedCuboid bb =this->GetBoundingBox();
+    if(bb.GetVolume()>0.0) {
+      nnear=-(bb.GetMax()[2])-1.0;
+      nfar=-(bb.GetMin()[2])+1.0;
     }
-  } else {
+  } else if (autoslab_mode_==1) {
+    // precise
     LimCalc limcalc;
     limcalc.transform=transform_;
     limcalc.minc = Vec3(std::numeric_limits<float>::max(),
@@ -2170,16 +2239,34 @@ void Scene::do_autoslab()
                               -std::numeric_limits<float>::max(),
                               -std::numeric_limits<float>::max());
     this->Apply(limcalc);
-    if(!limcalc.valid) {
-      return;
+    if(limcalc.valid) {
+      nnear=std::max(float(0.0), std::min(float(-limcalc.minc[2]),float(-limcalc.maxc[2])))-float(1.0);
+      nfar=std::max(float(-limcalc.minc[2]),float(-limcalc.maxc[2]))+float(1.0);
+    }
+  } else if(autoslab_mode_==2) {
+    // max
+    geom::AlignedCuboid bb =this->GetBoundingBox();
+
+    if(bb.GetVolume()>0.0) {
+      Vec3 cen = transform_.Apply(transform_.GetCenter());
+    
+      float bmax = std::max(std::abs(cen[0]-bb.GetMin()[0]),
+                            std::abs(cen[0]-bb.GetMax()[0]));
+      bmax = std::max(bmax,float(std::abs(cen[1]-bb.GetMin()[1])));
+      bmax = std::max(bmax,float(std::abs(cen[1]-bb.GetMax()[1])));
+      bmax = std::max(bmax,float(std::abs(cen[2]-bb.GetMin()[2])));
+      bmax = std::max(bmax,float(std::abs(cen[2]-bb.GetMax()[2])));
+      
+      nnear = -(cen[2]+bmax*1.5);
+      nfar = -(cen[2]-bmax*1.5);
     }
-    float mynear=std::max(float(0.0), std::min(float(-limcalc.minc[2]),float(-limcalc.maxc[2])))-float(1.0);
-    float myfar=std::max(float(-limcalc.minc[2]),float(-limcalc.maxc[2]))+float(1.0);
-    znear_=mynear;
-    zfar_=myfar;
-    set_near(mynear);
-    set_far(myfar);
   }
+
+  // necessary code duplication due to awkward slab limit impl
+  znear_=nnear;
+  zfar_=nfar;
+  set_near(nnear);
+  set_far(nfar);
   ResetProjection();
   RequestRedraw();
 }
diff --git a/modules/gfx/src/scene.hh b/modules/gfx/src/scene.hh
index a5868d0606581bff66c84b32b5d53f071bc44751..62630ced64dd95afd7b36957e2a97d6f35a3ba61 100644
--- a/modules/gfx/src/scene.hh
+++ b/modules/gfx/src/scene.hh
@@ -137,11 +137,18 @@ class DLLEXPORT_OST_GFX Scene {
   void SetAmbientOcclusionQuality(uint q);
   /// experimental feature
   uint GetAmbientOcclusionQuality() const;
+  /// experimental feature
+  void SetAmbientOcclusionSize(float f);
+  /// experimental feature
+  float GetAmbientOcclusionSize() const;
   
   /// \brief select shading mode
   /// one of fallback, basic, default, hf, toon1, toon2
   void SetShadingMode(const std::string& smode);
 
+  geom::Mat4 GetProjection() const {return pmat_;}
+  geom::Mat4 GetInvertedProjection() const {return ipmat_;}
+
   /// \name clipping planes, fog and field-of-view
   //@{
   /// \brief get near clipping plane
@@ -180,20 +187,48 @@ class DLLEXPORT_OST_GFX Scene {
   /// \brief convenciene function to set fog near and far offset
   void SetFogOffsets(float no, float fo);
   
-  /// \brief adjust near and far clipping plane to fit visible objects
-  // TODO: use mode aka fast, precise, max
-  void Autoslab(bool fast=false, bool redraw=true);
+  /// DEPRECATED, use Autoslab() and SetAutoslabMode(int)
+  void Autoslab(bool fast);
 
-  /// \brief adjust clipping planes to fix maximal extent of all objects
-  ///        even under rotation
-  // TODO: merge with Autoslab
+  /// DEPRECATED, use Autoslab() and SetAutoslabMode(int)
+  void Autoslab(bool fast, bool);
+
+  /// DEPRECATED, use SetAutoslabMode(2)
   void AutoslabMax();
 
-  /// \brief turn on automatic auto-slabbing (using the fast bounding box alg)
-  // TODO: more sophisticated mode, aka fast, precise, max
+  /*!
+    \brief adjust near and far clipping plane to fit visible objects
+
+    Use autoslab mode to calculate near and far clipping places; this
+    does not need to be called explicitely if AutoAutoslab is active.
+    Uses the mode set by \ref SetAutoslabMode
+  */
+  void Autoslab();
+
+  /*!
+    \brief set autoslab mode
+
+    0: fast (default), using only the bounding box
+    1: precise, using each graphical element (not implemented)
+    2: max, using maximal extent upon rotation
+  */
+  void SetAutoslabMode(int mode) {
+    autoslab_mode_=std::min(2,std::max(0,mode));
+  }
+
+  /// \brief return current autoslab mode
+  int GetAutoslabMode() const {
+    return autoslab_mode_;
+  }
+
+  /*!
+    \brief turn automatic autoslab'bing on or off for each scene update
+
+    the current autoslab mode is honored \ref SetAutoslabMode(int)
+  */
   void AutoAutoslab(bool f);
   
-  /// \brief get current state of automatic auto-slabbing
+  /// \brief get current state of automatic autoslab'bing
   bool GetAutoAutoslab() const { return auto_autoslab_; }
 
   //@}
@@ -319,7 +354,15 @@ class DLLEXPORT_OST_GFX Scene {
   /// \brief calculate unprojected point out of the scene
   geom::Vec3 UnProject(const geom::Vec3& v, bool ignore_vp=false) const;
 
-  /// \brief return bounding box of scene under given transform
+  /// \brief return bounding box of scene
+  /*!
+    the sole boolean parameter determines whether or not the scene 
+    transformation is applied to calculate the bounding box. Since in
+    most cases it should be used, the default value is true.
+  */
+  geom::AlignedCuboid GetBoundingBox(bool use_tf=true) const;
+
+  /// \brief return bounding box of with a given transform
   geom::AlignedCuboid GetBoundingBox(const mol::Transform& tf) const;
 
   /// \brief get full underlying transformation
@@ -478,6 +521,7 @@ private:
   float znear_,zfar_; // near and far clipping plane
   float fnear_,ffar_; // fog near and far offsets
 
+  geom::Mat4 pmat_,ipmat_; // projection and inverted projection matrix
   unsigned int vp_width_,vp_height_; // viewport
 
   SceneViewStack scene_view_stack_;
@@ -496,8 +540,9 @@ private:
   bool fix_cor_flag_;
   bool fog_flag_;
   Color fog_color_;
-  bool auto_autoslab_;
-  bool do_autoslab_,do_autoslab_fast_;
+  bool auto_autoslab_; // run autoslab on each scene update
+  bool do_autoslab_;   // run autoslab on next scene update
+  int autoslab_mode_;  // 0: fast, 1:precise, 2: max
 
   bool offscreen_flag_; // a simple indicator whether in offscreen mode or not
   OffscreenBuffer* main_offscreen_buffer_; // not null if a main offscreen buffer is present
diff --git a/modules/gfx/src/shader.cc b/modules/gfx/src/shader.cc
index c3b8b1d79ae42f3a58aeda6f1c8606a5bd8dc389..2a5e91ce25fa41c121ae12ecca5a6a2f08a82e68 100644
--- a/modules/gfx/src/shader.cc
+++ b/modules/gfx/src/shader.cc
@@ -47,11 +47,10 @@ Shader::Shader():
   valid_(false),
   current_program_(0),
   current_name_(""),
-  shader_code_map_(),
   shader_program_map_()
 {
   if(!OST_GL_VERSION_2_0) {
-    LOG_VERBOSE("OpenGL version smaller 2.0, deactivating shader functionality");
+    LOG_VERBOSE("OpenGL version less than 2.0, deactivating shader functionality");
   }
 }
 
@@ -59,7 +58,9 @@ Shader::Shader():
 void Shader::PreGLInit() 
 {
 #if !defined(__APPLE__)
-#if !defined(OST_MESA_SUPPORT_ENABLED)
+#if OST_MESA_SUPPORT_ENABLED
+  // skip glew initialization
+#else
   GLenum err = glewInit();
   if (GLEW_OK != err) {
     LOG_ERROR("glew failure: " << glewGetErrorString(err));
@@ -69,9 +70,12 @@ void Shader::PreGLInit()
 #endif
 }
 
-bool Shader::Compile(std::string shader_name, std::string shader_code, 
-                     GLenum shader_type, GLuint& shader_id)
+bool Shader::Compile(const std::string& shader_name, 
+                     const std::string& shader_code,
+                     GLenum shader_type,
+                     GLuint& shader_id)
 {
+  if(!OST_GL_VERSION_2_0) return false;
   shader_id = glCreateShader(shader_type);
   const char* tmp_ptr[] = {0};
   tmp_ptr[0]=shader_code.c_str();
@@ -81,30 +85,40 @@ bool Shader::Compile(std::string shader_name, std::string shader_code,
   GLint sh_compiled;
   glGetShaderiv(shader_id, GL_COMPILE_STATUS, &sh_compiled);
   if(sh_compiled==GL_TRUE) {
-    LOG_VERBOSE("shader [" << shader_name << "] successfully compiled (" << shader_id << ")");
+    LOG_DEBUG("shader [" << shader_name << "] successfully compiled (" << shader_id << ")");
   } else {
     GLint sh_log_length;
     glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH, &sh_log_length);
     std::vector<GLchar> sh_log(sh_log_length+1);
     glGetShaderInfoLog(shader_id, sh_log_length, NULL, &sh_log[0]);
-    LOG_ERROR("shader [" << shader_name << "] compilation failed:" << std::endl << String(&sh_log[0]));
+    LOG_WARNING("shader [" << shader_name << "] compilation failed:" << std::endl << String(&sh_log[0]));
     return false;
   }
   return true;
 }
 
-bool Shader::Link(const std::vector<GLuint>& code_list, std::string pr_name, GLuint& shader_pr)
+void Shader::Link(const std::string& pr_name, const std::string& vs_code, const std::string& fs_code)
 {
-  shader_pr = glCreateProgram();
-  for(std::vector<GLuint>::const_iterator it=code_list.begin();it!=code_list.end();++it) {
-    if(*it == 0) {
-      LOG_WARNING("skipping shader [" << pr_name << "] due to missing compiled code");
-      return false;
-    }
-    LOG_VERBOSE("attaching compiled shader id " << *it << " to " << shader_pr);
-    glAttachShader(shader_pr,*it);
+  if(!OST_GL_VERSION_2_0) return;
+  shader_program_map_[pr_name]=0;
+  GLuint shader_pr = glCreateProgram();
+
+  GLuint shader_id;
+  if(Compile(pr_name+" vs",vs_code,GL_VERTEX_SHADER,shader_id)) {
+    LOG_DEBUG("attaching compiled vertex shader id " << shader_id << " to " << shader_pr);
+    glAttachShader(shader_pr,shader_id);
+  } else {
+    LOG_WARNING("skipping [" << pr_name << "] due to error in vertex shader code");
+    return;
+  }
+  if(Compile(pr_name+" fs",fs_code,GL_FRAGMENT_SHADER,shader_id)) {
+    LOG_DEBUG("attaching compiled fragment shader id " << shader_id << " to " << shader_pr);
+    glAttachShader(shader_pr,shader_id);
+  } else {
+    LOG_WARNING("skipping [" << pr_name << "] due to error in fragment shader code");
+    return;
   }
-    
+
   glLinkProgram(shader_pr);
   GLint pr_linked;
   glGetProgramiv(shader_pr,GL_LINK_STATUS,&pr_linked);
@@ -115,38 +129,12 @@ bool Shader::Link(const std::vector<GLuint>& code_list, std::string pr_name, GLu
     glGetProgramiv(shader_pr, GL_INFO_LOG_LENGTH, &pr_log_length);
     std::vector<GLchar> pr_log(pr_log_length+1);
     glGetProgramInfoLog(shader_pr, pr_log_length, NULL, &pr_log[0]);
-    LOG_ERROR("shader [" << pr_name << "] linking failed:" << std::endl << String(&pr_log[0]));
-    return false;
+    LOG_WARNING("shader [" << pr_name << "] linking failed:" << std::endl << String(&pr_log[0]));
+    return;
   }
-  return true;
-}
-
-bool Shader::Add(const std::string& name, const std::string& vs_code, const std::string& fs_code)
-{
-  GLuint vs_id=0;
-  if(!Shader::Compile(name,vs_code,GL_VERTEX_SHADER,vs_id)) {
-    return false;
-  }
-  
-  GLuint fs_id=0;
-  if(!Shader::Compile(name,fs_code,GL_FRAGMENT_SHADER,fs_id)) {
-    return false;
-  }
-  
-  std::vector<GLuint> shader_program_list;
-  GLuint id;
-
-  shader_program_list.push_back(vs_id);
-  shader_program_list.push_back(fs_id);
-  if(!Shader::Link(shader_program_list,"hatch",id)) {
-    return false;
-  }
-
-  shader_program_map_[name]=id;
-  return true;
+  shader_program_map_[pr_name]=shader_pr;
 }
 
-
 void Shader::Setup() 
 {
   if(!OST_GL_VERSION_2_0) return;
@@ -166,17 +154,12 @@ void Shader::Setup()
     {"basic_fs.glsl", GL_FRAGMENT_SHADER},
     {"fraglight_vs.glsl", GL_VERTEX_SHADER},
     {"fraglight_fs.glsl", GL_FRAGMENT_SHADER},
-    {"basic_hf_vs.glsl", GL_VERTEX_SHADER},
     {"selfx_vs.glsl", GL_VERTEX_SHADER},
     {"selfx_fs.glsl", GL_FRAGMENT_SHADER},
-    {"toon_vs.glsl", GL_VERTEX_SHADER},
-    {"toon_fs.glsl", GL_FRAGMENT_SHADER},
-    {"toon2_fs.glsl", GL_FRAGMENT_SHADER},
     {"noop_vs.glsl", GL_VERTEX_SHADER},
     {"aaline_fs.glsl", GL_FRAGMENT_SHADER},
     {"iso_vs.glsl", GL_VERTEX_SHADER},
     {"iso_fs.glsl", GL_FRAGMENT_SHADER},
-    {"fast_sphere_vs.glsl", GL_VERTEX_SHADER},
     {"fast_sphere_fs.glsl", GL_FRAGMENT_SHADER},
     {"outline_vs.glsl", GL_VERTEX_SHADER},
     {"dumpnorm_vs.glsl", GL_VERTEX_SHADER},
@@ -188,18 +171,23 @@ void Shader::Setup()
     {"scenefx_fs.glsl", GL_FRAGMENT_SHADER},
     {"beacon_fs.glsl", GL_FRAGMENT_SHADER},
     {"screenblur4_fs.glsl", GL_FRAGMENT_SHADER},
-    {"test_tex_fs.glsl", GL_FRAGMENT_SHADER}
+    {"test_tex_fs.glsl", GL_FRAGMENT_SHADER},
+    {"material_phong.glsl", GL_FRAGMENT_SHADER},
+    {"material_hemi.glsl", GL_FRAGMENT_SHADER},
+    {"material_toon1.glsl", GL_FRAGMENT_SHADER},
+    {"material_toon2.glsl", GL_FRAGMENT_SHADER}
     //////////////////////////////////////////////////////////////////
   };
 
-  shader_code_map_.clear();
+  std::map<std::string, std::string> shader_code_map;
 
   for(unsigned int i=0;i<sizeof(shader_list)/sizeof(ShaderListEntry);++i) {
     String shader_name(shader_list[i].file);
     bf::path shader_file(shader_dir / shader_name);
 
     if(!bf::exists(shader_file)){
-      LOG_ERROR("not found: [" << shader_file.string() << "], cannot create shaders");
+      LOG_WARNING("shader file not found: [" << shader_file.string() << "]");
+      shader_code_map[shader_name]=std::string();
       continue;
     }
 
@@ -209,137 +197,95 @@ void Shader::Setup()
     while (std::getline(shader_file_stream,line)) {
       shader_code += line + "\n";
     }
-
-    GLuint shader_id;
-    if(Shader::Compile(shader_name,shader_code,shader_list[i].type,shader_id)) {
-      shader_code_map_[shader_name]=shader_id;
-    } else {
-      shader_code_map_[shader_name]=0;
-    }
+    shader_code_map[shader_name]=shader_code;
   }
 
   std::vector<GLuint> shader_program_list;
-  GLuint shader_program_id;
-  // basic shader
-  shader_program_list.push_back(shader_code_map_["basic_vs.glsl"]);
-  shader_program_list.push_back(shader_code_map_["basic_fs.glsl"]);
-  if(Shader::Link(shader_program_list,"basic",shader_program_id)) {
-    shader_program_map_["basic"]=shader_program_id;
-  }
-  // fraglight shader
-  shader_program_list.clear();
-  shader_program_list.push_back(shader_code_map_["fraglight_vs.glsl"]);
-  shader_program_list.push_back(shader_code_map_["fraglight_fs.glsl"]);
-  if(Shader::Link(shader_program_list,"fraglight",shader_program_id)) {
-    shader_program_map_["fraglight"]=shader_program_id;
-  }
-  // basic hemisphere lighting shader
-  shader_program_list.clear();
-  shader_program_list.push_back(shader_code_map_["basic_hf_vs.glsl"]);
-  shader_program_list.push_back(shader_code_map_["basic_fs.glsl"]);
-  if(Shader::Link(shader_program_list,"hemilight",shader_program_id)) {
-    shader_program_map_["hemilight"]=shader_program_id;
-    // alias
-    shader_program_map_["hf"]=shader_program_id;
-  }
-  // selfx shader
-  shader_program_list.clear();
-  shader_program_list.push_back(shader_code_map_["selfx_vs.glsl"]);
-  shader_program_list.push_back(shader_code_map_["selfx_fs.glsl"]);
-  if(Shader::Link(shader_program_list,"selfx",shader_program_id)) {
-    shader_program_map_["selfx"]=shader_program_id;
-  }
-  // toon shader
-  shader_program_list.clear();
-  shader_program_list.push_back(shader_code_map_["toon_vs.glsl"]);
-  shader_program_list.push_back(shader_code_map_["toon_fs.glsl"]);
-  if(Shader::Link(shader_program_list,"toon1",shader_program_id)) {
-    shader_program_map_["toon1"]=shader_program_id;
-  }
-  // toon2 shader
-  shader_program_list.clear();
-  shader_program_list.push_back(shader_code_map_["toon_vs.glsl"]);
-  shader_program_list.push_back(shader_code_map_["toon2_fs.glsl"]);
-  if(Shader::Link(shader_program_list,"toon2",shader_program_id)) {
-    shader_program_map_["toon2"]=shader_program_id;
-  }
-  // line shader
-  shader_program_list.clear();
-  shader_program_list.push_back(shader_code_map_["basic_vs.glsl"]);
-  shader_program_list.push_back(shader_code_map_["aaline_fs.glsl"]);
-  if(Shader::Link(shader_program_list,"aaline",shader_program_id)) {
-    shader_program_map_["aaline"]=shader_program_id;
-  }
-  // iso shader
-  shader_program_list.clear();
-  shader_program_list.push_back(shader_code_map_["iso_vs.glsl"]);
-  shader_program_list.push_back(shader_code_map_["iso_fs.glsl"]);
-  if(Shader::Link(shader_program_list,"iso",shader_program_id)) {
-    shader_program_map_["iso"]=shader_program_id;
-  }
-  // fast sphere shader
-  shader_program_list.clear();
-  shader_program_list.push_back(shader_code_map_["fast_sphere_vs.glsl"]);
-  shader_program_list.push_back(shader_code_map_["fast_sphere_fs.glsl"]);
-  if(Shader::Link(shader_program_list,"fast_sphere",shader_program_id)) {
-    shader_program_map_["fast_sphere"]=shader_program_id;
-  }
-  // outline shader
-  shader_program_list.clear();
-  shader_program_list.push_back(shader_code_map_["outline_vs.glsl"]);
-  shader_program_list.push_back(shader_code_map_["basic_fs.glsl"]);
-  if(Shader::Link(shader_program_list,"outline",shader_program_id)) {
-    shader_program_map_["outline"]=shader_program_id;
-  }
-  // dumpnorm shader
-  shader_program_list.clear();
-  shader_program_list.push_back(shader_code_map_["dumpnorm_vs.glsl"]);
-  shader_program_list.push_back(shader_code_map_["dumpnorm_fs.glsl"]);
-  if(Shader::Link(shader_program_list,"dumpnorm",shader_program_id)) {
-    shader_program_map_["dumpnorm"]=shader_program_id;
-  }
-  // convolute1 shader
-  shader_program_list.clear();
-  shader_program_list.push_back(shader_code_map_["quadpp_vs.glsl"]);
-  shader_program_list.push_back(shader_code_map_["convolute1_fs.glsl"]);
-  if(Shader::Link(shader_program_list,"convolute1",shader_program_id)) {
-    shader_program_map_["convolute1"]=shader_program_id;
-  }
-  // amboccl shader
-  shader_program_list.clear();
-  shader_program_list.push_back(shader_code_map_["quadpp_vs.glsl"]);
-  shader_program_list.push_back(shader_code_map_["amboccl_fs.glsl"]);
-  if(Shader::Link(shader_program_list,"amboccl",shader_program_id)) {
-    shader_program_map_["amboccl"]=shader_program_id;
-  }
-  // beacon shader
-  shader_program_list.clear();
-  shader_program_list.push_back(shader_code_map_["scenefx_vs.glsl"]);
-  shader_program_list.push_back(shader_code_map_["beacon_fs.glsl"]);
-  if(Shader::Link(shader_program_list,"beacon",shader_program_id)) {
-    shader_program_map_["beacon"]=shader_program_id;
-  }
-  // scenefx shader
-  shader_program_list.clear();
-  shader_program_list.push_back(shader_code_map_["scenefx_vs.glsl"]);
-  shader_program_list.push_back(shader_code_map_["scenefx_fs.glsl"]);
-  if(Shader::Link(shader_program_list,"scenefx",shader_program_id)) {
-    shader_program_map_["scenefx"]=shader_program_id;
-  }
-  // screen blur shader
-  shader_program_list.clear();
-  shader_program_list.push_back(shader_code_map_["quadpp_vs.glsl"]);
-  shader_program_list.push_back(shader_code_map_["screenblur4_fs.glsl"]);
-  if(Shader::Link(shader_program_list,"screenblur4",shader_program_id)) {
-    shader_program_map_["screenblur4"]=shader_program_id;
-  }
-  // test tex shader
-  shader_program_list.clear();
-  shader_program_list.push_back(shader_code_map_["fraglight_vs.glsl"]);
-  shader_program_list.push_back(shader_code_map_["test_tex_fs.glsl"]);
-  if(Shader::Link(shader_program_list,"test_tex",shader_program_id)) {
-    shader_program_map_["test_tex"]=shader_program_id;
-  }
+
+  Link("basic",
+       shader_code_map["basic_vs.glsl"],
+       shader_code_map["basic_fs.glsl"]);
+
+  // default frag lighting with phong lighting
+  Link("fraglight",
+       shader_code_map["fraglight_vs.glsl"],
+       shader_code_map["material_phong.glsl"]+
+       shader_code_map["fraglight_fs.glsl"]);
+
+  // hf lighting model
+  Link("hemilight",
+       shader_code_map["fraglight_vs.glsl"],
+       shader_code_map["material_hemi.glsl"]+
+       shader_code_map["fraglight_fs.glsl"]);
+  // alias
+  shader_program_map_["hf"]=shader_program_map_["hemilight"];
+
+  // toon 1 lighting model
+  Link("toon1",
+       shader_code_map["fraglight_vs.glsl"],
+       shader_code_map["material_toon1.glsl"]+
+       shader_code_map["fraglight_fs.glsl"]);
+
+  // toon 2 lighting model
+  Link("toon2",
+       shader_code_map["fraglight_vs.glsl"],
+       shader_code_map["material_toon2.glsl"]+
+       shader_code_map["fraglight_fs.glsl"]);
+
+  // raytraced sphere with different materials
+  Link("fast_sphere_phong",
+       shader_code_map["fraglight_vs.glsl"],
+       shader_code_map["material_phong.glsl"]+
+       shader_code_map["fast_sphere_fs.glsl"]);
+  Link("fast_sphere_hf",
+       shader_code_map["fraglight_vs.glsl"],
+       shader_code_map["material_hemi.glsl"]+
+       shader_code_map["fast_sphere_fs.glsl"]);
+  Link("fast_sphere_toon1",
+       shader_code_map["fraglight_vs.glsl"],
+       shader_code_map["material_toon1.glsl"]+
+       shader_code_map["fast_sphere_fs.glsl"]);
+  Link("fast_sphere_toon2",
+       shader_code_map["fraglight_vs.glsl"],
+       shader_code_map["material_toon2.glsl"]+
+       shader_code_map["fast_sphere_fs.glsl"]);
+
+  // selection fx
+  Link("selfx",
+       shader_code_map["selfx_vs.glsl"],
+       shader_code_map["selfx_fs.glsl"]);
+
+  Link("aaline",
+       shader_code_map["basic_vs.glsl"],
+       shader_code_map["aaline_fs.glsl"]);
+  Link("iso",
+       shader_code_map["iso_vs.glsl"],
+       shader_code_map["iso_fs.glsl"]);
+
+  Link("outline",
+       shader_code_map["outline_vs.glsl"],
+       shader_code_map["basic_fs.glsl"]);
+  Link("dumpnorm",
+       shader_code_map["dumpnorm_vs.glsl"],
+       shader_code_map["dumpnorm_fs.glsl"]);
+  Link("convolute1",
+       shader_code_map["quadpp_vs.glsl"],
+       shader_code_map["convolute1_fs.glsl"]);
+  Link("amboccl",
+       shader_code_map["quadpp_vs.glsl"],
+       shader_code_map["amboccl_fs.glsl"]);
+  Link("beacon",
+       shader_code_map["scenefx_vs.glsl"],
+       shader_code_map["beacon_fs.glsl"]);
+  Link("scenefx",
+       shader_code_map["scenefx_vs.glsl"],
+       shader_code_map["scenefx_fs.glsl"]);
+  Link("screenblur4",
+       shader_code_map["quadpp_vs.glsl"],
+       shader_code_map["screenblur4_fs.glsl"]);
+  Link("test_tex",
+       shader_code_map["fraglight_vs.glsl"],
+       shader_code_map["test_tex_fs.glsl"]);
 
   valid_=true;
 }
@@ -351,7 +297,7 @@ void Shader::Activate(const String& name)
   if(!name.empty()) {
     std::map<String, GLuint>::iterator it = shader_program_map_.find(name);
     if(it!=shader_program_map_.end()) {
-      LOG_VERBOSE("switching to shader [" << name << "]");
+      LOG_TRACE("switching to shader [" << name << "]");
       glUseProgram(it->second);
       current_program_=it->second;
       current_name_=name;
@@ -360,11 +306,11 @@ void Shader::Activate(const String& name)
       return;
 
     } else {
-      LOG_WARNING("shader program [" << name << "] not present");
+      LOG_TRACE("shader program [" << name << "] not present");
       return;
     }
   }
-  LOG_VERBOSE("switching to fixed pipeline");
+  LOG_TRACE("switching to fixed pipeline");
   glUseProgram(0);
   current_program_=0;
   current_name_="";
diff --git a/modules/gfx/src/shader.hh b/modules/gfx/src/shader.hh
index cd6e5a8bf6360fd43e32f6fe3293e3253cd294a9..149c8fc8668e773f651ffa0866fb27a7860f0b1d 100644
--- a/modules/gfx/src/shader.hh
+++ b/modules/gfx/src/shader.hh
@@ -40,13 +40,6 @@ public:
   // singleton implementation
   static Shader& Instance();
 
-  static bool Compile(std::string shader_name, std::string shader_code,
-                      GLenum shader_type, GLuint& shader_id);
-
-  static bool Link(const std::vector<GLuint>& code_list, std::string pr_name, GLuint& shader_pr);
-
-  bool Add(const std::string& name, const std::string& vs_code, const std::string& fs_code);
-
   void PreGLInit();
   void Setup();
   void Activate(const String& name);
@@ -61,6 +54,14 @@ public:
   void PopProgram();
 
   void UpdateState();
+
+  void Link(const std::string& pr_name, const std::string& vs_code, const std::string& fs_code);
+
+  static bool Compile(const std::string& shader_name, 
+                      const std::string& shader_code, 
+                      GLenum shader_type, 
+                      GLuint& shader_id);
+
 private:
   Shader();
 
@@ -70,7 +71,6 @@ private:
 
   std::stack<String> program_stack_;
 
-  std::map<String,GLuint> shader_code_map_;
   std::map<String,GLuint> shader_program_map_;
 };
 
diff --git a/modules/gfx/src/shader/amboccl_fs.glsl b/modules/gfx/src/shader/amboccl_fs.glsl
index 2d7819565c59158fc80272ce19bc059e7dfaeb9f..2c888d9e5a57d8dfbd983e9932035d98f30178be 100644
--- a/modules/gfx/src/shader/amboccl_fs.glsl
+++ b/modules/gfx/src/shader/amboccl_fs.glsl
@@ -2,6 +2,7 @@ uniform sampler2D depth_map;
 uniform sampler2D norm_map;
 uniform sampler1D kernel;
 uniform float step;
+uniform float size;
 uniform vec2 i_vp;
 uniform vec4 abcd;
 uniform int mode;
@@ -66,7 +67,7 @@ void main()
   float i;
   float sum=0.0;
   for(i=0.0;i<1.0;i+=step) {
-    vec2 nn=texture1D(kernel,i).xy*40.0-20.0;
+    vec2 nn=(texture1D(kernel,i).xy-0.5)*size;
     sum+=ao(nn,depth_p,norm_p,t_pos_p);
   }
   sum*=step;
diff --git a/modules/gfx/src/shader/basic_hf_vs.glsl b/modules/gfx/src/shader/basic_hf_vs.glsl
deleted file mode 100644
index 80324bf1d7a4764f719de0bff3f9dc5775b3f6e1..0000000000000000000000000000000000000000
--- a/modules/gfx/src/shader/basic_hf_vs.glsl
+++ /dev/null
@@ -1,43 +0,0 @@
-uniform bool lighting_flag;
-uniform bool two_sided;
-uniform bool occlusion_flag;
-
-void main()
-{    
-  vec4 ground_color=0.2*gl_Color;
-  vec4 sky_color=1.0*gl_Color;
-
-  if(occlusion_flag) {
-    ground_color.rgb*=gl_MultiTexCoord0.w;
-    sky_color.rgb*=gl_MultiTexCoord0.w;
-  }
-
-  gl_Position = ftransform();
-
-  // hemisphere lighting contribution
-  vec3 ec_pos = vec3(gl_ModelViewMatrix* gl_Vertex);
-  if(lighting_flag) {
-    vec3 normal = vec3(0,0,1);
-    if(dot(gl_Normal,gl_Normal)>0.001) {
-      normal = normalize(gl_NormalMatrix * gl_Normal);
-    }
-    vec3 l_dir  = normalize(gl_LightSource[0].position.xyz); // assume directional vector
-    float a  = 0.5+0.5*dot(normal,l_dir);
-    gl_FrontColor.rgb = mix(ground_color, sky_color, a).rgb;
-    gl_FrontColor.a = gl_Color.a;
-    if(two_sided) {
-      float a  = 0.5+0.5*dot(-normal,l_dir);
-      gl_BackColor.rgb = mix(ground_color, sky_color, a).rgb;
-      gl_BackColor.a = gl_Color.a;
-    } else {
-      gl_BackColor = gl_FrontColor;
-    }
-  } else {
-    gl_FrontColor = gl_Color;
-    gl_BackColor = gl_Color;
-  }
-
-  // for some reason, the fog and z coordinate are sign toggled...
-  gl_FogFragCoord = -ec_pos.z;
-}
-
diff --git a/modules/gfx/src/shader/basic_lf_fs.glsl b/modules/gfx/src/shader/basic_lf_fs.glsl
deleted file mode 100644
index 8b735383cd7ae141d8b3e58454c8047434931277..0000000000000000000000000000000000000000
--- a/modules/gfx/src/shader/basic_lf_fs.glsl
+++ /dev/null
@@ -1,13 +0,0 @@
-uniform bool fog_flag;
-
-void main()
-{
-  if(fog_flag) {
-    float fog = clamp((gl_Fog.end-gl_FogFragCoord) * gl_Fog.scale, 0.0, 1.0);
-    gl_FragColor.rgb = mix(gl_Fog.color.rgb, gl_Color.rgb, fog);
-    gl_FragColor.a = gl_Color.a;
-  } else {
-    gl_FragColor = gl_Color;
-  }
-}
-
diff --git a/modules/gfx/src/shader/basic_lf_vs.glsl b/modules/gfx/src/shader/basic_lf_vs.glsl
deleted file mode 100644
index bf9ca8e129192f40266b93ed1f277e725de7acdd..0000000000000000000000000000000000000000
--- a/modules/gfx/src/shader/basic_lf_vs.glsl
+++ /dev/null
@@ -1,87 +0,0 @@
-uniform bool lighting_flag;
-uniform bool two_sided_flag;
-uniform bool occlusion_flag;
-
-void DirectionalLight(in vec3 normal,
-                      in float shin,
-                      inout vec4 ambient,
-                      inout vec4 diffuse,
-                      inout vec4 specular)
-{
-  float n_vp = max(0.0, dot(normal, normalize(gl_LightSource[0].position.xyz)));
-  float pf = 0.0;
-  if(n_vp>0.0 && shin>0.0) {
-    float n_hv = max(0.0, dot(normal, normalize(gl_LightSource[0].halfVector.xyz)));
-    pf=pow(n_hv, shin);
-  }
-
-  ambient  += gl_LightSource[0].ambient;
-  diffuse  += gl_LightSource[0].diffuse * n_vp;
-  specular += gl_LightSource[0].specular * pf;
-}
-
-void CalcFrontAndBackColor(in vec3 normal)
-{
-  vec4 amb = vec4(0.0);
-  vec4 diff = vec4(0.0);
-  vec4 spec = vec4(0.0);
-
-  DirectionalLight(normal, gl_FrontMaterial.shininess, amb, diff, spec);
-
-  if(occlusion_flag) {
-    gl_FrontColor  = gl_FrontLightModelProduct.sceneColor  +
-                     (diff * gl_FrontMaterial.diffuse * gl_Color * gl_MultiTexCoord0.w) +
-                     (spec * gl_FrontMaterial.specular);
-
-  } else {
-    gl_FrontColor = gl_FrontLightModelProduct.sceneColor + 
-                    (amb  * gl_FrontMaterial.ambient * gl_Color) +
-                    (diff * gl_FrontMaterial.diffuse * gl_Color) +
-                    (spec * gl_FrontMaterial.specular);
-  }
-
-  if(two_sided_flag) {
-    amb=vec4(0.0);
-    diff=vec4(0.0);
-    spec=vec4(0.0);
-    
-    DirectionalLight(-normal, gl_BackMaterial.shininess, amb, diff, spec);
-    
-    if(occlusion_flag) {
-      gl_BackColor  = gl_FrontLightModelProduct.sceneColor  +
-                      (diff * gl_FrontMaterial.diffuse * gl_Color * gl_MultiTexCoord0.w) +
-                      (spec * gl_FrontMaterial.specular);
-
-    } else {
-      gl_BackColor = gl_BackLightModelProduct.sceneColor + 
-                     (amb  * gl_BackMaterial.ambient * gl_Color) +
-                     (diff * gl_BackMaterial.diffuse * gl_Color) +
-                     (spec * gl_BackMaterial.specular);
-    }
-
-  } else {
-    gl_BackColor = gl_FrontColor;
-  }
-
-  gl_FrontColor.a = gl_Color.a;
-  gl_BackColor.a = gl_Color.a;
-}
-
-void main()
-{    
-  // transformed position
-  gl_Position = ftransform();
-  vec4 ec_Pos = gl_ModelViewMatrix* gl_Vertex;
-
-  vec3 normal = normalize(gl_NormalMatrix * gl_Normal);
-  
-  if(lighting_flag) {
-    CalcFrontAndBackColor(normal);
-  } else {
-    gl_FrontColor = gl_Color;
-    gl_BackColor = gl_Color;
-  }
-  // for some reason, the fog and z coordinate are sign toggled...
-  gl_FogFragCoord = -ec_Pos.z;
-}
-
diff --git a/modules/gfx/src/shader/fast_sphere_fs.glsl b/modules/gfx/src/shader/fast_sphere_fs.glsl
index 66a8ca1605dca735386085e8b54908ebf10bb81f..72337e75038979e07e775aa337928a91bded56bf 100644
--- a/modules/gfx/src/shader/fast_sphere_fs.glsl
+++ b/modules/gfx/src/shader/fast_sphere_fs.glsl
@@ -2,28 +2,10 @@ uniform bool lighting_flag;
 uniform bool two_sided_flag;
 uniform bool fog_flag;
 uniform bool write_normals;
-uniform bool use_hemimodel;
 
 // gl_TexCoord[0] is from gl_MultiTexCoord0, which in turn
 // is custom crafted in the fast sphere prep routine
 
-// copy from basic_fl_vs !
-bool DirectionalLight(in vec3 normal,
-                      in float shin,
-                      inout vec4 ambient,
-                      inout vec4 diffuse,
-                      inout vec4 specular)
-{
-  float n_vp = max(0.0, dot(normal, normalize(vec3(gl_LightSource[0].position))));
-  float n_hv = max(0.0, dot(normal, vec3(gl_LightSource[0].halfVector)));
-  float pf = n_vp>0.0 ? pow(n_vp, shin) : 0.0;
-
-  ambient  += gl_LightSource[0].ambient;
-  diffuse  += gl_LightSource[0].diffuse*n_vp;
-  specular += gl_LightSource[0].specular * pf;
-  return true;
-}
-
 void main()
 {
   float xx = (gl_TexCoord[0].x-0.5)*2.0;
@@ -44,19 +26,9 @@ void main()
     return;
   }
 
-  vec4 color = vec4(0.0);
-  if(use_hemimodel) {
-    color = gl_Color;
-  } else {
-    vec4 amb = vec4(0.0);
-    vec4 diff = vec4(0.0);
-    vec4 spec = vec4(0.0);
-
-    DirectionalLight(normal, gl_FrontMaterial.shininess, amb, diff, spec);
-    color  = gl_FrontLightModelProduct.sceneColor  +
-             (amb  * gl_FrontMaterial.ambient * gl_Color) +
-             (diff * gl_FrontMaterial.diffuse * gl_Color) +
-             (spec * gl_FrontMaterial.specular);
+  vec4 color = gl_Color;
+  if(lighting_flag) {
+    color = light(normal,color,two_sided_flag);
   }
 
   if(fog_flag) {
@@ -65,5 +37,4 @@ void main()
   }
   gl_FragColor.rgb = color.rgb;
   gl_FragColor.a = 1.0;
-
 }
diff --git a/modules/gfx/src/shader/fast_sphere_vs.glsl b/modules/gfx/src/shader/fast_sphere_vs.glsl
deleted file mode 100644
index 5acd60562a4a59d500855e6a572f1ffe259ee439..0000000000000000000000000000000000000000
--- a/modules/gfx/src/shader/fast_sphere_vs.glsl
+++ /dev/null
@@ -1,33 +0,0 @@
-bool use_hemimodel;
-
-void main()
-{
-  // transformed position
-  gl_Position = ftransform();
-
-  vec4 ec_Pos = gl_ModelViewMatrix* gl_Vertex;
-  // for some reason, the fog and z coordinate are sign toggled...
-  gl_FogFragCoord = -ec_Pos.z;
-
-  gl_TexCoord[0]=gl_MultiTexCoord0;
-
-  if(use_hemimodel) {
-    vec4 ground_color=0.2*gl_Color;
-    vec4 sky_color=1.0*gl_Color;
-
-    // hemisphere lighting contribution
-    vec3 ec_pos = vec3(gl_ModelViewMatrix* gl_Vertex);
-    vec3 normal = vec3(0,0,1);
-    if(dot(gl_Normal,gl_Normal)>0.001) {
-      normal = normalize(gl_NormalMatrix * gl_Normal);
-    }
-    vec3 l_dir  = normalize(gl_LightSource[0].position.xyz); // assume directional vector
-    float a  = 0.5+0.5*dot(normal,l_dir);
-    gl_FrontColor.rgb = mix(ground_color, sky_color, a).rgb;
-    gl_FrontColor.a = gl_Color.a;
-    gl_BackColor = gl_FrontColor;
-  } else {
-    gl_FrontColor=gl_Color;
-    gl_BackColor=gl_Color;
-  }
-}
diff --git a/modules/gfx/src/shader/fraglight_fs.glsl b/modules/gfx/src/shader/fraglight_fs.glsl
index 76ff5dfaff9dbef8def110bee406ae67407fedac..9baa64b043a516b1293a66beaaf684e1627600b9 100644
--- a/modules/gfx/src/shader/fraglight_fs.glsl
+++ b/modules/gfx/src/shader/fraglight_fs.glsl
@@ -6,34 +6,8 @@ uniform int depth_mode;
 uniform bool tex_flag;
 uniform sampler2D tex_map;
 
-// copy from basic_fl_vs !
-bool DirectionalLight(in vec3 normal,
-                      in float shin,
-                      inout vec4 ambient,
-                      inout vec4 diffuse,
-                      inout vec4 specular,
-		      inout bool lflag)
-{
-  float n_vp = max(0.0, dot(normal, normalize(gl_LightSource[0].position.xyz)));
-
-  float pf = 0.0;
-  lflag = n_vp>0.0;
-  if(n_vp>0.0 && shin>0.0) {
-    float n_hv = max(0.0, dot(normal, normalize(gl_LightSource[0].halfVector.xyz)));
-    pf=pow(n_hv, shin);
-  }
-
-  ambient  += gl_LightSource[0].ambient;
-  diffuse  += gl_LightSource[0].diffuse * n_vp;
-  specular += gl_LightSource[0].specular * pf;
-
-  return true;
-}
-
 void main()
 {
-  bool lflag=false;
-
   vec4 color = gl_Color;
 
   if(tex_flag) {
@@ -42,26 +16,7 @@ void main()
 
   if(lighting_flag) {
     vec3 normal = normalize(gl_TexCoord[2].stp);
-
-    vec4 amb = vec4(0.0);
-    vec4 diff = vec4(0.0);
-    vec4 spec = vec4(0.0);
-
-    if(DirectionalLight(normal, gl_FrontMaterial.shininess, amb, diff, spec, lflag)) {
-
-      color  = gl_FrontLightModelProduct.sceneColor  +
-               (amb  * gl_FrontMaterial.ambient * color) +
-               (diff * gl_FrontMaterial.diffuse * color) +
-               (spec * gl_FrontMaterial.specular);
-    } else {
-      bool dummy;
-      DirectionalLight(-normal, gl_BackMaterial.shininess, amb, diff, spec, dummy);
-
-      color = gl_BackLightModelProduct.sceneColor  +
-              (amb  * gl_BackMaterial.ambient * color) +
-              (diff * gl_BackMaterial.diffuse * color) +
-              (spec * gl_BackMaterial.specular);
-    }
+    color=light(normal,color,two_sided_flag);
   }
 
   gl_FragColor = color;
diff --git a/modules/gfx/src/shader/fraglight_vs.glsl b/modules/gfx/src/shader/fraglight_vs.glsl
index 279016e1443fe061d0636f897d5d8b07829e5a9a..8a7ca2a3bc6e7fbac32e8420f867f5a833a876bc 100644
--- a/modules/gfx/src/shader/fraglight_vs.glsl
+++ b/modules/gfx/src/shader/fraglight_vs.glsl
@@ -3,13 +3,18 @@ void main()
   // transformed position
   gl_Position = ftransform();
 
+  // eye coordinate position
   vec4 ec_Pos = gl_ModelViewMatrix* gl_Vertex;
+
   // for some reason, the fog and z coordinate are sign toggled...
   gl_FogFragCoord = -ec_Pos.z;
 
-  // since a directional light is used, the position is not needed
-  // and only the normal is passed on
-  gl_TexCoord[2].stp=normalize(gl_NormalMatrix * gl_Normal);
+  // store fragment normal in tex coord 2
+  vec3 normal = vec3(0,0,1);
+  if(dot(gl_Normal,gl_Normal)>0.001) {
+    normal = normalize(gl_NormalMatrix * gl_Normal);
+  }
+  gl_TexCoord[2].stp=normal;
 
   // default tex coord
   gl_TexCoord[0] = gl_MultiTexCoord0;
diff --git a/modules/gfx/src/shader/material_hemi.glsl b/modules/gfx/src/shader/material_hemi.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..e9d223deaad03c709d20a8b42f5f0aaf9d3e1754
--- /dev/null
+++ b/modules/gfx/src/shader/material_hemi.glsl
@@ -0,0 +1,18 @@
+vec4 light(in vec3 normal,
+           in vec4 color,
+           in bool two_sided)
+{
+  vec4 ground_color=0.2*color;
+  vec4 sky_color=1.0*color;
+  
+  vec3 l_dir  = normalize(gl_LightSource[0].position.xyz); // assume directional vector
+  float a  = 0.5+0.5*dot(normal,l_dir);
+  color.rgb = mix(ground_color, sky_color, a).rgb;
+  bool backside = false;
+  if(two_sided && backside) {
+    float a  = 0.5+0.5*dot(-normal,l_dir);
+    color.rgb = mix(ground_color, sky_color, a).rgb;
+  }
+  return color;
+}
+
diff --git a/modules/gfx/src/shader/material_phong.glsl b/modules/gfx/src/shader/material_phong.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..ca5e097ce6b43bb119a9fa2d35610b334e8e59e0
--- /dev/null
+++ b/modules/gfx/src/shader/material_phong.glsl
@@ -0,0 +1,51 @@
+bool DirectionalLight(in vec3 normal,
+                      in int lightn,
+                      in float shin,
+                      inout vec4 ambient,
+                      inout vec4 diffuse,
+                      inout vec4 specular,
+                      inout bool lflag)
+{
+  float n_vp = max(0.0, dot(normal, normalize(gl_LightSource[lightn].position.xyz)));
+
+  float pf = 0.0;
+  lflag = n_vp>0.0;
+  if(n_vp>0.0 && shin>0.0) {
+    float n_hv = max(0.0, dot(normal, normalize(gl_LightSource[lightn].halfVector.xyz)));
+    pf=pow(n_hv, shin);
+  }
+
+  ambient  += gl_LightSource[lightn].ambient;
+  diffuse  += gl_LightSource[lightn].diffuse * n_vp;
+  specular += gl_LightSource[lightn].specular * pf;
+
+  return true;
+}
+
+
+vec4 light(in vec3 normal,
+           in vec4 color,
+           in bool two_sided)
+{
+  vec4 amb = vec4(0.0);
+  vec4 diff = vec4(0.0);
+  vec4 spec = vec4(0.0);
+  bool lflag=false;
+
+  DirectionalLight(normal, 0, gl_FrontMaterial.shininess, amb, diff, spec, lflag);
+
+  color  = gl_FrontLightModelProduct.sceneColor  +
+           (amb  * gl_FrontMaterial.ambient * color) +
+           (diff * gl_FrontMaterial.diffuse * color) +
+           (spec * gl_FrontMaterial.specular);
+
+/* TODO
+    DirectionalLight(-normal, 0, gl_BackMaterial.shininess, amb, diff, spec, dummy);
+    color = gl_BackLightModelProduct.sceneColor  +
+            (amb  * gl_BackMaterial.ambient * color) +
+            (diff * gl_BackMaterial.diffuse * color) +
+            (spec * gl_BackMaterial.specular);
+*/
+
+  return color;
+}
diff --git a/modules/gfx/src/shader/toon_fs.glsl b/modules/gfx/src/shader/material_toon1.glsl
similarity index 56%
rename from modules/gfx/src/shader/toon_fs.glsl
rename to modules/gfx/src/shader/material_toon1.glsl
index 4298ec02a44ff781e8dd87604a0d993403676d4e..2a21c7b140ec79ff28187550bb78461b1628f5ad 100644
--- a/modules/gfx/src/shader/toon_fs.glsl
+++ b/modules/gfx/src/shader/material_toon1.glsl
@@ -1,7 +1,3 @@
-uniform bool lighting_flag;
-uniform bool two_sided_flag;
-uniform bool fog_flag;
-
 void DirectionalLight(in vec3 normal,
                       inout vec4 ambient,
                       inout vec4 diffuse)
@@ -20,26 +16,26 @@ void DirectionalLight(in vec3 normal,
   diffuse  += gl_LightSource[0].diffuse*n_vp;
 }
 
-void main()
+vec4 light(in vec3 normal,
+           in vec4 color,
+           in bool two_sided)
 {
   vec4 amb = vec4(0.0);
   vec4 diff = vec4(0.0);
-  vec4 color = vec4(0.0);
-  vec3 normal = normalize(gl_TexCoord[2].stp);
+  vec4 color2 = vec4(0.0);
 
   DirectionalLight(normal, amb, diff);
 
-  color = (gl_FrontLightModelProduct.sceneColor + 
-           amb*gl_Color + diff*gl_Color);
+  color2 = (gl_FrontLightModelProduct.sceneColor + 
+           amb*color + diff*color);
 
-  if(two_sided_flag) {
+  if(two_sided) {
     amb=vec4(0.0);
     diff=vec4(0.0);
     DirectionalLight(-normal, amb, diff);
-    color += (gl_BackLightModelProduct.sceneColor + 
-              amb*gl_Color + diff*gl_Color);
+    color2 += (gl_BackLightModelProduct.sceneColor + 
+              amb*color + diff*color);
   }
 
-  gl_FragColor = clamp(color,0.0,1.0);
-  gl_FragColor.a = gl_Color.a;
+  return clamp(color2,0.0,1.0);
 }
diff --git a/modules/gfx/src/shader/toon2_fs.glsl b/modules/gfx/src/shader/material_toon2.glsl
similarity index 65%
rename from modules/gfx/src/shader/toon2_fs.glsl
rename to modules/gfx/src/shader/material_toon2.glsl
index ae12978378d24389a124313e3c6b70120ea81061..71332af6fb05a864cd5a9fcd3aef59f7d279d711 100644
--- a/modules/gfx/src/shader/toon2_fs.glsl
+++ b/modules/gfx/src/shader/material_toon2.glsl
@@ -1,8 +1,4 @@
-uniform bool lighting_flag;
-uniform bool two_sided_flag;
-uniform bool fog_flag;
-
-void DirectionalLight(in vec3 normal,
+bool DirectionalLight(in vec3 normal,
                       in float shin,
                       inout vec4 ambient,
                       inout vec4 diffuse,
@@ -25,30 +21,31 @@ void DirectionalLight(in vec3 normal,
   ambient  += gl_LightSource[0].ambient;
   diffuse  += gl_LightSource[0].diffuse*n_vp;
   spec     += gl_LightSource[0].specular*pf;
+  return true;
 }
 
-void main()
+vec4 light(in vec3 normal,
+           in vec4 color,
+           in bool two_sided)
 {
   vec4 amb = vec4(0.0);
   vec4 diff = vec4(0.0);
   vec4 spec = vec4(0.0);
-  vec4 color = vec4(0.0);
-  vec3 normal = normalize(gl_TexCoord[2].stp);
+  vec4 color2 = vec4(0.0);
 
   DirectionalLight(normal, gl_FrontMaterial.shininess, amb, diff, spec);
 
-  color = (gl_FrontLightModelProduct.sceneColor + 
-           amb*gl_Color + diff*gl_Color + spec*gl_Color);
+  color2 = (gl_FrontLightModelProduct.sceneColor + 
+           amb*color + diff*color + spec*color);
 
-  if(two_sided_flag) {
+  if(two_sided) {
     amb=vec4(0.0);
     diff=vec4(0.0);
     spec=vec4(0.0);
     DirectionalLight(-normal, gl_FrontMaterial.shininess, amb, diff, spec);
-    color += (gl_BackLightModelProduct.sceneColor + 
-              amb*gl_Color + diff*gl_Color + spec*gl_Color);
+    color2 += (gl_BackLightModelProduct.sceneColor + 
+              amb*color + diff*color + spec*color);
   }
 
-  gl_FragColor = clamp(color,0.0,1.0);
-  gl_FragColor.a = gl_Color.a;
+  return clamp(color2,0.0,1.0);
 }
diff --git a/modules/gfx/src/shader/toon_vs.glsl b/modules/gfx/src/shader/toon_vs.glsl
deleted file mode 100644
index c4624ebd72fa4899fd56e4acac138d6dcc70c2bc..0000000000000000000000000000000000000000
--- a/modules/gfx/src/shader/toon_vs.glsl
+++ /dev/null
@@ -1,19 +0,0 @@
-void main()
-{
-  // transformed position
-  gl_Position = ftransform();
-
-  vec4 ec_Pos = gl_ModelViewMatrix* gl_Vertex;
-  // for some reason, the fog and z coordinate are sign toggled...
-  gl_FogFragCoord = -ec_Pos.z;
-
-  vec3 normal = vec3(0,0,1);
-  if(dot(gl_Normal,gl_Normal)>0.001) {
-    normal = normalize(gl_NormalMatrix * gl_Normal);
-  }
-  // since a directional light is used, the position is not needed
-  gl_TexCoord[2].stp=normal;
-
-  gl_FrontColor=gl_Color;
-  gl_BackColor=gl_Color;
-}
diff --git a/modules/gfx/src/surface.cc b/modules/gfx/src/surface.cc
index 488375cf5b46ba29ee9e37c4c28f5368d750ad2c..0500e72b1482ae2ea32b7cd80fd3ee794a96e5bd 100644
--- a/modules/gfx/src/surface.cc
+++ b/modules/gfx/src/surface.cc
@@ -140,29 +140,32 @@ void Surface::Rebuild()
   recalc_bb_=true;
 }
 
-geom::AlignedCuboid Surface::GetBoundingBox() const
+geom::AlignedCuboid Surface::GetBoundingBox(bool use_tf) const
 {
-  static Vec3 minc,maxc;
+  static geom::AlignedCuboid bb;
   if(recalc_bb_) {
-    minc=Vec3(std::numeric_limits<float>::max(),
+    geom::Vec3 minc(std::numeric_limits<float>::max(),
                     std::numeric_limits<float>::max(),
                     std::numeric_limits<float>::max());
-    maxc=Vec3(-std::numeric_limits<float>::max(),
+    geom::Vec3 maxc(-std::numeric_limits<float>::max(),
                     -std::numeric_limits<float>::max(),
                     -std::numeric_limits<float>::max());
     
     std::vector<mol::SurfaceVertexID> svid_list = sh_.GetVertexIDList();
-    for(std::vector<mol::SurfaceVertexID>::const_iterator it=svid_list.begin();
-        it!=svid_list.end();++it) {
-      Vec3 pos = sh_.GetVertex(*it).position;
-      minc=Min(minc,pos);
-      maxc=Max(maxc,pos);
+    if(svid_list.size()>0) {
+      for(std::vector<mol::SurfaceVertexID>::const_iterator it=svid_list.begin();
+          it!=svid_list.end();++it) {
+        geom::Vec3 pos = sh_.GetVertex(*it).position;
+        minc=geom::Min(minc,pos);
+        maxc=geom::Max(maxc,pos);
+      }
+      minc-=geom::Vec3(1.0,1.0,1.0);
+      maxc+=geom::Vec3(1.0,1.0,1.0);
+      recalc_bb_=false;
+      bb=geom::AlignedCuboid(minc,maxc);
     }
-    minc-=Vec3(1.0,1.0,1.0);
-    maxc+=Vec3(1.0,1.0,1.0);
-    recalc_bb_=false;
   }
-  return geom::AlignedCuboid(minc,maxc);
+  return use_tf ? transform_.Apply(bb) : bb;
 }
 
 void Surface::CustomPreRenderGL(bool flag)
diff --git a/modules/gfx/src/surface.hh b/modules/gfx/src/surface.hh
index 740ae787fcb4c5f0550201ae36856c9d2ee07f4e..ff3ea292c6940cce040d5600aa370250f2868105 100644
--- a/modules/gfx/src/surface.hh
+++ b/modules/gfx/src/surface.hh
@@ -56,7 +56,7 @@ public:
 
   virtual void CustomRenderGL(RenderPass pass);
   virtual void CustomRenderPov(PovState& pov);
-  virtual geom::AlignedCuboid GetBoundingBox() const;
+  virtual geom::AlignedCuboid GetBoundingBox(bool use_global=false) const;
 
   mol::SurfaceHandle GetHandle() const;
 
diff --git a/modules/gfx/src/texture.cc b/modules/gfx/src/texture.cc
index 56ea7555360c05de3d4b2d0e36c5c446275f62b4..d708daa1a19629a5b4229d047c0fc6ed58b95d0b 100644
--- a/modules/gfx/src/texture.cc
+++ b/modules/gfx/src/texture.cc
@@ -1,4 +1,5 @@
 #include "texture.hh"
+#include "bitmap_io.hh"
 
 namespace ost { namespace gfx {
 
@@ -7,12 +8,12 @@ namespace ost { namespace gfx {
     d_()
   {
     if(!bm.data) return;
-    d_=boost::shared_array<Color>(new Color[w_*h_]);
+    d_=boost::shared_array<float>(new float[4*w_*h_]);
     static float f=1.0/255.0;
     for(GLint v=0;v<h_;++v) {
       for(GLint u=0;u<w_;++u) {
         int p=v*w_+u;
-        Color& c = d_[p];
+        float* c = &d_[p*4];
         if(bm.channels==1) {
           c[0]=f*static_cast<float>(bm.data[p]);
           c[1]=c[0];
diff --git a/modules/gfx/src/texture.hh b/modules/gfx/src/texture.hh
index b3a53dd2718786a747d3bd7fdf8f8fabf3c8c822..dd71404feb5f946a0965416546e7f57b42467fc3 100644
--- a/modules/gfx/src/texture.hh
+++ b/modules/gfx/src/texture.hh
@@ -29,11 +29,11 @@
 
 #include "module_config.hh"
 #include "glext_include.hh"
-#include "color.hh"
-#include "bitmap_io.hh"
 
 namespace ost { namespace gfx {
 
+class Bitmap;
+
 class Texture
 {
 public:
@@ -46,17 +46,14 @@ public:
   Texture(GLint w, GLint h):
     w_(w),
     h_(h),
-    d_(new Color[w*h])
+    d_(new float[4*w*h])
   {}
 
   Texture(const Bitmap& b);
 
   bool IsValid() const {return d_;}
 
-  Color& operator()(uint u, uint v) {return d_[v*w_+u];}
-  const Color& operator()(uint u, uint v) const {return d_[v*w_+u];}
-
-  float* data() {return d_[0];}
+  float* data() {return &d_[0];}
   
   GLint width() const {return w_;}
   GLint height() const {return h_;}
@@ -66,7 +63,7 @@ public:
 
 private:
   GLint w_,h_;
-  boost::shared_array<Color> d_;
+  boost::shared_array<float> d_;
 };
 
 }} // ns
diff --git a/modules/gfx/tests/CMakeLists.txt b/modules/gfx/tests/CMakeLists.txt
index b5bb03b71e8eb2dbf90fc8886f1cf34157e52670..273ab6809780c1c9cc2a7083b0c4beaac9ec7a29 100644
--- a/modules/gfx/tests/CMakeLists.txt
+++ b/modules/gfx/tests/CMakeLists.txt
@@ -1,6 +1,7 @@
 set(OST_GFX_UNIT_TESTS
   tests.cc
   test_gfx_node.cc
+  test_color.cc
   test_gfx.py
 )
 if (ENABLE_IMG)
diff --git a/modules/gfx/tests/test_color.cc b/modules/gfx/tests/test_color.cc
new file mode 100644
index 0000000000000000000000000000000000000000..88856fb1762fa5b636fc2f4ec449ea735865c62f
--- /dev/null
+++ b/modules/gfx/tests/test_color.cc
@@ -0,0 +1,194 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+
+/*
+  Author: Ansgar Philippsen
+*/
+
+#include <ost/gfx/color.hh>
+
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+#include <boost/test/floating_point_comparison.hpp>
+
+using boost::unit_test_framework::test_suite;
+
+using namespace ost;
+using namespace ost::gfx;
+
+static const float tolerance=1e-4;
+
+namespace {
+  bool compare_colors(const Color& c1, const Color& c2, float tol=1e-6) {
+    return std::fabs(c1.GetRed()-c2.GetRed()<tol) &&
+      std::fabs(c1.GetGreen()-c2.GetGreen()<tol) &&
+      std::fabs(c1.GetBlue()-c2.GetBlue()<tol) &&
+      std::fabs(c1.GetAlpha()-c2.GetAlpha()<tol) &&
+      std::fabs(c1.GetHue()-c2.GetHue()<tol) &&
+      std::fabs(c1.GetSat()-c2.GetSat()<tol) &&
+      std::fabs(c1.GetVal()-c2.GetVal()<tol);
+  }
+}
+
+#define FIXED_BOOST_WARN_CLOSE(F1,F2,F3) BOOST_WARN_CLOSE(static_cast<float>(F1), static_cast<float>(F2), static_cast<float>(F3))
+
+BOOST_AUTO_TEST_SUITE(gfx)
+
+BOOST_AUTO_TEST_CASE(default_color)
+{
+  Color c;
+  FIXED_BOOST_WARN_CLOSE(c.GetRed(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetGreen(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetBlue(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetAlpha(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetHue(),0.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetSat(),0.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetVal(),1.0f,tolerance);
+}
+
+BOOST_AUTO_TEST_CASE(set_rgb)
+{
+  Color c;
+  c = RGB(1.0f,0.0f,0.0f); // red
+  FIXED_BOOST_WARN_CLOSE(c.GetAlpha(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetRed(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetGreen(),0.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetBlue(),0.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetHue(),0.0f/6.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetSat(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetVal(),1.0f,tolerance);
+  c = RGB(1.0f,1.0f,0.0f); // yellow
+  FIXED_BOOST_WARN_CLOSE(c.GetRed(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetGreen(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetBlue(),0.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetHue(),1.0f/6.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetSat(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetVal(),1.0f,tolerance);
+  c = RGB(0.0f,1.0f,0.0f); // green
+  FIXED_BOOST_WARN_CLOSE(c.GetRed(),0.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetGreen(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetBlue(),0.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetHue(),2.0f/6.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetSat(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetVal(),1.0f,tolerance);
+  c = RGB(0.0f,1.0f,1.0f); // cyan
+  FIXED_BOOST_WARN_CLOSE(c.GetRed(),0.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetGreen(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetBlue(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetHue(),3.0f/6.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetSat(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetVal(),1.0f,tolerance);
+  c = RGB(0.0f,0.0f,1.0f); // blue
+  FIXED_BOOST_WARN_CLOSE(c.GetRed(),0.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetGreen(),0.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetBlue(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetHue(),4.0f/6.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetSat(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetVal(),1.0f,tolerance);
+  c = RGB(1.0f,0.0f,1.0f); // purple
+  FIXED_BOOST_WARN_CLOSE(c.GetRed(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetGreen(),0.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetBlue(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetHue(),5.0f/6.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetSat(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetVal(),1.0f,tolerance);
+}
+
+BOOST_AUTO_TEST_CASE(set_hsv)
+{
+  Color c;
+  c = HSV(0.0f/6.0,1.0f,1.0f); // red
+  FIXED_BOOST_WARN_CLOSE(c.GetAlpha(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetRed(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetGreen(),0.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetBlue(),0.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetHue(),0.0f/6.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetSat(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetVal(),1.0f,tolerance);
+  c = HSV(0.0f/6.0,0.5,1.0f); // light red
+  FIXED_BOOST_WARN_CLOSE(c.GetRed(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetGreen(),0.5f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetBlue(),0.5f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetHue(),0.0f/6.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetSat(),0.5f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetVal(),1.0f,tolerance);
+  c = HSV(1.0f/6.0,1.0f,1.0f); // yellow
+  FIXED_BOOST_WARN_CLOSE(c.GetRed(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetGreen(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetBlue(),0.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetHue(),1.0f/6.0,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetSat(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetVal(),1.0f,tolerance);
+  c = HSV(2.0/6.0,1.0f,1.0f); // green
+  FIXED_BOOST_WARN_CLOSE(c.GetRed(),0.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetGreen(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetBlue(),0.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetHue(),2.0f/6.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetSat(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetVal(),1.0f,tolerance);
+  c = HSV(2.0/6.0,0.5,1.0f); // light green
+  FIXED_BOOST_WARN_CLOSE(c.GetRed(),0.5f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetGreen(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetBlue(),0.5f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetHue(),2.0f/6.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetSat(),0.5f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetVal(),1.0f,tolerance);
+  c = HSV(3.0/6.0,1.0f,1.0f); // cyan
+  FIXED_BOOST_WARN_CLOSE(c.GetRed(),0.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetGreen(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetBlue(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetHue(),3.0f/6.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetSat(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetVal(),1.0f,tolerance);
+  c = HSV(4.0/6.0,1.0f,1.0f); // blue
+  FIXED_BOOST_WARN_CLOSE(c.GetRed(),0.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetGreen(),0.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetBlue(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetHue(),4.0f/6.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetSat(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetVal(),1.0f,tolerance);
+  c = HSV(4.0/6.0,0.5,1.0f); // light blue
+  FIXED_BOOST_WARN_CLOSE(c.GetRed(),0.5f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetGreen(),0.5f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetBlue(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetHue(),4.0f/6.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetSat(),0.5f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetVal(),1.0f,tolerance);
+  c = HSV(5.0/6.0,1.0f,1.0f); // purple
+  FIXED_BOOST_WARN_CLOSE(c.GetRed(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetGreen(),0.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetBlue(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetHue(),5.0f/6.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetSat(),1.0f,tolerance);
+  FIXED_BOOST_WARN_CLOSE(c.GetVal(),1.0f,tolerance);
+}
+
+BOOST_AUTO_TEST_CASE(set_char)
+{
+  BOOST_WARN(compare_colors(RGBb(255,0,0),RGB(1.0f,0.0f,0.0f)));
+  BOOST_WARN(compare_colors(RGBAb(0,127,0,127),RGBA(0.0f,0.5f,0.0f,0.5f)));
+}
+
+BOOST_AUTO_TEST_CASE(set_int)
+{
+  BOOST_WARN(compare_colors(RGBi(65535,65535,0),RGB(1.0f,1.0f,0.0f)));
+  BOOST_WARN(compare_colors(RGBAi(0,32767,0,32767),RGBA(0.0f,0.5f,0.0f,0.5f)));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/modules/gfx/tests/test_entity.py b/modules/gfx/tests/test_entity.py
new file mode 100644
index 0000000000000000000000000000000000000000..7b5056223cb18adb9e5935fecf0d6571dd2bbab7
--- /dev/null
+++ b/modules/gfx/tests/test_entity.py
@@ -0,0 +1,61 @@
+eh=io.LoadPDB("1crn",remote=True)
+
+scene.Add(gfx.Entity("simple_default",gfx.SIMPLE,eh))
+scene.Add(gfx.Entity("simple_mod",gfx.SIMPLE,eh))
+scene["simple_mod"].ColorBy("abfac",gfx.Gradient([gfx.BLUE,gfx.RED]))
+scene["simple_mod"].simple_options.line_width=3.5
+scene["simple_mod"].simple_options.aa_lines=True
+
+scene.Add(gfx.Entity("custom_default",gfx.CUSTOM,eh))
+scene.Add(gfx.Entity("custom_mod",gfx.CUSTOM,eh))
+scene["custom_mod"].custom_options.bond_rad=0.45
+scene["custom_mod"].custom_options.sphere_rad=0.55
+scene["custom_mod"].SetColor(gfx.ORANGE,"ele=C")
+
+scene.Add(gfx.Entity("cpk_default", gfx.CPK,eh))
+scene["cpk_default"].cpk_options.sphere_detail=2 # should have no influence
+scene.Add(gfx.Entity("cpk_mod", gfx.CPK,eh))
+scene["cpk_mod"].cpk_options.sphere_mode=0
+scene["cpk_mod"].cpk_options.sphere_detail=2
+
+scene.Add(gfx.Entity("ltrace_default", gfx.LINE_TRACE,eh))
+scene.Add(gfx.Entity("ltrace_mod", gfx.LINE_TRACE,eh))
+scene["ltrace_mod"].ColorBy("rnum",gfx.Gradient([gfx.PURPLE,gfx.YELLOW,gfx.CYAN]))
+scene["ltrace_mod"].line_trace_options.aa_lines=True
+scene["ltrace_mod"].line_trace_options.line_width=3.5
+
+scene.Add(gfx.Entity("trace_default", gfx.TRACE,eh))
+scene.Add(gfx.Entity("trace_mod", gfx.TRACE,eh))
+scene["trace_mod"].ColorBy("rnum",gfx.Gradient([gfx.RED,gfx.GREEN,gfx.BLUE]))
+scene["trace_mod"].trace_options.arc_detail=6
+scene["trace_mod"].trace_options.tube_radius=1.3
+
+scene.Add(gfx.Entity("tube_default", gfx.TUBE,eh))
+eh2=eh.Copy()
+scene.Add(gfx.Entity("tube_mod", gfx.TUBE,eh2))
+bfmin=1e-6
+bfmax=-1e-6
+for a in eh2.Select("peptide=1 and aname=CA").atoms:
+  bfmin=min(bfmin,a.b_factor)
+  bfmax=max(bfmax,a.b_factor)
+for a in eh2.Select("peptide=1 and aname=CA").atoms:
+  a.handle.SetFloatProp("trace_rad",5.0*min(1.0,max(0.0,(a.b_factor-bfmin)/(bfmax-bfmin)))+0.3)
+scene["tube_mod"].ColorBy("rbfac",gfx.Gradient([gfx.BLUE,gfx.RED]))
+scene["tube_mod"].tube_options.spline_detail=8
+scene["tube_mod"].tube_options.arc_detail=8
+scene["trace_mod"].tube_options.tube_radius=1.0
+
+scene.Add(gfx.Entity("hsc_default", gfx.HSC,eh))
+scene.Add(gfx.Entity("hsc_mod", gfx.HSC,eh))
+scene["hsc_mod"].SetColor(gfx.PURPLE,"rtype=H")
+scene["hsc_mod"].SetColor(gfx.ORANGE,"rtype=E")
+scene["hsc_mod"].cartoon_options.helix_width=1.3
+scene["hsc_mod"].cartoon_options.helix_thickness=0.6
+scene["hsc_mod"].cartoon_options.strand_width=1.6
+scene["hsc_mod"].cartoon_options.strand_thickness=0.4
+scene["hsc_mod"].cartoon_options.tube_radius=0.5
+
+
+
+scene.Match("*").Hide()
+
diff --git a/modules/gui/pymod/CMakeLists.txt b/modules/gui/pymod/CMakeLists.txt
index 9a623a9a1877f68e6aa7ff1f39229489acee84bd..cf4ea93cd6db34bc3764c2132c0836266f2ddc9c 100644
--- a/modules/gui/pymod/CMakeLists.txt
+++ b/modules/gui/pymod/CMakeLists.txt
@@ -85,6 +85,7 @@ set(OST_GUI_PYMOD_MODULES
   init_splash.py
   traj.py
   helpwidget.py
+  table.py
 )
 
 set(OST_GUI_PYMOD_DNG_MODULES
diff --git a/modules/gui/pymod/__init__.py b/modules/gui/pymod/__init__.py
index a63b91820c28a4eeb9b03a7c0eb916b99fcc84b9..7848916906ee02d47ef8d685c1551051a4e7fd21 100644
--- a/modules/gui/pymod/__init__.py
+++ b/modules/gui/pymod/__init__.py
@@ -59,8 +59,7 @@ def PickColor(default=gfx.WHITE):
   qt_color=dialog.getColor(qt_color)
   if not qt_color.isValid():
     return None
-  return gfx.Color(qt_color.red()/256.0, qt_color.green()/256.0,
-                   qt_color.blue()/256.0)
+  return gfx.RGBb(qt_color.red(), qt_color.green(),qt_color.blue())
                    
 def GetMenu(menu_name, create=False):
   persp=GostyApp.Instance().perspective
diff --git a/modules/gui/pymod/dng/superpositiondialog.py b/modules/gui/pymod/dng/superpositiondialog.py
index fa6ae50fbb1ae77a96b3eae862efc4ec8feef337..9ad8bc22fd0cf0d30c290f864367e4e015e2627f 100644
--- a/modules/gui/pymod/dng/superpositiondialog.py
+++ b/modules/gui/pymod/dng/superpositiondialog.py
@@ -60,7 +60,7 @@ class ChainComboBox(QComboBox):
 
   def _HighlightChain(self, chain):
     if str(chain) != 'All':
-      self.gfx.SetSelection(self.entity.Select('cname=' + str(chain)))
+      self.gfx.SetSelection(self.entity.Select('cname="%s"' % str(chain)))
     else:
       self.gfx.SetSelection(self.entity.Select(''))
 
@@ -69,7 +69,7 @@ class ChainComboBox(QComboBox):
       return mol.EntityHandle()
     elif self.currentText() == self.all_chains:
       return self.entity
-    return self.entity.Select('cname=' + str(self.currentText()))
+    return self.entity.Select('cname="%s"' % str(self.currentText()))
 
   def _SetSelectedChain(self, chain):
     if hasattr(chain, 'name'):
diff --git a/modules/gui/pymod/dng/termuse.py b/modules/gui/pymod/dng/termuse.py
index 8f90c4c47f785f571771bc9a5e09c913f87b71e0..a1fed90ddf2c9fdbc7bc74c2e172ebd9edcc43c8 100644
--- a/modules/gui/pymod/dng/termuse.py
+++ b/modules/gui/pymod/dng/termuse.py
@@ -45,7 +45,7 @@ class TerminalUsageDialog(QDialog):
     return str(self.path_combo.currentText())
 
 def _CreateLinks(bin_dir, sel_dir):
-  for bin in ('ost', 'dng',):
+  for bin in ('ost', 'dng','lddt', 'chemdict_tool'):
     if os.path.exists(os.path.join(sel_dir, bin)):
       os.unlink(os.path.join(sel_dir, bin))
     os.system('ln -s "%s" "%s"' % (os.path.join(bin_dir, bin), 
@@ -63,7 +63,7 @@ def InstallTerminalPrograms():
     if not os.access(sel_path, os.W_OK):
       admin_rights=AdminRights()
       if admin_rights.Acquire():
-        for bin in ('ost', 'dng'):
+        for bin in ('ost', 'dng', 'lddt', 'chemdict_tool'):
           admin_rights.CreateLink(os.path.join(bin_dir, bin), 
                                   os.path.join(sel_path, bin))
       admin_rights.Release()
diff --git a/modules/gui/pymod/export_input.cc b/modules/gui/pymod/export_input.cc
index fcda612aa0eebfff8447f3105ad17ca94303ae3e..8906e944b9821b8720b003039cfb3282b572a9e9 100644
--- a/modules/gui/pymod/export_input.cc
+++ b/modules/gui/pymod/export_input.cc
@@ -32,7 +32,12 @@ object spnav_get_instance()
 {
   static object sip_module=import("sip");
   static object pyqt4_module=import("PyQt4.QtCore");
-  return ost::gui::get_py_qobject<SpnavInput>(SpnavInput::Instance());
+  SpnavInput* si = SpnavInput::Instance();
+  if(si->isValid()) {
+    return ost::gui::get_py_qobject<SpnavInput>(si);
+  } else {
+    return object();
+  }
 }
 
 }
diff --git a/modules/gui/pymod/init_spacenav.py b/modules/gui/pymod/init_spacenav.py
index df8bf383b3efa580d385196d57a6a515a38fe2a5..c05a59a2dbee5d372870ec12db1090bb485c5e46 100644
--- a/modules/gui/pymod/init_spacenav.py
+++ b/modules/gui/pymod/init_spacenav.py
@@ -1,5 +1,8 @@
+import math,traceback
+
 from PyQt4 import QtCore
 
+import ost
 from ost import gfx, gui
 
 class SpacenavControl(QtCore.QObject):
@@ -11,33 +14,62 @@ class SpacenavControl(QtCore.QObject):
     
     self.trans = True
     self.rot = True
+    self.speed = 480.0
     
-  def Changed(self, tx,ty,tz,rx,ry,rz): 
-    transf = gfx.Scene().GetTransform()
+  def Changed(self, tx,ty,tz,rx,ry,rz):
+    scene=gfx.Scene()
+    tf = scene.transform
+    def d(r):
+      if r==0.0:
+        return 0.0
+      rr=r/abs(r)*max(0.0,abs(r)-0.9)
+      if abs(rr)>0:
+        return rr/abs(rr)*(math.pow(1.01,abs(rr))-1.0)*40.0/self.speed
+      return 0.0
     if(self.trans):
-      transf.ApplyXAxisTranslation(tx/480.0)
-      transf.ApplyYAxisTranslation(ty/480.0)
-      transf.ApplyZAxisTranslation(-tz/480.0)
+      tf.ApplyXAxisTranslation(d(tx))
+      tf.ApplyYAxisTranslation(d(ty))
+      # adjust translation speed to distance from viewpoint
+      currz=tf.trans[2];
+      delta=currz*math.pow(1.01,d(tz))-currz;
+      tf.ApplyZAxisTranslation(delta);
+      # adjust near and far clipping planes together with z trans
+      scene.SetNearFar(scene.near-delta,scene.far-delta);
     if(self.rot):
-      transf.ApplyXAxisRotation(rx/480.0)
-      transf.ApplyYAxisRotation(ry/480.0)
-      transf.ApplyZAxisRotation(rz/480.0) 
-    gfx.Scene().SetTransform(transf)
-    gfx.Scene().RequestRedraw()
+      tf.ApplyXAxisRotation(d(rx))
+      tf.ApplyYAxisRotation(d(ry))
+      tf.ApplyZAxisRotation(d(rz))
+
+    scene.transform=tf
+    scene.RequestRedraw()
 
   def Toggle(self, button):
     if button == 0:
       self.trans = not self.trans
-      print "Translation Enabled:",self.trans
+      ost.LogVerbose("SpaceNav: translation %s "%("enabled" if self.trans else "disabled"))
     elif button == 1:
       self.rot = not self.rot
-      print "Rotation Enabled:",self.rot
+      ost.LogVerbose("SpaceNav: rotation %s"%("enabled" if self.rot else "disabled"))
+    elif button == 12:
+      if self.speed > 20:
+        self.speed *= 0.8
+        ost.LogVerbose("SpaceNav: speed increased to "+str(self.speed))
+    elif button == 13:
+      self.speed /= 0.8
+      ost.LogVerbose("SpaceNav: speed reduced to "+str(self.speed))
+    else:
+      ost.LogVerbose("SpaceNav: unmapped button press ["+str(button)+"]")
+
       
 def _InitSpaceNav(app):
   try:
     spnav = gui.SpnavInput.GetQThread()
-    spnav.start()
-    parent = app.gl_win.qobject
-    SpacenavControl(spnav,parent)
-  except AttributeError:
-    pass
\ No newline at end of file
+    if spnav:
+      spnav.start()
+      parent = app.gl_win.qobject
+      SpacenavControl(spnav,parent)
+      ost.LogInfo("SpaceNav: device found and connected")
+    else:
+      ost.LogInfo("SpaceNav: no device found, or could not connect to device socket")
+  except:
+    ost.LogInfo("SpaceNav: caught exception during initialization: %s"%(traceback.format_exc()))
diff --git a/modules/gui/pymod/scene/color_options_widget.py b/modules/gui/pymod/scene/color_options_widget.py
index 13e33f7c68c52e17e858d5e8d0aa356a8433c08c..1d8e95cf6ec5ff9402daec6b917dcc5ea2d06742 100644
--- a/modules/gui/pymod/scene/color_options_widget.py
+++ b/modules/gui/pymod/scene/color_options_widget.py
@@ -146,7 +146,10 @@ class ByElementWidget(QtGui.QWidget):
       
   def ChangeViewColor(self, entity, view):
     if isinstance(entity, gfx.Entity) and isinstance(view, mol.EntityView):
-      beco=gfx.ByElementColorOp(mol.QueryViewWrapper(view))
+      if self.parent_.GetCarbonsOnly():
+        beco=gfx.ByElementColorOp(mol.QueryViewWrapper(mol.Query("ele=C"), view))
+      else:
+        beco=gfx.ByElementColorOp(mol.QueryViewWrapper(view))
       entity.Apply(beco)
       
   def GetText(self):
@@ -185,7 +188,10 @@ class ByChainWidget(QtGui.QWidget):
       
   def ChangeViewColor(self, entity, view):
     if isinstance(entity, gfx.Entity) and isinstance(view, mol.EntityView):
-      bco=gfx.ByChainColorOp(mol.QueryViewWrapper(view))
+      if self.parent_.GetCarbonsOnly():
+        bco=gfx.ByChainColorOp(mol.QueryViewWrapper(mol.Query("ele=C"),view))
+      else:
+        bco=gfx.ByChainColorOp(mol.QueryViewWrapper(view))
       entity.Apply(bco)
       
   def GetText(self):
@@ -234,7 +240,10 @@ class ByEntityWidget(QtGui.QWidget):
      
   def ChangeViewColor(self, entity, view):
     if isinstance(entity, gfx.Entity) and isinstance(view, mol.EntityView):
-      bco=gfx.ByChainColorOp(mol.QueryViewWrapper(view))
+      if self.parent_.GetCarbonsOnly():
+        bco=gfx.ByChainColorOp(mol.QueryViewWrapper(mol.Query("ele=C"),view))
+      else:
+        bco=gfx.ByChainColorOp(mol.QueryViewWrapper(view))
       entity.Apply(bco)
       
   def GetText(self):
diff --git a/modules/gui/pymod/scene/color_select_widget.py b/modules/gui/pymod/scene/color_select_widget.py
index 160842a54d3b5c4e36f2abf020b30d7c9383a9d0..110108e6340c1078268169fa369e3f9c7364e152 100644
--- a/modules/gui/pymod/scene/color_select_widget.py
+++ b/modules/gui/pymod/scene/color_select_widget.py
@@ -61,7 +61,7 @@ class ColorSelectWidget(QtGui.QWidget):
   
   def GetGfxColor(self):
     color = self.GetColor()
-    return gfx.Color(color.redF(), color.greenF(), color.blueF())
+    return gfx.RGB(color.redF(), color.greenF(), color.blueF())
   
   def SetColor(self, color):
     if(self.color_ != color):
diff --git a/modules/gui/pymod/scene/gradient_editor_widget.py b/modules/gui/pymod/scene/gradient_editor_widget.py
index 34c11a24ac0d70b2a2026308365ad8f351a64005..d4b93071b3e6b0b4085dfb0672ee00baf235e09c 100644
--- a/modules/gui/pymod/scene/gradient_editor_widget.py
+++ b/modules/gui/pymod/scene/gradient_editor_widget.py
@@ -90,7 +90,10 @@ class GradientEditor(QtGui.QWidget):
 
   def ChangeViewColor(self, entity, view):
     if isinstance(entity, gfx.Entity) and isinstance(view, mol.EntityView):
-      glco=gfx.GradientLevelColorOp(mol.QueryViewWrapper(view),self.props[self.prop_combo_box_.currentIndex()],self.gradient_edit_.GetGfxGradient(),mol.Prop.Level.UNSPECIFIED)
+      if self.parent_.GetCarbonsOnly():
+        glco=gfx.GradientLevelColorOp(mol.QueryViewWrapper(mol.Query("ele=C"),view),self.props[self.prop_combo_box_.currentIndex()],self.gradient_edit_.GetGfxGradient(),mol.Prop.Level.UNSPECIFIED)
+      else:
+        glco=gfx.GradientLevelColorOp(mol.QueryViewWrapper(view),self.props[self.prop_combo_box_.currentIndex()],self.gradient_edit_.GetGfxGradient(),mol.Prop.Level.UNSPECIFIED)
       entity.Apply(glco)
       
 #Gradient Preview
@@ -197,7 +200,7 @@ class GradientEdit(QtGui.QWidget):
     gradient = gfx.Gradient()
     for s in self.stops:
       c=s.GetColor();
-      gradient.SetColorAt(s.GetRel(), gfx.Color(c.redF(), c.greenF(), c.blueF()));
+      gradient.SetColorAt(s.GetRel(), gfx.RGB(c.redF(), c.greenF(), c.blueF()));
     return gradient;
 
   def GetGradient(self):
diff --git a/modules/gui/pymod/scene/immutable_gradient_info_handler.py b/modules/gui/pymod/scene/immutable_gradient_info_handler.py
index 9998820b6e06506e23b40e5173f29b5b475d02ca..c70b041e9bfa3818a2c8df552f7cde9b241029dd 100644
--- a/modules/gui/pymod/scene/immutable_gradient_info_handler.py
+++ b/modules/gui/pymod/scene/immutable_gradient_info_handler.py
@@ -78,5 +78,5 @@ class ImmutableGradientInfoHandler:
     for s in gradient.stops():
       rel=s[0]
       color=s[1]
-      gfx_gradient.SetColorAt(s[0], gfx.Color(s[1].redF(), s[1].greenF(), s[1].blueF()));
+      gfx_gradient.SetColorAt(s[0], gfx.RGB(s[1].redF(), s[1].greenF(), s[1].blueF()));
     return gfx_gradient;
diff --git a/modules/gui/pymod/scene/immutable_info_handler.py b/modules/gui/pymod/scene/immutable_info_handler.py
index b85a1103917bd64cfe1833ff78f8e80b09852bce..600fd393dbec78da4d28a3f2c8718dda9d1adf89 100644
--- a/modules/gui/pymod/scene/immutable_info_handler.py
+++ b/modules/gui/pymod/scene/immutable_info_handler.py
@@ -65,7 +65,7 @@ class ImmutableInfoHandler:
     for s in gradient.stops():
       rel=s[0]
       color=s[1]
-      gfxgradient.SetColorAt(s[0], gfx.Color(s[1].redF(), s[1].greenF(), s[1].blueF()));
+      gfxgradient.SetColorAt(s[0], gfx.RGB(s[1].redF(), s[1].greenF(), s[1].blueF()));
     return gfxgradient;
   
   def GetQGradients(self):
diff --git a/modules/gui/pymod/scene/preset_editor_widget.py b/modules/gui/pymod/scene/preset_editor_widget.py
index d5348e918890ed0ef8666e500d7e3559e571f370..97d7e7723d07284033826560317ae7f17f6657c5 100644
--- a/modules/gui/pymod/scene/preset_editor_widget.py
+++ b/modules/gui/pymod/scene/preset_editor_widget.py
@@ -218,12 +218,12 @@ class UniformColorOpWidget(QtGui.QDialog):
     
   def GetOp(self):
     qv=mol.QueryViewWrapper(self.query_editor_.GetQuery(),self.query_editor_.GetQueryFlags())
-    ufco = UniformColorOp(qv,gfx.Color(1,1,1,1))
+    ufco = UniformColorOp(qv,gfx.RGBA(1,1,1,1))
     
     detail = self.detail_selection_cb_.itemData(self.detail_selection_cb_.currentIndex()).toPyObject()
     ufco.SetMask(detail)
     qcolor = self.color_select_widget_.GetColor()
-    color=gfx.Color(qcolor.red()/255.0,qcolor.green()/255.0,qcolor.blue()/255.0,qcolor.alpha()/255.0)
+    color=gfx.RGBAb(qcolor.red(),qcolor.green(),qcolor.blue(),qcolor.alpha())
     ufco.SetColor(color)
     return ufco
 
diff --git a/modules/gui/pymod/scene/uniform_color_widget.py b/modules/gui/pymod/scene/uniform_color_widget.py
index db8e5346f3276fac962da07868670c88149e2f88..66461dcff9c391e926e47d77eaa1458fb1f1ce63 100644
--- a/modules/gui/pymod/scene/uniform_color_widget.py
+++ b/modules/gui/pymod/scene/uniform_color_widget.py
@@ -97,7 +97,10 @@ class UniformColorWidget(QtGui.QWidget):
   def ChangeViewColor(self, entity, view):
     if isinstance(entity, gfx.Entity) and isinstance(view, mol.EntityView):
       gfx_color = self.color_select_widget_.GetGfxColor()
-      ufco=gfx.UniformColorOp(mol.QueryViewWrapper(view),gfx_color)
+      if self.parent_.GetCarbonsOnly():
+        ufco=gfx.UniformColorOp(mol.QueryViewWrapper(mol.Query("ele=C"), view),gfx_color)
+      else:
+        ufco=gfx.UniformColorOp(mol.QueryViewWrapper(view),gfx_color)
       entity.Apply(ufco)
     
   def resizeEvent(self, event):
diff --git a/modules/gui/pymod/table.py b/modules/gui/pymod/table.py
new file mode 100644
index 0000000000000000000000000000000000000000..fd65e9ff69ad2a9f496894c3e30b58ad5f18e52e
--- /dev/null
+++ b/modules/gui/pymod/table.py
@@ -0,0 +1,49 @@
+from PyQt4.QtGui import *
+from PyQt4.QtCore import *
+
+
+__all__=('Table', )
+
+class TableModel(QAbstractTableModel):
+  def __init__(self, table, parent=None):
+    QAbstractTableModel.__init__(self, parent)
+    self.table=table
+    
+  def rowCount(self, index):
+    return len(self.table.rows)
+
+  def headerData(self, section, orientation, role):
+    if role!=Qt.DisplayRole or orientation!=Qt.Horizontal:
+      return QVariant()
+    return self.table.col_names[section]
+    
+  def columnCount(self, index):
+    return len(self.table.col_names)
+
+  def sort(self, column, order):
+    o='+'
+    if order!=Qt.AscendingOrder:
+      o='-'
+    self.table.Sort(by=self.table.col_names[column], order=o)
+    self.reset()
+    
+  def data(self, index, role):
+    if not index.isValid() or role!=Qt.DisplayRole:
+      return QVariant()
+    row=self.table.rows[index.row()]
+    return QVariant(row[index.column()])
+
+class Table(QTableView):
+  def __init__(self, table):
+     QTableView.__init__(self)
+     self._model=TableModel(table)
+     self.setFrameShape(QFrame.NoFrame)    
+     self.setAttribute(Qt.WA_MacSmallSize)
+     self.setShowGrid(False)
+     #self.horizontalHeader().setStretchLastSection(True)
+     self.setContextMenuPolicy(Qt.CustomContextMenu)
+     self.setSelectionBehavior(QAbstractItemView.SelectRows)
+     self.setSizePolicy(QSizePolicy.MinimumExpanding, 
+                        QSizePolicy.MinimumExpanding)
+     self.setSortingEnabled(True)
+     self.setModel(self._model)
\ No newline at end of file
diff --git a/modules/gui/src/CMakeLists.txt b/modules/gui/src/CMakeLists.txt
index 50c89edb8b7ee2ee3f3ff059e2fc2128ce72ba11..b4d9ee6e433268164006b2c8806b1ebaf905e168 100644
--- a/modules/gui/src/CMakeLists.txt
+++ b/modules/gui/src/CMakeLists.txt
@@ -98,6 +98,7 @@ log_reader.hh
 )
 
 if (ENABLE_SPNAV)
+include_directories(${SPNAV_INCLUDE_DIR})
 set(OST_GUI_INPUT_HEADERS
 spnav_input.hh
   IN_DIR input
@@ -171,9 +172,9 @@ gl_win.hh
 scene_menu.hh
 gosty_app.hh
 admin.hh
+module_config.hh
 main.hh
 main_area.hh
-module_config.hh
 perspective.hh
 remote_site_loader.hh
 scene_selection.hh
@@ -428,13 +429,22 @@ if (ENABLE_IMG)
 endif()
 
 if (ENABLE_SPNAV)
+  set(spnav_enabled 1)
   list(APPEND OST_GUI_SOURCES
       input/spnav_input.cc
   )
   list(APPEND HEADERS_TO_BE_MOCCED
       input/spnav_input.hh
   )
+else()
+  set(spnav_enabled 0)
 endif()
+
+set(config_hh_generator "CMake")
+set(MODULE_CONFIG_HH_FILE "${CMAKE_CURRENT_SOURCE_DIR}/module_config.hh")
+configure_file(module_config.hh.in ${MODULE_CONFIG_HH_FILE})
+# the resulting file, module_config.hh, is already included in OST_GUI_HEADERS
+
 if (APPLE)
   set(ADDITIONAL_LIBRARIES "-framework Security")
 endif()
diff --git a/modules/gui/src/data_viewer/data_viewer.cc b/modules/gui/src/data_viewer/data_viewer.cc
index 2bc7d368f8ce6b178a01d9580de9d7d383edddd2..8db37d504cbb4556e365c6e3ffd293a6ad7a5b51 100644
--- a/modules/gui/src/data_viewer/data_viewer.cc
+++ b/modules/gui/src/data_viewer/data_viewer.cc
@@ -83,6 +83,7 @@ DataViewer::~DataViewer()
 void DataViewer::SetData(const Data& d)
 {
   panel_->SetData(d);
+  fft_->SetData(d);
   info_->SetImageInfo(d);
 }
 
diff --git a/modules/gui/src/data_viewer/data_viewer_panel_base.hh b/modules/gui/src/data_viewer/data_viewer_panel_base.hh
index 4c4b59bb5df8bb4df9853d6f10dd42d577e78ed0..ec2345a5cd471ba29ab78eded8a53934d0ba5624 100644
--- a/modules/gui/src/data_viewer/data_viewer_panel_base.hh
+++ b/modules/gui/src/data_viewer/data_viewer_panel_base.hh
@@ -59,7 +59,7 @@ public:
   DataViewerPanelBase(const Data& data,QWidget* parent);
   virtual ~DataViewerPanelBase();
 
-  void SetData(const Data& d);
+  virtual void SetData(const Data& d);
 
   //////////////////
   // event handling
diff --git a/modules/gui/src/data_viewer/fft_panel.cc b/modules/gui/src/data_viewer/fft_panel.cc
index 00d3b60d2e2635600dae4d9b711144fa078fe46c..17dd63b4a9da18678ae40f712241b1c9a2a98f67 100644
--- a/modules/gui/src/data_viewer/fft_panel.cc
+++ b/modules/gui/src/data_viewer/fft_panel.cc
@@ -36,18 +36,17 @@ FFTPanel::FFTPanel(const Data& parent_data, QWidget* parent):
   DataViewerPanelBase(parent_data,parent),
   size_(std::min<int>(256,std::min<int>(parent_data.GetSize()[0],parent_data.GetSize()[1]))),
   parent_position_(parent_data.GetExtent().GetCenter()),
-  parent_data_(parent_data),
   fft_data_(CreateImage(Extent(Size(size_,size_),Point(0,0)),
-                              COMPLEX,HALF_FREQUENCY))
+                              COMPLEX,HALF_FREQUENCY)),
+  parent_observer_(parent_data)
 {
   QAction* a_set_size=new QAction("Set FFT size",this);
   popupmenu_->addAction(a_set_size);
   connect(a_set_size, SIGNAL(triggered()), this, SLOT(ShowSizeDialog()));
-  SetData(fft_data_);
+  DataViewerPanelBase::SetData(fft_data_);
   update_fft();
 }
 
-
 FFTPanel::~FFTPanel()
 {
 }
@@ -58,8 +57,6 @@ void FFTPanel::ObserverUpdate()
   UpdateView(true);
 }
 
-
-
 void FFTPanel::SetPosition(const Point& p)
 {
   parent_position_=p;
@@ -71,9 +68,14 @@ void FFTPanel::ShowSizeDialog()
   bool ok;
   #if QT_VERSION >= 0x040500
     int i = QInputDialog::getInt(this, "Set FFT size","FFT size", size_, 1, 
-                                 std::min<int>(parent_data_.GetSize()[0],parent_data_.GetSize()[1]), 1, &ok);
+                                 std::min<int>(parent_observer_.GetObservedData().GetSize()[0],
+                                               parent_observer_.GetObservedData().GetSize()[1]),
+                                 1, &ok);
   #else
-    int i = QInputDialog::getInteger(this, "Set FFT size","FFT size", size_, 1, std::min<int>(parent_data_.GetSize()[0],parent_data_.GetSize()[1]), 1, &ok);
+    int i = QInputDialog::getInteger(this, "Set FFT size","FFT size", size_, 1,
+                                     std::min<int>(parent_observer_.GetObservedData().GetSize()[0],
+                                                   parent_observer_.GetObservedData().GetSize()[1]),
+                                     1, &ok);
   #endif
   if (ok){
     SetFFTSize(i);
@@ -93,14 +95,21 @@ unsigned int FFTPanel::GetFFTSize()
   return size_;
 }
 
-void  FFTPanel::update_fft()
+void FFTPanel::SetData(const Data& parent_data)
 {
-  ImageHandle im=CreateImage(Extent(Size(size_,size_),
-                                                      parent_position_));
-  im.Paste(parent_data_);
+  parent_observer_=ParentDataObserver(parent_data);
+}
+
+
+void FFTPanel::update_fft()
+{
+  ImageHandle im=CreateImage(Extent(Size(size_,size_),parent_position_));
+  im.Paste(parent_observer_.GetObservedData());
   im.ApplyIP(alg::FFT());
   fft_data_.Paste(im);
   UpdateView(true);
 }
 
+
 }}}  //ns
+
diff --git a/modules/gui/src/data_viewer/fft_panel.hh b/modules/gui/src/data_viewer/fft_panel.hh
index fab31b6accdb9280ef12354da12cbcca4c787315..2add54b8d2ca8140a078249250382751dc18ae3e 100644
--- a/modules/gui/src/data_viewer/fft_panel.hh
+++ b/modules/gui/src/data_viewer/fft_panel.hh
@@ -29,6 +29,16 @@
 
 namespace ost { namespace img { namespace gui {
 
+class ParentDataObserver: public DataObserver
+{
+public:
+  ParentDataObserver(const Data& d):DataObserver(d){}
+  virtual void ObserverRelease()
+  {
+   // Noop as parent takes care of this.
+  }
+};
+
 class DLLEXPORT_OST_GUI FFTPanel: public DataViewerPanelBase
 {
 Q_OBJECT
@@ -39,6 +49,7 @@ public:
   void SetFFTSize(unsigned int size);
   unsigned int GetFFTSize();
   virtual void ObserverUpdate();
+  virtual void SetData(const Data& parent_data);
 
 public slots:
   void SetPosition(const Point& p);
@@ -48,8 +59,8 @@ protected:
   void update_fft();
   unsigned int size_;
   Point parent_position_;
-  const Data& parent_data_;
   ImageHandle fft_data_;
+  ParentDataObserver parent_observer_;
 };
 
 }}}  //ns
diff --git a/modules/gui/src/file_browser.cc b/modules/gui/src/file_browser.cc
index a6bf49fb31a33d77c318191e046347b4df3436ec..a41ff0a293f864c6a43f67382d5acf4236dedeb2 100644
--- a/modules/gui/src/file_browser.cc
+++ b/modules/gui/src/file_browser.cc
@@ -81,6 +81,7 @@ FileBrowser::FileBrowser(QWidget* parent):
     if (QDir(example_path).exists()) {
       path=example_path;
     }    else{
+      dir.cdUp();
       dir.cdUp();
       example_path=dir.path()+"/examples";
       if (QDir(example_path).exists()) {
diff --git a/modules/gui/src/gl_canvas.cc b/modules/gui/src/gl_canvas.cc
index 2d631931bafc912c9137587f28df24c1b9a0b9c0..f94bff0458c4fbfe746c489e424ebc467c9137d2 100644
--- a/modules/gui/src/gl_canvas.cc
+++ b/modules/gui/src/gl_canvas.cc
@@ -369,7 +369,7 @@ void GLCanvas::CopySelectionToClipboard()
       if (!rv.IsPeptideLinking() || rv.GetOneLetterCode()=='?')
         continue;      
       seq1 << rv.GetOneLetterCode();
-      if (sel.FindResidue(rv.GetHandle()).IsValid()) {
+      if (sel.ViewForHandle(rv.GetHandle()).IsValid()) {
         seq2 << rv.GetOneLetterCode();
       } else {
         seq2 << '-';
diff --git a/modules/gui/src/input/spnav_input.cc b/modules/gui/src/input/spnav_input.cc
index 362cfa3d5f0e8df4b747d750f463e89147e1ddbd..10022c6aef7fd6154cbe5246c4d24b10b82906f1 100644
--- a/modules/gui/src/input/spnav_input.cc
+++ b/modules/gui/src/input/spnav_input.cc
@@ -18,56 +18,86 @@
 //------------------------------------------------------------------------------
 
 /*
-  Author: Stefan Scheuber
+  Authors: Stefan Scheuber, Ansgar Philippsen
 */
 
 #include "spnav_input.hh"
 
 #include <iostream>
 
-#include <ost/io/io_exception.hh>
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <signal.h>
+#include <stdexcept>
+
 #include <spnav.h>
+#include <sys/un.h>
+#include <sys/types.h>
+#include <sys/socket.h>
 
-namespace ost { namespace gui {
+namespace {
 
-SpnavInput* SpnavInput::spnav_=NULL;
+  // immitate spnav_open, but without the annoying perror littering 
+  bool check_spnav() {
+    int s=0;
+    sockaddr_un addr;
 
-SpnavInput::SpnavInput(QObject* parent): QThread(parent)
-{
-  qRegisterMetaType<geom::Mat4>("geom::Mat4");
-  if(spnav_open()==-1) {
-    throw(io::IOException("failed to connect to the space navigator daemon\n"));
+    memset(&addr, 0, sizeof(sockaddr_un));
+    addr.sun_family = AF_UNIX;
+    strncpy(addr.sun_path, "/var/run/spnav.sock", sizeof(addr.sun_path));
+
+    if((s = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
+      return false;
+    }
+    if(connect(s, (struct sockaddr*)&addr, sizeof(sockaddr_un)) == -1) {
+      return false;
+    }
+    close(s);
+    return true;
   }
+
 }
 
-void SpnavInput::run(){
+namespace ost { namespace gui {
+
+SpnavInput::SpnavInput(QObject* parent): 
+  QThread(parent),
+  valid_(false)
+{
+  qRegisterMetaType<geom::Mat4>("geom::Mat4");
+  if(check_spnav() && spnav_open()!=-1) {
+    valid_=true;
+  } 
+}
 
+void SpnavInput::run()
+{
+  if(!valid_) return;
 	spnav_event sev;
 
   while(spnav_wait_event(&sev)) {
     if(sev.type == SPNAV_EVENT_MOTION) {
       emit this->deviceTransformed(sev.motion.x,sev.motion.y,sev.motion.z, sev.motion.rx, sev.motion.ry, sev.motion.rz);
-    } else {  /* SPNAV_EVENT_BUTTON */
-      printf("got button %s event b(%d)\n", sev.button.press ? "press" : "release", sev.button.bnum);
+    } else if (sev.type == SPNAV_EVENT_BUTTON) {
+      //printf("got button %s event b(%d)\n", sev.button.press ? "press" : "release", sev.button.bnum);
       if(sev.button.press)
         emit this->deviceButtonPressed(sev.button.bnum);
     }
   }
 }
 
-SpnavInput::~SpnavInput(){
-  spnav_close();
+SpnavInput::~SpnavInput()
+{
+  if(valid_) {
+    spnav_close();
+    this->quit();
+    this->terminate();
+  }
 }
 
 SpnavInput* SpnavInput::Instance() {
-  if (!SpnavInput::spnav_) {
-    SpnavInput::spnav_=new SpnavInput;
-  }
-  return SpnavInput::spnav_;
+  static SpnavInput inst;
+  return &inst;
 }
 
 }} //ns
diff --git a/modules/gui/src/input/spnav_input.hh b/modules/gui/src/input/spnav_input.hh
index a77734b34765e4f3e53732021ad8177da23f27af..fe6eec7e651421da882acced300b3aa5e3c52e2b 100644
--- a/modules/gui/src/input/spnav_input.hh
+++ b/modules/gui/src/input/spnav_input.hh
@@ -41,13 +41,15 @@ public:
 
   static SpnavInput* Instance();
 
+  bool isValid() const {return valid_;}
+
 signals:
   void deviceTransformed(int,int,int,int,int,int);
   void deviceButtonPressed(int);
 
 private:
   SpnavInput(QObject* parent=NULL);
-  static SpnavInput*  spnav_;
+  bool valid_;
 };
 
 }} //ns
diff --git a/modules/gui/src/module_config.hh b/modules/gui/src/module_config.hh.in
similarity index 91%
rename from modules/gui/src/module_config.hh
rename to modules/gui/src/module_config.hh.in
index a4c324080f637e137c217ca3ff0707a8ce1f864d..a45752148678c6e460b8d6bdcd4b0203cab07c59 100644
--- a/modules/gui/src/module_config.hh
+++ b/modules/gui/src/module_config.hh.in
@@ -19,8 +19,14 @@
 #ifndef OST_GUI_MODULE_CONFIG_HH
 #define OST_GUI_MODULE_CONFIG_HH
 
+/*
+  DO NOT EDIT, automatically generated by @config_hh_generator@
+*/
+
 #include <ost/base.hh>
 
+#define OST_SPNAV_ENABLED @spnav_enabled@
+
 #if defined(OST_MODULE_OST_GUI)
 #  define DLLEXPORT_OST_GUI DLLEXPORT
 #else
diff --git a/modules/gui/src/python_shell/python_shell_widget.cc b/modules/gui/src/python_shell/python_shell_widget.cc
index e1891ae2c6e8f9148b363747eac05784e4be605c..8b0fd88d3456405632b9068fb98fed33359e5aea 100644
--- a/modules/gui/src/python_shell/python_shell_widget.cc
+++ b/modules/gui/src/python_shell/python_shell_widget.cc
@@ -332,6 +332,13 @@ void PythonShellWidget::setup_state_machine_()
   single_line->addTransition(clear_all_tr_sl);
   connect(clear_all_tr_sl,SIGNAL(triggered()),this,SLOT(handle_clear_all_()));
 
+  single_line->addTransition(new KeyEventTransition(Qt::Key_Left,
+                                                    DNG_ARROW_MODIFIERS,
+                                                    single_line,
+                                                    true,
+                                                    new EditPositionGuard(this,EditPositionGuard::EQUAL,
+                                                                               EditPositionGuard::ANCHOREQUAL |EditPositionGuard::ANCHORBIGGER)));
+
   //multi line inactive transitions
   multi_line_inactive->addTransition(new KeyEventTransition(Qt::Key_Return,
                                                             Qt::NoModifier,
@@ -878,6 +885,7 @@ void PythonShellWidget::insertFromMimeData(const QMimeData * source)
   if(lines.size()>0){
     set_block_type_(block_edit_start_,document()->lastBlock(),BLOCKTYPE_BLOCKEDIT);
   }
+  setFocus();
 }
 
 GutterBlockList PythonShellWidget::GetGutterBlocks(const QRect& rect)
diff --git a/modules/gui/src/scene_menu.cc b/modules/gui/src/scene_menu.cc
index 67f85b90de1ccf0b1197693c0e9fc369f3be3cbd..ef02a2aee2807a00034228fc451a2763d73bdde1 100644
--- a/modules/gui/src/scene_menu.cc
+++ b/modules/gui/src/scene_menu.cc
@@ -60,12 +60,12 @@ SceneMenu::SceneMenu() {
 
 void SceneMenu::SelectBackbone()
 {
-  this->Select("peptide=true and aname=CA,C,N,O");
+  this->Select("peptide=true and aname=CA,C,N,O,H,HA,OXT,HXT,HA2,HA3");
 }
 
 void SceneMenu::SelectSidechains()
 {
-  this->Select("peptide=true and aname!=CA,C,N,O");
+  this->Select("peptide=true and aname!=CA,C,N,O,H,HA,OXT,HXT,HA2,HA3");
 }
 
 void SceneMenu::SelectLigands()
diff --git a/modules/gui/src/scene_win/entity_node.cc b/modules/gui/src/scene_win/entity_node.cc
index 4f49dcc96e676a8df67f73179c266f2e029649bd..02dc97c54f8396bc2e986b208c727a4a52144b43 100644
--- a/modules/gui/src/scene_win/entity_node.cc
+++ b/modules/gui/src/scene_win/entity_node.cc
@@ -59,9 +59,9 @@ EntityNode::EntityNode(gfx::EntityP& entity, SceneNode* parent):
   SceneNode* quick_selection = new LabelNode("Quick Selection",this);
   model->AddNode(this, quick_selection);
 
-  SceneNode* node = new EntityPartNode("Backbone", entity, mol::QueryViewWrapper(mol::Query("aname=CA,C,N,O and peptide=true"),entity->GetView()), quick_selection);
+  SceneNode* node = new EntityPartNode("Backbone", entity, mol::QueryViewWrapper(mol::Query("aname=CA,C,N,O,H,HA,OXT,HXT,HA2,HA3 and peptide=true"),entity->GetView()), quick_selection);
   model->AddNode(quick_selection, node);
-  node = new EntityPartNode("Sidechains", entity, mol::QueryViewWrapper(mol::Query("aname!=CA,C,N,O and peptide=true"),mol::QueryFlag::EXCLUSIVE_BONDS,entity->GetView()), quick_selection);
+  node = new EntityPartNode("Sidechains", entity, mol::QueryViewWrapper(mol::Query("aname!=CA,C,N,O,H,HA,OXT,HXT,HA2,HA3 and peptide=true"),mol::QueryFlag::EXCLUSIVE_BONDS,entity->GetView()), quick_selection);
   model->AddNode(quick_selection, node);
   node = new EntityPartNode("Ligands", entity, mol::QueryViewWrapper(mol::Query("ishetatm=1 and rname!=HOH,WAT"),entity->GetView()), quick_selection);
   model->AddNode(quick_selection, node);
diff --git a/modules/gui/src/sequence_viewer/sequence_view_object.cc b/modules/gui/src/sequence_viewer/sequence_view_object.cc
index f9303f8ddce335f16dbf4fd4f48cef5eb3bfaa16..97993f0cdf11d45967377249f0793cf01e37ea50 100644
--- a/modules/gui/src/sequence_viewer/sequence_view_object.cc
+++ b/modules/gui/src/sequence_viewer/sequence_view_object.cc
@@ -168,7 +168,7 @@ QMap<int, QList<int> > SequenceViewObject::GetIndexesForView(const mol::EntityVi
           // for each residue in the selection deduce index in sequence
           for (mol::ResidueViewList::const_iterator j=src_chain.GetResidueList().begin(),
              e2=src_chain.GetResidueList().end(); j!=e2; ++j) {
-            mol::ResidueView dst_res=dst_chain.FindResidue(j->GetHandle());
+            mol::ResidueView dst_res=dst_chain.ViewForHandle(j->GetHandle());
             assert(dst_res.IsValid());
             int p=dst_res.GetIndex()+1;
             assert(p>=0 && p<=seq.GetLength());
diff --git a/modules/gui/src/sequence_viewer/sequence_viewer.cc b/modules/gui/src/sequence_viewer/sequence_viewer.cc
index 024355c1b5325b87f60b67b462c55a4abef73b75..a34e917b6c20e86e2ba752c08d3b5e2ced3a2c29 100644
--- a/modules/gui/src/sequence_viewer/sequence_viewer.cc
+++ b/modules/gui/src/sequence_viewer/sequence_viewer.cc
@@ -96,6 +96,7 @@ SequenceViewer::SequenceViewer(bool stand_alone, bool observe_scene,
   layout->setSpacing(0);
   this->setLayout(layout);
 
+  toolbar_ = new QToolBar(this);
   this->InitActions();
 
 
@@ -120,7 +121,6 @@ SequenceViewer::SequenceViewer(bool stand_alone, bool observe_scene,
 
 void SequenceViewer::InitMenuBar()
 {
-  toolbar_ = new QToolBar(this);
   toolbar_->setToolButtonStyle(Qt::ToolButtonIconOnly);
   toolbar_->setIconSize(QSize(16,16));
   toolbar_->addActions(action_list_);
@@ -164,7 +164,7 @@ void SequenceViewer::InitActions()
   icon_path.cd("gui");
   icon_path.cd("icons");
 
-  QAction* find_action = new QAction(this);
+  QAction* find_action = new QAction(toolbar_);
   find_action->setText("Find Dialog");
   find_action->setShortcut(QKeySequence(tr("Ctrl+F")));
   find_action->setCheckable(true);
@@ -173,8 +173,8 @@ void SequenceViewer::InitActions()
   action_list_.append(find_action);
   connect(find_action, SIGNAL(triggered(bool)), this, SLOT(FindInSequence()));
 
-  display_mode_actions_ = new QActionGroup(this);
-  QAction* menu_action = new QAction(this);
+  display_mode_actions_ = new QActionGroup(toolbar_);
+  QAction* menu_action = new QAction(toolbar_);
   menu_action->setText("Menubar");
   menu_action->setShortcut(QKeySequence(tr("Ctrl+M")));
   menu_action->setToolTip("Display Options (Ctrl+M)");
diff --git a/modules/img/alg/src/fft.cc b/modules/img/alg/src/fft.cc
index 49fc3f6260ffdb986a3cb6f91a7da890516b2405..a924a0fe6ace8e5199ea31a04c664ddbe43194d7 100644
--- a/modules/img/alg/src/fft.cc
+++ b/modules/img/alg/src/fft.cc
@@ -118,6 +118,7 @@ ImageStateBasePtr FFTFnc::VisitState<Real,SpatialDomain>(const RealSpatialImageS
   boost::shared_ptr<ComplexHalfFrequencyImageState> out_state(new ComplexHalfFrequencyImageState(in_size,ps));
 
   out_state->SetSpatialOrigin(in_state.GetSpatialOrigin());
+  out_state->SetAbsoluteOrigin(in_state.GetAbsoluteOrigin());
 
   assert(sizeof(OST_FFTW_fftw_complex)==sizeof(Complex));
   OST_FFTW_fftw_complex* fftw_out =
@@ -211,6 +212,7 @@ ImageStateBasePtr FFTFnc::VisitState<Complex,HalfFrequencyDomain>(const ComplexH
   Size out_size = in_state.GetLogicalExtent().GetSize();
   boost::shared_ptr<RealSpatialImageState> out_state(new RealSpatialImageState(out_size,tmp_state.Data(),ps ));
   out_state->SetSpatialOrigin(in_state.GetSpatialOrigin());
+  out_state->SetAbsoluteOrigin(in_state.GetAbsoluteOrigin());
 
 
   Real* out_ptr = out_state->Data().GetData();
@@ -252,6 +254,7 @@ ImageStateBasePtr FFTFnc::VisitState<Complex,SpatialDomain>(const ComplexSpatial
   ps.SetDomain(FREQUENCY);
   boost::shared_ptr<ComplexFrequencyImageState> out_state(new ComplexFrequencyImageState(size,ps));
   out_state->SetSpatialOrigin(in_state.GetSpatialOrigin());
+  out_state->SetAbsoluteOrigin(in_state.GetAbsoluteOrigin());
 
   out_state->Data()=in_state.Data(); // use assignement op to copy data area to new state
   int rank = size.GetDim();
@@ -291,6 +294,7 @@ ImageStateBasePtr FFTFnc::VisitState<Complex,FrequencyDomain>(const ComplexFrequ
   // use memory located for tmp
   boost::shared_ptr<ComplexSpatialImageState> out_state(new ComplexSpatialImageState(size,tmp.Data(),ps));
   out_state->SetSpatialOrigin(in_state.GetSpatialOrigin());
+  out_state->SetAbsoluteOrigin(in_state.GetAbsoluteOrigin());
 
   int rank = size.GetDim();
   int n[3] = {size[0],size[1],size[2]};
diff --git a/modules/img/alg/src/fractional_shift.cc b/modules/img/alg/src/fractional_shift.cc
index b7545a523505a4ba83b34e6eb8cfbb707df76450..1d10dac297ab035d9a22643540abc8fa3aa6a882 100644
--- a/modules/img/alg/src/fractional_shift.cc
+++ b/modules/img/alg/src/fractional_shift.cc
@@ -56,7 +56,10 @@ Vec3 FractionalShift::GetShift() const
 
 void FractionalShift::Visit(ImageHandle& ih)
 {  
+  Vec3 ao=ih.GetAbsoluteOrigin();
+
   bool spatialflag=false;
+
   if(ih.GetDomain()==SPATIAL){
     spatialflag=true;
     ih.ApplyIP(FFT());
@@ -72,10 +75,12 @@ void FractionalShift::Visit(ImageHandle& ih)
   for(ExtentIterator it=ih.GetIterator();!it.AtEnd();++it) {
     ih.SetComplex(it,ih.GetComplex(it)*std::polar<Real>(1.0,-Dot(phaseshift,Point(it).ToVec3())));
   }
+
   if(spatialflag){
-    //back FFT
     ih.ApplyIP(FFT());
   }
+  // update spatial origin
+  ih.SetAbsoluteOrigin(ao-shift_);
 }
 
 }}}//ns
diff --git a/modules/img/alg/src/histogram.hh b/modules/img/alg/src/histogram.hh
index e6a22592acb24e4dea120b8ca6a20fa286ea4184..820744d31b01ace41437c9d0293a24f086291dfa 100644
--- a/modules/img/alg/src/histogram.hh
+++ b/modules/img/alg/src/histogram.hh
@@ -35,8 +35,7 @@ namespace ost { namespace img { namespace alg {
 
 class DLLEXPORT HistogramError: public Error {
 public:
-  virtual ~HistogramError() throw() {} // required for typeinfo visibility
-  HistogramError(const String& s):
+    HistogramError(const String& s):
     Error(String("A histogram error occured: ") + s)
   {}
 };
diff --git a/modules/img/alg/tests/test_fft.cc b/modules/img/alg/tests/test_fft.cc
index dd742e41ec869feadc9b8747874fef73013b28f6..3e3702690117843ed71fc633b0ddbfeb69e0d418 100644
--- a/modules/img/alg/tests/test_fft.cc
+++ b/modules/img/alg/tests/test_fft.cc
@@ -88,7 +88,7 @@ void Test_C2C_1D_calc(int N)
     Point peak(N/step,0);
     Complex peak_value = out_state->Value(peak);
     Complex calc_peak_value = Complex(sum,0.0);
-    std::cout << std::abs(peak_value-calc_peak_value);
+    //std::cout << std::abs(peak_value-calc_peak_value);
     BOOST_REQUIRE(std::abs(peak_value-calc_peak_value)<1e-06);
 
   } catch (alg::FFTException& e) {
diff --git a/modules/img/alg/tests/test_histogram.cc b/modules/img/alg/tests/test_histogram.cc
index 98f323a21c927ec4da09da9dd935699f20bb2042..c5382ce88745c390ebd3a988feeeb4b8b076f202 100644
--- a/modules/img/alg/tests/test_histogram.cc
+++ b/modules/img/alg/tests/test_histogram.cc
@@ -61,6 +61,13 @@ void test()
     msg << " expected bins[" << k << "] == 1 but got " << bins[k];
     BOOST_CHECK_MESSAGE(bins[k]==1,msg.str());
   }
+  try {
+      BOOST_CHECK_THROW(Histogram(1,0.0,1.0),HistogramError);
+  }catch(...){
+    BOOST_ERROR( "Failed to catch HisotgramException." );
+  }
+
+
 }
 
 } // namespace 
diff --git a/modules/img/base/pymod/export_image_handle.cc b/modules/img/base/pymod/export_image_handle.cc
index bbfdd713cbe3801926cce461acc478cf0ff99788..24aace26cb7b1a4d4945296e592c6ee3cd27d8f5 100644
--- a/modules/img/base/pymod/export_image_handle.cc
+++ b/modules/img/base/pymod/export_image_handle.cc
@@ -25,6 +25,7 @@
 #include <boost/python.hpp>
 using namespace boost::python;
 
+#include <ost/message.hh>
 #include <ost/img/algorithm.hh>
 #include <ost/img/image.hh>
 #include <ost/img/function.hh>
@@ -94,7 +95,7 @@ img::Point tuple_to_point(size_t dim, tuple t)
 {
   size_t tuple_len=len(t);
   if (tuple_len!=dim) {
-    throw std::runtime_error("length of tuple and image dimension must match");
+    throw ost::Error("length of tuple and image dimension must match");
   }
   img::Point p;
   for (size_t i=0; i<tuple_len; ++i) {
@@ -120,7 +121,7 @@ object ih_get_item_a(ConstImageHandle ih, tuple t)
 object ih_get_item_c(ConstImageHandle ih, int x)
 {
   if (ih.GetSize().GetDim()!=1) {
-    throw std::runtime_error("Can't address point of multi-dimensional image with scalar");
+    throw ost::Error("Can't address point of multi-dimensional image with scalar");
   }
   return ih_get_item(ih, img::Point(x, 0, 0));
 }
@@ -152,7 +153,7 @@ void ih_set_item_b(ImageHandle ih, img::Point p, object value)
 void ih_set_item_c(ImageHandle ih, int x, object value)
 {
   if (ih.GetSize().GetDim()!=1) {
-    throw std::runtime_error("Can't address point of multi-dimensional image with scalar");
+    throw ost::Error("Can't address point of multi-dimensional image with scalar");
   }  
   ih_set_item(ih, img::Point(x, 0, 0), value);
 }
@@ -205,9 +206,11 @@ void export_ImageHandle()
     .def("SetComplex",&ImageHandle::SetComplex, args("point","value"))
     .def("SetSpatialOrigin",&ImageHandle::SetSpatialOrigin)
     .def("GetSpatialOrigin",&ImageHandle::GetSpatialOrigin)
+    .add_property("spatial_origin",&ImageHandle::GetSpatialOrigin,&ImageHandle::SetSpatialOrigin)
     .def("CenterSpatialOrigin",&ImageHandle::CenterSpatialOrigin)
     .def("SetAbsoluteOrigin",&ImageHandle::SetAbsoluteOrigin)
     .def("GetAbsoluteOrigin",&ImageHandle::GetAbsoluteOrigin)
+    .add_property("absolute_origin",&ImageHandle::GetAbsoluteOrigin,&ImageHandle::SetAbsoluteOrigin)
     .def("IndexToCoord",&ImageHandle::IndexToCoord)
     .def("CoordToIndex",&ImageHandle::CoordToIndex)
     .def("FractionalIndexToCoord",&ImageHandle::FractionalIndexToCoord)
@@ -296,7 +299,9 @@ void export_ConstImageHandle()
     .def("Apply",apply_cmodip)
     .def("Apply",apply_cmodop)
     .def("GetSpatialOrigin",&ConstImageHandle::GetSpatialOrigin)
+    .add_property("spatial_origin",&ImageHandle::GetSpatialOrigin)
     .def("GetAbsoluteOrigin",&ConstImageHandle::GetAbsoluteOrigin)
+    .add_property("absolute_origin",&ImageHandle::GetAbsoluteOrigin)
     .def("IndexToCoord",&ConstImageHandle::IndexToCoord)
     .def("CoordToIndex",&ConstImageHandle::CoordToIndex)
     .def("FractionalIndexToCoord",&ConstImageHandle::FractionalIndexToCoord)
diff --git a/modules/img/base/src/point.cc b/modules/img/base/src/point.cc
index 80ac131f97ee3fb198027455c367dd16109dc4d5..3cadd17b077843974d54af42a7bce5610ccbaf52 100644
--- a/modules/img/base/src/point.cc
+++ b/modules/img/base/src/point.cc
@@ -87,7 +87,7 @@ Point::Point(const Vec4& v):
   data_()
 {
   if(std::abs(v[3])<1e-100) {
-    throw std::range_error("4th element of Vec4 is too close to zero for normalization");
+    throw geom::OutOfRangeException("4th element of Vec4 is too close to zero for normalization");
   } else {
     Real sf = 1.0/v[3];
     data_[0]=static_cast<int>(round(v[0]*sf));
@@ -245,7 +245,7 @@ int& Point::operator[](unsigned int index)
 
 int Point::operator[](unsigned int index) const 
 {
-  if(index>2) throw std::range_error("Point index out of range");
+  if(index>2) throw geom::OutOfRangeException("Point index out of range");
   return data_[index];
 }
 
diff --git a/modules/img/base/src/size.cc b/modules/img/base/src/size.cc
index e8c0ed1b86f9c8f6a00e85d9fe5e2f24995c9cc1..97e1fa46001e1365d21fb3b9e2ed67d9c49f6252 100644
--- a/modules/img/base/src/size.cc
+++ b/modules/img/base/src/size.cc
@@ -108,7 +108,7 @@ unsigned int& Size::operator[](unsigned int index)
   if(index==0) return w_;
   else if(index==1) return h_;
   else if(index==2) return d_;
-  else throw std::range_error("Size index out of range");
+  else throw geom::OutOfRangeException("Size index out of range");
 }
 
 unsigned int Size::operator[](unsigned int index) const 
@@ -116,7 +116,7 @@ unsigned int Size::operator[](unsigned int index) const
   if(index==0) return w_;
   else if(index==1) return h_;
   else if(index==2) return d_;
-  else throw std::range_error("Size index out of range");
+  else throw geom::OutOfRangeException("Size index out of range");
 }
 
 bool Size::operator==(const Size& s) const 
diff --git a/modules/index.rst b/modules/index.rst
index 89bb6d3614d7c91c7fb9050a1fc9f9ab73deecc3..cb92f375dcdc0b20527f1bc26fec308465c4cc62 100644
--- a/modules/index.rst
+++ b/modules/index.rst
@@ -7,6 +7,7 @@ OpenStructure documentation
   
   install
   intro
+  users
   base/generic
   base/base
   geom/geom
@@ -57,6 +58,7 @@ Density Maps and Images
 
 **Overview**: :doc:`images intro <intro-02>` | :doc:`img module <img/base/img>` | :doc:`img.alg module <img/alg/alg>`
 
+**Input/Output**: :ref:`loading and saving density maps <img-io>`
 
 
 
@@ -93,8 +95,9 @@ Varia
 
 **Datasets:** :doc:`tabular data <table>`
 
-**File Formats:** :doc:`supported file formats <io/formats>`
+**Supported File Formats:** :doc:`structure formats<io/structure_formats>` | :doc:`sequence formats <io/sequence_formats>` | :doc:`image formats <io/image_formats>`
 
+**Users** :doc:`Reporting a problem <users>`
 
 Extending OpenStructure
 --------------------------------------------------------------------------------
@@ -102,7 +105,3 @@ Extending OpenStructure
 **Howto:** :doc:`write new modules <newmodule>` | :doc:`integrate third-party tools <external>` | :doc:`logging <base/logging>` | :doc:`instructions for developers <contributing>`
 
 
-
-
-
-  
diff --git a/modules/io/doc/formats.rst b/modules/io/doc/formats.rst
deleted file mode 100644
index fc6fee4cb8e12e0b2ed01731d0a213be18270b76..0000000000000000000000000000000000000000
--- a/modules/io/doc/formats.rst
+++ /dev/null
@@ -1,186 +0,0 @@
-Supported File Formats
-================================================================================
-
-Structure File Formats
---------------------------------------------------------------------------------
-
-The following file formats are supported by :func:`~ost.io.LoadEntity`. 
-
-
-
-CRD - CARD format file used by CHARMM
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-This trajectory file format is used by the CHARMM program suite (Molecular Modelling).
-
-*Recognized File Extensions*
-  crd
-
-PDB - Brookhaven PDB File
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Fine grained control over PDB file import is available via the 
-:func:`~ost.io.LoadPDB` function. The PDB importer supports loading gzipped PDB 
-files, which are auto-detected by the .gz file extension.
-
-*Recognized File Extensions*
-  ent, pdb, ent.gz, pdb.gz
-
-*Format Name*
-  pdb
-
-PQR
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-*Recognized File Extensions*
-  pqr
-
-*Format Name*
-  pqr
-  
-SDF - Structured Data File
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-*Recognized File Extensions*
-  sdf
-  
-Sequence File Formats
---------------------------------------------------------------------------------
-
-FASTA
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-*Recognized File Extensions*
-  fasta, fna, fas, fa, fsa
-  
-*Format Name*
-  fasta
-
-ClustalW
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-*Recognized File Extensions*
-  aln
-  
-*Format Name*
-  clustal
-
-Promod
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-*Recognized File Extensions*
-  ali
-  
-*Format Name*
-  promod
-  
-
-Image File Formats
---------------------------------------------------------------------------------
-
-DAT
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-*Recognized File Extensions*
-  dat, img  
-
-*Format Name*
-  Simple binary format for square images
-
-DF3
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-*Recognized File Extensions*
-  df3
-
-*Format Name*
-  PovRay Density file format
-
-DM3
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-*Recognized File Extensions*
-  dm3
-
-*Format Name*
-  Format used by Gatan Inc.'s  Digital Micrograph software
-
-DX
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-*Recognized File Extensions*
-  dx  
-
-*Format Name*
-  Format used by the OpenDX software package
-
-IPL
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-*Recognized File Extensions*
-  ipl  
-
-*Format Name*
-  Ditabis Micron Image Plate Scanner Format
-
-JPK
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-*Recognized File Extensions*
-  jpk
-
-*Format Name*
-  Format used by JPK Instruments AG's software (Customized Tiff format)
-
-MRC
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-*Recognized File Extensions*
-  map, ccp4, mrc   
-
-*Format Name*
-  Format used by the MRC software package
-
-NanoScope
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-*Recognized File Extensions*
-  mod
-
-*Format Name*
-  Format used by software from Veeco
-
-PNG
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-*Recognized File Extensions*
-  png
-
-*Format Name*
-  Portable Network Graphic image format
-
-Situs
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-*Recognized File Extensions*
-  situs, sit
-
-*Format Name*
-  Format used by the Situs software package
-
-SPI
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-*Recognized File Extensions*
-  spi
-
-*Format Name*
-  Format used by the Spider software package
-
-TIFF
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-*Recognized File Extensions*
-  tif, tiff
-
-*Format Name*
-  Tagged Image File Format
-
diff --git a/modules/io/doc/image_formats.rst b/modules/io/doc/image_formats.rst
new file mode 100644
index 0000000000000000000000000000000000000000..0764bb5735ae81c9c8d95a32ca499b33d8773862
--- /dev/null
+++ b/modules/io/doc/image_formats.rst
@@ -0,0 +1,258 @@
+Supported Image File Formats
+================================================================================
+
+CCP4
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Format used by the ccp4 software package
+
+* Recognized file extensions: *ccp4, map*  
+* Recognized based on content: *yes*
+* File import: *yes*
+* File export: *yes*
+
+.. class:: ost.io.CCP4(normalize_on_save=false, endianess_on_save=OST_LOCAL_ENDIAN)
+ 
+  :param normalize_on_save: Determines wether to renormalize image upon saving.
+  :type  normalize_on_save: bool
+  :param endianess_on_save: Byte order for saving.
+  :type  endianess_on_save: ost.io.Endianess
+
+
+DAT
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Simple binary format for square images
+
+* Recognized file extensions: *dat, img*  
+* Recognized based on content: *no*
+* File import: *yes*
+* File export: *yes*
+
+.. class:: ost.io.DAT(normalize_on_save=false, format=OST_DEFAULT_FORMAT, signed=false, endianess=OST_LOCAL_ENDIAN)
+ 
+  :param normalize_on_save: Determines wether to renormalize image upon saving.
+  :type  normalize_on_save: bool
+  :param format: Data format for loading and saving.
+  :type  format: ost.io.Format
+  :param signed: Determines wether data is interpreted as signed or unsigned values during loading and saving.
+  :type  signed: bool
+  :param endianess: Byte order for loading and saving.
+  :type  endianess: ost.io.Endianess
+
+DF3
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+PovRay Density file format
+
+* Recognized file extensions: *df3*  
+* Recognized based on content: *no*
+* File import: *no*
+* File export: *yes*
+
+.. class:: ost.io.DF3(normalize_on_save=false)
+ 
+  :param normalize_on_save: Determines wether to renormalize image upon saving.
+  :type  normalize_on_save: bool
+
+
+DM3
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Format used by Gatan Inc.'s  Digital Micrograph software
+
+* Recognized file extensions: *dm3*  
+* Recognized based on content: *yes*
+* File import: *yes*
+* File export: *no*
+
+.. class:: ost.io.DM3( )
+
+DX
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Format used by the OpenDX software package
+
+* Recognized file extensions: *dx*  
+* Recognized based on content: *no*
+* File import: *yes*
+* File export: *yes*
+
+.. class:: ost.io.DX(normalize_on_save=false)
+ 
+  :param normalize_on_save: Determines wether to renormalize image upon saving.
+  :type  normalize_on_save: bool
+
+
+IPL
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Ditabis Micron Image Plate Scanner Format
+
+* Recognized file extensions: *ipl*  
+* Recognized based on content: *yes*
+* File import: *yes*
+* File export: *yes*
+
+.. class:: ost.io.IPL(normalize_on_save=false, format=OST_DEFAULT_FORMAT)
+ 
+  :param normalize_on_save: Determines wether to renormalize image upon saving.
+  :type  normalize_on_save: bool
+  :param format: Data format for loading and saving.
+  :type  format: ost.io.Format
+
+JPK
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Format used by JPK Instruments AG's software (Customized Tiff format)
+
+* Recognized file extensions: *jpk*  
+* Recognized based on content: *no (jpk files without file extension are recognized as tif)*
+* File import: *yes*
+* File export: *yes*
+
+
+
+.. class:: ost.io.JPK(normalize_on_save=indeterminate, format=OST_DEFAULT_FORMAT, signed=false, phasecolor=false, subimage=-1)
+ 
+  :param normalize_on_save: Determines wether to renormalize image upon saving.
+  :type  normalize_on_save: tribool
+  :param format: Data format for loading and saving.
+  :type  format: ost.io.Format
+  :param signed: Determines wether data is interpreted as signed or unsigned values during loading and saving.
+  :type  signed: bool
+  :param phasecolor: Determines wether the phases of complex values are encoded as color information.
+  :type  phasecolor: bool
+  :param subimage: Determines which subimage is read from a multi-image jpk (-1 = default image).
+  :type  subimage: int
+
+MRC
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Format used by the MRC software package
+
+* Recognized file extensions: *mrc*  
+* Recognized based on content: *yes*
+* File import: *yes*
+* File export: *yes*
+
+.. class:: ost.io.MRC(normalize_on_save=false, subformat=MRC_NEW_FORMAT, endianess_on_save=OST_LOCAL_ENDIAN)
+ 
+  :param normalize_on_save: Determines wether to renormalize image upon saving.
+  :type  normalize_on_save: bool
+  :param subformat: Determines wether old style or new style mrc files should be saved.
+  :type  subformat: ost.io.Subformat
+  :param endianess_on_save: Byte order for saving.
+  :type  endianess_on_save: ost.io.Endianess
+  
+.. py:class:: ost.io.Subformat
+
+   .. py:attribute:: MRC_AUTO_FORMAT
+   .. py:attribute:: MRC_OLD_FORMAT
+   .. py:attribute:: MRC_NEW_FORMAT
+
+Nanoscope
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Format used by software from Veeco
+
+* Recognized file extensions: *mod*  
+* Recognized based on content: *no*
+* File import: *yes*
+* File export: *yes*
+
+.. class:: ost.io.Nanoscope(subimage=-1)
+ 
+  :param subimage: Determines which subimage is read from a multi-image nanoscope file (-1 = default image).
+  :type  subimage: int
+
+
+PNG
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Portable Network Graphic image format
+
+* Recognized file extensions: *png*  
+* Recognized based on content: *yes*
+* File import: *yes*
+* File export: *yes*
+
+.. class:: ost.io.PNG(normalize_on_save=false)
+ 
+  :param normalize_on_save: Determines wether to renormalize image upon saving.
+  :type  normalize_on_save: bool
+
+Situs
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Format used by the Situs software package
+
+* Recognized file extensions: *situs, sit*  
+* Recognized based on content: *no*
+* File import: *yes*
+* File export: *yes*
+
+.. class:: ost.io.Situs(normalize_on_save=false)
+ 
+  :param normalize_on_save: Determines wether to renormalize image upon saving.
+  :type  normalize_on_save: bool
+
+Spider
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Format used by the Spider software package
+
+* Recognized file extensions: *spi*  
+* Recognized based on content: *no*
+* File import: *yes*
+* File export: *yes*
+
+.. class:: ost.io.Spider(normalize_on_save=false, endianess_on_save=OST_LOCAL_ENDIAN)
+ 
+  :param normalize_on_save: Determines wether to renormalize image upon saving.
+  :type  normalize_on_save: bool
+  :param endianess_on_save: Byte order for saving.
+  :type  endianess_on_save: ost.io.Endianess
+
+TIF
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Tagged Image File Format
+
+* Recognized file extensions: *tif, tiff*  
+* Recognized based on content: *yes*
+* File import: *yes*
+* File export: *yes*
+
+.. class:: ost.io.TIF(normalize_on_save=indeterminate, format=OST_DEFAULT_FORMAT, signed=false, phasecolor=false, subimage=-1)
+ 
+  :param normalize_on_save: Determines wether to renormalize image upon saving.
+  :type  normalize_on_save: tribool
+  :param format: Data format for loading and saving.
+  :type  format: ost.io.Format
+  :param signed: Determines wether data is interpreted as signed or unsigned values during loading and saving.
+  :type  signed: bool
+  :param phasecolor: Determines wether the phases of complex values are encoded as color information.
+  :type  phasecolor: bool
+  :param subimage: Determines which subimage is read from a multi-image tif (-1 = default image).
+  :type  subimage: int
+
+Common parameters
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. py:class:: ost.io.Endianess
+
+   .. py:attribute:: OST_BIG_ENDIAN
+   .. py:attribute:: OST_LITTLE_ENDIAN
+   .. py:attribute:: OST_VAX_DATA
+   .. py:attribute:: OST_LOCAL_ENDIAN
+
+.. py:class:: ost.io.Format
+
+   .. py:attribute:: OST_BIT8_FORMAT
+   .. py:attribute:: OST_BIT16_FORMAT
+   .. py:attribute:: OST_BIT32_FORMAT
+   .. py:attribute:: OST_FLOAT_FORMAT
+   .. py:attribute:: OST_DOUBLE_FORMAT
+   .. py:attribute:: OST_DEFAULT_FORMAT
+
diff --git a/modules/io/doc/io.rst b/modules/io/doc/io.rst
index 41759d1987ef149bd53ed942fc21814b22ba43c0..1f97001cf35f461b18527ee99c446580e0d57b20 100644
--- a/modules/io/doc/io.rst
+++ b/modules/io/doc/io.rst
@@ -4,7 +4,9 @@
 .. toctree::
   :hidden:
   
-  formats
+  structure_formats
+  sequence_formats
+  image_formats
   mmcif
   profile
 
@@ -49,7 +51,7 @@ on the file extension.
     # SDF file explicitly
     ent=io.LoadEntity('file', 'sdf')
 
-  For a list of file formats supported by :func:`LoadEntity`, see :doc:`formats`.
+  For a list of file formats supported by :func:`LoadEntity`, see :doc:`structure_formats`.
   
   :raises: :exc:`~ost.io.IOUnknownFormatException` if the format string supplied 
       is not recognized or the file format can not be detected based on the 
@@ -145,7 +147,7 @@ Loading sequence or alignment files
     aln=io.LoadAlignment('algnm.aln',format="clustal")
     
   For a list of file formats supported by :func:`LoadSequence` see
-  :doc:`formats`.
+  :doc:`sequence_formats`.
   
   :raises: :exc:`~ost.io.IOUnknownFormatException` if the format string supplied 
       is not recognized or the file format can not be detected based on the 
@@ -158,13 +160,13 @@ Loading sequence or alignment files
 
   For a desription of how to use :func:`LoadSequenceList` please refer to 
   :func:`LoadSequence`. For a list of file formats supported by
-  :func:`LoadSequenceList` see :doc:`formats`.
+  :func:`LoadSequenceList` see :doc:`sequence_formats`.
 
 .. function:: LoadAlignment(filename, format='auto')
 
   For a desription of how to use :func:`LoadAlignment` please refer to 
   :func:`LoadSequence`. For a list of file formats supported by 
-  :func:`LoadAlignment` see :doc:`formats`.
+  :func:`LoadAlignment` see :doc:`sequence_formats`.
       
 Saving Sequence Data
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -185,7 +187,7 @@ Saving Sequence Data
     io.SaveAlignment(aln,'algnm.aln',format="clustal")
     
   For a list of file formats supported by :func:`SaveSequence` see
-  :doc:`formats`.
+  :doc:`sequence_formats`.
   
   :raises: :exc:`~ost.io.IOUnknownFormatException` if the format string supplied 
       is not recognized or the file format can not be detected based on the 
@@ -198,7 +200,7 @@ Saving Sequence Data
 
   For a desription of how to use :func:`SaveSequenceList` please refer to 
   :func:`SaveSequence`. For a list of file formats supported by 
-  :func:`SaveSequenceList` see :doc:`formats`.
+  :func:`SaveSequenceList` see :doc:`sequence_formats`.
 
 .. function:: SaveAlignment(aln, filename, format='auto')
 
@@ -206,7 +208,79 @@ Saving Sequence Data
   :func:`SaveSequence`.
   
   For a list of file formats supported by :func:`SaveAlignment` see 
-  :doc:`formats`.
+  :doc:`sequence_formats`.
+
+
+.. _img-io: 
+
+Density Maps
+--------------------------------------------------------------------------------
+
+Loading Density Maps
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. function:: LoadImage(filename)
+.. function:: LoadImage(filename, format)
+
+  Load density map from disk. If no format is given, the function guesses the 
+  filetype based on the extension of the file. If the extension is unknown or not present the
+  filetype will be guessed based on the content of the file if possible.
+  
+  :param filename: The filename
+  :type  filename: string
+  :param format: The file format
+
+  :raises: :exc:`~ost.io.IOUnknownFormatException` if the format supplied 
+      is not recognized or the file format can not be detected based on the 
+      file extension and content
+      
+      :exc:`~ost.io.IOException` if the import fails due to an erroneous or 
+      inexistent file
+
+  .. code-block:: python
+
+    # recognizes mrc file by file extension
+    ent=io.LoadImage('file.mrc')
+
+    # It is always possible to explicitely set the image format
+    # DAT file explicitly
+    ent=io.LoadImage('file', Dat())
+
+  For a list of file formats supported by :func:`LoadImage`, see :doc:`image_formats`.
+  
+
+
+
+Saving Density Maps
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. function:: SaveImage(image,filename)
+.. function:: SaveImage(image,filename, format)
+
+
+  Save density map to disk. If no format is set, the function guesses the 
+  filetype based on the file extension.
+  
+  :param image: The density map to be saved
+  :type  image: :class:`~ost.img.IMageHandle`
+  :param filename: The filename
+  :type  filename: string
+  :param format: The file format
+  
+  :raises: :exc:`~ost.io.IOUnknownFormatException` if the file format can not be detected based on the 
+      file extension
+
+  For a list of file formats supported by :func:`SaveImage`, see :doc:`image_formats`.
+  
+  .. code-block:: python
+
+    # load density map
+    image=io.LoadImage('density_map.ccp4')
+    # save density map
+    io.SaveImage(image, 'new_map.map', CCP4())
+
+
+
 
 
 .. testsetup:: io
diff --git a/modules/io/doc/mmcif.rst b/modules/io/doc/mmcif.rst
index 7e1c330a4dc4f0efd72e8eb424ef43539c4d4352..da1bed9d710d3ec33a4c7dfc16cbc02f6812348e 100644
--- a/modules/io/doc/mmcif.rst
+++ b/modules/io/doc/mmcif.rst
@@ -4,7 +4,7 @@ mmCIF File Format
 The mmCIF file format is an alternate container for structural entities, also
 provided by the PDB. Here we describe how to load those files and how to deal
 with information provided above the common PDB format (:class:`MMCifInfo`,
-:class:`MMCifInfoCitation`, :class:`MMCifInfoTransOperation`,
+:class:`MMCifInfoCitation`, :class:`MMCifInfoTransOp`,
 :class:`MMCifInfoBioUnit`, :class:`MMCifInfoStructDetails`).
 
 
@@ -160,6 +160,42 @@ of the annotation available.
 
   .. method:: GetStructDetails()
 
+  .. method:: AddMMCifPDBChainTr(cif_chain_id, pdb_chain_id)
+
+    Set up a translation for a certain mmCIF chain name to the traditional PDB
+    chain name.
+
+    :param cif_chain_id: atom_site.label_asym_id
+    :type cif_chain_id: :class:`str`
+    :param pdb_chain_id: atom_site.auth_asym_id
+    :type pdb_chain_id: :class:`str`
+
+  .. method:: GetMMCifPDBChainTr(cif_chain_id)
+
+    Get the translation of a certain mmCIF chain name to the traditional PDB
+    chain name.
+
+    :param cif_chain_id: atom_site.label_asym_id
+    :type cif_chain_id: :class:`str`
+    :returns: atom_site.auth_asym_id as :class:`str`
+
+  .. method:: AddPDBCMMCifhainTr(pdb_chain_id, cif_chain_id)
+
+    Set up a translation for a certain PDB chain name to the mmCIF chain name.
+
+    :param pdb_chain_id: atom_site.label_asym_id
+    :type pdb_chain_id: :class:`str`
+    :param cif_chain_id: atom_site.auth_asym_id
+    :type cif_chain_id: :class:`str`
+
+  .. method:: GetPDBMMCifChainTr(pdb_chain_id)
+
+    Get the translation of a certain PDB chain name to the mmCIF chain name.
+
+    :param pdb_chain_id: atom_site.auth_asym_id
+    :type pdb_chain_id: :class:`str`
+    :returns: atom_site.label_asym_id as :class:`str`
+
 .. class:: MMCifInfoCitation
 
   This stores citation information from an input file.
@@ -343,7 +379,7 @@ of the annotation available.
     See :attr:`authors`
 
 
-.. class:: MMCifInfoTransOperation
+.. class:: MMCifInfoTransOp
 
   This stores operations needed to transform an
   :class:`entity <ost.mol.EntityHandle>` into a bio unit.
@@ -411,6 +447,14 @@ of the annotation available.
   This stores information how a structure is to be assembled to form the
   bio unit.
 
+  .. attribute:: id
+
+    The id of a bio unit as given by the original mmCIF file.
+
+    Also available as :meth:`GetID`. May also be modified by :meth:`SetID`.
+
+    :type: :class:`str`
+
   .. attribute:: details
 
     Special aspects of the biological assembly. If not provided, resembles an
@@ -429,11 +473,19 @@ of the annotation available.
   .. attribute:: operations
 
     Translations and rotations needed to create the bio unit. Filled with
-    objects of class :class:`MMCifInfoTransOperation`.
+    objects of class :class:`MMCifInfoTransOp`.
 
     Also available as :meth:`GetOperations`. May be modified by
     :meth:`AddOperations`
 
+  .. method:: GetID()
+
+    See :attr:`id`
+
+  .. method:: SetID(id)
+
+    See :attr:`id`
+
   .. method:: GetDetails()
 
     See :attr:`details`
@@ -682,14 +734,14 @@ of the annotation available.
 
     See :attr:`replace_pdb_id`
 
-.. class:: MMCifINfoStructRef
+.. class:: MMCifInfoStructRef
 
   Holds the information of the struct_ref category. The category describes the 
   link of polymers in the mmCIF file to sequences stored in external databases 
   such as uniprot. The related categories ``struct_ref_seq`` and 
   ``struct_ref_seq_dif`` also list differences between the sequences of the 
-  deposited structure and the sequences in the database. A promintent example of 
-  such differences include point mutations and/or expression tags.
+  deposited structure and the sequences in the database. Two prominent examples 
+  of such differences are point mutations and/or expression tags.
 
   .. attribute:: db_name
 
@@ -734,6 +786,7 @@ of the annotation available.
 
   .. attribute:: seq_begin
                  seq_end
+
     The starting point (1-based) and end point of the aligned range in the 
     deposited sequence, respectively.
 
@@ -741,6 +794,7 @@ of the annotation available.
    
   .. attribute:: db_begin
                  db_end
+
     The starting point (1-based) and end point of the aligned range in the 
     database sequence, respectively.
 
@@ -769,8 +823,11 @@ of the annotation available.
   .. attribute:: details
 
     A textual description of the difference, e.g. point mutation, 
-    expressiontag, purification artifact.
+    expression tag, purification artifact.
 
     :type: :class:`str`
+
 ..  LocalWords:  cas isbn pubmed asu seqres conop ConnectAll casp COMPND OBSLTE
-..  LocalWords:  SPRSDE pdb func
+..  LocalWords:  SPRSDE pdb func autofunction exptl attr pdbx oper conf spr dif
+..  LocalWords:  biounits biounit uniprot UNP seqs AddMMCifPDBChainTr cif asym
+..  LocalWords:  auth GetMMCifPDBChainTr AddPDBCMMCifhainTr GetPDBMMCifChainTr
diff --git a/modules/io/doc/profile.rst b/modules/io/doc/profile.rst
index 8df9254e5aaf1ba3554b1e4fc8c9d39b442ed764..a0a43565e6631ca9c2adc28449930a9ffbe3656c 100644
--- a/modules/io/doc/profile.rst
+++ b/modules/io/doc/profile.rst
@@ -45,7 +45,7 @@ STRICT
 
     IOProfile(dialect='PDB', strict_hydrogens=False, quack_mode=False,
               fault_tolerant=False, join_spread_atom_records=False,
-              no_hetatms=False)
+              no_hetatms=False, bond_feasibility_check=True)
 
 SLOPPY:
 
@@ -55,7 +55,7 @@ SLOPPY:
 
     IOProfile(dialect='PDB', strict_hydrogens=False, quack_mode=True,
               fault_tolerant=True, join_spread_atom_records=False,
-              no_hetatms=False)
+              no_hetatms=False, bond_feasibility_check=True)
 
 CHARMM:
 
@@ -66,13 +66,13 @@ CHARMM:
 
     IOProfile(dialect='CHARMM', strict_hydrogens=False, quack_mode=True,
               fault_tolerant=True, join_spread_atom_records=True,
-              no_hetatms=False)
+              no_hetatms=False, bond_feasibility_check=True)
 
 
 The IOProfile Class
 --------------------------------------------------------------------------------
 
-.. class:: IOProfile(quack_mode=False, dialect='PDB', strict_hydrogens=False, fault_tolerant=False)
+.. class:: IOProfile(dialect='PDB', strict_hydrogens=False, quack_mode=False, join_spread_atom_records=False, no_hetatms=False, calpha_only=False, fault_tolerant=False, bond_feasibility_check=True)
 
   Aggregates flags that control the import of molecular structures.
 
@@ -123,3 +123,18 @@ The IOProfile Class
   
     If set to true, atom records belonging to the same residue are joined, even 
     if they do not appear sequentially in the PDB file.
+
+  .. attribute:: calpha_only
+
+    When set to true, forces the importers to only load atoms named CA. This is
+    most useful in combination with protein-only PDB files to speed up subsequent
+    processing and importing.
+
+  .. attribute:: bond_feasibility_check
+
+    When set to true, adds an additional distance feasibility to figure out if
+    two atoms should be connected. Atoms are only connected if they are within a
+    certain distance range. Set this to false to completely disable distance
+    checks for intra-residual bonds. Peptide bonds as well as bonds between
+    nucleotides involving more than one residue still make use of the distance
+    check to figure out of if the two residues should be connected.
diff --git a/modules/io/doc/sequence_formats.rst b/modules/io/doc/sequence_formats.rst
new file mode 100644
index 0000000000000000000000000000000000000000..63f01ffc9189be292ec376a7e124a6faa7fb5cfc
--- /dev/null
+++ b/modules/io/doc/sequence_formats.rst
@@ -0,0 +1,31 @@
+Supported Sequence File Formats
+================================================================================
+
+FASTA
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+*Recognized File Extensions*
+  fasta, fna, fas, fa, fsa
+  
+*Format Name*
+  fasta
+
+ClustalW
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+*Recognized File Extensions*
+  aln
+  
+*Format Name*
+  clustal
+
+Promod
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+*Recognized File Extensions*
+  ali
+  
+*Format Name*
+  promod
+  
+
diff --git a/modules/io/doc/structure_formats.rst b/modules/io/doc/structure_formats.rst
new file mode 100644
index 0000000000000000000000000000000000000000..46ceadba36c66f78f922865b8382818282baa786
--- /dev/null
+++ b/modules/io/doc/structure_formats.rst
@@ -0,0 +1,54 @@
+Supported Structure File Formats
+================================================================================
+
+The following file formats are supported by :func:`~ost.io.LoadEntity`. 
+
+
+
+CRD - CARD format file used by CHARMM
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+This trajectory file format is used by the CHARMM program suite (Molecular Modelling).
+
+*Recognized File Extensions*
+  crd
+
+PDB - Brookhaven PDB File
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Fine grained control over PDB file import is available via the 
+:func:`~ost.io.LoadPDB` function. The PDB importer supports loading gzipped PDB 
+files, which are auto-detected by the .gz file extension.
+
+*Recognized File Extensions*
+  ent, pdb, ent.gz, pdb.gz
+
+*Format Name*
+  pdb
+
+mmCIF - macromolecular Crystallographic Information File
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Fine grained control over mmCIFile import is available via the 
+:func:`~ost.io.LoadMMCIF` function. Most notably, this gives you access to the
+:class:`MMCifInfo` class. The mmCIF importer supports loading gzipped files,
+which are auto-detected by the .gz file extension.
+
+*Recognized File Extensions*
+  cif, cif.gz
+
+*Format Name*
+  mmcif
+
+PQR
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+*Recognized File Extensions*
+  pqr
+
+*Format Name*
+  pqr
+  
+SDF - Structured Data File
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+*Recognized File Extensions*
+  sdf
+  
diff --git a/modules/io/pymod/__init__.py b/modules/io/pymod/__init__.py
index 95ea418b344a21910a925f463151d34af4a8eb22..0d6d0e142147cfc499b279610081f5a0fba28610 100644
--- a/modules/io/pymod/__init__.py
+++ b/modules/io/pymod/__init__.py
@@ -109,7 +109,7 @@ def LoadPDB(filename, restrict_chains="", no_hetatms=None,
   :param join_spread_atom_records: If set, overrides the value of 
       :attr:`IOProfile.join_spread_atom_records`.
   
-  :param remote: If set to true, the method tries to load the pdb from the 
+  :param remote: If set to True, the method tries to load the pdb from the 
      remote pdb repository www.pdb.org. The filename is then interpreted as the 
      pdb id.
      
@@ -119,7 +119,7 @@ def LoadPDB(filename, restrict_chains="", no_hetatms=None,
   :param dialect: Specifies the particular dialect to use. If set, overrides 
     the value of :attr:`IOProfile.dialect`
 
-  :param seqres: Whether to read SEQRES records. If set to true, the loaded 
+  :param seqres: Whether to read SEQRES records. If set to True, the loaded 
     entity and seqres entry will be returned as a tuple.
 
   :type dialect: :class:`str`
@@ -137,8 +137,11 @@ def LoadPDB(filename, restrict_chains="", no_hetatms=None,
       return val1
   if isinstance(profile, str):
     prof=profiles[profile].Copy()
-  else:
+  elif isinstance(profile, IOProfile):
     prof=profile.Copy()
+  else:
+    raise TypeError('profile must be of type string or IOProfile, '+\
+                    'instead of %s'%type(profile))
   if dialect not in (None, 'PDB', 'CHARMM',):
     raise ValueError('dialect must be PDB or CHARMM')
   prof.calpha_only=_override(prof.calpha_only, calpha_only)
@@ -208,8 +211,11 @@ def SavePDB(models, filename, dialect=None,  pqr=False, profile='DEFAULT'):
     models=[models]
   if isinstance(profile, str):
     profile=profiles[profile].Copy()
-  else:
+  elif isinstance(profile, IOProfile):
     profile.Copy()
+  else:
+    raise TypeError('profile must be of type string or IOProfile, '+\
+                    'instead of %s'%type(profile))
   profile.dialect=_override(profile.dialect, dialect)
   writer=PDBWriter(filename, profile)
   writer.SetIsPQR(pqr)
@@ -238,7 +244,7 @@ LoadMapList=LoadImageList
 
 def LoadCHARMMTraj(crd, dcd_file=None, profile='CHARMM',
                    lazy_load=False, stride=1, 
-                   dialect=None):
+                   dialect=None, detect_swap=True,swap_bytes=False):
   """
   Load CHARMM trajectory file.
   
@@ -257,6 +263,10 @@ def LoadCHARMMTraj(crd, dcd_file=None, profile='CHARMM',
       set, overrides the value of the profile
   :param profile: The IO profile to use for loading the PDB file. See 
       :doc:`profile`.
+  :param detect_swap: if True (the default), then automatic detection of endianess
+      is attempted, otherwise the swap_bytes parameter is used
+  :param swap_bytes: is detect_swap is False, this flag determines whether bytes
+      are swapped upon loading or not
   """
   if not isinstance(crd, mol.EntityHandle):
     if dcd_file==None:
@@ -266,7 +276,7 @@ def LoadCHARMMTraj(crd, dcd_file=None, profile='CHARMM',
   else:
     if not dcd_file:
       raise ValueError("No DCD filename given")
-  return LoadCHARMMTraj_(crd, dcd_file, stride, lazy_load)
+  return LoadCHARMMTraj_(crd, dcd_file, stride, lazy_load, detect_swap, swap_bytes)
 
 def LoadMMCIF(filename, restrict_chains="", fault_tolerant=None, calpha_only=None, profile='DEFAULT', remote=False, strict_hydrogens=None, seqres=False, info=False):
   """
@@ -282,7 +292,7 @@ def LoadMMCIF(filename, restrict_chains="", fault_tolerant=None, calpha_only=Non
   :param fault_tolerant: Enable/disable fault-tolerant import. If set, overrides
      the value of :attr:`IOProfile.fault_tolerant`.
   
-  :param remote: If set to true, the method tries to load the pdb from the 
+  :param remote: If set to True, the method tries to load the pdb from the 
      remote pdb repository www.pdb.org. The filename is then interpreted as the 
      pdb id.
      
@@ -291,7 +301,7 @@ def LoadMMCIF(filename, restrict_chains="", fault_tolerant=None, calpha_only=Non
   :param strict_hydrogens: If set, overrides the value of 
      :attr:`IOProfile.strict_hydrogens`.
 
-  :param seqres: Whether to read SEQRES records. If set to true, the loaded 
+  :param seqres: Whether to read SEQRES records. If set to True, the loaded 
     entity and seqres entry will be returned as second item.
 
   :param info: Whether to return an info container with the other output.
diff --git a/modules/io/pymod/export_map_io.cc b/modules/io/pymod/export_map_io.cc
index afe494d1997b4d1720fe49592b35c36e51976980..4d49dad7f6f2e08de62a1fa39a65146d8cecd7bd 100644
--- a/modules/io/pymod/export_map_io.cc
+++ b/modules/io/pymod/export_map_io.cc
@@ -17,6 +17,7 @@
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 //------------------------------------------------------------------------------
 #include <boost/python.hpp>
+#include  <ost/io/img/map_io_df3_handler.hh>
 #include  <ost/io/img/map_io_dx_handler.hh>
 #include  <ost/io/img/map_io_spi_handler.hh>
 #include  <ost/io/img/map_io_mrc_handler.hh>
@@ -92,6 +93,11 @@ void export_map_io()
     .def("GetMaximum", &ImageFormatBase::GetMaximum)
     .def("GetMinimum", &ImageFormatBase::GetMinimum)
   ;
+  
+  class_<DF3, bases<ImageFormatBase> >("DF3", init<bool>(arg("normalize_on_save") = false))
+    .def("SetNormalizeOnSave", &DF3::SetNormalizeOnSave)
+    .def("GetNormalizeOnSave", &DF3::GetNormalizeOnSave)
+  ;
 
   class_<DX, bases<ImageFormatBase> >("DX", init<bool>(arg("normalize_on_save") = false))
     .def("SetNormalizeOnSave", &DX::SetNormalizeOnSave)
@@ -107,7 +113,7 @@ void export_map_io()
   ;
 
   class_<MRC, bases<ImageFormatBase> >("MRC", init<bool,Subformat,Endianess>
-           ((arg("normalize_on_save") = false,arg("subformat")=MRC_NEW_FORMAT,arg("endianess_on_save")=OST_LOCAL_ENDIAN)))
+           ((arg("normalize_on_save") = false,arg("subformat")=MRC_AUTO_FORMAT,arg("endianess_on_save")=OST_LOCAL_ENDIAN)))
     .def("SetNormalizeOnSave", &MRC::SetNormalizeOnSave)
     .def("GetNormalizeOnSave", &MRC::GetNormalizeOnSave)
     .def("SetSubformat", &MRC::SetSubformat)
@@ -116,6 +122,10 @@ void export_map_io()
     .def("GetEndianessOnSave", &MRC::GetEndianessOnSave)
   ;
 
+  class_<CCP4, bases<MRC> >("CCP4", init<bool,Endianess>
+           ((arg("normalize_on_save") = false,arg("endianess_on_save")=OST_LOCAL_ENDIAN)))
+  ;
+
   class_<DM3, bases<ImageFormatBase> >("DM3", init<>())
   ;
 
diff --git a/modules/io/pymod/export_mmcif_io.cc b/modules/io/pymod/export_mmcif_io.cc
index 70e6b46590148293e396cd5dc28b9766fdda3ce5..f2527066afca1d2d715c97dcc1413276eafa7a6b 100644
--- a/modules/io/pymod/export_mmcif_io.cc
+++ b/modules/io/pymod/export_mmcif_io.cc
@@ -181,12 +181,15 @@ void export_mmcif_io()
     .def("AddOperations", &MMCifInfoBioUnit::AddOperations)
     .def("GetOperations", make_function(&MMCifInfoBioUnit::GetOperations,
                                    return_value_policy<copy_const_reference>()))
+    .def("SetID", &MMCifInfoBioUnit::SetID)
+    .def("GetID", &MMCifInfoBioUnit::GetID)
     .add_property("details", &MMCifInfoBioUnit::GetDetails,
                   &MMCifInfoBioUnit::SetDetails)
     .add_property("chains", make_function(&MMCifInfoBioUnit::GetChainList,
                                    return_value_policy<copy_const_reference>()))
     .add_property("operations", make_function(&MMCifInfoBioUnit::GetOperations,
                                    return_value_policy<copy_const_reference>()))
+    .add_property("id", &MMCifInfoBioUnit::GetID, &MMCifInfoBioUnit::SetID)
   ;
 
   class_<MMCifInfoStructRefs>("MMCifInfoStructRefs", init<>())
@@ -277,6 +280,10 @@ void export_mmcif_io()
     .def("GetStructDetails", &MMCifInfo::GetStructDetails)
     .def("SetObsoleteInfo", &MMCifInfo::SetObsoleteInfo)
     .def("GetObsoleteInfo", &MMCifInfo::GetObsoleteInfo)
+    .def("AddMMCifPDBChainTr", &MMCifInfo::AddMMCifPDBChainTr)
+    .def("GetMMCifPDBChainTr", &MMCifInfo::GetMMCifPDBChainTr)
+    .def("AddPDBMMCifChainTr", &MMCifInfo::AddPDBMMCifChainTr)
+    .def("GetPDBMMCifChainTr", &MMCifInfo::GetPDBMMCifChainTr)
     .add_property("citations", make_function(&MMCifInfo::GetCitations,
                                    return_value_policy<copy_const_reference>()))
     .add_property("biounits", make_function(&MMCifInfo::GetBioUnits,
diff --git a/modules/io/pymod/wrap_io.cc b/modules/io/pymod/wrap_io.cc
index bc10f6f6a32fc6c9e6c3031e5abd94031f367d2e..87e4c66185d6096ffa35ae0bff4bdfbeb0a33159 100644
--- a/modules/io/pymod/wrap_io.cc
+++ b/modules/io/pymod/wrap_io.cc
@@ -112,7 +112,9 @@ BOOST_PYTHON_MODULE(_ost_io)
 
   def("LoadCRD", &LoadCRD);
   def("LoadCHARMMTraj_", &LoadCHARMMTraj, (arg("ent"), arg("trj_filename"), 
-      arg("stride")=1, arg("lazy_load")=false));
+                                           arg("stride")=1, arg("lazy_load")=false,
+                                           arg("detect_swap")=true,arg("swap_bytes")=false))
+;
   def("LoadMAE", &LoadMAE);
 
   export_pdb_io();
diff --git a/modules/io/src/img/map_io_dm3_handler.hh b/modules/io/src/img/map_io_dm3_handler.hh
index 89d5f87c1ca78f98b794dff63b45f508c236238f..97191f67ef9456c3c3d5e804ec9a8011454daea2 100644
--- a/modules/io/src/img/map_io_dm3_handler.hh
+++ b/modules/io/src/img/map_io_dm3_handler.hh
@@ -50,7 +50,7 @@ class DLLEXPORT_OST_IO MapIODm3Handler: public MapIOHandler
     static bool MatchType(const ImageFormatBase& type);
     static bool MatchSuffix(const String& loc);
     static bool ProvidesImport() { return true; }
-    static bool ProvidesExport() { return true; }
+    static bool ProvidesExport() { return false; }
     static String GetFormatName() { return String("Dm3"); }
     static String GetFormatDescription() {return String("Format used by Gatan Inc.'s  Digital Micrograph software");}
 
diff --git a/modules/io/src/img/map_io_ipl_handler.cc b/modules/io/src/img/map_io_ipl_handler.cc
index dd1fb2981a1f8c95f407331086508253a425f450..a61715908fba718173e7af9b347e7ca7a5f3eaa7 100644
--- a/modules/io/src/img/map_io_ipl_handler.cc
+++ b/modules/io/src/img/map_io_ipl_handler.cc
@@ -193,9 +193,8 @@ std::ostream& operator<< (std::ostream& out, const IPLHeader& h )
   out << "COMMENT = Created by OpenStructure \r\n";
   out << " \r\n";
   uint fillsize=h.header_length-out.tellp()+start_pos;
-  char empty[fillsize];
-  std::fill_n(empty,fillsize,0);
-  out.write(empty,fillsize);
+  std::vector<char> empty(fillsize,'\0');
+  out.write(&empty[0],fillsize);
   return out;
 }
 
@@ -256,9 +255,8 @@ std::istream& operator>> (std::istream& in, IPLHeader& h)
     }
   }while(in.peek()!=0);
   uint fillsize=h.header_length-in.tellg()+start_pos;
-  char empty[h.header_length];
-  std::fill_n(empty,fillsize,0);
-  in.read(empty,fillsize);
+  std::vector<char> empty(fillsize,'\0');
+  in.read(&empty[0],fillsize);
   return in;
 }
 
diff --git a/modules/io/src/mol/chemdict_parser.cc b/modules/io/src/mol/chemdict_parser.cc
index a44dc733803bf7b805d52b839c8d756b3941f929..654204dcd6591d31267b67bbde7b14ddabea19b4 100644
--- a/modules/io/src/mol/chemdict_parser.cc
+++ b/modules/io/src/mol/chemdict_parser.cc
@@ -105,6 +105,12 @@ void ChemdictParser::OnDataItem(const StarDataItem& item)
         std::cout << "unknown pdbx_type '" << type << "' for compound "
                   << compound_->GetID() << std::endl;
       }
+    } else if (item.GetName()==StringRef("name", 4)) {
+      compound_->SetName(item.GetValue().str());
+      if (compound_->GetName()==""){
+        std::cout << "unknown compound name, chemcomp.name field empty for compound: "
+                  << compound_->GetID() << std::endl;
+      }
     } else if (item.GetName()==StringRef("formula", 7)) {
       compound_->SetFormula(item.GetValue().str());
       if (compound_->GetFormula()=="H2 O") {
diff --git a/modules/io/src/mol/dcd_io.cc b/modules/io/src/mol/dcd_io.cc
index 5acc5bf4b79dcb0eca650ebe306f6d944cc78b68..f21b67afc6019bba35f68142d9fd2da8d1fc5802 100644
--- a/modules/io/src/mol/dcd_io.cc
+++ b/modules/io/src/mol/dcd_io.cc
@@ -56,7 +56,7 @@ struct DCDHeader {
   char hdrr[4];
   int icntrl[20];
   int ntitle;
-  char title[1024];
+  std::string title;
   int num, istep, freq,nstep;
   int t_atom_count,f_atom_count, atom_count;
 };
@@ -67,29 +67,46 @@ bool less_index(const mol::AtomHandle& a1, const mol::AtomHandle& a2)
 }
 
 bool read_dcd_header(std::istream& istream, DCDHeader& header, bool& swap_flag, 
-                     bool& ucell_flag, bool& gap_flag)
+                     bool& ucell_flag, bool& gap_flag, bool detect_swap, bool byte_swap)
 {
   if (!istream) {
     return false;
   }
   char dummy[4];  
   gap_flag=true;
-  swap_flag=false;
+  swap_flag = detect_swap ? false : byte_swap;
+
   ucell_flag=false;
   if(gap_flag) istream.read(dummy,sizeof(dummy));
   istream.read(header.hdrr,sizeof(char)*4);
+  if(header.hdrr[0]!='C' || header.hdrr[1]!='O' || header.hdrr[2]!='R' || header.hdrr[3]!='D') {
+    throw IOException("LoadCHARMMTraj: missing CORD magic in header");
+  }
+
   istream.read(reinterpret_cast<char*>(header.icntrl),sizeof(int)*20);
-  if(header.icntrl[1]<0 || header.icntrl[1]>1e8) {
-    // nonsense atom count, try swapping
-    swap_int(header.icntrl,20);
-    if(header.icntrl[1]<0 || header.icntrl[1]>1e8) {
-      throw(IOException("LoadCHARMMTraj: nonsense atom count in header"));
-    } else {
-      LOG_VERBOSE("LoadCHARMMTraj: byte-swapping");
-      swap_flag=true;
+
+  if(detect_swap) {
+    if(header.icntrl[1]<0 || header.icntrl[1]>1e7) {
+      // nonsense atom count, try byte swapping
+      swap_int(header.icntrl,20);
+      if(header.icntrl[1]<0 || header.icntrl[1]>1e7) {
+        // still weird? swap back and keep fingers crossed
+        LOG_WARNING("LoadCHARMMTraj: byte swap detection failed, trying to continue");
+        swap_int(header.icntrl,20);
+        swap_flag=false;
+      } else {
+        LOG_VERBOSE("LoadCHARMMTraj: byte-swapping (auto-detected)");
+        swap_flag=true;
+      }
+    }
+  } else {
+    if(byte_swap) {
+      LOG_VERBOSE("LoadCHARMMTraj: byte-swapping (manually set)");
     }
   }
 
+  LOG_VERBOSE("LoadCHARMMTraj: found " << header.icntrl[1] << " atoms");
+
   if(header.icntrl[19]!=0) { // CHARMM format
     ucell_flag=(header.icntrl[10]!=0);
     if(ucell_flag) {
@@ -112,8 +129,12 @@ bool read_dcd_header(std::istream& istream, DCDHeader& header, bool& swap_flag,
   if(swap_flag) swap_int(&header.ntitle,1);
   if(gap_flag) istream.read(dummy,sizeof(dummy));
 
-  istream.read(header.title,sizeof(char)*header.ntitle);
-  header.title[header.ntitle]='\0';
+  std::vector<char> title(header.ntitle+1);
+
+  istream.read(&title[0],sizeof(char)*header.ntitle);
+  header.title=std::string(&title[0],header.ntitle);
+  LOG_VERBOSE("LoadCHARMMTraj: title string [" << header.title << "]")
+  
   if(gap_flag) istream.read(dummy,sizeof(dummy));
   istream.read(reinterpret_cast<char*>(&header.t_atom_count),sizeof(int));
   if(swap_flag) swap_int(&header.t_atom_count,1);
@@ -230,7 +251,9 @@ bool read_frame(std::istream& istream, const DCDHeader& header,
   
 mol::CoordGroupHandle load_dcd(const mol::AtomHandleList& alist, // this atom list is already sorted!
                                const String& trj_fn,
-                               unsigned int stride)
+                               unsigned int stride,
+                               bool detect_swap,
+                               bool byte_swap)
 {
   std::ifstream istream(trj_fn.c_str(), std::ios::binary);
   if(!istream) {
@@ -242,7 +265,7 @@ mol::CoordGroupHandle load_dcd(const mol::AtomHandleList& alist, // this atom li
 
   DCDHeader header; 
   bool swap_flag=false, ucell_flag=false, gap_flag=false;
-  read_dcd_header(istream, header, swap_flag, ucell_flag, gap_flag);
+  read_dcd_header(istream, header, swap_flag, ucell_flag, gap_flag, detect_swap, byte_swap);
   if(alist.size() != static_cast<size_t>(header.t_atom_count)) {
     LOG_ERROR("LoadCHARMMTraj: atom count missmatch: " << alist.size() 
                << " in coordinate file, " << header.t_atom_count 
@@ -285,9 +308,10 @@ mol::CoordGroupHandle load_dcd(const mol::AtomHandleList& alist, // this atom li
 class  DCDCoordSource : public mol::CoordSource {
 public:
   DCDCoordSource(const mol::AtomHandleList& atoms, const String& filename, 
-                 uint stride): 
+                 uint stride, bool detect_swap, bool byte_swap): 
     mol::CoordSource(atoms), filename_(filename), 
-    stream_(filename.c_str(), std::ios::binary), loaded_(false), stride_(stride)
+    stream_(filename.c_str(), std::ios::binary), loaded_(false), stride_(stride),
+    detect_swap_(detect_swap), byte_swap_(byte_swap)
   {
     frame_count_=0;
     this->SetMutable(false);
@@ -295,7 +319,7 @@ public:
   }
     
   
-  virtual uint GetFrameCount() 
+  virtual uint GetFrameCount() const
   { 
     if (!frame_count_)
       const_cast<DCDCoordSource*>(this)->FetchFrame(0);
@@ -323,6 +347,7 @@ private:
   uint                 frame_count_;
   uint                 curr_frame_;
   uint                 stride_;
+  bool                 detect_swap_, byte_swap_;
   size_t               frame_start_;
   mol::CoordFramePtr   frame_;
 };
@@ -331,7 +356,7 @@ private:
 void DCDCoordSource::FetchFrame(uint frame)
 {
   if (!loaded_) {
-    read_dcd_header(stream_, header_, swap_flag_, ucell_flag_, gap_flag_);
+    read_dcd_header(stream_, header_, swap_flag_, ucell_flag_, gap_flag_, detect_swap_,byte_swap_);
     frame_start_=stream_.tellg();
     loaded_=true;
     frame_count_=header_.num/stride_;
@@ -354,17 +379,20 @@ typedef boost::shared_ptr<DCDCoordSource> DCDCoordSourcePtr;
 
 mol::CoordGroupHandle LoadCHARMMTraj(const mol::EntityHandle& ent,
                                      const String& trj_fn,
-                                     unsigned int stride, bool lazy_load)
+                                     unsigned int stride,
+                                     bool lazy_load,
+                                     bool detect_swap,
+                                     bool byte_swap)
 {
   mol::AtomHandleList alist(ent.GetAtomList());
   std::sort(alist.begin(),alist.end(),less_index);
   if (lazy_load) {
-    LOG_INFO("Importing CHARMM trajectory with lazy_load=true");
-    DCDCoordSource* source=new DCDCoordSource(alist, trj_fn, stride);
-    return mol::CoordGroupHandle(DCDCoordSourcePtr(source));
+    LOG_VERBOSE("LoadCHARMMTraj: importing with lazy_load=true");
+    DCDCoordSourcePtr source(new DCDCoordSource(alist, trj_fn, stride, detect_swap, byte_swap));
+    return mol::CoordGroupHandle(source);
   }
-  LOG_INFO("Importing CHARMM trajectory with lazy_load=false");  
-  return load_dcd(alist, trj_fn, stride);
+  LOG_VERBOSE("LoadCHARMMTraj: importing with lazy_load=false");  
+  return load_dcd(alist, trj_fn, stride, detect_swap, byte_swap);
 }
 
 namespace {
diff --git a/modules/io/src/mol/dcd_io.hh b/modules/io/src/mol/dcd_io.hh
index 5915de6f16b62f44621356b0fbc145dbcfaccb5f..dded28a462727caeffb9d396092c2334819d667a 100644
--- a/modules/io/src/mol/dcd_io.hh
+++ b/modules/io/src/mol/dcd_io.hh
@@ -36,9 +36,11 @@ namespace ost { namespace io {
     atom layout of the entity must match the trajectory file
 */
 mol::CoordGroupHandle DLLEXPORT_OST_IO LoadCHARMMTraj(const mol::EntityHandle& ent,
-                                                       const String& trj_filename,
-                                                       unsigned int stride=1,
-                                                       bool lazy_load=false);
+                                                      const String& trj_filename,
+                                                      unsigned int stride=1,
+                                                      bool lazy_load=false,
+                                                      bool detect_swap=true,
+                                                      bool byte_swap=false);
 
 
 /*! \brief export coord group as PDB file and DCD trajectory
diff --git a/modules/io/src/mol/mmcif_info.cc b/modules/io/src/mol/mmcif_info.cc
index c8565a2e809ff1f84b182b9f73e4cacd1866c509..29f0db7463188068b3584a49457126d7ec1601d0 100644
--- a/modules/io/src/mol/mmcif_info.cc
+++ b/modules/io/src/mol/mmcif_info.cc
@@ -22,6 +22,42 @@
 
 namespace ost { namespace io {
 
+void MMCifInfo::AddMMCifPDBChainTr(String cif, String pdb)
+{
+  std::map<String, String>::iterator tr_it = cif_2_pdb_chain_id_.find(cif);
+  if (tr_it != cif_2_pdb_chain_id_.end()) {
+    throw IOException("mmCIF chain id '"+ cif +"' is already mapped to '"+
+                      tr_it->second+"'.");
+  }
+  cif_2_pdb_chain_id_.insert(std::pair<String, String>(cif, pdb));
+}
+
+String MMCifInfo::GetMMCifPDBChainTr(String cif) const
+{
+  std::map<String, String>::const_iterator tr_it =
+    cif_2_pdb_chain_id_.find(cif);
+  if (tr_it == cif_2_pdb_chain_id_.end()) { return ""; }
+  return tr_it->second;
+}
+
+void MMCifInfo::AddPDBMMCifChainTr(String pdb, String cif)
+{
+  std::map<String, String>::iterator tr_it = pdb_2_cif_chain_id_.find(pdb);
+  if (tr_it != pdb_2_cif_chain_id_.end()) {
+    throw IOException("PDB chain id '"+ pdb +"' is already mapped to '"+
+                      tr_it->second+"'.");
+  }
+  pdb_2_cif_chain_id_.insert(std::pair<String, String>(pdb, cif));
+}
+
+String MMCifInfo::GetPDBMMCifChainTr(String pdb) const
+{
+  std::map<String, String>::const_iterator tr_it =
+    pdb_2_cif_chain_id_.find(pdb);
+  if (tr_it == pdb_2_cif_chain_id_.end()) { return ""; }
+  return tr_it->second;
+}
+
 void MMCifInfo::AddAuthorsToCitation(StringRef id, std::vector<String> list)
 {
   // find citation
diff --git a/modules/io/src/mol/mmcif_info.hh b/modules/io/src/mol/mmcif_info.hh
index 38e49f58bec9420e353088d8a7858908be887456..3eebf54b2369947c9d007e616c4d33c2f968750c 100644
--- a/modules/io/src/mol/mmcif_info.hh
+++ b/modules/io/src/mol/mmcif_info.hh
@@ -22,6 +22,7 @@
 #include <vector>
 #include <map>
 #include <boost/shared_ptr.hpp>
+#include <ost/seq/sequence_list.hh>
 #include <ost/geom/geom.hh>
 #include <ost/string_ref.hh>
 #include <ost/io/module_config.hh>
@@ -238,7 +239,16 @@ typedef boost::shared_ptr<MMCifInfoTransOp> MMCifInfoTransOpPtr;
 class DLLEXPORT_OST_IO MMCifInfoBioUnit {
 public:
   /// \brief Create a biounit.
-  MMCifInfoBioUnit(): details_("") {};
+  MMCifInfoBioUnit(): id_(""), details_("") {};
+
+  /// \brief Set id
+  ///
+  /// \param id id
+  void SetID(String id) { id_ = id; }
+  /// \brief Get id
+  ///
+  /// \return id
+  String GetID() const { return id_; }
 
   /// \brief Set details
   ///
@@ -274,6 +284,9 @@ public:
   }
 
   bool operator==(const MMCifInfoBioUnit& bu) const {
+    if (this->id_ != bu.id_) {
+      return false;
+    }
     if (this->details_ != bu.details_) {
       return false;
     }
@@ -314,6 +327,7 @@ public:
   }
 
 private:
+  String id_;                  ///< pdbx_struct_assembly.id
   String details_;             ///< pdbx_struct_assembly.details
   std::vector<String> chains_; ///< chains involved in this assembly
   std::vector<std::vector<MMCifInfoTransOpPtr> > operations_;
@@ -758,6 +772,30 @@ public:
   /// \return experiment resolution
   Real GetResolution() const { return resolution_; }
 
+  /// \brief Add a new mmCIF/ PDB chain name tuple.
+  ///
+  /// \param cif chain name as used by the mmCIF file (label_asym_id)
+  /// \param pdb chain name as used in the PDB file (auth_asym_id)
+  void AddMMCifPDBChainTr(String cif, String pdb);
+
+  /// \brief Get a PDB chain name for a CIF chain name
+  ///
+  /// \param cif chain name as used by the mmCIF file (label_asym_id)
+  /// \return chain name as used in the PDB file (auth_asym_id)
+  String GetMMCifPDBChainTr(String cif) const;
+
+  /// \brief Add a new PDB/ mmCIF chain name tuple.
+  ///
+  /// \param pdb chain name as used by the PDB file (auth_asym_id)
+  /// \param cif chain name as used in the mmCIF file (label_asym_id)
+  void AddPDBMMCifChainTr(String pdb, String cif);
+
+  /// \brief Get a CIF chain name for a PDB chain name
+  ///
+  /// \param pdb chain name as used by the mmCIF file (auth_asym_id)
+  /// \return chain name as used in the PDB file (label_asym_id)
+  String GetPDBMMCifChainTr(String pdb) const;
+
   /// \brief Add a biounit
   ///
   /// \param bu biounit to be added
@@ -835,6 +873,8 @@ private:
   std::vector<MMCifInfoBioUnit>  biounits_;   ///< list of biounits
   std::vector<MMCifInfoTransOpPtr> transops_;
 	MMCifInfoStructRefs            struct_refs_;
+  std::map<String, String> cif_2_pdb_chain_id_;
+  std::map<String, String> pdb_2_cif_chain_id_;
 };
 
 
diff --git a/modules/io/src/mol/mmcif_reader.cc b/modules/io/src/mol/mmcif_reader.cc
index 409902ab4391a66860aeed24d9b9aa3d6a9720a9..762939ca817800366ee487ffadef9da493f5103a 100644
--- a/modules/io/src/mol/mmcif_reader.cc
+++ b/modules/io/src/mol/mmcif_reader.cc
@@ -975,7 +975,7 @@ void MMCifReader::ParsePdbxStructAssemblyGen(const std::vector<StringRef>& colum
   MMCifBioUAssembly assembly;
   assembly.biounit = MMCifInfoBioUnit();
 
-  assembly.biounit.SetDetails(columns[indices_[ASSEMBLY_ID]].str());
+  assembly.biounit.SetID(columns[indices_[ASSEMBLY_ID]].str());
 
   std::vector<StringRef> tmp_chains=columns[indices_[ASYM_ID_LIST]].split(',');
   std::vector<StringRef>::const_iterator tc_it;
@@ -1539,6 +1539,7 @@ void MMCifReader::OnEndData()
   // process chain types
   std::vector<std::pair<mol::ChainHandle, String> >::const_iterator css;
   MMCifEntityDescMap::const_iterator edm_it;
+  String pdb_auth_chain_name;
   for (css = chain_id_pairs_.begin(); css != chain_id_pairs_.end(); ++css) {
     edm_it = entity_desc_map_.find(css->second);
 
@@ -1548,6 +1549,9 @@ void MMCifReader::OnEndData()
       if (edm_it->second.seqres.length() > 0) {
         seqres_.AddSequence(seq::CreateSequence(css->first.GetName(),
                                                 edm_it->second.seqres));
+        pdb_auth_chain_name = css->first.GetStringProp("pdb_auth_chain_name");
+        info_.AddMMCifPDBChainTr(css->first.GetName(), pdb_auth_chain_name);
+        info_.AddPDBMMCifChainTr(pdb_auth_chain_name, css->first.GetName());
       } else if (edm_it->second.type!=mol::CHAINTYPE_WATER) {
         // mark everything that doesn't have SEQRES as ligand and isn't of type 
         // water as ligand
@@ -1586,14 +1590,15 @@ void MMCifReader::OnEndData()
        bua_it != bu_assemblies_.end();
        ++bua_it) {
     // pair with pdbx_struct_assembly entry
-    buom_it = bu_origin_map_.find(bua_it->biounit.GetDetails());
+    buom_it = bu_origin_map_.find(bua_it->biounit.GetID());
     if (buom_it == bu_origin_map_.end()) {
       throw IOException(this->FormatDiagnostic(STAR_DIAG_ERROR,
                                                "No pdbx_struct_assembly.id '"+
-                                               bua_it->biounit.GetDetails() +
+                                               bua_it->biounit.GetID() +
                          "' found as requested by pdbx_struct_assembly_gen.")); 
     }
     bua_it->biounit.SetDetails(buom_it->second);
+    bua_it->biounit.SetID(buom_it->first);
 
     // pair with pdbx_struct_oper_list
     for (aol_it = bua_it->operations.begin();
diff --git a/modules/io/src/mol/pdb_reader.cc b/modules/io/src/mol/pdb_reader.cc
index be91fb54b5530413a1ccc3d51e51f8481c87b229..b4b097c1b8c8bdffcf29a3ccfac8ee9173a4abf0 100644
--- a/modules/io/src/mol/pdb_reader.cc
+++ b/modules/io/src/mol/pdb_reader.cc
@@ -355,17 +355,17 @@ void PDBReader::Import(mol::EntityHandle& ent,
           }
         }
         break;
-      case 'C':
-      case 'c':
-        if (curr_line.size()<20) {
-          LOG_TRACE("skipping entry");
-          continue;
-        }
-        if (IEquals(curr_line.substr(0, 6), StringRef("COMPND", 6))) {
-          LOG_TRACE("processing COMPND entry");
-          this->ParseCompndEntry(curr_line, line_num_);
-        }
-        break;
+         case 'C':
+         case 'c':
+           if (curr_line.size()<20) {
+             LOG_TRACE("skipping entry");
+             continue;
+           }
+           if (IEquals(curr_line.substr(0, 6), StringRef("COMPND", 6))) {
+             LOG_TRACE("processing COMPND entry");
+             this->ParseCompndEntry(curr_line, line_num_);
+           }
+          break;
       case 'E':
       case 'e':
         if (curr_line.size()<3) {
diff --git a/modules/io/src/mol/pdb_writer.cc b/modules/io/src/mol/pdb_writer.cc
index 3be9390b7d7a3763345364004cbe39853de4579c..d06a5228c5890f593c40c86ac9ceb4617f6ee379 100644
--- a/modules/io/src/mol/pdb_writer.cc
+++ b/modules/io/src/mol/pdb_writer.cc
@@ -443,7 +443,7 @@ void PDBWriter::Write(const mol::AtomHandleList& atoms)
   
 PDBWriter::~PDBWriter()
 {
-  out_ << "END   ";
+  out_ << "END   " << std::endl;
 }
 
 }}
diff --git a/modules/io/tests/CMakeLists.txt b/modules/io/tests/CMakeLists.txt
index 9ac4ba1342db1995749b5cce02a1c89fa278b536..64a31041525e12f4c1c0bc2ba906284b1a424a5e 100644
--- a/modules/io/tests/CMakeLists.txt
+++ b/modules/io/tests/CMakeLists.txt
@@ -15,6 +15,7 @@ set(OST_IO_UNIT_TESTS
 )
 if (ENABLE_IMG)
   list(APPEND OST_IO_UNIT_TESTS test_io_img.cc)
+  list(APPEND OST_IO_UNIT_TESTS test_exceptions.cc)
 endif()
 ost_unittest(MODULE io
              SOURCES "${OST_IO_UNIT_TESTS}"
diff --git a/modules/io/tests/test_exceptions.cc b/modules/io/tests/test_exceptions.cc
new file mode 100644
index 0000000000000000000000000000000000000000..2ed51ce3e61239424f4d3ce8b9ce2f77a3825b24
--- /dev/null
+++ b/modules/io/tests/test_exceptions.cc
@@ -0,0 +1,54 @@
+//------------------------------------------------------------------------------
+// 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: Andreas Schenk
+ */
+
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+#include <boost/test/auto_unit_test.hpp>
+
+#include <ost/io/load_map.hh>
+#include <ost/img/image.hh>
+#include <ost/io/io_exception.hh>
+
+using namespace ost;
+using namespace ost::io;
+
+
+BOOST_AUTO_TEST_SUITE( io );
+
+
+BOOST_AUTO_TEST_CASE(exception) 
+{
+  try {
+      BOOST_CHECK_THROW(ost::img::ImageHandle loadedimage=LoadImage("nonexistent.mrc"),IOException);
+  }catch(...){
+    BOOST_ERROR( "Failed to catch IOException." );
+  }
+  ost::img::ImageHandle ih=ost::img::CreateImage();
+  try {
+      BOOST_CHECK_THROW(SaveImage(ih,"nonexistent.ABC"),IOUnknownFormatException);
+  }catch(...){
+    BOOST_ERROR( "Failed to catch IOUnknownFormatException." );
+  }
+}
+
+BOOST_AUTO_TEST_SUITE_END();
diff --git a/modules/io/tests/test_io_pdb.cc b/modules/io/tests/test_io_pdb.cc
index 0deef37f1912ad07c256c8fa32c9f58fade28179..b0e54cdc37dacf167da076cc78b813c2ee7b4fab 100644
--- a/modules/io/tests/test_io_pdb.cc
+++ b/modules/io/tests/test_io_pdb.cc
@@ -17,6 +17,7 @@
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 //------------------------------------------------------------------------------
 #include <ost/test_utils/compare_files.hh>
+#include <ost/geom/vec_mat_predicates.hh>
 
 #include <ost/platform.hh>
 #include <ost/dyn_cast.hh>
@@ -1009,8 +1010,7 @@ BOOST_AUTO_TEST_CASE(test_pqr_read_atom)
   BOOST_CHECK_EQUAL(a1.GetResidue().GetName(), "MET");
   BOOST_CHECK_EQUAL(a1.GetResidue().GetChain().GetName(), " ");
 
-
-  BOOST_CHECK_EQUAL(a1.GetPos(), geom::Vec3(21.6, 35.3, 56.7));
+  BOOST_CHECK(vec3_is_close(a1.GetPos(), geom::Vec3(21.6, 35.3, 56.7),Real(0.1)));
   BOOST_CHECK_EQUAL(a1.GetElement(), "");
   BOOST_CHECK_EQUAL(a1.IsHetAtom(), false);
   BOOST_CHECK_CLOSE(a1.GetCharge(), Real(-0.3755), Real(1e-4));
@@ -1022,7 +1022,7 @@ BOOST_AUTO_TEST_CASE(test_pqr_read_atom)
   BOOST_CHECK_EQUAL(a2.GetResidue().GetName(), "ARG");
   BOOST_CHECK_EQUAL(a2.GetResidue().GetChain().GetName(), " ");
 
-  BOOST_CHECK_EQUAL(a2.GetPos(), geom::Vec3(23.9, 28.7, 56.5));
+  BOOST_CHECK(vec3_is_close(a2.GetPos(), geom::Vec3(23.9, 28.7, 56.5),Real(0.1)));
   BOOST_CHECK_EQUAL(a2.GetElement(), "");
   BOOST_CHECK_EQUAL(a2.IsHetAtom(), false);
   BOOST_CHECK_CLOSE(a2.GetCharge(), Real(0.2507), Real(1e-4));
diff --git a/modules/io/tests/test_mmcif_info.cc b/modules/io/tests/test_mmcif_info.cc
index b47b90951543c82d03af168681e3fcb4c02b8d0d..65e4fdaecb42ec54fb50d3c579f24ba8b7ae8adb 100644
--- a/modules/io/tests/test_mmcif_info.cc
+++ b/modules/io/tests/test_mmcif_info.cc
@@ -171,7 +171,11 @@ BOOST_AUTO_TEST_CASE(mmcif_info_structdetails)
   BOOST_CHECK(sd.GetTitle() == "More than a structure");
   BOOST_CHECK(sd.GetCASPFlag() == 'Y');
   BOOST_CHECK(sd.GetDescriptor() == "ADENYLATE KINASE");
+  #if OST_DOUBLE_PRECISION
+  BOOST_CHECK_CLOSE(sd.GetMass(), 1.0, 0.001);
+  #else
   BOOST_CHECK_CLOSE(sd.GetMass(), 1.0f, 0.001f);
+  #endif
   BOOST_CHECK(sd.GetMassMethod() == "Good Guess");
   BOOST_CHECK(sd.GetModelDetails() == "Even more guessing");
   BOOST_CHECK(sd.GetModelTypeDetails() == "MINIMIZED AVERAGE");
@@ -193,7 +197,21 @@ BOOST_AUTO_TEST_CASE(mmcif_info)
   info.SetResolution(1.9f);
 
   BOOST_CHECK(info.GetMethod() == StringRef("Cooking.", 8));
+  #if OST_DOUBLE_PRECISION
+  BOOST_CHECK_CLOSE(info.GetResolution(), 1.9, 0.001);
+  #else
   BOOST_CHECK_CLOSE(info.GetResolution(), 1.9f, 0.001f);
+  #endif
+
+  info.AddMMCifPDBChainTr("A", "B");
+  BOOST_CHECK_THROW(info.AddMMCifPDBChainTr("A", "B"), IOException);
+  BOOST_CHECK("B" == info.GetMMCifPDBChainTr("A"));
+  BOOST_CHECK("" == info.GetMMCifPDBChainTr("C"));
+
+  info.AddPDBMMCifChainTr("A", "B");
+  BOOST_CHECK_THROW(info.AddPDBMMCifChainTr("A", "B"), IOException);
+  BOOST_CHECK("B" == info.GetPDBMMCifChainTr("A"));
+  BOOST_CHECK("" == info.GetPDBMMCifChainTr("C"));
 
   BOOST_MESSAGE("  done.");
 }
diff --git a/modules/io/tests/test_mmcif_reader.cc b/modules/io/tests/test_mmcif_reader.cc
index e5c415f6df503c1866d9a43caf0709d5a2a248b9..eb9c852b521990d2195cabc379a82b5d4673dd31 100644
--- a/modules/io/tests/test_mmcif_reader.cc
+++ b/modules/io/tests/test_mmcif_reader.cc
@@ -338,7 +338,7 @@ BOOST_AUTO_TEST_CASE(mmcif_unknown_entity_type)
   BOOST_MESSAGE("          unknown type...");
   columns.pop_back();
   columns.push_back(StringRef("foo", 3));
-  BOOST_CHECK_THROW(tmmcif_p.ParseEntity(columns), std::runtime_error);
+  BOOST_CHECK_THROW(tmmcif_p.ParseEntity(columns), Error);
   BOOST_MESSAGE("          done.");
 
   BOOST_MESSAGE("  done.");
@@ -399,6 +399,14 @@ BOOST_AUTO_TEST_CASE(mmcif_entity_tests)
 
 BOOST_AUTO_TEST_CASE(mmcif_entity_poly_tests)
 {
+  SetPrefixPath(getenv("OST_ROOT"));
+  String lib_path=GetSharedDataPath()+"/compounds.chemlib";
+  conop::CompoundLibPtr compound_lib=conop::CompoundLib::Load(lib_path);
+  if (!compound_lib) {
+    std::cout << "WARNING: skipping SEQRES import unit test. "
+              << "Rule-based builder is required" << std::endl;
+    return;
+  }
   conop::Conopology::Instance().SetDefaultBuilder("RBB");
   BOOST_MESSAGE("  Running mmcif_entity_poly_tests...");
   mol::ChainHandle ch;
@@ -603,7 +611,7 @@ BOOST_AUTO_TEST_CASE(mmcif_citation_author_tests)
   std::ifstream s("testfiles/mmcif/atom_site.mmcif");
   IOProfile profile;
   MMCifReader mmcif_p(s, eh, profile);
-  BOOST_CHECK_NO_THROW(mmcif_p.Parse());
+  BOOST_REQUIRE_NO_THROW(mmcif_p.Parse());
 
   std::vector<String> authors =
     mmcif_p.GetInfo().GetCitations().back().GetAuthorList();
@@ -659,8 +667,12 @@ BOOST_AUTO_TEST_CASE(mmcif_refine_tests)
     std::ifstream s("testfiles/mmcif/atom_site.mmcif");
     IOProfile profile;
     MMCifReader mmcif_p(s, eh, profile);
-    BOOST_CHECK_NO_THROW(mmcif_p.Parse());
+    BOOST_REQUIRE_NO_THROW(mmcif_p.Parse());
+    #if OST_DOUBLE_PRECISION
+    BOOST_CHECK_CLOSE(mmcif_p.GetInfo().GetResolution(), 2.0, 0.001);
+    #else
     BOOST_CHECK_CLOSE(mmcif_p.GetInfo().GetResolution(), 2.0f, 0.001f);
+    #endif
   }
   BOOST_MESSAGE("         done.");
   BOOST_MESSAGE("         capturing fishy data lines...");
@@ -1208,7 +1220,7 @@ BOOST_AUTO_TEST_CASE(mmcif_testreader)
   mmcif_p.SetRestrictChains("A O C");
 
   BOOST_MESSAGE("          testing Parse()...");
-  BOOST_CHECK_NO_THROW(mmcif_p.Parse());
+  BOOST_REQUIRE_NO_THROW(mmcif_p.Parse());
 
   BOOST_REQUIRE_EQUAL(eh.GetChainCount(),    3);
   BOOST_REQUIRE_EQUAL(eh.GetResidueCount(), 14);
@@ -1242,9 +1254,11 @@ BOOST_AUTO_TEST_CASE(mmcif_testreader)
   BOOST_MESSAGE("          done.");
 
   BOOST_MESSAGE("          reading data fields which should not fail...");
+  BOOST_MESSAGE(mmcif_p.GetInfo().GetBioUnits().back().GetID());
   BOOST_CHECK(mmcif_p.GetInfo().GetMethod().str() == "Deep-fry");
   BOOST_CHECK(mmcif_p.GetInfo().GetBioUnits().back().GetDetails() ==
               "author_defined_assembly");
+  BOOST_CHECK(mmcif_p.GetInfo().GetBioUnits().back().GetID() == "2");
   BOOST_CHECK(mmcif_p.GetInfo().GetBioUnits().back().GetChainList().back() ==
               "F");
   MMCifInfoBioUnit bu = mmcif_p.GetInfo().GetBioUnits().back();
@@ -1255,7 +1269,11 @@ BOOST_AUTO_TEST_CASE(mmcif_testreader)
   BOOST_CHECK(sd.GetTitle() == "A Title");
   BOOST_CHECK(sd.GetCASPFlag() == 'Y');
   BOOST_CHECK(sd.GetDescriptor() == "ADENYLATE KINASE");
+  #if OST_DOUBLE_PRECISION
+  BOOST_CHECK_CLOSE(sd.GetMass(), 1.0, 0.001);
+  #else
   BOOST_CHECK_CLOSE(sd.GetMass(), 1.0f, 0.001f);
+  #endif
   BOOST_CHECK(sd.GetMassMethod() == "Good Guess");
   BOOST_CHECK(sd.GetModelDetails() == "Even better guessing");
   BOOST_CHECK(sd.GetModelTypeDetails() == "Guess");
diff --git a/modules/io/tests/testfiles/mmcif/atom_site.mmcif b/modules/io/tests/testfiles/mmcif/atom_site.mmcif
index ce890cf9d3be305019cbc431726433df8a06beee..68b2fbb5769c6e735ec7e30cb7311f002f9b3346 100644
--- a/modules/io/tests/testfiles/mmcif/atom_site.mmcif
+++ b/modules/io/tests/testfiles/mmcif/atom_site.mmcif
@@ -168,10 +168,10 @@ ATOM C  CB  ILE  A  13  . 1  21.236  34.463  16.492  1.00  22.67  .  13  21  ? A
 ATOM C  CG1 ILE  A  13  . 1  20.478  33.469  17.371  1.00  22.14  .  13  22  ? A
 ATOM C  CG2 ILE  A  13  . 1  21.357  33.986  15.016  1.00  21.75  .  13  23  ? A
 # - - - - data truncated for brevity - - - -
-HETATM C C1 APS  C  1  1  1  4.171  29.012   7.116  0.58  17.27  1 300  101 ? A
-HETATM C C2 APS  C  1  1  1  4.949  27.758   6.793  0.58  16.95  1 300  102 ? A
-HETATM O O3 APS  C  1  1  1  4.800  26.678   7.393  0.58  16.85  1 300  103 ? A
-HETATM N N4 APS  C  1  1  1  5.930  27.841   5.869  0.58  16.43  1 300  104 ? A
+HETATM C C1 APS  C  1  1  1  4.171  29.012   7.116  0.58  17.27  1 300  101 ? C
+HETATM C C2 APS  C  1  1  1  4.949  27.758   6.793  0.58  16.95  1 300  102 ? C
+HETATM O O3 APS  C  1  1  1  4.800  26.678   7.393  0.58  16.85  1 300  103 ? C
+HETATM N N4 APS  C  1  1  1  5.930  27.841   5.869  0.58  16.43  1 300  104 ? C
 # - - - - data truncated for brevity - - - -
 # chain to be ignored by 'restrict_chains' feature
 ATOM N  N   ILE  Z  1  . 1  23.664  33.855  16.884  1.00  22.08  .  1  17  ? Z
diff --git a/modules/mol/alg/doc/molalg.rst b/modules/mol/alg/doc/molalg.rst
index 020ef98b6395f2ec74629e6fd4f3c8c9e4a88dc0..9455d58dee59c029ea8d37e3d82804f63b625021 100644
--- a/modules/mol/alg/doc/molalg.rst
+++ b/modules/mol/alg/doc/molalg.rst
@@ -4,105 +4,375 @@
 .. module:: ost.mol.alg
    :synopsis: Algorithms operating on molecular structures
 
-.. function:: LocalDistTest(model, reference, tolerance, radius, local_ldt_property_string="")
+.. function:: LocalDistDiffTest(model, reference, tolerance, radius, local_ldt_property_string="")
   
-  This function calculates the agreement of local contacts between the model and 
-  the reference structure. The overlap is a number between zero and one, where 
-  one indicates complete agreement, zero indicates no agreement at all. This 
-  score is similar to the GDT, but does not require any superposition of the 
-  model and the reference.
+  This function calculates the agreement of local contacts between a model and 
+  a reference structure (Local Distance Difference Tests). The overlap is a number 
+  between zero and one, where one indicates complete agreement, zero indicates no 
+  agreement at all. This score is similar to the GDT, but does not require any 
+  superposition between the model and the reference.
   
-  The distance of atom pairs in the reference structure that are closer than a 
-  certain distance (radius) to each other is compared to the distance found in 
+  The distance of atom pairs in the reference structure, when shorter than a 
+  certain predefined distance (inclusion radius), is compared with the same distance in 
   the model. If the difference between these two distances is smaller than a 
-  threshold value (tolerance), the model and the reference agree. Missing atoms 
-  in the model are treated disagreement and thus lower the score.
+  threshold value (tolerance), the distance is considered conserverd in the model. Missing atoms 
+  in the model lead to non-conserved distances and thus lower the score.
   
-  For residue with symmetric sidechains (GLU, ASP, ARG, VAL, PHE, TYR), the 
-  naming of the atoms is ambigous. For these residues, the overlap of both 
-  possible solutions to the fixed atoms, that is, everything that is not 
-  ambigous is calculated. The solution that gives higher overlap is then used to 
-  calculate the actual overlap score.
-
-  If a string is passed as last parameter, the function computes the overlap score for
-  each residue and saves it as a float property in the ResidueHandle, with the passed string
-  as property name
+  The function only processes standard residues in the first chains of the model and of the reference
+  For residues with symmetric sidechains (GLU, ASP, ARG, VAL, PHE, TYR), the 
+  naming of the atoms is ambigous. For these residues, the function computes the Local Distance Difference 
+  Test score that each naming convention would generate when considering all non-ambigous surrounding atoms.
+  The solution that gives higher score is then picked to compute the final Local Difference
+  Distance Score for the whole model.
+
+  If a string is passed as last parameter to the function, the function computes the Local Difference Distance
+  Test score for each residue and saves it as a float property in the ResidueHandle, with the passed string
+  as property name. Additionally, the actual residue-based counts of the total checked distances and of 
+  the distances conserved in the model are stored as integer properties in the ResidueHandle. The property
+  names are respectively <passed string>_total and <passed string>_conserved.
+
+  :param model: the model structure
+  :type model: :class:`~ost.mol.EntityView`
+  :param reference: the reference structure
+  :type reference: :class:`~ost.mol.EntityView`
+  :param tolerance: the tolerance threshold used to determine distance conservation
+  :param radius: the inclusion radius in Angstroms
+  :param local_ldt_property_string: the base name for the ResidueHandle properties that store the local scores
+
+  :returns: the Local Distance Difference Test score
   
-.. function:: SuperposeFrames(frames, sel, from=0, to=-1, ref=-1)
-
-  This function superposes the frames of the given coord group and returns them
-  as a new coord group.
+.. function:: LocalDistDiffTest(model, distance_list, tolerance_list, sequence_separation=0,  local_ldt_property_string="")
   
-  :param frames: The source coord group.
-  :type frames: :class:`~ost.mol.CoordGroupHandle`
-  :param sel: An entity view containing the selection of atoms to be used for     
-    superposition. If set to an invalid view, all atoms in the coord group are 
-    used.
-  :type sel: :class:`ost.mol.EntityView`
-  :param from: index of the first frame
-  :param to: index of the last frame plus one. If set to -1, the value is set to 
-     the number of frames in the coord group
-  :param ref: The index of the reference frame to use for superposition. If set 
-     to -1, the each frame is superposed to the previous frame.
-     
-  :returns: A newly created coord group containing the superposed frames.
-
+  This function counts the conserved local contacts between the model and the reference structure
+  (these are the values needed to compute the Local Distance Difference Test score, see description of 
+  the previous function). It shares the same properties as the previous function, with some differences:
+  the thresholds can be more than one (the return counts are then the average over all thresholds), and
+  the input is not the reference structure, but already a list of distances to be checked for conservation
+
+  A sequence separation parameter can be passed to the function. If this happens, only distances between residues
+  whose separation is higher than the provided parameter are considered when computing the score
+
+  If a string is passed as the last parameter, residue-based counts and the value of the residue-based Local
+  Distance Difference Test score are saved in each ResidueHandle as int and float properties, as detailed in
+  the description of the previous function. 
+
+  :param model: the model structure
+  :type model: :class:`~ost.mol.EntityView`
+  :param distance_list: the list of distances to check for conservation
+  :type distance_list: :class:`~ost.mol.alg.GlobalRDMap`
+  :param tolerance_list: a list of thresholds used to determine distance conservation
+  :param sequence_separation: sequence separation parameter used when computing the score
+  :param local_ldt_property_string: the base name for the ResidueHandle properties that store the local scores
+
+  :returns: a tuple containing the counts of the conserved distances in the model and of all the checked 
+            distances
+
+.. function::  LocalDistDiffTest(alignment, tolerance, radius, ref_index=0, mdl_index=1);
+
+  Calculates the Local Distance Difference Test score (see previous functions) starting from an
+  alignment between a reference structure and a model. The AlignmentHandle parameter used to provide the 
+  alignment to the function needs to have the two structures attached to it. By default the first structure in the
+  alignment is considered to be the reference structure, and the second structure is taken as the model. This
+  can however be changed by passing the indexes of the two structures in the AlignmentHandle as parameters to the
+  function. 
+
+  BEWARE: This function uses the old implementation of the Local Distance Difference Test algorithm and
+  will give slightly different results from the new one.  
+
+  :param alignment: an alignment containing the sequences of the reference and of the model structures, with the structures themselves
+                    attached
+  :type alignment: :class:`~ost.seq.AlignmentHandle`
+  :param tolerance: a list of thresholds used to determine distance conservation
+  :param radius: the inclusion radius in Angstroms (to determine which distances are checked for conservation)
+  :param ref_index: index of the reference structure in the alignment 
+  :param mdl_index: index of the model in the alignment
+
+  :returns: the Local Distance Difference Test score
+
+.. function::  LDDTHA(model, distance_list, sequence_separation=0);
+
+  This function calculates the Local Distance Difference Test - High Accuracy score (see previous functions).
+  The High Accuracy name comes from the fact that the tolerance levels used by this function are the same
+  as the thresholds used by GDT-HA (0.5, 1, 2, and 4 Angstrom). 
+
+  The function only compares the input distance list to the first chain of the model structure
+
+  The local Local Distance Difference Test score values are stored in the ResidueHandles of the model passed to the 
+  function in a float property called "locallddt" 
+
+  A sequence separation parameter can be passed to the function. If this happens, only distances between residues
+  whose separation is higher than the provided parameter are considered when computing the score
+
+  :param model: the model structure
+  :type model: :class:`~ost.mol.EntityView`
+  :param distance_list: the list of distances to check for conservation
+  :type distance_list: :class:`~ost.mol.alg.GlobalRDMap`
+  :param sequence_separation: sequence separation parameter used when computing the score
+
+  :returns: the Local Distance Difference Test score
+
+.. function:: CreateDistanceList(reference, radius);
+.. function:: CreateDistanceListFromMultipleReferences(reference_list, tolerance_list, sequence_separation, radius);
+
+  Both these functions create lists of distances to be checked during a Local Distance Difference Test
+  (see description of the functions above). 
+
+  Both functions process only standard residues present in the first chain of the reference structures.
+
+  The only difference between the two functions is that one takes a single reference structure and the other
+  a list of reference structures. The structures in the list have to be properly prepared before being passed 
+  to the function. Corresponding residues in the structures must have the same residue number, the same chain name,
+  etc. Gaps are allowed and automatically dealt with: if information about a distance is present in at least one of
+  the structures, it will be considered.  
+
+  If a distance between two atoms is shorter than the inclusion radius in all structures in which the two atoms are
+  present, it is included in the list. However, if the distance is longer than the inclusion radius in at least
+  one of the structures, it is not considered to be a local interaction and is excluded from the list.
+
+  The multiple-reference function takes care of residues with ambigous symmetric sidechains. To decide which naming
+  convention to use, the function computes a Local Distance Difference Test score for  each reference against the
+  first reference structure in the list, using only non ambigously-named atoms. It picks then the naming convention
+  that gives the highest score, guaranteeing that all references are processed with the correct atom names.
+
+  The cutoff list that will later be used to compute the Local Distance Difference Test score and the sequence
+  separation parameter must be passed to the multi-reference function. These parameters do not influence the output
+  distance list, which always includes all distances within the provided radius (to make it consistent with the
+  single-reference corresponding function). However, the parameters are used when dealing with the naming convention
+  of residues with ambiguous nomenclature.
+
+  :param reference: a reference structure from which distances are derived
+  :type reference: :class:`~ost.mol.EntityView`
+  :param reference_list: a list of  of reference structures from which distances are derived
+  :type reference_list: list of :class:`~ost.mol.EntityView`
+  :param tolerance_list: a list of thresholds used to determine distance conservation when computing the LDDT score
+  :param sequence_separation: sequence separation parameter used when computing the LDDT score
+  :param radius: inclusion radius (in Angstroms) used to determine the distances included in the list
   
-.. function:: SuperposeFrames(frames, sel, ref_view, from=0, to=-1)
-
-  Same as SuperposeFrames above, but the superposition is done on a reference
-  view and not on another frame of the trajectory.
-  
-  :param frames: The source coord group.
-  :type frames: :class:`~ost.mol.CoordGroupHandle`
-  :param sel: An entity view containing the selection of atoms of the frames to be used for     
-    superposition.
-  :type sel: :class:`ost.mol.EntityView`
-  :param ref_view: The reference view on which the frames will be superposed. The number
-    of atoms in this reference view should be equal to the number of atoms in sel.
-  :type ref_view: :class:`ost.mol.EntityView`
-  :param from: index of the first frame
-  :param to: index of the last frame plus one. If set to -1, the value is set to 
-     the number of frames in the coord group     
+  :returns: class `~ost.mol.alg.GlobalRDMap`
   
-  :returns: A newly created coord group containing the superposed frames.
+.. class:: UniqueAtomIdentifier
 
-.. autofunction:: ParseAtomNames
+  Object containing enough information to uniquely identify an atom in a structure
 
-.. autofunction:: MatchResidueByNum
+  .. method:: UniqueAtomIdentifier(chain,residue_number,residue_name,atom_name)
+    
+    Creates an UniqueAtomIdentifier object starting from relevant atom information
 
-.. autofunction:: MatchResidueByIdx
+    :param chain: a string containing the name of the chain to which the atom belongs
+    :param residue_number: the number of the residue to which the atom belongs 
+    :type residue_number: :class:`~ost.mol.ResNum`
+    :param residue_name: a string containing the name of the residue to which the atom belongs
+    :param atom_name: a string containing the name of the atom
 
-.. autofunction:: MatchResidueByLocalAln
+  .. method:: GetChainName() 
 
-.. autofunction:: MatchResidueByGlobalAln
+    Returns the name of the chain to which the atom belongs, as a String  
 
-.. autofunction:: Superpose
+  .. method:: GetResNum() 
 
+    Returns the number of the residue the atom belongs to, as a :class:`~ost.mol.ResNum` object
+
+  .. method:: GetResidueName()
+    
+     Returns the name of the residue to which the atom belongs, as a String
+ 
+  .. method:: GetAtomName()
+
+     Returns the name of the atom, as a String
+
+.. class:: ResidueRDMap
+
+  Dictionary-like object containing the a list of distances that originate from the a single residue residue, to
+  check during a run of the Local Distance Difference Test algorithm 
+
+.. class:: GlobalRDMap
+
+  Dictionary-like object containing all the :class:`~ost.mol.alg.ResidueRDMap` objects related to residues
+  of a single structure
+  
+.. function: PrintResidueRDMap(residue_distance_list)
+
+  Prints to standard output all the distances contained in a :class:`~ost.mol.ResidueRDMap` object 
+
+.. function: PrintGlobalRDMap(global_distance_list)
+
+  Prints to standard output all the distances contained in each of the :class:`~ost.mol.ResidueRDMap` objects that
+  make up a :class:`~ost.mol.GlobalRDMap` object
+
+
+.. _steric-clashes:
 
 Steric Clashes
 --------------------------------------------------------------------------------
 
-The following function detects steric clashes in atomic structures. Two atoms are clashing if their euclidian distance is smaller than a threshold value. The threshold values are calculated from high-resolution X-ray structures for each possible element pair. The value is chosen such that 99.99% of observed distances between 0 and 5 Angstroem are above the threshold.
+The following function detects steric clashes in atomic structures. Two atoms are clashing if their euclidian distance is smaller than a threshold value (minus a tolerance offset). 
 
+.. function:: FilterClashes(entity, clashing_distances, always_remove_bb=False)
 
-.. function:: FilterClashes(ent, tolerance=0.0)
+  This function filters out residues with non-bonded clashing atoms. If the clashing atom 
+  is a backbone atom, the complete residue is removed from the structure, if the atom is part of 
+  the sidechain, only the sidechain atoms are removed. This behavior is changed 
+  by the always_remove_bb flag: when the flag is set to True the whole residue is removed even if
+  a clash is just detected in the side-chain.
+
+  The function performs the filtering directly on the the entity which is passed as an argument. The entity
+  gets altered by the function.
+  
+  Two atoms are defined as clashing if their distance is shorter than the reference distance minus a tolerance
+  threshold. The information about the clashing distances and the tolerance thresholds for all possible pairs of 
+  atoms is passed to the function as a parameter
 
-  This function filters out residues with clashing atoms. If the clashing atom 
-  is a backbone atom, the complete residue is removed, if the atom is part of 
-  the sidechain, only the sidechain atoms are removed.
+  Hydrogen and deuterium atoms are ignored by this function.
   
-  Hydrogen and deuterium atoms are ignored.
+  :param entity: The input entity
+  :type entity: :class:`~ost.mol.EntityView` or :class:`~ost.mol.EntityHandle`
+  :param clashing_distances: information about the clashing distances
+  :type clashing_distances: :class:`~ost.mol.alg.ClashingDistances`
+  :param always_remove_bb: if set to True, the whole residue is removed even if the clash happens in the side-chain
+
+  :returns: The filtered :class:`~ost.mol.EntityView`
+
+.. function:: CheckStereoChemistry(entity,bond_stats,angle_stats,bond_tolerance,angle_tolerance,always_remove_bb=False)
+
+  This function filters out residues with severe stereo-chemical violations. If the violation 
+  involves a backbone atom, the complete residue is removed from the structure, if it involves an atom that is 
+  part of the sidechain, only the sidechain is removed. This behavior is changed 
+  by the always_remove_bb flag: when the flag is set to True the whole residue is removed even if
+  a violation is just detected in the side-chain
+
+  The function performs the filtering directly on the the entity which is passed as an argument. The entity
+  gets altered by the function.
   
-  :param ent: The input entity
-  :type ent: :class:`~ost.mol.EntityView` or :class:`~ost.mol.EntityHandle`
-  :param tolerance: The tolerance in (Angstroem) is substracted from the 
-     thresholds calculated from high resolution X-ray structures to make the 
-     function less pedantic. Negative values are also allowed and make the 
-     function more stringent.
+  A violation is defined as a bond length that lies outside of the range: [mean_length-std_dev*bond_tolerance <-> meanlength+std_dev*bond_tolerance] or an angle width lying outside of the range [mean_width-std_dev*angle_tolerance <-> mean_width+std_dev*angle_tolerance ]. The information about the mean lengths and widths and the corresponding standard deviations is passed to the function using two parameters.
+
+  Hydrogen and deuterium atoms are ignored by this function.
+
+  :param entity: The input entity
+  :type entity: :class:`~ost.mol.EntityView` or :class:`~ost.mol.EntityHandle`
+  :param bond_stats: statistics about bond lengths
+  :type bond_stats: :class:`~ost.mol.alg.StereoChemicalParams`
+  :param angle_stats: statistics about angle widths
+  :type angle_stats: :class:`~ost.mol.alg.StereoChemicalParams`
+  :param bond_tolerance: tolerance for bond lengths (in standard deviations)
+  :param angle_tolerance: tolerance for angle widths (in standard deviations)£
+  :param always_remove_bb: if set to True, the whole residue is removed even if a violation in just detected in the side-chain
 
   :returns: The filtered :class:`~ost.mol.EntityView`
 
+.. class:: ClashingDistances
+
+  Object containing information about clashing distances between non-bonded atoms
+
+  .. method:: ClashingDistances()
+
+    Creates an empty distance list
+
+  .. method:: SetClashingDistance(ele1,ele2, clash_distance, tolerance)
+
+    Adds or replaces an entry in the list
+
+    :param ele1: string containing the first element's name 
+    :param ele2: string containing the second element's name 
+    :param clash_distance: minimum clashing distance (in Angstroms)
+    :param tolerance: tolerance threshold (in Angstroms)
+
+  .. method GetClashingDistance()
+
+     Recovers a reference distance and a tolerance threshold from the list
+
+    :param ele1: string containing the first element's name 
+    :param ele2: string containing the second element's name 
+
+    :returns: a tuple containing the minimum clashing distance and the tolerance threshold
+
+  .. method::  GetMaxAdjustedDistance()
+ 
+    Returns the longest clashing distance in the list, after adjustment with tolerance threshold    
+
+  .. method:: IsEmpty()
+
+    Returns True if the list is empty (i.e. in an invalid, useless state)
+ 
+  .. method:: PrintAllDistances()
+
+    Prints all distances in the list to standard output
+
+
+.. class:: StereoChemicalParams
+
+  Object containing stereo-chemical information about bonds and angles. For each item (bond or angle
+  in a specific residue), stores the mean and standard deviation 
+
+  .. method:: StereoChemicalParams()
+
+    Creates an empty parameter list
+
+  .. method:: SetParam(item, residue, mean, standard_dev)
+
+    Adds or replaces an entry in the list
+
+    :param item: string defining a bond (format: X-Y) or an angle (format:X-Y-Z), where X,Y an Z are atom names 
+    :param residue: string containing the residue type the information pertains to 
+    :param mean: mean bond length or angle width
+    :param standard_dev: standard deviation of the bond length or of the angle width
+
+  .. method GetParam(item,residue)
+
+     Recovers an entry from the list, 
+
+    :param item: string defining a bond (format: X-Y) or an angle (format:X-Y-Z), where X,Y an Z are atom names 
+    :param residue: string containing the residue type the item information pertains to 
+
+    :returns: a tuple containing the mean length or width and the standard deviation
+
+  .. method ContainsParam(item,residue)
+
+    Checks if a specific entry is present in the list 
+
+    :param item: string defining a bond (format: X-Y) or an angle (format:X-Y-Z), where X,Y an Z are atom names 
+    :param residue: string containing the residue type the information pertains to 
+
+    :returns: True if the list contains an entry corresponding to the correct item and residue, False if it does not
+
+  .. method:: IsEmpty()
+
+    Returns True if the list is empty (i.e. in an invalid, useless state)
+ 
+  .. method:: PrintAllParameters()
+
+    Prints all distances in the list to standard output  
+
+.. function:: FillClashingDistances(file_content)
+.. function:: FillBondStereoChemicalParams(file_content)
+.. function:: FillAngleStereoChemicalParams(file_content)
+
+  These three functions fill a list of reference clashing distances, a list of stereo-chemical parameters for 
+  bonds and a list of stereo-chemical parameters for angles, respectively, starting from a the content of 
+  parameter file. The content of the file is passed to the function as a list of strings, each containing
+  a line from the parameter file
+
+  :returns: :class:`~ost.mol.alg.ClashingDistances` and :class:`~ost.mol.alg.StereoChemicalParams` respectively
+
+.. function:: FillClashingDistancesFromFile(filename)
+.. function:: FillBondStereoChemicalParamsFromFile(filename)
+.. function:: FillAngleStereoChemicalParamsFromFile(filename)
+
+  These three functions fill a list of reference clashing distances, a list of stereo-chemical parameters for 
+  bonds and a list of stereo-chemical parameters for angles, respectively, starting from a file. The filename 
+  passed to the function can be a full path.
+
+  :returns: :class:`~ost.mol.alg.ClashingDistances` and :class:`~ost.mol.alg.StereoChemicalParams` respectively
+
+.. function:: DefaultClashingDistances()
+.. function:: DefaultBondStereoChemicalParams()
+.. function:: DefaultAngleStereoChemicalParams()
+
+  These three functions fill a list of reference clashing distances, a list of stereo-chemical parameters for 
+  bonds and a list of stereo-chemical parameters for angles, respectively, using the default parameter file
+  distributed with OpenStructure.
+
+  :returns: :class:`~ost.mol.alg.ClashingDistances` and :class:`~ost.mol.alg.StereoChemicalParams` respectively
+
 
 .. _traj-analysis:
 
@@ -230,8 +500,6 @@ used to skip frames in the analysis.
   :param stride: Size of the increment of the frame's index between two 
       consecutive frames analyzed.
 
-
-
 .. function:: AnalyzeMinDistance(traj, view1, view2, stride=1)
 
   This function extracts the minimal distance between two sets of atoms 
@@ -278,3 +546,53 @@ used to skip frames in the analysis.
   :param stride: Size of the increment of the frame's index between two 
      consecutive frames analyzed.  
 
+.. function:: SuperposeFrames(frames, sel, from=0, to=-1, ref=-1)
+
+  This function superposes the frames of the given coord group and returns them
+  as a new coord group.
+  
+  :param frames: The source coord group.
+  :type frames: :class:`~ost.mol.CoordGroupHandle`
+  :param sel: An entity view containing the selection of atoms to be used for     
+    superposition. If set to an invalid view, all atoms in the coord group are 
+    used.
+  :type sel: :class:`ost.mol.EntityView`
+  :param from: index of the first frame
+  :param to: index of the last frame plus one. If set to -1, the value is set to 
+     the number of frames in the coord group
+  :param ref: The index of the reference frame to use for superposition. If set 
+     to -1, the each frame is superposed to the previous frame.
+     
+  :returns: A newly created coord group containing the superposed frames.
+
+.. function:: SuperposeFrames(frames, sel, ref_view, from=0, to=-1)
+
+  Same as SuperposeFrames above, but the superposition is done on a reference
+  view and not on another frame of the trajectory.
+  
+  :param frames: The source coord group.
+  :type frames: :class:`~ost.mol.CoordGroupHandle`
+  :param sel: An entity view containing the selection of atoms of the frames to be used for     
+    superposition.
+  :type sel: :class:`ost.mol.EntityView`
+  :param ref_view: The reference view on which the frames will be superposed. The number
+    of atoms in this reference view should be equal to the number of atoms in sel.
+  :type ref_view: :class:`ost.mol.EntityView`
+  :param from: index of the first frame
+  :param to: index of the last frame plus one. If set to -1, the value is set to 
+     the number of frames in the coord group     
+  
+  :returns: A newly created coord group containing the superposed frames.
+
+.. autofunction:: ParseAtomNames
+
+.. autofunction:: MatchResidueByNum
+
+.. autofunction:: MatchResidueByIdx
+
+.. autofunction:: MatchResidueByLocalAln
+
+.. autofunction:: MatchResidueByGlobalAln
+
+.. autofunction:: Superpose
+
diff --git a/modules/mol/alg/pymod/__init__.py b/modules/mol/alg/pymod/__init__.py
index 3d7901d005e4328a1c730c1fd2e5a493360cce16..126d0196f2d6ff25148a6724df5dd63a1e764d6a 100644
--- a/modules/mol/alg/pymod/__init__.py
+++ b/modules/mol/alg/pymod/__init__.py
@@ -1,5 +1,55 @@
+import os.path
 from _ost_mol_alg import *
 from ost.mol.alg.superpose import *
 import ost.mol.alg.trajectory_analysis
 import ost.mol.alg.structure_analysis
 import ost.mol.alg.helix_kinks
+
+# Fills a list of reference clashing distances from a file (requires a path to the file)
+def FillClashingDistancesFromFile(filename,default_clashing_distance,default_tolerance):
+  fh=open(filename,'r')
+  lines=fh.readlines()
+  fh.close()
+  return FillClashingDistances(lines,default_clashing_distance,default_tolerance)
+
+# Fills a list of bond stereo-chemical statistics from a file (requires a path to the file)
+def FillBondStereoChemicalParamsFromFile(filename):
+  fh=open(filename,'r')
+  lines=fh.readlines()
+  fh.close()
+  return FillBondStereoChemicalParams("Bond",lines)
+
+# Fills a list of angle stereo-chemical statistics from a file (requires a path to the file)
+def FillAngleStereoChemicalParamsFromFile(filename):
+  fh=open(filename,'r')
+  lines=fh.readlines()
+  fh.close()
+  return FillAngleStereoChemicalParams("Angle",lines)
+
+# Returns the default list of reference clashing distances (from the default OpenStructure parameter file)
+def DefaultClashingDistances():
+  shared_path=ost.GetSharedDataPath()	
+  filename=os.path.join(shared_path,'stereo_chemical_props.txt')
+  fh=open(filename,'r')
+  lines=fh.readlines()
+  fh.close()
+  return FillClashingDistances(lines,1.5,0.0)
+
+# Returns the default list of bond stereo-chemical statistics (from the default OpenStructure parameter file)
+def DefaultBondStereoChemicalParams():
+  shared_path=ost.GetSharedDataPath()	
+  filename=os.path.join(shared_path,'stereo_chemical_props.txt')
+  fh=open(filename,'r')
+  lines=fh.readlines()
+  fh.close()
+  return FillStereoChemicalParams("Bond",lines)
+
+# Returns the default list of angle stereo-chemical statistics (from the default OpenStructure parameter file)
+def DefaultAngleStereoChemicalParams():
+  shared_path=ost.GetSharedDataPath()	
+  filename=os.path.join(shared_path,'stereo_chemical_props.txt')
+  fh=open(filename,'r')
+  lines=fh.readlines()
+  fh.close()
+  return FillStereoChemicalParams("Angle",lines)
+
diff --git a/modules/mol/alg/pymod/wrap_mol_alg.cc b/modules/mol/alg/pymod/wrap_mol_alg.cc
index c7c3e1c3b3b62e46de87b21ff5a118da5808cbcb..72a67e4d09299d1e0ce88c0d839e2fe1b599492a 100644
--- a/modules/mol/alg/pymod/wrap_mol_alg.cc
+++ b/modules/mol/alg/pymod/wrap_mol_alg.cc
@@ -18,9 +18,9 @@
 //------------------------------------------------------------------------------
 
 #include <boost/python.hpp>
-#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
+#include <boost/python/suite/indexing/map_indexing_suite.hpp>
 #include <ost/config.hh>
-#include <ost/mol/alg/local_dist_test.hh>
+#include <ost/mol/alg/local_dist_diff_test.hh>
 #include <ost/mol/alg/superpose_frames.hh>
 #include <ost/mol/alg/filter_clashes.hh>
 using namespace boost::python;
@@ -36,8 +36,9 @@ void export_entity_to_density();
 
 namespace {
   
-Real (*ldt_a)(const mol::EntityView&, const mol::alg::GlobalDistanceList& glob_dist_list, Real, const String&)=&mol::alg::LocalDistTest;
-Real (*ldt_b)(const seq::AlignmentHandle&,Real, Real, int, int)=&mol::alg::LocalDistTest;
+std::pair<long int,long int> (*lddt_a)(const mol::EntityView&, const mol::alg::GlobalRDMap& , std::vector<Real>, int, const String&)=&mol::alg::LocalDistDiffTest;
+Real (*lddt_c)(const mol::EntityView&, const mol::EntityView& , Real, Real, const String&)=&mol::alg::LocalDistDiffTest;
+Real (*lddt_b)(const seq::AlignmentHandle&,Real, Real, int, int)=&mol::alg::LocalDistDiffTest;
 mol::EntityView (*fc_a)(const mol::EntityView&, const mol::alg::ClashingDistances&,bool)=&mol::alg::FilterClashes;
 mol::EntityView (*fc_b)(const mol::EntityHandle&, const mol::alg::ClashingDistances&, bool)=&mol::alg::FilterClashes;
 mol::EntityView (*csc_a)(const mol::EntityView&, const mol::alg::StereoChemicalParams&, const mol::alg::StereoChemicalParams&, Real, Real, bool)=&mol::alg::CheckStereoChemistry;
@@ -66,11 +67,28 @@ ost::mol::alg::ClashingDistances fill_clashing_distances_wrapper (const list& st
     stereo_chemical_props_file_vector[i] = boost::python::extract<char const*>(stereo_chemical_props_file[i]);
   }
  
- return ost::mol::alg::FillClashingDistances(stereo_chemical_props_file_vector,min_default_distance,min_distance_tolerance);
+ return ost::mol::alg::FillClashingDistances(stereo_chemical_props_file_vector);
 }
 
+ost::mol::alg::GlobalRDMap create_distance_list_from_multiple_references(const list& ref_list, const list& cutoff_list, int sequence_separation, Real max_dist)
+{
+  int ref_list_length = boost::python::extract<int>(ref_list.attr("__len__")());
+  std::vector<ost::mol::EntityView> ref_list_vector(ref_list_length);
+  
+  for (int i=0; i<ref_list_length; i++) {
+    ref_list_vector[i] = boost::python::extract<ost::mol::EntityView>(ref_list[i]);
+  }
+
+  int cutoff_list_length = boost::python::extract<int>(cutoff_list.attr("__len__")());
+  std::vector<Real> cutoff_list_vector(cutoff_list_length);
+  
+  for (int i=0; i<cutoff_list_length; i++) {
+    cutoff_list_vector[i] = boost::python::extract<Real>(cutoff_list[i]);
+  }
+  return ost::mol::alg::CreateDistanceListFromMultipleReferences(ref_list_vector, cutoff_list_vector, sequence_separation, max_dist);  	
 }
 
+}
 
 
 BOOST_PYTHON_MODULE(_ost_mol_alg)
@@ -78,18 +96,21 @@ BOOST_PYTHON_MODULE(_ost_mol_alg)
   export_svdSuperPose();
   export_TrajectoryAnalysis();
   export_StructureAnalysis();
+  export_Clash();
   #if OST_IMG_ENABLED
   export_entity_to_density();
   #endif
   
-  def("LocalDistTest", ldt_a, (arg("local_ldt_property_string")=""));
-  def("LocalDistTest", ldt_b, (arg("ref_index")=0, arg("mdl_index")=1));
+  def("LocalDistDiffTest", lddt_a, (arg("sequence_separation")=0,arg("local_lddt_property_string")=""));
+  def("LocalDistDiffTest", lddt_c, (arg("local_lddt_property_string")=""));
+  def("LocalDistDiffTest", lddt_b, (arg("ref_index")=0, arg("mdl_index")=1));
   def("FilterClashes", fc_a, (arg("ent"), arg("clashing_distances"), arg("always_remove_bb")=false));
   def("FilterClashes", fc_b, (arg("ent"), arg("clashing_distances"), arg("always_remove_bb")=false));
   def("CheckStereoChemistry", csc_a, (arg("ent"), arg("bonds"), arg("angles"), arg("bond_tolerance"), arg("angle_tolerance"), arg("always_remove_bb")=false));
   def("CheckStereoChemistry", csc_b, (arg("ent"), arg("bonds"), arg("angles"), arg("bond_tolerance"), arg("angle_tolerance"), arg("always_remove_bb")=false));
-  def("LDTHA",&mol::alg::LDTHA);
+  def("LDDTHA",&mol::alg::LDDTHA, (arg("sequence_separation")=0));
   def("CreateDistanceList",&mol::alg::CreateDistanceList);
+  def("CreateDistanceListFromMultipleReferences",&create_distance_list_from_multiple_references);
     
   def("SuperposeFrames", superpose_frames1, 
       (arg("source"), arg("sel")=ost::mol::EntityView(), arg("begin")=0, 
@@ -98,7 +119,7 @@ BOOST_PYTHON_MODULE(_ost_mol_alg)
   (arg("source"), arg("sel"), arg("ref_view"),arg("begin")=0, arg("end")=-1));
 
   
-  class_<mol::alg::ClashingDistances> ("ClashingDistances" ,init<Real,Real>())
+  class_<mol::alg::ClashingDistances> ("ClashingDistances",init<>())
     .def("SetClashingDistance",&mol::alg::ClashingDistances::SetClashingDistance)
     .def("GetClashingDistance",&mol::alg::ClashingDistances::GetClashingDistance)
     .def("GetMaxAdjustedDistance",&mol::alg::ClashingDistances::GetMaxAdjustedDistance)    
@@ -125,23 +146,18 @@ BOOST_PYTHON_MODULE(_ost_mol_alg)
   ;    
    
   
-  class_<mol::alg::ReferenceDistance> ("ReferenceDistance", init <const mol::alg::UniqueAtomIdentifier&,const mol::alg::UniqueAtomIdentifier&, Real, Real>())
-    .def("GetFirstAtom",&mol::alg::ReferenceDistance::GetFirstAtom)
-    .def("GetSecondAtom",&mol::alg::ReferenceDistance::GetSecondAtom)
-    .def("GetMinDistance",&mol::alg::ReferenceDistance::GetMinDistance)
-    .def("GetMaxDistance",&mol::alg::ReferenceDistance::GetMaxDistance)
-  ;
-  
-  class_<std::vector<mol::alg::ReferenceDistance> >("ResidueDistanceList")
-    .def(vector_indexing_suite<std::vector<mol::alg::ReferenceDistance > >())
+  class_<mol::alg::ResidueRDMap>("ResidueRDMap")
+    .def(map_indexing_suite<mol::alg::ResidueRDMap>())
   ;
   
-  class_<std::vector<mol::alg::ResidueDistanceList> >("GlobalDistanceList")
-    .def(vector_indexing_suite<std::vector<mol::alg::ResidueDistanceList > >())
+  class_<mol::alg::GlobalRDMap>("GlobalRDMap")
+    .def(map_indexing_suite<mol::alg::GlobalRDMap>())
   ;
   
   def("FillClashingDistances",&fill_clashing_distances_wrapper);
   def("FillStereoChemicalParams",&fill_stereochemical_params_wrapper);
   def("IsStandardResidue",&mol::alg::IsStandardResidue);
+  def("PrintGlobalRDMap",&mol::alg::PrintGlobalRDMap);
+  def("PrintResidueRDMap",&mol::alg::PrintResidueRDMap);
   
 }
diff --git a/modules/mol/alg/src/CMakeLists.txt b/modules/mol/alg/src/CMakeLists.txt
index 050d4822712f8789bfac97938e18c327334f7d92..146717ace4972b697c0ce160206b67749c029f2e 100644
--- a/modules/mol/alg/src/CMakeLists.txt
+++ b/modules/mol/alg/src/CMakeLists.txt
@@ -2,7 +2,7 @@ set(OST_MOL_ALG_HEADERS
   svd_superpose.hh
   module_config.hh
   sec_structure_segments.hh
-  local_dist_test.hh
+  local_dist_diff_test.hh
   superpose_frames.hh
   filter_clashes.hh
   construct_cbeta.hh
@@ -15,7 +15,7 @@ set(OST_MOL_ALG_SOURCES
   svd_superpose.cc
   clash_score.cc
   sec_structure_segments.cc
-  local_dist_test.cc
+  local_dist_diff_test.cc
   superpose_frames.cc
   filter_clashes.cc
   construct_cbeta.cc
@@ -39,7 +39,7 @@ if (ENABLE_IMG)
   set(MOL_ALG_DEPS ${MOL_ALG_DEPS} ost_img ost_img_alg)
 endif()
 
-executable(NAME ldt SOURCES ldt.cc 
+executable(NAME lddt SOURCES lddt.cc 
            DEPENDS_ON  ost_mol ost_mol_alg ost_io STATIC)
 
 module(NAME mol_alg SOURCES ${OST_MOL_ALG_SOURCES}
diff --git a/modules/mol/alg/src/construct_cbeta.cc b/modules/mol/alg/src/construct_cbeta.cc
index 19cdec41dafd5ea4e3a1369d6bd21520e464c1cf..5eaf96046ca42eb475992972b2d7b88c31742a25 100644
--- a/modules/mol/alg/src/construct_cbeta.cc
+++ b/modules/mol/alg/src/construct_cbeta.cc
@@ -1,5 +1,6 @@
 #include <cmath>
 
+#include <ost/message.hh>
 #include <ost/mol/mol.hh>
 #include <ost/log.hh>
 #include "construct_cbeta.hh"
@@ -83,7 +84,7 @@ geom::Vec3 CBetaPosition(const ResidueHandle& residue, Real bond_length)
   std::stringstream ss;
   ss << "residue " << residue.GetQualifiedName() 
      << "doesn't have enough backbone atoms to reconstruct CBeta position";
-    throw std::runtime_error(ss.str());
+    throw ost::Error(ss.str());
   }
   return CBetaPosition(n.GetPos(), ca.GetPos(), c.GetPos(), bond_length);
 }
diff --git a/modules/mol/alg/src/entity_to_density.cc b/modules/mol/alg/src/entity_to_density.cc
index 6a15ac44fc68fd179f19b5f1d9405b259ecc3923..a01bd49c173f2f9c6ad2a76ac7c0465df49edfe2 100644
--- a/modules/mol/alg/src/entity_to_density.cc
+++ b/modules/mol/alg/src/entity_to_density.cc
@@ -378,9 +378,9 @@ void EntityToDensityScattering(const mol::EntityView& entity_view,
                                      bool clear_map_flag,
                                      Real source_wavelength)
 {
-  if(falloff_start<=0.0) throw std::runtime_error("Invalid falloff start");
+  if(falloff_start<=0.0) throw ost::Error("Invalid falloff start");
   if(falloff_end<=0.0 || falloff_end>falloff_start)
-     throw std::runtime_error("Invalid falloff end");
+     throw ost::Error("Invalid falloff end");
 
  geom ::Vec3 rs_sampl = map.GetSpatialSampling();
   geom ::Vec3 abs_orig = map.GetAbsoluteOrigin();
@@ -420,7 +420,7 @@ void EntityToDensityRosetta(const mol::EntityView& entity_view,
                             Real source_wavelength)
 
 {
-  if(resolution <=0.0) throw std::runtime_error("Invalid resolution");
+  if(resolution <=0.0) throw ost::Error("Invalid resolution");
   if (clear_map_flag==true) {
     img::MapHandle mm=img::CreateImage(img::Extent(img::Point(0,0),
                                        map.GetSize()));
diff --git a/modules/mol/alg/src/filter_clashes.cc b/modules/mol/alg/src/filter_clashes.cc
index 1b163d17616c676e0933b7ebc7bad4c6e56dea91..27ffb844853f7d68821d3356ec6895ef4389b4f1 100644
--- a/modules/mol/alg/src/filter_clashes.cc
+++ b/modules/mol/alg/src/filter_clashes.cc
@@ -27,6 +27,7 @@
 
 namespace {
 
+// helper function
 String bond_string(const ost::mol::AtomView& atom1, const ost::mol::AtomHandle& atom2) {
   String atom1_str = atom1.GetName();
   String atom2_str = atom2.GetName();
@@ -43,6 +44,22 @@ String bond_string(const ost::mol::AtomView& atom1, const ost::mol::AtomHandle&
   return stkey.str();  
 }
 
+// helper function
+String bond_string_elems(String& ele1, String ele2) {
+  String string1,string2;
+  if (ele1 < ele2) {
+    string1 = ele1;
+    string2 = ele2;
+  } else {
+    string1 = ele2;
+    string2 = ele1;
+  }
+  std::stringstream stkey;
+  stkey << string1 << "-" << string2;
+  return stkey.str();  
+}
+
+// helper function
 String angle_string(const ost::mol::AtomHandle& atom1, const ost::mol::AtomView& atom, const ost::mol::AtomHandle& atom2 ) {
   String atom1_str = atom1.GetName();
   String atom2_str = atom2.GetName();
@@ -62,7 +79,6 @@ String angle_string(const ost::mol::AtomHandle& atom1, const ost::mol::AtomView&
 
 }  
 
-
 namespace ost { namespace mol { namespace alg {
 
 void ClashingDistances::SetClashingDistance(const String& ele1,const String& ele2, Real min_distance, Real tolerance)
@@ -84,7 +100,9 @@ std::pair<Real,Real> ClashingDistances::GetClashingDistance(const String& ele1,c
   String key=stkey.str();
   std::map <String,std::pair<float,float> >::const_iterator find_ci= min_distance_.find(key);
   if (find_ci == min_distance_.end()) {
-    return std::make_pair<Real,Real> (default_min_distance_,default_min_distance_tolerance_);
+      std::stringstream serr;
+      serr << "Entry for distance " << stkey <<  " not found in the parameter table";   
+      throw Error(serr.str());
   }    
   return find_ci->second;
 }
@@ -239,9 +257,9 @@ StereoChemicalParams FillStereoChemicalParams(const String& header, std::vector<
   return table;
 };  
 
-ClashingDistances FillClashingDistances(std::vector<String>& stereo_chemical_props_file, Real min_default_distance, Real min_distance_tolerance)
+ClashingDistances FillClashingDistances(std::vector<String>& stereo_chemical_props_file)
 {
-  ClashingDistances table(min_default_distance,min_distance_tolerance);
+  ClashingDistances table;
   bool found=false;
   std::vector<String>::const_iterator line_iter=stereo_chemical_props_file.begin();
   while (line_iter!=stereo_chemical_props_file.end()) {
@@ -257,7 +275,7 @@ ClashingDistances FillClashingDistances(std::vector<String>& stereo_chemical_pro
             std::vector<StringRef> second_line_str_vec = second_line_string_ref.split();
             if (second_line_str_vec.size()!=3) {
               std::cout << "The number of elements in one of the lines is wrong" << std::endl;
-              return ClashingDistances(min_default_distance,min_distance_tolerance);
+              return ClashingDistances();
             } 
             String item = second_line_str_vec[0].str();
 
@@ -268,19 +286,19 @@ ClashingDistances FillClashingDistances(std::vector<String>& stereo_chemical_pro
               value=static_cast<Real>(parse_value.second);
             } else {
               std::cout << "One of the distance values is not a number" << std::endl;
-              return ClashingDistances(min_default_distance,min_distance_tolerance);
+              return ClashingDistances();
             };
             if (parse_stddev.first==true) {
               stddev=static_cast<Real>(parse_stddev.second);
             } else {
               std::cout << "One of the tolerance values is not a number" << std::endl;
-              return ClashingDistances(min_default_distance,min_distance_tolerance);
+              return ClashingDistances();
             }
             StringRef itemsr(item.data(),item.length());
             std::vector<StringRef> eles = itemsr.split('-');
             if (itemsr.size() != 3) {
               std::cout << "One of the strings describing the interacting atoms has the wrong format" << std::endl;
-              return ClashingDistances(min_default_distance,min_distance_tolerance);
+              return ClashingDistances();
             }  
             String ele1=eles[0].str();
             String ele2=eles[1].str();
@@ -298,7 +316,7 @@ ClashingDistances FillClashingDistances(std::vector<String>& stereo_chemical_pro
   }
   if (found==false) {
     std::cout << "Could not find the relevant section in the stereo-chemical parameter file" << std::endl;
-    return ClashingDistances(min_default_distance,min_distance_tolerance);
+    return ClashingDistances();
   } 
   return table;
 }  
@@ -312,6 +330,9 @@ EntityView CheckStereoChemistry(const EntityView& ent, const StereoChemicalParam
   int bad_bond_count = 0;
   int angle_count = 1;
   int bad_angle_count = 0;
+  std::map<String,Real> bond_length_sum;
+  std::map<String,Real> bond_zscore_sum;
+  std::map<String,int> bond_counter_sum;
   LOG_INFO("Checking stereo-chemistry")
   EntityView filtered=ent.CreateEmptyView();
   ResidueViewList residues=ent.GetResidueList();
@@ -365,8 +386,19 @@ EntityView CheckStereoChemistry(const EntityView& ent, const StereoChemicalParam
             } else {
               LOG_VERBOSE("BOND:" << " " << res.GetChain() << " " << res.GetName() << " " << res.GetNumber() << " " << bond_str << " " << min_length << " " << max_length << " " << blength << " " << zscore << " " << "PASS")
             }
-	    bond_count++;
-            running_sum_zscore_bonds+=zscore;  
+            bond_count++;
+            running_sum_zscore_bonds+=zscore;
+            String bond_elems=bond_string_elems(ele1,ele2);
+            std::map<String,Real>::const_iterator find_be = bond_length_sum.find(bond_elems);  
+            if (find_be==bond_length_sum.end()) {
+                bond_length_sum[bond_elems]=blength;
+                bond_zscore_sum[bond_elems]=zscore;
+                bond_counter_sum[bond_elems]=1;
+            } else {
+                bond_length_sum[bond_elems]+=blength;
+                bond_zscore_sum[bond_elems]+=zscore;
+                bond_counter_sum[bond_elems]+=1;
+            }
           }  
       }
       
@@ -448,6 +480,17 @@ EntityView CheckStereoChemistry(const EntityView& ent, const StereoChemicalParam
   Real avg_zscore_angles = running_sum_zscore_angles/static_cast<float>(angle_count);
   LOG_SCRIPT("Average Z-Score for bond lengths: " << avg_zscore_bonds);
   LOG_SCRIPT("Bonds outside of tolerance range: " << bad_bond_count << " out of " << bond_count);
+  LOG_SCRIPT("Bond\tAvg Length\tAvg zscore\tNum Bonds")
+
+  for (std::map<String,Real>::const_iterator bls_it=bond_length_sum.begin();bls_it!=bond_length_sum.end();++bls_it) {
+    String key = (*bls_it).first;
+    int counter=bond_counter_sum[key];
+    Real sum_bond_length=(*bls_it).second;
+    Real sum_bond_zscore=bond_zscore_sum[key];
+    Real avg_length=sum_bond_length/static_cast<Real>(counter);
+    Real avg_zscore=sum_bond_zscore/static_cast<Real>(counter);
+    LOG_SCRIPT(key << "\t" << avg_length << "\t" << avg_zscore << "\t" << counter);
+  }
   LOG_SCRIPT("Average Z-Score angle widths: " << avg_zscore_angles);
   LOG_SCRIPT("Angles outside of tolerance range: " << bad_angle_count << " out of " << angle_count);
   return filtered;
@@ -464,6 +507,7 @@ EntityView FilterClashes(const EntityView& ent, const ClashingDistances& min_dis
 {
   int distance_count = 0;
   int bad_distance_count = 0;
+  Real average_offset_sum = 0.0;
   LOG_INFO("Filtering non-bonded clashes")
   EntityView filtered=ent.CreateEmptyView();
   ResidueViewList residues=ent.GetResidueList();
@@ -488,9 +532,6 @@ EntityView FilterClashes(const EntityView& ent, const ClashingDistances& min_dis
       for (AtomViewList::iterator 
            k=within.begin(), e3=within.end(); k!=e3; ++k) {
         AtomView atom2=*k;
-
-
-
         if (atom2==atom) {
           continue;
         }
@@ -507,8 +548,6 @@ EntityView FilterClashes(const EntityView& ent, const ClashingDistances& min_dis
           continue;
         }
 
-
-
         Real d=geom::Length2(atom.GetPos()-atom2.GetPos());
         std::pair <Real,Real> distance_tolerance=min_distances.GetClashingDistance(ele1, ele2);
         Real distance=distance_tolerance.first;
@@ -518,6 +557,7 @@ EntityView FilterClashes(const EntityView& ent, const ClashingDistances& min_dis
         if (d<threshold*threshold) {
           LOG_INFO(atom.GetResidue().GetChain() << " " << atom.GetResidue().GetName() << " " << atom.GetResidue().GetNumber() << " " << atom.GetName() << " " << atom2.GetResidue().GetChain() << " " << atom2.GetResidue().GetName() << " " << atom2.GetResidue().GetNumber() << " " << atom2.GetName() << " " << threshold << " " << sqrt(d) << " " << sqrt(d)-threshold << " " << "FAIL")
           bad_distance_count++; 
+          average_offset_sum+=sqrt(d)-threshold;
           remove_sc=true;
           if (always_remove_bb==true) {
             remove_bb=true;
@@ -551,7 +591,12 @@ EntityView FilterClashes(const EntityView& ent, const ClashingDistances& min_dis
     }
     filtered.AddResidue(res, ViewAddFlag::INCLUDE_ATOMS);
   }
-  LOG_SCRIPT(bad_distance_count << " out of " << distance_count << " non-bonded short-range distances checked shorter than tolerance distance");
+  Real average_offset = 0;
+  if (bad_distance_count!=0) {
+    average_offset = average_offset_sum / static_cast<Real>(bad_distance_count);
+  }
+  LOG_SCRIPT(bad_distance_count << " non-bonded short-range distances shorter than tolerance distance");
+  LOG_SCRIPT("Distances shorter than tolerance are on average shorter by: " << average_offset);
   return filtered;
 }
 
diff --git a/modules/mol/alg/src/filter_clashes.hh b/modules/mol/alg/src/filter_clashes.hh
index 5d64fc23060cdf879c434ccf52c950444b2087d0..f9d7473b6ce1eb0d5044c6f46a4bebadc86bff83 100644
--- a/modules/mol/alg/src/filter_clashes.hh
+++ b/modules/mol/alg/src/filter_clashes.hh
@@ -24,17 +24,29 @@
 
 namespace ost { namespace mol { namespace alg {
 
-class ClashingDistances
+/// \brief List of reference atom-atom distances to detect clashes between non-bonded atoms 
+class DLLEXPORT_OST_MOL_ALG ClashingDistances
 {
 
 public:
-  ClashingDistances(Real default_dist, Real tolerance): default_min_distance_(default_dist), default_min_distance_tolerance_(tolerance), valid_flag_(true) {}
+  /// \brief Default constructor (creates an empty list)
+  ClashingDistances(): valid_flag_(true) {}
+
+  /// \brief Adds or replaces an entry 
+  ///
+  /// Requires an atom-atom distance and a tolerance threshold
   void SetClashingDistance(const String& ele1,const String& ele2, Real min_distance, Real tolerance);
+
+  /// \brief Recovers a reference distance and a tolerance threshold (respectively) from the list
   std::pair<Real,Real> GetClashingDistance(const String& ele1,const String& ele2) const;
+
+  /// \brief Recovers the longest distance in the list, corrected by tolerance
   Real GetMaxAdjustedDistance() const;
+
+  /// \brief Returns true if the list is empty (i.e. in an invalid, useless state)
   bool IsEmpty() const;
   
-  //DEBUG
+  /// \brief Prints all distances in the list to standard output
   void PrintAllDistances() const;
   
 private:
@@ -45,17 +57,33 @@ private:
   bool valid_flag_;
   
 };
-  
-class StereoChemicalParams
+
+/// \brief List of stereo chemical parameters (Bonds and angles)
+///
+/// For each item (bond or angle in a specific residue), stores the mean and standard deviation 
+class DLLEXPORT_OST_MOL_ALG StereoChemicalParams
 {
 
 public:
+  /// \brief Adds or replaces an entry 
   void SetParam(const String& param, const String& residue, Real value, Real st_dev);
+
+  /// \brief Recovers mean and standard deviation (respectively) of a stereo⁻chemical item (bond or angle) from the list
+  ///
+  /// Item format: Bond: X-Y, Angle:X-Y-Z
   std::pair<Real,Real> GetParam(const String& element,const String& residue) const;
+
+  /// \brief Checks if the list contains an entry for a specific stereo-chemical item (a bond or atom in a specific residue)
+  ///
+  /// Item format: Bond: X-Y, Angle:X-Y-Z
   bool ContainsParam(const String& param,const String& residue) const;
+
+  /// \brief Returns true if the list is empty (i.e. in an invalid, useless state)
+  ///
+  /// Item format: Bond: X-Y, Angle:X-Y-Z
   bool IsEmpty() const;
   
-  //DEBUG
+  /// \brief Prints all distances in the list to standard output
   void PrintAllParameters() const;
   
 private:
@@ -64,15 +92,44 @@ private:
  
 };
 
-ClashingDistances DLLEXPORT_OST_MOL_ALG FillClashingDistances(std::vector<String>& stereo_chemical_props_file, Real min_default_distance, Real min_distance_tolerance);
+/// \brief Fills a list of reference clashing distances from the content of a parameter file
+///
+/// Requires a list of strings holding the contents of a parameter file, one line per string
+ClashingDistances DLLEXPORT_OST_MOL_ALG FillClashingDistances(std::vector<String>& stereo_chemical_props_file);
+
+/// \brief Fills a list of stereo-chemical statistics from the content of a parameter file
+///
+/// Requires a list of strings holding the contents of a parameter file, one line per string
+/// The header can be 'Bonds' to read bond statistics or 'Angles' to read angle statistics
 StereoChemicalParams DLLEXPORT_OST_MOL_ALG FillStereoChemicalParams(const String& header, std::vector<String>& stereo_chemical_props_file);  
- 
+
+/// \brief Filters a structure based on detected clashes between non bonded atoms. Entity version
+///
+/// If a clash between two atoms (distance shorter than reference clashing distance - tolerance threshold)
+/// is detected in a residue's side-chain, all atoms in the side chain are removed from the structure
+/// If a clash is detected in the backbone, all atoms in the residue are removed. This behavior is changed 
+/// by the always_remove_bb flag: when the flag is set to true all atoms in the residue are removed even if
+/// a clash is just detected in the side-chain
 EntityView DLLEXPORT_OST_MOL_ALG FilterClashes(const EntityView& ent, 
                                                const ClashingDistances& min_distances, bool always_remove_bb=false);
 
+/// \brief Filters a structure based on detected clashes between non bonded atoms. Handle version
+///
+/// If a clash between two atoms (distance shorter than reference clashing distance - tolerance threshold)
+/// is detected in a residue's side-chain, all atoms in the side chain are removed from the structure
+/// If a clash is detected in the backbone, all atoms in the residue are removed. This behavior is changed 
+/// by the always_remove_bb flag: when the flag is set to true all atoms in the residue are removed even if
+/// a clash is just detected in the side-chain
 EntityView DLLEXPORT_OST_MOL_ALG FilterClashes(const EntityHandle& ent, 
                                                const ClashingDistances& min_distances, bool always_remove_bb=false);
 
+/// \brief Filters a structure based on detected stereo-chemical violations. Entity version
+///
+/// If a stereo-chemical violation (i.e., a bond or an angle with a value outside the range defined by
+/// the mean value, the standard deviation and the tolerance parameter) is detected in a residue's side-chain, 
+/// all atoms in the side chain are removed from the structure. If a violation is detected in the backbone, all 
+/// atoms in the residue are removed. This behavior is changed by the always_remove_bb flag: when the flag is 
+/// set to true all atoms in the residue are removed even if a violation is just detected in the side-chain
 EntityView DLLEXPORT_OST_MOL_ALG CheckStereoChemistry(const EntityView& ent, 
                                                       const StereoChemicalParams& bond_table, 
                                                       const StereoChemicalParams& angle_table,
@@ -80,6 +137,13 @@ EntityView DLLEXPORT_OST_MOL_ALG CheckStereoChemistry(const EntityView& ent,
                                                       Real angle_tolerance,
                                                       bool always_remove_bb=false);
 
+/// \brief Filters a structure based on detected stereo-chemical violations. Handle version
+///
+/// If a stereo-chemical violation (i.e., a bond or an angle with a value outside the range defined by
+/// the mean value, the standard deviation and the tolerance parameter) is detected in a residue's side-chain, 
+/// all atoms in the side chain are removed from the structure. If a violation is detected in the backbone, all 
+/// atoms in the residue are removed. This behavior is changed by the always_remove_bb flag: when the flag is 
+/// set to true all atoms in the residue are removed even if a violation is just detected in the side-chain
 EntityView DLLEXPORT_OST_MOL_ALG CheckStereoChemistry(const EntityHandle& ent, 
                                                       const StereoChemicalParams& bond_table, 
                                                       const StereoChemicalParams& angle_table,
diff --git a/modules/mol/alg/src/ldt.cc b/modules/mol/alg/src/lddt.cc
similarity index 63%
rename from modules/mol/alg/src/ldt.cc
rename to modules/mol/alg/src/lddt.cc
index 709adeb9909ecf5dd0b7187155ed7e74272b0113..fdd70d953c802f7319611071b57ca1e30a2b5c32 100644
--- a/modules/mol/alg/src/ldt.cc
+++ b/modules/mol/alg/src/lddt.cc
@@ -16,17 +16,19 @@
 // along with this library; if not, write to the  Free Software Foundation, Inc.,
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 //------------------------------------------------------------------------------
+#include <iomanip>
 #if defined (_MSC_VER)
 #define BOOST_ALL_DYN_LINK 1
 #endif
 #include <boost/program_options.hpp>
 #include <boost/filesystem/fstream.hpp>
 #include <boost/filesystem/convenience.hpp>
-#include <ost/mol/alg/local_dist_test.hh>
+#include <ost/mol/alg/local_dist_diff_test.hh>
 #include <ost/mol/alg/filter_clashes.hh>
 #include <ost/io/mol/pdb_reader.hh>
 #include <ost/io/io_exception.hh>
 #include <ost/conop/conop.hh>
+#include <ost/string_ref.hh>
 #include <ost/conop/amino_acids.hh>
 #include <ost/mol/iterator.hh>
 #include <ost/platform.hh>
@@ -41,6 +43,7 @@ using namespace ost::mol;
 using namespace ost::mol::alg;
 namespace po=boost::program_options;
 
+// loads a file
 EntityHandle load(const String& file, const IOProfile& profile)
 {
   try {
@@ -50,6 +53,9 @@ EntityHandle load(const String& file, const IOProfile& profile)
       reader.Import(ent);
       conop::Conopology& conop_inst=conop::Conopology::Instance();
       conop_inst.ConnectAll(conop_inst.GetBuilder(), ent);
+      if (ent.GetChainList().size()!=1) {
+        std::cout << "WARNING: File " << file << "has more than one chain" << std::endl; 
+      }    
       return ent;
     }
     std::cerr << "ERROR: '" << file << "' does not contain any ATOM records. "
@@ -61,9 +67,10 @@ EntityHandle load(const String& file, const IOProfile& profile)
   }
 }
 
+// prints usage output
 void usage()
 {
-  std::cerr << "usage: ldt [options] <mod1> [mod1 [mod2]] <ref>" << std::endl;
+  std::cerr << "usage: lddt [options] <mod1> [mod1 [mod2]] <re1>[,ref2,ref3]" << std::endl;
   std::cerr << "   -s         selection performed on ref" << std::endl;
   std::cerr << "   -c         use Calphas only" << std::endl;
   std::cerr << "   -f         perform structural checks and filter input data" << std::endl;
@@ -74,10 +81,12 @@ void usage()
   std::cerr << "   -a <value> tolerance in stddevs for angles" << std::endl;
   std::cerr << "   -m <value> clashing distance for unknwon atom types" << std::endl;
   std::cerr << "   -r <value> distance inclusion radius" << std::endl;
+  std::cerr << "   -i <value> sequence separation" << std::endl;
   std::cerr << "   -e         print version" << std::endl;
 }
 
-std::pair<int,int> compute_coverage (const EntityView& v,const GlobalDistanceList& glob_dist_list)
+// computes coverage
+std::pair<int,int> compute_coverage (const EntityView& v,const GlobalRDMap& glob_dist_list)
 {
   int second=0;
   int first=0;
@@ -85,15 +94,12 @@ std::pair<int,int> compute_coverage (const EntityView& v,const GlobalDistanceLis
     return std::make_pair<int,int>(0,1);
   }
   ChainView vchain=v.GetChainList()[0];
-  for (std::vector<ResidueDistanceList>::const_iterator i=glob_dist_list.begin();i!=glob_dist_list.end();++i)
+  for (GlobalRDMap::const_iterator i=glob_dist_list.begin();i!=glob_dist_list.end();++i)
   {
-    ResNum rnum = (*i)[0].GetFirstAtom().GetResNum();
-    String rname = (*i)[0].GetFirstAtom().GetResidueName();
-    if (IsStandardResidue(rname)) {
-      second++;
-      if (vchain.FindResidue(rnum)) {
-        first++;
-      }
+    ResNum rnum = (*i).first;
+    second++;
+    if (vchain.FindResidue(rnum)) {
+      first++;
     }
   }
   return std::make_pair<int,int>(first,second);
@@ -101,16 +107,18 @@ std::pair<int,int> compute_coverage (const EntityView& v,const GlobalDistanceLis
 
 int main (int argc, char **argv)
 {
-  String version = "Beta - 2012-01-17";
-  Real min_default_distance = 1.5;
-  Real min_distance_tolerance = 0.0;
-  Real bond_tolerance = 8.0;
-  Real angle_tolerance = 8.0;
-  Real radius=15.0;
-  
+  // sets some default values for parameters
+  String version = "1.2";
+  Real bond_tolerance = 15.0;
+  Real angle_tolerance = 15.0;
+  Real radius=15.0; 
+  int sequence_separation = 0;
+
+  // creates the required loading profile
   IOProfile profile;
   profile.bond_feasibility_check=false;
-  // parse options
+
+  // parses options
   String sel;
   bool structural_checks=false;
   po::options_description desc("Options");
@@ -124,17 +132,23 @@ int main (int argc, char **argv)
     ("verbosity,v", po::value<int>(), "verbosity level")
     ("bond_tolerance,b", po::value<Real>(), "tolerance in stddev for bonds")
     ("angle_tolerance,a", po::value<Real>(), "tolerance in stddev for angles")
-    ("default_clash,m", po::value<Real>(), "clashing distance for unknown atom types")
     ("inclusion_radius,r", po::value<Real>(), "distance inclusion radius")
+    ("sequence_separation,i", po::value<int>(), "sequence separation")
     ("files", po::value< std::vector<String> >(), "input file(s)")
-	("reference",po::value<String>(),"reference(s)")
+    ("reference",po::value<String>(),"reference(s)")
   ;
   po::positional_options_description p;
   p.add("files", -1);
   po::variables_map vm;
-  po::store(po::command_line_parser(argc, argv).
+  try {
+    po::store(po::command_line_parser(argc, argv).
                 options(desc).positional(p).run(),
-            vm);
+              vm);
+  } catch (std::exception& e) {
+    std::cout << e.what() << std::endl;
+    usage();
+    exit(-1);
+  }
   po::notify(vm);
   if (vm.count("version")) {
     std::cout << "Version: " << version << std::endl;
@@ -158,8 +172,8 @@ int main (int argc, char **argv)
   }
   String parameter_filename;
   if (vm.count("parameter-file")) {
-    parameter_filename=vm["parameter-file"].as<String>();
-  } else if (structural_checks==true) {
+      parameter_filename=vm["parameter-file"].as<String>();
+    } else if (structural_checks==true) {
     std::cout << "Please specify a stereo-chemical parameter file" << std::endl;
     exit(-1);
   }
@@ -187,20 +201,57 @@ int main (int argc, char **argv)
   if (vm.count("angle_tolerance")) {
     angle_tolerance=vm["angle_tolerance"].as<Real>();
   }
-  if (vm.count("default_clash")) {
-    min_default_distance=vm["default_clash"].as<Real>();
-  }
   if (vm.count("inclusion_radius")) {
     radius=vm["inclusion_radius"].as<Real>();
   }
-  String ref_file=files.back();
-  EntityHandle ref=load(ref_file, profile);
-  if (!ref) {
-    exit(-1);
+  if (vm.count("sequence_separation")) {
+    sequence_separation=vm["sequence_separation"].as<int>();
   }
+    
+  std::vector<Real> cutoffs;
+  cutoffs.push_back(0.5);
+  cutoffs.push_back(1.0);
+  cutoffs.push_back(2.0);
+  cutoffs.push_back(4.0);
+    
+  // loads the reference file and creates the list of distances to check in lddt    
+  // if the reference file is a comma-separated list of files, switches to multi-
+  // reference mode
+  GlobalRDMap glob_dist_list; 
+  String ref_file=files.back();    
+  ost::StringRef ref_file_sr(ref_file.c_str(),ref_file.length());
+  std::vector<StringRef> ref_file_split_sr=ref_file_sr.split(',');
+  if (ref_file_split_sr.size()==1) { 
+    std::cout << "Multi-reference mode: Off" << std::endl;  
+    String ref_filename = ref_file_split_sr[0].str();  
+    EntityHandle ref=load(ref_filename, profile);
+    if (!ref) {
+      exit(-1);
+    }  
+    glob_dist_list = CreateDistanceList(ref.CreateFullView(),radius);  
+  } else {
+    std::cout << "Multi-reference mode: On" << std::endl;  
+    std::vector<EntityView> ref_list;  
+    for (std::vector<StringRef>::const_iterator ref_file_split_sr_it = ref_file_split_sr.begin();
+         ref_file_split_sr_it != ref_file_split_sr.end();++ref_file_split_sr_it) {
+      String ref_filename = ref_file_split_sr_it->str();  
+      EntityHandle ref=load(ref_filename, profile);
+      if (!ref) {
+        exit(-1);
+      }
+      if (ref_list.size()>0) {
+        if (ref_list[0].GetChainList()[0].GetName()!=ref.GetChainList()[0].GetName()) {
+          std::cout << "ERROR: First chains in the reference structures have different names" << std::endl;
+          exit(-1);  
+        }    
+      }
+      ref_list.push_back(ref.CreateFullView());
+    } 
+    glob_dist_list = CreateDistanceListFromMultipleReferences (ref_list,cutoffs,sequence_separation,radius);  
+  }         
   files.pop_back();
-  EntityView ref_view=ref.Select(sel);
-  GlobalDistanceList glob_dist_list = CreateDistanceList(ref_view,radius);
+
+  // prints out parameters used in the lddt calculation
   std::cout << "Verbosity level: " << verbosity_level << std::endl;
   if (structural_checks) {
     std::cout << "Stereo-chemical and steric clash checks: On " << std::endl;
@@ -208,17 +259,19 @@ int main (int argc, char **argv)
     std::cout << "Stereo-chemical and steric clash checks: Off " << std::endl;
   }
   std::cout << "Inclusion Radius: " << radius << std::endl;
+  std::cout << "Sequence separation: " << sequence_separation << std::endl;
   if (structural_checks) {
     std::cout << "Parameter filename: " << parameter_filename << std::endl;
     std::cout << "Tolerance in stddevs for bonds: " << bond_tolerance << std::endl;
     std::cout << "Tolerance in stddevs for angles: " << angle_tolerance << std::endl;
-    std::cout << "Clashing distance for unknown atom types: " << min_default_distance << std::endl;
     LOG_INFO("Log entries format:");
     LOG_INFO("BOND INFO FORMAT:  Chain  Residue  ResNum  Bond  Min  Max  Observed  Z-score  Status");
     LOG_INFO("ANGLE INFO FORMAT:  Chain  Residue  ResNum  Angle  Min  Max  Observed  Z-score  Status");
     LOG_INFO("CLASH INFO FORMAT:  Chain1  Residue1  ResNum1  Atom1  Chain2  Residue2  ResNum2  Atom2  Observed  Difference  Status");
   }
-  LOG_INFO("LDT INFO FORMAT:  Chain1  Residue1  ResNum1  Atom1  Chain2  Residue2  ResNum2  Atom2  ModelDist  TargetDist  Difference  Tolerance Status");
+  LOG_INFO("LDDT INFO FORMAT:  Chain1  Residue1  ResNum1  Atom1  Chain2  Residue2  ResNum2  Atom2  ModelDist  TargetDist  Difference  Tolerance Status");
+
+  // cycles through the models to evaluate 
   for (size_t i=0; i<files.size(); ++i) {
     EntityHandle model=load(files[i], profile);
     if (!model) {
@@ -229,32 +282,19 @@ int main (int argc, char **argv)
     }
     EntityView v=model.CreateFullView();
 
-
-    // The code in this following block is only used to make CASP9 models load correctly and normally commented out
-    EntityView model2=model.Select("aname!=CEN,NV,OT1,OT,CAY,CY,OXT,1OCT,NT,OT2,2OCT,OVL1,OC1,O1,OC2,O2,OVU1");
-    EntityView v1=model2.Select("not (rname==GLY and aname==CB)");
     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      
-    
-    if (filestring.substr(5,5)=="TS257" || filestring.substr(5,5)=="TS458" ) {
-      for (AtomHandleIter ait=v1.GetHandle().AtomsBegin();ait!=v1.GetHandle().AtomsEnd();++ait){
-        AtomHandle aitv = *ait;
-        String atomname=aitv.GetName();            
-        String firstletter=atomname.substr(0,1);
-        aitv.SetElement(firstletter);
-      }
-    }  
-    v=v1;
     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;
 
     if (structural_checks) {
+      // reads in parameter files   
       boost::filesystem::path loc(parameter_filename);
       boost::filesystem::ifstream infile(loc);
       if (!infile) {
@@ -279,38 +319,60 @@ int main (int argc, char **argv)
         exit(-1);
       }
 
-      ClashingDistances nonbonded_table = FillClashingDistances(stereo_chemical_props,min_default_distance,min_distance_tolerance);
+      ClashingDistances nonbonded_table = FillClashingDistances(stereo_chemical_props);
 
       if (nonbonded_table.IsEmpty()) {
         std::cout << "Error reading the Clashing section of the stereo-chemical parameter file." << std::endl;
         exit(-1);
-      }  
-      v=alg::CheckStereoChemistry(v,bond_table,angle_table,bond_tolerance,angle_tolerance);
+      }
+      // performs structural checks and filters the structure   
+      try { 
+        v=alg::CheckStereoChemistry(v,bond_table,angle_table,bond_tolerance,angle_tolerance);
+      } catch (std::exception& e) {       
+        std::cout << "An error occurred during the structure quality checks, stage 1:" << std::endl;    
+        std::cout << e.what() << std::endl;
+        exit(-1);
+      }
       cov = compute_coverage(v,glob_dist_list);
       std::cout << "Coverage after stereo-chemical checks: " << (float(cov.first)/float(cov.second)) << " (" << cov.first << " out of " << cov.second << " residues)" << std::endl;
-      v=alg::FilterClashes(v,nonbonded_table);
+      try {
+        v=alg::FilterClashes(v,nonbonded_table);
+      } catch (std::exception& e) {       
+        std::cout << "An error occurred during the structure quality checks, stage 2:" << std::endl;    
+        std::cout << e.what() << std::endl;
+        exit(-1);
+      }
       cov = compute_coverage(v,glob_dist_list);
       std::cout << "Coverage after clashing checks: " << (float(cov.first)/float(cov.second)) << " (" << cov.first << " out of " << cov.second << " residues)" << std::endl;
     }
     if (cov.first==0) {
-      std::cout << "Global LDT score: 0.0" << std::endl;
+      std::cout << "Global LDDT score: 0.0" << std::endl;
       return 0;
     }
-    Real ldt=LDTHA(v, glob_dist_list);
 
-    std::cout << "Global LDT score: " << ldt << std::endl;
-    std::cout << "Local LDT Score:" << std::endl;
-    std::cout << "Chain\tResName\tResNum\tScore" << std::endl;
-    String labels[]={"localldt0.5","localldt1","localldt2","ldtlocal4"};
+    // computes the lddt score   
+    String label="localldt";
+    std::pair<int,int> total_ov=alg::LocalDistDiffTest(v, glob_dist_list, cutoffs, sequence_separation, label);
+    Real lddt = static_cast<Real>(total_ov.first)/(static_cast<Real>(total_ov.second) ? static_cast<Real>(total_ov.second) : 1);
+    std::cout << "Global LDDT score: " << std::setprecision(4) << lddt << std::endl;
+    std::cout << "(" << std::fixed << total_ov.first << " conserved distances out of " << total_ov.second
+              << " checked, over " << cutoffs.size() << " thresholds)" << std::endl;
+
+    // prints the residue-by-residue statistics  
+    std::cout << "Local LDDT Score:" << std::endl;
+    std::cout << "Chain\tResName\tResNum\tScore\t(Conserved/Total, over " << cutoffs.size() << " thresholds)" << std::endl;
     for (ResidueViewIter rit=v.ResiduesBegin();rit!=v.ResiduesEnd();++rit){
       ResidueView ritv = *rit;
-      Real ldt_local_sum = 0;
-      if (ritv.HasProp("localldt0.5")) {
-        for (int n=0; n<4; ++n) {
-          ldt_local_sum+=ritv.GetFloatProp(labels[n]);
-        }
-        ldt_local_sum/=4.0;
-        std::cout << ritv.GetChain() << "\t" << ritv.GetName() << "\t" << ritv.GetNumber() << '\t' << ldt_local_sum << std::endl;
+      Real lddt_local = 0;
+      int conserved_dist = 0;
+      int total_dist = 0;      
+      if (ritv.HasProp(label)) {
+          lddt_local=ritv.GetFloatProp(label);
+          conserved_dist=ritv.GetIntProp(label+"_conserved");
+      total_dist=ritv.GetIntProp(label+"_total");
+      }
+      if (lddt_local!=0) {
+        std::cout << ritv.GetChain() << "\t" << ritv.GetName() << "\t" << ritv.GetNumber() << '\t' << std::setprecision(4) << lddt_local << "\t" << "("<< conserved_dist << "/" << total_dist << ")" <<std::endl;
       }
     }
     std::cout << std::endl;
diff --git a/modules/mol/alg/src/local_dist_diff_test.cc b/modules/mol/alg/src/local_dist_diff_test.cc
new file mode 100644
index 0000000000000000000000000000000000000000..74c6278e2075882cf2a35d32b97d75b742ebb678
--- /dev/null
+++ b/modules/mol/alg/src/local_dist_diff_test.cc
@@ -0,0 +1,618 @@
+#include <ost/log.hh>
+#include <ost/mol/mol.hh>
+#include "local_dist_diff_test.hh"
+#include <boost/concept_check.hpp>
+
+namespace ost { namespace mol { namespace alg {
+
+namespace {
+
+// helper function
+String swapped_name(const String& name)
+{
+  if (name=="OE1") return "OE2";
+  if (name=="OE2") return "OE1";
+
+  if (name=="OD1") return "OD2";
+  if (name=="OD2") return "OD1";
+
+  if (name=="CG1") return "CG2";
+  if (name=="CG2") return "CG1";
+
+  if (name=="CE1") return "CE2";
+  if (name=="CE2") return "CE1";  
+
+  if (name=="CD1") return "CD2";
+  if (name=="CD2") return "CD1";
+
+  if (name=="NH1") return "NH2";
+  if (name=="NH2") return "NH1";
+
+  return name;
+}
+
+// helper function
+bool swappable(const String& rname, const String& aname)
+{
+  if (rname=="GLU") {
+    return (aname=="OE1" || aname=="OE2");
+  }
+  if (rname=="ASP") {
+    return (aname=="OD1" || aname=="OD2");
+  }
+  if (rname=="VAL") {     
+
+    return (aname=="CG1" || aname=="CG2");
+  }
+  if (rname=="TYR" || rname=="PHE") {
+    return (aname=="CD1" || aname=="CD2" || aname=="CE1" || aname=="CE2");
+  }
+  if (rname=="LEU") {
+    return (aname=="CD1" || aname=="CD2");
+  }
+  if (rname=="ARG") {
+    return (aname=="NH1" || aname=="NH2");
+  }  
+  return false;
+}
+
+// helper function
+bool within_tolerance(Real mdl_dist, const std::pair<Real,Real>& values, Real tol)
+{
+
+  return (values.first-tol)<=mdl_dist && (values.second+tol)>=mdl_dist;
+}      
+
+// helper function
+std::pair<long int, long int> calc_overlap1(const ResidueRDMap& res_distance_list, const ResNum& rnum,
+                                    ChainView mdl_chain, int sequence_separation,
+                                    std::vector<Real>& tol_list, bool only_fixed, 
+                                    bool swap,std::vector<std::pair<long int, long int> >& overlap_list, bool log )
+{
+  std::pair<long int, long int> overlap(0, 0);
+  ResidueView mdl_res=mdl_chain.FindResidue(rnum); 
+  for (ResidueRDMap::const_iterator ai=res_distance_list.begin(); ai!=res_distance_list.end(); ++ai) {
+    const UAtomIdentifiers& uais = ai->first; 
+    const std::pair <Real,Real>& values = ai->second;
+    const UniqueAtomIdentifier& first_atom=uais.first;
+    const UniqueAtomIdentifier& second_atom=uais.second;
+    String name=swap ? swapped_name(first_atom.GetAtomName()) : first_atom.GetAtomName();
+    AtomView av1=mdl_res ? mdl_res.FindAtom(name) : AtomView();
+ 
+    if (only_fixed) {
+       if (std::abs(first_atom.GetResNum().GetNum()-second_atom.GetResNum().GetNum())<=sequence_separation) {
+          continue;
+        }
+      if (swappable(second_atom.GetResidueName(), second_atom.GetAtomName())) {
+          continue;
+      }
+    }
+    if (!only_fixed) {   
+      if (first_atom.GetResNum().GetNum()<=(second_atom.GetResNum().GetNum()+sequence_separation)) {
+        continue;
+      }    
+    }
+    ResidueView rv2=mdl_chain.FindResidue(second_atom.GetResNum());
+    overlap.second+=tol_list.size();
+    int rindex2=0;
+    int rindex1=mdl_res ? mdl_res.GetIndex() : -1;
+    if (!only_fixed && rindex1!=-1)
+      overlap_list[rindex1].second+=tol_list.size();
+    if (!rv2) {
+      continue;
+    }
+    rindex2=rv2.GetIndex();
+    if (!only_fixed)
+      overlap_list[rindex2].second+=tol_list.size();
+    AtomView av2=rv2.FindAtom(second_atom.GetAtomName());
+    if (!(av1 && av2)) {
+     continue;
+    }
+    Real mdl_dist=geom::Length(av1.GetPos()-av2.GetPos());
+    std::vector<Real>::const_reverse_iterator rend_it=tol_list.rend();
+    for (std::vector<Real>::const_reverse_iterator tol_list_it=tol_list.rbegin();tol_list_it!=rend_it;++tol_list_it) {
+      Real tol = * tol_list_it; 
+      if (within_tolerance(mdl_dist,values,tol)) {
+        if (log) {
+          LOG_VERBOSE("lddt:" << " " << av1.GetResidue().GetChain() << " " << av1.GetResidue().GetName() << " " << av1.GetResidue().GetNumber() << " " << av1.GetName() 
+                      << " " << av2.GetResidue().GetChain() << " " << av2.GetResidue().GetName() << " " << av2.GetResidue().GetNumber() << " " << av2.GetName() << " " 
+                      << mdl_dist << " " << values.first << " " << values.second << " " << tol << " " << "PASS")
+        }   
+        overlap.first+=1;
+        if (!only_fixed) {
+          overlap_list[rindex1].first+=1;
+          overlap_list[rindex2].first+=1;
+        }
+      } else {
+        if (log) {
+          LOG_VERBOSE("lddt:" << " " << av1.GetResidue().GetChain() << " " << av1.GetResidue().GetName() << " " << av1.GetResidue().GetNumber() << " " << av1.GetName() 
+             << " " << av2.GetResidue().GetChain() << " " << av2.GetResidue().GetName() << " " << av2.GetResidue().GetNumber() << " " << av2.GetName() << " " 
+             << mdl_dist << " " << values.first << " " << values.second << " " << tol << " " << "FAIL");
+        }  
+        break;  
+      }
+    }    
+  }
+  return overlap;
+}  
+
+// helper function used by the alignment-based Local Distance Difference Test
+std::pair<Real, Real> calc_overlap2(const seq::ConstSequenceHandle& ref_seq,
+                                    const seq::ConstSequenceHandle& mdl_seq,
+                                    int pos, Real tol, Real max_dist, 
+                                    bool only_fixed, bool swap)
+{
+  std::pair<Real, Real> overlap(0.0, 0.0);
+  EntityView ref=ref_seq.GetAttachedView();
+  ResidueView ref_res=ref_seq.GetResidue(pos);
+  if (!ref_res.IsValid()) {
+    return std::pair<Real,Real>(0.0, 0.0);
+  }
+  AtomViewList ref_atoms=ref_res.GetAtomList();
+  ResidueView mdl_res=mdl_seq.GetResidue(pos);
+  AtomViewList within;
+  if (max_dist<0) {
+    within=ref.GetAtomList();
+  }  
+  for (AtomViewList::iterator ai=ref_atoms.begin(),
+       ae=ref_atoms.end(); ai!=ae; ++ai) {
+    if (ai->GetElement()=="H") { continue; }
+    String name=swap ? swapped_name(ai->GetName()) : ai->GetName();
+    AtomView av1=mdl_res ? mdl_res.FindAtom(name) : AtomView();
+    if (max_dist>=0){ 
+      within=ref.FindWithin(ai->GetPos(), max_dist);
+    }
+    for (AtomViewList::iterator aj=within.begin(),
+         ae2=within.end(); aj!=ae2; ++aj) {
+      if (aj->GetElement()=="H" || 
+          aj->GetResidue().GetChain()!=ai->GetResidue().GetChain()) { 
+          continue; 
+      }
+      if (only_fixed) {
+        if (aj->GetResidue().GetNumber()==ref_res.GetNumber()) {
+          continue;
+        }
+        if (swappable(aj->GetResidue().GetName(), aj->GetName())) {
+          continue;
+        }
+        overlap.second+=1.0;
+        // map from residue index to position in alignment
+        try {
+          int aln_pos=ref_seq.GetPos(aj->GetResidue().GetIndex());
+          ResidueView r2=mdl_seq.GetResidue(aln_pos);
+          if (!r2.IsValid()) {
+            continue;
+          }
+          AtomView av2=r2.FindAtom(aj->GetName());
+          if (!(av1 && av2)) {
+            continue;
+          }
+          Real mdl_dist=geom::Length(av1.GetPos()-av2.GetPos());
+          Real ref_dist=geom::Length(ai->GetPos()-aj->GetPos());
+          if (std::abs(mdl_dist-ref_dist)<tol) {
+            overlap.first+=1;
+          }
+        } catch(...) { }
+        continue;
+      } else {
+        if (aj->GetResidue().GetNumber()>ref_res.GetNumber()) {
+          overlap.second+=1.0;    
+
+          try {
+           int aln_pos=ref_seq.GetPos(aj->GetResidue().GetIndex());
+            ResidueView r2=mdl_seq.GetResidue(aln_pos);
+            if (!r2.IsValid()) {
+              continue;
+            }
+            AtomView av2=r2.FindAtom(aj->GetName());
+            if (!(av1 && av2)) {
+              continue;
+            }
+            Real mdl_dist=geom::Length(av1.GetPos()-av2.GetPos());
+            Real ref_dist=geom::Length(ai->GetPos()-aj->GetPos());
+            if (std::abs(mdl_dist-ref_dist)<tol) {
+              overlap.first+=1;
+            }
+          } catch (...) { }
+        }  
+      }
+    }      
+  }
+  return overlap;
+}
+
+// for each residue with multiple possible nomenclature conventions, checks which choice (switched or not) 
+// of atom nomenclature gives the highest lddt score then changes the naming convention of the input 
+// entity view accordingly
+void check_and_swap(const GlobalRDMap& glob_dist_list, const EntityView& mdl, std::vector<Real> cutoff_list, int sequence_separation,  std::vector<std::pair<long int, long int> > overlap_list)
+{
+  ChainView mdl_chain=mdl.GetChainList()[0]; 
+  XCSEditor edi=mdl.GetHandle().EditXCS(BUFFERED_EDIT);
+  for (GlobalRDMap::const_iterator i=glob_dist_list.begin(); i!=glob_dist_list.end(); ++i) {  
+    ResNum rnum =  i->first;
+    if (i->second.size()==0) {
+      continue;
+    }
+    ResidueView mdl_res=mdl_chain.FindResidue(rnum); 
+    if (!mdl_res) {   
+      continue;
+    }
+    String rname = mdl_res.GetName();
+    if (!(rname=="GLU" || rname=="ASP" || rname=="VAL" || rname=="TYR" ||
+          rname=="PHE" || rname=="LEU" || rname=="ARG")) {
+      continue;
+    }
+    std::pair<long int, long int> ov1=calc_overlap1(i->second, rnum,mdl_chain, sequence_separation,
+                                          cutoff_list, true, 
+                                          false, overlap_list,false);
+ 
+    std::pair<long int, long int> ov2=calc_overlap1(i->second, rnum, mdl_chain, sequence_separation,
+                                          cutoff_list, true, 
+                                          true, overlap_list,false); 
+
+    if (static_cast<Real>(ov1.first)/ov1.second<
+        static_cast<Real>(ov2.first)/ov2.second) {
+      AtomViewList atoms=mdl_res.GetAtomList();
+      for (AtomViewList::iterator j=atoms.begin(), e2=atoms.end(); j!=e2; ++j) {
+        if (swappable(rname, j->GetName())) {
+          edi.RenameAtom(j->GetHandle(), swapped_name(j->GetName()));
+        }
+      }
+    } 
+  }
+}
+
+// helper function to update existence map entries for multiple reference input structures
+void update_existence_map (ExistenceMap& ex_map, const EntityView& ev, int ref_counter)
+{
+  AtomViewList ev_atom=ev.GetAtomList();
+  for (AtomViewList::iterator ev_atom_it=ev_atom.begin(); ev_atom_it!=ev_atom.end();++ev_atom_it) {
+    UniqueAtomIdentifier uai (ev_atom_it->GetResidue().GetChain().GetName(),ev_atom_it->GetResidue().GetNumber(),ev_atom_it->GetResidue().GetName(),ev_atom_it->GetName());
+    ex_map[uai] |=1 << ref_counter;
+  }
+}
+
+// helper function for super-fast lookup of atom existence in multiple reference input structures
+int in_existence_map(const ExistenceMap& ex_map, const UniqueAtomIdentifier& uai) 
+{
+  ExistenceMap::const_iterator find_uai_ci = ex_map.find(uai);
+  return find_uai_ci!=ex_map.end() ? find_uai_ci->second : 0;
+}    
+
+// merges distance lists from multiple reference structures. The login is described in the code
+void merge_distance_lists(GlobalRDMap& ref_dist_map, const GlobalRDMap& new_dist_map, ExistenceMap& ex_map, const EntityView& ref,int ref_counter)
+{
+  // iterate over the residues in the ref_dist_map   
+  for (GlobalRDMap::iterator ref_dist_map_it=ref_dist_map.begin();ref_dist_map_it!=ref_dist_map.end();++ref_dist_map_it) {
+    ResNum ref_resnum = ref_dist_map_it->first;
+    GlobalRDMap::const_iterator find_new_res_ci = new_dist_map.find(ref_resnum);
+    //if the residue is found in new_dist_map,  
+    if (find_new_res_ci != new_dist_map.end()) {
+      //iterate over the the reference distances in the ResidueDistanceMap  
+      //It's on purpose that we don't increase the loop variable inside
+      //the for statement! This is required to make iteration work when erasing
+      //an element from the map while iterating over it.
+      for (ResidueRDMap::iterator
+           ref_res_map_it = ref_dist_map_it->second.begin();
+           ref_res_map_it!=ref_dist_map_it->second.end();) {
+        const UAtomIdentifiers& ref_rd = ref_res_map_it->first;
+        bool erased=false;
+        std::pair<Real,Real>& ref_minmax = ref_res_map_it->second;
+        ResidueRDMap::const_iterator find_new_rd_ci = find_new_res_ci->second.find(ref_rd);
+        // if you find the distance in the residue new, udate min and max  
+        if (find_new_rd_ci != find_new_res_ci->second.end()) {
+          if (find_new_rd_ci->second.first < ref_minmax.first) {
+            ref_minmax.first=find_new_rd_ci->second.first;
+          } else if (find_new_rd_ci->second.second > ref_minmax.second) {
+            ref_minmax.second=find_new_rd_ci->second.second;
+          }
+        } else {              
+          // if you don't find it in the residue new, check that it is not missing because it is too long  
+          UniqueAtomIdentifier first_atom_to_find = ref_rd.first;
+          UniqueAtomIdentifier second_atom_to_find = ref_rd.second;  
+          // if both atoms are there, remove the distance from the ref_dist_map,
+          if ((ref.FindAtom(first_atom_to_find.GetChainName(),first_atom_to_find.GetResNum(),first_atom_to_find.GetAtomName()).IsValid() &&
+               ref.FindAtom(second_atom_to_find.GetChainName(),second_atom_to_find.GetResNum(),second_atom_to_find.GetAtomName()).IsValid()) ) {
+            erased=true;
+            ref_dist_map_it->second.erase(ref_res_map_it++);
+          }
+        }
+        if (!erased) {
+          ++ref_res_map_it;
+        }
+      }
+      // now iterate over the the new  reference distances in residue new
+      for (ResidueRDMap::const_iterator new_res_map_it = find_new_res_ci->second.begin(); new_res_map_it!=find_new_res_ci->second.end();++new_res_map_it) {
+        UAtomIdentifiers new_rd = new_res_map_it->first;
+        std::pair<Real,Real> new_minmax = new_res_map_it->second;
+        ResidueRDMap::const_iterator find_ref_rd_ci = ref_dist_map_it->second.find(new_rd);
+        // if the distance is found in the residue ref, 
+        // it has been taken care of before. If not
+        if (find_ref_rd_ci==ref_dist_map_it->second.end()) {
+          UniqueAtomIdentifier first_atom_to_find = new_rd.first;
+          UniqueAtomIdentifier second_atom_to_find = new_rd.second;
+          // check that there isn't a structure already processed where both atoms are in
+          // if there is none, add the distance to the residue ref map 
+          if (!(in_existence_map(ex_map,first_atom_to_find) & in_existence_map(ex_map,second_atom_to_find))) {
+            ref_dist_map_it->second[new_rd]= new_minmax; 
+          }
+        }      
+      } 
+    }
+  // if the residue was not found in the new list, it means that it is 
+  // absent in the new structure, no new information
+  }
+  // now iterate over the residues in the new_list
+  for (GlobalRDMap::const_iterator new_dist_map_it=new_dist_map.begin();new_dist_map_it!=new_dist_map.end();++new_dist_map_it) {
+    ResNum new_resnum = new_dist_map_it->first;
+    GlobalRDMap::const_iterator find_ref_res_ci = ref_dist_map.find(new_resnum);
+    // if the residue is found in new_dist_map, it has been taken care before,
+    // if not, add it to the res_dist_map:
+      if (find_ref_res_ci == ref_dist_map.end()) {
+      ref_dist_map[new_resnum] = new_dist_map_it->second;           
+    }
+  }
+}
+
+}
+
+// helper function
+bool IsStandardResidue(String rn)
+{
+  String upper_rn=rn;
+  std::transform(rn.begin(),rn.end(),rn.begin(),toupper);
+  if (upper_rn == "ALA" ||    
+  upper_rn == "ARG" ||
+  upper_rn == "ASN" ||
+  upper_rn == "ASP" ||
+  upper_rn == "GLN" ||
+  upper_rn == "GLU" ||
+  upper_rn == "LYS" ||
+  upper_rn == "SER" ||
+  upper_rn == "CYS" ||      
+  upper_rn == "TYR" ||  
+  upper_rn == "TRP" || 
+  upper_rn == "THR" ||
+  upper_rn == "VAL" ||
+  upper_rn == "ILE" ||
+  upper_rn == "MET" ||
+  upper_rn == "LEU" ||  
+  upper_rn == "GLY" ||  
+  upper_rn == "PRO" ||  
+  upper_rn == "HIS" ||  
+  upper_rn == "PHE") {
+    return true;
+  }  
+  return false;
+}  
+
+
+GlobalRDMap CreateDistanceList(const EntityView& ref,Real max_dist)
+{
+ GlobalRDMap 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())) {
+     ResidueRDMap res_dist_list;
+     ResNum rnum = i->GetNumber();  
+     AtomViewList ref_atoms=i->GetAtomList();
+     AtomViewList within;
+     if (max_dist<0){
+       within=ref.GetAtomList();
+     }  
+     for (AtomViewList::iterator ai=ref_atoms.begin(), ae=ref_atoms.end(); ai!=ae; ++ai) {
+       UniqueAtomIdentifier first_atom(ai->GetResidue().GetChain().GetName(),ai->GetResidue().GetNumber(),ai->GetResidue().GetName(),ai->GetName());
+       if (ai->GetElement()=="H") { continue; }
+       if (max_dist>=0){ 
+         within=ref.FindWithin(ai->GetPos(), max_dist);
+       }
+       for (AtomViewList::iterator aj=within.begin(), ae2=within.end(); aj!=ae2; ++aj) {      
+         UniqueAtomIdentifier second_atom(aj->GetResidue().GetChain().GetName(),aj->GetResidue().GetNumber(),aj->GetResidue().GetName(),aj->GetName());
+         if (aj->GetElement()=="H" ||
+             aj->GetResidue().GetChain()!=ai->GetResidue().GetChain()) {
+             continue;
+         }
+         Real dist=geom::Length(ai->GetPos()-aj->GetPos());
+         UAtomIdentifiers atoms = std::make_pair<UniqueAtomIdentifier,UniqueAtomIdentifier>(first_atom,second_atom); 
+         std::pair<Real,Real> values = std::make_pair<Real,Real>(dist,dist);  
+         res_dist_list[atoms]=values;
+       }
+     }   
+     dist_list[rnum]=res_dist_list;
+   }
+ } 
+ return dist_list;
+} 
+
+GlobalRDMap CreateDistanceListFromMultipleReferences(const std::vector<EntityView>& ref_list, std::vector<Real>& cutoff_list, int sequence_separation, Real max_dist)
+{
+  int ref_counter=0;  
+  ExistenceMap ex_map;  
+  GlobalRDMap glob_dist_list = CreateDistanceList(ref_list[0],max_dist);
+  update_existence_map (ex_map,ref_list[0],ref_counter);
+  ref_counter++;  
+  for (std::vector<EntityView>::const_iterator ref_list_it=ref_list.begin()+1;ref_list_it!=ref_list.end();++ref_list_it) {
+       EntityView ref = *ref_list_it;
+       std::vector<std::pair<long int, long int> > overlap_list(ref.GetResidueCount(), std::pair<long int, long int>(0, 0));
+       check_and_swap(glob_dist_list,ref,cutoff_list,sequence_separation,overlap_list);
+       GlobalRDMap new_dist_list=CreateDistanceList(ref,max_dist);
+       merge_distance_lists(glob_dist_list,new_dist_list,ex_map,ref,ref_counter);
+       update_existence_map (ex_map,ref,ref_counter); 
+       ref_counter++;
+  }    
+  return glob_dist_list;  
+}
+
+void PrintResidueRDMap(const ResidueRDMap& res_dist_list)
+{
+  for (ResidueRDMap::const_iterator res_dist_list_it = res_dist_list.begin();res_dist_list_it!=res_dist_list.end();++res_dist_list_it) {
+    UAtomIdentifiers uais = res_dist_list_it->first;
+    std::pair<Real,Real> minmax = res_dist_list_it->second;
+    std::cout << uais.first.GetChainName() << " " << uais.first.GetResNum() << " " << uais.first.GetResidueName() << " " << uais.first.GetAtomName() << " " <<
+                 uais.second.GetChainName() << " " << uais.second.GetResNum() << " " << uais.second.GetResidueName() << " " << uais.second.GetAtomName() << " " <<
+                 minmax.first << " " << minmax.second << std::endl;       
+  }
+}
+
+
+void PrintGlobalRDMap(const GlobalRDMap& glob_dist_list){
+  for (GlobalRDMap::const_iterator glob_dist_list_it = glob_dist_list.begin();glob_dist_list_it!=glob_dist_list.end();++glob_dist_list_it) {
+    if (glob_dist_list_it->second.size()!=0) {  
+      PrintResidueRDMap(glob_dist_list_it->second);
+    }    
+  }    
+}
+
+
+
+std::pair<long int,long int> LocalDistDiffTest(const EntityView& mdl, const GlobalRDMap& glob_dist_list,
+                   std::vector<Real> cutoff_list, int sequence_separation, const String& local_lddt_property_string)
+{
+  if (!mdl.GetResidueCount()) {
+    LOG_WARNING("model structures doesn't contain any residues");
+    return std::make_pair<long int,long int>(0,0);
+  }
+  if (glob_dist_list.size()==0) {
+    LOG_WARNING("global reference list is empty");
+    return std::make_pair<long int,long int>(0,0);
+  }
+  std::vector<std::pair<long int, long int> > overlap_list(mdl.GetResidueCount(), std::pair<long int, long int>(0, 0));
+  check_and_swap(glob_dist_list,mdl,cutoff_list,sequence_separation,overlap_list);
+  ChainView mdl_chain=mdl.GetChainList()[0];  
+  overlap_list.clear();
+  std::pair<long int, long int> total_ov(0, 0);
+  for (GlobalRDMap::const_iterator i=glob_dist_list.begin(), e=glob_dist_list.end(); i!=e; ++i) {
+    ResNum rn = i->first;
+    if (i->second.size()!=0) {
+      std::pair<long int, long int> ov1=calc_overlap1(i->second, rn, mdl_chain, sequence_separation, cutoff_list, 
+                                            false, false, overlap_list,true);
+      total_ov.first+=ov1.first;
+      total_ov.second+=ov1.second;
+    }
+
+  }
+  for (GlobalRDMap::const_iterator i=glob_dist_list.begin(),
+       e=glob_dist_list.end();i!=e; ++i) {
+    ResNum rn = i->first;
+    if(local_lddt_property_string!="") {
+      ResidueView mdlr=mdl_chain.FindResidue(rn);
+      if (mdlr.IsValid()) {
+        int mdl_res_index =mdlr.GetIndex();
+        Real local_lddt=static_cast<Real>(overlap_list[mdl_res_index].first)/(static_cast<Real>(overlap_list[mdl_res_index].second) ? static_cast<Real>(overlap_list[mdl_res_index].second) : 1);
+        mdlr.SetFloatProp(local_lddt_property_string, local_lddt);
+        mdlr.SetIntProp(local_lddt_property_string+"_conserved", overlap_list[mdl_res_index].first);
+        mdlr.SetIntProp(local_lddt_property_string+"_total", overlap_list[mdl_res_index].second);
+      }
+    }
+  }
+  overlap_list.clear();
+  return std::make_pair<long int,long int>(total_ov.first,total_ov.second);
+}
+
+Real LocalDistDiffTest(const EntityView& mdl, const EntityView& target, Real cutoff, Real max_dist, const String& local_lddt_property_string)
+{
+   std::vector<Real> cutoffs;
+   cutoffs.push_back(cutoff);
+   GlobalRDMap glob_dist_list = CreateDistanceList(target,max_dist);
+   int sequence_separation = 0; 
+   std::pair<long int,long int>  total_ov = LocalDistDiffTest(mdl, glob_dist_list, cutoffs, sequence_separation, local_lddt_property_string);
+   return static_cast<Real>(total_ov.first)/(static_cast<Real>(total_ov.second) ? static_cast<Real>(total_ov.second) : 1);
+}
+
+
+Real LocalDistDiffTest(const ost::seq::AlignmentHandle& aln,
+                   Real cutoff, Real max_dist, int ref_index, int mdl_index)
+{
+  seq::ConstSequenceHandle ref_seq=aln.GetSequence(ref_index);
+  seq::ConstSequenceHandle mdl_seq=aln.GetSequence(mdl_index);  
+  if (!ref_seq.HasAttachedView()) {
+    LOG_ERROR("reference sequence doesn't have a view attached.");
+    return 0.0;
+  }
+  if (!mdl_seq.HasAttachedView()) {
+    LOG_ERROR("model sequence doesn't have a view attached");
+    return 0.0;
+  }
+  XCSEditor edi=ref_seq.GetAttachedView().GetHandle().EditXCS(BUFFERED_EDIT);
+  for (int i=0; i<aln.GetLength(); ++i) {
+    ResidueView mdl_res=mdl_seq.GetResidue(i);
+    if (!mdl_res) {
+      continue;
+    }
+    String rname=mdl_res.GetName();
+    if (!(rname=="GLU" || rname=="ASP" || rname=="VAL" || rname=="TYR" || 
+         rname=="PHE" || rname=="LYS" || rname=="ARG")) {
+      continue;
+    }
+    std::pair<Real, Real> ov1=calc_overlap2(ref_seq, mdl_seq, i,
+                                            cutoff, max_dist, true, 
+                                            false);
+    std::pair<Real, Real> ov2=calc_overlap2(ref_seq, mdl_seq, i,
+                                            cutoff, max_dist, true, 
+                                            true);
+    if (ov1.first/ov1.second<ov2.first/ov2.second) {
+     AtomViewList atoms=mdl_res.GetAtomList();
+     for (AtomViewList::iterator j=atoms.begin(), 
+          e2=atoms.end(); j!=e2; ++j) {
+       if (swappable(rname, j->GetName())) {
+         edi.RenameAtom(j->GetHandle(), swapped_name(j->GetName()));
+       }
+     }
+    }
+  }
+  std::pair<Real, Real> total_ov(0.0, 0.0);
+  for (int i=0; i<aln.GetLength(); ++i) {
+     std::pair<Real, Real> ov1=calc_overlap2(ref_seq, mdl_seq, i, cutoff, 
+                                             max_dist, false, false);
+     total_ov.first+=ov1.first;
+     total_ov.second+=ov1.second;
+  }
+   return total_ov.first/(total_ov.second ? total_ov.second : 1);
+}
+
+Real LDDTHA(EntityView& v, const GlobalRDMap& global_dist_list, int sequence_separation)
+{
+    std::vector<Real> cutoffs;
+    cutoffs.push_back(0.5);
+    cutoffs.push_back(1.0);
+    cutoffs.push_back(2.0);
+    cutoffs.push_back(4.0);
+    String label="locallddt";
+    std::pair<long int,long int> total_ov=alg::LocalDistDiffTest(v, global_dist_list, cutoffs,  sequence_separation, label);
+    return static_cast<Real>(total_ov.first)/(static_cast<Real>(total_ov.second) ? static_cast<Real>(total_ov.second) : 1);
+}
+
+// debugging code
+/*
+Real OldStyleLDDTHA(EntityView& v, const GlobalRDMap& global_dist_list)
+{
+    Real lddt =0;
+    std::vector<Real> cutoffs05;
+    cutoffs05.push_back(0.5);
+    std::pair<Real,Real> lddt05o=alg::LocalDistDiffTest(v, global_dist_list, cutoffs05, "locallddt0.5");
+    std::vector<Real> cutoffs1;
+    cutoffs1.push_back(1.0);
+    std::pair<Real,Real> lddt1o=alg::LocalDistDiffTest(v, global_dist_list, cutoffs1, "locallddt1");
+    std::vector<Real> cutoffs2;
+    cutoffs2.push_back(2.0);
+    std::pair<Real,Real> lddt2o=alg::LocalDistDiffTest(v, global_dist_list, cutoffs2, "locallddt2");
+    std::vector<Real> cutoffs4;
+    cutoffs4.push_back(4.0);
+    std::pair<Real,Real> lddt4o=alg::LocalDistDiffTest(v, global_dist_list, cutoffs4, "locallddt4");
+    Real lddt05 = lddt05o.first/(lddt05o.second ? lddt05o.second : 1);
+    Real lddt1 = lddt1o.first/(lddt1o.second ? lddt1o.second : 1);
+    Real lddt2 = lddt2o.first/(lddt2o.second ? lddt2o.second : 1);
+    Real lddt4 = lddt4o.first/(lddt4o.second ? lddt4o.second : 1);            
+    lddt = (lddt05+lddt1+lddt2+lddt4)/4.0;
+    for (ResidueViewIter rit=v.ResiduesBegin();rit!=v.ResiduesEnd();++rit){
+      ResidueView ritv = *rit;
+      if (ritv.HasProp("locallddt0.5")) {
+        Real lddt_local = (ritv.GetFloatProp("locallddt0.5")+ritv.GetFloatProp("locallddt1")+ritv.GetFloatProp("locallddt2")+ritv.GetFloatProp("locallddt4"))/4.0;
+        ritv.SetFloatProp("locallddt",lddt_local);
+      }    
+    }    
+    return lddt;
+}
+*/
+
+}}}
diff --git a/modules/mol/alg/src/local_dist_diff_test.hh b/modules/mol/alg/src/local_dist_diff_test.hh
new file mode 100644
index 0000000000000000000000000000000000000000..9803f0a723d3c77ae8b1332ef5ab09e444ae5ff1
--- /dev/null
+++ b/modules/mol/alg/src/local_dist_diff_test.hh
@@ -0,0 +1,212 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+#ifndef OST_MOL_ALG_LOCAL_DIST_TEST_HH
+#define OST_MOL_ALG_LOCAL_DIST_TEST_HH
+
+#include <ost/mol/entity_view.hh>
+#include <ost/mol/alg/module_config.hh>
+#include <ost/seq/alignment_handle.hh>
+
+namespace ost { namespace mol { namespace alg {
+  
+/// \brief Contains the infomation needed to uniquely identify an atom in a structure
+///
+/// Used by the the Local Distance Difference Test classes and functions
+class DLLEXPORT_OST_MOL_ALG UniqueAtomIdentifier
+{
+  
+public:
+  /// \brief Constructor with all the relevant information  
+  UniqueAtomIdentifier(const String& chain,const ResNum& residue,const String& residue_name, const String& atom): chain_(chain),residue_(residue),residue_name_(residue_name),atom_(atom) {}  
+
+  // to make the compiler happy (boost python map suite)
+  UniqueAtomIdentifier(): chain_(""),residue_(ResNum(1)),residue_name_(""),atom_("") {}  
+
+  /// \brief Returns the name of the chain to which the atom belongs, as a String  
+  String GetChainName() const { return chain_; } 
+
+  /// \brief Returns the ResNum of the residue to which the atom belongs
+  ResNum GetResNum() const { return residue_; }  
+
+  /// \brief Returns the name of the residue to which the atom belongs, as a String
+  String GetResidueName() const { return residue_name_; }
+
+  /// \brief Returns the name of the atom, as a String
+  String GetAtomName() const { return atom_; }
+
+  // required because UniqueAtomIdentifier is used as a key for a std::map  
+  bool operator==(const UniqueAtomIdentifier& rhs) const {
+    return chain_==rhs.chain_ && residue_==rhs.residue_ && atom_==rhs.atom_;
+  }
+
+  // required because UniqueAtomIdentifier is used as a key for a std::map  
+  bool operator<(const UniqueAtomIdentifier& rhs) const {
+    int cc=chain_.compare(rhs.chain_);
+    if (cc) {
+      return cc<0;
+    }
+    if (residue_<rhs.residue_) {
+      return true;
+    } else if (residue_>rhs.residue_) {
+     return false;
+    }
+    return atom_.compare(rhs.atom_)<0;
+  }   
+private:
+
+  String chain_;
+  ResNum residue_;
+  String residue_name_;
+  String atom_;    
+};
+
+// typedef used to make the code cleaner
+typedef std::pair<UniqueAtomIdentifier,UniqueAtomIdentifier> UAtomIdentifiers;
+
+/// \brief Residue distance list. 
+///
+/// Container for all the interatomic distances that are checked in a Local Distance Difference Test 
+/// and are originating from a single specific residue 
+typedef std::map<std::pair<UniqueAtomIdentifier,UniqueAtomIdentifier>,std::pair<Real,Real> > ResidueRDMap;
+
+/// \brief Global distance list. 
+///
+/// Container for all the residue-based interatomic distance lists that are checked in a Local Distance Difference Test
+/// and  belong to the same structure
+typedef std::map<ost::mol::ResNum,ResidueRDMap> GlobalRDMap;
+
+// used by the multi-reference distance-list generator function
+typedef std::map<UniqueAtomIdentifier,int> ExistenceMap;
+
+/// \brief Calculates number of distances conserved in a model, given a list of distances to check and a model
+///
+/// Calculates the two values needed to determine the Local Distance Difference Test for a given model, i.e.
+/// the number of conserved distances in the model and the number of total distances in the reference structure. 
+/// The function requires a list of distances to check, a model on which the distances are checked, and a 
+/// list of tolerance thresholds that are used to determine if the distances are conserved. 
+/// 
+/// The function only processes standard residues in the first chains of the model and of the reference
+/// For residues with symmetric sidechains (GLU, ASP, ARG, VAL, PHE, TYR), the 
+/// naming of the atoms is ambigous. For these residues, the function computes the Local Distance Difference 
+/// Test score that each naming convention would generate when considering all non-ambigous surrounding atoms.
+/// The solution that gives higher score is then picked to compute the final Local Difference
+/// Distance Score for the whole model.
+///
+/// A sequence separation parameter can be passed to the function. If this happens, only distances between residues
+/// whose separation is higher than the provided parameter are considered when computing the score. 
+///
+/// If a string is provided as an argument to the function, residue-per-residue statistics are stored as 
+/// residue properties. Specifically, the local residue-based lddt score is stored in a float property named
+/// as the provided string, while the residue-based number of conserved and total distances are saved in two 
+/// int properties named <string>_conserved and <string>_total.
+std::pair<long int,long int> DLLEXPORT_OST_MOL_ALG LocalDistDiffTest(const EntityView& mdl,
+                                         const GlobalRDMap& dist_list,
+                                         std::vector<Real> cutoff_list,
+                                         int sequence_separation = 0, 
+                                         const String& local_ldt_property_string="");
+
+/// \brief Calculates the Local Distance Difference Score for a given model with respect to a given target
+///
+/// Calculates the Local Distance Difference Test score for a given model with respect to a given reference structure. Requires
+/// a model, a reference structure, a list of thresholds that are used to determine if distances are conserved, and an inclusion
+/// radius value used to determine which distances are checked.
+/// 
+/// The function only processes standard residues in the first chains of the model and of the reference
+/// For residues with symmetric sidechains (GLU, ASP, ARG, VAL, PHE, TYR), the 
+/// naming of the atoms is ambigous. For these residues, the function computes the Local Distance Difference 
+/// Test score that each naming convention would generate when considering all non-ambigous surrounding atoms.
+/// The solution that gives higher score is then picked to compute the final Local Difference
+/// Distance Score for the whole model.
+///
+/// If a string is provided as an argument to the function, residue-per-residue statistics are stored as 
+/// residue properties. Specifically, the local residue-based lddt score is stored in a float property named
+/// as the provided string, while the residue-based number of conserved and total distances are saved in two 
+/// int properties named <string>_conserved and <string>_total.
+Real DLLEXPORT_OST_MOL_ALG LocalDistDiffTest(const EntityView& mdl,
+                                         const EntityView& target,
+                                         Real cutoff, 
+                                         Real max_dist,
+                                         const String& local_ldt_property_string="");
+/// \brief Calculates the Local Distance Difference Test score for a given model starting from an alignment between a reference structure and the model. 
+///
+/// Calculates the Local Distance Difference Test score given an alignment between a model and a taget structure.
+/// Requires a threshold on which to calculate the score and an inclusion radius to determine the interatiomic 
+/// distances to check. Obviously, the strucvtures of the model and the reference must be attached to the alignment.
+/// By default the first structure in the alignment is considered the reference and the second is considered the
+/// model, but this can be changed by passing to the function the indexes of the two structures in the ref_index
+/// and mdl_index parameters.
+/// BEWARE: This algorithm uses the old version of the Local Distance Difference Test 
+/// (multiple cycles, single threshold, etc. ) and will give a slightly different result than the other functions
+Real DLLEXPORT_OST_MOL_ALG LocalDistDiffTest(const ost::seq::AlignmentHandle& aln,
+                                         Real cutoff, Real max_dist,
+                                         int ref_index=0, int mdl_index=1);
+
+/// \brief Computes the Local Distance Difference High-Accuracy Test given a list of distances to check
+///
+/// Computes the Local Distance Difference High-Accuracy Test (with threshold 0.5,1,2 and 4 Angstrom)
+/// Requires a list of distances to check and a model for which the score is computed
+///
+/// A sequence separation parameter can be passed to the function. If this happens, only distances between residues
+/// whose separation is higher than the provided parameter are considered when computing the score. 
+Real DLLEXPORT_OST_MOL_ALG LDDTHA(EntityView& v, const GlobalRDMap& global_dist_list, int sequence_separation=0);
+
+/// \brief Creates a list of distances to check during a Local Difference Distance Test
+///
+/// Requires a reference structure and an inclusion radius (max_dist)
+GlobalRDMap DLLEXPORT_OST_MOL_ALG CreateDistanceList(const EntityView& ref,Real max_dist);
+
+/// \brief Creates a list of distances to check during a Local Difference Distance Test starting from multiple reference structures
+///
+/// Requires a list of reference structure and an inclusion radius (max_dist).
+/// 
+/// The structures in the list have to be properly prepared before being passed 
+/// to the function. Corresponding residues in the structures must have the same residue number, the same chain name,
+/// etc. Gaps are allowed and automatically dealt with: if information about a distance is present in at least one of
+/// the structures, it will be considered.  
+///
+///
+/// If a distance between two atoms is shorter than the inclusion radius in all structures in which the two atoms are 
+/// present, it is included in the list. However, if the distance is longer than the inclusion radius in at least one 
+/// of the structures, it is not be considered a local interaction and is exluded from the list
+///
+/// The function takes care of residues with ambigous symmetric sidechains. To decide which naming convention to use, the functions
+/// computes a local distance score of each reference structure with the first reference structure in the list, using only non ambigously-named atoms. 
+/// It picks then the naming convention that gives the highest score, guaranteeing that all references are processed with the correct atom names.
+///
+/// The cutoff list that will later be used to compute the Local Distance Difference Test score and the  sequence separation parameter 
+/// must be passed to the function. These parameters do not influence the output distance list, which always includes all distances
+/// within the provided max_dist (to make it consistent with the single-reference corresponding function). However, the parameters are used when
+/// dealing with the naming convention of residues with ambiguous nomenclature. 
+GlobalRDMap DLLEXPORT_OST_MOL_ALG CreateDistanceListFromMultipleReferences(const std::vector<EntityView>& ref_list,std::vector<Real>& cutoff_list, int sequence_separation, Real max_dist);
+
+/// \brief Prints all distances in a global distance list to standard output
+void DLLEXPORT_OST_MOL_ALG PrintGlobalRDMap(const GlobalRDMap& glob_dist_list);
+
+/// \brief Prints all distances in a residue distance list to standard output
+void DLLEXPORT_OST_MOL_ALG PrintResidueRDMap(const ResidueRDMap& res_dist_list);
+
+// required by some helper function. Cannot reuse similar functions in other modules without creating
+// circular dependencies
+bool DLLEXPORT_OST_MOL_ALG IsStandardResidue(String rn);
+
+}}}
+
+#endif
+
+
diff --git a/modules/mol/alg/src/local_dist_test.cc b/modules/mol/alg/src/local_dist_test.cc
deleted file mode 100644
index 430dd31bebb4e5c5bea26461df9b253e8bc0d608..0000000000000000000000000000000000000000
--- a/modules/mol/alg/src/local_dist_test.cc
+++ /dev/null
@@ -1,492 +0,0 @@
-#include <ost/log.hh>
-#include <ost/mol/mol.hh>
-#include "local_dist_test.hh"
-#include <boost/concept_check.hpp>
-
-namespace ost { namespace mol { namespace alg {
-
-namespace {
-
-String swapped_name(const String& name)
-{
-  if (name=="OE1") return "OE2";
-  if (name=="OE2") return "OE1";
-
-  if (name=="OD1") return "OD2";
-  if (name=="OD2") return "OD1";
-
-  if (name=="CG1") return "CG2";
-  if (name=="CG2") return "CG1";
-
-  if (name=="CE1") return "CE2";
-  if (name=="CE2") return "CE1";  
-
-  if (name=="CD1") return "CD2";
-  if (name=="CD2") return "CD1";
-
-  if (name=="NH1") return "NH2";
-  if (name=="NH2") return "NH1";
-
-  return name;
-}
-
-bool swappable(const String& rname, const String& aname)
-{
-  if (rname=="GLU") {
-    return (aname=="OE1" || aname=="OE2");
-  }
-  if (rname=="ASP") {
-    return (aname=="OD1" || aname=="OD2");
-  }
-  if (rname=="VAL") {     
-
-    return (aname=="CG1" || aname=="CG2");
-  }
-  if (rname=="TYR" || rname=="PHE") {
-    return (aname=="CD1" || aname=="CD2" || aname=="CE1" || aname=="CE2");
-  }
-  if (rname=="ARG") {
-    return (aname=="NH1" || aname=="NH2");
-  }  
-  return false;
-}
-
-std::pair<bool,Real> within_tolerance(Real mdl_dist, const ReferenceDistance& ref_dist, Real tol)
-{
-  Real min = ref_dist.GetMaxDistance();
-  Real max = ref_dist.GetMaxDistance();
-  bool within_tol = false;
-  Real difference = 0;
-  if (mdl_dist>=min && mdl_dist <=max) {
-    within_tol=true;
-  } else if (mdl_dist < min && std::abs(min-mdl_dist) < tol) {
-    within_tol = true;
-  } else if (mdl_dist > max && std::abs(mdl_dist-max) < tol) {
-    within_tol = true;
-  }
-  if (within_tol == false) {
-    if (mdl_dist > max) {
-      difference = mdl_dist-(max+tol);
-    } else {
-      difference = mdl_dist-(min-tol);
-    }
-  }  
-  return std::make_pair<bool,Real>(within_tol,difference);  
-}      
-
-
-std::pair<Real, Real> calc_overlap1(const ResidueDistanceList& res_distance_list, 
-                                    ChainView mdl_chain, 
-                                    Real tol, bool only_fixed, 
-                                    bool swap,std::vector<std::pair<Real, Real> >& overlap_list, bool log )
-{
-  std::pair<Real, Real> overlap(0.0, 0.0);
-
-  ResidueView mdl_res=mdl_chain.FindResidue(res_distance_list[0].GetFirstAtom().GetResNum()); 
-  for (ResidueDistanceList::const_iterator ai=res_distance_list.begin(),
-       ae=res_distance_list.end(); ai!=ae; ++ai) {
-    UniqueAtomIdentifier first_atom=ai->GetFirstAtom();
-    UniqueAtomIdentifier second_atom=ai->GetSecondAtom();
-    String name=swap ? swapped_name(first_atom.GetAtomName()) : first_atom.GetAtomName();
-    AtomView av1=mdl_res ? mdl_res.FindAtom(name) : AtomView();
- 
-    if (only_fixed) {
-      if (swappable(second_atom.GetResidueName(), second_atom.GetAtomName())) {
-          continue;
-      }
-      AtomView av2=mdl_chain.FindAtom(second_atom.GetResNum(),second_atom.GetAtomName());
-      overlap.second+=1.0;
-      if (!(av1 && av2)) {
-        continue;
-      }
-      Real mdl_dist=geom::Length(av1.GetPos()-av2.GetPos());
-      ReferenceDistance ref_dist=*ai;
-      if (within_tolerance(mdl_dist,ref_dist,tol).first) {
-        if (log) {
-          LOG_VERBOSE("LDT:" << " " << av1.GetResidue().GetChain() << " " << av1.GetResidue().GetName() << " " << av1.GetResidue().GetNumber() << " " << av1.GetName() 
-             << " " << av2.GetResidue().GetChain() << " " << av2.GetResidue().GetName() << " " << av2.GetResidue().GetNumber() << " " << av2.GetName() << " " 
-             << mdl_dist << " " << ref_dist.GetMinDistance() << " " << ref_dist.GetMaxDistance() << " " << tol << " " << "PASS")
-        }   
-        overlap.first+=1;
-      } else {
-        if (log) {
-          LOG_VERBOSE("LDT:" << " " << av1.GetResidue().GetChain() << " " << av1.GetResidue().GetName() << " " << av1.GetResidue().GetNumber() << " " << av1.GetName() 
-             << " " << av2.GetResidue().GetChain() << " " << av2.GetResidue().GetName() << " " << av2.GetResidue().GetNumber() << " " << av2.GetName() << " " 
-             << mdl_dist << " " << ref_dist.GetMinDistance() << " " << mdl_dist-ref_dist.GetMinDistance() << " " << tol << " " << "FAIL")
-        }  
-      }
-      continue;
-    }
-    AtomView av2=mdl_chain.FindAtom(second_atom.GetResNum(), second_atom.GetAtomName());
-    overlap.second+=1.0;
-    if (av1) {
-      overlap_list[av1.GetResidue().GetIndex()].second+=1.0;
-    }
-    if (av2) {
-      overlap_list[av2.GetResidue().GetIndex()].second+=1.0;
-     }  
-    if (!(av1 && av2)) {
-      continue;
-    }
-    
-    Real mdl_dist=geom::Length(av1.GetPos()-av2.GetPos());
-    ReferenceDistance ref_dist=*ai;
-    if (within_tolerance(mdl_dist,ref_dist,tol).first) {
-      LOG_INFO("LDT:" << " " << av1.GetResidue().GetChain() << " " << av1.GetResidue().GetName() << " " << av1.GetResidue().GetNumber() << " " << av1.GetName() 
-           << " " << av2.GetResidue().GetChain() << " " << av2.GetResidue().GetName() << " " << av2.GetResidue().GetNumber() << " " << av2.GetName() << " " 
-           << mdl_dist << " " << ref_dist.GetMinDistance() << " " << mdl_dist-ref_dist.GetMinDistance() << " " << tol << " " << "PASS")
-      overlap.first+=1;
-      overlap_list[av1.GetResidue().GetIndex()].first+=1.0;
-      overlap_list[av2.GetResidue().GetIndex()].first+=1.0;
-    } else {
-      LOG_VERBOSE("LDT:" << " " << av1.GetResidue().GetChain() << " " << av1.GetResidue().GetName() << " " << av1.GetResidue().GetNumber() << " " << av1.GetName() 
-             << " " << av2.GetResidue().GetChain() << " " << av2.GetResidue().GetName() << " " << av2.GetResidue().GetNumber() << " " << av2.GetName() << " " 
-             << mdl_dist << " " << ref_dist.GetMinDistance() << " " << mdl_dist-ref_dist.GetMinDistance() << " " << tol << " " << "FAIL")
-    } 
-  }    
-  return overlap;
-}
-
-
-std::pair<Real, Real> calc_overlap2(const seq::ConstSequenceHandle& ref_seq,
-                                    const seq::ConstSequenceHandle& mdl_seq,
-                                    int pos, Real tol, Real max_dist, 
-                                    bool only_fixed, bool swap)
-{
-  std::pair<Real, Real> overlap(0.0, 0.0);
-  EntityView ref=ref_seq.GetAttachedView();
-  ResidueView ref_res=ref_seq.GetResidue(pos);
-  if (!ref_res.IsValid()) {
-    return std::pair<Real,Real>(0.0, 0.0);
-  }
-  AtomViewList ref_atoms=ref_res.GetAtomList();
-  ResidueView mdl_res=mdl_seq.GetResidue(pos);
-  AtomViewList within;
-  if (max_dist<0) {
-    within=ref.GetAtomList();
-  }  
-  for (AtomViewList::iterator ai=ref_atoms.begin(),
-       ae=ref_atoms.end(); ai!=ae; ++ai) {
-    if (ai->GetElement()=="H") { continue; }
-    String name=swap ? swapped_name(ai->GetName()) : ai->GetName();
-    AtomView av1=mdl_res ? mdl_res.FindAtom(name) : AtomView();
-    if (max_dist>=0){ 
-      within=ref.FindWithin(ai->GetPos(), max_dist);
-    }
-    for (AtomViewList::iterator aj=within.begin(),
-         ae2=within.end(); aj!=ae2; ++aj) {
-      if (aj->GetElement()=="H" || 
-          aj->GetResidue().GetChain()!=ai->GetResidue().GetChain()) { 
-          continue; 
-      }
-      if (only_fixed) {
-        if (aj->GetResidue().GetNumber()==ref_res.GetNumber()) {
-          continue;
-        }
-        if (swappable(aj->GetResidue().GetName(), aj->GetName())) {
-          continue;
-        }
-        overlap.second+=1.0;
-        // map from residue index to position in alignment
-        try {
-          int aln_pos=ref_seq.GetPos(aj->GetResidue().GetIndex());
-          ResidueView r2=mdl_seq.GetResidue(aln_pos);
-          if (!r2.IsValid()) {
-            continue;
-          }
-          AtomView av2=r2.FindAtom(aj->GetName());
-          if (!(av1 && av2)) {
-            continue;
-          }
-          Real mdl_dist=geom::Length(av1.GetPos()-av2.GetPos());
-          Real ref_dist=geom::Length(ai->GetPos()-aj->GetPos());
-          if (std::abs(mdl_dist-ref_dist)<tol) {
-            overlap.first+=1;
-          }
-        } catch(...) { }
-        continue;
-      } else {
-        if (aj->GetResidue().GetNumber()>ref_res.GetNumber()) {
-          overlap.second+=1.0;    
-
-          try {
-           int aln_pos=ref_seq.GetPos(aj->GetResidue().GetIndex());
-            ResidueView r2=mdl_seq.GetResidue(aln_pos);
-            if (!r2.IsValid()) {
-              continue;
-            }
-            AtomView av2=r2.FindAtom(aj->GetName());
-            if (!(av1 && av2)) {
-              continue;
-            }
-            Real mdl_dist=geom::Length(av1.GetPos()-av2.GetPos());
-            Real ref_dist=geom::Length(ai->GetPos()-aj->GetPos());
-            if (std::abs(mdl_dist-ref_dist)<tol) {
-              overlap.first+=1;
-            }
-          } catch (...) { }
-        }  
-      }
-    }      
-  }
-  return overlap;
-}
-
-}
-
-bool IsStandardResidue(String rn)
-{
-  String upper_rn=rn;
-  std::transform(rn.begin(),rn.end(),rn.begin(),toupper);
-  if (upper_rn == "ALA" ||    
-  upper_rn == "ARG" ||
-  upper_rn == "ASN" ||
-  upper_rn == "ASP" ||
-  upper_rn == "GLN" ||
-  upper_rn == "GLU" ||
-  upper_rn == "LYS" ||
-  upper_rn == "SER" ||
-  upper_rn == "CYS" ||      
-  upper_rn == "TYR" ||  
-  upper_rn == "TRP" || 
-  upper_rn == "THR" ||
-  upper_rn == "VAL" ||
-  upper_rn == "ILE" ||
-  upper_rn == "MET" ||
-  upper_rn == "LEU" ||  
-  upper_rn == "GLY" ||  
-  upper_rn == "PRO" ||  
-  upper_rn == "HIS" ||  
-  upper_rn == "PHE") {
-    return true;
-  }  
-  return false;
-}  
-
-bool UniqueAtomIdentifier::operator==(const UniqueAtomIdentifier& rhs) const
-{
-  if (chain_ == rhs.GetChainName() && 
-      residue_ == rhs.GetResNum() &&
-      residue_name_ == rhs.GetResidueName() &&
-      atom_ == rhs.GetAtomName() ) {
-    return true;
-  }
-  return false;   
-}
-
-bool ReferenceDistance::IsValid() const 
-{
-  if (mind_ == -1.0 and maxd_ == -1.0) {
-    return false;
-  } 
-  return true;
-}
-
-void ReferenceDistance::Print() const 
-{ 
-  if (this->IsValid() == true) {
-    std::cout << first_atom_.GetChainName() << " " << first_atom_.GetResNum() << " " << first_atom_.GetResidueName() << " " << first_atom_.GetAtomName() << " " <<
-                 second_atom_.GetChainName() << " " << second_atom_.GetResNum() << " " << second_atom_.GetResidueName() << " " << second_atom_.GetAtomName() << " " <<
-                 mind_ << " " << maxd_ << std::endl; 
-  } else {
-    std::cout << first_atom_.GetChainName() << " " << first_atom_.GetResNum() << " " << first_atom_.GetResidueName() << " Placeholder" << std::endl;
-  }
-}
-
-bool ReferenceDistance::operator==(const ReferenceDistance& rhs) const
-{
-  if (first_atom_ == rhs.GetFirstAtom() && 
-      second_atom_ == rhs.GetSecondAtom() &&
-      mind_ == rhs.GetMinDistance() &&
-      maxd_ == rhs.GetMaxDistance() ) {
-    return true;
-  }
-  return false;
-}
-
-
-
-
-GlobalDistanceList CreateDistanceList(const EntityView& ref,Real max_dist)
-{
- GlobalDistanceList dist_list; 
- ResidueViewList ref_residues=ref.GetChainList()[0].GetResidueList();
- for (ResidueViewList::iterator i=ref_residues.begin(), e=ref_residues.end(); i!=e; ++i) {
-   ResidueView rview = (*i);
-   if (IsStandardResidue(rview.GetName())) {
-     ResidueDistanceList res_dist_list;
-     AtomViewList ref_atoms=(*i).GetAtomList();
-     AtomViewList within;
-     if (max_dist<0){
-     dist_list.push_back(res_dist_list);
-       within=ref.GetAtomList();
-     }  
-     for (AtomViewList::iterator ai=ref_atoms.begin(), ae=ref_atoms.end(); ai!=ae; ++ai) {
-       UniqueAtomIdentifier first_atom(ai->GetResidue().GetChain().GetName(),ai->GetResidue().GetNumber(),ai->GetResidue().GetName(),ai->GetName());
-       if (ai->GetElement()=="H") { continue; }
-       if (max_dist>=0){ 
-         within=ref.FindWithin(ai->GetPos(), max_dist);
-       }
-       for (AtomViewList::iterator aj=within.begin(), ae2=within.end(); aj!=ae2; ++aj) {      
-         UniqueAtomIdentifier second_atom(aj->GetResidue().GetChain().GetName(),aj->GetResidue().GetNumber(),aj->GetResidue().GetName(),aj->GetName());
-         if (aj->GetElement()=="H" ||
-             aj->GetResidue().GetChain()!=ai->GetResidue().GetChain()) {
-             continue;
-         }
-         if (aj->GetResidue().GetNumber()>i->GetNumber()) {
-           Real dist=geom::Length(ai->GetPos()-aj->GetPos());
-           ReferenceDistance ref_dist(first_atom,second_atom,dist,dist);
-           res_dist_list.push_back(ref_dist);
-         }
-       }
-     }
-     if (res_dist_list.size()==0) {
-       UniqueAtomIdentifier current_residue_fake_atom(rview.GetChain().GetName(),rview.GetNumber(),rview.GetName(),"CA");
-       ReferenceDistance fake_ref_distance(current_residue_fake_atom,current_residue_fake_atom,-1.0,-1.0);
-       res_dist_list.push_back(fake_ref_distance);
-     }  
-     dist_list.push_back(res_dist_list);
-   }
- }  
- return dist_list;
-} 
-
-
-Real LocalDistTest(const EntityView& mdl, const GlobalDistanceList& glob_dist_list,
-                   Real cutoff, const String& local_ldt_property_string)
-{
-  if (!mdl.GetResidueCount()) {
-    LOG_WARNING("model structures doesn't contain any residues");
-    return 0.0;
-  }
-  if (glob_dist_list.size()==0) {
-    LOG_WARNING("global reference list is empty");
-    return 0.0;
-  }
-  std::vector<std::pair<Real, Real> > overlap_list(mdl.GetResidueCount(), std::pair<Real, Real>(0.0, 0.0));
-  ChainView mdl_chain=mdl.GetChainList()[0];  
-  // Residues with symmetric side-chains require special treatment as there are 
-  // two possible ways to name the atoms. We calculate the overlap with the 
-  // fixed atoms and take the solution that gives bigger scores.
-  XCSEditor edi=mdl.GetHandle().EditXCS(BUFFERED_EDIT);
-  for (GlobalDistanceList::const_iterator i=glob_dist_list.begin(), e=glob_dist_list.end(); i!=e; ++i) {
-    ResidueDistanceList rdl = *i;
-    if (!rdl[0].IsValid()) {
-      continue;
-    }
-    
-    ResNum rnum =  rdl[0].GetFirstAtom().GetResNum() ;
-    String rname=rdl[0].GetFirstAtom().GetResidueName();
-    ResidueView mdl_res=mdl_chain.FindResidue(rnum);  
-    if (!mdl_res) {   
-      continue;
-    }
-    if (!(rname=="GLU" || rname=="ASP" || rname=="VAL" || rname=="TYR" || rname=="PHE" || rname=="LYS" || rname=="ARG")) {
-      continue;
-    }
-    std::pair<Real, Real> ov1=calc_overlap1(*i, mdl_chain, 
-                                          cutoff, true, 
-                                          false, overlap_list,false);
- 
-    std::pair<Real, Real> ov2=calc_overlap1(*i, mdl_chain, 
-                                          cutoff, true, 
-                                          true, overlap_list,false); 
-    if (ov1.first/ov1.second<ov2.first/ov2.second) {
-      AtomViewList atoms=mdl_res.GetAtomList();
-      for (AtomViewList::iterator j=atoms.begin(), e2=atoms.end(); j!=e2; ++j) {
-        if (swappable(rname, j->GetName())) {
-          edi.RenameAtom(j->GetHandle(), swapped_name(j->GetName()));
-        }
-      }
-    }
-  }
-  overlap_list.clear();
-  std::pair<Real, Real> total_ov(0.0, 0.0);
-  for (GlobalDistanceList::const_iterator i=glob_dist_list.begin(), e=glob_dist_list.end(); i!=e; ++i) {
-    ResidueDistanceList rdl = *i;
-    if (rdl[0].IsValid()) {
-      std::pair<Real, Real> ov1=calc_overlap1(*i, mdl_chain, cutoff, 
-                                            false, false, overlap_list,true);
-      total_ov.first+=ov1.first;
-      total_ov.second+=ov1.second;       
-    }
-    if(local_ldt_property_string!="") {
-      ResNum rn = rdl[0].GetFirstAtom().GetResNum();
-      ResidueView mdlr=mdl_chain.FindResidue(rn);  
-      if (mdlr.IsValid()) {
-        int mdl_res_index =mdlr.GetIndex();
-        Real local_ldt=overlap_list[mdl_res_index].first/(overlap_list[mdl_res_index].second ? overlap_list[mdl_res_index].second : 1);
-        ResidueView res_to_wr = mdl_chain.FindResidue((*i)[0].GetFirstAtom().GetResNum()); 
-        res_to_wr.SetFloatProp(local_ldt_property_string, local_ldt);
-      }  
-    }       
-  }
-  overlap_list.clear();
-  return total_ov.first/(total_ov.second ? total_ov.second : 1);
-}
-
-Real LocalDistTest(const ost::seq::AlignmentHandle& aln,
-                   Real cutoff, Real max_dist, int ref_index, int mdl_index)
-{
-  seq::ConstSequenceHandle ref_seq=aln.GetSequence(ref_index);
-  seq::ConstSequenceHandle mdl_seq=aln.GetSequence(mdl_index);  
-  if (!ref_seq.HasAttachedView()) {
-    LOG_ERROR("reference sequence doesn't have a view attached.");
-    return 0.0;
-  }
-  if (!mdl_seq.HasAttachedView()) {
-    LOG_ERROR("model sequence doesn't have a view attached");
-    return 0.0;
-  }
-  XCSEditor edi=ref_seq.GetAttachedView().GetHandle().EditXCS(BUFFERED_EDIT);
-  for (int i=0; i<aln.GetLength(); ++i) {
-    ResidueView mdl_res=mdl_seq.GetResidue(i);
-    if (!mdl_res) {
-      continue;
-    }
-    String rname=mdl_res.GetName();
-    if (!(rname=="GLU" || rname=="ASP" || rname=="VAL" || rname=="TYR" || 
-         rname=="PHE" || rname=="LYS" || rname=="ARG")) {
-      continue;
-    }
-    std::pair<Real, Real> ov1=calc_overlap2(ref_seq, mdl_seq, i,
-                                            cutoff, max_dist, true, 
-                                            false);
-    std::pair<Real, Real> ov2=calc_overlap2(ref_seq, mdl_seq, i,
-                                            cutoff, max_dist, true, 
-                                            true);
-    if (ov1.first/ov1.second<ov2.first/ov2.second) {
-     AtomViewList atoms=mdl_res.GetAtomList();
-     for (AtomViewList::iterator j=atoms.begin(), 
-          e2=atoms.end(); j!=e2; ++j) {
-       if (swappable(rname, j->GetName())) {
-         edi.RenameAtom(j->GetHandle(), swapped_name(j->GetName()));
-       }
-     }
-    }
-  }
-  std::pair<Real, Real> total_ov(0.0, 0.0);
-  for (int i=0; i<aln.GetLength(); ++i) {
-     std::pair<Real, Real> ov1=calc_overlap2(ref_seq, mdl_seq, i, cutoff, 
-                                             max_dist, false, false);
-     total_ov.first+=ov1.first;
-     total_ov.second+=ov1.second;
-  }
-  return total_ov.first/(total_ov.second ? total_ov.second : 1);
-  return 0.0;
-}
-
-Real LDTHA(EntityView& v, const GlobalDistanceList& global_dist_list)
-{
-    
-    Real cutoffs[]={0.5,1,2,4};
-    String labels[]={"localldt0.5","localldt1","localldt2","ldtlocal4"};
-    Real ldt=0.0;   
-    for (int n=0; n<4; ++n) { 
-      ldt+=alg::LocalDistTest(v, global_dist_list, cutoffs[n], labels[n]);
-    }      
-    ldt/=4.0;    
-    return ldt;
-}
-
-}}}
diff --git a/modules/mol/alg/src/local_dist_test.hh b/modules/mol/alg/src/local_dist_test.hh
deleted file mode 100644
index 74e0f4f29ca00b54340a683a036904d3eb66e596..0000000000000000000000000000000000000000
--- a/modules/mol/alg/src/local_dist_test.hh
+++ /dev/null
@@ -1,96 +0,0 @@
-//------------------------------------------------------------------------------
-// This file is part of the OpenStructure project <www.openstructure.org>
-//
-// Copyright (C) 2008-2011 by the OpenStructure authors
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License as published by the Free
-// Software Foundation; either version 3.0 of the License, or (at your option)
-// any later version.
-// This library is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with this library; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//------------------------------------------------------------------------------
-#ifndef OST_MOL_ALG_LOCAL_DIST_TEST_HH
-#define OST_MOL_ALG_LOCAL_DIST_TEST_HH
-
-#include <ost/mol/entity_view.hh>
-#include <ost/mol/alg/module_config.hh>
-#include <ost/seq/alignment_handle.hh>
-
-namespace ost { namespace mol { namespace alg {
-  
-  
-class UniqueAtomIdentifier
-{
-  
-public:
-  UniqueAtomIdentifier(const String& chain,const ResNum& residue,const String& residue_name, const String& atom): chain_(chain),residue_(residue),residue_name_(residue_name),atom_(atom) {}  
-  
-  String GetChainName() const { return chain_; } 
-  ResNum GetResNum() const { return residue_; }  
-  String GetResidueName() const { return residue_name_; }
-  String GetAtomName() const { return atom_; }
-  bool operator==(const UniqueAtomIdentifier& rhs) const;
-    
-private:
-
-  String chain_;
-  ResNum residue_;
-  String residue_name_;
-  String atom_;    
-};
-
-class ReferenceDistance
-{
-  
-public:
-  
-  ReferenceDistance(const UniqueAtomIdentifier& first_atom, const UniqueAtomIdentifier& second_atom, Real mind, Real maxd):
-       first_atom_(first_atom),second_atom_(second_atom),mind_(mind),maxd_(maxd) {}
-  UniqueAtomIdentifier GetFirstAtom() const {return first_atom_;}
-  UniqueAtomIdentifier GetSecondAtom() const {return second_atom_;}
-  Real GetMinDistance() const {return mind_ ;}
-  Real GetMaxDistance() const {return maxd_ ;}
-  bool IsValid() const; 
-  void Print() const; 
-  bool operator==(const ReferenceDistance& rhs) const;
-  
-private:
-  
-  UniqueAtomIdentifier first_atom_;
-  UniqueAtomIdentifier second_atom_;
-  Real mind_;
-  Real maxd_;
-};
-
-typedef std::vector<ReferenceDistance> ResidueDistanceList;
-typedef std::vector<ResidueDistanceList> GlobalDistanceList;
-  
-Real DLLEXPORT_OST_MOL_ALG LocalDistTest(const EntityView& mdl,
-                                         const GlobalDistanceList& dist_list,
-                                         Real cutoff, 
-                                         const String& local_ldt_property_string="");
-
-Real DLLEXPORT_OST_MOL_ALG LocalDistTest(const ost::seq::AlignmentHandle& aln,
-                                         Real cutoff, Real max_dist,
-                                         int ref_index=0, int mdl_index=1);
-
-
-Real DLLEXPORT_OST_MOL_ALG LDTHA(EntityView& v, const GlobalDistanceList& global_dist_list);
-
-GlobalDistanceList CreateDistanceList(const EntityView& ref,Real max_dist);
-bool IsStandardResidue(String rn);
-
-
-
-}}}
-
-#endif
-
-
diff --git a/modules/mol/alg/src/new_stereo_chemical_props.txt b/modules/mol/alg/src/new_stereo_chemical_props.txt
deleted file mode 100644
index 25262efd7689fc76f4d6ea1a7c75e342e840ea1d..0000000000000000000000000000000000000000
--- a/modules/mol/alg/src/new_stereo_chemical_props.txt
+++ /dev/null
@@ -1,345 +0,0 @@
-Bond			Residue		Mean		StdDev
-CA-CB			ALA		1.520		0.021
-N-CA			ALA		1.459		0.020
-CA-C			ALA		1.525		0.026
-C-O			ALA		1.229		0.019
-CA-CB			ARG		1.535		0.022
-CB-CG			ARG		1.521		0.027
-CG-CD			ARG		1.515		0.025
-CD-NE			ARG		1.460		0.017
-NE-CZ			ARG		1.326		0.013
-CZ-NH1			ARG		1.326		0.013
-CZ-NH2			ARG		1.326		0.013
-N-CA			ARG		1.459		0.020
-CA-C			ARG		1.525		0.026
-C-O			ARG		1.229		0.019
-CA-CB			ASN		1.527		0.026
-CB-CG			ASN		1.506		0.023
-CG-OD1			ASN		1.235		0.022
-CG-ND2			ASN		1.324		0.025
-N-CA			ASN		1.459		0.020
-CA-C			ASN		1.525		0.026
-C-O			ASN		1.229		0.019
-CA-CB			ASP		1.535		0.022
-CB-CG			ASP		1.513		0.021
-CG-OD1			ASP		1.249		0.023
-CG-OD2			ASP		1.249		0.023
-N-CA			ASP		1.459		0.020
-CA-C			ASP		1.525		0.026
-C-O			ASP		1.229		0.019
-CA-CB			CYS		1.526		0.013
-CB-SG			CYS		1.812		0.016
-N-CA			CYS		1.459		0.020
-CA-C			CYS		1.525		0.026
-C-O			CYS		1.229		0.019
-CA-CB			GLU		1.535		0.022
-CB-CG			GLU		1.517		0.019
-CG-CD			GLU		1.515		0.015
-CD-OE1			GLU		1.252		0.011
-CD-OE2			GLU		1.252		0.011
-N-CA			GLU		1.459		0.020
-CA-C			GLU		1.525		0.026
-C-O			GLU		1.229		0.019
-CA-CB			GLN		1.535		0.022
-CB-CG			GLN		1.521		0.027
-CG-CD			GLN		1.506		0.023
-CD-OE1			GLN		1.235		0.022
-CD-NE2			GLN		1.324		0.025
-N-CA			GLN		1.459		0.020
-CA-C			GLN		1.525		0.026
-C-O			GLN		1.229		0.019
-N-CA			GLY		1.456		0.015
-CA-C			GLY		1.514		0.016
-C-O			GLY		1.232		0.016
-CA-CB			HIS		1.535		0.022
-CB-CG			HIS		1.492		0.016
-CG-ND1			HIS		1.369		0.015
-CG-CD2			HIS		1.353		0.017
-ND1-CE1			HIS		1.343		0.025
-CD2-NE2			HIS		1.415		0.021
-CE1-NE2			HIS		1.322		0.023
-N-CA			HIS		1.459		0.020
-CA-C			HIS		1.525		0.026
-C-O			HIS		1.229		0.019
-CA-CB			ILE		1.544		0.023
-CB-CG1			ILE		1.536		0.028
-CB-CG2			ILE		1.524		0.031
-CG1-CD1			ILE		1.500		0.069
-N-CA			ILE		1.459		0.020
-CA-C			ILE		1.525		0.026
-C-O			ILE		1.229		0.019
-CA-CB			LEU		1.533		0.023
-CB-CG			LEU		1.521		0.029
-CG-CD1			LEU		1.514		0.037
-CG-CD2			LEU		1.514		0.037
-N-CA			LEU		1.459		0.020
-CA-C			LEU		1.525		0.026
-C-O			LEU		1.229		0.019
-CA-CB			LYS		1.535		0.022
-CB-CG			LYS		1.521		0.027
-CG-CD			LYS		1.520		0.034
-CD-CE			LYS		1.508		0.025
-CE-NZ			LYS		1.486		0.025
-N-CA			LYS		1.459		0.020
-CA-C			LYS		1.525		0.026
-C-O			LYS		1.229		0.019
-CA-CB			MET		1.535		0.022
-CB-CG			MET		1.509		0.032
-CG-SD			MET		1.807		0.026
-SD-CE			MET		1.774		0.056
-N-CA			MET		1.459		0.020
-CA-C			MET		1.525		0.026
-C-O			MET		1.229		0.019
-CA-CB			PHE		1.535		0.022
-CB-CG			PHE		1.509		0.017
-CG-CD1			PHE		1.383		0.015
-CG-CD2			PHE		1.383		0.015
-CD1-CE1			PHE		1.388		0.020
-CD2-CE2			PHE		1.388		0.020
-CE1-CZ			PHE		1.369		0.019
-CE2-CZ			PHE		1.369		0.019
-N-CA			PHE		1.459		0.020
-CA-C			PHE		1.525		0.026
-C-O			PHE		1.229		0.019
-CA-CB			PRO		1.531		0.020
-CB-CG			PRO		1.495		0.050
-CG-CD			PRO		1.502		0.033
-CD-N			PRO		1.474		0.014
-N-CA			PRO		1.468		0.017
-CA-C			PRO		1.524		0.020
-C-O			PRO		1.228		0.020
-CA-CB			SER		1.525		0.015
-CB-OG			SER		1.418		0.013
-N-CA			SER		1.459		0.020
-CA-C			SER		1.525		0.026
-C-O			SER		1.229		0.019
-CA-CB			THR		1.529		0.026
-CB-OG1			THR		1.428		0.020
-CB-CG2			THR		1.519		0.033
-N-CA			THR		1.459		0.020
-CA-C			THR		1.525		0.026
-C-O			THR		1.229		0.019
-CA-CB			TRP		1.535		0.022
-CB-CG			TRP		1.498		0.018
-CG-CD1			TRP		1.363		0.014
-CG-CD2			TRP		1.432		0.017
-CD1-NE1			TRP		1.375		0.017
-NE1-CE2			TRP		1.371		0.013
-CD2-CE2			TRP		1.409		0.012
-CD2-CE3			TRP		1.399		0.015
-CE2-CZ2			TRP		1.393		0.017
-CE3-CZ3			TRP		1.380		0.017
-CZ2-CH2			TRP		1.369		0.019
-CZ3-CH2			TRP		1.396		0.016
-N-CA			TRP		1.459		0.020
-CA-C			TRP		1.525		0.026
-C-O			TRP		1.229		0.019
-CA-CB			TYR		1.535		0.022
-CB-CG			TYR		1.512		0.015
-CG-CD1			TYR		1.387		0.013
-CG-CD2			TYR		1.387		0.013
-CD1-CE1			TYR		1.389		0.015
-CD2-CE2			TYR		1.389		0.015
-CE1-CZ			TYR		1.381		0.013
-CE2-CZ			TYR		1.381		0.013
-CZ-OH			TYR		1.374		0.017
-N-CA			TYR		1.459		0.020
-CA-C			TYR		1.525		0.026
-C-O			TYR		1.229		0.019
-CA-CB			VAL		1.543		0.021
-CB-CG1			VAL		1.524		0.021
-CB-CG2			VAL		1.524		0.021
-N-CA			VAL		1.459		0.020
-CA-C			VAL		1.525		0.026
-C-O			VAL		1.229		0.019
--
-
-Angle			Residue		Mean		StdDev
-N-CA-CB			ALA		110.1		1.4
-CB-CA-C			ALA		110.1		1.5
-N-CA-C			ALA		111.0		2.7
-CA-C-O			ALA		120.1		2.1
-N-CA-CB			ARG		110.6		1.8
-CB-CA-C			ARG		110.4		2.0
-CA-CB-CG		ARG		113.4		2.2
-CB-CG-CD		ARG		111.6		2.6
-CG-CD-NE		ARG		111.8		2.1
-CD-NE-CZ		ARG		123.6		1.4
-NE-CZ-NH1		ARG		120.3		0.5
-NE-CZ-NH2		ARG		120.3		0.5
-NH1-CZ-NH2		ARG		119.4		1.1
-N-CA-C			ARG		111.0		2.7
-CA-C-O			ARG		120.1		2.1
-N-CA-CB			ASN		110.6		1.8
-CB-CA-C			ASN		110.4		2.0
-CA-CB-CG		ASN		113.4		2.2
-CB-CG-ND2		ASN		116.7		2.4
-CB-CG-OD1		ASN		121.6		2.0
-ND2-CG-OD1		ASN		121.9		2.3
-N-CA-C			ASN		111.0		2.7
-CA-C-O			ASN		120.1		2.1
-N-CA-CB			ASP		110.6		1.8
-CB-CA-C			ASP		110.4		2.0
-CA-CB-CG		ASP		113.4		2.2
-CB-CG-OD1		ASP		118.3		0.9
-CB-CG-OD2		ASP		118.3		0.9
-OD1-CG-OD2		ASP		123.3		1.9
-N-CA-C			ASP		111.0		2.7
-CA-C-O			ASP		120.1		2.1
-N-CA-CB			CYS		110.8		1.5
-CB-CA-C			CYS		111.5		1.2
-CA-CB-SG		CYS		114.2		1.1
-N-CA-C			CYS		111.0		2.7
-CA-C-O			CYS		120.1		2.1
-N-CA-CB			GLU		110.6		1.8
-CB-CA-C			GLU		110.4		2.0
-CA-CB-CG		GLU		113.4		2.2
-CB-CG-CD		GLU		114.2		2.7
-CG-CD-OE1		GLU		118.3		2.0
-CG-CD-OE2		GLU		118.3		2.0
-OE1-CD-OE2		GLU		123.3		1.2
-N-CA-C			GLU		111.0		2.7
-CA-C-O			GLU		120.1		2.1
-N-CA-CB			GLN		110.6		1.8
-CB-CA-C			GLN		110.4		2.0
-CA-CB-CG		GLN		113.4		2.2
-CB-CG-CD		GLN		111.6		2.6
-CG-CD-OE1		GLN		121.6		2.0
-CG-CD-NE2		GLN		116.7		2.4
-OE1-CD-NE2		GLN		121.9		2.3
-N-CA-C			GLN		111.0		2.7
-CA-C-O			GLN		120.1		2.1
-N-CA-C			GLY		113.1		2.5
-CA-C-O			GLY		120.6		1.8
-N-CA-CB			HIS		110.6		1.8
-CB-CA-C			HIS		110.4		2.0
-CA-CB-CG		HIS		113.6		1.7
-CB-CG-ND1		HIS		123.2		2.5
-CB-CG-CD2		HIS		130.8		3.1
-CG-ND1-CE1		HIS		108.2		1.4
-ND1-CE1-NE2		HIS		109.9		2.2
-CE1-NE2-CD2		HIS		106.6		2.5
-NE2-CD2-CG		HIS		109.2		1.9
-CD2-CG-ND1		HIS		106.0		1.4
-N-CA-C			HIS		111.0		2.7
-CA-C-O			HIS		120.1		2.1
-N-CA-CB			ILE		110.8		2.3
-CB-CA-C			ILE		111.6		2.0
-CA-CB-CG1		ILE		111.0		1.9
-CB-CG1-CD1		ILE		113.9		2.8
-CA-CB-CG2		ILE		110.9		2.0
-CG1-CB-CG2		ILE		111.4		2.2
-N-CA-C			ILE		111.0		2.7
-CA-C-O			ILE		120.1		2.1
-N-CA-CB			LEU		110.4		2.0
-CB-CA-C			LEU		110.2		1.9
-CA-CB-CG		LEU		115.3		2.3
-CB-CG-CD1		LEU		111.0		1.7
-CB-CG-CD2		LEU		111.0		1.7
-CD1-CG-CD2		LEU		110.5		3.0
-N-CA-C			LEU		111.0		2.7
-CA-C-O			LEU		120.1		2.1
-N-CA-CB			LYS		110.6		1.8
-CB-CA-C			LYS		110.4		2.0
-CA-CB-CG		LYS		113.4		2.2
-CB-CG-CD		LYS		111.6		2.6
-CG-CD-CE		LYS		111.9		3.0
-CD-CE-NZ		LYS		111.7		2.3
-N-CA-C			LYS		111.0		2.7
-CA-C-O			LYS		120.1		2.1
-N-CA-CB			MET		110.6		1.8
-CB-CA-C			MET		110.4		2.0
-CA-CB-CG		MET		113.3		1.7
-CB-CG-SD		MET		112.4		3.0
-CG-SD-CE		MET		100.2		1.6
-N-CA-C			MET		111.0		2.7
-CA-C-O			MET		120.1		2.1
-N-CA-CB			PHE		110.6		1.8
-CB-CA-C			PHE		110.4		2.0
-CA-CB-CG		PHE		113.9		2.4
-CB-CG-CD1		PHE		120.8		0.7
-CB-CG-CD2		PHE		120.8		0.7
-CD1-CG-CD2		PHE		118.3		1.3
-CG-CD1-CE1		PHE		120.8		1.1
-CG-CD2-CE2		PHE		120.8		1.1
-CD1-CE1-CZ		PHE		120.1		1.2
-CD2-CE2-CZ		PHE		120.1		1.2
-CE1-CZ-CE2		PHE		120.0		1.8
-N-CA-C			PHE		111.0		2.7
-CA-C-O			PHE		120.1		2.1
-N-CA-CB			PRO		103.3		1.2
-CB-CA-C			PRO		111.7		2.1
-CA-CB-CG		PRO		104.8		1.9
-CB-CG-CD		PRO		106.5		3.9
-CG-CD-N			PRO		103.2		1.5
-CA-N-CD			PRO		111.7		1.4
-N-CA-C			PRO		112.1		2.6
-CA-C-O			PRO		120.2		2.4
-N-CA-CB			SER		110.5		1.5
-CB-CA-C			SER		110.1		1.9
-CA-CB-OG		SER		111.2		2.7
-N-CA-C			SER		111.0		2.7
-CA-C-O			SER		120.1		2.1
-N-CA-CB			THR		110.3		1.9
-CB-CA-C			THR		111.6		2.7
-CA-CB-OG1		THR		109.0		2.1
-CA-CB-CG2		THR		112.4		1.4
-OG1-CB-CG2		THR		110.0		2.3
-N-CA-C			THR		111.0		2.7
-CA-C-O			THR		120.1		2.1
-N-CA-CB			TRP		110.6		1.8
-CB-CA-C			TRP		110.4		2.0
-CA-CB-CG		TRP		113.7		1.9
-CB-CG-CD1		TRP		127.0		1.3
-CB-CG-CD2		TRP		126.6		1.3
-CD1-CG-CD2		TRP		106.3		0.8
-CG-CD1-NE1		TRP		110.1		1.0
-CD1-NE1-CE2		TRP		109.0		0.9
-NE1-CE2-CD2		TRP		107.3		1.0
-CE2-CD2-CG		TRP		107.3		0.8
-CG-CD2-CE3		TRP		133.9		0.9
-NE1-CE2-CZ2		TRP		130.4		1.1
-CE3-CD2-CE2		TRP		118.7		1.2
-CD2-CE2-CZ2		TRP		122.3		1.2
-CE2-CZ2-CH2		TRP		117.4		1.0
-CZ2-CH2-CZ3		TRP		121.6		1.2
-CH2-CZ3-CE3		TRP		121.2		1.1
-CZ3-CE3-CD2		TRP		118.8		1.3
-N-CA-C			TRP		111.0		2.7
-CA-C-O			TRP		120.1		2.1
-N-CA-CB			TYR		110.6		1.8
-CB-CA-C			TYR		110.4		2.0
-CA-CB-CG		TYR		113.4		1.9
-CB-CG-CD1		TYR		121.0		0.6
-CB-CG-CD2		TYR		121.0		0.6
-CD1-CG-CD2		TYR		117.9		1.1
-CG-CD1-CE1		TYR		121.3		0.8
-CG-CD2-CE2		TYR		121.3		0.8
-CD1-CE1-CZ		TYR		119.8		0.9
-CD2-CE2-CZ		TYR		119.8		0.9
-CE1-CZ-CE2		TYR		119.8		1.6
-CE1-CZ-OH		TYR		120.1		2.7
-CE2-CZ-OH		TYR		120.1		2.7
-N-CA-C			TYR		111.0		2.7
-CA-C-O			TYR		120.1		2.1
-N-CA-CB			VAL		111.5		2.2
-CB-CA-C			VAL		111.4		1.9
-CA-CB-CG1		VAL		110.9		1.5
-CA-CB-CG2		VAL		110.9		1.5
-CG1-CB-CG2		VAL		110.9		1.6
-N-CA-C			VAL		111.0		2.7
-CA-C-O			VAL		120.1		2.1
--
-
-Non-bonded distance     Minimum Dist    Tolerance
-C-C                     3.4             1.5
-C-N                     3.25            1.5
-C-S                     3.5             1.5
-C-O                     3.22            1.5
-N-N                     3.1             1.5
-N-S                     3.35            1.5
-N-O                     3.07            1.5
-O-S                     3.32            1.5
-O-O                     3.04            1.5
-S-S                     2.03            1.0
--
diff --git a/modules/mol/alg/src/stereo_chemical_props.txt b/modules/mol/alg/src/stereo_chemical_props.txt
index f17af3cf31baf8789c648fb1d5f1eff1d882a46d..25262efd7689fc76f4d6ea1a7c75e342e840ea1d 100644
--- a/modules/mol/alg/src/stereo_chemical_props.txt
+++ b/modules/mol/alg/src/stereo_chemical_props.txt
@@ -1,367 +1,345 @@
-# This file contains stereochemical parameters used to evaluate the quality of models. 
-# Bond distances and Angles come from Engh,Huber (1991). Non bonded distances come from
-
 Bond			Residue		Mean		StdDev
-N-CA			ALA		1.458		0.019
-CA-C			ALA		1.525		0.021
-C-O			ALA		1.231		0.02
-CA-CB			ALA		1.521		0.033
-N-CA			CYS		1.458		0.019
-CA-C			CYS		1.525		0.021
-C-O			CYS		1.231		0.02
-CA-CB			CYS		1.53		0.02
-CB-SG			CYS		1.808		0.033
-N-CA			ASP		1.458		0.019
-CA-C			ASP		1.525		0.021
-C-O			ASP		1.231		0.02
-CA-CB			ASP		1.53		0.02
-CB-CG			ASP		1.516		0.025
-CG-OD1			ASP		1.249		0.019
-CG-OD2			ASP		1.249		0.019
-N-CA			GLU		1.458		0.019
-CA-C			GLU		1.525		0.021
-C-O			GLU		1.231		0.02
-CA-CB			GLU		1.53		0.02
-CB-CG			GLU		1.52		0.03
-CG-CD			GLU		1.516		0.025
-CD-OE1			GLU		1.249		0.019
-CD-OE2			GLU		1.249		0.019
-N-CA			PHE		1.458		0.019
-CA-C			PHE		1.525		0.021
-C-O			PHE		1.231		0.02
-CA-CB			PHE		1.53		0.02
-CB-CG			PHE		1.502		0.023
-CG-CD1			PHE		1.384		0.021
-CG-CD2			PHE		1.384		0.021
-CD1-CE1			PHE		1.382		0.03
-CD2-CE2			PHE		1.382		0.03
-CE1-CZ			PHE		1.382		0.03
-CE2-CZ			PHE		1.382		0.03
-N-CA			GLY		1.451		0.016
-CA-C			GLY		1.516		0.018
-C-O			GLY		1.231		0.02
-N-CA			HIS		1.458		0.019
-CA-C			HIS		1.525		0.021
-C-O			HIS		1.231		0.02
-CA-CB			HIS		1.53		0.02
-CB-CG			HIS		1.497		0.014
-CG-ND1			HIS		1.378		0.011
-CG-CD2			HIS		1.354		0.011
-ND1-CE1			HIS		1.321		0.01
-CD2-NE2			HIS		1.374		0.011
-CE1-NE2			HIS		1.321		0.01
-N-CA			ILE		1.458		0.019
-CA-C			ILE		1.525		0.021
-C-O			ILE		1.231		0.02
-CA-CB			ILE		1.54		0.027
-CB-CG1			ILE		1.53		0.02
-CB-CG2			ILE		1.521		0.033
-CG1-CD1			ILE		1.513		0.039
-N-CA			LYS		1.458		0.019
-CA-C			LYS		1.525		0.021
-C-O			LYS		1.231		0.02
-CA-CB			LYS		1.53		0.02
-CB-CG			LYS		1.52		0.03
-CG-CD			LYS		1.52		0.03
-CD-CE			LYS		1.52		0.03
-CE-NZ			LYS		1.489		0.03
-N-CA			LEU		1.458		0.019
-CA-C			LEU		1.525		0.021
-C-O			LEU		1.231		0.02
-CA-CB			LEU		1.53		0.02
-CB-CG			LEU		1.53		0.02
-CG-CD1			LEU		1.521		0.033
-CG-CD2			LEU		1.521		0.033
-N-CA			MET		1.458		0.019
-CA-C			MET		1.525		0.021
-C-O			MET		1.231		0.02
-CA-CB			MET		1.53		0.02
-CB-CG			MET		1.52		0.03
-CG-SD			MET		1.803		0.034
-SD-CE			MET		1.791		0.059
-N-CA			ASN		1.458		0.019
-CA-C			ASN		1.525		0.021
-C-O			ASN		1.231		0.02
-CA-CB			ASN		1.53		0.02
-CB-CG			ASN		1.516		0.025
-CG-OD1			ASN		1.231		0.02
-CG-ND2			ASN		1.328		0.021
-N-CA			PRO		1.466		0.015
-CA-C			PRO		1.525		0.021
-C-O			PRO		1.231		0.02
-CA-CB			PRO		1.53		0.02
-CB-CG			PRO		1.492		0.05
-CG-CD			PRO		1.503		0.034
-CD-N			PRO		1.473		0.014
-N-CA			GLN		1.458		0.019
-CA-C			GLN		1.525		0.021
-C-O			GLN		1.231		0.02
-CA-CB			GLN		1.53		0.02
-CB-CG			GLN		1.52		0.03
-CG-CD			GLN		1.516		0.025
-CD-OE1			GLN		1.231		0.02
-CD-NE2			GLN		1.328		0.021
-N-CA			ARG		1.458		0.019
-CA-C			ARG		1.525		0.021
-C-O			ARG		1.231		0.02
-CA-CB			ARG		1.53		0.02
-CB-CG			ARG		1.52		0.03
-CG-CD			ARG		1.52		0.03
-CD-NE			ARG		1.46		0.018
-NE-CZ			ARG		1.329		0.014
-CZ-NH1			ARG		1.326		0.018
-CZ-NH2			ARG		1.326		0.018
-N-CA			SER		1.458		0.019
-CA-C			SER		1.525		0.021
-C-O			SER		1.231		0.02
-CA-CB			SER		1.53		0.02
-CB-OG			SER		1.417		0.02
-N-CA			THR		1.458		0.019
-CA-C			THR		1.525		0.021
-C-O			THR		1.231		0.02
-CA-CB			THR		1.54		0.027
-CB-OG1			THR		1.433		0.016
-CB-CG2			THR		1.521		0.033
-N-CA			VAL		1.458		0.019
-CA-C			VAL		1.525		0.021
-C-O			VAL		1.231		0.02
-CA-CB			VAL		1.54		0.027
-CB-CG1			VAL		1.521		0.033
-CB-CG2			VAL		1.521		0.033
-N-CA			TRP		1.458		0.019
-CA-C			TRP		1.525		0.021
-C-O			TRP		1.231		0.02
-CA-CB			TRP		1.53		0.02
-CB-CG			TRP		1.498		0.031
-CG-CD1			TRP		1.365		0.025
-CG-CD2			TRP		1.433		0.018
-CD1-NE1			TRP		1.374		0.021
-NE1-CE2			TRP		1.37		0.011
-CD2-CE2			TRP		1.409		0.017
-CD2-CE3			TRP		1.398		0.016
-CE2-CZ2			TRP		1.394		0.021
-CE3-CZ3			TRP		1.382		0.03
-CZ2-CH2			TRP		1.368		0.019
-CZ3-CH2			TRP		1.4		0.025
-N-CA			TYR		1.458		0.019
-CA-C			TYR		1.525		0.021
-C-O			TYR		1.231		0.02
-CA-CB			TYR		1.53		0.02
-CB-CG			TYR		1.512		0.022
-CG-CD1			TYR		1.389		0.021
-CG-CD2			TYR		1.389		0.021
-CD1-CE1			TYR		1.382		0.03
-CD2-CE2			TYR		1.382		0.03
-CE1-CZ			TYR		1.378		0.024
-CE2-CZ			TYR		1.378		0.024
-CZ-OH			TYR		1.376		0.021
+CA-CB			ALA		1.520		0.021
+N-CA			ALA		1.459		0.020
+CA-C			ALA		1.525		0.026
+C-O			ALA		1.229		0.019
+CA-CB			ARG		1.535		0.022
+CB-CG			ARG		1.521		0.027
+CG-CD			ARG		1.515		0.025
+CD-NE			ARG		1.460		0.017
+NE-CZ			ARG		1.326		0.013
+CZ-NH1			ARG		1.326		0.013
+CZ-NH2			ARG		1.326		0.013
+N-CA			ARG		1.459		0.020
+CA-C			ARG		1.525		0.026
+C-O			ARG		1.229		0.019
+CA-CB			ASN		1.527		0.026
+CB-CG			ASN		1.506		0.023
+CG-OD1			ASN		1.235		0.022
+CG-ND2			ASN		1.324		0.025
+N-CA			ASN		1.459		0.020
+CA-C			ASN		1.525		0.026
+C-O			ASN		1.229		0.019
+CA-CB			ASP		1.535		0.022
+CB-CG			ASP		1.513		0.021
+CG-OD1			ASP		1.249		0.023
+CG-OD2			ASP		1.249		0.023
+N-CA			ASP		1.459		0.020
+CA-C			ASP		1.525		0.026
+C-O			ASP		1.229		0.019
+CA-CB			CYS		1.526		0.013
+CB-SG			CYS		1.812		0.016
+N-CA			CYS		1.459		0.020
+CA-C			CYS		1.525		0.026
+C-O			CYS		1.229		0.019
+CA-CB			GLU		1.535		0.022
+CB-CG			GLU		1.517		0.019
+CG-CD			GLU		1.515		0.015
+CD-OE1			GLU		1.252		0.011
+CD-OE2			GLU		1.252		0.011
+N-CA			GLU		1.459		0.020
+CA-C			GLU		1.525		0.026
+C-O			GLU		1.229		0.019
+CA-CB			GLN		1.535		0.022
+CB-CG			GLN		1.521		0.027
+CG-CD			GLN		1.506		0.023
+CD-OE1			GLN		1.235		0.022
+CD-NE2			GLN		1.324		0.025
+N-CA			GLN		1.459		0.020
+CA-C			GLN		1.525		0.026
+C-O			GLN		1.229		0.019
+N-CA			GLY		1.456		0.015
+CA-C			GLY		1.514		0.016
+C-O			GLY		1.232		0.016
+CA-CB			HIS		1.535		0.022
+CB-CG			HIS		1.492		0.016
+CG-ND1			HIS		1.369		0.015
+CG-CD2			HIS		1.353		0.017
+ND1-CE1			HIS		1.343		0.025
+CD2-NE2			HIS		1.415		0.021
+CE1-NE2			HIS		1.322		0.023
+N-CA			HIS		1.459		0.020
+CA-C			HIS		1.525		0.026
+C-O			HIS		1.229		0.019
+CA-CB			ILE		1.544		0.023
+CB-CG1			ILE		1.536		0.028
+CB-CG2			ILE		1.524		0.031
+CG1-CD1			ILE		1.500		0.069
+N-CA			ILE		1.459		0.020
+CA-C			ILE		1.525		0.026
+C-O			ILE		1.229		0.019
+CA-CB			LEU		1.533		0.023
+CB-CG			LEU		1.521		0.029
+CG-CD1			LEU		1.514		0.037
+CG-CD2			LEU		1.514		0.037
+N-CA			LEU		1.459		0.020
+CA-C			LEU		1.525		0.026
+C-O			LEU		1.229		0.019
+CA-CB			LYS		1.535		0.022
+CB-CG			LYS		1.521		0.027
+CG-CD			LYS		1.520		0.034
+CD-CE			LYS		1.508		0.025
+CE-NZ			LYS		1.486		0.025
+N-CA			LYS		1.459		0.020
+CA-C			LYS		1.525		0.026
+C-O			LYS		1.229		0.019
+CA-CB			MET		1.535		0.022
+CB-CG			MET		1.509		0.032
+CG-SD			MET		1.807		0.026
+SD-CE			MET		1.774		0.056
+N-CA			MET		1.459		0.020
+CA-C			MET		1.525		0.026
+C-O			MET		1.229		0.019
+CA-CB			PHE		1.535		0.022
+CB-CG			PHE		1.509		0.017
+CG-CD1			PHE		1.383		0.015
+CG-CD2			PHE		1.383		0.015
+CD1-CE1			PHE		1.388		0.020
+CD2-CE2			PHE		1.388		0.020
+CE1-CZ			PHE		1.369		0.019
+CE2-CZ			PHE		1.369		0.019
+N-CA			PHE		1.459		0.020
+CA-C			PHE		1.525		0.026
+C-O			PHE		1.229		0.019
+CA-CB			PRO		1.531		0.020
+CB-CG			PRO		1.495		0.050
+CG-CD			PRO		1.502		0.033
+CD-N			PRO		1.474		0.014
+N-CA			PRO		1.468		0.017
+CA-C			PRO		1.524		0.020
+C-O			PRO		1.228		0.020
+CA-CB			SER		1.525		0.015
+CB-OG			SER		1.418		0.013
+N-CA			SER		1.459		0.020
+CA-C			SER		1.525		0.026
+C-O			SER		1.229		0.019
+CA-CB			THR		1.529		0.026
+CB-OG1			THR		1.428		0.020
+CB-CG2			THR		1.519		0.033
+N-CA			THR		1.459		0.020
+CA-C			THR		1.525		0.026
+C-O			THR		1.229		0.019
+CA-CB			TRP		1.535		0.022
+CB-CG			TRP		1.498		0.018
+CG-CD1			TRP		1.363		0.014
+CG-CD2			TRP		1.432		0.017
+CD1-NE1			TRP		1.375		0.017
+NE1-CE2			TRP		1.371		0.013
+CD2-CE2			TRP		1.409		0.012
+CD2-CE3			TRP		1.399		0.015
+CE2-CZ2			TRP		1.393		0.017
+CE3-CZ3			TRP		1.380		0.017
+CZ2-CH2			TRP		1.369		0.019
+CZ3-CH2			TRP		1.396		0.016
+N-CA			TRP		1.459		0.020
+CA-C			TRP		1.525		0.026
+C-O			TRP		1.229		0.019
+CA-CB			TYR		1.535		0.022
+CB-CG			TYR		1.512		0.015
+CG-CD1			TYR		1.387		0.013
+CG-CD2			TYR		1.387		0.013
+CD1-CE1			TYR		1.389		0.015
+CD2-CE2			TYR		1.389		0.015
+CE1-CZ			TYR		1.381		0.013
+CE2-CZ			TYR		1.381		0.013
+CZ-OH			TYR		1.374		0.017
+N-CA			TYR		1.459		0.020
+CA-C			TYR		1.525		0.026
+C-O			TYR		1.229		0.019
+CA-CB			VAL		1.543		0.021
+CB-CG1			VAL		1.524		0.021
+CB-CG2			VAL		1.524		0.021
+N-CA			VAL		1.459		0.020
+CA-C			VAL		1.525		0.026
+C-O			VAL		1.229		0.019
 -
 
 Angle			Residue		Mean		StdDev
-N-CA-C			ALA		111.2		2.8
-CA-C-O			ALA		120.8		1.7
-N-CA-CB			ALA		110.4		1.5
-C-CA-CB			ALA		110.5		1.5
-N-CA-C			CYS		111.2		2.8
-CA-C-O			CYS		120.8		1.7
-N-CA-CB			CYS		110.5		1.7
-C-CA-CB			CYS		110.1		1.9
-N-CA-C			ASP		111.2		2.8
-CA-C-O			ASP		120.8		1.7
-N-CA-CB			ASP		110.5		1.7
-C-CA-CB			ASP		110.1		1.9
-CA-CB-CG		ASP		112.6		1.0
-CB-CG-OD2		ASP		118.4		2.3
-CB-CG-OD1		ASP		118.4		2.3
-OD2-CG-OD1		ASP		122.9		2.4
-N-CA-C			GLU		111.2		2.8
-CA-C-O			GLU		120.8		1.7
-N-CA-CB			GLU		110.5		1.7
-C-CA-CB			GLU		110.1		1.9
-CA-CB-CG		GLU		114.1		2.0
-CB-CG-CD		GLU		112.6		1.7
-CG-CD-OE2		GLU		118.4		2.3
-CG-CD-OE1		GLU		118.4		2.3
-OE2-CD-OE1		GLU		122.9		2.4
-N-CA-C			PHE		111.2		2.8
-CA-C-O			PHE		120.8		1.7
-N-CA-CB			PHE		110.5		1.7
-C-CA-CB			PHE		110.1		1.9
-CA-CB-CG		PHE		113.8		1.0
-CB-CG-CD1		PHE		120.7		1.7
-CB-CG-CD2		PHE		120.7		1.7
-CG-CD1-CE1		PHE		120.7		1.7
-CG-CD2-CE2		PHE		120.7		1.7
-CD1-CE1-CZ		PHE		120.0		1.8
-CD2-CE2-CZ		PHE		120.0		1.8
+N-CA-CB			ALA		110.1		1.4
+CB-CA-C			ALA		110.1		1.5
+N-CA-C			ALA		111.0		2.7
+CA-C-O			ALA		120.1		2.1
+N-CA-CB			ARG		110.6		1.8
+CB-CA-C			ARG		110.4		2.0
+CA-CB-CG		ARG		113.4		2.2
+CB-CG-CD		ARG		111.6		2.6
+CG-CD-NE		ARG		111.8		2.1
+CD-NE-CZ		ARG		123.6		1.4
+NE-CZ-NH1		ARG		120.3		0.5
+NE-CZ-NH2		ARG		120.3		0.5
+NH1-CZ-NH2		ARG		119.4		1.1
+N-CA-C			ARG		111.0		2.7
+CA-C-O			ARG		120.1		2.1
+N-CA-CB			ASN		110.6		1.8
+CB-CA-C			ASN		110.4		2.0
+CA-CB-CG		ASN		113.4		2.2
+CB-CG-ND2		ASN		116.7		2.4
+CB-CG-OD1		ASN		121.6		2.0
+ND2-CG-OD1		ASN		121.9		2.3
+N-CA-C			ASN		111.0		2.7
+CA-C-O			ASN		120.1		2.1
+N-CA-CB			ASP		110.6		1.8
+CB-CA-C			ASP		110.4		2.0
+CA-CB-CG		ASP		113.4		2.2
+CB-CG-OD1		ASP		118.3		0.9
+CB-CG-OD2		ASP		118.3		0.9
+OD1-CG-OD2		ASP		123.3		1.9
+N-CA-C			ASP		111.0		2.7
+CA-C-O			ASP		120.1		2.1
+N-CA-CB			CYS		110.8		1.5
+CB-CA-C			CYS		111.5		1.2
+CA-CB-SG		CYS		114.2		1.1
+N-CA-C			CYS		111.0		2.7
+CA-C-O			CYS		120.1		2.1
+N-CA-CB			GLU		110.6		1.8
+CB-CA-C			GLU		110.4		2.0
+CA-CB-CG		GLU		113.4		2.2
+CB-CG-CD		GLU		114.2		2.7
+CG-CD-OE1		GLU		118.3		2.0
+CG-CD-OE2		GLU		118.3		2.0
+OE1-CD-OE2		GLU		123.3		1.2
+N-CA-C			GLU		111.0		2.7
+CA-C-O			GLU		120.1		2.1
+N-CA-CB			GLN		110.6		1.8
+CB-CA-C			GLN		110.4		2.0
+CA-CB-CG		GLN		113.4		2.2
+CB-CG-CD		GLN		111.6		2.6
+CG-CD-OE1		GLN		121.6		2.0
+CG-CD-NE2		GLN		116.7		2.4
+OE1-CD-NE2		GLN		121.9		2.3
+N-CA-C			GLN		111.0		2.7
+CA-C-O			GLN		120.1		2.1
+N-CA-C			GLY		113.1		2.5
+CA-C-O			GLY		120.6		1.8
+N-CA-CB			HIS		110.6		1.8
+CB-CA-C			HIS		110.4		2.0
+CA-CB-CG		HIS		113.6		1.7
+CB-CG-ND1		HIS		123.2		2.5
+CB-CG-CD2		HIS		130.8		3.1
+CG-ND1-CE1		HIS		108.2		1.4
+ND1-CE1-NE2		HIS		109.9		2.2
+CE1-NE2-CD2		HIS		106.6		2.5
+NE2-CD2-CG		HIS		109.2		1.9
+CD2-CG-ND1		HIS		106.0		1.4
+N-CA-C			HIS		111.0		2.7
+CA-C-O			HIS		120.1		2.1
+N-CA-CB			ILE		110.8		2.3
+CB-CA-C			ILE		111.6		2.0
+CA-CB-CG1		ILE		111.0		1.9
+CB-CG1-CD1		ILE		113.9		2.8
+CA-CB-CG2		ILE		110.9		2.0
+CG1-CB-CG2		ILE		111.4		2.2
+N-CA-C			ILE		111.0		2.7
+CA-C-O			ILE		120.1		2.1
+N-CA-CB			LEU		110.4		2.0
+CB-CA-C			LEU		110.2		1.9
+CA-CB-CG		LEU		115.3		2.3
+CB-CG-CD1		LEU		111.0		1.7
+CB-CG-CD2		LEU		111.0		1.7
+CD1-CG-CD2		LEU		110.5		3.0
+N-CA-C			LEU		111.0		2.7
+CA-C-O			LEU		120.1		2.1
+N-CA-CB			LYS		110.6		1.8
+CB-CA-C			LYS		110.4		2.0
+CA-CB-CG		LYS		113.4		2.2
+CB-CG-CD		LYS		111.6		2.6
+CG-CD-CE		LYS		111.9		3.0
+CD-CE-NZ		LYS		111.7		2.3
+N-CA-C			LYS		111.0		2.7
+CA-C-O			LYS		120.1		2.1
+N-CA-CB			MET		110.6		1.8
+CB-CA-C			MET		110.4		2.0
+CA-CB-CG		MET		113.3		1.7
+CB-CG-SD		MET		112.4		3.0
+CG-SD-CE		MET		100.2		1.6
+N-CA-C			MET		111.0		2.7
+CA-C-O			MET		120.1		2.1
+N-CA-CB			PHE		110.6		1.8
+CB-CA-C			PHE		110.4		2.0
+CA-CB-CG		PHE		113.9		2.4
+CB-CG-CD1		PHE		120.8		0.7
+CB-CG-CD2		PHE		120.8		0.7
+CD1-CG-CD2		PHE		118.3		1.3
+CG-CD1-CE1		PHE		120.8		1.1
+CG-CD2-CE2		PHE		120.8		1.1
+CD1-CE1-CZ		PHE		120.1		1.2
+CD2-CE2-CZ		PHE		120.1		1.2
 CE1-CZ-CE2		PHE		120.0		1.8
-CD1-CG-CD2		PHE		118.6		1.5
-N-CA-C			GLY		112.5		2.9
-CA-C-O			GLY		120.8		2.1
-N-CA-C			HIS		111.2		2.8
-CA-C-O			HIS		120.8		1.7
-N-CA-CB			HIS		110.5		1.7
-C-CA-CB			HIS		110.1		1.9
-CA-CB-CG		HIS		113.8		1.0
-CB-CG-ND1		HIS		122.7		1.5
-CG-ND1-CE1		HIS		109.3		1.7
-ND1-CE1-NE2		HIS		108.4		1.0
-CE1-NE2-CD2		HIS		109.0		1.0
-NE2-CD2-CG		HIS		107.2		1.0
-CD2-CG-ND1		HIS		106.1		1.0
-CB-CG-CD2		HIS		131.2		1.3
-N-CA-C			ILE		111.2		2.8
-CA-C-O			ILE		120.8		1.7
-N-CA-CB			ILE		111.5		1.7
-C-CA-CB			ILE		109.1		2.2
-CA-CB-CG2		ILE		110.5		1.7
-CA-CB-CG1		ILE		110.4		1.7
-CG2-CB-CG1		ILE		110.7		3.0
-CB-CG1-CD1		ILE		113.8		2.1
-N-CA-C			LYS		111.2		2.8
-CA-C-O			LYS		120.8		1.7
-N-CA-CB			LYS		110.5		1.7
-C-CA-CB			LYS		110.1		1.9
-CA-CB-CG		LYS		114.1		2.0
-CB-CG-CD		LYS		111.3		2.3
-CG-CD-CE		LYS		111.3		2.3
-CD-CE-NZ		LYS		111.9		3.2
-N-CA-C			LEU		111.2		2.8
-CA-C-O			LEU		120.8		1.7
-N-CA-CB			LEU		110.5		1.7
-C-CA-CB			LEU		110.1		1.9
-CA-CB-CG		LEU		116.3		3.5
-CB-CG-CD1		LEU		110.7		3.0
-CB-CG-CD2		LEU		110.7		3.0
-CD1-CG-CD2		LEU		110.8		2.2
-N-CA-C			MET		111.2		2.8
-CA-C-O			MET		120.8		1.7
-N-CA-CB			MET		110.5		1.7
-C-CA-CB			MET		110.1		1.9
-CA-CB-CG		MET		114.1		2.0
-CB-CG-SD		MET		112.7		3.0
-CG-SD-CE		MET		100.9		2.2
-N-CA-C			ASN		111.2		2.8
-CA-C-O			ASN		120.8		1.7
-N-CA-CB			ASN		110.5		1.7
-C-CA-CB			ASN		110.1		1.9
-CA-CB-CG		ASN		112.6		1.0
-CB-CG-ND2		ASN		116.4		1.5
-CB-CG-OD1		ASN		120.8		2.0
-ND2-CG-OD1		ASN		122.6		1.0
-N-CA-C			PRO		111.8		2.5
-CA-C-O			PRO		120.8		1.7
-N-CA-CB			PRO		103.0		1.1
-C-CA-CB			PRO		110.1		1.9
-CA-CB-CG		PRO		104.5		1.9
-CB-CG-CD		PRO		106.1		3.2
+N-CA-C			PHE		111.0		2.7
+CA-C-O			PHE		120.1		2.1
+N-CA-CB			PRO		103.3		1.2
+CB-CA-C			PRO		111.7		2.1
+CA-CB-CG		PRO		104.8		1.9
+CB-CG-CD		PRO		106.5		3.9
 CG-CD-N			PRO		103.2		1.5
-CD-N-CA			PRO		112.0		1.4
-N-CA-C			GLN		111.2		2.8
-CA-C-O			GLN		120.8		1.7
-N-CA-CB			GLN		110.5		1.7
-C-CA-CB			GLN		110.1		1.9
-CA-CB-CG		GLN		114.1		2.0
-CB-CG-CD		GLN		112.6		1.7
-CG-CD-NE2		GLN		116.4		1.5
-CG-CD-OE1		GLN		120.8		2.0
-NE2-CD-OE1		GLN		122.6		1.0
-N-CA-C			ARG		111.2		2.8
-CA-C-O			ARG		120.8		1.7
-N-CA-CB			ARG		110.5		1.7
-C-CA-CB			ARG		110.1		1.9
-CA-CB-CG		ARG		114.1		2.0
-CB-CG-CD		ARG		111.3		2.3
-CG-CD-NE		ARG		112.0		2.2
-CD-NE-CZ		ARG		124.2		1.5
-NE-CZ-NH1		ARG		120.0		1.9
-NE-CZ-NH2		ARG		120.0		1.9
-NH1-CZ-NH2		ARG		119.7		1.8
-N-CA-C			SER		111.2		2.8
-CA-C-O			SER		120.8		1.7
-N-CA-CB			SER		110.5		1.7
-C-CA-CB			SER		110.1		1.9
-CA-CB-OG		SER		111.1		2.0
-N-CA-C			THR		111.2		2.8
-CA-C-O			THR		120.8		1.7
-N-CA-CB			THR		111.5		1.7
-C-CA-CB			THR		109.1		2.2
-CA-CB-CG2		THR		110.5		1.7
-CA-CB-OG1		THR		109.6		1.5
-CG2-CB-OG1		THR		109.3		2.0
-N-CA-C			VAL		111.2		2.8
-CA-C-O			VAL		120.8		1.7
-N-CA-CB			VAL		111.5		1.7
-C-CA-CB			VAL		109.1		2.2
-CA-CB-CG1		VAL		110.5		1.7
-CA-CB-CG2		VAL		110.5		1.7
-CG1-CB-CG2		VAL		110.8		2.2
-N-CA-C			TRP		111.2		2.8
-CA-C-O			TRP		120.8		1.7
-N-CA-CB			TRP		110.5		1.7
-C-CA-CB			TRP		110.1		1.9
-CA-CB-CG		TRP		113.6		1.9
-CB-CG-CD1		TRP		126.9		1.5
-CB-CG-CD2		TRP		126.8		1.4
-CD1-CG-CD2		TRP		106.3		1.6
-CG-CD1-NE1		TRP		110.2		1.3
-CD1-NE1-CE2		TRP		108.9		1.8
-NE1-CE2-CZ2		TRP		130.1		1.5
-NE1-CE2-CD2		TRP		107.4		1.3
-CZ2-CE2-CD2		TRP		122.4		1.0
-CE2-CZ2-CH2		TRP		117.5		1.3
-CZ2-CH2-CZ3		TRP		121.5		1.3
-CH2-CZ3-CE3		TRP		121.1		1.3
-CZ3-CE3-CD2		TRP		118.6		1.3
-CE3-CD2-CG		TRP		133.9		1.0
-CE3-CD2-CE2		TRP		118.8		1.0
-CG-CD2-CE2		TRP		107.2		1.2
-N-CA-C			TYR		111.2		2.8
-CA-C-O			TYR		120.8		1.7
-N-CA-CB			TYR		110.5		1.7
-C-CA-CB			TYR		110.1		1.9
-CA-CB-CG		TYR		113.9		1.8
-CB-CG-CD1		TYR		120.8		1.5
-CB-CG-CD2		TYR		120.8		1.5
-CG-CD1-CE1		TYR		121.2		1.5
-CG-CD2-CE2		TYR		121.2		1.5
-CD1-CE1-CZ		TYR		119.6		1.8
-CD2-CE2-CZ		TYR		119.6		1.8
-CE1-CZ-CE2		TYR		120.3		2.0
-CD1-CG-CD2		TYR		118.1		1.5
-CE1-CZ-OH		TYR		119.9		3.0
-CE2-CZ-OH		TYR		119.9		3.0
+CA-N-CD			PRO		111.7		1.4
+N-CA-C			PRO		112.1		2.6
+CA-C-O			PRO		120.2		2.4
+N-CA-CB			SER		110.5		1.5
+CB-CA-C			SER		110.1		1.9
+CA-CB-OG		SER		111.2		2.7
+N-CA-C			SER		111.0		2.7
+CA-C-O			SER		120.1		2.1
+N-CA-CB			THR		110.3		1.9
+CB-CA-C			THR		111.6		2.7
+CA-CB-OG1		THR		109.0		2.1
+CA-CB-CG2		THR		112.4		1.4
+OG1-CB-CG2		THR		110.0		2.3
+N-CA-C			THR		111.0		2.7
+CA-C-O			THR		120.1		2.1
+N-CA-CB			TRP		110.6		1.8
+CB-CA-C			TRP		110.4		2.0
+CA-CB-CG		TRP		113.7		1.9
+CB-CG-CD1		TRP		127.0		1.3
+CB-CG-CD2		TRP		126.6		1.3
+CD1-CG-CD2		TRP		106.3		0.8
+CG-CD1-NE1		TRP		110.1		1.0
+CD1-NE1-CE2		TRP		109.0		0.9
+NE1-CE2-CD2		TRP		107.3		1.0
+CE2-CD2-CG		TRP		107.3		0.8
+CG-CD2-CE3		TRP		133.9		0.9
+NE1-CE2-CZ2		TRP		130.4		1.1
+CE3-CD2-CE2		TRP		118.7		1.2
+CD2-CE2-CZ2		TRP		122.3		1.2
+CE2-CZ2-CH2		TRP		117.4		1.0
+CZ2-CH2-CZ3		TRP		121.6		1.2
+CH2-CZ3-CE3		TRP		121.2		1.1
+CZ3-CE3-CD2		TRP		118.8		1.3
+N-CA-C			TRP		111.0		2.7
+CA-C-O			TRP		120.1		2.1
+N-CA-CB			TYR		110.6		1.8
+CB-CA-C			TYR		110.4		2.0
+CA-CB-CG		TYR		113.4		1.9
+CB-CG-CD1		TYR		121.0		0.6
+CB-CG-CD2		TYR		121.0		0.6
+CD1-CG-CD2		TYR		117.9		1.1
+CG-CD1-CE1		TYR		121.3		0.8
+CG-CD2-CE2		TYR		121.3		0.8
+CD1-CE1-CZ		TYR		119.8		0.9
+CD2-CE2-CZ		TYR		119.8		0.9
+CE1-CZ-CE2		TYR		119.8		1.6
+CE1-CZ-OH		TYR		120.1		2.7
+CE2-CZ-OH		TYR		120.1		2.7
+N-CA-C			TYR		111.0		2.7
+CA-C-O			TYR		120.1		2.1
+N-CA-CB			VAL		111.5		2.2
+CB-CA-C			VAL		111.4		1.9
+CA-CB-CG1		VAL		110.9		1.5
+CA-CB-CG2		VAL		110.9		1.5
+CG1-CB-CG2		VAL		110.9		1.6
+N-CA-C			VAL		111.0		2.7
+CA-C-O			VAL		120.1		2.1
 -
 
-Non-bonded distance	Minimum Dist    Tolerance
-C-C			2.10		0.5             
-C-N			2.10		0.5               
-C-S			2.45		0.5             
-C-O			2.25		0.5             
-N-N			2.05		0.5		
-N-S			2.55		0.5		
-N-O			2.10		0.5		
-O-S			2.45		0.5		
-O-O			2.05		0.5		
-S-S			1.80		0.5		
+Non-bonded distance     Minimum Dist    Tolerance
+C-C                     3.4             1.5
+C-N                     3.25            1.5
+C-S                     3.5             1.5
+C-O                     3.22            1.5
+N-N                     3.1             1.5
+N-S                     3.35            1.5
+N-O                     3.07            1.5
+O-S                     3.32            1.5
+O-O                     3.04            1.5
+S-S                     2.03            1.0
 -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/modules/mol/alg/src/superpose_frames.cc b/modules/mol/alg/src/superpose_frames.cc
index 85514d6d73a51ea060af6214dd9a748ca336f684..f5cbba61073416b7c47dd05393c9104f4ee0b0b2 100644
--- a/modules/mol/alg/src/superpose_frames.cc
+++ b/modules/mol/alg/src/superpose_frames.cc
@@ -21,6 +21,7 @@
 #include <Eigen/Array>
 #include <Eigen/SVD>
 #include <Eigen/LU>
+#include <ost/message.hh>
 #include <ost/mol/mol.hh>
 #include <ost/mol/alg/superpose_frames.hh>
 
@@ -196,7 +197,7 @@ CoordGroupHandle SuperposeFrames(CoordGroupHandle& cg, EntityView& sel,
   //This function superposes the frames of a CoordGroup (cg) with indices between begin and end,
   //using a selection of atoms (sel), onto an EntityView (ref_view).
   if (!ref_view.IsValid()){
-    throw std::runtime_error("Invalid reference view");
+    throw ost::Error("Invalid reference view");
   }
   int real_end=end==-1 ? cg.GetFrameCount() : end;
   CoordFramePtr ref_frame;
@@ -215,7 +216,7 @@ CoordGroupHandle SuperposeFrames(CoordGroupHandle& cg, EntityView& sel,
     }
   }
   if (int(indices.size())!=ref_view.GetAtomCount()){
-    throw std::runtime_error("atom counts of the two views are not equal");
+    throw ost::Error("atom counts of the two views are not equal");
   }
   mol::AtomHandleList alist(cg.GetEntity().GetAtomList());
   std::sort(alist.begin(), alist.end(),less_index);
diff --git a/modules/mol/alg/src/svd_superpose.cc b/modules/mol/alg/src/svd_superpose.cc
index 22fa34c1d8c48a9aa370d006a3ab68a5276af091..f6b0a353d23c8ca6db39175082a745960cd570a6 100644
--- a/modules/mol/alg/src/svd_superpose.cc
+++ b/modules/mol/alg/src/svd_superpose.cc
@@ -55,7 +55,7 @@ Real CalculateRMSD(const mol::EntityView& ev1,
   int counta=ev1.GetAtomCount();
   int countb=ev2.GetAtomCount();
   if (counta!=countb){
-    throw std::runtime_error("atom counts of the two views are not equal");
+    throw Error("atom counts of the two views are not equal");
   }
   eht=ev1.GetHandle();
   int natoms=ev1.GetAtomCount();
@@ -308,10 +308,10 @@ SuperpositionResult SuperposeAtoms(const mol::AtomViewList& atoms1,
   int counta=static_cast<int>(atoms1.size());
   int countb=static_cast<int>(atoms2.size());
   if (counta!=countb){
-    throw std::runtime_error("atom counts do not match");
+    throw Error("atom counts do not match");
   }
   if ((counta<3)){
-    throw std::runtime_error("at least 3 atoms are required");
+    throw Error("at least 3 atoms are required");
   }
   SuperposerSVD sp(counta, true);
 
@@ -333,10 +333,10 @@ SuperpositionResult SuperposeSVD(const mol::EntityView& ev1,
   int counta=ev1.GetAtomCount();
   int countb=ev2.GetAtomCount();
   if (counta!=countb){
-    throw std::runtime_error("atom counts of the two views are not equal");
+    throw Error("atom counts of the two views are not equal");
   }
   if ((counta<3)){
-    throw std::runtime_error("atom counts of any view must be larger or "
+    throw Error("atom counts of any view must be larger or "
                              "equal 3");
   }
   int nrows=counta;
@@ -358,10 +358,10 @@ SuperpositionResult SuperposeSVD(const std::vector<geom::Vec3>& pl1,
                                  const std::vector<geom::Vec3>& pl2)
 {
   if (pl1.size()!=pl2.size()){
-    throw std::runtime_error("pointlist lengths not equal");
+    throw Error("pointlist lengths not equal");
   }
   if ((pl1.size()<3)){
-    throw std::runtime_error("three or more points required");
+    throw Error("three or more points required");
   }
   SuperposerSVD sp(pl1.size(), true);
   SuperpositionResult res=sp.Run(pl1, pl2);
diff --git a/modules/mol/alg/src/trajectory_analysis.cc b/modules/mol/alg/src/trajectory_analysis.cc
index 4a2671c01b981c8eed22fc8ebe9c9a86a66664e7..a4ce2026b2248fd2ea8144c170e13b2cca46198f 100644
--- a/modules/mol/alg/src/trajectory_analysis.cc
+++ b/modules/mol/alg/src/trajectory_analysis.cc
@@ -138,7 +138,7 @@ std::vector<Real> AnalyzeRMSD(const CoordGroupHandle& traj, const EntityView& re
   int count_ref=reference_view.GetAtomCount();
   int count_sele=sele_view.GetAtomCount();
   if (count_ref!=count_sele){
-    throw std::runtime_error("atom counts of the two views are not equal");
+    throw Error("atom counts of the two views are not equal");
   }  
   std::vector<Real> rmsd;
   rmsd.reserve(ceil(traj.GetFrameCount()/float(stride)));
@@ -160,10 +160,10 @@ std::vector<Real>  AnalyzeMinDistance(const CoordGroupHandle& traj, const Entity
   {
   CheckHandleValidity(traj);
   if (view1.GetAtomCount()==0){
-    throw std::runtime_error("first EntityView is empty");
+    throw Error("first EntityView is empty");
   }
   if (view2.GetAtomCount()==0){
-    throw std::runtime_error("second EntityView is empty");
+    throw Error("second EntityView is empty");
   }  
   std::vector<Real> dist;
   dist.reserve(ceil(traj.GetFrameCount()/float(stride)));
@@ -184,10 +184,10 @@ std::vector<Real> AnalyzeMinDistanceBetwCenterOfMassAndView(const CoordGroupHand
   {
   CheckHandleValidity(traj);
   if (view_cm.GetAtomCount()==0){
-    throw std::runtime_error("first EntityView is empty");
+    throw Error("first EntityView is empty");
   }
   if (view_atoms.GetAtomCount()==0){
-    throw std::runtime_error("second EntityView is empty");
+    throw Error("second EntityView is empty");
   } 
   std::vector<Real> dist, masses_cm;
   dist.reserve(ceil(traj.GetFrameCount()/float(stride)));
@@ -211,10 +211,10 @@ std::vector<Real> AnalyzeAromaticRingInteraction(const CoordGroupHandle& traj, c
   {
   CheckHandleValidity(traj);
   if (view_ring1.GetAtomCount()==0){
-    throw std::runtime_error("first EntityView is empty");
+    throw Error("first EntityView is empty");
   }
   if (view_ring2.GetAtomCount()==0){
-    throw std::runtime_error("second EntityView is empty");
+    throw Error("second EntityView is empty");
   } 
   std::vector<Real> dist, masses_ring1,masses_ring2;
   dist.reserve(ceil(traj.GetFrameCount()/float(stride)));
@@ -239,7 +239,7 @@ std::vector<Real> AnalyzeAromaticRingInteraction(const CoordGroupHandle& traj, c
   {
     CheckHandleValidity(traj);
     if (prot_seg.GetAtomCount()==0){
-      throw std::runtime_error("EntityView is empty");
+      throw Error("EntityView is empty");
     }
     std::vector<unsigned long> indices_ca;
     geom::Line3 axis;
@@ -266,7 +266,7 @@ std::vector<Real> AnalyzeAromaticRingInteraction(const CoordGroupHandle& traj, c
   {
     CheckHandleValidity(traj);
     if (prot_seg.GetAtomCount()==0){
-      throw std::runtime_error("EntityView is empty");
+      throw Error("EntityView is empty");
     }
     std::vector<unsigned long> indices_ca;
     geom::Line3 axis;
@@ -287,7 +287,7 @@ std::vector<Real> AnalyzeAromaticRingInteraction(const CoordGroupHandle& traj, c
   {
     CheckHandleValidity(traj);
     if (prot_seg.GetAtomCount()==0){
-      throw std::runtime_error("EntityView is empty");
+      throw Error("EntityView is empty");
     }
     std::vector<unsigned long> indices_ca;
     geom::Plane best_plane;
@@ -308,7 +308,7 @@ std::vector<Real> AnalyzeAromaticRingInteraction(const CoordGroupHandle& traj, c
   {
     CheckHandleValidity(traj);
     if (prot_seg.GetAtomCount()==0){
-      throw std::runtime_error("EntityView is empty");
+      throw Error("EntityView is empty");
     }
     std::vector<unsigned long> indices_c,indices_o, indices_n, indices_ca;
     std::vector<Real> helicity;
@@ -329,14 +329,14 @@ std::vector<Real> AnalyzeAromaticRingInteraction(const CoordGroupHandle& traj, c
     if (to==-1)to=traj.GetFrameCount();
     unsigned int n_atoms=selection.GetAtomCount();
     if (to<from) {
-      throw std::runtime_error("to smaller than from");
+      throw Error("to smaller than from");
     }
     unsigned int n_frames=ceil((to-from)/stride);
     if (n_atoms==0){
-      throw std::runtime_error("EntityView is empty");
+      throw Error("EntityView is empty");
     }
     if (n_frames<=1) {
-      throw std::runtime_error("number of frames is too small");
+      throw Error("number of frames is too small");
     }
     std::vector<unsigned long> indices;
     std::vector<geom::Vec3> mean_positions;
@@ -368,14 +368,14 @@ std::vector<Real> AnalyzeAromaticRingInteraction(const CoordGroupHandle& traj, c
     if (to==-1)to=traj.GetFrameCount();
     unsigned int n_atoms=selection.GetAtomCount();
     if (to<from) {
-      throw std::runtime_error("to smaller than from");
+      throw Error("to smaller than from");
     }
     unsigned int n_frames=ceil((to-from)/stride);
     if (n_atoms==0){
-      throw std::runtime_error("EntityView is empty");
+      throw Error("EntityView is empty");
     }
     if (n_frames<=1) {
-      throw std::runtime_error("number of frames is too small");
+      throw Error("number of frames is too small");
     }
     Real rmsf=0.0;
     geom::Vec3 v;
@@ -396,7 +396,7 @@ std::vector<Real> AnalyzeAromaticRingInteraction(const CoordGroupHandle& traj, c
         rmsf+=geom::Dot(v,v);
       }
     }
-    return pow(rmsf/float(n_atoms*n_frames),0.5);
+    return sqrt(rmsf/float(n_atoms*n_frames));
   }
   
 }}} //ns
diff --git a/modules/mol/base/doc/editors.rst b/modules/mol/base/doc/editors.rst
index ad4d7fb07f3d0f6a135f966a7ff82ef947e2712e..8ef488da36699f758e8346766d1ecaf1d391d3ea 100644
--- a/modules/mol/base/doc/editors.rst
+++ b/modules/mol/base/doc/editors.rst
@@ -213,6 +213,23 @@ The basic functionality of editors is implemented in the EditorBase class.
                       valid atom identifier.
      :type new_name:  string
 
+  .. method:: Connect(atom1, atom2)
+              Connect(atom1, atom2, bond_order)
+
+     Add a bond between two atoms.
+
+     :param atom1:       Must be a valid atom
+     :type atom1:        :class:`AtomHandle`
+     :param atom2:       Must be a valid atom
+     :type atom2:        :class:`AtomHandle`
+     :param bond_order:  bond order (e.g. 1=single, 2=double, 3=triple)
+     :type bond_order:   :class:`int`
+
+BondHandle (EditorBase::*connect_b)(const AtomHandle&, const AtomHandle&,
+                                    Real, Real, Real)=&EditorBase::Connect;
+BondHandle (EditorBase::*connect_d)(const AtomHandle&, const AtomHandle&,
+                                    Real, Real, Real,
+                                    unsigned char)=&EditorBase::Connect;
 
 Editor for the External Coordinate System
 --------------------------------------------------------------------------------
diff --git a/modules/mol/base/doc/entity.rst b/modules/mol/base/doc/entity.rst
index 94b8a1b3b14bbb62f03c68a043cf270b1e827e9f..847dcefb73a1b275277c69eb14e94aa4928a8103 100644
--- a/modules/mol/base/doc/entity.rst
+++ b/modules/mol/base/doc/entity.rst
@@ -181,7 +181,7 @@ The Handle Classes
       # select calpha atoms of peptides
       calphas=ent.Select('aname=CA and peptide=true')
       
-      # select atoms in a box of size 10, centered at the origin
+      # select atoms in a box of size 10, centred at the origin
       in_box=ent.Select('x=-5:5 and y=-5:5 and z=-5:5')
     
     :param query: The query to be executed. See :class:`Query` for details.
@@ -256,7 +256,7 @@ The Handle Classes
     
   .. method:: FindWithin(pos, radius)
   
-    Find all atoms in sphere of given radius centered at *pos*. To turn the
+    Find all atoms in sphere of given radius centred at *pos*. To turn the
     returned list of atoms into an :class:`EntityView`, use
     :func:`CreateViewFromAtomList`.
     
@@ -856,44 +856,59 @@ The View Classes
 
     Returns a copy of this entity. Provided for `duck-typing <http://en.wikipedia.org/wiki/Duck_typing>` purposes.
     
-    :rtype: EntityView
-  
+    :rtype: :class:`EntityView`
+
   .. method:: AddChain(chain_handle[, view_add_flags])
 
     Add chain to view. By default, only the chain is added to the view, but not 
-    its residues and atoms. This behavior can be changed by passing in an
-    appropriate set of `view_add_flags`
-    
-    :param chain_handle:
-    :type  chain_handle: ChainHandle
-    :param view_add_flags: An ORed together combination of `view_add_flags`.
-    :type  view_add_flags: int
-    :rtype: class:`ChainView`
+    its residues and atoms. This behaviour can be changed by passing in an
+    appropriate set of `view_add_flags`.
+
+    The following example just adds a chain without residues and atoms:
+
+    .. code-block:: python
+
+        pdb = ost.io.LoadPDB(<PDB file name>)
+        v = pdb.CreateEmptyView()
+        v.AddChain(pdb.chains[0])
+
+    To **copy** a whole chain, go like:
+
+    .. code-block:: python
+
+        pdb = ost.io.LoadPDB(<PDB file name>)
+        v = pdb.CreateEmptyView()
+        v.AddChain(pdb.chains[0], ost.mol.INCLUDE_ALL)
+
+    :param chain_handle: The chain handle to be added.
+    :type  chain_handle: :class:`ChainHandle`
+    :param view_add_flags: An ORed together combination of :ref:`viewaddflags`.
+    :type view_add_flags: :class:`int`
+    :rtype: :class:`ChainView`
 
   .. method:: AddResidue(residue_handle[, view_add_flags])
 
-    Add residue to view. If the residue's chain is not already part of the view, 
-    it will be added. By default, only the residue is added, but not its atoms. 
-    This behaviour can be modified by passing in an appropriate combination of 
-    `view_add_flags`.
-    
-    :param residue_handle:
-    :type  residue_handle: ResidueHandle
-    :param view_add_flags:
-    :type  view_add_flags: int
-    :rtype: class:`ResidueView`
+    Add residue to view. If the residue's chain is not already part of the
+    view, it will be added. By default, only the residue is added, but not its
+    atoms. This behaviour can be modified by passing in an appropriate
+    combination of :ref:`viewaddflags`.
+
+    :param residue_handle: The residue handle to be added
+    :type  residue_handle: :class:`ResidueHandle`
+    :param view_add_flags: An ORed together combination of :ref:`viewaddflags`
+    :type  view_add_flags: :class:`int`
+    :rtype: :class:`ResidueView`
 
   .. method:: AddAtom(atom_handle[, view_add_flags])
 
     Add the atom to view. The chain and residue of the atom are added to the 
     view if they haven't already been added.
     
-    
     :param atom_handle: The atom handle
-    :type  atom_handle: AtomHandle
-    :param view_add_flags: An ORed together combination of ViewAddFlags
-    :type  view_add_flags: int
-    :rtype: class:`AtomView`
+    :type  atom_handle: :class:`AtomHandle`
+    :param view_add_flags: An ORed together combination of :ref:`viewaddflags`
+    :type  view_add_flags: :class:`int`
+    :rtype: :class:`AtomView`
 
   .. method:: AddBond(bond_handle)
 
@@ -1210,24 +1225,25 @@ The View Classes
 
     Add atom to the view. If the residue of the atom is not already part of the 
     view, it will be added. If the atom does not belong to chain, the result is
-    undefined. 
+    undefined. Foo
     
     :param atom_handle: The atom to be added
     :type  atom_handle: :class:`AtomHandle`
-    :param view_add_flags: An ORed together combination of ViewAddFlags
-    :type  view_add_flags: int
+    :param view_add_flags: An ORed together combination of :ref:`viewaddflags`
+    :type  view_add_flags: :class:`int`
     :rtype: :class:`AtomView`
 
   .. method:: AddResidue(residue_handle[, view_add_flags])
 
     Add residue to the view. If the atom does not belong to chain, the result is
-    undefined. By default, only the residue, but no atoms are added to the view. 
-    To change the behavior, pass in a suitable combination of `view_add_flags`.
+    undefined. By default, only the residue, but no atoms are added to the
+    view. To change the behavior, pass in a suitable combination of
+    :ref:`viewaddflags`.
     
-    :param residue_handle:
+    :param residue_handle: The residue handle to be added.
     :type  residue_handle: :class:`ResidueHandle`
-    :param view_add_flags:
-    :type  view_add_flags: int
+    :param view_add_flags: An ORed together combination of :ref:`viewaddflags`
+    :type  view_add_flags: :class:`int`
     :rtype: :class:`ResidueView`
 
   .. method:: FindAtom(res_num, atom_name)
@@ -1462,11 +1478,12 @@ The View Classes
 
   .. method:: AddAtom(atom_handle[, flags])
 
-    Add atom to the view. 
-    :param atom_handle:
+    Add atom to the view.
+
+    :param atom_handle: Atom handle to be added
     :type  atom_handle: :class:`AtomHandle`
-    :param flags: An ORed together combination of ViewAddFlags.
-    :type  flags: int
+    :param flags: An ORed together combination of :ref:`viewaddflags`
+    :type  flags: :class:`int`
     :rtype: :class:`AtomView`
 
   .. method:: GetCenterOfAtoms()
@@ -1618,3 +1635,23 @@ ChainType functions
 
    :returns: :class:`str`
 
+.. _viewaddflags:
+
+ViewAddFlags
+--------------------------------------------------------------------------------
+
+Those are the flags controlling behaviour of routines adding handles to views.
+
+* ``INCLUDE_ATOMS`` - Include all atoms when adding a residue handle to a view
+
+* ``INCLUDE_RESIDUES`` - Include all residues when adding a chain to a view
+
+* ``INCLUDE_CHAINS`` - Include all chains when creating a new entity view
+
+* ``INCLUDE_ALL`` = ``INCLUDE_ATOMS`` | ``INCLUDE_RESIDUES`` |
+  ``INCLUDE_CHAINS`` - Convenience flags to include all substructures
+
+* ``CHECK_DUPLICATES`` - If set, it will be checked that no duplicates are
+  created when adding a new handle
+    
+
diff --git a/modules/mol/base/pymod/CMakeLists.txt b/modules/mol/base/pymod/CMakeLists.txt
index 3f514b2b8afba9e8f95473898b9649da2b3afcb7..6e158771aa0c9e3b2608203469f9b3afc65e5708 100644
--- a/modules/mol/base/pymod/CMakeLists.txt
+++ b/modules/mol/base/pymod/CMakeLists.txt
@@ -18,6 +18,7 @@ export_bounding_box.cc
 export_query_view_wrapper.cc
 export_torsion.cc
 export_visitor.cc
+export_transform.cc
 wrap_mol.cc
 export_entity_property_mapper.cc
 )
diff --git a/modules/mol/base/pymod/export_chain_view.cc b/modules/mol/base/pymod/export_chain_view.cc
index e8c54c9a4a9436585531da168bdcbeab4130d3b2..70ee5d1d1a216c56ad6757ffa681094141d85b41 100644
--- a/modules/mol/base/pymod/export_chain_view.cc
+++ b/modules/mol/base/pymod/export_chain_view.cc
@@ -34,7 +34,8 @@ typedef ResidueView (ChainView::*RnumMethod)(const ResNum&) const;
 typedef ResidueView (ChainView::*HandleMethod)(const ResidueHandle&) const;
 
 RnumMethod rnum_find_residue=&ChainView::FindResidue;
-HandleMethod handle_find_residue=&ChainView::FindResidue;    
+HandleMethod handle_find_residue=&ChainView::FindResidue;
+HandleMethod view_for_rh=&ChainView::ViewForHandle;
 
 typedef ResidueView (ChainView::*HM)(const ResidueHandle&, ViewAddFlags);
 typedef ResidueView (ChainView::*VM)(const ResidueView&, ViewAddFlags);
@@ -48,9 +49,11 @@ BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(X_add_atom_overloads,
                                       ChainView::AddAtom, 1, 2)
                                       
 AtomView (ChainView::*find_atom_a)(const ResNum&, const String&) const=&ChainView::FindAtom;
-AtomView (ChainView::*find_atom_b)(const AtomHandle&) const=&ChainView::FindAtom;                                      
+AtomView (ChainView::*find_atom_b)(const AtomHandle&) const=&ChainView::FindAtom;
+AtomView (ChainView::*view_for_ah)(const AtomHandle&) const=&ChainView::ViewForHandle;
 typedef EntityView (ChainView::*QueryMethod)(const Query&, uint) const;
 typedef EntityView (ChainView::*StringMethod)(const String&, uint) const;  
+
 QueryMethod select_query=&ChainView::Select;
 StringMethod select_string=&ChainView::Select;
 }
@@ -71,8 +74,10 @@ void export_ChainView()
     .def("GetEntity", &ChainView::GetEntity)
     .def("FindResidue",rnum_find_residue, arg("residue_number"))
     .def("FindResidue", handle_find_residue, arg("residue_handle"))
+    .def("ViewForHandle", view_for_rh, arg("residue_handle"))
     .def("FindAtom", find_atom_a)
-    .def("FindAtom", find_atom_b)    
+    .def("FindAtom", find_atom_b)
+    .def("ViewForHandle", view_for_ah)
     .def("AddAtom", &ChainView::AddAtom, 
          X_add_atom_overloads(args("atom_handle", "view_add_flags")))
     .def("AddResidue", hm, 
diff --git a/modules/mol/base/pymod/export_coord_group.cc b/modules/mol/base/pymod/export_coord_group.cc
index 6bdeb1d6958f797898aea3a2915a3063daf10dea..a445e74c079e0d2074f3b6bd3e4ce6b7a520ec0a 100644
--- a/modules/mol/base/pymod/export_coord_group.cc
+++ b/modules/mol/base/pymod/export_coord_group.cc
@@ -47,24 +47,32 @@ void export_CoordGroup()
   class_<CoordGroupHandle>("CoordGroupHandle",no_init)
     .def("IsValid",&CoordGroupHandle::IsValid)
     .def("GetEntity",&CoordGroupHandle::GetEntity)
+    .add_property("entity",&CoordGroupHandle::GetEntity)
     .def("GetAtomCount",&CoordGroupHandle::GetAtomCount)
+    .add_property("atom_count",&CoordGroupHandle::GetAtomCount)
     .def("GetFrame",&CoordGroupHandle::GetFrame2)
     .def("AddFrames", &CoordGroupHandle::AddFrames)
     .def("AddFrame", add_frame1)
     .def("AddFrame", add_frame2)
     .def("GetFrameCount",&CoordGroupHandle::GetFrameCount)
+    .add_property("frame_count",&CoordGroupHandle::GetFrameCount)
     .def("GetFramePositions",&CoordGroupHandle::GetFramePositions)
     .def("SetFramePositions",&CoordGroupHandle::SetFramePositions)
     .def("SetAtomPos",&CoordGroupHandle::SetAtomPos)
     .def("GetAtomPos",&CoordGroupHandle::GetAtomPos)
     .def("CopyFrame",&CoordGroupHandle::CopyFrame)
-    .add_property("atoms", &CoordGroupHandle::GetAtomList)
-    .add_property("entity", &CoordGroupHandle::GetEntity)
     .def("IsValid", &CoordGroupHandle::IsValid)
     .def("Capture", capture1)
     .def("Capture", capture2)
     .def("CaptureInto",&CoordGroupHandle::CaptureInto)
     .def("GetAtomList",&CoordGroupHandle::GetAtomList)
+    .add_property("atoms", &CoordGroupHandle::GetAtomList)
+    .def("GetDelta",&CoordGroupHandle::GetDelta)
+    .def("SetDelta",&CoordGroupHandle::SetDelta)
+    .add_property("delta",&CoordGroupHandle::GetDelta,&CoordGroupHandle::SetDelta)
+    .def("GetStartTime",&CoordGroupHandle::GetStartTime)
+    .def("SetStartTime",&CoordGroupHandle::SetStartTime)
+    .add_property("start_time",&CoordGroupHandle::GetStartTime,&CoordGroupHandle::SetStartTime)
     .def("__getitem__",cg_getitem)
     .def("__setitem__",cg_setitem)
     .def("Filter", &CoordGroupHandle::Filter, (arg("selected"),arg("first")=0,arg("last")=-1))
diff --git a/modules/mol/base/pymod/export_editors.cc b/modules/mol/base/pymod/export_editors.cc
index 6cee09765c2ce84e7a07bbddf4d05abebdd84cf6..e53a02d35ffc39d35e826c9f34938dfd2821c4a1 100644
--- a/modules/mol/base/pymod/export_editors.cc
+++ b/modules/mol/base/pymod/export_editors.cc
@@ -82,13 +82,13 @@ void set_pos2_t(XCSEditor& e, const AtomHandleList& alist, object pyobj)
   size_t acount = alist.size();
   
   if(!PyArray_Check(pyobj.ptr())) {
-    throw std::runtime_error("expected a numpy array");
+    throw Error("expected a numpy array");
     return;
   }
   PyArrayObject* na=reinterpret_cast<PyArrayObject*>(pyobj.ptr());
   
   if(PyArray_NDIM(na)!=2 || PyArray_DIM(na,0)!=int(acount) || PyArray_DIM(na,1)!=3) {
-    throw std::runtime_error("excpected a numpy array of shape (NAtoms, 3)");
+    throw Error("excpected a numpy array of shape (NAtoms, 3)");
     return;
   }
   
@@ -106,20 +106,20 @@ void set_pos2_t(XCSEditor& e, const AtomHandleList& alist, object pyobj)
         e.SetAtomTransformedPos(alist,reinterpret_cast<double*>(PyArray_DATA(na)));
       }
     } else {
-      throw std::runtime_error("expected a numpy array of type float or double");
+      throw Error("expected a numpy array of type float or double");
       return;
     }
   } else {
     // non-contiguous
 #if 0
-    throw std::runtime_error("expected contiguous numpy array");
+    throw Error("expected contiguous numpy array");
 #else
     if(PyArray_TYPE(na)==NPY_FLOAT) {
       set_pos2_nc_t<float,O>(e,alist,na);
     } else if(PyArray_TYPE(na)==NPY_DOUBLE) {
       set_pos2_nc_t<double,O>(e,alist,na);
     } else {
-      throw std::runtime_error("expected a numpy array of type float or double");
+      throw Error("expected a numpy array of type float or double");
       return;
     }
 #endif
@@ -172,7 +172,7 @@ void set_pos(XCSEditor& e, object o1, object o2, bool trans)
   }
 
 #else
-  throw std::runtime_error("SetAtom*Pos(...,ndarray) not available, because numpy support not compiled in");
+  throw Error("SetAtom*Pos(...,ndarray) not available, because numpy support not compiled in");
 #endif
 }
 
diff --git a/modules/mol/base/pymod/export_entity.cc b/modules/mol/base/pymod/export_entity.cc
index 6fda49c793342259e0d3ab5078716d3dda8c0a5e..adf2c83b7621420f1000aafa96439f90d34a203f 100644
--- a/modules/mol/base/pymod/export_entity.cc
+++ b/modules/mol/base/pymod/export_entity.cc
@@ -63,15 +63,15 @@ ICSEditor depr_request_ics_editor(EntityHandle e, EditMode m)
   return e.EditICS(m);
 }
 
+
+#if OST_NUMPY_SUPPORT_ENABLED
+
 bool less_index(const mol::AtomHandle& a1, const mol::AtomHandle& a2)
 {
   return a1.GetIndex()<a2.GetIndex();
 }
-
-
 PyObject* get_pos2(EntityHandle& entity, bool id_sorted)
 {
-#if OST_NUMPY_SUPPORT_ENABLED
   npy_intp dims[]={entity.GetAtomCount(),3};
   PyObject* na = PyArray_SimpleNew(2,dims,NPY_FLOAT);
   npy_float* nad = reinterpret_cast<npy_float*>(PyArray_DATA(na));
@@ -93,10 +93,6 @@ PyObject* get_pos2(EntityHandle& entity, bool id_sorted)
     }
   }
   return na;
-#else
-  throw std::runtime_error("GetPositions disabled, since numpy support is not compiled in");
-  return 0;
-#endif
 }
 
 PyObject* get_pos1(EntityHandle& entity)
@@ -104,6 +100,9 @@ PyObject* get_pos1(EntityHandle& entity)
   return get_pos2(entity,true);
 }
 
+
+
+#endif
 } // ns
 
 void export_Entity()
@@ -208,3 +207,4 @@ void export_Entity()
     .def(vector_indexing_suite<EntityHandleList>())
   ;
 }
+
diff --git a/modules/mol/base/pymod/export_entity_property_mapper.cc b/modules/mol/base/pymod/export_entity_property_mapper.cc
index fa271bed83a04df8773f8110e773b94e5a7676e1..df008566a416b74fe97d151f76660b2ab29157e8 100644
--- a/modules/mol/base/pymod/export_entity_property_mapper.cc
+++ b/modules/mol/base/pymod/export_entity_property_mapper.cc
@@ -40,7 +40,7 @@ EntityPropertyMapper create_epm(const String& prop_name, char level)
     case 'u':
       return EntityPropertyMapper(prop_name, Prop::UNSPECIFIED);
     default:
-      throw std::runtime_error(String("unknown property level '")+level+"'");
+      throw Error(String("unknown property level '")+level+"'");
   }
 }
 
diff --git a/modules/mol/base/pymod/export_entity_view.cc b/modules/mol/base/pymod/export_entity_view.cc
index 5169ded4a4927fbc4dbcaee4a59ab77545361b53..4ce29c03b4be50ba28d895fa957b25a626fbe690 100644
--- a/modules/mol/base/pymod/export_entity_view.cc
+++ b/modules/mol/base/pymod/export_entity_view.cc
@@ -57,6 +57,7 @@ VM vm=&EntityView::AddChain;
 HM hm=&EntityView::AddChain;
 
 HandleMethod find_chain_hnd=&EntityView::FindChain;
+HandleMethod view_for_ch=&EntityView::ViewForHandle;
 StringMethod find_chain_str=&EntityView::FindChain;
 QSMethod select_string=&EntityView::Select;
 QueryMethod  select_query=&EntityView::Select;
@@ -94,8 +95,16 @@ BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(X_add_chain_overloads,
 BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(X_add_atom_overloads,
                                       EntityView::AddAtom, 1, 2)
 
-AtomView (EntityView::*find_atom_a)(const String&, const ResNum&, const String&) const=&EntityView::FindAtom;
+AtomView (EntityView::*find_atom_a)(const String&, const ResNum&,
+                                    const String&) const=&EntityView::FindAtom;
 AtomView (EntityView::*find_atom_b)(const AtomHandle&) const=&EntityView::FindAtom;
+AtomView (EntityView::*view_for_ah)(const AtomHandle&) const=&EntityView::ViewForHandle;
+
+ResidueView (EntityView::*find_res_a)(const ResidueHandle&) const=&EntityView::FindResidue;
+ResidueView (EntityView::*find_res_b)(const String&,
+                                      const ResNum&) const=&EntityView::FindResidue;
+
+ResidueView (EntityView::*view_for_rh)(const ResidueHandle&) const=&EntityView::ViewForHandle;
 }
 
 
@@ -118,9 +127,15 @@ void export_EntityView()
     .def("ExtendViewToResidues", &EntityView::ExtendViewToResidues)
     .def("ExtendViewToSurrounding", &EntityView::ExtendViewToSurrounding)
     .def("FindChain", find_chain_str)
-    .def("FindResidue", &EntityView::FindResidue)
+    .def("FindChain", find_chain_hnd)
+    .def("ViewForHandle", view_for_rh)
+    .def("ViewForHandle", view_for_ch)
     .def("FindAtom", find_atom_a)
-    .def("FindAtom", find_atom_b)    
+    .def("FindAtom", find_atom_b)
+    .def("FindResidue", find_res_a)
+    .def("FindResidue", find_res_b)
+
+    .def("ViewForHandle", view_for_ah)
     .def("GetAtomCount", &EntityView::GetAtomCount)
     .def("GetGeometricStart", geom_start<EntityView>)
     .def("GetGeometricEnd", geom_end<EntityView>)
diff --git a/modules/mol/base/pymod/export_residue_view.cc b/modules/mol/base/pymod/export_residue_view.cc
index 89c6eddc428833b3dfe3d019b109b0e558c95ed7..79d167996ed18eb6d53d0ae57e66df3f8c2c695a 100644
--- a/modules/mol/base/pymod/export_residue_view.cc
+++ b/modules/mol/base/pymod/export_residue_view.cc
@@ -35,6 +35,7 @@ typedef AtomView (ResidueView::*HandleMethodNonConst)(const AtomHandle&, ViewAdd
 
 StringMethod string_find_atom=&ResidueView::FindAtom;
 HandleMethod handle_find_atom=&ResidueView::FindAtom;
+HandleMethod view_for_ah=&ResidueView::ViewForHandle;
 HandleMethodNonConst add_atom_handle=&ResidueView::AddAtom;
 ViewMethod add_atom_view=&ResidueView::AddAtom;
 BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(X_add_atom_overloads,
@@ -67,6 +68,7 @@ void export_ResidueView()
     .def("AddAtom", add_atom_handle, X_add_atom_overloads(args("atom_handle", "flags")))
     .def("AddAtom", add_atom_view, X_add_atom_overloads(args("atom_view", "flags")))
     .def("FindAtom", handle_find_atom, args("atom_handle"))
+    .def("ViewForHandle", view_for_ah, arg("atom_handle"))
     .def("IsAtomIncluded", &ResidueView::IsAtomIncluded, args("atom_handle"))
     .def("GetIndex", &ResidueView::GetIndex)  
     .add_property("index", &ResidueView::GetIndex)
diff --git a/modules/mol/base/pymod/export_transform.cc b/modules/mol/base/pymod/export_transform.cc
new file mode 100644
index 0000000000000000000000000000000000000000..1dc8bdc16bb6df0ba9f55693ebd0866da449400e
--- /dev/null
+++ b/modules/mol/base/pymod/export_transform.cc
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+// 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>
+
+#include <ost/mol/transform.hh>
+#if(OST_INFO_ENABLED)
+#include <ost/info/info.hh>
+#endif
+
+using namespace boost::python;
+using namespace ost;
+using namespace ost::mol;
+
+void export_Transform()
+{
+  class_<Transform>("Transform", init<>())
+    .def(init<const Transform&>()) // shouldn't this be there automatically ?
+    .def("GetMatrix",&Transform::GetMatrix)
+    .def("SetMatrix",&Transform::SetMatrix)
+    .add_property("matrix",&Transform::GetMatrix,&Transform::SetMatrix)
+    .def("GetTransposedMatrix",&Transform::GetTransposedMatrix)
+    .add_property("tmatrix",&Transform::GetTransposedMatrix)
+    .add_property("transposed_matrix",&Transform::GetTransposedMatrix)
+    .def("GetInvertedMatrix",&Transform::GetInvertedMatrix)
+    .add_property("inverted_matrix",&Transform::GetInvertedMatrix)
+    .def("SetTrans",&Transform::SetTrans)
+    .def("GetTrans",&Transform::GetTrans)
+    .add_property("trans",&Transform::GetTrans,&Transform::SetTrans)
+    .def("SetCenter",&Transform::SetCenter)
+    .def("GetCenter",&Transform::GetCenter)
+    .add_property("center",&Transform::GetCenter,&Transform::SetCenter)
+    .def("SetRot",&Transform::SetRot)
+    .def("GetRot",&Transform::GetRot)
+    .add_property("rot",&Transform::GetRot,&Transform::SetRot)
+    .def("ApplyXAxisRotation",&Transform::ApplyXAxisRotation)
+    .def("ApplyYAxisRotation",&Transform::ApplyYAxisRotation)
+    .def("ApplyZAxisRotation",&Transform::ApplyZAxisRotation)
+    .def("ApplyXAxisTranslation",&Transform::ApplyXAxisTranslation)
+    .def("ApplyYAxisTranslation",&Transform::ApplyYAxisTranslation)
+    .def("ApplyZAxisTranslation",&Transform::ApplyZAxisTranslation)
+    .def("ApplyAxisRotation",&Transform::ApplyAxisRotation)
+    ;
+#if(OST_INFO_ENABLED)
+  def("TransformToInfo", &TransformToInfo);
+  def("TransformFromInfo", &TransformFromInfo);
+#endif
+}
diff --git a/modules/mol/base/pymod/wrap_mol.cc b/modules/mol/base/pymod/wrap_mol.cc
index 33b09e2f20b4c1126f05cf501c04a599663048f9..31cf8165b463460f346fc6d1ec820ceb317edb65 100644
--- a/modules/mol/base/pymod/wrap_mol.cc
+++ b/modules/mol/base/pymod/wrap_mol.cc
@@ -17,11 +17,7 @@
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 //------------------------------------------------------------------------------
 #include <boost/python.hpp>
-#include <ost/mol/transform.hh>
 #include <ost/mol/editor_base.hh>
-#if(OST_INFO_ENABLED)
-#include <ost/info/info.hh>
-#endif
 
 using namespace boost::python;
 using namespace ost::mol;
@@ -46,6 +42,8 @@ void export_PropertyID();
 void export_BoundingBox();
 void export_QueryViewWrapper();
 void export_EntityPropertyMapper();
+void export_Transform();
+
 BOOST_PYTHON_MODULE(_ost_mol)
 {
   enum_<EditMode>("EditMode")
@@ -73,33 +71,5 @@ BOOST_PYTHON_MODULE(_ost_mol)
   export_BoundingBox();
   export_QueryViewWrapper();
   export_EntityPropertyMapper();
-  class_<Transform>("Transform", init<>())
-    .def(init<const Transform&>()) // shouldn't this be there automatically ?
-    .def("GetMatrix",&Transform::GetMatrix)
-    .def("SetMatrix",&Transform::SetMatrix)
-    .add_property("matrix",&Transform::GetMatrix,&Transform::SetMatrix)
-    .def("GetTransposedMatrix",&Transform::GetTransposedMatrix)
-    .add_property("tmatrix",&Transform::GetTransposedMatrix)
-    .def("SetTrans",&Transform::SetTrans)
-    .def("GetTrans",&Transform::GetTrans)
-    .add_property("trans",&Transform::GetTrans,&Transform::SetTrans)
-    .def("SetCenter",&Transform::SetCenter)
-    .def("GetCenter",&Transform::GetCenter)
-    .add_property("center",&Transform::GetCenter,&Transform::SetCenter)
-    .def("SetRot",&Transform::SetRot)
-    .def("GetRot",&Transform::GetRot)
-    .add_property("rot",&Transform::GetRot,&Transform::SetRot)
-    .def("ApplyXAxisRotation",&Transform::ApplyXAxisRotation)
-    .def("ApplyYAxisRotation",&Transform::ApplyYAxisRotation)
-    .def("ApplyZAxisRotation",&Transform::ApplyZAxisRotation)
-    .def("ApplyXAxisTranslation",&Transform::ApplyXAxisTranslation)
-    .def("ApplyYAxisTranslation",&Transform::ApplyYAxisTranslation)
-    .def("ApplyZAxisTranslation",&Transform::ApplyZAxisTranslation)
-    .def("ApplyAxisRotation",&Transform::ApplyAxisRotation)
-    ;
-#if(OST_INFO_ENABLED)
-  def("TransformToInfo", &TransformToInfo);
-  def("TransformFromInfo", &TransformFromInfo);
-#endif
-  
+  export_Transform();
 }
diff --git a/modules/mol/base/src/CMakeLists.txt b/modules/mol/base/src/CMakeLists.txt
index 134eb4e25691507a50039077bdf58099b57ae9ea..7c92f9f45ca67bef9452a829ef6e6de6e933c5ff 100644
--- a/modules/mol/base/src/CMakeLists.txt
+++ b/modules/mol/base/src/CMakeLists.txt
@@ -109,4 +109,4 @@ endif()
 module(NAME mol SOURCES ${OST_MOL_SOURCES}
        HEADERS ${OST_MOL_IMPL_HEADERS} IN_DIR impl
        ${OST_MOL_HEADERS} HEADER_OUTPUT_DIR ost/mol
-       DEPENDS_ON ost_geom ost_base ${INFO_DEPS})
+       DEPENDS_ON ost_geom ost_base ${INFO_DEPS} LINK ${LINK})
diff --git a/modules/mol/base/src/atom_view.cc b/modules/mol/base/src/atom_view.cc
index 2d81e4aec04be48a8310209fc05250139e71709e..ed16ac0f82f314a452cddbc8b35fd8fe5842b2ab 100644
--- a/modules/mol/base/src/atom_view.cc
+++ b/modules/mol/base/src/atom_view.cc
@@ -120,9 +120,9 @@ mol::AtomViewList AtomView::GetBondPartners() const
   mol::BondHandleList::const_iterator i;
   for (i=data_->bonds.begin();i!=data_->bonds.end();++i) {
     if (i->GetFirst().GetHandle()!=this->GetHandle()) {
-      avl.push_back(this->GetEntity().FindAtom(i->GetFirst()));
+      avl.push_back(this->GetEntity().ViewForHandle(i->GetFirst()));
     } else {
-      avl.push_back(this->GetEntity().FindAtom(i->GetSecond()));
+      avl.push_back(this->GetEntity().ViewForHandle(i->GetSecond()));
     }
   }
   return avl;
@@ -138,9 +138,9 @@ void AtomView::RemoveBonds()
     BondHandle b=*i;
     AtomView av;
     if (b.GetFirst()==this->GetHandle()) {
-      av=ent.FindAtom(b.GetSecond());
+      av=ent.ViewForHandle(b.GetSecond());
     } else {
-      av=ent.FindAtom(b.GetFirst());
+      av=ent.ViewForHandle(b.GetFirst());
     }
     ent.RemoveBond(b);
   }
diff --git a/modules/mol/base/src/chain_type.cc b/modules/mol/base/src/chain_type.cc
index 6b3841d8909e4378db492db306efe86ece0bba44..2c6c091b9b9cb37608c8a067175ae64eb7961e4b 100644
--- a/modules/mol/base/src/chain_type.cc
+++ b/modules/mol/base/src/chain_type.cc
@@ -17,7 +17,7 @@
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 //------------------------------------------------------------------------------
 
-#include <stdexcept>
+#include <ost/message.hh>
 #include "chain_type.hh"
 
 namespace ost { namespace mol {
@@ -52,7 +52,7 @@ ChainType ChainTypeFromString(StringRef identifier)
       return CHAINTYPE_UNKNOWN;
   }
 
-  throw std::runtime_error("Unrecognised chain type descriptor found: '" +
+  throw Error("Unrecognised chain type descriptor found: '" +
                            identifier.str() +"'!");
 }
 
@@ -92,7 +92,7 @@ String StringFromChainType(ChainType type)
 
   std::stringstream ss("Unknonw ChainType item found: '");
   ss << type << "'!";
-  throw std::runtime_error(ss.str());
+  throw Error(ss.str());
 }
 
 }} //ns
diff --git a/modules/mol/base/src/chain_type.hh b/modules/mol/base/src/chain_type.hh
index 18a00fb457cd4f49ba261aab3f2f74c11cb91508..513cb1d51b3c295376d4b7094844b58967091336 100644
--- a/modules/mol/base/src/chain_type.hh
+++ b/modules/mol/base/src/chain_type.hh
@@ -22,6 +22,8 @@
 #include <ost/base.hh>
 #include <ost/string_ref.hh>
 
+#include "module_config.hh"
+
 namespace ost { namespace mol {
 
 /// \enum different kinds of chains
@@ -45,24 +47,24 @@ typedef enum {
 /// \param identifier StringRef to be translated
 ///
 /// \return The ChainType corresponding to the input, throws a
-///         std::runtime_error on unknown type
-ChainType ChainTypeFromString(const StringRef identifier);
+///         ost:Error on unknown type
+ChainType DLLEXPORT_OST_MOL ChainTypeFromString(const StringRef identifier);
 
 /// \brief Create a ChainType item for a given string
 ///
 /// \param identifier String to be translated
 ///
 /// \return The ChainType corresponding to the input, throws a
-///         std::runtime_error on unknown type
-ChainType ChainTypeFromString(const String& identifier);
+///         ost::Error on unknown type
+ChainType DLLEXPORT_OST_MOL ChainTypeFromString(const String& identifier);
 
 /// \brief Return the String identifier for a given type
 ///
 /// \param type ChainType to be translated
 ///
-/// \return String corresponding to the input, throws a std::runtime_error on
+/// \return String corresponding to the input, throws a ost::Error on
 ///         unknown type
-String StringFromChainType(ChainType type);
+String DLLEXPORT_OST_MOL StringFromChainType(ChainType type);
 
 }} //ns
 
diff --git a/modules/mol/base/src/chain_view.cc b/modules/mol/base/src/chain_view.cc
index 4727e31ddce6764bcdfc0e78bb5e7c3c31e0d83f..355bd6cf5963f68a3a42fdf587c7ec60f2ed9c80 100644
--- a/modules/mol/base/src/chain_view.cc
+++ b/modules/mol/base/src/chain_view.cc
@@ -18,8 +18,8 @@
 //------------------------------------------------------------------------------
 #include <algorithm>
 #include <limits>
-
 #include <boost/bind.hpp>
+#include <ost/log.hh>
 #include <ost/mol/bond_handle.hh>
 #include <ost/mol/residue_handle.hh>
 #include <ost/mol/chain_view.hh>
@@ -176,7 +176,13 @@ ResidueView ChainView::FindResidue(const ResNum& number) const {
   }
 }
 
-ResidueView ChainView::FindResidue(const ResidueHandle& handle) const {
+ResidueView ChainView::FindResidue(const ResidueHandle& residue) const {
+  LOG_WARNING("ChainView::FindResidue(handle) is deprecated. "
+              "Use ChainView::ViewForHandle instead.");
+  return this->ViewForHandle(residue);
+}
+
+ResidueView ChainView::ViewForHandle(const ResidueHandle& handle) const {
   this->CheckValidity();  
   const ResidueViewList& l=data_->residues;
   ResidueViewList::const_iterator i;
@@ -187,7 +193,7 @@ ResidueView ChainView::FindResidue(const ResidueHandle& handle) const {
 
 bool ChainView::IsResidueIncluded(const ResidueHandle& handle) const {
   this->CheckValidity();  
-  return this->FindResidue(handle).IsValid();
+  return this->ViewForHandle(handle).IsValid();
 }
 
 ResidueView ChainView::AddResidue(const ResidueHandle& residue_handle, 
@@ -195,7 +201,7 @@ ResidueView ChainView::AddResidue(const ResidueHandle& residue_handle,
   this->CheckValidity();                                    
   ResidueView rv;
   if ((flags & ViewAddFlag::CHECK_DUPLICATES) && 
-      (rv=this->FindResidue(residue_handle)))
+      (rv=this->ViewForHandle(residue_handle)))
     return rv;
   rv=ResidueView(*this, residue_handle);
   if (!data_->residues.empty()) {
@@ -213,12 +219,18 @@ ResidueView ChainView::AddResidue(const ResidueHandle& residue_handle,
 }
 
 AtomView ChainView::FindAtom(const AtomHandle& atom) const {
+  LOG_WARNING("ChainView::FindAtom(handle) is deprecated. "
+              "Use ChainView::ViewForHandle instead.");
+  return this->ViewForHandle(atom);
+}
+
+AtomView ChainView::ViewForHandle(const AtomHandle& atom) const {
   ResidueHandle residue=atom.GetResidue();
   if (atom.GetEntity()!=this->GetEntity().GetHandle())
     return AtomView();
 
   ResidueView v=this->FindResidue(residue.GetNumber());
-  return v.IsValid() ? v.FindAtom(atom) : AtomView();
+  return v.IsValid() ? v.ViewForHandle(atom) : AtomView();
 }
 
 AtomView ChainView::AddAtom(const AtomHandle& atom_handle, 
@@ -262,7 +274,7 @@ ResidueView ChainView::AddResidue(const ResidueView& residue_view,
   this->CheckValidity();
   ResidueView rv;
   if ((flags & ViewAddFlag::CHECK_DUPLICATES) && 
-      (rv=this->FindResidue(residue_view.GetHandle()))) {
+      (rv=this->ViewForHandle(residue_view.GetHandle()))) {
     if (!(flags & ViewAddFlag::INCLUDE_ATOMS)) {
       return rv;
     }
diff --git a/modules/mol/base/src/chain_view.hh b/modules/mol/base/src/chain_view.hh
index 72ed7a72e47877f485931994c2d4f501bc95a925..70bd305aa1c17884f062a2b0721c97cb1cea7340 100644
--- a/modules/mol/base/src/chain_view.hh
+++ b/modules/mol/base/src/chain_view.hh
@@ -125,12 +125,15 @@ public:
   ResidueView FindResidue(const ResNum& number) const;
     
   /// \brief Find view for given atom handle
-  AtomView FindAtom(const AtomHandle& atom) const;  
+  /// Deprecated: Use ViewForHandle instead
+  AtomView FindAtom(const AtomHandle& atom) const;
   
+  AtomView ViewForHandle(const AtomHandle& atom) const;
   AtomView FindAtom(const ResNum& num, const String& name) const;
   /// \brief Find residue by residue handle
-  ResidueView FindResidue(const ResidueHandle& handle) const;
+  ResidueView ViewForHandle(const ResidueHandle& handle) const;
   
+  ResidueView FindResidue(const ResidueHandle& handle) const;
   /// \brief Check whether the view includes the given residue.
   bool IsResidueIncluded(const ResidueHandle& handle) const;
   
diff --git a/modules/mol/base/src/coord_frame.cc b/modules/mol/base/src/coord_frame.cc
index 1c30611b3b82a75ffd6660c6980183a0a94e5663..52907d7f771aea5aa1e980cc11e6ba1546d7ae1c 100644
--- a/modules/mol/base/src/coord_frame.cc
+++ b/modules/mol/base/src/coord_frame.cc
@@ -39,13 +39,12 @@ namespace ost { namespace mol {
     */
     Real Eval2AngleDist(Real phi, Real phi0, Real psi, Real psi0, Real delta)
     {
-      Real d1,d2,d;
-      d1=abs(phi-phi0);
-      d2=abs(psi-psi0);
-      if (d1>M_PI) d1=abs(d1-2.*M_PI);
-      if (d2>M_PI) d1=abs(d2-2.*M_PI);
-      d=(pow(d1,2.)+pow(d2,2.))/pow(delta,2.);
-      return 1./(1+d);
+      Real d1=std::abs(phi-phi0);
+      Real d2=std::abs(psi-psi0);
+      if (d1>M_PI) d1=std::abs(d1-2.*M_PI);
+      if (d2>M_PI) d1=std::abs(d2-2.*M_PI);
+      Real d=(d1*d1+d2*d2)/(delta*delta);
+      return 1.0/(1.0+d);
     }
   }
 
@@ -138,7 +137,7 @@ namespace ost { namespace mol {
       val=geom::Length2(av_ref-av_sele);
       rmsd+=val;
     }
-    return pow(rmsd/indices_sele.size(),0.5);
+    return sqrt(rmsd/indices_sele.size());
   }
   
   Real CoordFrame::GetRMSD(const EntityView& reference_view,const EntityView& sele_view) const
@@ -146,7 +145,7 @@ namespace ost { namespace mol {
     int count_ref=reference_view.GetAtomCount();
     int count_sele=sele_view.GetAtomCount();
     if (count_ref!=count_sele){
-      throw std::runtime_error("atom counts of the two views are not equal");
+      throw Error("atom counts of the two views are not equal");
     }
     std::vector<unsigned long> indices_sele;
     std::vector<geom::Vec3> ref_pos;
@@ -286,10 +285,10 @@ namespace ost { namespace mol {
     dist.reserve(n_atoms-2);
     dist2.reserve(n_atoms-2);
     if (n_atoms!=indices_n.size()||n_atoms!=indices_c.size()||n_atoms!=indices_o.size()){
-      throw std::runtime_error("not same numbers of CA, C, O and N atoms in the selection");
+      throw Error("not same numbers of CA, C, O and N atoms in the selection");
     }
     if (n_atoms<=5){
-      throw std::runtime_error("At least five residues are needed to calulate an alpha helix similarity");
+      throw Error("At least five residues are needed to calulate an alpha helix similarity");
     }
     c=(*this)[indices_c[0]];
     n_next=(*this)[indices_n[1]];
@@ -303,8 +302,10 @@ namespace ost { namespace mol {
       psi=geom::DihedralAngle(n,ca,c,n_next);
       score.push_back(Eval2AngleDist(phi,phi_0,psi,psi_0,delta));
     }
-    score2[0]=pow(score[0]*score[1],3./2.);
-    score2[n_atoms-3]=pow(score[n_atoms-3]*score[n_atoms-4],3./2.);
+    score2[0]=sqrt(score[0]*score[1]*score[0]*score[1]*score[0]*score[1]);
+    score2[n_atoms-3]=sqrt(score[n_atoms-3]*score[n_atoms-4]*
+                           score[n_atoms-3]*score[n_atoms-4]*
+                           score[n_atoms-3]*score[n_atoms-4]);
     for (unsigned long i=1; i!=n_atoms-3; ++i) {
       score2[i]=score[i-1]*score[i]*score[i+1];
     }
@@ -357,7 +358,7 @@ namespace ost { namespace mol {
     indices_ca.reserve(residues.size());
     //for (ResidueViewList::const_iterator res=residues.begin()+1,
     //     e=residues.end(); res!=e-1; ++res){
-    //  if (!InSequence((*res).GetHandle(),(*(res+1)).GetHandle())) throw std::runtime_error("Residues are not in a continuous sequence");
+    //  if (!InSequence((*res).GetHandle(),(*(res+1)).GetHandle())) throw Error("Residues are not in a continuous sequence");
     //}
     for (ResidueViewList::const_iterator res=residues.begin(),
          e=residues.end(); res!=e; ++res) {
@@ -377,7 +378,7 @@ namespace ost { namespace mol {
     indices_o.reserve(residues.size());
     for (ResidueViewList::const_iterator res=residues.begin()+1,
          e=residues.end(); res!=e-1; ++res){
-      if (!InSequence((*res).GetHandle(),(*(res+1)).GetHandle())) throw std::runtime_error("Residues are not in a continuous sequence");
+      if (!InSequence((*res).GetHandle(),(*(res+1)).GetHandle())) throw Error("Residues are not in a continuous sequence");
     }
     for (ResidueViewList::const_iterator res=residues.begin(),
          e=residues.end(); res!=e; ++res) {
diff --git a/modules/mol/base/src/coord_frame.hh b/modules/mol/base/src/coord_frame.hh
index ad76a5dc869d281775ca61fe0ce191fc6a4d8757..b7cce0661ef615db5799e0dfe287d0d0187cb74c 100644
--- a/modules/mol/base/src/coord_frame.hh
+++ b/modules/mol/base/src/coord_frame.hh
@@ -216,31 +216,31 @@ public:
     This function returns a vector containing the atom indices of the atoms in an EntityView;
     it is used to accelerate the extraction of information from a trajectory
   */
-  void GetIndices(const EntityView& sele, std::vector<unsigned long>& indices);
+  DLLEXPORT_OST_MOL void GetIndices(const EntityView& sele, std::vector<unsigned long>& indices);
 
   /*!
     This function returns a vector containing the atom masses of the atoms in an EntityView;
     it is used together with GetIndices to accelerate the extraction of RMSD from a trajectory
   */
-  void GetMasses(const EntityView& sele, std::vector<Real>& masses);
+  DLLEXPORT_OST_MOL void GetMasses(const EntityView& sele, std::vector<Real>& masses);
 
   //! conveniece for GetIndices and GetMasses in one call
-  void GetIndicesAndMasses(const EntityView& sele,
-                           std::vector<unsigned long>& indices,
-                           std::vector<Real>& masses);
+  DLLEXPORT_OST_MOL void GetIndicesAndMasses(const EntityView& sele,
+                                             std::vector<unsigned long>& indices,
+                                             std::vector<Real>& masses);
 
   //! Writes the positions of all atoms in the EntityView into the provided vec3 list
-  void GetPositions(const EntityView& sele, std::vector<geom::Vec3>& ref_pos);
-
+  DLLEXPORT_OST_MOL void GetPositions(const EntityView& sele, std::vector<geom::Vec3>& ref_pos);
+  
   //! Writes the indices of all atoms in the EntityView into the provided list
-  void GetCaIndices(const EntityView& segment, std::vector<unsigned long>& indices_ca);
-
+  DLLEXPORT_OST_MOL void GetCaIndices(const EntityView& segment, std::vector<unsigned long>& indices_ca);
+  
   //! Writes the backbone indices of all residues in the EntityView into the provided list
-  void GetCaCONIndices(const EntityView& segment, 
-                       std::vector<unsigned long>& indices_ca, 
-                       std::vector<unsigned long>& indices_c,
-                       std::vector<unsigned long>& indices_o, 
-                       std::vector<unsigned long>& indices_n);
+  DLLEXPORT_OST_MOL void GetCaCONIndices(const EntityView& segment, 
+                                         std::vector<unsigned long>& indices_ca, 
+                                         std::vector<unsigned long>& indices_c,
+                                         std::vector<unsigned long>& indices_o, 
+                                         std::vector<unsigned long>& indices_n);
 
 
 }}
diff --git a/modules/mol/base/src/coord_group.cc b/modules/mol/base/src/coord_group.cc
index db3fd341ce04a76c6e928ca1e0fd93e869b583c7..4fe6677ee7da3981ee2bc3f9b48f2c26599820e4 100644
--- a/modules/mol/base/src/coord_group.cc
+++ b/modules/mol/base/src/coord_group.cc
@@ -66,6 +66,30 @@ uint CoordGroupHandle::GetFrameCount() const
   return source_->GetFrameCount();
 }
 
+float CoordGroupHandle::GetDelta() const
+{
+  this->CheckValidity();  
+  return source_->GetFrameDelta();
+}
+
+void CoordGroupHandle::SetDelta(float d)
+{
+  this->CheckValidity();  
+  source_->SetFrameDelta(d);
+}
+
+float CoordGroupHandle::GetStartTime() const
+{
+  this->CheckValidity();  
+  return source_->GetStartTime();
+}
+
+void CoordGroupHandle::SetStartTime(float t)
+{
+  this->CheckValidity();  
+  source_->SetStartTime(t);
+}
+
 void CoordGroupHandle::SetFramePositions(uint frame, 
                                          const std::vector<geom::Vec3>& clist)
 {
@@ -230,6 +254,15 @@ CoordGroupHandle CoordGroupHandle::Filter(const EntityView& selected, int first,
   }
   return filtered_cg;
 }
- 
+
+void CoordGroupHandle::ApplyTransform(const mol::Transform& tf)
+{
+  this->CheckValidity();
+  if (source_->IsMutable()) {
+    source_->ApplyTransform(tf);
+  } else {
+    throw IntegrityError("Cannot apply transform, CoordGroup is immutable");
+  }  
+} 
   
 }} // ns
diff --git a/modules/mol/base/src/coord_group.hh b/modules/mol/base/src/coord_group.hh
index 652fe34636d3dc11c7fa5168c83c05d906b6524a..74fffcb6c45d47f2e0f0e3c469e5174a07a31cab 100644
--- a/modules/mol/base/src/coord_group.hh
+++ b/modules/mol/base/src/coord_group.hh
@@ -30,11 +30,15 @@
 
 namespace ost { namespace mol {
 
+class Transform;
+
 /// \brief coordinate group, for trajectories and such
 class DLLEXPORT_OST_MOL CoordGroupHandle {
 public:
   /// \brief create empty, invalid handle
   CoordGroupHandle();
+  /// \brief used internally
+  CoordGroupHandle(CoordSourcePtr source);
 
   /// \brief return trajectories entity handle
   EntityHandle GetEntity() const;
@@ -48,6 +52,18 @@ public:
   /// \brief number of frames
   uint GetFrameCount() const;
 
+  /// \brief time in ps between frames, default 0.0
+  float GetDelta() const;
+
+  /// \brief set time between each frame in ps
+  void SetDelta(float d);
+
+  /// \brief start time in ps, default 0.0
+  float GetStartTime() const;
+
+  /// \rbrief set start time in ps
+  void SetStartTime(float t);
+
   /// \brief assign positions to the given frame - order and count must match 
   ///      initial atomlist
   void SetFramePositions(uint frame, const std::vector<geom::Vec3>& clist);
@@ -91,8 +107,9 @@ public:
   /// \brief return a filtered coord group, containing only the atoms in the 
   ///     view
   CoordGroupHandle Filter(const EntityView& selected,int first=0,int last=-1) const;
-  
-  CoordGroupHandle(CoordSourcePtr source);
+
+  /// \brief apply in-place transform to each coordinate in each frame
+  void ApplyTransform(const Transform& tf);
 
 
 private:
diff --git a/modules/mol/base/src/coord_source.cc b/modules/mol/base/src/coord_source.cc
index 5f0e42a633334acc768b9796399ab002fdad6599..06b7864b7a831fa2fe8d0e144765b6bff2094b9e 100644
--- a/modules/mol/base/src/coord_source.cc
+++ b/modules/mol/base/src/coord_source.cc
@@ -21,13 +21,12 @@
   Author: Marco Biasini
  */
 #include <ost/log.hh>
-#include <ost/mol/atom_handle.hh>
-#include <ost/mol/xcs_editor.hh>
-#include <ost/mol/in_mem_coord_source.hh>
-
+#include "atom_handle.hh"
+#include "xcs_editor.hh"
+#include "in_mem_coord_source.hh"
+#include "transform.hh"
 #include "coord_source.hh"
 
-
 namespace ost { namespace mol {
   
 
@@ -35,7 +34,9 @@ CoordSource::CoordSource(const AtomHandleList& atoms):
   atoms_(atoms), 
   entity_(),
   mutable_(false),
-  atom_dict_()
+  atom_dict_(),
+  delta_(1.0),
+  start_time_(0.0)
 {
   if (!atoms_.empty()) {
     entity_=atoms_.front().GetEntity();
@@ -45,12 +46,6 @@ CoordSource::CoordSource(const AtomHandleList& atoms):
   }
 }
 
-  
-CoordSource::~CoordSource()
-{
-  
-}
-
 void CoordSource::CopyFrame(uint frame_id)
 {
   if (atoms_.empty()) {
@@ -170,4 +165,16 @@ geom::Vec3 CoordSource::GetAtomPos(uint frame, AtomHandle atom) const
   return geom::Vec3();
 }
 
+void CoordSource::ApplyTransform(const Transform& tf)
+{
+  if(!mutable_) return;
+  size_t frame_count=GetFrameCount();
+  for(size_t n=0;n<frame_count;++n) {
+    CoordFramePtr cfp=GetFrame(n);
+    for(CoordFrame::iterator it=cfp->begin();it!=cfp->end();++it) {
+      *it=tf.Apply(*it);
+    }
+  }
+}
+
 }} // ns
diff --git a/modules/mol/base/src/coord_source.hh b/modules/mol/base/src/coord_source.hh
index fec0d9946cb2ecd275abb23d5ebb58b080422734..a33162abc4e14a95a94e1414aa90401cb47bd0af 100644
--- a/modules/mol/base/src/coord_source.hh
+++ b/modules/mol/base/src/coord_source.hh
@@ -31,6 +31,7 @@
 namespace ost { namespace mol {
 
 class CoordSource;
+class Transform;
 
 typedef boost::shared_ptr<CoordSource> CoordSourcePtr;
 
@@ -43,14 +44,22 @@ class DLLEXPORT_OST_MOL CoordSource {
 public:
   CoordSource(const AtomHandleList& atoms);
   
-  virtual ~CoordSource();
+  virtual ~CoordSource() {}
   
+  virtual uint GetFrameCount() const =0;
+
+  virtual CoordFramePtr GetFrame(uint frame_id) const = 0;
+ 
   CoordSourcePtr Extract(int start=0, int stop=-1, int step=1);
   
-  virtual uint GetFrameCount()=0;
+  // time in ps between frames
+  float GetFrameDelta() const {return delta_;}
+  void SetFrameDelta(float d) {delta_=d;}
+
+  // start time in ps
+  float GetStartTime() const {return start_time_;}
+  void SetStartTime(float t) {start_time_=t;}
   
-  virtual CoordFramePtr GetFrame(uint frame_id) const = 0;
- 
   int GetAtomCount() const;
   
   EntityHandle GetEntity() const;
@@ -72,6 +81,9 @@ public:
   virtual void AddFrame(const std::vector<geom::Vec3>& coords) = 0;
   virtual void AddFrame(const std::vector<geom::Vec3>& coords,const geom::Vec3& cell_size,const geom::Vec3& cell_angles) = 0;
   virtual void InsertFrame(int pos, const std::vector<geom::Vec3>& coords) = 0;
+
+  void ApplyTransform(const Transform& tf);
+
 protected:
   void SetMutable(bool flag);
 private:
@@ -79,6 +91,7 @@ private:
   EntityHandle   entity_;
   bool           mutable_;
   std::map<long,uint> atom_dict_;
+  float delta_,start_time_;
 };
 
 }}
diff --git a/modules/mol/base/src/entity_view.cc b/modules/mol/base/src/entity_view.cc
index a88f0b39553a438c0d51359fee91cacf9d85a7a1..d81940ee1bfc89228a9db78163ac410b95a96738 100644
--- a/modules/mol/base/src/entity_view.cc
+++ b/modules/mol/base/src/entity_view.cc
@@ -1,4 +1,5 @@
 //------------------------------------------------------------------------------
+//
 // This file is part of the OpenStructure project <www.openstructure.org>
 //
 // Copyright (C) 2008-2011 by the OpenStructure authors
@@ -207,7 +208,7 @@ ChainView EntityView::AddChain(const ChainHandle& chain_handle,
   this->CheckValidity();
   ChainView cv;
   if (flags & ViewAddFlag::CHECK_DUPLICATES &&
-      (cv=this->FindChain(chain_handle)))
+      (cv=this->ViewForHandle(chain_handle)))
     return cv;
   cv=ChainView(*this, chain_handle);
   data_->chains.push_back(cv);
@@ -256,14 +257,14 @@ ChainView EntityView::FindChain(const String& chain_name) const{
 }
 
 
-ResidueView EntityView::FindResidue(const ResidueHandle& residue) const {
+ResidueView EntityView::ViewForHandle(const ResidueHandle& residue) const {
   ChainHandle chain=residue.GetChain();
-  ChainView v=this->FindChain(chain);
-  return v.IsValid() ? v.FindResidue(residue) : ResidueView();
+  ChainView v=this->ViewForHandle(chain);
+  return v.IsValid() ? v.ViewForHandle(residue) : ResidueView();
 }
 
 
-AtomView EntityView::FindAtom(const AtomHandle& atom) const 
+AtomView EntityView::ViewForHandle(const AtomHandle& atom) const
 {
   this->CheckValidity();
   return data_->ViewForHandle(atom);
@@ -409,7 +410,7 @@ EntityView EntityView::Select(const Query& query, QueryFlags flags) const
   return view;
 }
 
-ChainView EntityView::FindChain(const ChainHandle& chain) const {
+ChainView EntityView::ViewForHandle(const ChainHandle& chain) const {
   this->CheckValidity();
   ChainViewList::const_iterator i;
   i=std::find_if(data_->chains.begin(), data_->chains.end(),
@@ -421,7 +422,7 @@ ChainView EntityView::FindChain(const ChainHandle& chain) const {
 bool EntityView::IsChainIncluded(const ChainHandle& chain) const 
 {
   this->CheckValidity();
-  return this->FindChain(chain).IsValid();
+  return this->ViewForHandle(chain).IsValid();
 }
 
 
@@ -584,7 +585,7 @@ ChainView EntityView::AddChain(const ChainView& chain_view,
   this->CheckValidity();
   ChainView cv;
   if (flags & ViewAddFlag::CHECK_DUPLICATES &&
-     (cv=this->FindChain(chain_view.GetHandle()))) {
+     (cv=this->ViewForHandle(chain_view.GetHandle()))) {
     if (!(flags & ViewAddFlag::INCLUDE_RESIDUES)) {
       return cv;
     }
@@ -627,7 +628,7 @@ AtomViewList EntityView::FindWithin(const geom::Vec3& center, Real radius) const
   AtomHandleList ahl=this->GetHandle().FindWithin(center, radius);
   AtomViewList avl;
   for (AtomHandleList::iterator i=ahl.begin(), e=ahl.end(); i!=e; ++i) {
-    if (AtomView v=this->FindAtom(*i)) {
+    if (AtomView v=this->ViewForHandle(*i)) {
       avl.push_back(v);
     }
   }
@@ -721,7 +722,7 @@ AtomView EntityView::AddXAtom(const AtomHandle& ah, ViewAddFlags flags)
 }
 AtomView EntityView::FindXAtom(const AtomHandle& ah)
 {
-  return this->FindAtom(ah);
+  return this->ViewForHandle(ah);
 }
 #endif
 
@@ -737,6 +738,18 @@ AtomView EntityView::FindAtom(const String& chain_name,
   }
   return AtomView();
 }
+
+ResidueView EntityView::FindResidue(const String& chain,
+                                    const ResNum& num) const
+{
+  this->CheckValidity();
+  ChainView ch=this->FindChain(chain);
+  if (ch.IsValid()) {
+    return ch.FindResidue(num);
+ }
+  return ResidueView();
+}
+
 geom::AlignedCuboid EntityView::GetBounds() const
 {
   this->CheckValidity();
@@ -878,5 +891,26 @@ String EntityView::Dump() const
   return stream.str();
 }
 
+ChainView EntityView::FindChain(const ChainHandle& chain) const
+{
+  LOG_WARNING("EntityView::FindChain is deprecated. "
+              "Use EntityView::ViewForHandle instead");
+  return this->ViewForHandle(chain);
+}
+
+ResidueView EntityView::FindResidue(const ResidueHandle& residue) const
+{
+  LOG_WARNING("EntityView::FindResidue is deprecated. "
+              "Use EntityView::ViewForHandle instead");
+  return this->ViewForHandle(residue);
+}
+
+AtomView EntityView::FindAtom(const AtomHandle& atom) const
+{
+  LOG_WARNING("EntityView::FindAtom(handle) is deprecated. "
+              "Use EntityView::ViewForHandle instead");
+  return this->ViewForHandle(atom);
+}
+
 }} // ns
 
diff --git a/modules/mol/base/src/entity_view.hh b/modules/mol/base/src/entity_view.hh
index 6e5b2371695064033bfa4637d7a5e533e6c9957b..56136733b06abfca2abc5bf12c3f299f6de9e002 100644
--- a/modules/mol/base/src/entity_view.hh
+++ b/modules/mol/base/src/entity_view.hh
@@ -221,16 +221,39 @@ public:
   ChainView FindChain(const String& chain_name) const;
 
   /// \brief Find atom for given residue handle
+  ///
+  /// deprecated. Use ViewForHandle instead
   ResidueView FindResidue(const ResidueHandle& residue) const;
 
+  ResidueView FindResidue(const String& chain, const ResNum& num) const;
+
+  /// \brief locate residue view for given residue handle
+  ///
+  /// returns an invalid ResidueView if the residue could not be
+  /// located in the structure
+  ResidueView ViewForHandle(const ResidueHandle& residue) const;
   /// \brief Find view for given atom handle
+  ///
+  /// deprecated. Use ViewForHandle instead
   AtomView FindAtom(const AtomHandle& atom) const;
+  AtomView ViewForHandle(const AtomHandle& atom) const;
 
+  /// \brief locate atom view for given atom handle
+  ///
+  /// returns an invalid AtomView if the residue could not be
+  /// located in the structure
   AtomView FindAtom(const String& chain_name, const ResNum& num,
                     const String& atom_name) const;
   /// \brief Find chain for given chain handle
-  ChainView FindChain(const ChainHandle& chain) const;
+  ///
+  /// deprecated: Use ViewForHandle instead
 
+  ChainView FindChain(const ChainHandle& chain) const;
+  /// \brief locate chain view for given chain handle
+  ///
+  /// returns an invalid AtomView if the residue could not be
+  /// located in the structure
+  ChainView ViewForHandle(const ChainHandle& chain) const;
   /// \brief  Check whether the view includes the given chain
   /// \return True, if the chain is included in the view, false if not.
   bool IsChainIncluded(const ChainHandle& chain) const;
diff --git a/modules/mol/base/src/in_mem_coord_source.cc b/modules/mol/base/src/in_mem_coord_source.cc
index ea01db894a69efa04189e126b3f2d6429df46f12..a8d985c25acd30213949ad9139b2dc3e7048cd70 100644
--- a/modules/mol/base/src/in_mem_coord_source.cc
+++ b/modules/mol/base/src/in_mem_coord_source.cc
@@ -9,7 +9,7 @@ InMemCoordSource::InMemCoordSource(const AtomHandleList& atoms):
   this->SetMutable(true);
 }
   
-uint InMemCoordSource::GetFrameCount()
+uint InMemCoordSource::GetFrameCount() const
 {
   return frames_.size();
 }
diff --git a/modules/mol/base/src/in_mem_coord_source.hh b/modules/mol/base/src/in_mem_coord_source.hh
index 0984791aae634bcf315efe08f55f10850ef77c5f..6b6d15f6a22c804fdbe901358817f59093f83f47 100644
--- a/modules/mol/base/src/in_mem_coord_source.hh
+++ b/modules/mol/base/src/in_mem_coord_source.hh
@@ -38,7 +38,7 @@ class DLLEXPORT_OST_MOL InMemCoordSource : public CoordSource {
 public:
   InMemCoordSource(const AtomHandleList& atoms);
   
-  virtual uint GetFrameCount();
+  virtual uint GetFrameCount() const;
   
   virtual CoordFramePtr GetFrame(uint frame_id) const;
   
diff --git a/modules/mol/base/src/not_connected_error.hh b/modules/mol/base/src/not_connected_error.hh
index cce9f1b4f8b6bf6d227716b048cf0ecd0217f9a9..ac736c74e4eff141c20a3345fd05ac9e0c31e948 100644
--- a/modules/mol/base/src/not_connected_error.hh
+++ b/modules/mol/base/src/not_connected_error.hh
@@ -26,7 +26,7 @@ namespace ost { namespace mol {
   
 /// \brief Error to indicate that two atoms that are supposed to be connected
 ///        are not.
-class DLLEXPORT_OST_MOL NotConnectedError : public Error {
+class DLLEXPORT NotConnectedError : public Error {
 public:
   NotConnectedError(AtomHandle one, AtomHandle two);
   virtual ~NotConnectedError() throw() {}
diff --git a/modules/mol/base/src/property_id.hh b/modules/mol/base/src/property_id.hh
index 3632f996ac468a9891139a69a107d87aa2f8d711..981b747cfe500b8b7f41c8b294036527a29522d3 100644
--- a/modules/mol/base/src/property_id.hh
+++ b/modules/mol/base/src/property_id.hh
@@ -87,15 +87,13 @@ Prop::ID DLLEXPORT_OST_MOL PropertyIDFromString(const String& prop);
 Prop DLLEXPORT_OST_MOL PropertyFromString(const String& prop);
 
 
-struct DLLEXPORT PropertyError: public std::exception
+struct DLLEXPORT PropertyError: public ost::Error
 {
   PropertyError(ost::mol::Prop::ID prop):
+    ost::Error("invalid property"),
     prop_(prop)
   {}
   virtual ~PropertyError() throw() {}
-  virtual const char* what() const throw() {
-    return "invalid property";
-  }
   
   ost::mol::Prop::ID Prop() const 
   {
diff --git a/modules/mol/base/src/query_error.cc b/modules/mol/base/src/query_error.cc
index 1cdce0fe205b6ed04a0aa4d4fa3a5d42cca8f638..34bb3b83c919e7b3fcea9fd54019b908de88b27e 100644
--- a/modules/mol/base/src/query_error.cc
+++ b/modules/mol/base/src/query_error.cc
@@ -39,7 +39,7 @@ String QueryError::GetFormattedMessage() const throw() {
 
 QueryError::QueryError(const String& query, 
                        const QueryErrorDesc& desc) throw()
-  : query_(query),desc_(desc) { 
+  : ost::Error(""),query_(query),desc_(desc) {
 }
   
 QueryError::~QueryError() throw() { 
diff --git a/modules/mol/base/src/query_error.hh b/modules/mol/base/src/query_error.hh
index 4d2fe8639fb8a63ba2431a8db406d98e44f03d9e..84d0164997afe8a3e4d9365ef8c75b8cef064d8b 100644
--- a/modules/mol/base/src/query_error.hh
+++ b/modules/mol/base/src/query_error.hh
@@ -19,6 +19,7 @@
 #ifndef OST_QUERY_ERROR_HH
 #define OST_QUERY_ERROR_HH
 
+#include <ost/message.hh>
 #include <ost/range.hh>
 #include <ost/mol/module_config.hh>
 
@@ -35,7 +36,7 @@ struct DLLEXPORT_OST_MOL QueryErrorDesc {
   Range       range;
 };
 
-class DLLEXPORT_OST_MOL QueryError : public std::exception {
+class DLLEXPORT_OST_MOL QueryError : public ost::Error {
 public:
   QueryError(const String& query, const QueryErrorDesc& desc) throw();    
 
diff --git a/modules/mol/base/src/residue_prop.hh b/modules/mol/base/src/residue_prop.hh
index e86eef5f11b16ba4eed55153e0cb38901faedd1e..4a411cca6e27250fdd23d4b538ffea6064b8d106 100644
--- a/modules/mol/base/src/residue_prop.hh
+++ b/modules/mol/base/src/residue_prop.hh
@@ -34,6 +34,12 @@ class DLLEXPORT ResNum: private
     boost::unit_steppable<ResNum> > > > >
 {
 public:
+ 
+  // needed to wrap certain map classes
+  ResNum():
+    num_(1),alt_('\0')	 
+  {}  
+
   ResNum(int n):
     num_(n), alt_('\0')
   { }
diff --git a/modules/mol/base/src/residue_view.cc b/modules/mol/base/src/residue_view.cc
index 4bd75ba32e1701750d89a28a04ab9169c5ce9dc2..406854a1f0f077c61080c320320e82577765e625 100644
--- a/modules/mol/base/src/residue_view.cc
+++ b/modules/mol/base/src/residue_view.cc
@@ -20,7 +20,7 @@
 #include <limits>
 
 #include <boost/bind.hpp>
-
+#include <ost/log.hh>
 #include <ost/mol/bond_handle.hh>
 #include <ost/mol/chain_view.hh>
 #include <ost/mol/atom_view.hh>
@@ -96,7 +96,7 @@ AtomView ResidueView::AddAtom(const AtomHandle& atom_handle,
   this->CheckValidity();
   AtomView v;
   if ((flags & ViewAddFlag::CHECK_DUPLICATES) &&
-      (v=this->FindAtom(atom_handle))) {
+      (v=this->ViewForHandle(atom_handle))) {
     return v;
   }
   v=AtomView(*this, atom_handle);
@@ -118,7 +118,7 @@ AtomView ResidueView::FindAtom(const String& atom_name) const {
   return i==data_->atoms.end() ? AtomView() : *i;
 }
 
-AtomView ResidueView::FindAtom(const AtomHandle& handle) const {
+AtomView ResidueView::ViewForHandle(const AtomHandle& handle) const {
   this->CheckValidity();
   const AtomViewList& l=data_->atoms;
   AtomViewList::const_iterator i;
@@ -128,7 +128,7 @@ AtomView ResidueView::FindAtom(const AtomHandle& handle) const {
 
 bool ResidueView::IsAtomIncluded(const AtomHandle& handle) const {
   // validity is checked by FindAtom
-  return this->FindAtom(handle).IsValid();
+  return this->ViewForHandle(handle).IsValid();
 }
 
 
@@ -274,4 +274,11 @@ EntityView ResidueView::Select(const String& q, QueryFlags flags) const {
   return this->GetEntity().Select(Query(s.str()), flags);
 }
 
+AtomView ResidueView::FindAtom(const AtomHandle& handle) const
+{
+  LOG_WARNING("ResidueView::FindAtom(handle) is deprecated. "
+              "Use ResidueView::ViewForHandle instead.");
+  return this->ViewForHandle(handle);
+}
+
 }} //ns
diff --git a/modules/mol/base/src/residue_view.hh b/modules/mol/base/src/residue_view.hh
index 8efe0c97f8739a5e8c64a1d1f84f3db357e94835..1727e87719c93b1d437352d861e8674c6cd72963 100644
--- a/modules/mol/base/src/residue_view.hh
+++ b/modules/mol/base/src/residue_view.hh
@@ -118,6 +118,7 @@ public:
   AtomView FindAtom(const String& atom_name) const;
 
   /// \brief Find residue by residue handle
+  AtomView ViewForHandle(const AtomHandle& handle) const;
   AtomView FindAtom(const AtomHandle& handle) const;
 
   /// \brief Check whether the view includes the the given atom.
diff --git a/modules/mol/base/src/transform.cc b/modules/mol/base/src/transform.cc
index c1ffbff6b8a34bf6016d01fba72deeba8a2f4fdb..ba1e59258299ca1f6011ddc1ebe1582aafba222b 100644
--- a/modules/mol/base/src/transform.cc
+++ b/modules/mol/base/src/transform.cc
@@ -22,6 +22,7 @@
 #include <ost/info/info.hh>
 #include <ost/info/geom_info_conversion.hh>
 #endif
+#include <ost/log.hh>
 #include "transform.hh"
 
 namespace ost { 
@@ -40,20 +41,11 @@ Transform::Transform():
   update_tm();
 }
     
-Mat4 Transform::GetMatrix() const
-{
-  return tm_;
-}
-
 void Transform::SetMatrix(const Mat4& m)
 {
   tm_=m;
   ttm_ = Transpose(tm_);
-}
-
-Mat4 Transform::GetTransposedMatrix() const
-{
-  return ttm_;
+  update_components();
 }
 
 void Transform::SetTrans(const Vec3& t) 
@@ -130,7 +122,7 @@ void Transform::ApplyZAxisRotation(float delta)
 
 void Transform::ApplyAxisRotation(float delta, const Vec3& axis)
 {
-  rot_=rot_*AxisRotation(rot_*axis, delta*P_180);
+  rot_=rot_*AxisRotation(axis, delta*P_180);
   update_tm();
 }
 
@@ -164,6 +156,23 @@ Vec4 Transform::Apply(const Vec4& v) const
   return nrvo;
 }
 
+geom::AlignedCuboid Transform::Apply(const geom::AlignedCuboid& c) const
+{
+  geom::Vec3 cmin=c.GetMin();
+  geom::Vec3 cmax=c.GetMax();
+  Vec3 t1 = Apply(Vec3(cmin[0],cmin[1],cmin[2]));
+  Vec3 t2 = Apply(Vec3(cmin[0],cmax[1],cmin[2]));
+  Vec3 t3 = Apply(Vec3(cmax[0],cmax[1],cmin[2]));
+  Vec3 t4 = Apply(Vec3(cmax[0],cmin[1],cmin[2]));
+  Vec3 t5 = Apply(Vec3(cmin[0],cmin[1],cmax[2]));
+  Vec3 t6 = Apply(Vec3(cmin[0],cmax[1],cmax[2]));
+  Vec3 t7 = Apply(Vec3(cmax[0],cmax[1],cmax[2]));
+  Vec3 t8 = Apply(Vec3(cmax[0],cmin[1],cmax[2]));
+  geom::Vec3 minc = Min(t1,Min(t2,Min(t3,Min(t4,Min(t5,Min(t6,Min(t7,t8)))))));
+  geom::Vec3 maxc = Max(t1,Max(t2,Max(t3,Max(t4,Max(t5,Max(t6,Max(t7,t8)))))));
+  return geom::AlignedCuboid(minc,maxc);
+}
+
 /*
   The order of the transformations given herein is conceptually
   "backward" as they are applied to a vertex, because the left-right
@@ -194,6 +203,22 @@ void Transform::update_tm()
                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 {
+    itm_ = Invert(tm_);
+  } catch (GeomException& e) {
+    LOG_WARNING("caught GeomException in Transform::update_tm: " << e.what());
+    itm_=geom::Mat4();
+  }
+}
+
+void Transform::update_components()
+{
+  rot_ = tm_.ExtractRotation();
+  cen_ = tm_.ExtractTranslation();
+  trans_[0] = tm_(3,0);
+  trans_[1] = tm_(3,1);
+  trans_[2] = tm_(3,2);
 }
 
 #if(OST_INFO_ENABLED)
diff --git a/modules/mol/base/src/transform.hh b/modules/mol/base/src/transform.hh
index 1ed33135e1ca1287f0e2c9debc151aeacca069cc..f9c59f6f5095256795b90e105d8067f20f1e6772 100644
--- a/modules/mol/base/src/transform.hh
+++ b/modules/mol/base/src/transform.hh
@@ -38,8 +38,9 @@ class DLLEXPORT_OST_MOL Transform {
 public:
   Transform();
 
-  geom::Mat4 GetMatrix() const;
-  geom::Mat4 GetTransposedMatrix() const;
+  geom::Mat4 GetMatrix() const {return tm_;}
+  geom::Mat4 GetTransposedMatrix() const {return ttm_;}
+  geom::Mat4 GetInvertedMatrix() const {return itm_;}
 
   void SetCenter(const geom::Vec3& c);
   geom::Vec3 GetCenter() const;
@@ -73,6 +74,7 @@ public:
   
   geom::Vec3 Apply(const geom::Vec3& v) const;
   geom::Vec4 Apply(const geom::Vec4& v) const;
+  geom::AlignedCuboid Apply(const geom::AlignedCuboid& c) const;
 
 private:
   geom::Mat3 rot_;
@@ -80,10 +82,14 @@ private:
   geom::Vec3 cen_;
   geom::Mat4 tm_;
   geom::Mat4 ttm_;
+  geom::Mat4 itm_;
 
   void update_tm();
+  void update_components();
 };
 
+
+
 #if(OST_INFO_ENABLED)
 /// \brief read transformation from info group
 /// \relates Transform
diff --git a/modules/mol/base/src/view_op.cc b/modules/mol/base/src/view_op.cc
index 973fa768662d38a4992874bf40917a768810d19a..6e4227e741d0faa02d5b1a902b1d63be0050aee2 100644
--- a/modules/mol/base/src/view_op.cc
+++ b/modules/mol/base/src/view_op.cc
@@ -64,14 +64,14 @@ mol::EntityView Union(const mol::EntityView& ev1, const mol::EntityView& ev2)
   mol::ChainViewList::const_iterator c_it=ev2.GetChainList().begin();
   for ( ; c_it!=ev2.GetChainList().end(); ++c_it) {
     mol::ChainView cv=*c_it;
-    mol::ChainView cv2=merge.FindChain(cv.GetHandle());
+    mol::ChainView cv2=merge.ViewForHandle(cv.GetHandle());
     if (!cv2) {
       cv2=merge.AddChain(cv, mol::ViewAddFlag::INCLUDE_ALL);
     } else {
       mol::ResidueViewList::const_iterator r_it=cv.GetResidueList().begin();
       for (; r_it!=cv.GetResidueList().end(); ++r_it) {
         mol::ResidueView rv=*r_it;
-        mol::ResidueView rv2=cv2.FindResidue(rv.GetHandle());
+        mol::ResidueView rv2=cv2.ViewForHandle(rv.GetHandle());
         if (!rv2) {
           rv2=cv2.AddResidue(rv, mol::ViewAddFlag::INCLUDE_ALL);
         } else {
@@ -115,7 +115,7 @@ mol::EntityView Difference(const mol::EntityView& ev1,
   mol::ChainViewList::const_iterator c_it=ev1.GetChainList().begin();
   for ( ; c_it!=ev1.GetChainList().end(); ++c_it) {
     mol::ChainView cv=*c_it;
-    mol::ChainView cv2=ev2.FindChain(cv.GetHandle());
+    mol::ChainView cv2=ev2.ViewForHandle(cv.GetHandle());
     if (!cv2) {
       diff.AddChain(cv,mol::ViewAddFlag::INCLUDE_ALL);
     } else {
@@ -123,7 +123,7 @@ mol::EntityView Difference(const mol::EntityView& ev1,
       mol::ResidueViewList::const_iterator r_it=cv.GetResidueList().begin();
       for (; r_it!=cv.GetResidueList().end(); ++r_it) {
         mol::ResidueView rv=*r_it;
-        mol::ResidueView rv2=cv2.FindResidue(rv.GetHandle());
+        mol::ResidueView rv2=cv2.ViewForHandle(rv.GetHandle());
         if (!rv2) {
           if(!chain_added){
             diff.AddChain(cv);
@@ -134,7 +134,7 @@ mol::EntityView Difference(const mol::EntityView& ev1,
           bool residue_added = false;
           mol::AtomViewList::const_iterator a_it=rv.GetAtomList().begin();
           for (; a_it!=rv.GetAtomList().end(); ++a_it) {
-            if (!rv2.FindAtom((*a_it).GetHandle())) {
+            if (!rv2.ViewForHandle((*a_it).GetHandle())) {
               if(!residue_added){
                 diff.AddResidue(rv);
                 residue_added = true;
@@ -182,7 +182,7 @@ mol::EntityView Intersection(const mol::EntityView& ev1,
   BondHandleList bonds_to_add;
   for (AtomViewIter a=ev1.AtomsBegin(),e=ev1.AtomsEnd(); a!=e; ++a) {
     AtomView av=*a;
-    AtomView av2=ev2.FindAtom(av.GetHandle());
+    AtomView av2=ev2.ViewForHandle(av.GetHandle());
     if (av2.IsValid()) {
       intersection.AddAtom(av.GetHandle());
       bl=av.GetBondList();
diff --git a/modules/mol/base/tests/CMakeLists.txt b/modules/mol/base/tests/CMakeLists.txt
index 5085b0b10b257fab18361001a1cb7a55b796769d..c29dc6adfe3d5ec1bbe2e85a5a587940b35848c2 100644
--- a/modules/mol/base/tests/CMakeLists.txt
+++ b/modules/mol/base/tests/CMakeLists.txt
@@ -10,6 +10,7 @@ set(OST_MOL_BASE_UNIT_TESTS
   test_query.cc
   test_surface.cc
   test_residue.cc
+  test_transform.cc
   test_view.cc
   test_view_op.cc
   tests.cc
diff --git a/modules/mol/base/tests/test_chain.cc b/modules/mol/base/tests/test_chain.cc
index e6587c2992be6486d31bb173625db9e9dbc670ac..ee4d933d0c095766079bb4278774d41d97a74ae3 100644
--- a/modules/mol/base/tests/test_chain.cc
+++ b/modules/mol/base/tests/test_chain.cc
@@ -301,7 +301,7 @@ BOOST_AUTO_TEST_CASE(chain_type)
                CHAINTYPE_POLY_DN_RN);
    BOOST_CHECK(ChainTypeFromString("other") == CHAINTYPE_UNKNOWN);
    BOOST_CHECK_THROW(ChainTypeFromString("supposed to fail"),
-                     std::runtime_error);
+                     Error);
 
    // chain type -> string
    BOOST_CHECK(StringFromChainType(CHAINTYPE_POLY) == "polymer");
@@ -322,7 +322,7 @@ BOOST_AUTO_TEST_CASE(chain_type)
                "polydeoxyribonucleotide/polyribonucleotide hybrid");
    BOOST_CHECK(StringFromChainType(CHAINTYPE_UNKNOWN) == "other");
    BOOST_CHECK_THROW(StringFromChainType(CHAINTYPE_N_CHAINTYPES),
-                     std::runtime_error);
+                     Error);
 }
 
 BOOST_AUTO_TEST_CASE(chain_description)
diff --git a/modules/mol/base/tests/test_coord_group.cc b/modules/mol/base/tests/test_coord_group.cc
index 7e3d385982636a346a6b88ea6b143b410352d64d..3c0cdc18fbe5fe139c930d0e7f54ad26cb5941ea 100644
--- a/modules/mol/base/tests/test_coord_group.cc
+++ b/modules/mol/base/tests/test_coord_group.cc
@@ -80,6 +80,18 @@ BOOST_AUTO_TEST_CASE(coord_group)
   BOOST_CHECK(ab.GetPos()==geom::Vec3(-14,-15,-16));
   BOOST_CHECK(ac.GetPos()==geom::Vec3(-17,-18,-19));
   BOOST_CHECK(ad.GetPos()==geom::Vec3(9,10,11));
+
+  Transform tf;
+  tf.ApplyXAxisRotation(17.0);
+  tf.ApplyYAxisRotation(-135.0);
+  tf.ApplyZAxisRotation(234.0);
+  tf.SetCenter(geom::Vec3(-7.3,1.2,5.5));
+  tf.SetTrans(geom::Vec3(14.5,-87.1,22.2));
+
+  cg.ApplyTransform(tf);
+  for(size_t i=0;i<3;++i) {
+    BOOST_CHECK_CLOSE(geom::Distance(cg.GetAtomPos(1,alist[i]),tf.Apply(clist[i])),Real(0),1e-6);
+  }
 }
 
 BOOST_AUTO_TEST_SUITE_END();
diff --git a/modules/mol/base/tests/test_entity.cc b/modules/mol/base/tests/test_entity.cc
index 1b8b195bd22307710b72c77f377475e2aa5d3ffc..46a4de626f41d8a37c57c8b0292ab2e7605dca2b 100644
--- a/modules/mol/base/tests/test_entity.cc
+++ b/modules/mol/base/tests/test_entity.cc
@@ -23,19 +23,20 @@
 #include <ost/geom/vec_mat_predicates.hh>
 #include <ost/mol/chem_class.hh>
 #include <ost/mol/mol.hh>
+#include <ost/mol/property_id.hh>
 #include <cmath>
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 #include <boost/test/auto_unit_test.hpp>
 
 #define CHECK_TRANSFORMED_ATOM_POSITION(ATOM,TARGET) \
-   BOOST_CHECK(vec3_is_close(ATOM.GetPos(), TARGET))
+   BOOST_CHECK(vec3_is_close(ATOM.GetPos(), TARGET,Real(0.1)))
 
 #define CHECK_ORIGINAL_ATOM_POSITION(ATOM,TARGET) \
- BOOST_CHECK(vec3_is_close(ATOM.GetOriginalPos(), TARGET))
+   BOOST_CHECK(vec3_is_close(ATOM.GetOriginalPos(), TARGET,Real(0.1)))
 
 #define CHECK_ALTERNATE_ATOM_POSITION(ATOM,TARGET,GROUP) \
-   BOOST_CHECK(vec3_is_close(ATOM.GetAltPos(GROUP), TARGET))
+   BOOST_CHECK(vec3_is_close(ATOM.GetAltPos(GROUP), TARGET,Real(0.1)))
 
 using namespace ost;
 using namespace ost::mol;
@@ -413,4 +414,19 @@ BOOST_AUTO_TEST_CASE(rename_atom)
    BOOST_CHECK_EQUAL(atom.GetName(), "B");
 }
 
+BOOST_AUTO_TEST_CASE(minmax)
+{
+  EntityHandle eh=make_test_entity();
+  EntityView ev = eh.CreateFullView();
+  mol::AtomViewList avl = ev.GetAtomList();
+  mol::AtomViewList::iterator i;
+  int n=0.0;
+  for (i=avl.begin(); i!=avl.end(); ++i, ++n) {
+    i->SetFloatProp("test", n);
+  }
+  std::pair<float,float> minmax = ev.GetMinMax("test", Prop::ATOM);
+  BOOST_CHECK_EQUAL(minmax.first, 0.0);
+  BOOST_CHECK_EQUAL(minmax.second, 7.0);
+}
+
 BOOST_AUTO_TEST_SUITE_END();
diff --git a/modules/mol/base/tests/test_ics.cc b/modules/mol/base/tests/test_ics.cc
index 77be8d680f5b1623067e02c3ef172bbf84152961..c2285ee1b0464ce64e7372e041b760317b0a04fb 100644
--- a/modules/mol/base/tests/test_ics.cc
+++ b/modules/mol/base/tests/test_ics.cc
@@ -117,11 +117,11 @@ BOOST_AUTO_TEST_CASE(ics_settorsion_unbuffered)
   Real eps = 0.0001;
   TorsionStructure s;
   ICSEditor e = s.e.EditICS(mol::UNBUFFERED_EDIT);
-  BOOST_CHECK_CLOSE(s.t1.GetAngle(), Real(M_PI), Real(eps));
+  BOOST_CHECK_CLOSE(std::abs(s.t1.GetAngle()), Real(M_PI), Real(eps));
   BOOST_CHECK_SMALL(s.t2.GetAngle(), eps);
   e.SetTorsionAngle(s.t1,0);
   BOOST_CHECK_SMALL(s.t1.GetAngle(), eps);
-  BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(M_PI), Real(eps));
+  BOOST_CHECK_CLOSE(std::abs(s.t2.GetAngle()), Real(M_PI), Real(eps));
   e.SetTorsionAngle(s.t2,M_PI/4);
   BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(M_PI/4), Real(eps));
   BOOST_CHECK_CLOSE(s.t1.GetAngle(), Real(-M_PI+M_PI/4), Real(eps));
@@ -138,11 +138,11 @@ BOOST_AUTO_TEST_CASE(ics_settorsion_buffered)
   Real eps = 0.0001;
   TorsionStructure s;
   ICSEditor e = s.e.EditICS(mol::BUFFERED_EDIT);
-  BOOST_CHECK_CLOSE(s.t1.GetAngle(), Real(M_PI), Real(eps));
+  BOOST_CHECK_CLOSE(std::abs(s.t1.GetAngle()), Real(M_PI), Real(eps));
   BOOST_CHECK_SMALL(s.t2.GetAngle(), eps);
   e.SetTorsionAngle(s.t1,0);
   BOOST_CHECK_SMALL(s.t1.GetAngle(), eps);
-  BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(M_PI), Real(eps));
+  BOOST_CHECK_CLOSE(std::abs(s.t2.GetAngle()), Real(M_PI), Real(eps));
   e.SetTorsionAngle(s.t2,M_PI/4);
   BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(M_PI/4), Real(eps));
   BOOST_CHECK_CLOSE(s.t1.GetAngle(), Real(-M_PI+M_PI/4), Real(eps));
diff --git a/modules/mol/base/tests/test_query.cc b/modules/mol/base/tests/test_query.cc
index 52fece59d284408ef8e5e7cdc2adda6d1f48f836..9f85dbcf1a8585f584354d525ff76f261af68d79 100644
--- a/modules/mol/base/tests/test_query.cc
+++ b/modules/mol/base/tests/test_query.cc
@@ -270,15 +270,15 @@ BOOST_AUTO_TEST_CASE(test_query_throw)
   EntityHandle e=make_query_test_entity();
   BOOST_CHECK_NO_THROW(e.Select("gatestpropa:0=1"));
   BOOST_CHECK_NO_THROW(e.Select("gatestpropa:1=1"));
-  BOOST_CHECK_THROW(e.Select("gatestpropa=1"), std::exception);
+  BOOST_CHECK_THROW(e.Select("gatestpropa=1"), ost::Error);
   BOOST_CHECK_NO_THROW(e.Select("grtestpropr:0=1"));
   BOOST_CHECK_NO_THROW(e.Select("grtestpropr:1=1"));
-  BOOST_CHECK_THROW(e.Select("grtestpropr=1"), std::exception);
+  BOOST_CHECK_THROW(e.Select("grtestpropr=1"), ost::Error);
   BOOST_CHECK_NO_THROW(e.Select("gctestprop_c:0=1"));
   BOOST_CHECK_NO_THROW(e.Select("gctestprop_c:1=1"));
-  BOOST_CHECK_THROW(e.Select("ganotsetprop=1"), std::exception);
-  BOOST_CHECK_THROW(e.Select("grnotsetprop=1"), std::exception);
-  BOOST_CHECK_THROW(e.Select("gcnotsetprop=1"), std::exception);
+  BOOST_CHECK_THROW(e.Select("ganotsetprop=1"), ost::Error);
+  BOOST_CHECK_THROW(e.Select("grnotsetprop=1"), ost::Error);
+  BOOST_CHECK_THROW(e.Select("gcnotsetprop=1"), ost::Error);
   BOOST_CHECK_NO_THROW(e.Select("ganotsetprop:0=1"));
   BOOST_CHECK_NO_THROW(e.Select("grnotsetprop:0=1"));
   BOOST_CHECK_NO_THROW(e.Select("gcnotsetprop:0=1"));
diff --git a/modules/mol/base/tests/test_transform.cc b/modules/mol/base/tests/test_transform.cc
new file mode 100644
index 0000000000000000000000000000000000000000..5c950acc5a170448290be09dde71d76fad5e8e66
--- /dev/null
+++ b/modules/mol/base/tests/test_transform.cc
@@ -0,0 +1,51 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+/*
+  Authors: Tobias Schmidt
+ */
+ #define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+#include <boost/test/auto_unit_test.hpp>
+#include <ost/mol/mol.hh>
+#include <ost/mol/transform.hh>
+#include <ost/geom/geom.hh>
+
+using namespace ost;
+using namespace ost::mol;
+
+BOOST_AUTO_TEST_SUITE( mol_base );
+
+BOOST_AUTO_TEST_CASE(test_transform)
+{
+  Transform tf;
+
+  BOOST_CHECK_EQUAL(tf.GetMatrix(), geom::Mat4());
+  BOOST_CHECK_EQUAL(tf.GetRot(), geom::Mat3());
+  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));
+}
+
+BOOST_AUTO_TEST_SUITE_END();
diff --git a/modules/mol/base/tests/test_view_op.cc b/modules/mol/base/tests/test_view_op.cc
index bd48a74094ab155e7aad1198fcdba10e91f51eb6..abe84f3baa65d356bcc2989245084c605f21f672 100644
--- a/modules/mol/base/tests/test_view_op.cc
+++ b/modules/mol/base/tests/test_view_op.cc
@@ -82,20 +82,20 @@ BOOST_AUTO_TEST_CASE(test_difference)
   BOOST_CHECK(diff_view.FindChain("B"));
 
   // check residues
-  BOOST_CHECK(!diff_view.FindResidue(ent.FindResidue("A", mol::ResNum(1))));
-  BOOST_CHECK(diff_view.FindResidue(ent.FindResidue("A", mol::ResNum(2))));
-  BOOST_CHECK(diff_view.FindResidue(ent.FindResidue("B", mol::ResNum(1))));
-  BOOST_CHECK(diff_view.FindResidue(ent.FindResidue("B", mol::ResNum(2))));
+  BOOST_CHECK(!diff_view.ViewForHandle(ent.FindResidue("A", mol::ResNum(1))));
+  BOOST_CHECK(diff_view.ViewForHandle(ent.FindResidue("A", mol::ResNum(2))));
+  BOOST_CHECK(diff_view.ViewForHandle(ent.FindResidue("B", mol::ResNum(1))));
+  BOOST_CHECK(diff_view.ViewForHandle(ent.FindResidue("B", mol::ResNum(2))));
 
   // check atoms
-  BOOST_CHECK(!diff_view.FindAtom(ent.FindAtom("A", mol::ResNum(1), "A")));
-  BOOST_CHECK(!diff_view.FindAtom(ent.FindAtom("A", mol::ResNum(1), "B")));
-  BOOST_CHECK(!diff_view.FindAtom(ent.FindAtom("A", mol::ResNum(2), "C")));
-  BOOST_CHECK(diff_view.FindAtom(ent.FindAtom("A", mol::ResNum(2), "D")));
-  BOOST_CHECK(diff_view.FindAtom(ent.FindAtom("B", mol::ResNum(1), "E")));
-  BOOST_CHECK(diff_view.FindAtom(ent.FindAtom("B", mol::ResNum(1), "F")));
-  BOOST_CHECK(diff_view.FindAtom(ent.FindAtom("B", mol::ResNum(2), "G")));
-  BOOST_CHECK(diff_view.FindAtom(ent.FindAtom("B", mol::ResNum(2), "H")));
+  BOOST_CHECK(!diff_view.ViewForHandle(ent.FindAtom("A", mol::ResNum(1), "A")));
+  BOOST_CHECK(!diff_view.ViewForHandle(ent.FindAtom("A", mol::ResNum(1), "B")));
+  BOOST_CHECK(!diff_view.ViewForHandle(ent.FindAtom("A", mol::ResNum(2), "C")));
+  BOOST_CHECK(diff_view.ViewForHandle(ent.FindAtom("A", mol::ResNum(2), "D")));
+  BOOST_CHECK(diff_view.ViewForHandle(ent.FindAtom("B", mol::ResNum(1), "E")));
+  BOOST_CHECK(diff_view.ViewForHandle(ent.FindAtom("B", mol::ResNum(1), "F")));
+  BOOST_CHECK(diff_view.ViewForHandle(ent.FindAtom("B", mol::ResNum(2), "G")));
+  BOOST_CHECK(diff_view.ViewForHandle(ent.FindAtom("B", mol::ResNum(2), "H")));
 
   // check bonds
   BondHandleList bonds=diff_view.GetBondList();
@@ -133,21 +133,21 @@ BOOST_AUTO_TEST_CASE(test_union_a)
   BOOST_CHECK(un.FindChain("B"));
   
   // test residues
-  BOOST_CHECK(un.FindResidue(ent.FindResidue("A", mol::ResNum(1))));
-  BOOST_CHECK(un.FindResidue(ent.FindResidue("A", mol::ResNum(2))));  
-  BOOST_CHECK(un.FindResidue(ent.FindResidue("B", mol::ResNum(1))));
-  BOOST_CHECK(un.FindResidue(ent.FindResidue("B", mol::ResNum(2))));  
+  BOOST_CHECK(un.ViewForHandle(ent.FindResidue("A", mol::ResNum(1))));
+  BOOST_CHECK(un.ViewForHandle(ent.FindResidue("A", mol::ResNum(2))));
+  BOOST_CHECK(un.ViewForHandle(ent.FindResidue("B", mol::ResNum(1))));
+  BOOST_CHECK(un.ViewForHandle(ent.FindResidue("B", mol::ResNum(2))));
   
   // test atoms
-  BOOST_CHECK(!un.FindAtom(ent.FindAtom("A", mol::ResNum(1), "A")));
-  BOOST_CHECK(un.FindAtom(ent.FindAtom("A", mol::ResNum(1), "B")));
-  BOOST_CHECK(un.FindAtom(ent.FindAtom("A", mol::ResNum(2), "C")));
-  BOOST_CHECK(!un.FindAtom(ent.FindAtom("A", mol::ResNum(2), "D")));
+  BOOST_CHECK(!un.ViewForHandle(ent.FindAtom("A", mol::ResNum(1), "A")));
+  BOOST_CHECK(un.ViewForHandle(ent.FindAtom("A", mol::ResNum(1), "B")));
+  BOOST_CHECK(un.ViewForHandle(ent.FindAtom("A", mol::ResNum(2), "C")));
+  BOOST_CHECK(!un.ViewForHandle(ent.FindAtom("A", mol::ResNum(2), "D")));
   
-  BOOST_CHECK(!un.FindAtom(ent.FindAtom("B", mol::ResNum(1), "E")));
-  BOOST_CHECK(un.FindAtom(ent.FindAtom("B", mol::ResNum(1), "F")));  
-  BOOST_CHECK(un.FindAtom(ent.FindAtom("B", mol::ResNum(2), "G")));
-  BOOST_CHECK(!un.FindAtom(ent.FindAtom("B", mol::ResNum(2), "H")));
+  BOOST_CHECK(!un.ViewForHandle(ent.FindAtom("B", mol::ResNum(1), "E")));
+  BOOST_CHECK(un.ViewForHandle(ent.FindAtom("B", mol::ResNum(1), "F")));
+  BOOST_CHECK(un.ViewForHandle(ent.FindAtom("B", mol::ResNum(2), "G")));
+  BOOST_CHECK(!un.ViewForHandle(ent.FindAtom("B", mol::ResNum(2), "H")));
   
   // bonds
    BondHandleList bonds=un.GetBondList();
@@ -187,21 +187,21 @@ BOOST_AUTO_TEST_CASE(test_union_b)
   BOOST_CHECK(un.FindChain("B"));
   
   // test residues
-  BOOST_CHECK(un.FindResidue(ent.FindResidue("A", mol::ResNum(1))));
-  BOOST_CHECK(un.FindResidue(ent.FindResidue("A", mol::ResNum(2))));  
-  BOOST_CHECK(un.FindResidue(ent.FindResidue("B", mol::ResNum(1))));
-  BOOST_CHECK(un.FindResidue(ent.FindResidue("B", mol::ResNum(2))));  
+  BOOST_CHECK(un.ViewForHandle(ent.FindResidue("A", mol::ResNum(1))));
+  BOOST_CHECK(un.ViewForHandle(ent.FindResidue("A", mol::ResNum(2))));
+  BOOST_CHECK(un.ViewForHandle(ent.FindResidue("B", mol::ResNum(1))));
+  BOOST_CHECK(un.ViewForHandle(ent.FindResidue("B", mol::ResNum(2))));
   
   // test atoms
-  BOOST_CHECK(un.FindAtom(ent.FindAtom("A", mol::ResNum(1), "A")));
-  BOOST_CHECK(un.FindAtom(ent.FindAtom("A", mol::ResNum(1), "B")));
-  BOOST_CHECK(un.FindAtom(ent.FindAtom("A", mol::ResNum(2), "C")));
-  BOOST_CHECK(!un.FindAtom(ent.FindAtom("A", mol::ResNum(2), "D")));
+  BOOST_CHECK(un.ViewForHandle(ent.FindAtom("A", mol::ResNum(1), "A")));
+  BOOST_CHECK(un.ViewForHandle(ent.FindAtom("A", mol::ResNum(1), "B")));
+  BOOST_CHECK(un.ViewForHandle(ent.FindAtom("A", mol::ResNum(2), "C")));
+  BOOST_CHECK(!un.ViewForHandle(ent.FindAtom("A", mol::ResNum(2), "D")));
   
-  BOOST_CHECK(!un.FindAtom(ent.FindAtom("B", mol::ResNum(1), "E")));
-  BOOST_CHECK(un.FindAtom(ent.FindAtom("B", mol::ResNum(1), "F")));  
-  BOOST_CHECK(un.FindAtom(ent.FindAtom("B", mol::ResNum(2), "G")));
-  BOOST_CHECK(!un.FindAtom(ent.FindAtom("B", mol::ResNum(2), "H")));
+  BOOST_CHECK(!un.ViewForHandle(ent.FindAtom("B", mol::ResNum(1), "E")));
+  BOOST_CHECK(un.ViewForHandle(ent.FindAtom("B", mol::ResNum(1), "F")));
+  BOOST_CHECK(un.ViewForHandle(ent.FindAtom("B", mol::ResNum(2), "G")));
+  BOOST_CHECK(!un.ViewForHandle(ent.FindAtom("B", mol::ResNum(2), "H")));
   
   // bonds
    BondHandleList bonds=un.GetBondList();
@@ -241,22 +241,22 @@ BOOST_AUTO_TEST_CASE(test_intersection_a)
   BOOST_CHECK(is.FindChain("B"));
   
   // test residues
-  BOOST_CHECK(!is.FindResidue(ent.FindResidue("A", mol::ResNum(1))));
-  BOOST_CHECK(is.FindResidue(ent.FindResidue("A", mol::ResNum(2))));  
-  BOOST_CHECK(is.FindResidue(ent.FindResidue("B", mol::ResNum(1))));
-  BOOST_CHECK(is.FindResidue(ent.FindResidue("B", mol::ResNum(2))));  
+  BOOST_CHECK(!is.ViewForHandle(ent.FindResidue("A", mol::ResNum(1))));
+  BOOST_CHECK(is.ViewForHandle(ent.FindResidue("A", mol::ResNum(2))));
+  BOOST_CHECK(is.ViewForHandle(ent.FindResidue("B", mol::ResNum(1))));
+  BOOST_CHECK(is.ViewForHandle(ent.FindResidue("B", mol::ResNum(2))));
   
   // test atoms
-  BOOST_CHECK(!is.FindAtom(ent.FindAtom("A", mol::ResNum(1), "A")));
-  BOOST_CHECK(!is.FindAtom(ent.FindAtom("A", mol::ResNum(1), "B")));
-  BOOST_CHECK(is.FindAtom(ent.FindAtom("A", mol::ResNum(2), "C")));
-  BOOST_CHECK(!is.FindAtom(ent.FindAtom("A", mol::ResNum(2), "D")));
+  BOOST_CHECK(!is.ViewForHandle(ent.FindAtom("A", mol::ResNum(1), "A")));
+  BOOST_CHECK(!is.ViewForHandle(ent.FindAtom("A", mol::ResNum(1), "B")));
+  BOOST_CHECK(is.ViewForHandle(ent.FindAtom("A", mol::ResNum(2), "C")));
+  BOOST_CHECK(!is.ViewForHandle(ent.FindAtom("A", mol::ResNum(2), "D")));
   
-  BOOST_CHECK(!is.FindAtom(ent.FindAtom("B", mol::ResNum(1), "E")));
-  BOOST_CHECK(is.FindAtom(ent.FindAtom("B", mol::ResNum(1), "F")));  
+  BOOST_CHECK(!is.ViewForHandle(ent.FindAtom("B", mol::ResNum(1), "E")));
+  BOOST_CHECK(is.ViewForHandle(ent.FindAtom("B", mol::ResNum(1), "F")));
   
-  BOOST_CHECK(is.FindAtom(ent.FindAtom("B", mol::ResNum(2), "G")));
-  BOOST_CHECK(!is.FindAtom(ent.FindAtom("B", mol::ResNum(2), "H")));
+  BOOST_CHECK(is.ViewForHandle(ent.FindAtom("B", mol::ResNum(2), "G")));
+  BOOST_CHECK(!is.ViewForHandle(ent.FindAtom("B", mol::ResNum(2), "H")));
 
   // bonds
   BondHandleList bonds=is.GetBondList();
@@ -296,22 +296,22 @@ BOOST_AUTO_TEST_CASE(test_intersection_b)
   BOOST_CHECK(is.FindChain("B"));
   
   // test residues
-  BOOST_CHECK(!is.FindResidue(ent.FindResidue("A", mol::ResNum(1))));
-  BOOST_CHECK(!is.FindResidue(ent.FindResidue("A", mol::ResNum(2))));  
-  BOOST_CHECK(is.FindResidue(ent.FindResidue("B", mol::ResNum(1))));
-  BOOST_CHECK(is.FindResidue(ent.FindResidue("B", mol::ResNum(2))));  
+  BOOST_CHECK(!is.ViewForHandle(ent.FindResidue("A", mol::ResNum(1))));
+  BOOST_CHECK(!is.ViewForHandle(ent.FindResidue("A", mol::ResNum(2))));
+  BOOST_CHECK(is.ViewForHandle(ent.FindResidue("B", mol::ResNum(1))));
+  BOOST_CHECK(is.ViewForHandle(ent.FindResidue("B", mol::ResNum(2))));
   
   // test atoms
-  BOOST_CHECK(!is.FindAtom(ent.FindAtom("A", mol::ResNum(1), "A")));
-  BOOST_CHECK(!is.FindAtom(ent.FindAtom("A", mol::ResNum(1), "B")));
-  BOOST_CHECK(!is.FindAtom(ent.FindAtom("A", mol::ResNum(2), "C")));
-  BOOST_CHECK(!is.FindAtom(ent.FindAtom("A", mol::ResNum(2), "D")));
+  BOOST_CHECK(!is.ViewForHandle(ent.FindAtom("A", mol::ResNum(1), "A")));
+  BOOST_CHECK(!is.ViewForHandle(ent.FindAtom("A", mol::ResNum(1), "B")));
+  BOOST_CHECK(!is.ViewForHandle(ent.FindAtom("A", mol::ResNum(2), "C")));
+  BOOST_CHECK(!is.ViewForHandle(ent.FindAtom("A", mol::ResNum(2), "D")));
   
-  BOOST_CHECK(!is.FindAtom(ent.FindAtom("B", mol::ResNum(1), "E")));
-  BOOST_CHECK(is.FindAtom(ent.FindAtom("B", mol::ResNum(1), "F")));  
+  BOOST_CHECK(!is.ViewForHandle(ent.FindAtom("B", mol::ResNum(1), "E")));
+  BOOST_CHECK(is.ViewForHandle(ent.FindAtom("B", mol::ResNum(1), "F")));
   
-  BOOST_CHECK(is.FindAtom(ent.FindAtom("B", mol::ResNum(2), "G")));
-  BOOST_CHECK(!is.FindAtom(ent.FindAtom("B", mol::ResNum(2), "H")));
+  BOOST_CHECK(is.ViewForHandle(ent.FindAtom("B", mol::ResNum(2), "G")));
+  BOOST_CHECK(!is.ViewForHandle(ent.FindAtom("B", mol::ResNum(2), "H")));
   
   // bonds
   BondHandleList bonds=is.GetBondList();
diff --git a/modules/seq/alg/pymod/renumber.py b/modules/seq/alg/pymod/renumber.py
index 39f34ba7b0dc68b4c84421e6b14ac606a9ddc107..f715f0bd6f1ef9dbbc60b3afc316502a9d462398 100644
--- a/modules/seq/alg/pymod/renumber.py
+++ b/modules/seq/alg/pymod/renumber.py
@@ -38,7 +38,7 @@ def Renumber(seq_handle, sequence_number_with_attached_view=1):
               renumberingFlag = True
             r_n=ed.AppendResidue(c,r.name, mol.ResNum(pos+1))
             for atom in r.atoms:
-              ed.InsertAtom(r_n,atom.name,atom.pos,atom.prop)
+              ed.InsertAtom(r_n,atom.name,atom.pos,element=atom.element)
         else:
           err='Error: renumbering failed at position %s' %pos
           raise RuntimeError, err
diff --git a/modules/seq/alg/tests/test_aligntoseqres.py b/modules/seq/alg/tests/test_aligntoseqres.py
index 0f4b8ceaa9bdbdf61bec7a390127b6ebc6687f89..6c390008e69d81d2613337a863503769b6da1872 100644
--- a/modules/seq/alg/tests/test_aligntoseqres.py
+++ b/modules/seq/alg/tests/test_aligntoseqres.py
@@ -68,5 +68,9 @@ class TestAlignToSeqRes(unittest.TestCase):
     self.assertEqual(seq.alg.ValidateSEQRESAlignment(seqres_aln, chain), False)
 
 if __name__ == "__main__":
-  from ost import testutils
-  testutils.RunTests()
+  builder=conop.GetBuilder()
+  if not hasattr(builder, 'compound_lib'):
+    print 'default builder does not use compound library. ignoring unit tests'
+  else:
+    from ost import testutils
+    testutils.RunTests()
diff --git a/modules/seq/base/doc/seq.rst b/modules/seq/base/doc/seq.rst
index e84cfe6747c627a07f7c756eb26397ce95e1598d..042f1d09c9811d0b7f42650576ec604cfa9d8fce 100644
--- a/modules/seq/base/doc/seq.rst
+++ b/modules/seq/base/doc/seq.rst
@@ -65,14 +65,16 @@ The SequenceHandle
 .. function:: CreateSequence(name, sequence)
 
   Create a new :class:`SequenceHandle` with the given name and sequence. 
-  
+
   :param name: name of the sequence
   :type  name: str
   :param sequence: String of characters representing the sequence. Only   
-       alphanumerical characters and '-' are allowed.
+       'word' characters (no digits), '?', '-' and '.' are allowed. In an
+       upcoming release, '?' and '.' will also be forbidden so its best to
+       translate those to 'X' or '-'.
   :type sequence: str
   :raises InvalidSequence: When the sequence string contains forbidden
-       characters, that is anything that is not alphanumeric or a hyphen.
+       characters. In the future, '?' and '.' will also raise this exception.
 
 .. class:: SequenceHandle
 
@@ -386,3 +388,47 @@ an alignment:
     
     :raises: In case one of the two sequences doesn't have an attached view, a 
        :exc:`RuntimeError` is raised.
+
+  .. method:: AddSequence(sequence)
+
+    Append a sequence to the alignment. The sequence must have the same length as
+    sequences already present in the alignment.
+
+    :raises: :exc:`RuntimeError` if the sequence length does not match
+    :param sequence: Sequence to be added
+    :type sequence: :class:`ConstSequenceHandle`
+
+  .. method:: GetSequenceOffset(index)
+              SetSequenceOffset(index, offset)
+
+    Get/set the offset for sequence at *index*.
+
+    :param index: The index of the sequence
+    :type index: :class:`int`
+    :param offset: The new offset
+    :type offset: :class:`int`
+    :rtype: :class:`int`
+  
+  .. method:: GetSequenceRole(index)
+              SetSequenceRole(index, role)
+
+    Get/Set the sequence role for sequence at *index*.
+
+    :param index: The index of the sequence
+    :type index: :class:`int`
+    :param role: The new role
+    :type role: :class:`str`
+    :rtype: :class:`str`
+
+  .. method:: GetCoverage(index)
+
+    Get coverage of sequence at *index* to the first sequence.
+
+    :param index: The index of the sequence
+    :type index: :class:`int`
+    :returns: Coverage as a number between 0 and 1.
+  
+  .. method:: RemoveSequence(index)
+
+    Remove sequence at *index* from the alignment.
+
diff --git a/modules/seq/base/src/alignment_handle.cc b/modules/seq/base/src/alignment_handle.cc
index 47a4fd0dd371747b35761519f15c696751fa3a4a..8b8f2fc282bd50c14f1c2cce31130e59fac29e68 100644
--- a/modules/seq/base/src/alignment_handle.cc
+++ b/modules/seq/base/src/alignment_handle.cc
@@ -66,10 +66,14 @@ int AlignmentHandle::GetResidueIndex(int seq_index, int pos) const
 void AlignmentHandle::AddSequence(const ConstSequenceHandle& sequence)
 {
   this->CheckValidity();
-  if (!sequence.IsValid() || (impl_->GetCount()>0 &&
-      impl_->GetSequence(0)->GetLength()!=sequence.GetLength())) {
+  if (!sequence.IsValid()) {
     throw InvalidSequence();
   }
+  if (impl_->GetCount()>0 &&
+      impl_->GetSequence(0)->GetLength()!=sequence.GetLength()) {
+    throw Error("sequence doesn't have the same length as the "
+                             "alignment");
+  }
   return impl_->AddSequence(sequence.Impl());
 }
 
@@ -137,7 +141,7 @@ AlignmentHandle AlignmentFromSequenceList(const SequenceList& seq_list)
   if (seq_list.IsValid() && seq_list.SequencesHaveEqualLength()) {
     return AlignmentHandle(seq_list.Impl());
   }
-  throw InvalidAlignment();
+  throw Error("sequences have different lengths");
 }
 
 ConstSequenceList AlignmentHandle::GetSequences() const
@@ -285,7 +289,7 @@ mol::EntityViewPair AlignmentHandle::GetMatchingBackboneViews(int idx0, int idx1
   const impl::SequenceImpl& s1=*impl_->GetSequence(idx0).get();
   const impl::SequenceImpl& s2=*impl_->GetSequence(idx1).get();
   if (!s1.HasAttachedView() || !s2.HasAttachedView()) {
-    throw std::runtime_error("both sequences must have a view attached");
+    throw Error("both sequences must have a view attached");
   }
   mol::EntityView v1=s1.GetAttachedView().CreateEmptyView();
   mol::EntityView v2=s2.GetAttachedView().CreateEmptyView();
diff --git a/modules/seq/base/tests/test_alignment.cc b/modules/seq/base/tests/test_alignment.cc
index 2a70c90a75c9b22fec5c340b15da7c1bf6d92e92..a70c19b226cb46140aa1fb70b5a8518b581156bd 100644
--- a/modules/seq/base/tests/test_alignment.cc
+++ b/modules/seq/base/tests/test_alignment.cc
@@ -64,11 +64,12 @@ BOOST_AUTO_TEST_CASE(alignment_triv)
   a = CreateAlignment();
   BOOST_CHECK_NO_THROW(a.AddSequence(CreateSequence("S1","-asdf-")));
   BOOST_CHECK_THROW(a.AddSequence(SequenceHandle()),InvalidSequence);
-  BOOST_CHECK_THROW(a.AddSequence(CreateSequence("S2","-asdf-f")),InvalidSequence);
+  BOOST_CHECK_THROW(a.AddSequence(CreateSequence("S2","-asdf-f")),
+                    Error);
   SequenceList list = CreateSequenceList();
   list.AddSequence(CreateSequence("S1", "-asdf-"));
   list.AddSequence(CreateSequence("S2", "fasdfas"));
-  BOOST_CHECK_THROW(AlignmentFromSequenceList(list),InvalidAlignment);
+  BOOST_CHECK_THROW(AlignmentFromSequenceList(list), Error);
   list = CreateSequenceList();
   list.AddSequence(CreateSequence("S1", "-asdf-"));
   list.AddSequence(CreateSequence("S2", "fasdfa"));
diff --git a/scripts/ost.in b/scripts/ost.in
index 5eee1638bdee1f44e731b405e872671da62c4283..407daed10f8d2b6fed92f1724c9c4b369bef0244 100755
--- a/scripts/ost.in
+++ b/scripts/ost.in
@@ -34,5 +34,3 @@ source $BIN_DIR/../@LIBEXEC_PATH@/ost_config
 $pyexec $interactive "$DNG_ROOT/@LIBDIR@/python@PYTHON_VERSION@/site-packages/init_cl.py" $opts
 RC=$?
 exit $RC
-
-
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b6289985b62ad1b6fac0d51c1d1e6976684430a7
--- /dev/null
+++ b/tools/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(molck)
diff --git a/tools/molck/CMakeLists.txt b/tools/molck/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..346f3466a7f728d411b418968fab7f8ed94a7bca
--- /dev/null
+++ b/tools/molck/CMakeLists.txt
@@ -0,0 +1,3 @@
+executable(NAME molck SOURCES main.cc 
+           DEPENDS_ON ost_io STATIC)
+
diff --git a/tools/molck/main.cc b/tools/molck/main.cc
new file mode 100644
index 0000000000000000000000000000000000000000..07baf9496ca1a9a3aee7bd2deb03502206f010fe
--- /dev/null
+++ b/tools/molck/main.cc
@@ -0,0 +1,419 @@
+#include <unistd.h>
+#include <boost/program_options.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/filesystem/convenience.hpp>
+#include <ost/platform.hh>
+#include <ost/conop/model_check.hh>
+#include <ost/conop/conop.hh>
+#include <ost/conop/amino_acids.hh>
+#include <ost/io/mol/pdb_reader.hh>
+#include <ost/io/mol/pdb_writer.hh>
+#include <ost/io/io_exception.hh>
+#include <ost/conop/nonstandard.hh>
+#if defined(__APPLE__)
+#include <mach-o/dyld.h>
+#endif
+using namespace ost;
+using namespace ost::conop;
+using namespace ost::mol;
+using namespace ost::io;
+
+namespace po=boost::program_options;
+namespace fs=boost::filesystem;
+
+EntityHandle load_x(const String& file, const IOProfile& profile)
+{
+  try {
+    PDBReader reader(file, profile);
+    if (reader.HasNext()) {
+      EntityHandle ent=CreateEntity();
+      reader.Import(ent);
+      return ent;
+    }
+    std::cerr << "ERROR: '" << file << "' does not contain any ATOM records. "
+              << "Are you sure this is a PDB file?" << std::endl;
+    return EntityHandle();
+  } catch (std::exception& e) {
+    std::cerr << "ERROR: " << e.what() << std::endl;
+    return EntityHandle();
+  }
+}
+
+// load compound library, exiting if it could not be found...
+CompoundLibPtr load_compound_lib(const String& custom_path)
+{
+  if (custom_path!="") {
+    if (fs::exists(custom_path)) {  
+      return CompoundLib::Load(custom_path);
+    } else {
+      std::cerr << "Could not find compounds.chemlib at the provided location, trying other options" << std::endl;
+    }
+  } 
+  if (fs::exists("compounds.chemlib")) {
+    return CompoundLib::Load("compounds.chemlib");
+  }
+  char result[ 1024 ]; 
+  CompoundLibPtr lib;
+  String exe_path; 
+  #if defined(__APPLE__)
+  uint32_t size=1023;
+  if (!_NSGetExecutablePath(result, &size)) {
+    exe_path=String(result); 
+  }
+  #else 
+  ssize_t count = readlink( "/proc/self/exe", result, 1024 );
+  exe_path = std::string( result, (count > 0) ? count : 0 );
+  #endif
+  if (exe_path.empty()) { 
+    std::cerr << "Could not determine the path of the molck executable. Will only look for compounds.chemlib in the current working directory" << std::endl;
+  } else {
+    fs::path path_and_exe(exe_path);
+    fs::path path_only=path_and_exe.branch_path();
+    fs::path share_path = path_only.branch_path();
+    share_path/="share";
+    share_path/="openstructure";
+    share_path/="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       
+      
+    if (fs::exists(share_path_string)) {
+      return CompoundLib::Load(share_path_string);
+    }  
+  }
+  if (!lib) {
+    std::cerr << "Could not load compounds.chemlib" << std::endl;
+    exit(-1);
+  }
+  return CompoundLibPtr();
+}
+
+void usage()
+{
+  std::cerr << "usage: molck [options] file1.pdb [file2.pdb [...]]" << std::endl;
+  std::cerr << "options" << std::endl;
+  std::cerr << "  --complib=path   location of the compound library file" << std::endl;   
+  std::cerr << "                   If not provided, the following locations are searched" << std::endl;   
+  std::cerr << "                   in this order:" << std::endl;   
+  std::cerr << "                   1. Working directory" << std::endl;   
+  std::cerr << "                   2. OpenStructure standard library location" << std::endl;   
+  std::cerr << "                      (if the executable is part of a standard" << std::endl;
+  std::cerr << "                      OpenStructure installation)" << std::endl;
+  std::cerr << "  --rm=<a>,<b>   remove atoms and residues matching some criteria" << std::endl;
+  std::cerr << "          zeroocc  - Remove atoms with zero occupancy" << std::endl;
+  std::cerr << "          hyd      - Remove hydrogen atoms" << std::endl;
+  std::cerr << "          oxt      - Remove terminal oxygens" << std::endl;
+  std::cerr << "          nonstd   - Remove all residues not " << std::endl 
+            << "                     one of the 20 standard amino acids" << std::endl;
+  std::cerr << "          unk      - Remove unknown atoms and atoms that " << std::endl 
+            << "                     are not supposed to be part of a residue" << std::endl;
+  std::cerr << "  --fix-ele      clean up element column" << std::endl;
+  std::cerr << "  --stdout       write cleaned file(s) to stdout" << std::endl;
+  std::cerr << "  --fileout=blueprint   write cleaned file(s) to disk" << std::endl;  
+  std::cerr << "                        The blueprint string, which must contain a % character," << std::endl;
+  std::cerr << "                        is used to generate the output filename and path" << std::endl; 
+  std::cerr << "                        by replacing % with the input file name without" << std::endl;
+  std::cerr << "                        the extension. Output files automatically add" << std::endl; 
+  std::cerr << "                        '.pdb' extension" << std::endl;
+  std::cerr << "  --color=auto|on|off " << std::endl 
+            << "          whether output should be colored" << std::endl;
+  std::cerr << "  --map-nonstd   maps modified residues back to the parent amino " << std::endl 
+            << "          acid, e.g. MSE -> MET, SEP -> SER." << std::endl;
+  exit(0);
+}	
+
+int main(int argc, char *argv[])
+{
+  if (argc<2) {
+    usage();
+  }
+  IOProfile prof;
+  prof.fault_tolerant=true;
+  String rm;
+  String color;
+  bool colored = false;
+
+  bool rm_unk_atoms=false;
+  bool rm_hyd_atoms=false;
+  bool rm_non_std=false;
+  bool rm_oxt_atoms=false;
+  bool rm_zero_occ_atoms=false;
+  bool write_to_stdout = false;
+  bool write_to_file = false;
+  bool map_nonstd_res = false;
+  bool assign_elem = false;
+  String output_blueprint_string;
+  String custom_path="";
+
+  po::options_description desc("Options");
+  desc.add_options()
+    ("rm", po::value<String>(&rm)->default_value("hyd"), "atoms to be removed")
+    ("color", po::value<String>(&color)->default_value("auto"), 
+     "whether the output should be colored.")
+    ("files", po::value< std::vector<String> >(), "input file(s)")
+    ("stdout", "write cleaned file(s) to stdout")
+    ("fileout", po::value<String>(&output_blueprint_string), "write cleaned file to output using blueprint to determine path")
+    ("map-nonstd", "map non standard residues back to standard ones (e.g.: MSE->MET,SEP->SER,etc.)")
+    ("fix-ele", "insert element") 
+    ("complib", po::value<String>(&custom_path)->default_value(""),"location of the compound library file")       
+  ;
+  po::positional_options_description p;
+  p.add("files", -1);
+  std::vector<String> files;
+  po::variables_map vm;
+  
+  try {
+    po::store(po::command_line_parser(argc, argv).
+                options(desc).positional(p).run(),
+              vm);
+  } catch (std::exception& e) {
+    std::cerr << e.what() << std::endl;
+    usage();
+    exit(-1);
+  }
+  po::notify(vm); 
+  if (vm.count("files")) {
+    files = vm["files"].as<std::vector<String> >();
+  } else {
+    usage();
+    exit(-1);
+  }
+  if (vm.count("complib")) {
+    custom_path = vm["complib"].as<String>();
+  }    
+  if (vm.count("stdout")) {
+    write_to_stdout = true;
+  }
+  if (vm.count("fileout")) {
+    write_to_file = true;
+    output_blueprint_string = vm["fileout"].as<String>();
+  }  
+  if (vm.count("map-nonstd")) {
+    map_nonstd_res = true;
+  }
+  if (vm.count("fix-ele")) {
+    assign_elem = true;
+  }
+  
+  std::vector<StringRef> rms=StringRef(rm.c_str(), rm.size()).split(',');
+  for (size_t i=0; i<rms.size(); ++i) {
+    if (rms[i] == StringRef("unk", 3)) {
+      rm_unk_atoms = true;
+    } else if (rms[i] == StringRef("nonstd", 6)) {
+      rm_non_std = true;
+    } else if (rms[i] == StringRef("hyd", 3)) {
+      rm_hyd_atoms = true;
+    } else if (rms[i] == StringRef("oxt", 3)) {
+      rm_oxt_atoms = true;
+    } else if (rms[i] == StringRef("zeroocc", 7)) {
+      rm_zero_occ_atoms = true;
+    } else {
+      std::cerr << "unknown value to remove '" << rms[i] << "'" << std::endl;
+      usage();
+      exit(-1);
+    }
+  }
+  if (color=="auto") {
+    colored = isatty(STDERR_FILENO);
+  } else if (color == "on" || color == "1" || color == "yes") {
+    colored = true;
+  } else if (color == "off" || color == "0" || color == "no") {
+    colored = false;	
+  } else {
+    usage();
+    exit(-1);
+  }
+  CompoundLibPtr lib=load_compound_lib(custom_path);  
+  for (unsigned int i = 0; i < files.size(); ++i) {
+    EntityHandle ent=load_x(files[i], prof);
+    if (!ent.IsValid()) {
+      continue;
+    }
+    if (map_nonstd_res)  {
+      EntityHandle new_ent=CreateEntity();  
+      ChainHandleList chains=ent.GetChainList();
+      XCSEditor new_edi=new_ent.EditXCS();
+      for (ChainHandleList::const_iterator c=chains.begin();c!=chains.end();++c) {
+        ChainHandle new_chain = new_edi.InsertChain(c->GetName());
+        ResidueHandleList residues = c->GetResidueList();
+        for (ResidueHandleList::const_iterator r=residues.begin();r!=residues.end();++r) {
+          AminoAcid aa = ResidueToAminoAcid(*r);
+          if (aa!=XXX) {
+            ResidueHandle dest_res = new_edi.AppendResidue(new_chain,r->GetName(),r->GetNumber());
+            AtomHandleList atoms = r->GetAtomList();
+            for (AtomHandleList::const_iterator a=atoms.begin();a!=atoms.end();++a) {
+              new_edi.InsertAtom(dest_res,a->GetName(),a->GetPos(),a->GetElement(),a->GetOccupancy(),a->GetBFactor(),a->IsHetAtom());
+            }
+            continue;
+          } else {
+            CompoundPtr compound=lib->FindCompound(r->GetName(),Compound::PDB);
+            if (!compound || !compound->IsPeptideLinking() || compound->GetChemClass()==ChemClass::D_PEPTIDE_LINKING || 
+                 OneLetterCodeToAminoAcid(compound->GetOneLetterCode())==XXX) {
+               ResidueHandle dest_res = new_edi.AppendResidue(new_chain,r->GetName(),r->GetNumber());
+               AtomHandleList atoms = r->GetAtomList();
+               for (AtomHandleList::const_iterator a=atoms.begin();a!=atoms.end();++a) {
+                 new_edi.InsertAtom(dest_res,a->GetName(),a->GetPos(),a->GetElement(),a->GetOccupancy(),a->GetBFactor(),a->IsHetAtom());
+               }
+               continue;
+            } 
+            ResidueHandle dest_res = new_edi.AppendResidue(new_chain,OneLetterCodeToResidueName(compound->GetOneLetterCode()),r->GetNumber());
+            CopyResidue(*r,dest_res,new_edi,lib);
+          }   
+        }        
+      }
+    ent=new_ent;
+    }
+
+    XCSEditor edi=ent.EditXCS();
+    DiagEngine diags;
+    Checker checker(lib, ent, diags);
+    if (rm_zero_occ_atoms) {
+      std::cerr << "removing atoms with zero occupancy" << std::endl;
+      int zremoved=0;
+      AtomHandleList zero_atoms=checker.GetZeroOccupancy();
+      for (AtomHandleList::const_iterator i=zero_atoms.begin(), e=zero_atoms.end(); i!=e; ++i) {
+         edi.DeleteAtom(*i);
+         zremoved++;   
+      }
+      std::cerr << " --> removed " << zremoved << " hydrogen atoms" << std::endl;
+    }
+
+    if (rm_hyd_atoms) {
+      std::cerr << "removing hydrogen atoms" << std::endl;
+      int hremoved=0;
+      AtomHandleList hyd_atoms=checker.GetHydrogens();
+      for (AtomHandleList::const_iterator i=hyd_atoms.begin(), e=hyd_atoms.end(); i!=e; ++i) {
+         edi.DeleteAtom(*i);
+         hremoved++;   
+      }
+      std::cerr << " --> removed " << hremoved << " hydrogen atoms" << std::endl;
+    }
+    if (rm_oxt_atoms) {
+      std::cerr << "removing OXT atoms" << std::endl;
+      int oremoved=0;
+      AtomHandleList atoms=ent.GetAtomList();
+      for (AtomHandleList::const_iterator i=atoms.begin(), e=atoms.end(); i!=e; ++i) {
+         if (i->GetName()=="OXT") {
+           edi.DeleteAtom(*i);
+           oremoved++;   
+         }
+      }
+      std::cerr << " --> removed " << oremoved << " OXT atoms" << std::endl;
+    }
+
+    if (rm_non_std) {
+      std::cerr << "removing OXT atoms" << std::endl;
+      int oremoved=0;
+      AtomHandleList atoms=ent.GetAtomList();
+      for (AtomHandleList::const_iterator i=atoms.begin(), e=atoms.end(); i!=e; ++i) {
+         if (i->GetName()=="OXT") {
+           edi.DeleteAtom(*i);
+           oremoved++;   
+         }
+      }
+      std::cerr << " --> removed " << oremoved << " OXT atoms" << std::endl;
+    }
+
+    checker.CheckForCompleteness();
+    checker.CheckForUnknownAtoms();
+    checker.CheckForNonStandard();
+      for (size_t j=0; j<diags.GetDiags().size(); ++j) {
+      const Diag* diag=diags.GetDiags()[j];
+      std::cerr << diag->Format(colored);
+      switch (diag->GetType()) {
+        case DIAG_UNK_ATOM:
+          if (rm_unk_atoms) {
+            edi.DeleteAtom(diag->GetAtom(0));
+            std::cerr << " --> removed ";  
+          }
+          break;
+        case DIAG_NONSTD_RESIDUE:
+          if (rm_non_std) {
+            edi.DeleteResidue(diag->GetResidue(0));
+            std::cerr << " --> removed ";  
+          }
+          break;
+        default:
+          break;
+      }
+      std::cerr << std::endl;
+    }
+    if (assign_elem)  {
+      ChainHandleList chains=ent.GetChainList();
+      for (ChainHandleList::const_iterator c=chains.begin();c!=chains.end();++c) {
+        ResidueHandleList residues = c->GetResidueList();
+        for (ResidueHandleList::const_iterator r=residues.begin();r!=residues.end();++r) {
+          CompoundPtr compound=lib->FindCompound(r->GetName(),Compound::PDB);            
+          AtomHandleList atoms=r->GetAtomList();
+          if (!compound) {
+            for (AtomHandleList::iterator j=atoms.begin(), e2=atoms.end(); j!=e2; ++j) {
+                j->SetElement("");
+            }
+            continue; 
+          }
+          for (AtomHandleList::iterator j=atoms.begin(), e2=atoms.end(); j!=e2; ++j) {
+            int specindx=compound->GetAtomSpecIndex(j->GetName());
+            if (specindx!=-1) {  
+              j->SetElement(compound->GetAtomSpecs()[specindx].element);
+            } else {
+              j->SetElement("");
+            }
+          }
+        }    
+      }
+    }          
+ 
+    if (write_to_stdout) {
+      PDBWriter writer(std::cout, prof);
+      writer.Write(ent);
+    }
+    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       
+
+      size_t replstart =output_blueprint_string.find('%');	
+
+      if (replstart == String::npos) {
+        std::cerr << "The output blueprint string does not contain a % character" << std::endl;
+        exit(-1);
+      } 
+      String output_blueprint_string_copy = output_blueprint_string;
+      output_blueprint_string_copy.replace(replstart,1,input_filename_string); 
+      output_blueprint_string_copy+=".pdb";
+ 
+      try {
+        fs::path out_path(output_blueprint_string_copy);
+        if (!exists(out_path)) {
+          std::cerr << "Output path does not exist: " << output_blueprint_string_copy << std::endl;
+          exit(-1);
+        }
+      } catch (std::exception& e) {
+
+        size_t perden = String(e.what()).find("Permission denied");	
+
+        if (perden != String::npos) {
+          std::cerr << "Cannot write into output directory: " << output_blueprint_string_copy << std::endl;
+          exit(-1);
+        } else {
+          std::cerr << e.what() << std::endl;
+          exit(-1);
+        }
+      }
+      std::cerr << "Writing out file: " << output_blueprint_string_copy << std::endl;
+      PDBWriter writer(output_blueprint_string_copy, prof);
+       writer.Write(ent);
+    }
+  }
+ 
+  return 0;
+}