diff --git a/.gitignore b/.gitignore
index c4c1b9add1cca6fb92c973b33b29748e8c3a46a8..56410cfa551dd48078e87a6a355fa7eadf1823ab 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,7 @@ CTestTestfile.cmake
 .*
 !.gitignore
 CMakeCache.txt
+version.hh
 config.hh
 *.pyc
 index.txt
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 12e52f7c6838493fb1e4ab528a3225f9b299f046..90755377da882c5c1d7c2e4b31134786a1df957c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -4,13 +4,17 @@
 
 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_STRING ${OST_VERSION_MAJOR}.${OST_VERSION_MINOR}.${OST_VERSION_PATCH} )
 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake_support)
 include(OST)
 
 
 option(USE_SHADER "whether to compile with shader support"
        OFF)
-option(SET_RPATH "embed rpath upon make install"
+option(USE_RPATH "embed rpath upon make install"
        OFF)
 option(COMPILE_TMTOOLS "whether to compile the tmalign and tmscore programs"
        OFF)
@@ -30,8 +34,10 @@ option(ENABLE_SPNAV "whether 3DConnexion devices should be supported"
       OFF)
 option(STATIC_PROPERTY_WORKAROUND "workaround for static property bug with some boost/boost_python combinations" OFF)
 option(DEPLOYMENT "switch on deployment settings" OFF)
-option(COMPILE_TESTS "wheter unit tests should be compiled by default" 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)
+
 if (CXX)
   set(CMAKE_CXX_COMPILER ${CXX})
 endif()
@@ -110,6 +116,12 @@ else()
   set(_PROFILE OFF)
 endif()
 
+if (DEBIAN_STYLE_LIBEXEC)
+  set(_DEBIAN_STYLE_LIBEXEC ON)
+else()
+  set(_DEBIAN_STYLE_LIBEXEC OFF)
+endif()
+
 add_definitions(-DEIGEN2_SUPPORT)
 
 if (COMPOUND_LIB)
@@ -218,16 +230,17 @@ set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES
 
 message(STATUS 
         "OpenStructure will be built with the following options:\n"
-        "   Install Prefix                 (-DPREFIX) : ${CMAKE_INSTALL_PREFIX}\n"
-        "   RPath in install            (-DUSE_RPATH) : ${_USE_RPATH}\n"
-        "   Graphical interface        (-DENABLE_GUI) : ${_UI}\n"
-        "   OpenGL support             (-DENABLE_GFX) : ${_OPENGL}\n"
-        "   Image Processing support   (-DENABLE_IMG) : ${_IMG}\n"
-        "   Shader support             (-DUSE_SHADER) : ${_SHADER}\n"
-        "   Numpy support               (-DUSE_NUMPY) : ${_NUMPY}\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}")
+        "   Install Prefix                       (-DPREFIX) : ${CMAKE_INSTALL_PREFIX}\n"
+        "   RPath in install                  (-DUSE_RPATH) : ${_USE_RPATH}\n"
+        "   Graphical interface              (-DENABLE_GUI) : ${_UI}\n"
+        "   OpenGL support                   (-DENABLE_GFX) : ${_OPENGL}\n"
+        "   Image Processing support         (-DENABLE_IMG) : ${_IMG}\n"
+        "   Shader support                   (-DUSE_SHADER) : ${_SHADER}\n"
+        "   Numpy support                     (-DUSE_NUMPY) : ${_NUMPY}\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}")
\ No newline at end of file
diff --git a/cmake_support/OST.cmake b/cmake_support/OST.cmake
index f392eb87efd7054720015ac739ed908bec5c1571..297696f4ce0d1468309feed082bc96c68f0fa302 100644
--- a/cmake_support/OST.cmake
+++ b/cmake_support/OST.cmake
@@ -187,6 +187,9 @@ macro(module)
     get_target_property(_DEFS ${_LIB_NAME} COMPILE_DEFINITIONS)
     set_target_properties(${_LIB_NAME} PROPERTIES
                           COMPILE_DEFINITIONS OST_MODULE_${_UPPER_LIB_NAME})
+    set_target_properties(${_LIB_NAME} PROPERTIES
+                          VERSION ${OST_VERSION_STRING}
+                          SOVERSION ${OST_VERSION_MAJOR}.${OST_VERSION_MINOR})    
     set_target_properties(${_LIB_NAME} PROPERTIES
                           LIBRARY_OUTPUT_DIRECTORY ${LIB_STAGE_PATH}
                           ARCHIVE_OUTPUT_DIRECTORY ${LIB_STAGE_PATH}
@@ -310,6 +313,40 @@ macro(executable)
 endmacro()
 
 
+#-------------------------------------------------------------------------------
+# Synopsis
+#   executable_libexec(NAME exe_name SOURCES source1 source2 LINK link1 link2)
+#
+# Description:
+#  Compile, link and stage a C++ executable into the libexec directory
+#-------------------------------------------------------------------------------
+macro(executable_libexec)
+  parse_argument_list(_ARG 
+                      "NAME;SOURCES;LINK;DEPENDS_ON" "NO_RPATH;STATIC" ${ARGN})
+  if (NOT _ARG_NAME)
+    message(FATAL_ERROR "invalid use of executable(): a name must be provided")
+  endif()   
+  add_executable(${_ARG_NAME} ${_ARG_SOURCES})
+  set_target_properties(${_ARG_NAME}
+                        PROPERTIES RUNTIME_OUTPUT_DIRECTORY
+                       "${LIBEXEC_STAGE_PATH}")  
+  if (APPLE AND NOT _ARG_NO_RPATH AND NOT _ARG_STATIC)
+    set_target_properties(${_ARG_NAME} PROPERTIES
+                          LINK_FLAGS "-Wl,-rpath,@loader_path/../lib")
+  endif()
+  if (_ARG_LINK)
+    target_link_libraries(${_ARG_NAME} ${_ARG_LINK})
+  endif()
+  if (ENABLE_STATIC AND _ARG_STATIC)
+    set(TARGET_SUFFIX _static)
+    target_link_libraries(${_ARG_NAME} ${STATIC_LIBRARIES})
+  endif()
+  foreach(_DEP ${_ARG_DEPENDS_ON})
+    target_link_libraries(${_ARG_NAME} ${_DEP}${TARGET_SUFFIX})
+  endforeach()
+  install(TARGETS ${_ARG_NAME} DESTINATION ${LIBEXEC_PATH})
+endmacro()
+
 #-------------------------------------------------------------------------------
 # Synopsis:
 #   substitute(IN_FILE in_file OUT_FILE out_file DICT a=b c=d)
@@ -583,7 +620,7 @@ macro(ost_unittest)
       endif()
       if (WIN32)
         target_link_libraries(${_test_name} ${BOOST_UNIT_TEST_LIBRARIES} "${_ARG_PREFIX}_${_ARG_MODULE}")  
-        add_custom_target("${_test_name}_run"
+        add_custom_target("${_test_name}_run":
                         COMMAND ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${_test_name}.exe || echo
                         WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${CMAKE_BUILD_TYPE}/..
                         COMMENT "running checks for module ${_ARG_MODULE}"
@@ -722,7 +759,6 @@ macro(setup_stage)
   set(STAGE_DIR "${CMAKE_BINARY_DIR}/stage")
   set(EXECUTABLE_OUTPUT_PATH ${STAGE_DIR}/bin  )
   set(HEADER_STAGE_PATH ${STAGE_DIR}/include )
-  set(LIBEXEC_STAGE_PATH ${STAGE_DIR}/libexec/openstructure  )
   set(SHARED_DATA_PATH ${STAGE_DIR}/share/openstructure  )
 
   if (UNIX AND NOT APPLE)
@@ -736,6 +772,16 @@ macro(setup_stage)
     set(LIB_DIR lib  )
     set(LIB_STAGE_PATH "${STAGE_DIR}/lib"  )
   endif()
+  if (_DEBIAN_STYLE_LIBEXEC)
+    set(LIBEXEC_PATH ${LIB_DIR}/openstructure/libexec  )
+  else()
+    set(LIBEXEC_PATH libexec/openstructure  )
+  endif()
+  if (_DEBIAN_STYLE_LIBEXEC)
+    set(LIBEXEC_STAGE_PATH ${LIB_STAGE_PATH}/openstructure/libexec  )
+  else()
+    set(LIBEXEC_STAGE_PATH ${STAGE_DIR}/libexec/openstructure  )
+  endif()
 
   include_directories("${HEADER_STAGE_PATH}")
   link_directories(${LIB_STAGE_PATH})
diff --git a/deployment/linux/README.txt b/deployment/linux/README.txt
index 841009281b2e8f4b0cecec638baadc6305984263..2f1ab3010a1c0854b08e58e45337296f3fe4938a 100644
--- a/deployment/linux/README.txt
+++ b/deployment/linux/README.txt
@@ -4,13 +4,3 @@ HOW TO USE THE BUNDLE SCRIPTS:
 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
-
-
-HOW TO USE THE QMEAN BUNDLE SCRIPTS:
-
-1. Checkout a copy of the OpenStructure repository.
-2. Check out a copy of the scratch repository in modules/scratch
-3. Create a folder called ChemLib in the <OpenStructure Folder> and copy the compunds.chemlib file into it.
-4. Move to the <OpenStructure folder>/deployment/linux folder and start the create_qmeqn_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_qmean_repository.py script or delete the <OpenStructure Folder> and restart from scratch
\ No newline at end of file
diff --git a/deployment/linux/create_bundle.py b/deployment/linux/create_bundle.py
index dbb88bb70feaa46329922ba30e3efefaea0b89fb..3f04533f0c4d6c3f84e907a0f73099bdf5988929 100644
--- a/deployment/linux/create_bundle.py
+++ b/deployment/linux/create_bundle.py
@@ -12,7 +12,7 @@ if len(sys.argv) < 3:
   print 'usage: create_bundle.py  additional_label system_python_version'
   sys.exit()
 
-system_python_version=sys.argv[2]
+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
@@ -43,28 +43,21 @@ date_pattern='%Y-%b-%d'
 build=datetime.date.today()
 directory_name='openstructure-linux-'+archstring+'-'+additional_label+'-'+str(build)
 print 'Hardcoding package python binary path in openstructure executables'
-subprocess.call('mv scripts/ost.in scripts/ost.in.backup',shell=True,cwd='../../')
-subprocess.call('sed "s/@PYTHON_BINARY@/\$DNG_ROOT\/bin\/'+python_bin_in_bundle+'/g" scripts/ost.in.backup > scripts/ost.in.prepreprepre',shell=True,cwd='../../')
-subprocess.call('sed "s/\#export LD_LIBRARY_PATH/ export LD_LIBRARY_PATH/g" scripts/ost.in.prepreprepre > scripts/ost.in.preprepre',shell=True,cwd='../../')
-subprocess.call('sed "s/\#export PYTHONHOME/ export PYTHONHOME/g" scripts/ost.in.preprepre > scripts/ost.in.prepre',shell=True,cwd='../../')
-subprocess.call('sed "s/\#export PYTHONPATH/ export PYTHONPATH/g" scripts/ost.in.prepre > scripts/ost.in.pre',shell=True,cwd='../../')
-subprocess.call('sed "s/\#export QT_PLUGIN_PATH/ export QT_PLUGIN_PATH/g" scripts/ost.in.pre > scripts/ost.in',shell=True,cwd='../../')
-subprocess.call('mv scripts/dng.in scripts/dng.in.backup',shell=True,cwd='../../')
-subprocess.call('sed "s/\#export LD_LIBRARY_PATH/ export LD_LIBRARY_PATH/g" scripts/dng.in.backup > scripts/dng.in.preprepre',shell=True,cwd='../../')
-subprocess.call('sed "s/\#export PYTHONHOME/ export PYTHONHOME/g" scripts/dng.in.preprepre > scripts/dng.in.prepre',shell=True,cwd='../../')
-subprocess.call('sed "s/\#export PYTHONPATH/ export PYTHONPATH/g" scripts/dng.in.prepre > scripts/dng.in.pre',shell=True,cwd='../../')
-subprocess.call('sed "s/\#export QT_PLUGIN_PATH/ export QT_PLUGIN_PATH/g" scripts/dng.in.pre > scripts/dng.in',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/\#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 '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+' -DBoost_COMPILER='+boost_string+' -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/compounds.chemlib -DENABLE_IMG=ON -DENABLE_UI=ON -DENABLE_GFX=ON -DOPTIMIZE=ON',shell=True,cwd='../../')
 subprocess.call('make -j2',shell=True,cwd='../../')
 print 'Removing obsolete packages and package directory'
@@ -73,13 +66,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,shell=True,cwd='../../')
-subprocess.call('rm -fr stage/'+libdir+'/'+system_python_version+'/dist-packages',shell=True,cwd='../../')
+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+'/'+system_python_version,shell=True,cwd='../../')
-  subprocess.call('cp -pRL '+second_system_python_libs+'/PyQt* stage/'+libdir+'/'+system_python_version,shell=True,cwd='../../')
+  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='../../')
 print 'Creating new dependency list'
 so_list=[]
 walk_list=os.walk('../../stage')
@@ -104,22 +98,21 @@ for entry in sorted_dep_list:
        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'
-subprocess.call('mkdir '+directory_name+'/'+libdir,shell=True,cwd='../../')
 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,shell=True,cwd='../../')
-subprocess.call('rm -fr '+directory_name+'/'+libdir+'/'+system_python_version+'/dist-packages',shell=True,cwd='../../')
+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+'/'+system_python_version,shell=True,cwd='../../')
-  subprocess.call('cp -pRL '+second_system_python_libs+'/PyQt* '+directory_name+'/'+libdir+'/'+system_python_version,shell=True,cwd='../../')
+  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='../../')
 print 'Copy Qt 4 plugins into package directory structure'
 subprocess.call('cp -pRL '+qt4_plugins+' '+directory_name+'/bin/',shell=True,cwd='../../')
-print 'Installing OpenStructure into package directory structure'
-subprocess.call('make install',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'
@@ -140,11 +133,8 @@ 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.in',shell=True,cwd='../../')
-subprocess.call('rm scripts/ost.in.pre*',shell=True,cwd='../../')
-subprocess.call('rm scripts/dng.in',shell=True,cwd='../../')
-subprocess.call('rm scripts/dng.in.pre*',shell=True,cwd='../../')
-subprocess.call('mv scripts/ost.in.backup scripts/ost.in',shell=True,cwd='../../')
-subprocess.call('mv scripts/dng.in.backup scripts/dng.in',shell=True,cwd='../../')
+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='../../')
 subprocess.call('tar cfz '+directory_name+'.tgz '+directory_name,shell=True,cwd='../../')
 
diff --git a/deployment/linux/create_qmean_bundle.py b/deployment/linux/create_qmean_bundle.py
deleted file mode 100644
index e8743cb03106a2819475635a4353f5dcee39a1b0..0000000000000000000000000000000000000000
--- a/deployment/linux/create_qmean_bundle.py
+++ /dev/null
@@ -1,138 +0,0 @@
-import os
-import shutil
-import subprocess
-import string
-import sys
-
-
-# custom parameters
-
-boost_string='\".so.1.40.0\"'
-system_python_bin='/usr/bin/python2.6'
-name_python_bin='python2.6'
-system_python_libs='/usr/lib/python2.6'
-second_system_python_libs_flag=True
-second_system_python_libs='/usr/lib/pymodules/python2.6'
-qt4_plugins='/usr/lib/qt4/plugins'
-additional_label='ubuntu'
-list_of_excluded_libraries=['ld-linux','libexpat','libgcc_s','libglib','cmov','libice','libSM','libX','libg','libGL.so','libfontconfig','libfreetype','libdrm','libxcb','libICE']
-
-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 '\n'
-print 'WARNING: If this script does not run to completion, please run the reset_repository_qmean.py script before restarting'
-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'
-svninfo_output=subprocess.Popen('svn info', shell=True, cwd='../../',stdout=subprocess.PIPE).stdout
-svninfo_lines=svninfo_output.readlines()
-svninfo_split=string.split(svninfo_lines[4])
-revstring=svninfo_split[1]
-directory_name='qmean-'+archstring+'-'+additional_label+'-rev'+revstring
-print 'Stripping subversion information to avoid accidental commit'
-subprocess.call('rm -rf $(find . -name .svn)',shell=True,cwd='../../')
-print 'Tweaking scripts for bundle use'
-subprocess.call('mv scripts/ost.in scripts/ost.in.backup',shell=True,cwd='../../')
-subprocess.call('sed "s/@PYTHON_BINARY@/\$DNG_ROOT\/bin\/'+name_python_bin+'/g" scripts/ost.in.backup > scripts/ost.in.preprepre',shell=True,cwd='../../')
-subprocess.call('sed "s/\#export LD_LIBRARY_PATH/ export LD_LIBRARY_PATH/g" scripts/ost.in.prepreprepre > scripts/ost.in.preprepre',shell=True,cwd='../../')
-subprocess.call('sed "s/\#export PYTHONHOME/ export PYTHONHOME/g" scripts/ost.in.preprepre > scripts/ost.in.prepre',shell=True,cwd='../../')
-subprocess.call('sed "s/\#export PYTHONPATH/ export PYTHONPATH/g" scripts/ost.in.prepre > scripts/ost.in.pre',shell=True,cwd='../../')
-subprocess.call('sed "s/\#export QT_PLUGIN_PATH/ export QT_PLUGIN_PATH/g" scripts/ost.in.pre > scripts/ost.in',shell=True,cwd='../../')
-subprocess.call('mv modules/scratch/qmean/scripts/qmean.in modules/scratch/qmean/scripts/qmean.in.backup',shell=True,cwd='../../')
-subprocess.call('sed "s/@PYTHON_BINARY@/\$DNG_ROOT\/bin\/'+name_python_bin+'/g" modules/scratch/qmean/scripts/qmean.in.backup > modules/scratch/qmean/scripts/qmean.in.prepreprepre',shell=True,cwd='../../')
-subprocess.call('sed "s/\#export LD_LIBRARY_PATH/ export LD_LIBRARY_PATH/g" modules/scratch/qmean/scripts/qmean.in.prepreprepre > modules/scratch/qmean/scripts/qmean.in.preprepre',shell=True,cwd='../../')
-subprocess.call('sed "s/\#export PYTHONHOME/ export PYTHONHOME/g" modules/scratch/qmean/scripts/qmean.in.preprepre > modules/scratch/qmean/scripts/qmean.in.prepre',shell=True,cwd='../../')
-subprocess.call('sed "s/\#export PYTHONPATH/ export PYTHONPATH/g" modules/scratch/qmean/scripts/qmean.in.prepre > modules/scratch/qmean/scripts/qmean.in.pre',shell=True,cwd='../../')
-subprocess.call('sed "s/\#export QT_PLUGIN_PATH/ export QT_PLUGIN_PATH/g" modules/scratch/qmean/scripts/qmean.in.pre > modules/scratch/qmean/scripts/qmean.in',shell=True,cwd='../../')
-subprocess.call('mv scripts/dng.in scripts/dng.in.backup',shell=True,cwd='../../')
-subprocess.call('sed "s/\#export LD_LIBRARY_PATH/ export LD_LIBRARY_PATH/g" scripts/dng.in.backup > scripts/dng.in.preprepre',shell=True,cwd='../../')
-subprocess.call('sed "s/\#export PYTHONHOME/ export PYTHONHOME/g" scripts/dng.in.preprepre > scripts/dng.in.prepre',shell=True,cwd='../../')
-subprocess.call('sed "s/\#export PYTHONPATH/ export PYTHONPATH/g" scripts/ost.in.prepre > scripts/ost.in.pre',shell=True,cwd='../../')
-subprocess.call('sed "s/\#export QT_PLUGIN_PATH/ export QT_PLUGIN_PATH/g" scripts/dng.in.pre > scripts/dng.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/Qmean'
-subprocess.call('cmake ./ -DCMAKE_BUILD_TYPE=Release -DPREFIX='+directory_name+' -DBoost_COMPILER='+boost_string+' -DONLY_QMEAN=ON -DENABLE_IMG=OFF -DENABLE_UI=OFF -DENABLE_GFX=OFF -DCOMPOUND_LIB=ChemLib/compounds.chemlib', shell=True,cwd='../../')
-subprocess.call('make',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'
-subprocess.call('cmake ./ -DCOMPOUND_LIB=compounds.chemlib',shell=True,cwd='../../')
-subprocess.call('make',shell=True,cwd='../../')
-print 'Removing obsolete packages and package directory'
-subprocess.call('rm -fr qmean-*',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='../../')
-so_list=[]
-print 'Creating new dependency 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 'Copy libraries in the package directory structure'
-subprocess.call('mkdir '+directory_name+'/'+libdir,shell=True,cwd='../../')
-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',shell=True,cwd='../../')
-print 'Copy python libraries into package directory structure'
-subprocess.call('cp -pRL '+system_python_libs+' '+directory_name+'/'+libdir,shell=True,cwd='../../')
-if second_system_python_libs_flag==True:
-  subprocess.call('cp -pRL '+second_system_python_libs+'/* '+directory_name+'/'+libdir+'/'+name_python_bin,shell=True,cwd='../../')
-print 'Copy Qt 4 plugins into package directory structure'
-subprocess.call('cp -pRL '+qt4_plugins+' '+directory_name+'/bin/',shell=True,cwd='../../')
-print 'Installing OpenStructure into package directory structure'
-subprocess.call('make install',shell=True,cwd='../../')
-print 'Copy examples into package directory structure'
-subprocess.call('cp -pRL  examples  '+directory_name+'/share/openstructure/',shell=True,cwd='../../')
-print 'Removing headers from package directory structure'
-subprocess.call('rm -fr   '+directory_name+'/include',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 'Copy qmean examples into package directory structure'
-subprocess.call('cp -pRL  modules/scratch/qmean/examples '+directory_name+'',shell=True,cwd='../../')
-print 'Copy readme and license files into package directory structure'
-subprocess.call('cp -pRL  modules/scratch/qmean/LICENSE.txt '+directory_name+'',shell=True,cwd='../../')
-subprocess.call('cp -pRL  modules/scratch/qmean/README.txt '+directory_name+'',shell=True,cwd='../../')
-print 'Resetting script to non-bundle versions'
-subprocess.call('rm scripts/ost.in',shell=True,cwd='../../')
-subprocess.call('rm scripts/ost.in.pre*',shell=True,cwd='../../')
-subprocess.call('rm scripts/dng.in',shell=True,cwd='../../')
-subprocess.call('rm modules/scratch/qmean/scripts/qmean.in',shell=True,cwd='../../')
-subprocess.call('rm modules/scratch/qmean/scripts/qmean.in.pre*',shell=True,cwd='../../')
-subprocess.call('rm scripts/dng.in.pre*',shell=True,cwd='../../')
-subprocess.call('mv scripts/ost.in.backup scripts/ost.in',shell=True,cwd='../../')
-subprocess.call('mv scripts/dng.in.backup scripts/dng.in',shell=True,cwd='../../')
-subprocess.call('mv modules/scratch/qmean/scripts/qmean.in.backup modules/scratch/qmean/scripts/qmean.in',shell=True,cwd='../../')
-subprocess.call('tar cfz '+directory_name+'.tgz '+directory_name,shell=True,cwd='../../')
-
diff --git a/deployment/linux/debian/README b/deployment/linux/debian/README
new file mode 100644
index 0000000000000000000000000000000000000000..c3a5a886f2754202845d533c5399e6eeb416ae86
--- /dev/null
+++ b/deployment/linux/debian/README
@@ -0,0 +1,8 @@
+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
new file mode 100644
index 0000000000000000000000000000000000000000..c6c09893537f7e95bd2a01b7fe343ed65798ecf3
--- /dev/null
+++ b/deployment/linux/debian/debian/README.source
@@ -0,0 +1,18 @@
+===============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
new file mode 100644
index 0000000000000000000000000000000000000000..9ecfb662316dd8c2d6a8e6ddcc17e4cf3573e526
--- /dev/null
+++ b/deployment/linux/debian/debian/changelog
@@ -0,0 +1,5 @@
+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
new file mode 100644
index 0000000000000000000000000000000000000000..7cbb4e805d2f7e52bf0ae16701d208cc5946fff1
--- /dev/null
+++ b/deployment/linux/debian/debian/chemdict_tool.1
@@ -0,0 +1,33 @@
+.\" 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
new file mode 100644
index 0000000000000000000000000000000000000000..7f8f011eb73d6043d2e6db9d2c101195ae2801f2
--- /dev/null
+++ b/deployment/linux/debian/debian/compat
@@ -0,0 +1 @@
+7
diff --git a/deployment/linux/debian/debian/control b/deployment/linux/debian/debian/control
new file mode 100644
index 0000000000000000000000000000000000000000..43a9f02fdda663dcf358819cf3bb92381c501311
--- /dev/null
+++ b/deployment/linux/debian/debian/control
@@ -0,0 +1,23 @@
+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
new file mode 100644
index 0000000000000000000000000000000000000000..b93d7503fb504646b3023bcc25817335d2579868
--- /dev/null
+++ b/deployment/linux/debian/debian/copyright
@@ -0,0 +1,40 @@
+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
new file mode 100644
index 0000000000000000000000000000000000000000..dbc68330d425affad81420e25645719ac07c8b24
--- /dev/null
+++ b/deployment/linux/debian/debian/dng.1
@@ -0,0 +1,39 @@
+.\" 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
new file mode 100644
index 0000000000000000000000000000000000000000..b5ae761af421073b92e3ce58fa0c5100417a3ae8
--- /dev/null
+++ b/deployment/linux/debian/debian/openstructure.desktop
@@ -0,0 +1,8 @@
+[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
new file mode 100644
index 0000000000000000000000000000000000000000..e73d09dbbec1bf1adaed4065f926ecbe8e872771
--- /dev/null
+++ b/deployment/linux/debian/debian/openstructure.manpages
@@ -0,0 +1,3 @@
+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
new file mode 100644
index 0000000000000000000000000000000000000000..afd5f75dcb8eadc27a09ecacb147138c3451ac7a
--- /dev/null
+++ b/deployment/linux/debian/debian/ost.1
@@ -0,0 +1,18 @@
+.\" 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
new file mode 100644
index 0000000000000000000000000000000000000000..a448189622f2efd26b94eb33f2759706a6d7bdbd
--- /dev/null
+++ b/deployment/linux/debian/debian/postinst
@@ -0,0 +1,40 @@
+#!/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
new file mode 100755
index 0000000000000000000000000000000000000000..7b9d18ba98b725099155c5f3d87a78f20e2cba5c
--- /dev/null
+++ b/deployment/linux/debian/debian/rules
@@ -0,0 +1,27 @@
+#!/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
new file mode 100644
index 0000000000000000000000000000000000000000..c3d9f2407417795889250717d7b519eadd8373e6
--- /dev/null
+++ b/deployment/linux/debian/debian/source/format
@@ -0,0 +1,2 @@
+3.0 (quilt)
+
diff --git a/deployment/linux/debian/debian/source/include-binaries b/deployment/linux/debian/debian/source/include-binaries
new file mode 100644
index 0000000000000000000000000000000000000000..e2a64033aea5f1dda66b509afe7ee03c8d40095e
--- /dev/null
+++ b/deployment/linux/debian/debian/source/include-binaries
@@ -0,0 +1 @@
+compounds.chemlib
diff --git a/deployment/linux/fedora/openstructure.desktop b/deployment/linux/fedora/openstructure.desktop
new file mode 100644
index 0000000000000000000000000000000000000000..5da5cfab6fa466c91de1e5be5cf5073448ad72dd
--- /dev/null
+++ b/deployment/linux/fedora/openstructure.desktop
@@ -0,0 +1,8 @@
+[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
new file mode 100644
index 0000000000000000000000000000000000000000..3d27b5deac2b8e299e1ab1406900a722347866be
--- /dev/null
+++ b/deployment/linux/fedora/openstructure.spec
@@ -0,0 +1,82 @@
+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
index bf030685da06e5b319b0af7964b7c3bec0948f82..6ac0809e34a767ff7ff16febd6d392b95e31861f 100644
--- a/deployment/linux/reset_repository.py
+++ b/deployment/linux/reset_repository.py
@@ -8,7 +8,6 @@ if currdir.find('deployment')==-1 or currdir.find('linux')==-1:
   print '\n'
   sys.exit()
 
-subprocess.call('rm -fr scripts/dng.in.pre* scripts/ost_cl.in.pre*',shell=True,cwd='../../')
-subprocess.call('mv scripts/ost.in.backup scripts/ost.in',shell=True,cwd='../../')
-subprocess.call('mv scripts/dng.in.backup scripts/dng.in',shell=True,cwd='../../')
+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/linux/reset_repository_qmean.py b/deployment/linux/reset_repository_qmean.py
deleted file mode 100644
index 93ab7c531ababb26dcb0daaf06332b69ccb71965..0000000000000000000000000000000000000000
--- a/deployment/linux/reset_repository_qmean.py
+++ /dev/null
@@ -1,14 +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/dng.in.pre* scripts/ost_cl.in.pre* modules/scratch/qmean/scripts/qmean.in.pre*',shell=True,cwd='../../')
-subprocess.call('mv scripts/ost.in.backup scripts/ost.in',shell=True,cwd='../../')
-subprocess.call('mv scripts/dng.in.backup scripts/dng.in',shell=True,cwd='../../')
-subprocess.call('mv modules/scratch/qmean/scripts/qmean.in.backup scripts/dng.in modules/scratch/qmean/scripts/qmean.in',shell=True,cwd='../../')
\ No newline at end of file
diff --git a/modules/base/pymod/wrap_base.cc b/modules/base/pymod/wrap_base.cc
index 1c305685bba1800c9f4b10d0efc42dcd5707b526..40ad33717f79c38e58c21624b87736f387016f3c 100644
--- a/modules/base/pymod/wrap_base.cc
+++ b/modules/base/pymod/wrap_base.cc
@@ -91,6 +91,7 @@ BOOST_PYTHON_MODULE(_ost_base)
   scope().attr("VERSION_MAJOR")=OST_VERSION_MAJOR;
   scope().attr("VERSION_MINOR")=OST_VERSION_MINOR;  
   scope().attr("VERSION_PATCH")=OST_VERSION_PATCH;
+  scope().attr("WITH_NUMPY")= OST_NUMPY_SUPPORT_ENABLED;
   export_Logger();
   export_Range();
   export_Units();
diff --git a/modules/config/CMakeLists.txt b/modules/config/CMakeLists.txt
index 65c9ca6bebf69a4def544c5c58dfc50be04ee98d..617aa51c5b87a2dc03b95d7a92730b097b31d371 100644
--- a/modules/config/CMakeLists.txt
+++ b/modules/config/CMakeLists.txt
@@ -1,3 +1,6 @@
+set(SUBST_DICT OST_VERSION_MAJOR=${OST_VERSION_MAJOR} OST_VERSION_MINOR=${OST_VERSION_MINOR} 
+    OST_VERSION_PATCH=${OST_VERSION_PATCH})
+
 set(OST_CONFIG_HEADERS
 base.hh
 config.hh
@@ -54,10 +57,17 @@ if (FFTW_USE_THREADS)
 else()
   set(fftw_use_threads 0)
 endif()
+if (_DEBIAN_STYLE_LIBEXEC)
+  set(debian_style_libexec 1)
+else()
+  set(debian_style_libexec 0)
+endif()
 
 set(config_hh_generator "CMake")
 set(CONFIG_HH_FILE "${CMAKE_CURRENT_SOURCE_DIR}/config.hh")
+set(VERSION_HH_FILE "${CMAKE_CURRENT_SOURCE_DIR}/version.hh")
 configure_file(config.hh.in ${CONFIG_HH_FILE})
+configure_file(version.hh.in ${VERSION_HH_FILE})
 add_custom_target(ost_config)
 stage_headers("${OST_CONFIG_HEADERS}" "ost" 
               "ost_config" "" "ost")
diff --git a/modules/config/config.hh.in b/modules/config/config.hh.in
index 88653c1e8df5bc5f75bf99dd6554c5a25c5ffaa6..a9e33adca707baed39710d3c75f63ca2b210bf0b 100644
--- a/modules/config/config.hh.in
+++ b/modules/config/config.hh.in
@@ -32,4 +32,6 @@
 #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@
+
 #endif
diff --git a/modules/config/version.hh b/modules/config/version.hh.in
similarity index 85%
rename from modules/config/version.hh
rename to modules/config/version.hh.in
index c2c019aed425009563f897d8c8ea9bd9e16a62f9..94948475f862b2876ccdd459638f8c781735f784 100644
--- a/modules/config/version.hh
+++ b/modules/config/version.hh.in
@@ -19,9 +19,9 @@
 #ifndef OST_VERSION_HH_
 #define OST_VERSION_HH_
 
-#define OST_VERSION_MAJOR 1
-#define OST_VERSION_MINOR 2
-#define OST_VERSION_PATCH 0
-#define OST_VERSION_STRING "1.2.0"
+#define OST_VERSION_MAJOR @OST_VERSION_MAJOR@
+#define OST_VERSION_MINOR @OST_VERSION_MINOR@
+#define OST_VERSION_PATCH @OST_VERSION_PATCH@
+#define OST_VERSION_STRING "@OST_VERSION_STRING@"
 
 #endif /* OST_VERSION_HH_ */
diff --git a/modules/conop/doc/cleanup.rst b/modules/conop/doc/cleanup.rst
new file mode 100644
index 0000000000000000000000000000000000000000..35b20e5705b248a995ec61c5e06604c53df0767f
--- /dev/null
+++ b/modules/conop/doc/cleanup.rst
@@ -0,0 +1,8 @@
+:mod:`conop.cleanup <ost.conop.cleanup>` -- Sanitize structures
+================================================================================
+
+.. module:: ost.conop.ceanup
+   :synopsis: Contains functions to sanitize (cleanup) structures by using 
+        information from the compound library.
+
+.. autofunction:: ost.conop.cleanup.Cleanup
\ No newline at end of file
diff --git a/modules/conop/doc/conop.rst b/modules/conop/doc/conop.rst
index 8c3f413469872a1d95f9da98e37f4e21ffb24bfc..fb72db2645a92ea70f3db4f686c0f33a35c7e956 100644
--- a/modules/conop/doc/conop.rst
+++ b/modules/conop/doc/conop.rst
@@ -20,3 +20,4 @@ In this module
  aminoacid
  connectivity
  compoundlib
+ cleanup
\ No newline at end of file
diff --git a/modules/conop/pymod/CMakeLists.txt b/modules/conop/pymod/CMakeLists.txt
index 5affa4b457d780b7368b34a097bec832d2c3f36c..97de72d7a52f1a74233a9782e746bd596620ffc7 100644
--- a/modules/conop/pymod/CMakeLists.txt
+++ b/modules/conop/pymod/CMakeLists.txt
@@ -7,4 +7,4 @@ set(OST_CONOP_PYMOD_SOURCES
   export_ring_finder.cc
 )
 
-pymod(NAME conop CPP ${OST_CONOP_PYMOD_SOURCES} PY __init__.py)
\ No newline at end of file
+pymod(NAME conop CPP ${OST_CONOP_PYMOD_SOURCES} PY __init__.py cleanup.py)
diff --git a/modules/conop/pymod/__init__.py b/modules/conop/pymod/__init__.py
index 44aaed354facbf286933d5e2ff19dd89bf7544e1..a534ea808bf883c616c7eb7165af5b71155fdc5b 100644
--- a/modules/conop/pymod/__init__.py
+++ b/modules/conop/pymod/__init__.py
@@ -18,6 +18,17 @@
 #------------------------------------------------------------------------------
 from _ost_conop import *
 
+# The 20 standard amino acids in no particular order
+STANDARD_AMINOACIDS=(
+ 'ALA', 'ARG', 'ASN',
+ 'ASP', 'GLN', 'GLU',
+ 'LYS', 'SER', 'CYS',
+ 'MET', 'TRP', 'TYR',
+ 'THR', 'VAL', 'ILE',
+ 'LEU', 'GLY', 'PRO',
+ 'HIS', 'PHE',
+)
+
 def ConnectAll(ent):
   '''
   Uses the current default builder to connect the atoms of the entity, assign 
diff --git a/modules/conop/pymod/cleanup.py b/modules/conop/pymod/cleanup.py
new file mode 100644
index 0000000000000000000000000000000000000000..9ecf9c7ef12b8bb4fce889a5fb8062aab2364eda
--- /dev/null
+++ b/modules/conop/pymod/cleanup.py
@@ -0,0 +1,167 @@
+from ost import conop, mol
+  
+def Cleanup(entity, strip_water=True, canonicalize=True, remove_ligands=True):
+  """
+  This function returns a cleaned-up (simplified) version of the protein
+  structure. Different parameters affect the behaviour of the function.
+
+  :param strip_water: Whether to remove water from the structure
+  :param canonicalize: Whether to strip off modifications of amino acids and map
+     them back to their parent standard amino acid, e.g. selenium methionine to
+     methionine.For more complex amino acids, where the relation between the
+     modified and the standard parent amino acid is not known, sidechain atoms
+     are removed. D-peptide-linking residues are completely removed as well.
+  :param remove_ligands: Whether to remove ligands from the structure
+
+  :return: a cleaned version of the entity
+  """
+  #setup
+  builder = conop.GetBuilder()
+  if not hasattr(builder, "compound_lib") :
+    raise RuntimeError( "Cannot cleanup structure, since the default builder doesn't use the compound library")
+  compound_lib = builder.compound_lib
+  clean_entity = entity.Copy()
+  ed = clean_entity.EditXCS()
+  #remove water residues
+  if strip_water:
+    _StripWater(clean_entity, ed)
+  #replace modified residues before removing ligands to avoid removing MSE and others
+  if canonicalize:
+    _CanonicalizeResidues(clean_entity, ed, compound_lib)
+  #remove all hetatoms that are not water
+  if remove_ligands:
+    _RemoveLigands(clean_entity, ed)
+  return clean_entity
+
+
+def _StripWater(clean_entity, ed) :
+  """
+  This function removes water residues from the structure
+  """
+  for res in clean_entity.residues:
+    if res.IsValid():
+      if res.chem_class == mol.WATER:
+        ed.DeleteResidue(res.handle)
+  ed.UpdateICS()
+  return
+  
+def _RemoveLigands(clean_entity, ed) :
+  """
+  This function removes ligands from the structure
+  """
+  for res in clean_entity.residues:
+    if res.IsValid():
+      #WHEN mmCIF WILL BE USED, CHANGE IsPeptideLinking() TO IsProtein()
+      if not res.IsPeptideLinking() and res.atoms[0].is_hetatom and res.chem_class != mol.WATER:
+        ed.DeleteResidue(res.handle)
+  ed.UpdateICS()
+  return
+  
+def _CanonicalizeResidues(clean_entity, ed, compound_lib) :
+  """
+  This function strips off modifications of amino acids and maps
+  them back to their parent standard amino acid, e.g. selenium methionine to
+  methionine.For more complex amino acids, where the relation between the 
+  modified and the standard parent amino acid is not known, sidechain atoms 
+  are removed. D-peptide-linking residues are completely removed as well.
+  """
+
+  for res in clean_entity.residues:
+    if res.IsValid() and res.IsPeptideLinking() :
+      parent_olc = res.one_letter_code
+      if parent_olc == "X" :
+        _DeleteSidechain(res, ed)
+        for atom in res.atoms:
+          atom.is_hetatom = False
+      else:
+        parent_tlc = conop.OneLetterCodeToResidueName(parent_olc)
+        parent_res = compound_lib.FindCompound(parent_tlc)
+        if not parent_res:
+          _DeleteSidechain(res, ed)
+          for atom in res.atoms:
+            atom.is_hetatom = False
+          print "Removing sidechain of %s, beacuse it has not been found in the compound library"% parent_tlc
+        else:
+          #collect atom's names
+          modif_atom_names = set([atom.name for atom in res.atoms
+                                                  if atom.element != "H" and atom.element != "D" ])
+          #if the res is the first or last take all the atoms from the parent res
+          if res.FindAtom("OXT").IsValid() :
+            parent_atom_names = set([atom.name for atom in parent_res.atom_specs
+                                                  if atom.element != "H" and atom.element != "D" ])
+          else:
+            parent_atom_names = set([atom.name for atom in parent_res.atom_specs
+                                                    if atom.element != "H" and atom.element != "D" and not atom.is_leaving ])
+          additional_parent_atoms = parent_atom_names - modif_atom_names
+          additional_modif_atoms = modif_atom_names - parent_atom_names
+          #WHEN mmCIF WILL BE USED, CHANGE IsPeptideLinking() TO IsProtein(), TO EXCLUDE LIGANDS FROM CANONICALISATION
+          if res.atoms[0].is_hetatom :
+            old_name = res.name
+            ed.RenameResidue(res, parent_tlc)
+            if additional_parent_atoms:
+              if additional_modif_atoms:
+                #replacement
+                _Replacement(res, ed, old_name)
+              else:
+                #deletion
+                _Deletion(res, ed)
+            elif additional_modif_atoms:
+              #addition
+              _Addition(res, ed, additional_modif_atoms)
+            else:
+              #unchanged, later check stereochemistry or H atoms
+              _Unchanged(res, ed)
+          #the res is a peptide but not a ligand (is a protein res)
+          else:
+            if additional_parent_atoms:# if the sidechain is incomplete
+              _DeleteSidechain(res, ed)
+  ed.UpdateICS()
+  return
+  
+def _Replacement(res, ed, old_name) :
+  #TEMP ONLY MSE
+  if old_name == "MSE" :
+    for atom in res.atoms:
+      atom.is_hetatom = False
+    sel = res.FindAtom("SE")
+    if sel.IsValid() :
+      ed.InsertAtom( res, "SD", sel.pos, "S", sel.occupancy, sel.b_factor ) #S radius=~1;SE=~1.2
+      ed.DeleteAtom( sel )
+    else:
+      _DeleteSidechain(res, ed)
+  else:
+    _DeleteSidechain(res, ed)
+  return
+  
+def _Deletion(res, ed) :
+  _DeleteSidechain(res, ed)
+  for atom in res.atoms :
+    atom.is_hetatom = False
+  return
+  
+def _Addition(res, ed, additional_modif_atoms) :
+  for add_atom_name in additional_modif_atoms:
+    add_atom = res.FindAtom( add_atom_name )
+    if add_atom.IsValid() :
+      ed.DeleteAtom( add_atom )
+  for atom in res.atoms:
+    atom.is_hetatom = False
+  return
+  
+def _Unchanged(res, ed) :
+  if res.chem_class == mol.D_PEPTIDE_LINKING:
+    ed.DeleteResidue(res)
+  else:
+    _DeleteSidechain(res, ed)
+    for atom in res.atoms :
+      atom.is_hetatom = False
+  return
+  
+def _DeleteSidechain(res, ed) :
+  for atom in res.atoms:
+    if not atom.name in ['CA','CB','C','N','O']:
+      ed.DeleteAtom(atom)
+  return
+  
+#visible functions
+__all__ = [Cleanup]
diff --git a/modules/conop/tests/CMakeLists.txt b/modules/conop/tests/CMakeLists.txt
index aa06791bf0be4d64640499010893d9db179f3e33..1af92df10be705d46354506d72df5c0c645be732 100644
--- a/modules/conop/tests/CMakeLists.txt
+++ b/modules/conop/tests/CMakeLists.txt
@@ -4,6 +4,7 @@ set(OST_CONOP_UNIT_TESTS
   tests.cc
   test_builder.cc
   test_compound.py
+  test_cleanup.py
 )
 
 ost_unittest(MODULE conop
diff --git a/modules/conop/tests/sample_noligands.pdb b/modules/conop/tests/sample_noligands.pdb
new file mode 100644
index 0000000000000000000000000000000000000000..7fd199276d45124bbe2b2bc6ddf7d47b780d9401
--- /dev/null
+++ b/modules/conop/tests/sample_noligands.pdb
@@ -0,0 +1,65 @@
+HETATM    1  N   MSE A   1      16.152  35.832  19.337  1.00 68.79           N
+ANISOU    1  N   MSE A   1     9680   7396   9061   1038   -716    -25       N
+HETATM    2  CA  MSE A   1      16.961  36.379  20.419  1.00 66.57           C
+ANISOU    2  CA  MSE A   1     9387   7212   8694   1121   -806     40       C
+HETATM    3  C   MSE A   1      18.345  36.796  19.931  1.00 62.52           C
+ANISOU    3  C   MSE A   1     8685   6846   8225   1266   -870   -107       C
+HETATM    4  O   MSE A   1      19.030  36.049  19.227  1.00 60.36           O
+ANISOU    4  O   MSE A   1     8358   6511   8064   1396   -922   -219       O
+HETATM    5  CB  MSE A   1      17.100  35.372  21.563  1.00 69.52           C
+ANISOU    5  CB  MSE A   1     9961   7405   9049   1204   -927    192       C
+HETATM    6  CG  MSE A   1      17.608  35.983  22.861  1.00 69.50           C
+ANISOU    6  CG  MSE A   1     9977   7515   8914   1239  -1006    292       C
+HETATM    7 SE   MSE A   1      16.174  36.321  24.145  0.70149.62          SE
+ANISOU    7 SE   MSE A   1    20306  17658  18883   1013   -917    492      SE
+HETATM    8  CE  MSE A   1      16.439  38.231  24.424  1.00101.32           C
+ANISOU    8  CE  MSE A   1    13992  11855  12651    950   -853    413       C
+ATOM      9  N   GLY A   2      21.960  55.913  14.093  1.00 32.26           N
+ANISOU    9  N   GLY A   2     3786   4717   3755   -417   -110   -697       N
+ATOM     10  CA  GLY A   2      21.067  57.037  14.316  1.00 33.47           C
+ANISOU   10  CA  GLY A   2     4071   4728   3919   -478    -95   -611       C
+ATOM     11  C   GLY A   2      20.632  57.066  15.769  1.00 28.81           C
+ANISOU   11  C   GLY A   2     3536   4062   3349   -382   -126   -599       C
+ATOM     12  O   GLY A   2      19.474  57.360  16.089  1.00 26.62           O
+ANISOU   12  O   GLY A   2     3358   3653   3104   -343   -120   -528       O
+HETATM  694  N   MLY A   3      26.382  48.690   2.460  1.00 30.43           N
+ANISOU  694  N   MLY A   3     2388   5919   3254   -646    317  -1852       N
+HETATM  695  CA  MLY A   3      27.776  48.333   2.142  1.00 32.62           C
+ANISOU  695  CA  MLY A   3     2438   6444   3514   -645    358  -2093       C
+HETATM  696  CB  MLY A   3      28.523  49.535   1.556  1.00 34.25           C
+ANISOU  696  CB  MLY A   3     2578   6874   3563   -918    442  -2107       C
+HETATM  697  CG  MLY A   3      28.053  50.058   0.208  1.00 51.47           C
+ANISOU  697  CG  MLY A   3     4819   9152   5586  -1157    527  -2046       C
+HETATM  698  CD  MLY A   3      29.170  50.911  -0.420  1.00 65.96           C
+ANISOU  698  CD  MLY A   3     6527  11268   7265  -1416    622  -2140       C
+HETATM  699  CE  MLY A   3      28.648  51.881  -1.478  1.00 78.91           C
+ANISOU  699  CE  MLY A   3     8300  12955   8728  -1697    684  -1985       C
+HETATM  700  NZ  MLY A   3      27.996  53.093  -0.885  1.00 83.04           N
+ANISOU  700  NZ  MLY A   3     9040  13267   9244  -1780    633  -1724       N
+HETATM  701  CH1 MLY A   3      27.490  53.898  -2.008  1.00 82.17           C
+ANISOU  701  CH1 MLY A   3     9059  13197   8964  -2028    679  -1578       C
+HETATM  702  CH2 MLY A   3      29.059  53.885  -0.248  1.00 83.95           C
+ANISOU  702  CH2 MLY A   3     9084  13473   9342  -1885    652  -1769       C
+HETATM  703  C   MLY A   3      28.551  47.875   3.386  1.00 35.38           C
+ANISOU  703  C   MLY A   3     2698   6760   3986   -436    275  -2175       C
+HETATM  704  O   MLY A   3      29.262  46.867   3.369  1.00 36.09           O
+ANISOU  704  O   MLY A   3     2632   6928   4151   -274    255  -2373       O
+HETATM   24  N   DHA A   4      26.289  27.329   2.438  1.00 21.02           N
+HETATM   25  CA  DHA A   4      26.295  27.688   3.823  1.00 20.17           C
+HETATM   26  CB  DHA A   4      27.128  28.481   4.578  1.00 25.40           C
+HETATM   27  C   DHA A   4      25.128  27.215   4.536  1.00 14.98           C
+HETATM   28  O   DHA A   4      24.918  27.318   5.770  1.00 15.17           O
+ATOM   1454  N   CYS A   5      35.381  45.298  39.476  1.00 31.23           N
+ATOM   1455  CA  CYS A   5      35.559  43.873  39.703  1.00 26.90           C
+ATOM   1456  C   CYS A   5      34.291  43.354  40.319  1.00 28.31           C
+ATOM   1457  OXT CYS A   5      33.569  44.119  40.933  1.00 32.71           O
+ATOM   1458  CB  CYS A   5      36.760  43.592  40.596  1.00 27.44           C
+ATOM   1460  H   CYS A   5      34.717  45.766  40.024  1.00  0.00           H
+HETATM 1345  N   DAL A   6      16.130  53.915  24.417  1.00  8.63           N
+HETATM 1346  CA  DAL A   6      16.958  55.083  24.235  1.00 24.17           C
+HETATM 1347  CB  DAL A   6      16.321  56.394  24.733  1.00 30.20           C
+HETATM 1348  C   DAL A   6      17.335  55.218  22.790  1.00 32.54           C
+HETATM 1349  O   DAL A   6      16.693  54.552  21.946  1.00 27.41           O
+HETATM 1350  OXT DAL A   6      18.286  55.960  22.546  1.00 18.81           O
+HETATM   36  O   HOH A  19       0.180  48.781   4.764  1.00 23.28           O
+END
diff --git a/modules/conop/tests/sample_nowater.pdb b/modules/conop/tests/sample_nowater.pdb
new file mode 100644
index 0000000000000000000000000000000000000000..0f8c440aa83c10dec2cfffe71cbe524a15d0af15
--- /dev/null
+++ b/modules/conop/tests/sample_nowater.pdb
@@ -0,0 +1,71 @@
+HETATM    1  N   MSE A   1      16.152  35.832  19.337  1.00 68.79           N
+ANISOU    1  N   MSE A   1     9680   7396   9061   1038   -716    -25       N
+HETATM    2  CA  MSE A   1      16.961  36.379  20.419  1.00 66.57           C
+ANISOU    2  CA  MSE A   1     9387   7212   8694   1121   -806     40       C
+HETATM    3  C   MSE A   1      18.345  36.796  19.931  1.00 62.52           C
+ANISOU    3  C   MSE A   1     8685   6846   8225   1266   -870   -107       C
+HETATM    4  O   MSE A   1      19.030  36.049  19.227  1.00 60.36           O
+ANISOU    4  O   MSE A   1     8358   6511   8064   1396   -922   -219       O
+HETATM    5  CB  MSE A   1      17.100  35.372  21.563  1.00 69.52           C
+ANISOU    5  CB  MSE A   1     9961   7405   9049   1204   -927    192       C
+HETATM    6  CG  MSE A   1      17.608  35.983  22.861  1.00 69.50           C
+ANISOU    6  CG  MSE A   1     9977   7515   8914   1239  -1006    292       C
+HETATM    7 SE   MSE A   1      16.174  36.321  24.145  0.70149.62          SE
+ANISOU    7 SE   MSE A   1    20306  17658  18883   1013   -917    492      SE
+HETATM    8  CE  MSE A   1      16.439  38.231  24.424  1.00101.32           C
+ANISOU    8  CE  MSE A   1    13992  11855  12651    950   -853    413       C
+ATOM      9  N   GLY A   2      21.960  55.913  14.093  1.00 32.26           N
+ANISOU    9  N   GLY A   2     3786   4717   3755   -417   -110   -697       N
+ATOM     10  CA  GLY A   2      21.067  57.037  14.316  1.00 33.47           C
+ANISOU   10  CA  GLY A   2     4071   4728   3919   -478    -95   -611       C
+ATOM     11  C   GLY A   2      20.632  57.066  15.769  1.00 28.81           C
+ANISOU   11  C   GLY A   2     3536   4062   3349   -382   -126   -599       C
+ATOM     12  O   GLY A   2      19.474  57.360  16.089  1.00 26.62           O
+ANISOU   12  O   GLY A   2     3358   3653   3104   -343   -120   -528       O
+HETATM  694  N   MLY A   3      26.382  48.690   2.460  1.00 30.43           N
+ANISOU  694  N   MLY A   3     2388   5919   3254   -646    317  -1852       N
+HETATM  695  CA  MLY A   3      27.776  48.333   2.142  1.00 32.62           C
+ANISOU  695  CA  MLY A   3     2438   6444   3514   -645    358  -2093       C
+HETATM  696  CB  MLY A   3      28.523  49.535   1.556  1.00 34.25           C
+ANISOU  696  CB  MLY A   3     2578   6874   3563   -918    442  -2107       C
+HETATM  697  CG  MLY A   3      28.053  50.058   0.208  1.00 51.47           C
+ANISOU  697  CG  MLY A   3     4819   9152   5586  -1157    527  -2046       C
+HETATM  698  CD  MLY A   3      29.170  50.911  -0.420  1.00 65.96           C
+ANISOU  698  CD  MLY A   3     6527  11268   7265  -1416    622  -2140       C
+HETATM  699  CE  MLY A   3      28.648  51.881  -1.478  1.00 78.91           C
+ANISOU  699  CE  MLY A   3     8300  12955   8728  -1697    684  -1985       C
+HETATM  700  NZ  MLY A   3      27.996  53.093  -0.885  1.00 83.04           N
+ANISOU  700  NZ  MLY A   3     9040  13267   9244  -1780    633  -1724       N
+HETATM  701  CH1 MLY A   3      27.490  53.898  -2.008  1.00 82.17           C
+ANISOU  701  CH1 MLY A   3     9059  13197   8964  -2028    679  -1578       C
+HETATM  702  CH2 MLY A   3      29.059  53.885  -0.248  1.00 83.95           C
+ANISOU  702  CH2 MLY A   3     9084  13473   9342  -1885    652  -1769       C
+HETATM  703  C   MLY A   3      28.551  47.875   3.386  1.00 35.38           C
+ANISOU  703  C   MLY A   3     2698   6760   3986   -436    275  -2175       C
+HETATM  704  O   MLY A   3      29.262  46.867   3.369  1.00 36.09           O
+ANISOU  704  O   MLY A   3     2632   6928   4151   -274    255  -2373       O
+HETATM   24  N   DHA A   4      26.289  27.329   2.438  1.00 21.02           N
+HETATM   25  CA  DHA A   4      26.295  27.688   3.823  1.00 20.17           C
+HETATM   26  CB  DHA A   4      27.128  28.481   4.578  1.00 25.40           C
+HETATM   27  C   DHA A   4      25.128  27.215   4.536  1.00 14.98           C
+HETATM   28  O   DHA A   4      24.918  27.318   5.770  1.00 15.17           O
+ATOM   1454  N   CYS A   5      35.381  45.298  39.476  1.00 31.23           N
+ATOM   1455  CA  CYS A   5      35.559  43.873  39.703  1.00 26.90           C
+ATOM   1456  C   CYS A   5      34.291  43.354  40.319  1.00 28.31           C
+ATOM   1457  OXT CYS A   5      33.569  44.119  40.933  1.00 32.71           O
+ATOM   1458  CB  CYS A   5      36.760  43.592  40.596  1.00 27.44           C
+ATOM   1460  H   CYS A   5      34.717  45.766  40.024  1.00  0.00           H
+HETATM 1345  N   DAL A   6      16.130  53.915  24.417  1.00  8.63           N
+HETATM 1346  CA  DAL A   6      16.958  55.083  24.235  1.00 24.17           C
+HETATM 1347  CB  DAL A   6      16.321  56.394  24.733  1.00 30.20           C
+HETATM 1348  C   DAL A   6      17.335  55.218  22.790  1.00 32.54           C
+HETATM 1349  O   DAL A   6      16.693  54.552  21.946  1.00 27.41           O
+HETATM 1350  OXT DAL A   6      18.286  55.960  22.546  1.00 18.81           O
+HETATM   29  C1  GOL A  17       3.793  59.768   8.209  1.00 31.00           C
+HETATM   30  O1  GOL A  17       3.244  58.473   8.337  1.00 27.42           O
+HETATM   31  C2  GOL A  17       4.701  60.020   9.406  1.00 26.81           C
+HETATM   32  O2  GOL A  17       5.573  58.919   9.512  1.00 26.44           O
+HETATM   33  C3  GOL A  17       5.505  61.287   9.156  1.00 24.74           C
+HETATM   34  O3  GOL A  17       6.429  61.468  10.222  1.00 31.06           O
+HETATM   35 CL    CL A  18      11.844  59.221  16.755  0.79 32.84          CL
+END
diff --git a/modules/conop/tests/sample_test_cleanup.pdb b/modules/conop/tests/sample_test_cleanup.pdb
new file mode 100644
index 0000000000000000000000000000000000000000..cce7fe04d4fe753d68c9e73620fea8617ce07059
--- /dev/null
+++ b/modules/conop/tests/sample_test_cleanup.pdb
@@ -0,0 +1,72 @@
+HETATM    1  N   MSE A   1      16.152  35.832  19.337  1.00 68.79           N
+ANISOU    1  N   MSE A   1     9680   7396   9061   1038   -716    -25       N
+HETATM    2  CA  MSE A   1      16.961  36.379  20.419  1.00 66.57           C
+ANISOU    2  CA  MSE A   1     9387   7212   8694   1121   -806     40       C
+HETATM    3  C   MSE A   1      18.345  36.796  19.931  1.00 62.52           C
+ANISOU    3  C   MSE A   1     8685   6846   8225   1266   -870   -107       C
+HETATM    4  O   MSE A   1      19.030  36.049  19.227  1.00 60.36           O
+ANISOU    4  O   MSE A   1     8358   6511   8064   1396   -922   -219       O
+HETATM    5  CB  MSE A   1      17.100  35.372  21.563  1.00 69.52           C
+ANISOU    5  CB  MSE A   1     9961   7405   9049   1204   -927    192       C
+HETATM    6  CG  MSE A   1      17.608  35.983  22.861  1.00 69.50           C
+ANISOU    6  CG  MSE A   1     9977   7515   8914   1239  -1006    292       C
+HETATM    7 SE   MSE A   1      16.174  36.321  24.145  0.70149.62          SE
+ANISOU    7 SE   MSE A   1    20306  17658  18883   1013   -917    492      SE
+HETATM    8  CE  MSE A   1      16.439  38.231  24.424  1.00101.32           C
+ANISOU    8  CE  MSE A   1    13992  11855  12651    950   -853    413       C
+ATOM      9  N   GLY A   2      21.960  55.913  14.093  1.00 32.26           N
+ANISOU    9  N   GLY A   2     3786   4717   3755   -417   -110   -697       N
+ATOM     10  CA  GLY A   2      21.067  57.037  14.316  1.00 33.47           C
+ANISOU   10  CA  GLY A   2     4071   4728   3919   -478    -95   -611       C
+ATOM     11  C   GLY A   2      20.632  57.066  15.769  1.00 28.81           C
+ANISOU   11  C   GLY A   2     3536   4062   3349   -382   -126   -599       C
+ATOM     12  O   GLY A   2      19.474  57.360  16.089  1.00 26.62           O
+ANISOU   12  O   GLY A   2     3358   3653   3104   -343   -120   -528       O
+HETATM  694  N   MLY A   3      26.382  48.690   2.460  1.00 30.43           N
+ANISOU  694  N   MLY A   3     2388   5919   3254   -646    317  -1852       N
+HETATM  695  CA  MLY A   3      27.776  48.333   2.142  1.00 32.62           C
+ANISOU  695  CA  MLY A   3     2438   6444   3514   -645    358  -2093       C
+HETATM  696  CB  MLY A   3      28.523  49.535   1.556  1.00 34.25           C
+ANISOU  696  CB  MLY A   3     2578   6874   3563   -918    442  -2107       C
+HETATM  697  CG  MLY A   3      28.053  50.058   0.208  1.00 51.47           C
+ANISOU  697  CG  MLY A   3     4819   9152   5586  -1157    527  -2046       C
+HETATM  698  CD  MLY A   3      29.170  50.911  -0.420  1.00 65.96           C
+ANISOU  698  CD  MLY A   3     6527  11268   7265  -1416    622  -2140       C
+HETATM  699  CE  MLY A   3      28.648  51.881  -1.478  1.00 78.91           C
+ANISOU  699  CE  MLY A   3     8300  12955   8728  -1697    684  -1985       C
+HETATM  700  NZ  MLY A   3      27.996  53.093  -0.885  1.00 83.04           N
+ANISOU  700  NZ  MLY A   3     9040  13267   9244  -1780    633  -1724       N
+HETATM  701  CH1 MLY A   3      27.490  53.898  -2.008  1.00 82.17           C
+ANISOU  701  CH1 MLY A   3     9059  13197   8964  -2028    679  -1578       C
+HETATM  702  CH2 MLY A   3      29.059  53.885  -0.248  1.00 83.95           C
+ANISOU  702  CH2 MLY A   3     9084  13473   9342  -1885    652  -1769       C
+HETATM  703  C   MLY A   3      28.551  47.875   3.386  1.00 35.38           C
+ANISOU  703  C   MLY A   3     2698   6760   3986   -436    275  -2175       C
+HETATM  704  O   MLY A   3      29.262  46.867   3.369  1.00 36.09           O
+ANISOU  704  O   MLY A   3     2632   6928   4151   -274    255  -2373       O
+HETATM   24  N   DHA A   4      26.289  27.329   2.438  1.00 21.02           N
+HETATM   25  CA  DHA A   4      26.295  27.688   3.823  1.00 20.17           C
+HETATM   26  CB  DHA A   4      27.128  28.481   4.578  1.00 25.40           C
+HETATM   27  C   DHA A   4      25.128  27.215   4.536  1.00 14.98           C
+HETATM   28  O   DHA A   4      24.918  27.318   5.770  1.00 15.17           O
+ATOM   1454  N   CYS A   5      35.381  45.298  39.476  1.00 31.23           N
+ATOM   1455  CA  CYS A   5      35.559  43.873  39.703  1.00 26.90           C
+ATOM   1456  C   CYS A   5      34.291  43.354  40.319  1.00 28.31           C
+ATOM   1457  OXT CYS A   5      33.569  44.119  40.933  1.00 32.71           O
+ATOM   1458  CB  CYS A   5      36.760  43.592  40.596  1.00 27.44           C
+ATOM   1460  H   CYS A   5      34.717  45.766  40.024  1.00  0.00           H
+HETATM 1345  N   DAL A   6      16.130  53.915  24.417  1.00  8.63           N
+HETATM 1346  CA  DAL A   6      16.958  55.083  24.235  1.00 24.17           C
+HETATM 1347  CB  DAL A   6      16.321  56.394  24.733  1.00 30.20           C
+HETATM 1348  C   DAL A   6      17.335  55.218  22.790  1.00 32.54           C
+HETATM 1349  O   DAL A   6      16.693  54.552  21.946  1.00 27.41           O
+HETATM 1350  OXT DAL A   6      18.286  55.960  22.546  1.00 18.81           O
+HETATM   29  C1  GOL A  17       3.793  59.768   8.209  1.00 31.00           C
+HETATM   30  O1  GOL A  17       3.244  58.473   8.337  1.00 27.42           O
+HETATM   31  C2  GOL A  17       4.701  60.020   9.406  1.00 26.81           C
+HETATM   32  O2  GOL A  17       5.573  58.919   9.512  1.00 26.44           O
+HETATM   33  C3  GOL A  17       5.505  61.287   9.156  1.00 24.74           C
+HETATM   34  O3  GOL A  17       6.429  61.468  10.222  1.00 31.06           O
+HETATM   35 CL    CL A  18      11.844  59.221  16.755  0.79 32.84          CL
+HETATM   36  O   HOH A  19       0.180  48.781   4.764  1.00 23.28           O
+END
diff --git a/modules/conop/tests/test_cleanup.py b/modules/conop/tests/test_cleanup.py
new file mode 100644
index 0000000000000000000000000000000000000000..ee6ab57cae413a550e1cc6abdbc7875a1d7d3210
--- /dev/null
+++ b/modules/conop/tests/test_cleanup.py
@@ -0,0 +1,162 @@
+import unittest
+from ost import geom, conop
+from ost.conop import cleanup
+
+class TestCleanUp(unittest.TestCase):
+
+  def setUp(self):
+    self.comp_lib=conop.GetBuilder().compound_lib
+    self.ent = io.LoadPDB("sample_test_cleanup.pdb")
+    self.ent_no_wat = io.LoadPDB("sample_nowater.pdb")
+    self.ent_no_lig = io.LoadPDB("sample_noligands.pdb")
+
+  def testStripWater(self):
+    self.new_ent = cleanup.Cleanup(self.ent, strip_water=True, canonicalize=False, remove_ligands=False)
+    self.assertEqual( self.new_ent.residue_count, self.ent_no_wat.residue_count )
+    self.assertTrue( self.new_ent.residues[0].IsValid() )
+    self.assertEqual( self.new_ent.residues[0].qualified_name, self.ent_no_wat.residues[0].qualified_name)
+    self.assertTrue( self.new_ent.residues[1].IsValid() )
+    self.assertEqual( self.new_ent.residues[1].qualified_name, self.ent_no_wat.residues[1].qualified_name)
+    self.assertTrue( self.new_ent.residues[2].IsValid() )
+    self.assertEqual( self.new_ent.residues[2].qualified_name, self.ent_no_wat.residues[2].qualified_name)
+    self.assertTrue( self.new_ent.residues[3].IsValid() )
+    self.assertEqual( self.new_ent.residues[3].qualified_name, self.ent_no_wat.residues[3].qualified_name)
+    self.assertTrue( self.new_ent.residues[4].IsValid() )
+    self.assertEqual( self.new_ent.residues[4].qualified_name, self.ent_no_wat.residues[4].qualified_name)
+    self.assertTrue( self.new_ent.residues[5].IsValid() )
+    self.assertEqual( self.new_ent.residues[5].qualified_name, self.ent_no_wat.residues[5].qualified_name)
+    self.assertTrue( self.new_ent.residues[6].IsValid() )
+    self.assertEqual( self.new_ent.residues[6].qualified_name, self.ent_no_wat.residues[6].qualified_name)
+    self.assertTrue( self.new_ent.residues[7].IsValid() )
+    self.assertEqual( self.new_ent.residues[7].qualified_name, self.ent_no_wat.residues[7].qualified_name)
+
+  def testCanonicalize(self):
+    self.new_ent = cleanup.Cleanup(self.ent, strip_water=False, canonicalize=True, remove_ligands=False)
+    #standard residue must be the same
+    self.gly = self.ent.residues[1]
+    self.new_gly = self.new_ent.residues[1]
+    self.assertTrue(self.new_gly.IsValid())
+    self.assertTrue(self.new_gly.IsPeptideLinking())
+    self.assertEqual(self.gly.atom_count, self.new_gly.atom_count)
+    #TEMP del sidechain of incomplete residue and OXT if present
+    self.new_cys = self.new_ent.residues[4]
+    self.new_cys_atoms = set([atm.name for atm in self.new_cys.atoms])
+    self.assertEqual( len(self.new_cys_atoms), 4, msg = repr(self.new_cys_atoms))
+    self.assertTrue( "CB" in self.new_cys_atoms)
+    self.assertTrue( "CA" in self.new_cys_atoms)
+    self.assertTrue( "C" in self.new_cys_atoms)
+    self.assertFalse( "OXT" in self.new_cys_atoms)
+    self.assertTrue( "N" in self.new_cys_atoms)
+    #test replacement of atoms
+    self.mse = self.ent.residues[0]
+#    self.assertTrue( self.mse.IsValid())
+#    self.assertTrue( self.mse.IsPeptideLinking())
+    self.sel = self.mse.FindAtom("SE")
+#    self.assertTrue( self.sel.IsValid())
+    self.met = self.new_ent.residues[0]
+    self.assertTrue(self.met.IsValid())
+    self.assertEqual(self.mse.atom_count, self.met.atom_count)
+    self.assertEqual(self.met.name, "MET")
+    self.assertEqual(self.met.one_letter_code, "M")
+    self.assertTrue(self.met.IsPeptideLinking())
+    self.sul = self.met.FindAtom("SD")
+    self.assertTrue(self.sul.IsValid())
+    self.assertTrue(geom.Equal(self.sul.pos,self.sel.pos), msg = "sul:%s sel:%s"%(str(self.sul.pos), str(self.sel.pos)) )
+    self.assertEqual(self.sul.element, "S")
+#    self.AssertTrue( sul.mass == conop.Conopology.Instance().GetDefaultAtomMass("S"))
+#    self.AssertTrue( sul.radius == conop.Conopology.Instance().GetDefaultAtomRadius("S"))
+    for atm in self.met.atoms:
+      self.assertFalse( atm.is_hetatom)
+    #test addition
+    self.mly = self.ent.residues[2]
+#    self.assertTrue( self.mly.IsValid())
+#    self.assertTrue( self.mly.IsPeptideLinking())
+    self.new_lys = self.new_ent.residues[2]
+    self.assertTrue(self.new_lys.IsValid())
+    self.assertTrue(self.new_lys.IsPeptideLinking())
+    self.assertEqual(self.new_lys.name, "LYS")
+    self.assertEqual(self.new_lys.one_letter_code, "K")
+    self.new_lys_atoms = set([atm.name for atm in self.new_lys.atoms])
+    self.canon_lys = self.comp_lib.FindCompound("LYS")
+    self.canon_lys_atoms = set([atom.name for atom in self.canon_lys.atom_specs
+                                             if atom.element != "H" and atom.element != "D"  and not atom.is_leaving ])
+    self.assertEqual(self.canon_lys_atoms, self.new_lys_atoms)
+    self.assertFalse(self.canon_lys_atoms - self.new_lys_atoms)
+    self.assertFalse(self.new_lys_atoms - self.canon_lys_atoms) #test the reverse
+    for atm in self.new_lys.atoms:
+      self.assertFalse( atm.is_hetatom)
+    #deletions
+    self.dha = self.ent.residues[3]
+#    self.assertTrue( self.dha.IsValid())
+#    self.assertTrue( self.dha.IsPeptideLinking())
+    self.new_ser = self.new_ent.residues[3]
+    self.assertTrue(self.new_ser.IsValid())
+    self.assertTrue(self.new_ser.IsPeptideLinking())
+    self.assertEqual(self.new_ser.name, "SER")
+    self.assertEqual(self.new_ser.one_letter_code, "S")
+    self.new_ser_atoms = set([atm.name for atm in self.new_ser.atoms])
+    self.canon_ser = self.comp_lib.FindCompound("SER")
+    self.canon_ser_atoms = set([atom.name for atom in self.canon_ser.atom_specs
+                                             if atom.element != "H" and atom.element != "D"  and not atom.is_leaving ])
+    #TEMP
+    self.assertEqual( len(self.new_ser_atoms), 5)
+    self.assertTrue( "CB" in self.new_ser_atoms)
+    self.assertTrue( "CA" in self.new_ser_atoms)
+    self.assertTrue( "C" in self.new_ser_atoms)
+    self.assertTrue( "O" in self.new_ser_atoms)
+    self.assertTrue( "N" in self.new_ser_atoms)
+    #AFTER TEMP
+    #self.assertEqual( self.canon_ser_atoms, self.new_ser_atoms)
+    #self.assertFalse(self.canon_ser_atoms - self.new_ser_atoms)
+    #self.assertFalse(self.new_ser_atoms - self.canon_ser_atoms) #test the reverse
+    for atm in self.new_ser.atoms:
+      self.assertFalse( atm.is_hetatom)
+    #test deletion of whole residue
+    self.assertEqual(self.ent.residues[5].chem_class, "D_PEPTIDE_LINKING")
+    self.assertNotEqual(self.new_ent.residues[5].name, "DAL")
+    self.assertNotEqual(self.ent.residue_count, self.new_ent.residue_count)
+
+  def testRemoveLigands(self):
+    self.new_ent = cleanup.Cleanup(self.ent, strip_water=False, canonicalize=False, remove_ligands=True)
+    self.assertEqual(self.new_ent.residue_count, self.ent_no_lig.residue_count )
+    #MSE
+    self.assertTrue(self.new_ent.residues[0].IsValid() )
+    self.assertEqual(self.new_ent.residues[0].qualified_name, self.ent_no_lig.residues[0].qualified_name)
+    self.assertTrue(self.new_ent.residues[0].IsPeptideLinking())
+    self.assertTrue(self.new_ent.residues[0].atoms[0].is_hetatom)
+    #GLY
+    self.assertTrue(self.new_ent.residues[1].IsValid() )
+    self.assertEqual(self.new_ent.residues[1].qualified_name, self.ent_no_lig.residues[1].qualified_name)
+    self.assertTrue(self.new_ent.residues[1].IsPeptideLinking())
+    self.assertFalse(self.new_ent.residues[1].atoms[0].is_hetatom)
+    #MLY
+    self.assertTrue(self.new_ent.residues[2].IsValid() )
+    self.assertEqual(self.new_ent.residues[2].qualified_name, self.ent_no_lig.residues[2].qualified_name)
+    self.assertTrue(self.new_ent.residues[2].IsPeptideLinking())
+    self.assertTrue(self.new_ent.residues[2].atoms[0].is_hetatom)
+    #DHA
+    self.assertTrue(self.new_ent.residues[3].IsValid() )
+    self.assertEqual(self.new_ent.residues[3].qualified_name, self.ent_no_lig.residues[3].qualified_name)
+    self.assertTrue(self.new_ent.residues[3].IsPeptideLinking())
+    self.assertTrue(self.new_ent.residues[3].atoms[0].is_hetatom)
+    #CYS
+    self.assertTrue(self.new_ent.residues[4].IsValid() )
+    self.assertEqual(self.new_ent.residues[4].qualified_name, self.ent_no_lig.residues[4].qualified_name)
+    self.assertTrue(self.new_ent.residues[4].IsPeptideLinking())
+    self.assertFalse(self.new_ent.residues[4].atoms[0].is_hetatom)
+    #DAL
+    self.assertTrue(self.new_ent.residues[5].IsValid() )
+    self.assertEqual(self.new_ent.residues[5].qualified_name, self.ent_no_lig.residues[5].qualified_name)
+    self.assertTrue(self.new_ent.residues[5].IsPeptideLinking())
+    self.assertTrue(self.new_ent.residues[5].atoms[0].is_hetatom)
+    #HOH
+    self.assertTrue(self.new_ent.residues[6].IsValid() )
+    self.assertEqual(self.new_ent.residues[6].qualified_name, self.ent_no_lig.residues[6].qualified_name)
+    self.assertFalse(self.new_ent.residues[6].IsPeptideLinking()) # here assertFalse instead of assertTrue
+    self.assertTrue(self.new_ent.residues[6].atoms[0].is_hetatom)
+
+if not hasattr(conop.GetBuilder(), 'compound_lib'):
+  print 'Default builder without compound lib. Ignoring test_cleanup.py tests'
+  sys.exit()
+suite = unittest.TestLoader().loadTestsFromTestCase(TestCleanUp)
+unittest.TextTestRunner().run(suite)
diff --git a/modules/geom/pymod/export_mat2.cc b/modules/geom/pymod/export_mat2.cc
index fa1e382c9c62b7bc7ef789303d41cc88bcca6316..8905a47466622acc71b60f69ad1210dd11a06cba 100644
--- a/modules/geom/pymod/export_mat2.cc
+++ b/modules/geom/pymod/export_mat2.cc
@@ -33,6 +33,16 @@ String mat2_repr(const geom::Mat2& m) {
      << m(1,0) << ", " << m(1,1) << ")";
   return ss.str();
 }
+
+list mat2_data(const geom::Mat2& m)
+{
+  list nrvo;
+  for(size_t k=0;k<4;++k) {
+    nrvo.append(m.Data()[k]);
+  }
+  return nrvo;
+}
+
 void export_Mat2()
 {
   using namespace geom;
@@ -54,5 +64,6 @@ void export_Mat2()
     .def(self_ns::str(self))
     .def("__getitem__",Mat2_getitem)
     .def("__setitem__",Mat2_setitem)
+    .add_property("data",mat2_data)
   ;
 }
diff --git a/modules/geom/pymod/export_mat3.cc b/modules/geom/pymod/export_mat3.cc
index 4d86381a4db04b747f6834f6e56d5b3890c0de3c..bf92d2e4e5c11f34ad692953f913902237206c4d 100644
--- a/modules/geom/pymod/export_mat3.cc
+++ b/modules/geom/pymod/export_mat3.cc
@@ -63,6 +63,14 @@ String mat3_repr(const geom::Mat3& m)
   return ss.str();
 }
 
+list mat3_data(const geom::Mat3& m)
+{
+  list nrvo;
+  for(size_t k=0;k<9;++k) {
+    nrvo.append(m.Data()[k]);
+  }
+  return nrvo;
+}
 
 void export_Mat3()
 {
@@ -88,6 +96,7 @@ void export_Mat3()
     .def("__setitem__",Mat3_setitem)
     .def("__setitem__",Mat3_setslice)
     .def("GetCol", &Mat3::GetCol)
-    .def("GetRow", &Mat3::GetRow)    
+    .def("GetRow", &Mat3::GetRow)
+    .add_property("data",mat3_data)
   ;
 }
diff --git a/modules/geom/pymod/export_mat4.cc b/modules/geom/pymod/export_mat4.cc
index 7a5805dc6c45305fcebc5742428065d9d49f2afe..3bb555b2cfe0783346c0cf3de9a3c1626dc7fa36 100644
--- a/modules/geom/pymod/export_mat4.cc
+++ b/modules/geom/pymod/export_mat4.cc
@@ -85,6 +85,14 @@ String mat4_repr(const geom::Mat4& m) {
   return ss.str();
 }
 
+list mat4_data(const geom::Mat4& m)
+{
+  list nrvo;
+  for(size_t k=0;k<16;++k) {
+    nrvo.append(m.Data()[k]);
+  }
+  return nrvo;
+}
 
 void export_Mat4()
 {
@@ -115,5 +123,6 @@ void export_Mat4()
     .def("PasteRotation",&Mat4::PasteRotation)
     .def("ExtractTranslation",&Mat4::ExtractTranslation)
     .def("PasteTranslation",&Mat4::PasteTranslation)
+    .add_property("data",mat4_data)
   ;
 }
diff --git a/modules/geom/pymod/export_vec2.cc b/modules/geom/pymod/export_vec2.cc
index eec194418d780663aab9ecfe8e09388067c7f28f..456d26db370fdad9e364cfaa9d98fa74a4dd28d1 100644
--- a/modules/geom/pymod/export_vec2.cc
+++ b/modules/geom/pymod/export_vec2.cc
@@ -35,6 +35,15 @@ String vec2_repr(const geom::Vec2& v)
   return ss.str();
 }
 
+list vec2_data(const geom::Vec2& v)
+{
+  list nrvo;
+  for(size_t k=0;k<2;++k) {
+    nrvo.append(v.Data()[k]);
+  }
+  return nrvo;
+}
+
 void export_Vec2()
 {
   using namespace geom;
@@ -66,6 +75,7 @@ void export_Vec2()
     .def("GetY", &Vec2::GetY)
     .add_property("x", &Vec2::GetX, &Vec2::SetX)
     .add_property("y", &Vec2::GetY, &Vec2::SetY)
+    .add_property("data",vec2_data)
   ;
   class_<Vec2List>("Vec2List", init<>())
     .def(vector_indexing_suite<Vec2List>())
diff --git a/modules/geom/pymod/export_vec3.cc b/modules/geom/pymod/export_vec3.cc
index 623671de519d14f73d7843115a5d5b18e74c8da8..9a9b8f47c0850448a80a8033eb67c5df007b86e2 100644
--- a/modules/geom/pymod/export_vec3.cc
+++ b/modules/geom/pymod/export_vec3.cc
@@ -38,6 +38,15 @@ String vec3_repr(const geom::Vec3& v)
   return ss.str();
 }
 
+list vec3_data(const geom::Vec3& v)
+{
+  list nrvo;
+  for(size_t k=0;k<3;++k) {
+    nrvo.append(v.Data()[k]);
+  }
+  return nrvo;
+}
+
 void export_Vec3()
 {
   using namespace geom;
@@ -71,6 +80,7 @@ void export_Vec3()
     .add_property("x", &Vec3::GetX, &Vec3::SetX)
     .add_property("y", &Vec3::GetY, &Vec3::SetY)
     .add_property("z", &Vec3::GetZ, &Vec3::SetZ)
+    .add_property("data",vec3_data)
   ;
   
   def("Normalize", &NormalizeV3);
@@ -82,5 +92,7 @@ void export_Vec3()
     .add_property("center", &Vec3List::GetCenter)
     .add_property("inertia", &Vec3List::GetInertia)
     .add_property("principal_axes", &Vec3List::GetPrincipalAxes)
+    .def("GetODRLine", &Vec3List::GetODRLine)
+    .def("FitCylinder", &Vec3List::FitCylinder)
   ;
 }
diff --git a/modules/geom/pymod/export_vec4.cc b/modules/geom/pymod/export_vec4.cc
index bb3d80f90cc62205ec40e6fd22a736d05c0b1d20..4ebe1bbd108c95db0709622f544b9d79ee285c55 100644
--- a/modules/geom/pymod/export_vec4.cc
+++ b/modules/geom/pymod/export_vec4.cc
@@ -34,6 +34,15 @@ String vec4_repr(const geom::Vec4& v)
   return ss.str();
 }
 
+list vec4_data(const geom::Vec4& v)
+{
+  list nrvo;
+  for(size_t k=0;k<4;++k) {
+    nrvo.append(v.Data()[k]);
+  }
+  return nrvo;
+}
+
 void export_Vec4()
 {
   using namespace geom;
@@ -61,6 +70,11 @@ void export_Vec4()
     .def(self_ns::str(self))
     .def("__getitem__",Vec4_getitem)
     .def("__setitem__",Vec4_setitem)
+    .add_property("x", &Vec4::GetX, &Vec4::SetX)
+    .add_property("y", &Vec4::GetY, &Vec4::SetY)
+    .add_property("z", &Vec4::GetZ, &Vec4::SetZ)
+    .add_property("w", &Vec4::GetW, &Vec4::SetW)
+    .add_property("data",vec4_data)
   ;
 
 }
diff --git a/modules/geom/pymod/export_vecmat2_op.cc b/modules/geom/pymod/export_vecmat2_op.cc
index 4215e25fdf4cbc28f0dfdc09f5820cb1adc5ea91..cf1f0ac0b4df0579caa5638238d3301c3a83b16f 100644
--- a/modules/geom/pymod/export_vecmat2_op.cc
+++ b/modules/geom/pymod/export_vecmat2_op.cc
@@ -35,6 +35,8 @@ Mat2   (*Mat2Transpose)(const Mat2& m)                                  = &Trans
 Real (*Vec2Angle)(const Vec2& v1, const Vec2& v2)                     = &Angle;
 Vec2   (*Vec2Normalize)(const Vec2& v1)                                 = &Normalize;
 Vec2   (*Vec2Rotate)(const Vec2& v1,Real ang)                         = &Rotate;
+Vec2 (*Vec2Min)(const Vec2&, const Vec2&) = &Min;
+Vec2 (*Vec2Max)(const Vec2&, const Vec2&) = &Max;
 
 void export_VecMat2_op()
 {
@@ -53,4 +55,6 @@ void export_VecMat2_op()
   def("Angle",Vec2Angle);
   def("Normalize",Vec2Normalize);
   def("Rotate",Vec2Rotate);
+  def("Min",Vec2Min);
+  def("Max",Vec2Max);
 }
diff --git a/modules/geom/pymod/export_vecmat3_op.cc b/modules/geom/pymod/export_vecmat3_op.cc
index fe4444b75a176651a700c032895d04a926fc2257..048cdd170b4ca4e45c724db50f21d7a93fdcabd6 100644
--- a/modules/geom/pymod/export_vecmat3_op.cc
+++ b/modules/geom/pymod/export_vecmat3_op.cc
@@ -36,6 +36,8 @@ Mat3   (*Mat3Invert)(const Mat3& m)                                     = &Inver
 Mat3   (*Mat3Transpose)(const Mat3& m)                                  = &Transpose;
 Real (*Mat3Comp)(const Mat3& m, unsigned int i, unsigned int j)       = &Comp;
 Real (*Mat3Minor)(const Mat3& m, unsigned int i, unsigned int j)      = &Minor;
+Vec3 (*Vec3Min)(const Vec3&, const Vec3&) = &Min;
+Vec3 (*Vec3Max)(const Vec3&, const Vec3&) = &Max;
 
 
 void export_VecMat3_op()
@@ -60,4 +62,6 @@ void export_VecMat3_op()
   def("EulerTransformation",EulerTransformation);
   def("AxisRotation",AxisRotation);
   def("OrthogonalVector",OrthogonalVector);
+  def("Min",Vec3Min);
+  def("Max",Vec3Max);
 }
diff --git a/modules/geom/pymod/export_vecmat4_op.cc b/modules/geom/pymod/export_vecmat4_op.cc
index 9d91f48bbf9c3e8f6378e6822fdeeeefcd10fd16..af64cef7476c00ee2c31db423ec40af4d3674aa9 100644
--- a/modules/geom/pymod/export_vecmat4_op.cc
+++ b/modules/geom/pymod/export_vecmat4_op.cc
@@ -36,6 +36,8 @@ Mat4   (*Mat4Transpose)(const Mat4& m)                                  = &Trans
 Real (*Mat4Comp)(const Mat4& m, unsigned int i, unsigned int j)       = &Comp;
 Real (*Mat4Minor)(const Mat4& m, unsigned int i, unsigned int j)      = &Minor;
 Real (*Vec4Angle)(const Vec4& v1, const Vec4& v2)                     = &Angle;
+Vec4 (*Vec4Min)(const Vec4&, const Vec4&) = &Min;
+Vec4 (*Vec4Max)(const Vec4&, const Vec4&) = &Max;
 
 
 void export_VecMat4_op()
@@ -55,4 +57,6 @@ void export_VecMat4_op()
   def("Comp",Mat4Comp);
   def("Minor",Mat4Minor);
   def("Angle",Vec4Angle);
+  def("Min",Vec4Min);
+  def("Max",Vec4Max);
 }
diff --git a/modules/geom/src/composite3.cc b/modules/geom/src/composite3.cc
index 686e843e150c15729acd330cd8bc8d4112249c7f..751901b303d3b25f2b863c6767a7b21ff3343948 100644
--- a/modules/geom/src/composite3.cc
+++ b/modules/geom/src/composite3.cc
@@ -224,25 +224,12 @@ Vec3 Rotation3::GetRotationAxis() const
 }
 Real Rotation3::GetRotationAngle() const
 {
-  return 2.0*acos(q_.GetAngle());
+  //return 2.0*acos(q_.GetAngle());
+  return q_.GetAngle();
 }
 Mat3 Rotation3::GetRotationMatrix() const
 {
-  Real ww = q_.GetAngle()*q_.GetAngle();
-  Real wx = q_.GetAngle()*q_.GetAxis().GetX();
-  Real wy = q_.GetAngle()*q_.GetAxis().GetY();
-  Real wz = q_.GetAngle()*q_.GetAxis().GetZ();
-  Real xx = q_.GetAxis().GetX()*q_.GetAxis().GetX();
-  Real xy = q_.GetAxis().GetX()*q_.GetAxis().GetY();
-  Real xz = q_.GetAxis().GetX()*q_.GetAxis().GetZ();
-  Real yy = q_.GetAxis().GetY()*q_.GetAxis().GetY();
-  Real yz = q_.GetAxis().GetY()*q_.GetAxis().GetZ();
-  Real zz = q_.GetAxis().GetZ()*q_.GetAxis().GetZ();
-
-
-  return Mat3((ww+xx-yy-zz), 2.0*(-wz+xy), 2.0*(wy+xz),
-                 2.0*(wz+xy), (ww-xx+yy-zz), 2.0*(-wx+yz),
-                 2.0*(-wy+xz), 2.0*(wx+yz),(ww-xx-yy+zz));
+  return q_.ToRotationMatrix();
 }
 
 void Rotation3::SetOrigin(const Vec3& o)
@@ -299,7 +286,8 @@ Quat Rotation3::generate_from_eulers(Real phi, Real theta, Real psi)
 }
 Quat Rotation3::generate_from_axis_angle(const Vec3& axis, Real angle)
 {
-  return Quat(cos(angle/2.0),sin(angle/2.0)*Normalize(axis));
+  //return Quat(cos(angle/2.0),sin(angle/2.0)*Normalize(axis));
+  return Quat(angle, axis);
 }
 
 /*
diff --git a/modules/geom/src/composite3_op.cc b/modules/geom/src/composite3_op.cc
index 09fb2c72e7430c2fc938534ff4167052485a4b24..672896f0d9aaec18fad77a24aa8065c7c43e34e4 100644
--- a/modules/geom/src/composite3_op.cc
+++ b/modules/geom/src/composite3_op.cc
@@ -178,5 +178,50 @@ bool IsInSphere(const Sphere& s, const Vec3& v){
   return Length(s.GetOrigin()-v)<=s.GetRadius();
 }
 
+Line3 Vec3List::FitCylinder(){
+  Line3 axis=this->GetODRLine(),axis_old;
+  Real radius,res_sum_old,res_sum,delta=0.01,prec=0.001,err;
+  unsigned long n_step=1000, n_res=this->size();
+  Vec3 v,gradient;
+  radius=0.0;
+  for (Vec3List::const_iterator i=this->begin(),e=this->end(); i!=e; ++i) {
+    radius+=geom::Distance(axis,(*i));
+  }
+  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.);
+  }
+  unsigned long k=0;
+  err=2.0*prec;
+  while (err>prec and k<n_step) {
+    res_sum_old=res_sum;
+    axis_old=axis;
+    for (Vec3List::const_iterator i=this->begin(),e=this->end(); i!=e; ++i) {
+      radius+=Distance(axis,(*i));
+    }
+    radius/=Real(n_res);
+    for (int j=0; j!=3; ++j){
+      res_sum=0.0;
+      v=Vec3(0.0,0.0,0.0);
+      v[j]=delta;
+      axis=Line3(axis_old.GetOrigin(),axis_old.GetOrigin()+axis_old.GetDirection()+v);
+      for (Vec3List::const_iterator i=this->begin(),e=this->end(); i!=e; ++i) {
+        res_sum+=pow(Distance(axis,(*i))-radius,2.);
+      }
+      gradient[j]=res_sum-res_sum_old;
+    }
+    gradient=Normalize(gradient);
+    axis=Line3(axis_old.GetOrigin(),axis_old.GetOrigin()+axis_old.GetDirection()-delta*gradient);
+    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.);
+    }
+    err=fabs((res_sum-res_sum_old)/float(n_res));
+    k++;
+  }
+  return axis;
+}
+
 } // ns
 
diff --git a/modules/geom/src/quat.cc b/modules/geom/src/quat.cc
index b923a668008fbe908f55bd1a10a584598ea930de..f9b852cae7799478c8f0ca3bfb599c3b80821421 100644
--- a/modules/geom/src/quat.cc
+++ b/modules/geom/src/quat.cc
@@ -287,7 +287,8 @@ Vec3 Quat::GetAxis() const
 
 Real Quat::GetAngle() const
 {
-  Real ww = std::acos(w/Length(Vec3(x,y,z)));
+  //Real ww = std::acos(w/Length(Vec3(x,y,z)));
+  Real ww = 2.0*std::acos(w);
   return ww;
 }
 
diff --git a/modules/geom/src/vec3.cc b/modules/geom/src/vec3.cc
index 84467ced5a4ddf66dd5ae23e1de054c7cb8e175d..bcc62d42ad0bb0814581f96b9750730e4a84ce7c 100644
--- a/modules/geom/src/vec3.cc
+++ b/modules/geom/src/vec3.cc
@@ -68,5 +68,12 @@ Vec3 Vec3List::GetCenter() const
   return center/=this->size();
 }
 
+Line3 Vec3List::GetODRLine()
+{
+  Vec3 center=this->GetCenter();
+  Vec3 direction=this->GetPrincipalAxes().GetRow(2);
+  return Line3(center,center+direction);
+}
+
 
 }
diff --git a/modules/geom/src/vec3.hh b/modules/geom/src/vec3.hh
index db2b8bb7097dc76d0b74c7906a0ea4a63bda5929..2a27d500a8a0c5ca9c66127de47f0cf37f48f932 100644
--- a/modules/geom/src/vec3.hh
+++ b/modules/geom/src/vec3.hh
@@ -34,7 +34,7 @@ namespace geom {
 // fw decl
 class Vec2;
 class Vec4;
-
+class Line3;
 
 /// \brief Three dimensional vector class, using Real precision.
 class DLLEXPORT_OST_GEOM Vec3:
@@ -193,6 +193,7 @@ inline std::ostream& operator<<(std::ostream& os, const Vec3& v)
 #include <ost/geom/vec2.hh>
 #include <ost/geom/vec4.hh>
 #include <ost/geom/mat3.hh>
+#include <ost/geom/composite3.hh>
 
 namespace geom {
 
@@ -216,6 +217,9 @@ public:
   Vec3 GetCenter() const;
   
   Mat3 GetPrincipalAxes() const;
+  Line3 GetODRLine();
+  Line3 FitCylinder();
+
 };
 
 
diff --git a/modules/geom/tests/CMakeLists.txt b/modules/geom/tests/CMakeLists.txt
index 7a7dace6b3ed006ba13997889693a4b3910949f8..42d7f4c43b393411b5c7edeaecec9bc1e8bc2ca4 100644
--- a/modules/geom/tests/CMakeLists.txt
+++ b/modules/geom/tests/CMakeLists.txt
@@ -11,7 +11,7 @@ set(GEOM_UNITTESTS
   test_vec3.cc
   test_vec4.cc
   tests.cc
-  test_repr.py
+  test_geom.py
 )
 
 ost_unittest(MODULE geom
diff --git a/modules/geom/tests/test_geom.py b/modules/geom/tests/test_geom.py
new file mode 100644
index 0000000000000000000000000000000000000000..e25081bf1f0f305cf7928bd897566ade46c9c9e3
--- /dev/null
+++ b/modules/geom/tests/test_geom.py
@@ -0,0 +1,84 @@
+#------------------------------------------------------------------------------
+# 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
+#------------------------------------------------------------------------------
+
+import unittest
+if __name__== '__main__':
+  import sys
+  sys.path.insert(0,"../../../stage/lib64/openstructure/")
+  sys.path.insert(0,"../../../stage/lib/openstructure/")
+
+import ost
+import ost.geom as geom
+
+class TestGeom(unittest.TestCase):
+  def runTest(self):
+    self.test_repr()
+    self.test_data()
+
+  def test_repr(self):
+    v=geom.Vec2(1,2)
+    v2=eval(repr(v))
+    self.assertTrue(geom.Equal(v, v2))
+                     
+    v=geom.Vec3(1,2,3)
+    v2=eval(repr(v))
+    self.assertTrue(geom.Equal(v, v2))
+
+    v=geom.Vec4(1,2,3,4)
+    v2=eval(repr(v))
+    self.assertTrue(geom.Equal(v, v2))
+
+    m=geom.Mat2(1,2,3,4)
+    m2=eval(repr(m))
+    self.assertTrue(geom.Equal(m, m2))
+
+    m=geom.Mat3(1,2,3,4,5,6,7,8,9)
+    m2=eval(repr(m))
+    self.assertTrue(geom.Equal(m, m2))
+
+    m=geom.Mat4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)
+    m2=eval(repr(m))
+    self.assertTrue(geom.Equal(m, m2))
+
+  def test_data(self):
+    self.assertEqual(geom.Vec2(1,2).data,[1,2])
+    self.assertEqual(geom.Vec3(1,2,3).data,[1,2,3])
+    self.assertEqual(geom.Vec4(1,2,3,4).data,[1,2,3,4])
+    self.assertEqual(geom.Mat2(1,2,
+                               3,4).data,
+                     [1,2,
+                      3,4])
+    self.assertEqual(geom.Mat3(1,2,3,
+                               4,5,6,
+                               7,8,9).data,
+                     [1,2,3,
+                      4,5,6,
+                      7,8,9])
+    self.assertEqual(geom.Mat4(1,2,3,4,
+                               5,6,7,8,
+                               9,10,11,12,
+                               13,14,15,16).data,
+                     [1,2,3,4,
+                      5,6,7,8,
+                      9,10,11,12,
+                      13,14,15,16])
+    
+if __name__== '__main__':
+  unittest.main()
+
diff --git a/modules/geom/tests/test_repr.py b/modules/geom/tests/test_repr.py
deleted file mode 100644
index e69358f20f783c7f8b731de7f13deb569105a0fa..0000000000000000000000000000000000000000
--- a/modules/geom/tests/test_repr.py
+++ /dev/null
@@ -1,39 +0,0 @@
-import unittest
-from ost import geom
-
-class TestRepr(unittest.TestCase):
-  def testReprVec2(self):
-    v=geom.Vec2(1,2)
-    v2=eval(repr(v))
-    assert geom.Equal(v, v2)
-
-  def testReprVec3(self):
-    v=geom.Vec3(1,2,3)
-    v2=eval(repr(v))
-    assert geom.Equal(v, v2)
-
-  def testReprVec4(self):
-    v=geom.Vec4(1,2,3,4)
-    v2=eval(repr(v))
-    assert geom.Equal(v, v2)
-
-  def testReprMat2(self):
-    m=geom.Mat2(1,2,3,4)
-    m2=eval(repr(m))
-    assert geom.Equal(m, m2)
-
-  def testReprMat3(self):
-    m=geom.Mat3(1,2,3,4,5,6,7,8,9)
-    m2=eval(repr(m))
-    assert geom.Equal(m, m2)
-
-  def testReprMat4(self):
-    m=geom.Mat4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)
-    m2=eval(repr(m))
-    assert geom.Equal(m, m2)
-
-if __name__ == "__main__":
-  try:
-    unittest.main()
-  except Exception, e:
-    print e
\ No newline at end of file
diff --git a/modules/gfx/pymod/CMakeLists.txt b/modules/gfx/pymod/CMakeLists.txt
index 210cce509623565695582e20969f818e8f2e042d..a3d8b251dda72f07f6e7394ad4fb3d0996fb4bd4 100644
--- a/modules/gfx/pymod/CMakeLists.txt
+++ b/modules/gfx/pymod/CMakeLists.txt
@@ -14,13 +14,14 @@ set(OST_GFX_PYMOD_SOURCES
   export_gradient.cc
   export_color_ops.cc
   export_glwin_base.cc
+  export_exporter.cc
 )
 
 if (ENABLE_IMG)
   set(OST_GFX_PYMOD_SOURCES ${OST_GFX_PYMOD_SOURCES} export_map.cc)
 endif()
 
-pymod(NAME gfx CPP ${OST_GFX_PYMOD_SOURCES} PY __init__.py)
+pymod(NAME gfx CPP ${OST_GFX_PYMOD_SOURCES} PY __init__.py py_gfx_obj.py)
 
 set(GRADIENT_FILE
   gradients.xml
diff --git a/modules/gfx/pymod/__init__.py b/modules/gfx/pymod/__init__.py
index ab6f3d27baf4440029f9abc7262c1fd974354774..be887c4ab071e3c4f2da12a771e7e1edad6b8b30 100644
--- a/modules/gfx/pymod/__init__.py
+++ b/modules/gfx/pymod/__init__.py
@@ -17,6 +17,7 @@
 # 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 #------------------------------------------------------------------------------
 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)
@@ -202,7 +203,7 @@ def _primlist_add_point(self,pos,color=None):
     color=WHITE
   self._add_point(pos,color)
   
-def _primlist_add_line(self,pos1,pos2,color=None,color1=None,color2=None):
+def _primlist_add_line(self,pos1,pos2,color1=None,color2=None,color=None):
   pos1=_to_vec3(pos1)
   pos2=_to_vec3(pos2)
   if not color:
@@ -210,7 +211,7 @@ def _primlist_add_line(self,pos1,pos2,color=None,color1=None,color2=None):
   if not color1:
     color1=color
   if not color2:
-    color2=color
+    color2=color1
   self._add_line(pos1,pos2,color1,color2)
 
 def _primlist_add_sphere(self,cen,radius=1.0,color=None):
@@ -219,7 +220,7 @@ def _primlist_add_sphere(self,cen,radius=1.0,color=None):
     color=WHITE
   self._add_sphere(pos,radius,color)
   
-def _primlist_add_cyl(self,pos1,pos2,radius=None,radius1=None,radius2=None,color=None,color1=None,color2=None):
+def _primlist_add_cyl(self,pos1,pos2,radius1=None,radius2=None,radius=None,color1=None,color2=None,color=None,):
   pos1=_to_vec3(pos1)
   pos2=_to_vec3(pos2)
   if radius is None:
@@ -227,13 +228,13 @@ def _primlist_add_cyl(self,pos1,pos2,radius=None,radius1=None,radius2=None,color
   if radius1 is None:
     radius1=radius
   if radius2 is None:
-    radius2=radius
+    radius2=radius1
   if not color:
     color=WHITE
   if not color1:
     color1=color
   if not color2:
-    color2=color
+    color2=color1
   self._add_cyl(pos1,pos2,radius1,radius2,color1,color2)
 
 def _primlist_add_text(self,text,pos,color=None,point_size=None):
@@ -243,7 +244,7 @@ def _primlist_add_text(self,text,pos,color=None,point_size=None):
   if not point_size:
     point_size=1.0
   self._add_text(text,pos,color,point_size)
-  
+
 PrimList.AddPoint=_primlist_add_point
 PrimList.AddLine=_primlist_add_line
 PrimList.AddSphere=_primlist_add_sphere
diff --git a/modules/gfx/pymod/export_entity.cc b/modules/gfx/pymod/export_entity.cc
index 0767825bdb12415a5eca9477e5ea5f56e20b7015..6202bd1cc4d353d61b673c78d68b402ecbc7b137 100644
--- a/modules/gfx/pymod/export_entity.cc
+++ b/modules/gfx/pymod/export_entity.cc
@@ -338,12 +338,14 @@ void export_Entity()
     .def("BlurSnapshot", &Entity::BlurSnapshot)
     .def("SetBlurFactors",&Entity::SetBlurFactors)
     .def("SetBlur",&Entity::SetBlur)
-    .def("GetBoundingBox",&Entity::GetBoundingBox)    
+    .def("GetBoundingBox",&Entity::GetBoundingBox)
+    .add_property("bounding_box",&Entity::GetBoundingBox)
     .def("SetSelection",&Entity::SetSelection)
     .def("GetSelection",&Entity::GetSelection)    
     .add_property("selection", &Entity::GetSelection, 
                   &set_selection)
     .def("GetView", &Entity::GetView)
+    .add_property("view",&Entity::GetView)
     .def("UpdateView", &Entity::UpdateView)
     .def("SetQuery", set_query)
     .def("SetQueryView",&Entity::SetQueryView)
@@ -356,7 +358,6 @@ void export_Entity()
     .def("SetRenderMode", set_rm3, (arg("mode"), arg("sel"), arg("keep")=false))    
     .def("SetEnableRenderMode", &Entity::SetEnableRenderMode)
     .def("IsRenderModeEnabled", &Entity::IsRenderModeEnabled)
-    .add_property("view", &Entity::GetView)
     .def("SetVisible", set_vis1, (arg("view"), arg("flag")=true))
     .def("SetVisible", set_vis2, (arg("sel"), arg("flag")=true))    
     .def("ColorBy", color_by_01)
diff --git a/modules/gfx/pymod/export_exporter.cc b/modules/gfx/pymod/export_exporter.cc
new file mode 100644
index 0000000000000000000000000000000000000000..655fe54f77282e2d6656142addf51e18006d7f7c
--- /dev/null
+++ b/modules/gfx/pymod/export_exporter.cc
@@ -0,0 +1,38 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+#include <boost/python.hpp>
+using namespace boost::python;
+
+#include <ost/gfx/exporter.hh>
+#include <ost/gfx/gost_exporter.hh>
+#include <ost/gfx/collada_exporter.hh>
+
+using namespace ost;
+using namespace ost::gfx;
+
+void export_Exporter()
+{
+  class_<Exporter, boost::noncopyable>("Exporter", no_init);
+
+  class_<GostExporter, bases<Exporter>, boost::noncopyable>("GostExporter", init<const std::string&>())
+    ;
+
+  class_<ColladaExporter, bases<Exporter>, boost::noncopyable>("ColladaExporter", init<const std::string&, optional<float> >())
+    ;
+}
diff --git a/modules/gfx/pymod/export_gfx_obj.cc b/modules/gfx/pymod/export_gfx_obj.cc
index 70458055914d2e74f399c318eae2b398e98a2943..f9caac28c0d4c9181e29dd1aa01ca5ca84d04cd6 100644
--- a/modules/gfx/pymod/export_gfx_obj.cc
+++ b/modules/gfx/pymod/export_gfx_obj.cc
@@ -58,6 +58,63 @@ namespace {
     LOG_INFO("AALines(bool) is deprecated, use SetAALines(bool) instead");
     b->SetAALines(f);
   }
+
+  class GfxObjWrap: public GfxObj, public wrapper<GfxObj>
+  {
+  public:
+    GfxObjWrap(const std::string& name):
+      GfxObj(name)
+    {}
+
+    virtual geom::AlignedCuboid GetBoundingBox() const
+    {
+      if(override f = this->get_override("GetBoundingBox")) {
+        return f();
+      } else {
+        return GfxObj::GetBoundingBox();
+      }
+    }
+
+    geom::AlignedCuboid default_GetBoundingBox() const {
+      return GfxObj::GetBoundingBox();
+    }
+
+    virtual void CustomRenderGL(RenderPass pass) {
+      if(override f = this->get_override("_CustomRenderGL")) {
+        f(pass);
+      } else {
+        GfxObj::CustomRenderGL(pass);
+      }
+    }
+
+    void default_CustomRenderGL(RenderPass pass) {
+        GfxObj::CustomRenderGL(pass);
+    }
+
+    virtual void CustomPreRenderGL(bool rebuild) {
+      if(override f = this->get_override("_CustomPreRenderGL")) {
+        f(rebuild);
+      } else {
+        GfxObj::CustomPreRenderGL(rebuild);
+      }
+    }
+
+    void default_CustomPreRenderGL(bool rebuild) {
+        GfxObj::CustomPreRenderGL(rebuild);
+    }
+
+    virtual void InitGL() {
+      if(override f = this->get_override("_InitGL")) {
+        f();
+      } else {
+        GfxObj::InitGL();
+      }
+    }
+
+    void default_InitGL() {
+        GfxObj::InitGL();
+    }
+  };
 }
 
 void export_GfxObj()
@@ -77,26 +134,38 @@ void export_GfxObj()
     .def("ContextSwitch", &GfxObjBase::ContextSwitch)
     .def("SetRenderMode", &GfxObjBase::SetRenderMode)
     .def("GetRenderMode", &GfxObjBase::GetRenderMode)
-    .def("GetCenter",&GfxObjBase::GetCenter)
+    .def("GetCenter",&GfxObjBase::GetCenter) 
+    .add_property("center", &GfxObjBase::GetCenter)
     .def("SetLineWidth", &GfxObjBase::SetLineWidth)
     .def("SetPolyMode",&GfxObjBase::SetPolyMode)
-    .def("AALines",set_aalines)
+    .def("AALines",set_aalines) /* deprecated */
     .def("SetAALines",&GfxObjBase::SetAALines)
     .def("SetLineHalo",&GfxObjBase::SetLineHalo)
-    .def("Outline",set_outline)
+    .def("Outline",set_outline) /* deprecated */
     .def("SetOutline",&GfxObjBase::SetOutline)
+    .def("GetOutline",&GfxObjBase::GetOutline)
+    .add_property("outline",&GfxObjBase::GetOutline,&GfxObjBase::SetOutline)
     .def("SetOutlineMode",&GfxObjBase::SetOutlineMode)
+    .add_property("outline_mode",&GfxObjBase::GetOutlineMode,&GfxObjBase::SetOutlineMode)
     .def("SetOutlineWidth",&GfxObjBase::SetOutlineWidth)
+    .add_property("outline_width",&GfxObjBase::GetOutlineWidth,&GfxObjBase::SetOutlineWidth)
     .def("SetOutlineExpandFactor",&GfxObjBase::SetOutlineExpandFactor)
+    .add_property("outline_expand_factor",&GfxObjBase::GetOutlineExpandFactor,&GfxObjBase::SetOutlineExpandFactor)
     .def("SetOutlineExpandColor",&GfxObjBase::SetOutlineExpandColor)
+    .add_property("outline_expand_color",&GfxObjBase::GetOutlineExpandColor,&GfxObjBase::SetOutlineExpandColor)
+    .add_property("outline_color",&GfxObjBase::GetOutlineExpandColor,&GfxObjBase::SetOutlineExpandColor)
     .def("SetOpacity",&GfxObjBase::SetOpacity)
     .def("GetOpacity",&GfxObjBase::GetOpacity)
-    .add_property("center", &GfxObjBase::GetCenter)
+    .add_property("opacity",&GfxObjBase::GetOpacity,&GfxObjBase::SetOpacity)
     COLOR_BY_DEF()
    ;
-  //register_ptr_to_python<GfxObjBaseP>();
 
-  class_<GfxObj, boost::shared_ptr<GfxObj>, bases<GfxObjBase>, boost::noncopyable>("GfxObj",no_init)
+  enum_<RenderPass>("RenderPass")
+    .value("STANDARD_RENDER_PASS",STANDARD_RENDER_PASS)
+    .value("TRANSPARENT_RENDER_PASS",TRANSPARENT_RENDER_PASS)
+    ;        
+
+  class_<GfxObjWrap, boost::shared_ptr<GfxObj>, bases<GfxObjBase>, boost::noncopyable>("GfxObj",init<const std::string&>())
     .def("GetTF", &GfxObj::GetTF, return_value_policy<copy_const_reference>())
     .def("SetTF", &GfxObj::SetTF)
     .def("FlagRebuild",&GfxObj::FlagRebuild)
@@ -108,7 +177,10 @@ void export_GfxObj()
     .def("GetAALines",&GfxObj::GetAALines)
     .def("GetLineWidth",&GfxObj::GetLineWidth)
     .def("GetLineHalo",&GfxObj::GetLineHalo)
-    ;
-  //register_ptr_to_python<GfxObjP>();
+    .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 e24cc9cee5fec611fc536b8c0ab5a4e95c3712a1..6cb26cee020a295eb56111aa4101d189470eadc3 100644
--- a/modules/gfx/pymod/export_gradient.cc
+++ b/modules/gfx/pymod/export_gradient.cc
@@ -26,7 +26,7 @@ using namespace ost;
 using namespace ost::gfx;
 
 namespace {
-  Gradient* make_gradient(const dict& d)
+  Gradient* make_gradient_d(const dict& d)
   {
     std::auto_ptr<Gradient> grad(new Gradient);
     list keys = d.keys();
@@ -57,13 +57,42 @@ namespace {
     }
     return grad.release();
   }
+
+  Gradient* make_gradient_l(const list& l)
+  {
+    std::auto_ptr<Gradient> grad(new Gradient);
+    float mf = len(l)<2 ? 0.0 : 1.0/static_cast<float>(len(l)-1); 
+    for(int i=0;i<len(l);++i) {
+      float mark = static_cast<float>(i)*mf;
+      Color col;
+      object val = l[i];
+      extract<Color> cex(val);
+      if(cex.check()) {
+        // use gfx.Color
+        col=cex();
+      } else {
+        // try simple sequence
+        if(len(val)!=3) {
+          throw std::runtime_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");
+        }
+      }
+      grad->SetColorAt(mark,col);
+    }
+    return grad.release();
+  }
 }
 
 void export_gradient()
 {
   class_<Gradient>("Gradient", init<>())
     .def(init<const String&>())
-    .def("__init__", make_constructor(make_gradient))
+    .def("__init__", make_constructor(make_gradient_d))
+    .def("__init__", make_constructor(make_gradient_l))
     .def("SetColorAt", &Gradient::SetColorAt)
     .def("GetColorAt", &Gradient::GetColorAt)
     .def("GetStops", &Gradient::GetStops)
diff --git a/modules/gfx/pymod/export_primitives.cc b/modules/gfx/pymod/export_primitives.cc
index 91ce753ed91df2006caf3928438d4ed1937032cc..01b328d7288116ab8c6dcd9e7d86c5c3ad97fb07 100644
--- a/modules/gfx/pymod/export_primitives.cc
+++ b/modules/gfx/pymod/export_primitives.cc
@@ -25,8 +25,7 @@ using namespace ost::gfx;
 
 void export_primitives()
 {
-  class_<Primitive, boost::shared_ptr<Primitive>, 
-         bases<GfxNode>, boost::noncopyable>("Primitive", no_init)
+  class_<Primitive, bases<GfxNode>, boost::noncopyable>("Primitive", no_init)
     .def("HasOutline", &Primitive::HasOutline)
     .def("HasFill", &Primitive::HasFill)    
     .def("SetFill", &Primitive::SetFill)
@@ -40,10 +39,10 @@ void export_primitives()
     .def("GetOutlineColor", &Primitive::GetOutlineColor,
          return_value_policy<copy_const_reference>())
   ;
-  class_<Cuboid, boost::shared_ptr<Cuboid>, bases<Primitive>, 
+  class_<Cuboid, bases<Primitive>, 
          boost::noncopyable>("Cuboid", init<const String&, const geom::Cuboid>())
   ; 
-  class_<Quad, boost::shared_ptr<Quad>, bases<Primitive>, 
+  class_<Quad, bases<Primitive>, 
        boost::noncopyable>("Quad", init<const String&, const geom::Vec3&,
                                         const geom::Vec3&, const geom::Vec3&,
                                         const geom::Vec3&>())
diff --git a/modules/gfx/pymod/export_primlist.cc b/modules/gfx/pymod/export_primlist.cc
index b8326509d8ed7065f120ab4760a541b5766e207b..bb986d7e14c1580555d2bb3b4db2fb497c1c9fcc 100644
--- a/modules/gfx/pymod/export_primlist.cc
+++ b/modules/gfx/pymod/export_primlist.cc
@@ -25,8 +25,90 @@ using namespace boost::python;
 using namespace ost;
 using namespace ost::gfx;
 
+#if OST_NUMPY_SUPPORT_ENABLED
+#include <numpy/arrayobject.h>
+#endif
+
+namespace {
+  void add_mesh(PrimList& p, object ova, object ona, object oca, object oia)
+  {
+#if OST_NUMPY_SUPPORT_ENABLED
+    if(!PyArray_Check(ova.ptr())) {
+      throw std::runtime_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");
+    }
+    if(!PyArray_TYPE(va)==NPY_FLOAT) {
+      throw std::runtime_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");
+    }
+    size_t v_count=v_size/3;
+    float* vp=reinterpret_cast<float*>(PyArray_DATA(va));
+    float* np=0;
+    float* cp=0;
+    if(ona!=object()) {
+      if(!PyArray_Check(ona.ptr())) {
+        throw std::runtime_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");
+      }
+      if(!PyArray_TYPE(na)==NPY_FLOAT) {
+        throw std::runtime_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");
+      }
+      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");
+      }
+      PyArrayObject* ca=reinterpret_cast<PyArrayObject*>(oca.ptr());
+      if(!PyArray_ISCONTIGUOUS(ca)) {
+        throw std::runtime_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");
+      }
+      if(PyArray_SIZE(ca)!=v_count*4) {
+        throw std::runtime_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");
+    }
+    PyArrayObject* ia=reinterpret_cast<PyArrayObject*>(oia.ptr());
+    if(!PyArray_ISCONTIGUOUS(ia)) {
+      throw std::runtime_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");
+    }
+    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");
+#endif
+  }
+}
+
 void export_primlist()
 {
+#if OST_NUMPY_SUPPORT_ENABLED
+  import_array(); // magic handshake for numpy module
+#endif
+
   class_<PrimList, bases<GfxObj>, boost::shared_ptr<PrimList>, boost::noncopyable>("PrimList", init<const String& >())
     .def("Clear",&PrimList::Clear)
     .def("_add_line",&PrimList::AddLine)
@@ -34,6 +116,7 @@ void export_primlist()
     .def("_add_sphere",&PrimList::AddSphere)
     .def("_add_cyl",&PrimList::AddCyl)
     .def("_add_text",&PrimList::AddText)
+    .def("AddMesh",add_mesh)
     .def("SetColor",&PrimList::SetColor)
     .def("SetDiameter",&PrimList::SetDiameter)
     .def("SetRadius",&PrimList::SetRadius)
diff --git a/modules/gfx/pymod/export_scene.cc b/modules/gfx/pymod/export_scene.cc
index f5692fad5b197d02c94f024add51392e78f72b2b..8b73a3391ec8a0a8ac5f4e41357b17738320d1d2 100644
--- a/modules/gfx/pymod/export_scene.cc
+++ b/modules/gfx/pymod/export_scene.cc
@@ -21,6 +21,7 @@ using namespace boost::python;
 
 #include <ost/gfx/gfx_object.hh>
 #include <ost/gfx/scene.hh>
+#include <ost/gfx/exporter.hh>
 using namespace ost;
 using namespace ost::gfx;
 
@@ -63,6 +64,7 @@ void export_Scene()
 
   void (Scene::* export1)(const String&, uint, uint, bool) = &Scene::Export;
   void (Scene::* export2)(const String&, bool) = &Scene::Export;
+  void (Scene::* export3)(Exporter*) const = &Scene::Export;
   void (Scene::*remove1)(const GfxNodeP&) = &Scene::Remove;
   void (Scene::*remove2)(const String&) = &Scene::Remove;
   void (Scene::*center_on1)(const String&) = &Scene::CenterOn;
@@ -116,6 +118,7 @@ void export_Scene()
     .def("SetFogColor",&Scene::SetFogColor)
     .def("GetFogColor",&Scene::GetFogColor)
     .add_property("fogcol", &Scene::GetFogColor, &Scene::SetFogColor)
+    .add_property("fog_color", &Scene::GetFogColor, &Scene::SetFogColor)
     .def("SetFOV",&Scene::SetFOV)
     .def("GetFOV",&Scene::GetFOV)
     .add_property("fov", &Scene::GetFOV, &Scene::SetFOV)
@@ -159,8 +162,9 @@ void export_Scene()
     .def("SetLightProp",set_light_prop1)
     .def("SetLightProp",set_light_prop2)
     .def("Apply", apply)
-    .def("Export",export1, arg("transparent")=true)
-    .def("Export",export2, arg("transparent")=true)
+    .def("Export",export1, arg("transparent")=false)
+    .def("Export",export2, arg("transparent")=false)
+    .def("Export",export3)
     .def("ExportPov",&Scene::ExportPov,
          scene_export_pov_overloads())
     .def("PushView",&Scene::PushView)
@@ -169,14 +173,25 @@ void export_Scene()
     .def("BlurSnapshot",&Scene::BlurSnapshot)
     .def("RemoveAll", &Scene::RemoveAll)
     .def("SetShadow",&Scene::SetShadow)
+    .add_property("shadow",&Scene::GetShadow,&Scene::SetShadow)
     .def("SetShadowQuality",&Scene::SetShadowQuality)
+    .add_property("shadow_quality",&Scene::GetShadowQuality,&Scene::SetShadowQuality)
     .def("SetShadowWeight",&Scene::SetShadowWeight)
+    .add_property("shadow_weight",&Scene::GetShadowWeight,&Scene::SetShadowWeight)
     .def("SetDepthDarkening",&Scene::SetDepthDarkening)
     .def("SetDepthDarkeningWeight",&Scene::SetDepthDarkeningWeight)
     .def("SetAmbientOcclusion",&Scene::SetAmbientOcclusion)
+    .add_property("ambient_occlusion",&Scene::GetAmbientOcclusion,&Scene::SetAmbientOcclusion)
+    .add_property("ao",&Scene::GetAmbientOcclusion,&Scene::SetAmbientOcclusion)
     .def("SetAmbientOcclusionWeight",&Scene::SetAmbientOcclusionWeight)
+    .add_property("ambient_occlusion_weight",&Scene::GetAmbientOcclusionWeight,&Scene::SetAmbientOcclusionWeight)
+    .add_property("ao_weight",&Scene::GetAmbientOcclusionWeight,&Scene::SetAmbientOcclusionWeight)
     .def("SetAmbientOcclusionMode",&Scene::SetAmbientOcclusionMode)
+    .add_property("ambient_occlusion_mode",&Scene::GetAmbientOcclusionMode,&Scene::SetAmbientOcclusionMode)
+    .add_property("ao_mode",&Scene::GetAmbientOcclusionMode,&Scene::SetAmbientOcclusionMode)
     .def("SetAmbientOcclusionQuality",&Scene::SetAmbientOcclusionQuality)
+    .add_property("ambient_occlusion_quality",&Scene::GetAmbientOcclusionQuality,&Scene::SetAmbientOcclusionQuality)
+    .add_property("ao_quality",&Scene::GetAmbientOcclusionQuality,&Scene::SetAmbientOcclusionQuality)
     .def("AttachObserver",&Scene::AttachObserver)
     .def("StartOffscreenMode",&Scene::StartOffscreenMode)
     .def("StopOffscreenMode",&Scene::StopOffscreenMode)
@@ -185,5 +200,7 @@ void export_Scene()
     .add_property("root_node", &Scene::GetRootNode)
     .def("SetBeaconOff",&Scene::SetBeaconOff)
     .def("__getitem__",scene_getitem)
+    .add_property("show_center",&Scene::GetShowCenter, &Scene::SetShowCenter)
+    .add_property("fix_center",&Scene::GetFixCenter, &Scene::SetFixCenter)
   ;
 }
diff --git a/modules/gfx/pymod/py_gfx_obj.py b/modules/gfx/pymod/py_gfx_obj.py
new file mode 100644
index 0000000000000000000000000000000000000000..ac91e9073a47b061ee57145e0d3d7b6b6a51dcc5
--- /dev/null
+++ b/modules/gfx/pymod/py_gfx_obj.py
@@ -0,0 +1,79 @@
+#------------------------------------------------------------------------------
+# 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
+#------------------------------------------------------------------------------
+import traceback
+from _ost_gfx import *
+
+class PyGfxObj(GfxObj):
+  def __init__(self,name):
+    """
+    requires a unique name not yet utilized in the Scene;
+    do not place OpenGL calls in the ctor, use InitGL for
+    that purpose
+    """
+    GfxObj.__init__(self,name)
+    self._valid_flag=False
+
+  def _InitGL(self):
+    try:
+      self.InitGL()
+      self._valid_flag=True
+    except:
+      traceback.print_exc()
+      
+  def InitGL(self):
+    """
+    called once for each OpenGL context (usually one time),
+    allows one-time OpenGL initialization to be implemented,
+    such as vbo allocation
+    """
+    pass
+
+
+  def _CustomPreRenderGL(self,rebuild):
+    if not self._valid_flag:
+      return
+    try:
+      self.CustomPreRenderGL(rebuild)
+    except:
+      self._valid_flag=False
+      traceback.print_exc()
+
+  def CustomPreRenderGL(self,rebuild):
+    """
+    called just before CustomRenderGL is called; the flag
+    indicates that a rebuild is required or was requested
+    """
+    pass
+
+
+  def _CustomRenderGL(self,render_pass):
+    if not self._valid_flag:
+      return
+    try:
+      self.CustomRenderGL(render_pass)
+    except:
+      self._valid_flag=False
+      traceback.print_exc()
+
+  def CustomRenderGL(self,render_pass):
+    """
+    called for each scene refresh
+    """
+    pass
+
diff --git a/modules/gfx/pymod/wrap_gfx.cc b/modules/gfx/pymod/wrap_gfx.cc
index 0198d3a0fb27ae5869ff572b9335e6580737b8e9..28229edf12ada259a25443f363d43db51199291d 100644
--- a/modules/gfx/pymod/wrap_gfx.cc
+++ b/modules/gfx/pymod/wrap_gfx.cc
@@ -37,6 +37,8 @@ extern void export_primlist();
 extern void export_primitives();
 extern void export_color();
 extern void export_gradient();
+extern void export_Exporter();
+
 #if OST_IMG_ENABLED
   extern void export_Map();
 #endif
@@ -135,6 +137,8 @@ BOOST_PYTHON_MODULE(_ost_gfx)
     ;
 #endif
 
+  export_primitives();
+  export_Exporter();
 }
 
 
diff --git a/modules/gfx/src/CMakeLists.txt b/modules/gfx/src/CMakeLists.txt
index 4f23812fd1120c170b45ff54ace477657314d9f2..9309a6af7ebec7fed643e303a732bf1b0c53b4ab 100644
--- a/modules/gfx/src/CMakeLists.txt
+++ b/modules/gfx/src/CMakeLists.txt
@@ -1,6 +1,7 @@
 set(OST_GFX_HEADERS
 render_pass.hh
 bitmap_io.hh
+collada_exporter.hh
 color.hh
 entity.hh
 entity_fw.hh
@@ -37,6 +38,9 @@ module_config.hh
 primitives.hh
 povray_fw.hh
 povray.hh
+exporter.hh
+exporter_fw.hh
+gost_exporter.hh
 )
 
 set(OST_GFX_COLOR_OPS_HEADERS
@@ -89,6 +93,7 @@ endif()
 
 set(OST_GFX_SOURCES
 bitmap_io.cc
+collada_exporter.cc
 color.cc
 primitives.cc
 entity.cc
@@ -108,6 +113,7 @@ vertex_array.cc
 vertex_array_helper.cc
 material.cc
 povray.cc
+gost_exporter.cc
 texture.cc
 color_ops/color_op.cc
 color_ops/by_element_color_op.cc
diff --git a/modules/gfx/src/collada_exporter.cc b/modules/gfx/src/collada_exporter.cc
new file mode 100644
index 0000000000000000000000000000000000000000..902334f851fc0df651f58f380e3c3771e8ae1e96
--- /dev/null
+++ b/modules/gfx/src/collada_exporter.cc
@@ -0,0 +1,279 @@
+//------------------------------------------------------------------------------
+// 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 <sstream>
+#include <boost/format.hpp>
+
+#include "collada_exporter.hh"
+#include "scene.hh"
+
+namespace ost { namespace gfx {
+
+ColladaExporter::ColladaExporter(const std::string& file, float scale):
+  file_(file),
+  out_(file_.c_str()),
+  scale_(scale),
+  obj_()
+{
+  out_ << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
+  out_ << "<COLLADA version=\"1.4.0\" xmlns=\"http://www.collada.org/2005/11/COLLADASchema\">\n";
+}
+
+ColladaExporter::~ColladaExporter()
+{
+  out_ << "</COLLADA>\n";
+}
+
+void ColladaExporter::SceneStart(const Scene* scene)
+{
+  out_ << " <library_cameras>\n";
+	out_ << "  <camera id=\"Camera-Camera\" name=\"Camera-Camera\">\n";
+  out_ << "   <optics>\n";
+  out_ << "    <technique_common>\n";
+  out_ << "      <perspective>\n";
+  out_ << "       <yfov>" << scene->GetFOV() << "</yfov>\n";
+  out_ << "       <znear>" << scene->GetNear() << "</znear>\n";
+  out_ << "       <zfar>" << scene->GetFar() << "</zfar>\n";
+  out_ << "      </perspective>\n";
+  out_ << "    </technique_common>\n";
+  out_ << "   </optics>\n";
+	out_ << "  </camera>\n";
+  out_ << " </library_cameras>\n";
+
+  out_ << " <library_geometries>\n" << std::endl;
+}
+
+void ColladaExporter::SceneEnd(const Scene* scene)
+{
+  out_ << " </library_geometries>\n" << std::endl;
+
+  out_ << " <library_visual_scenes>\n";
+  out_ << "  <visual_scene id=\"Scene\" name=\"Scene\">\n";
+
+  out_ << "   <node id=\"Camera\" name=\"Camera\">\n";
+  out_ << "    <instance_camera url=\"#Camera-Camera\"/>\n";
+  out_ << "   </node>\n";
+
+  out_ << "   <node id=\"Root\" name=\"Root\">\n";
+  out_ << "    <matrix>\n";
+  geom::Mat4 tm=scene->GetTransform().GetMatrix();
+  out_ << "    " << tm(0,0) << " " << tm(0,1) << " " << tm(0,2) << " " << tm(0,3) << "\n";
+  out_ << "    " << tm(1,0) << " " << tm(1,1) << " " << tm(1,2) << " " << tm(1,3) << "\n";
+  out_ << "    " << tm(2,0) << " " << tm(2,1) << " " << tm(2,2) << " " << tm(2,3) << "\n";
+  out_ << "    " << tm(3,0) << " " << tm(3,1) << " " << tm(3,2) << " " << tm(3,3) << "\n";
+  out_ << "    </matrix>\n";
+  for(std::vector<std::string>::const_iterator oit=obj_.begin();oit!=obj_.end();++oit) {
+    out_ << "    <node id=\"" << *oit << "\" name=\"" << *oit <<"\">\n";
+    out_ << "     <instance_geometry url=\"#" << *oit << "\"/>\n";
+    out_ << "    </node>\n";
+  }
+  out_ << "   </node>\n";
+  out_ << "  </visual_scene>\n";
+	out_ << " </library_visual_scenes>\n";
+
+	out_ << " <scene>\n";
+  out_ << "  <instance_visual_scene url=\"#Scene\"/>\n";
+	out_ << " </scene>\n";
+}
+
+void ColladaExporter::NodeStart(const std::string& name, NodeType t)
+{
+  if(name!="Scene") {
+    obj_.push_back(name);
+    out_ << "<geometry id=\"" << name << "\" name=\"" << name << "\">\n";
+    out_ << " <mesh>\n";
+  }
+}
+
+void ColladaExporter::NodeEnd(const std::string& name)
+{
+  if(name!="Scene") {
+    out_ << " </mesh>\n";
+    out_ << "</geometry>\n";
+  }
+}
+
+void ColladaExporter::WriteVertexData(const float* vdata,
+                                      const float* ndata, 
+                                      const float* cdata,
+                                      const float* tdata,
+                                      size_t stride2, size_t count)
+{
+  std::string name=obj_.back();
+  size_t stride=stride2/sizeof(float);
+
+  out_ << "  <source id=\"" << name+"-Positions" << "\">\n";
+  out_ << "   <float_array count=\"" << count*3 << "\" id=\"" << name+"-Positions-array" << "\">\n";
+  if(vdata) {
+    const float* src=vdata;
+    for(unsigned int i=0;i<count;++i) {
+      out_ << scale_*src[0] << " ";
+      out_ << scale_*src[1] << " ";
+      out_ << scale_*src[2] << " ";
+      src+=stride;
+    }
+  } else {
+    for(unsigned int i=0;i<count;++i) {
+      out_ << "0.0 0.0 0.0 ";
+    }
+  }
+  out_ << "   </float_array>\n";
+  out_ << "   <technique_common>\n";
+  out_ << "    <accessor count=\"" << count << "\" source=\"#" << name + "-Positions-array" << "\" stride=\"3\">\n";
+  out_ << "     <param name=\"X\" type=\"float\"/>\n";
+  out_ << "     <param name=\"Y\" type=\"float\"/>\n";
+  out_ << "     <param name=\"Z\" type=\"float\"/>\n";
+  out_ << "    </accessor>\n";
+  out_ << "   </technique_common>\n";
+  out_ << "  </source>\n";
+
+  // normals, lots of code duplication for now
+  out_ << "  <source id=\"" << name+"-Normals" << "\">\n";
+  out_ << "   <float_array count=\"" << count*3 << "\" id=\"" << name+"-Normals-array" << "\">\n";
+  if(ndata) {
+    const float* src=ndata;
+    for(unsigned int i=0;i<count;++i) {
+      out_ << src[0] << " ";
+      out_ << src[1] << " ";
+      out_ << src[2] << " ";
+      src+=stride;
+    }
+  } else {
+    for(unsigned int i=0;i<count;++i) {
+      out_ << "0.0 0.0 0.0 ";
+    }
+  }
+  out_ << "   </float_array>\n";
+  out_ << "   <technique_common>\n";
+  out_ << "    <accessor count=\"" << count << "\" source=\"#" << name + "-Normals-array" << "\" stride=\"3\">\n";
+  out_ << "     <param name=\"X\" type=\"float\"/>\n";
+  out_ << "     <param name=\"Y\" type=\"float\"/>\n";
+  out_ << "     <param name=\"Z\" type=\"float\"/>\n";
+  out_ << "    </accessor>\n";
+  out_ << "   </technique_common>\n";
+  out_ << "  </source>\n";
+
+  // colors, again lots of code duplication
+  out_ << "  <source id=\"" << name+"-Colors" << "\">\n";
+  //out_ << "   <float_array count=\"" << count*4 << "\" id=\"" << name+"-Colors-array" << "\">\n";
+  out_ << "   <float_array count=\"" << count*3 << "\" id=\"" << name+"-Colors-array" << "\">\n";
+  if(cdata) {
+    const float* src=cdata;
+    for(unsigned int i=0;i<count;++i) {
+      out_ << src[0] << " ";
+      out_ << src[1] << " ";
+      out_ << src[2] << " ";
+      //out_ << src[3] << " ";
+      src+=stride;
+    }
+  } else {
+    for(unsigned int i=0;i<count;++i) {
+      out_ << "0.0 0.0 0.0 ";
+    }
+  }
+  out_ << "   </float_array>\n";
+  out_ << "   <technique_common>\n";
+  //out_ << "    <accessor count=\"" << count << "\" source=\"#" << name + "-Colors-array" << "\" stride=\"4\">\n";
+  out_ << "    <accessor count=\"" << count << "\" source=\"#" << name + "-Colors-array" << "\" stride=\"3\">\n";
+  out_ << "     <param name=\"R\" type=\"float\"/>\n";
+  out_ << "     <param name=\"G\" type=\"float\"/>\n";
+  out_ << "     <param name=\"B\" type=\"float\"/>\n";
+  //out_ << "     <param name=\"A\" type=\"float\"/>\n";
+  out_ << "    </accessor>\n";
+  out_ << "   </technique_common>\n";
+  out_ << "  </source>\n";
+
+  out_ << "  <vertices id=\"" << name+"-Vertex" << "\">\n";
+  out_ << "   <input semantic=\"POSITION\" source =\"#" << name+"-Positions" << "\"/>\n";
+  //out_ << "   <input semantic=\"NORMAL\" source =\"#" << name+"-Normals" << "\"/>\n";
+  //out_ << "   <input semantic=\"COLOR\" source =\"#" << name+"-Colors" << "\"/>\n";
+  out_ << "  </vertices>\n";
+}
+
+void ColladaExporter::WritePointData(const unsigned int* i, size_t count)
+{
+}
+
+void ColladaExporter::WriteLineData(const unsigned int* ij, size_t count)
+{
+}
+
+void ColladaExporter::WriteTriData(const unsigned int* ijk, size_t count)
+{
+  std::string name=obj_.back();
+
+  out_ << "  <triangles count=\"" << count << "\">\n";
+  out_ << "   <input offset=\"0\" semantic=\"VERTEX\" source =\"#" << name+"-Vertex" << "\"/>\n";
+  out_ << "   <input offset=\"1\" semantic=\"NORMAL\" source =\"#" << name+"-Normals" << "\"/>\n";
+  out_ << "   <input offset=\"2\" semantic=\"COLOR\" source =\"#" << name+"-Colors" << "\"/>\n";
+  out_ << "   <p>\n";
+  for(unsigned int c=0;c<count*3;c+=3) {
+    out_ << ijk[c+0] << " ";
+    out_ << ijk[c+0] << " ";
+    out_ << ijk[c+0] << " ";
+    out_ << ijk[c+1] << " ";
+    out_ << ijk[c+1] << " ";
+    out_ << ijk[c+1] << " ";
+    out_ << ijk[c+2] << " ";
+    out_ << ijk[c+2] << " ";
+    out_ << ijk[c+2] << " ";
+  }
+  out_ << "   </p>\n";
+  out_ << "  </triangles>\n";
+}
+
+void ColladaExporter::WriteQuadData(const unsigned int* ijkl, size_t count)
+{
+  std::string name=obj_.back();
+
+  out_ << "  <triangles count=\"" << count << "\">\n";
+  out_ << "   <input offset=\"0\" semantic=\"VERTEX\" source =\"#" << name+"-Vertex" << "\"/>\n";
+  out_ << "   <input offset=\"1\" semantic=\"NORMAL\" source =\"#" << name+"-Normals" << "\"/>\n";
+  out_ << "   <input offset=\"2\" semantic=\"COLOR\" source =\"#" << name+"-Colors" << "\"/>\n";
+  out_ << "   <p>\n";
+  for(unsigned int c=0;c<count*4;c+=4) {
+    out_ << ijkl[c+0] << " ";
+    out_ << ijkl[c+0] << " ";
+    out_ << ijkl[c+0] << " ";
+    out_ << ijkl[c+1] << " ";
+    out_ << ijkl[c+1] << " ";
+    out_ << ijkl[c+1] << " ";
+    out_ << ijkl[c+2] << " ";
+    out_ << ijkl[c+2] << " ";
+    out_ << ijkl[c+2] << " ";
+    //
+    out_ << ijkl[c+0] << " ";
+    out_ << ijkl[c+0] << " ";
+    out_ << ijkl[c+0] << " ";
+    out_ << ijkl[c+2] << " ";
+    out_ << ijkl[c+2] << " ";
+    out_ << ijkl[c+2] << " ";
+    out_ << ijkl[c+3] << " ";
+    out_ << ijkl[c+3] << " ";
+    out_ << ijkl[c+3] << " ";
+  }
+  out_ << "   </p>\n";
+  out_ << "  </triangles>\n";
+}
+
+}} // ns
diff --git a/modules/gfx/src/collada_exporter.hh b/modules/gfx/src/collada_exporter.hh
new file mode 100644
index 0000000000000000000000000000000000000000..c0192a10097e6cb0d2b48801431a3be2437509d5
--- /dev/null
+++ b/modules/gfx/src/collada_exporter.hh
@@ -0,0 +1,62 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+#ifndef OST_GFX_COLLADA_EXPORTER_HH
+#define OST_GFX_COLLADA_EXPORTER_HH
+
+/*
+  Author: Ansgar Philippsen
+*/
+
+#include <string>
+#include <fstream>
+#include <vector>
+
+#include "module_config.hh"
+#include "exporter.hh"
+
+namespace ost { namespace gfx {
+
+class DLLEXPORT_OST_GFX ColladaExporter: public Exporter
+{
+public:
+  ColladaExporter(const std::string& collada_file, float scale=1.0);
+  virtual ~ColladaExporter();
+
+  // exporter interface
+  virtual void SceneStart(const Scene* scene);
+  virtual void SceneEnd(const Scene* scene);
+  virtual void NodeStart(const std::string& name, NodeType t);
+  virtual void NodeEnd(const std::string& name);
+  virtual void WriteVertexData(const float* v, const float* n, const float* c, const float* t, 
+                               size_t stride, size_t count);
+  virtual void WritePointData(const unsigned int* i, size_t count);
+  virtual void WriteLineData(const unsigned int* ij, size_t count);
+  virtual void WriteTriData(const unsigned int* ijk, size_t count);
+  virtual void WriteQuadData(const unsigned int* ijkl, size_t count);
+
+private:
+  std::string file_;
+  std::ofstream out_;
+  float scale_;
+  std::vector<std::string> obj_;
+};
+
+}} // ns
+
+#endif
diff --git a/modules/gfx/src/color.cc b/modules/gfx/src/color.cc
index f99de522b962df1c1ce030b74c97a551fb0cd492..f40e69c53629e136a661b380424d4e075419ae50 100644
--- a/modules/gfx/src/color.cc
+++ b/modules/gfx/src/color.cc
@@ -81,9 +81,9 @@ geom::Vec3 HSVtoRGB(const geom::Vec3& hsv)
 geom::Vec3 RGBtoHSV(const geom::Vec3& rgb)
 {
   geom::Vec3 hsv;
-  double var_R = ( rgb[0] / 255.0 );
-  double var_G = ( rgb[1] / 255.0 );
-  double var_B = ( rgb[2] / 255.0 );
+  double var_R = ( rgb[0] );
+  double var_G = ( rgb[1] );
+  double var_B = ( rgb[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 );
@@ -107,13 +107,18 @@ geom::Vec3 RGBtoHSV(const geom::Vec3& rgb)
     } else if ( var_B == var_Max ){
       hsv[0] = ( 2.0 / 3.0 ) + del_G - del_R;
     }
-    if ( hsv[0] < 0 ){
-      hsv[0] += 1;
+    if ( hsv[0] < 0.0 ){
+      hsv[0] += 1.0;
     }
-    if ( hsv[0] > 1 ){
-      hsv[0] -= 1;
+    if ( hsv[0] > 1.0 ){
+      hsv[0] -= 1.0;
     }
   }
+
+  hsv[0]=hsv[0]*360.0;
+  hsv[1]=hsv[1]*100.0;
+  hsv[2]=hsv[2]*100.0;
+
   return hsv;
 }
 } // anon ns
@@ -126,6 +131,11 @@ geom::Vec3 Color::ToHSV()
 
 Color HSV(double h, double s, double v)
 {
+  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]);
 }
diff --git a/modules/gfx/src/color.hh b/modules/gfx/src/color.hh
index 1fdee9fa64eb146ee45e8a4882e833dc43ee4b0e..533381dbc07d06880f2f2b3ab00a2b1a3e72c0f3 100644
--- a/modules/gfx/src/color.hh
+++ b/modules/gfx/src/color.hh
@@ -85,6 +85,13 @@ private:
   float rgba[4];
 };
 
+/*!
+  \brief HSV color spec
+
+  h: Hue from 0 to 360 (0=red, 120=green, 240=blue)
+  s: Saturation from 0 (no color) to 100 (full color)
+  v: Value from 0 (no light, black) to 100 (full light)
+*/
 Color DLLEXPORT_OST_GFX HSV(double h, double s, double v);
 
 DLLEXPORT_OST_GFX std::ostream& operator<<(std::ostream&, const Color& c);
diff --git a/modules/gfx/src/entity.cc b/modules/gfx/src/entity.cc
index b5f0f6b75c4e6d516caa1bcffa28c26fbbe45ac8..dff4bfa1fb8465036438a59ebdf8f72dc2a3277b 100644
--- a/modules/gfx/src/entity.cc
+++ b/modules/gfx/src/entity.cc
@@ -54,6 +54,7 @@
 #if OST_SHADER_SUPPORT_ENABLED
 #include "shader.hh"
 #endif
+#include "exporter.hh"
 
 namespace ost {
 
@@ -401,6 +402,23 @@ void Entity::CustomRenderPov(PovState& pov)
   }
 }
 
+void Entity::Export(Exporter* ex)
+{
+  ex->NodeStart(GetName(),Exporter::OBJ);
+  // in the simplest case, just export va
+  if(rebuild_ || refresh_) {
+    PreRenderGL(true);
+  }
+
+  for (RendererMap::iterator it=renderer_.begin(); it!=renderer_.end(); ++it) {
+    if(it->second->IsEnabled() && it->second->HasDataToRender()){
+      it->second->Export(ex);
+    }
+  }
+  
+  ex->NodeEnd(GetName());
+}
+
 mol::AtomHandle Entity::PickAtom(const geom::Line3& line, Real line_width)
 {
   mol::AtomHandle picked_atom;
diff --git a/modules/gfx/src/entity.hh b/modules/gfx/src/entity.hh
index 7e6d595fa27f0e34c7d4e7eff73732f28dbca6a6..7663fe3782fe053df4eb7f0428d6401da26905c9 100644
--- a/modules/gfx/src/entity.hh
+++ b/modules/gfx/src/entity.hh
@@ -324,6 +324,8 @@ public:
   void SetSeqHack(bool b);
   bool GetSeqHack() const;
   
+  virtual void Export(Exporter* ex);
+
 protected:
 
   virtual void CustomPreRenderGL(bool flag);
diff --git a/modules/gfx/src/exporter.hh b/modules/gfx/src/exporter.hh
new file mode 100644
index 0000000000000000000000000000000000000000..20b0601aee6a110a4c713a687db50d4834c5978c
--- /dev/null
+++ b/modules/gfx/src/exporter.hh
@@ -0,0 +1,56 @@
+//------------------------------------------------------------------------------
+// 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_EXPORTER_HH
+#define OST_GFX_EXPORTER_HH
+
+#include <ost/gfx/module_config.hh>
+
+namespace ost { namespace gfx {
+
+class Scene;
+
+class DLLEXPORT_OST_GFX Exporter
+{
+public:
+  enum NodeType {
+    ROOT=1,
+    GROUP=2,
+    OBJ=3
+  };
+
+  virtual ~Exporter() {}
+  virtual void SceneStart(const Scene* scene) {}
+  virtual void SceneEnd(const Scene* scene) {}
+
+  virtual void NodeStart(const std::string& name, NodeType t) {}
+  virtual void NodeEnd(const std::string& name) {}
+  
+  // this indicates beginning of new data, including a reset of the indices
+  // may occur more than once for a given node
+  virtual void WriteVertexData(const float* v, const float* n, const float* c, const float* t,
+                               size_t stride, size_t count) {}
+  virtual void WritePointData(const unsigned int* i, size_t count) {}
+  virtual void WriteLineData(const unsigned int* ij, size_t count) {}
+  virtual void WriteTriData(const unsigned int* ijk, size_t count) {}
+  virtual void WriteQuadData(const unsigned int* ijkl, size_t count) {}
+};
+
+}} // ns
+
+#endif
diff --git a/modules/gfx/src/exporter_fw.hh b/modules/gfx/src/exporter_fw.hh
new file mode 100644
index 0000000000000000000000000000000000000000..499248014e24d9df5374569c7a66d5227a4c8443
--- /dev/null
+++ b/modules/gfx/src/exporter_fw.hh
@@ -0,0 +1,28 @@
+//------------------------------------------------------------------------------
+// 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_EXPORTER_FW_HH
+#define OST_GFX_EXPORTER_FW_HH
+
+namespace ost { namespace gfx {
+
+  class Exporter;
+
+}} // ns
+
+#endif
diff --git a/modules/gfx/src/gfx_node.cc b/modules/gfx/src/gfx_node.cc
index e7f038a2668e2d4fdd162e00f29e4acd37592881..8d417aeec6660d3ecf3aa689cf68d3e90c781fa7 100644
--- a/modules/gfx/src/gfx_node.cc
+++ b/modules/gfx/src/gfx_node.cc
@@ -18,9 +18,11 @@
 //------------------------------------------------------------------------------
 #include <boost/bind.hpp>
 #include <ost/dyn_cast.hh>
+
 #include "gfx_node.hh"
 #include "gfx_object.hh"
 #include "scene.hh"
+#include "exporter.hh"
 
 namespace ost { namespace gfx {
 
@@ -101,6 +103,16 @@ void GfxNode::RenderPov(PovState& pov)
   }
 }
 
+void GfxNode::Export(Exporter* ex)
+{
+  if(!IsVisible()) return;
+  ex->NodeStart(GetName(),Exporter::GROUP);
+  for(GfxNodeVector::iterator it=node_vector_.begin();it!=node_vector_.end();++it) {
+    (*it)->Export(ex);
+  }
+  ex->NodeEnd(GetName());
+}
+
 String GfxNode::GetName() const
 {
   return name_;
diff --git a/modules/gfx/src/gfx_node.hh b/modules/gfx/src/gfx_node.hh
index b211ca8a9ccb7cda837e109a338ac79d33201301..6cff8388518b96924eec6802dad40e5631cf8c4c 100644
--- a/modules/gfx/src/gfx_node.hh
+++ b/modules/gfx/src/gfx_node.hh
@@ -34,6 +34,7 @@
 #include "gfx_object_fw.hh"
 #include "gfx_node_visitor.hh"
 #include "povray_fw.hh"
+#include "exporter_fw.hh"
 
 namespace ost { namespace gfx {
 
@@ -56,10 +57,11 @@ class DLLEXPORT_OST_GFX GfxNode: public boost::enable_shared_from_this<GfxNode>
   // render all child leaves and nodes
   virtual void RenderGL(RenderPass pass);
 
-
   // render all child leaves and nodes into POVray state
   virtual void RenderPov(PovState& pov);
 
+  virtual void Export(Exporter* ex);
+
   // visitor interface
   virtual void Apply(GfxNodeVisitor& v, GfxNodeVisitor::Stack st);
 
diff --git a/modules/gfx/src/gfx_object.cc b/modules/gfx/src/gfx_object.cc
index 8a45e784b52cb9f18ba77fe354d9262bc355bc9c..1f0486017c6139adc74134f712d72409486744cd 100644
--- a/modules/gfx/src/gfx_object.cc
+++ b/modules/gfx/src/gfx_object.cc
@@ -33,6 +33,7 @@
 
 #include "povray.hh"
 #include "impl/mapped_property.hh"
+#include "exporter.hh"
 
 #if OST_IMG_ENABLED
 #  include <ost/img/alg/stat.hh>
@@ -180,6 +181,9 @@ void GfxObj::RenderGL(RenderPass pass)
   }
 }
 
+void GfxObj::InitGL()
+{
+}
 
 void GfxObj::RenderPov(PovState& pov)
 {
@@ -195,6 +199,20 @@ void GfxObj::RenderPov(PovState& pov)
   }
 }
 
+
+void GfxObj::Export(Exporter* ex)
+{
+  if(IsVisible()) {
+    ex->NodeStart(GetName(),Exporter::OBJ);
+    // in the simplest case, just export va
+    if(rebuild_ || refresh_) {
+      PreRenderGL(true);
+    }
+    va_.Export(ex);
+    ex->NodeEnd(GetName());
+  }
+}
+
 void GfxObj::Apply(GfxNodeVisitor& v, GfxNodeVisitor::Stack st)
 {
   v.VisitObject(this,st);
@@ -322,18 +340,33 @@ void GfxObj::SetOutlineWidth(float f)
   Scene::Instance().RequestRedraw();
 }
 
+float GfxObj::GetOutlineWidth() const
+{
+  return va_.GetOutlineWidth();
+}
+
 void GfxObj::SetOutlineExpandFactor(float f)
 {
   va_.SetOutlineExpandFactor(f);
   Scene::Instance().RequestRedraw();
 }
 
+float GfxObj::GetOutlineExpandFactor() const
+{
+  return va_.GetOutlineExpandFactor();
+}
+
 void GfxObj::SetOutlineExpandColor(const Color& c)
 {
   va_.SetOutlineExpandColor(c);
   Scene::Instance().RequestRedraw();
 }
 
+Color GfxObj::GetOutlineExpandColor() const
+{
+  return va_.GetOutlineExpandColor();
+}
+
 void GfxObj::SetOpacity(float o)
 {
   opacity_=o;
diff --git a/modules/gfx/src/gfx_object.hh b/modules/gfx/src/gfx_object.hh
index b59009ba2a07700da07618bc95ac71a4c7496552..d241be75e19f15158d173554f01384b26cdab15f 100644
--- a/modules/gfx/src/gfx_object.hh
+++ b/modules/gfx/src/gfx_object.hh
@@ -40,6 +40,7 @@
 #include "gfx_prim.hh"
 #include "vertex_array.hh"
 #include "input.hh"
+#include "exporter_fw.hh"
 
 namespace ost { namespace gfx {
 
@@ -56,7 +57,8 @@ public:
   virtual void DeepSwap(GfxObj& go);
   virtual void RenderGL(RenderPass pass);
   virtual void RenderPov(PovState& pov);
-  virtual void Apply(GfxNodeVisitor& v,GfxNodeVisitor::Stack st);
+  virtual void Export(Exporter* ex);
+  virtual void Apply(GfxNodeVisitor& v, GfxNodeVisitor::Stack st);
   virtual int GetType() const;
   //
 
@@ -75,10 +77,15 @@ public:
   virtual void SetAALines(bool f);
   virtual void SetLineHalo(float f);
   virtual void SetOutline(bool f);
+  virtual bool GetOutline() const {return outline_flag_;};
   virtual void SetOutlineMode(int m);
+  virtual int GetOutlineMode() const {return outline_mode_;}
   virtual void SetOutlineWidth(float f);
+  virtual float GetOutlineWidth() const;
   virtual void SetOutlineExpandFactor(float f);
+  virtual float GetOutlineExpandFactor() const;
   virtual void SetOutlineExpandColor(const Color& c);
+  virtual Color GetOutlineExpandColor() const;
   virtual void SetOpacity(float f);
   virtual float GetOpacity() const {return opacity_;}
   virtual void ColorBy(const mol::EntityView& ev, 
@@ -113,6 +120,15 @@ public:
   */
   virtual void CustomRenderGL(RenderPass pass);
 
+  // implemented in derived classes to deal with initialization etc
+  // called just before CustomRenderGL is called
+  // the boolean flag indicated that a re-build was requested
+  virtual void CustomPreRenderGL(bool rebuild);
+
+  // implemented in derived classes for first GL initialization
+  // which should be done here, not in the ctor
+  virtual void InitGL();
+
   // implemented in derived classes for the actual POVray export
   virtual void CustomRenderPov(PovState& pov);
 
@@ -181,7 +197,6 @@ public:
  protected:
   
   void PreRenderGL(bool flag);
-  virtual void CustomPreRenderGL(bool flag);
 
  private:
   GfxObj(const GfxObj& o);
diff --git a/modules/gfx/src/gfx_object_base.hh b/modules/gfx/src/gfx_object_base.hh
index 7884c7de4744c6a0598ec9b1c35578c72b9d0c1a..eb6c7c21743805e237377bc64e15ced0d61f3885 100644
--- a/modules/gfx/src/gfx_object_base.hh
+++ b/modules/gfx/src/gfx_object_base.hh
@@ -91,14 +91,26 @@ class DLLEXPORT_OST_GFX GfxObjBase: public GfxNode
 
   /// \brief turn outline rendering on or off
   virtual void SetOutline(bool f) = 0;
-  /// \brief set outline mode
+  /// \brief get state of outline rendering
+  virtual bool GetOutline() const = 0;
+  /// \brief set outline mode, 1, 2 or 3
   virtual void SetOutlineMode(int m) = 0;
-  /// \brief set outline width (modes 1 + 2)
+  /// \brief get current outline mode
+  virtual int GetOutlineMode() const = 0;
+  /// \brief set outline width in pixels (modes 1 + 2)
+  /// this does not scale with resolution
   virtual void SetOutlineWidth(float f) = 0;
-  /// \brief set outline tweak factor (mode 3)
+  /// \brief get current outline width
+  virtual float GetOutlineWidth() const = 0;
+  /// \brief set outline expansion factor (mode 3)
+  /// this scales with resolution
   virtual void SetOutlineExpandFactor(float f) = 0;
+  /// \brief get current outline expand factor (mode 3)
+  virtual float GetOutlineExpandFactor() const = 0;
   /// \brief set outline color (mode 3)
   virtual void SetOutlineExpandColor(const Color& c) = 0;
+  /// \brief get current outline color (mode 3)
+  virtual Color GetOutlineExpandColor() const = 0;
 
   /// \brief set opacity (1 = no transparency)
   virtual void SetOpacity(float f) = 0;
diff --git a/modules/gfx/src/gost_exporter.cc b/modules/gfx/src/gost_exporter.cc
new file mode 100644
index 0000000000000000000000000000000000000000..79a6e9b28390f1ce2d1890e88d824de48856e358
--- /dev/null
+++ b/modules/gfx/src/gost_exporter.cc
@@ -0,0 +1,277 @@
+//------------------------------------------------------------------------------
+// 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 <sstream>
+
+#include "gost_exporter.hh"
+#include "scene.hh"
+
+namespace ost { namespace gfx {
+
+  namespace {
+    enum TYPE {
+      GOST_UNKNOWN=0,
+      GOST_SCENE=1,
+      GOST_START_NODE=2,
+      GOST_END_NODE=3,
+      GOST_DATA=4,
+      GOST_FRAME=5
+    };
+
+    enum NODE_TYPE {
+      GOST_ROOT=1,
+      GOST_GROUP=2,
+      GOST_OBJ=3
+    };
+
+    enum DATA_TYPE {
+      GOST_VDATA=1,
+      GOST_NDATA=2,
+      GOST_CDATA=3,
+      GOST_TDATA=4,
+      GOST_PINDEX=5,
+      GOST_LINDEX=6,
+      GOST_TINDEX=7,
+      GOST_QINDEX=8
+    };
+  }
+
+GostExporter::GostExporter(const std::string& fname):
+  file_(0)
+{
+  file_=fopen(fname.c_str(),"w");
+  if(!file_) {
+    std::ostringstream m;
+    m << "Could not open '" << fname << "' for writing";
+    throw Error(m.str());
+  }
+  char headr[]={'G','O','S','T','1','0'};
+  fwrite(headr,sizeof(char),6,file_);
+}
+
+GostExporter::~GostExporter()
+{
+  fclose(file_);
+  file_=0;
+}
+
+void GostExporter::SceneStart(const Scene* scene)
+{
+  int type=GOST_SCENE;
+  int subtype=0;
+  size_t size=0;
+
+  fwrite(&type,sizeof(int),1,file_);
+  fwrite(&subtype,sizeof(int),1,file_);
+  fwrite(&size,sizeof(size_t),1,file_);
+}
+
+void GostExporter::SceneEnd(const Scene* scene)
+{}
+
+void GostExporter::NodeStart(const std::string& name, NodeType t)
+{
+  int type=GOST_START_NODE;
+  int subtype=0;
+  if(t==Exporter::ROOT) subtype=GOST_ROOT;
+  else if(t==Exporter::GROUP) subtype=GOST_GROUP;
+  else if(t==Exporter::OBJ) subtype=GOST_OBJ;
+  size_t size=name.size();
+
+  fwrite(&type,sizeof(int),1,file_);
+  fwrite(&subtype,sizeof(int),1,file_);
+  fwrite(&size,sizeof(size_t),1,file_);
+  fwrite(name.c_str(),sizeof(char), size,file_);
+}
+
+void GostExporter::NodeEnd(const std::string& name)
+{
+  int type=GOST_END_NODE;
+  int subtype=0;
+  size_t size=0;
+
+  fwrite(&type,sizeof(int),1,file_);
+  fwrite(&subtype,sizeof(int),1,file_);
+  fwrite(&size,sizeof(size_t),1,file_);
+}
+
+void GostExporter::WriteVertexData(const float* vdata, const float* ndata, 
+                                   const float* cdata, const float* tdata,
+                                   size_t stride2, size_t count)
+{
+  std::vector<float> buffer(count*4);
+  int type=GOST_DATA;
+  int subtype=0;
+  size_t size=0;
+  size_t stride=stride2/sizeof(float);
+
+  if(vdata) {
+    // positions
+    subtype=GOST_VDATA;
+    size=sizeof(float)*3*count+sizeof(size_t);
+    float* dest=&buffer[0];
+    const float* src=vdata;
+    for(size_t i=0;i<count;++i) {
+      dest[0]=src[0];
+      dest[1]=src[1];
+      dest[2]=src[2];
+      src+=stride;
+      dest+=3;
+    }
+    fwrite(&type,sizeof(int),1,file_);
+    fwrite(&subtype,sizeof(int),1,file_);
+    fwrite(&size,sizeof(size_t),1,file_);
+    //
+    fwrite(&count,sizeof(size_t),1,file_);
+    fwrite(&buffer[0],sizeof(float),3*count,file_);
+  }
+
+  if(ndata) {
+    // normals
+    subtype=GOST_NDATA;
+    size=sizeof(float)*count*3+sizeof(size_t);
+    float* dest=&buffer[0];
+    const float* src=ndata;
+    for(size_t i=0;i<count;++i) {
+      dest[0]=src[0];
+      dest[1]=src[1];
+      dest[2]=src[2];
+      src+=stride;
+      dest+=3;
+    }
+    fwrite(&type,sizeof(int),1,file_);
+    fwrite(&subtype,sizeof(int),1,file_);
+    fwrite(&size,sizeof(size_t),1,file_);
+    //
+    fwrite(&count,sizeof(size_t),1,file_);
+    fwrite(&buffer[0],sizeof(float),3*count,file_);
+  }
+  
+  if(cdata) {
+    // colors
+    subtype=GOST_CDATA;
+    size=sizeof(float)*count*4+sizeof(size_t);
+    float* dest=&buffer[0];
+    const float* src=cdata;
+    for(size_t i=0;i<count;++i) {
+      dest[0]=src[0];
+      dest[1]=src[1];
+      dest[2]=src[2];
+      dest[3]=src[3];
+      src+=stride;
+      dest+=4;
+    }
+    fwrite(&type,sizeof(int),1,file_);
+    fwrite(&subtype,sizeof(int),1,file_);
+    fwrite(&size,sizeof(size_t),1,file_);
+    //
+    fwrite(&count,sizeof(size_t),1,file_);
+    fwrite(&buffer[0],sizeof(float),4*count,file_);
+  }
+
+  if(tdata) {
+    // texture coordinates
+    subtype=GOST_TDATA;
+    size=sizeof(float)*count*2+sizeof(size_t);
+    float* dest=&buffer[0];
+    const float* src=tdata;
+    for(size_t i=0;i<count;++i) {
+      dest[0]=src[0];
+      dest[1]=src[1];
+      src+=stride;
+      dest+=2;
+    }
+    fwrite(&type,sizeof(int),1,file_);
+    fwrite(&subtype,sizeof(int),1,file_);
+    fwrite(&size,sizeof(size_t),1,file_);
+    //
+    fwrite(&count,sizeof(size_t),1,file_);
+    fwrite(&buffer[0],sizeof(float),2*count,file_);
+  }
+}
+
+void GostExporter::WritePointData(const unsigned int* i, size_t count)
+{
+  int type=GOST_DATA;
+  int subtype=GOST_PINDEX;
+  size_t size=sizeof(unsigned int)*count+sizeof(size_t);
+  fwrite(&type,sizeof(int),1,file_);
+  fwrite(&subtype,sizeof(int),1,file_);
+  fwrite(&size,sizeof(size_t),1,file_);
+  //
+  fwrite(&count,sizeof(size_t),1,file_);
+  fwrite(i,sizeof(unsigned int),count,file_);
+}
+
+void GostExporter::WriteLineData(const unsigned int* ij, size_t count)
+{
+  int type=GOST_DATA;
+  int subtype=GOST_LINDEX;
+  size_t size=sizeof(unsigned int)*2*count+sizeof(size_t);
+  fwrite(&type,sizeof(int),1,file_);
+  fwrite(&subtype,sizeof(int),1,file_);
+  fwrite(&size,sizeof(size_t),1,file_);
+  //
+  fwrite(&count,sizeof(size_t),1,file_);
+  fwrite(ij,sizeof(unsigned int),2*count,file_);
+}
+
+void GostExporter::WriteTriData(const unsigned int* ijk, size_t count)
+{
+  int type=GOST_DATA;
+  int subtype=GOST_TINDEX;
+  size_t size=sizeof(unsigned int)*3*count+sizeof(size_t);
+  fwrite(&type,sizeof(int),1,file_);
+  fwrite(&subtype,sizeof(int),1,file_);
+  fwrite(&size,sizeof(size_t),1,file_);
+  //
+  fwrite(&count,sizeof(size_t),1,file_);
+  fwrite(ijk,sizeof(unsigned int),3*count,file_);
+}
+
+void GostExporter::WriteQuadData(const unsigned int* ijkl, size_t count)
+{
+  int type=GOST_DATA;
+  int subtype=GOST_QINDEX;
+  size_t size=sizeof(unsigned int)*4*count+sizeof(size_t);
+  fwrite(&type,sizeof(int),1,file_);
+  fwrite(&subtype,sizeof(int),1,file_);
+  fwrite(&size,sizeof(size_t),1,file_);
+  //
+  fwrite(&count,sizeof(size_t),1,file_);
+  fwrite(ijkl,sizeof(unsigned int),4*count,file_);
+}
+
+void GostExporter::SetFrame(size_t frame)
+{
+  int type=GOST_FRAME;
+  int subtype=0;
+  size_t size=sizeof(size_t);
+  fwrite(&type,sizeof(int),1,file_);
+  fwrite(&subtype,sizeof(int),1,file_);
+  fwrite(&size,sizeof(size_t),1,file_);
+  //
+  fwrite(&frame,sizeof(size_t),1,file_);
+}
+
+}} // ns
diff --git a/modules/gfx/src/gost_exporter.hh b/modules/gfx/src/gost_exporter.hh
new file mode 100644
index 0000000000000000000000000000000000000000..03f47680eeabba9fe36236ff057b5e13f4385c9c
--- /dev/null
+++ b/modules/gfx/src/gost_exporter.hh
@@ -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
+//------------------------------------------------------------------------------
+#ifndef OST_GFX_GOST_EXPORTER_HH
+#define OST_GFX_GOST_EXPORTER_HH
+
+#include <cstdio>
+
+#include "exporter.hh"
+
+namespace ost { namespace gfx {
+
+class DLLEXPORT_OST_GFX GostExporter: public Exporter
+{
+public:
+  GostExporter(const std::string& fname);
+  virtual ~GostExporter();
+
+  // exporter interface
+  virtual void SceneStart(const Scene* scene);
+  virtual void SceneEnd(const Scene* scene);
+  virtual void NodeStart(const std::string& name, NodeType t);
+  virtual void NodeEnd(const std::string& name);
+  virtual void WriteVertexData(const float* v, const float* n, const float* c, const float* t, 
+                               size_t stride, size_t count);
+  virtual void WritePointData(const unsigned int* i, size_t count);
+  virtual void WriteLineData(const unsigned int* ij, size_t count);
+  virtual void WriteTriData(const unsigned int* ijk, size_t count);
+  virtual void WriteQuadData(const unsigned int* ijkl, size_t count);
+
+  // gost interface
+  void SetFrame(size_t f);
+private:
+  FILE* file_;
+};
+
+}} // ns
+
+#endif
diff --git a/modules/gfx/src/impl/entity_renderer.cc b/modules/gfx/src/impl/entity_renderer.cc
index 3464d1292297e3161e3aaed4a1130974b7763fb1..fb22e24a375988bdcb36bf8b9b1b9b0e34695fef 100644
--- a/modules/gfx/src/impl/entity_renderer.cc
+++ b/modules/gfx/src/impl/entity_renderer.cc
@@ -156,6 +156,11 @@ void EntityRenderer::RenderPov(PovState& pov, const std::string& name)
   va_.RenderPov(pov,name);
 }
 
+void EntityRenderer::Export(Exporter* ex)
+{
+  va_.Export(ex);
+}
+
 bool EntityRenderer::HasSelection() const
 {
   return (sel_.IsValid() && sel_.GetAtomCount()>0);
diff --git a/modules/gfx/src/impl/entity_renderer.hh b/modules/gfx/src/impl/entity_renderer.hh
index ceed73fa4d8d2f41a739c949a6e978ae29b18fbc..14c0332c3b5a15d0d0f101b19aad3e9363d03047 100644
--- a/modules/gfx/src/impl/entity_renderer.hh
+++ b/modules/gfx/src/impl/entity_renderer.hh
@@ -39,8 +39,9 @@
 #include <ost/gfx/module_config.hh>
 #include <ost/gfx/render_pass.hh>
 #include <ost/gfx/vertex_array.hh>
+#include <ost/gfx/exporter_fw.hh>
+
 #include <ost/gfx/render_options/render_options.hh>
-#include <ost/gfx/impl/mapped_property.hh>
 
 #include <ost/gfx/color_ops/color_op.hh>
 #include <ost/gfx/color_ops/by_element_color_op.hh>
@@ -51,7 +52,9 @@
 #if OST_IMG_ENABLED
 #include <ost/gfx/color_ops/map_handle_color_op.hh>
 #endif //OST_IMG_ENABLED
-#include <ost/gfx/impl/entity_renderer_fw.hh>
+
+#include "mapped_property.hh"
+#include "entity_renderer_fw.hh"
 
 namespace ost { namespace gfx { namespace impl {
 
@@ -123,6 +126,9 @@ public:
   ///\brief povray rendering call
   virtual void RenderPov(PovState& pov, const std::string& name);
 
+  ///\brief scene exporter interface
+  virtual void Export(Exporter* ex);
+
   virtual bool CanSetOptions(RenderOptionsPtr& render_options)=0;
   virtual void SetOptions(RenderOptionsPtr& render_options)=0;
   
diff --git a/modules/gfx/src/prim_list.cc b/modules/gfx/src/prim_list.cc
index 6113aecfb45e02867496f1c6129a92d9da8db2a1..a9debc0edd67dfa55d9a4057fb9ad0b77bdf4d2f 100644
--- a/modules/gfx/src/prim_list.cc
+++ b/modules/gfx/src/prim_list.cc
@@ -38,7 +38,8 @@ PrimList::PrimList(const String& name):
   texts_(),
   sphere_detail_(4),
   arc_detail_(4),
-  simple_va_()
+  simple_va_(),
+  vas_()
 {}
 
 void PrimList::Clear()
@@ -48,13 +49,14 @@ void PrimList::Clear()
   spheres_.clear();
   cyls_.clear();
   texts_.clear();
+  vas_.clear();
   Scene::Instance().RequestRedraw();
   this->FlagRebuild();
 }
 
 geom::AlignedCuboid PrimList::GetBoundingBox() const
 {
-  if(points_.empty() && lines_.empty() && spheres_.empty() && cyls_.empty()) {
+  if(points_.empty() && lines_.empty() && spheres_.empty() && cyls_.empty() && texts_.empty() && vas_.empty()) {
     return geom::AlignedCuboid(geom::Vec3(-1,-1,-1),geom::Vec3(1,1,1));
   }
   geom::Vec3 minc(std::numeric_limits<float>::max(),
@@ -101,6 +103,11 @@ void PrimList::ProcessLimits(geom::Vec3& minc, geom::Vec3& maxc,
     minc=geom::Min(minc,tpos);
     maxc=geom::Max(maxc,tpos);
   }
+  for(std::vector<IndexedVertexArray>::const_iterator it=vas_.begin();it!=vas_.end();++it) {
+    geom::AlignedCuboid bb=it->GetBoundingBox();
+    minc=geom::Min(minc,bb.GetMin());
+    maxc=geom::Max(maxc,bb.GetMax());
+  }
   minc-=1.0;
   maxc+=1.0;
 }
@@ -152,12 +159,15 @@ void PrimList::CustomRenderGL(RenderPass pass)
     va_.RenderGL();
     simple_va_.RenderGL();
     render_text();
+    for(std::vector<IndexedVertexArray>::iterator it=vas_.begin();it!=vas_.end();++it) {
+      it->RenderGL();
+    }
   }
 }
 
 void PrimList::CustomRenderPov(PovState& pov)
 {
-  if(points_.empty() && lines_.empty()) return;
+  if(points_.empty() && lines_.empty() && spheres_.empty() && cyls_.empty()) return;
   pov.write_merge_or_union(GetName());
 
   for(SpherePrimList::const_iterator it=points_.begin();it!=points_.end();++it) {
@@ -262,6 +272,42 @@ void PrimList::SetColor(const Color& c)
   FlagRebuild();
 }
 
+void PrimList::AddMesh(float* v, float* n, float* c, size_t nv, unsigned int* i, size_t ni)
+{
+  static float dummy_normal[]={0.0,0.0,1.0};
+  static float dummy_color[]={1.0,1.0,1.0,1.0};
+  vas_.push_back(IndexedVertexArray());
+  IndexedVertexArray& va=vas_.back();
+  va.SetLighting(true);
+  va.SetTwoSided(true);
+  va.SetColorMaterial(true);
+  va.SetCullFace(false);
+  float* vv=v;
+  float* nn=n;
+  if(!n) {
+    nn=dummy_normal;
+    va.SetLighting(false);
+  }
+  float* cc=c;
+  if(!c) {
+    cc=dummy_color;
+  }
+  for(size_t k=0;k<nv;++k) {
+    va.Add(geom::Vec3(vv[0],vv[1],vv[2]),
+           geom::Vec3(nn[0],nn[1],nn[2]),
+           Color(cc[0],cc[1],cc[2],cc[3]));
+    vv+=3;
+    if(n) nn+=3;
+    if(c) cc+=4;
+  }
+  unsigned int* ii=i;
+  for(size_t k=0;k<ni;++k) {
+    va.AddTri(ii[0],ii[1],ii[2]);
+    ii+=3;
+  }
+  Scene::Instance().RequestRedraw();
+  FlagRebuild();
+}
 
 ////////////////////////////////
 // private methods
diff --git a/modules/gfx/src/prim_list.hh b/modules/gfx/src/prim_list.hh
index 4e8a4c297ea044eda07d2cc199a4988b3d7e4e23..395e53e2ad22ce359b37281caead22cad1a423e9 100644
--- a/modules/gfx/src/prim_list.hh
+++ b/modules/gfx/src/prim_list.hh
@@ -139,6 +139,24 @@ class DLLEXPORT_OST_GFX PrimList: public GfxObj
 
   // TODO: add point and line pixel width
 
+  /*!
+    \brief add triangle mesh
+
+    v : pointer to nv*3 floats for the positions (mandatory)
+    n : pointer to nv*3 floats for the normals (may be NULL)
+    c : pointer to nv*4 floats for the colors (may be NULL)
+    nv: number of vertices, normals, and colors
+    i : pointer to ni*3 vertex indices
+    ni: number of index triplets
+
+    Python interface, using numpy arrays:
+
+      AddMesh(vertex_array, normal_array, color_array, index_array)
+
+    where normal_array and color_array may be None
+  */
+  void AddMesh(float* v, float* n, float* c, size_t nv, unsigned int* i, size_t ni);
+
  protected:
   virtual void CustomPreRenderGL(bool flag);
 
@@ -152,6 +170,8 @@ class DLLEXPORT_OST_GFX PrimList: public GfxObj
   unsigned int arc_detail_;
 
   IndexedVertexArray simple_va_;
+
+  std::vector<IndexedVertexArray> vas_;
   
   void prep_simple_va();
   void prep_va();
diff --git a/modules/gfx/src/scene.cc b/modules/gfx/src/scene.cc
index 8b991110743b0235d45abc68f9182344a31033cd..1bd5e460742f0a774bd7e7d46eba5974b4804dd7 100644
--- a/modules/gfx/src/scene.cc
+++ b/modules/gfx/src/scene.cc
@@ -42,6 +42,7 @@
 #include "gl_helper.hh"
 
 #include <ost/config.hh>
+
 #include "scene.hh"
 #include "input.hh"
 #include "gfx_node.hh"
@@ -49,6 +50,7 @@
 #include "gfx_test_object.hh"
 #include "bitmap_io.hh"
 #include "entity.hh"
+#include "exporter.hh"
 #include "povray.hh"
 #include "offscreen_buffer.hh"
 
@@ -107,7 +109,8 @@ Scene::Scene():
   light_amb_(0.1,0.1,0.1),
   light_diff_(0.9,0.9,0.9),
   light_spec_(0.5,0.5,0.5),
-  axis_flag_(false),
+  cor_flag_(false),
+  fix_cor_flag_(true),
   fog_flag_(true),
   fog_color_(0.0,0.0,0.0,0.0),
   auto_autoslab_(true),
@@ -194,6 +197,15 @@ void Scene::SetShadowQuality(int q)
 #endif
 }
 
+int Scene::GetShadowQuality() const
+{
+#if OST_SHADER_SUPPORT_ENABLED
+  return impl::SceneFX::Instance().shadow_quality;
+#else
+  return 0;
+#endif
+}
+
 void Scene::SetShadowWeight(float w)
 {
 #if OST_SHADER_SUPPORT_ENABLED
@@ -202,6 +214,15 @@ void Scene::SetShadowWeight(float w)
 #endif
 }
 
+float Scene::GetShadowWeight() const
+{
+#if OST_SHADER_SUPPORT_ENABLED
+  return impl::SceneFX::Instance().shadow_weight;
+#else
+  return 0.0;
+#endif
+}
+
 void Scene::SetDepthDarkening(bool f)
 {
 #if OST_SHADER_SUPPORT_ENABLED
@@ -247,6 +268,15 @@ void Scene::SetAmbientOcclusionWeight(float f)
 #endif
 }
 
+float Scene::GetAmbientOcclusionWeight() const
+{
+#if OST_SHADER_SUPPORT_ENABLED
+  return impl::SceneFX::Instance().amb_occl_factor;
+#else
+  return 1.0;
+#endif
+}
+
 void Scene::SetAmbientOcclusionMode(uint m)
 {
 #if OST_SHADER_SUPPORT_ENABLED
@@ -256,6 +286,15 @@ void Scene::SetAmbientOcclusionMode(uint m)
 #endif
 }
 
+uint Scene::GetAmbientOcclusionMode() const
+{
+#if OST_SHADER_SUPPORT_ENABLED
+  return impl::SceneFX::Instance().amb_occl_mode;
+#else
+  return 0;
+#endif
+}
+
 void Scene::SetAmbientOcclusionQuality(uint m)
 {
 #if OST_SHADER_SUPPORT_ENABLED
@@ -265,6 +304,15 @@ void Scene::SetAmbientOcclusionQuality(uint m)
 #endif
 }
 
+uint Scene::GetAmbientOcclusionQuality() const
+{
+#if OST_SHADER_SUPPORT_ENABLED
+  return impl::SceneFX::Instance().amb_occl_quality;
+#else
+  return 0;
+#endif
+}
+
 void Scene::SetShadingMode(const std::string& smode)
 {
 #if OST_SHADER_SUPPORT_ENABLED
@@ -309,12 +357,18 @@ void Scene::SetBeaconOff()
 
 namespace {
 
-void set_light_dir(Vec3 ld)
-{
-  GLfloat l_pos[]={0.0, 0.0, 0.0, 0.0};
-  l_pos[0]=-ld[0]; l_pos[1]=-ld[1]; l_pos[2]=-ld[2];
-  glLightfv(GL_LIGHT0, GL_POSITION, l_pos);
-}
+  void set_light_dir(Vec3 ld)
+  {
+    GLfloat l_pos[]={0.0, 0.0, 0.0, 0.0};
+    l_pos[0]=-ld[0]; l_pos[1]=-ld[1]; l_pos[2]=-ld[2];
+    glLightfv(GL_LIGHT0, GL_POSITION, l_pos);
+  }
+
+  struct GfxObjInitGL: public GfxNodeVisitor {
+    virtual void VisitObject(GfxObj* o, const Stack& st) {
+      o->InitGL();
+    }
+  };
 
 }
 
@@ -355,7 +409,8 @@ void Scene::InitGL(bool full)
   glClearDepth(1.0);
 
   // background
-  SetBackground(background_);
+  glClearColor(background_.Red(),background_.Green(),background_.Blue(),background_.Alpha());
+  fog_color_=background_;
 
   // polygon orientation setting
   glFrontFace(GL_CCW);
@@ -457,8 +512,14 @@ void Scene::InitGL(bool full)
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
   glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE, GL_REPLACE);
 
+  LOG_DEBUG("Scene: calling gl init for all objects");
+  GfxObjInitGL initgl;
+  this->Apply(initgl);
+
   LOG_DEBUG("Scene: gl init done");
   gl_init_=true;
+  
+  if(!def_shading_mode_.empty()) SetShadingMode(def_shading_mode_);
 }
 
 void Scene::RequestRedraw()
@@ -773,9 +834,13 @@ void Scene::Add(const GfxNodeP& n, bool redraw)
 
   LOG_DEBUG("Scene: graphical object added @" << n.get() << std::endl);
 
-  if(root_node_->GetChildCount()==0) {
-    GfxObjP go = boost::dynamic_pointer_cast<GfxObj>(n);
-    if(go) {
+  GfxObjP go = boost::dynamic_pointer_cast<GfxObj>(n);
+
+  if(go) {
+    if(gl_init_) {
+      go->InitGL();
+    }
+    if(root_node_->GetChildCount()==0) {
       SetCenter(go->GetCenter());
     }
     do_autoslab_=true;
@@ -954,10 +1019,18 @@ void Scene::OnInput(const InputEvent& e)
     gluUnProject(wx+2.0,wy+2.0,wz,mm,pm,vp,&ox,&oy,&oz);
     Vec2 fxy = Vec2(ox,oy);
 
-    if(e.GetCommand()==INPUT_COMMAND_TRANSX) {
-      transform_.ApplyXAxisTranslation(e.GetDelta()*fxy[0]);
+    if(fix_cor_flag_) {
+      if(e.GetCommand()==INPUT_COMMAND_TRANSX) {
+        transform_.SetCenter(transform_.GetCenter()+Transpose(transform_.GetRot())*Vec3(-fxy[0]*e.GetDelta(),0.0,0.0));
+      } else {
+        transform_.SetCenter(transform_.GetCenter()+Transpose(transform_.GetRot())*Vec3(0.0,-fxy[1]*e.GetDelta(),0.0));
+      }
     } else {
-      transform_.ApplyYAxisTranslation(e.GetDelta()*fxy[1]);
+      if(e.GetCommand()==INPUT_COMMAND_TRANSX) {
+        transform_.ApplyXAxisTranslation(e.GetDelta()*fxy[0]);
+      } else {
+        transform_.ApplyYAxisTranslation(e.GetDelta()*fxy[1]);
+      }
     }
   } else if(e.GetCommand()==INPUT_COMMAND_TRANSZ) {
     float currz=transform_.GetTrans()[2];
@@ -1573,6 +1646,13 @@ void Scene::ExportPov(const std::string& fname, const std::string& wdir)
   pov.write_postamble();
 }
 
+void Scene::Export(Exporter* ex) const
+{
+  ex->SceneStart(this);
+  root_node_->Export(ex);
+  ex->SceneEnd(this);
+}
+
 void Scene::ResetProjection()
 {
   LOG_TRACE("Scene: projection matrix " << fov_ << " " << znear_ << " " << zfar_);
@@ -1740,6 +1820,12 @@ void Scene::SetTestMode(bool f)
   }
 }
 
+void Scene::SetShowCenter(bool f)
+{
+  cor_flag_=f;
+  RequestRedraw();
+}
+
 void Scene::prep_glyphs()
 {
   glGenTextures(1,&glyph_tex_id_);
@@ -1800,6 +1886,32 @@ void Scene::render_scene()
   impl::SceneFX::Instance().Preprocess();
 #endif
 
+  if(cor_flag_) {
+    geom::Vec3 cen=transform_.GetCenter();
+    glPushAttrib(GL_ENABLE_BIT | GL_LIGHTING_BIT | GL_LINE_BIT | GL_CURRENT_BIT);
+#if OST_SHADER_SUPPORT_ENABLED
+    Shader::Instance().PushProgram();
+    Shader::Instance().Activate("");
+#endif
+    glLineWidth(1.5);
+    glDisable(GL_LIGHTING);
+    glDisable(GL_COLOR_MATERIAL);
+    
+    glBegin(GL_LINES);
+    glColor3f(0.5,0.5,0.5);
+    glVertex3f(cen[0]-1.0,cen[1],cen[2]);
+    glVertex3f(cen[0]+1.0,cen[1],cen[2]);
+    glVertex3f(cen[0],cen[1]-1.0,cen[2]);
+    glVertex3f(cen[0],cen[1]+1.0,cen[2]);
+    glVertex3f(cen[0],cen[1],cen[2]-1.0);
+    glVertex3f(cen[0],cen[1],cen[2]+1.0);
+    glEnd();
+    glPopAttrib();
+#if OST_SHADER_SUPPORT_ENABLED
+    Shader::Instance().PopProgram();
+#endif
+  }
+
   root_node_->RenderGL(STANDARD_RENDER_PASS);
   glEnable(GL_BLEND);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -1862,7 +1974,7 @@ void Scene::stereo_projection(int view)
       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);
+      glRotated(-180.0/M_PI*atan(0.1*ff/iod),0.0,1.0,0.0);
       glTranslated(0.0,0.0,dist);
     } else {
       // correct off-axis frustims
@@ -1871,10 +1983,12 @@ void Scene::stereo_projection(int view)
 
       // 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);
       }
+#endif
     
       Real sd = -ff*0.5*iod*zn/fo;
       left+=sd;
@@ -1892,6 +2006,9 @@ void Scene::stereo_projection(int view)
 
 void Scene::render_stereo()
 {
+  glPushAttrib(GL_ALL_ATTRIB_BITS);
+  glPushClientAttrib(GL_ALL_ATTRIB_BITS);
+
   int old_stereo_eye=stereo_eye_;
   stereo_eye_=-1;
   stereo_projection(-1);
@@ -1909,6 +2026,7 @@ void Scene::render_stereo()
   stereo_eye_=1;
   stereo_projection(1);
   render_scene();
+
   glEnable(GL_TEXTURE_2D);
 #if OST_SHADER_SUPPORT_ENABLED
   if(OST_GL_VERSION_2_0) {
@@ -1925,7 +2043,6 @@ void Scene::render_stereo()
   Shader::Instance().Activate("");
 #endif
 
-  glPushAttrib(GL_ALL_ATTRIB_BITS);
   glDisable(GL_DEPTH_TEST);
   glDisable(GL_LIGHTING);
   glDisable(GL_COLOR_MATERIAL);
@@ -1946,7 +2063,7 @@ void Scene::render_stereo()
   glLoadIdentity();
 
   if(stereo_mode_==2) {
-    // draw interlace lines in stencil buffer
+    // draw interlaced lines in stencil buffer
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     glLineWidth(1.0);
     glEnable(GL_STENCIL_TEST);
@@ -2011,10 +2128,14 @@ void Scene::render_stereo()
   glEnd();
   
   // restore settings
+  glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 0, 0, 0);
+  glBindTexture(GL_TEXTURE_2D, 0);
+  glDisable(GL_TEXTURE_2D);
   glMatrixMode(GL_PROJECTION);
   glPopMatrix();
   glMatrixMode(GL_MODELVIEW);
   glPopMatrix();
+  glPopClientAttrib();
   glPopAttrib();
 #if OST_SHADER_SUPPORT_ENABLED
   Shader::Instance().PopProgram();
diff --git a/modules/gfx/src/scene.hh b/modules/gfx/src/scene.hh
index bf093efaff7384f608ce2cac18e5a4b92c14c13e..a5868d0606581bff66c84b32b5d53f071bc44751 100644
--- a/modules/gfx/src/scene.hh
+++ b/modules/gfx/src/scene.hh
@@ -42,6 +42,7 @@
 #include "scene_observer.hh"
 #include "gfx_prim.hh"
 #include "povray_fw.hh"
+#include "exporter_fw.hh"
 
 namespace ost { namespace gfx {
 
@@ -95,27 +96,25 @@ class DLLEXPORT_OST_GFX Scene {
 
   /// \brief turn fog on or off
   void SetFog(bool f);
-
   /// \brief check fog status
   bool GetFog() const;
-
   /// \brief set the fog color
   void SetFogColor(const Color& c);
-
   /// \brief get the fog color
   Color GetFogColor() const;
 
   /// \brief turn shadow mapping on and off
   void SetShadow(bool f);
-
   /// \brief get shadow mapping status
   bool GetShadow() const;
-
   /// \brief shadow quality from 0 (low) to 3 (high), default=1
   void SetShadowQuality(int q);
-
+  /// \brief get shadow quality
+  int GetShadowQuality() const;
   /// \brief multiplier for shadow strength
   void SetShadowWeight(float w);
+  /// \brief get shadow strength
+  float GetShadowWeight() const;
 
   /// experimental feature
   void SetDepthDarkening(bool f);
@@ -129,9 +128,15 @@ class DLLEXPORT_OST_GFX Scene {
   /// experimental feature
   void SetAmbientOcclusionWeight(float f);
   /// experimental feature
+  float GetAmbientOcclusionWeight() const;
+  /// experimental feature
   void SetAmbientOcclusionMode(uint m);
   /// experimental feature
+  uint GetAmbientOcclusionMode() const;
+  /// experimental feature
   void SetAmbientOcclusionQuality(uint q);
+  /// experimental feature
+  uint GetAmbientOcclusionQuality() const;
   
   /// \brief select shading mode
   /// one of fallback, basic, default, hf, toon1, toon2
@@ -249,13 +254,17 @@ class DLLEXPORT_OST_GFX Scene {
   /// if a main offscreen buffer is active (\sa StartOffscreenMode), then the
   /// dimensions here are ignored
   void Export(const String& fname, unsigned int w,
-              unsigned int h, bool transparent=true);
+              unsigned int h, bool transparent=false);
 
   /// \brief export snapshot of current scene
-  void Export(const String& fname, bool transparent=true);
+  void Export(const String& fname, bool transparent=false);
 
   /// \brief export scene into povray files named fname.pov and fname.inc
   void ExportPov(const std::string& fname, const std::string& wdir=".");
+
+  /// \rbrief export scene via exporter
+  void Export(Exporter* ex) const;
+
   //@}
   /// \brief entry point for gui events (internal use)
   void OnInput(const InputEvent& e);
@@ -409,6 +418,17 @@ class DLLEXPORT_OST_GFX Scene {
   /// \brief stops offline rendering in interactive mode
   void StopOffscreenMode();
 
+  /// \brief show center of rotation of true
+  void SetShowCenter(bool f);
+
+  bool GetShowCenter() const {return cor_flag_;}
+
+  /// \brief if true fix center of rotation upon input induced shift
+  void SetFixCenter(bool f) {fix_cor_flag_=f;}
+
+  /// \brief return flag
+  bool GetFixCenter() const {return fix_cor_flag_;}
+  
   /// experimental feature
   void SetBlur(uint n);
   /// experimental feature
@@ -472,7 +492,8 @@ private:
   Color light_diff_;
   Color light_spec_;
 
-  bool axis_flag_;
+  bool cor_flag_;
+  bool fix_cor_flag_;
   bool fog_flag_;
   Color fog_color_;
   bool auto_autoslab_;
diff --git a/modules/gfx/src/vertex_array.cc b/modules/gfx/src/vertex_array.cc
index c1c53d57fa29110368a7b1a5a2da28fb2c7c5612..b9c45e5a7ce54f274b2b1e0b029f100fd81772ec 100644
--- a/modules/gfx/src/vertex_array.cc
+++ b/modules/gfx/src/vertex_array.cc
@@ -30,6 +30,7 @@
 #include "scene.hh"
 #include "vertex_array_helper.hh"
 #include "povray.hh"
+#include "exporter.hh"
 
 #if OST_SHADER_SUPPORT_ENABLED
 #include "shader.hh"
@@ -108,7 +109,7 @@ unsigned int IndexedVertexArray::GetFormat()
 void IndexedVertexArray::Cleanup() 
 {
   if(initialized_) {
-    glDeleteTextures(1,&tex_id_);
+    //glDeleteTextures(1,&tex_id_);
     glDeleteLists(outline_mat_dlist_,1);
 #if OST_SHADER_SUPPORT_ENABLED
     glDeleteBuffers(7,buffer_id_);
@@ -431,6 +432,12 @@ void IndexedVertexArray::RenderGL()
   
   glPushAttrib(GL_ALL_ATTRIB_BITS);
   glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
+  
+  if(use_tex_) {
+    glEnable(GL_TEXTURE_2D);
+  } else {
+    glDisable(GL_TEXTURE_2D);
+  }
 
   if(outline_mode_>0) {
     LOG_TRACE("outline rendering");
@@ -654,6 +661,14 @@ void IndexedVertexArray::RenderPov(PovState& pov, const std::string& name)
   pov.inc() << "}\n";
 }
 
+void IndexedVertexArray::Export(Exporter* ex) const
+{
+  ex->WriteVertexData(entry_list_[0].v,entry_list_[0].n, entry_list_[0].c, entry_list_[0].t, sizeof(Entry), entry_list_.size());
+  ex->WriteLineData(&line_index_list_[0],line_index_list_.size()/2);
+  ex->WriteTriData(&tri_index_list_[0],tri_index_list_.size()/3);
+  ex->WriteQuadData(&quad_index_list_[0],quad_index_list_.size()/4);
+}
+
 void IndexedVertexArray::Clear()
 {
   dirty_=true;
@@ -685,7 +700,7 @@ void IndexedVertexArray::Reset()
   outline_exp_factor_=0.1;
   outline_exp_color_=Color(0,0,0);
   draw_normals_=false;
-  use_tex_=true;
+  use_tex_=false;
 }
 
 void IndexedVertexArray::FlagRefresh()
diff --git a/modules/gfx/src/vertex_array.hh b/modules/gfx/src/vertex_array.hh
index 1a945f7cf6094738b0a539bfad19d72ee1767d39..ee63c939aae475959cfa12963b730f7326392df6 100644
--- a/modules/gfx/src/vertex_array.hh
+++ b/modules/gfx/src/vertex_array.hh
@@ -39,6 +39,7 @@
 #include "material.hh"
 #include "gfx_prim.hh"
 #include "povray_fw.hh"
+#include "exporter_fw.hh"
 
 namespace ost { namespace gfx {
 
@@ -107,10 +108,14 @@ class DLLEXPORT_OST_GFX IndexedVertexArray {
   void SetLineHalo(float lh);
 
   void SetOutlineMode(int m);
+  int GetOutlineMode() const {return outline_mode_;}
   void SetOutlineWidth(float f);
+  float GetOutlineWidth() const {return outline_width_;}
   void SetOutlineMaterial(const Material& m);
   void SetOutlineExpandFactor(float f);
+  float GetOutlineExpandFactor() const {return outline_exp_factor_;}
   void SetOutlineExpandColor(const Color& c);
+  Color GetOutlineExpandColor() const {return outline_exp_color_;}
 
   // vertex, normal, color and texcoord (T2F_C4F_N3F_V3F)
   VertexID Add(const geom::Vec3& vert, const geom::Vec3& norm, const Color& col, const geom::Vec2& tex=geom::Vec2());
@@ -158,6 +163,8 @@ class DLLEXPORT_OST_GFX IndexedVertexArray {
   // POVray export
   void RenderPov(PovState& pov, const std::string& name);
 
+  void Export(Exporter* ex) const;
+
   // only removes the drawing elements
   void Clear();
   // removes all elements and resets internal state to default
diff --git a/modules/gfx/tests/test_gfx.py b/modules/gfx/tests/test_gfx.py
index b6911eee12fc2a5401a11d1284dc14d1eb7e3f17..0ddeeab7e2961fd9187f7e7bb9414ab8191c1a0a 100644
--- a/modules/gfx/tests/test_gfx.py
+++ b/modules/gfx/tests/test_gfx.py
@@ -1,3 +1,22 @@
+#------------------------------------------------------------------------------
+# This file is part of the OpenStructure project <www.openstructure.org>
+#
+# Copyright (C) 2008-2011 by the OpenStructure authors
+#
+# This library is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation; either version 3.0 of the License, or (at your option)
+# any later version.
+# This library is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this library; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+#------------------------------------------------------------------------------
+
 import unittest
 if __name__== '__main__':
   import sys
@@ -9,15 +28,44 @@ import ost.mol as mol
 import ost.gfx as gfx
 import ost.geom as geom
 
+if ost.WITH_NUMPY:
+  has_numpy=True
+  try:
+    import numpy
+  except ImportError, e:
+    has_numpy=False
+else:
+  has_numpy=False
+
 def col_delta(c1,c2):
   return geom.Distance(geom.Vec3(c1[0],c1[1],c1[2]),geom.Vec3(c2[0],c2[1],c2[2]))
 
+class MyGfxObj(gfx.GfxObj):
+  def __init__(self,name):
+    gfx.GfxObj.__init__(self,name)
+    self.rendered=False
+    
+  def CustomRenderGL(self,render_pass):
+    self.rendered=True
+
 class TestGfx(unittest.TestCase):
   def runTest(self):
     self.test_gradient()
     self.test_color()
     self.test_primlist()
     self.test_entity_reset()
+    self.test_custom_gfx_obj()
+    self.test_gfxobj_conv()
+
+  def test_gfxobj_conv(self):
+    e=mol.CreateEntity()
+    gfx.Scene().Add(gfx.Entity("foo2",e))
+    gfx.Scene()["foo2"].SetColor(gfx.YELLOW)
+    
+  def test_custom_gfx_obj(self):
+    myobj=MyGfxObj("foo")
+    gfx.Scene().Add(myobj)
+    #self.assertTrue(myobj.rendered)
 
   def test_entity_reset(self):
     eh=mol.CreateEntity()
@@ -32,7 +80,8 @@ class TestGfx(unittest.TestCase):
 
   def test_gradient(self):
     gs=[gfx.Gradient(),
-        gfx.Gradient({0.0: [1,0,0], 1.0: gfx.Color(0,1,0)})]
+        gfx.Gradient({0.0: [1,0,0], 1.0: gfx.Color(0,1,0)}),
+        gfx.Gradient([[1,0,0], gfx.Color(0,1,0)])]
     gs[0].SetColorAt(0.0,gfx.Color(1.0,0.0,0.0))
     gs[0].SetColorAt(1.0,gfx.Color(0.0,1.0,0.0))
     for g in gs:
@@ -71,6 +120,16 @@ class TestGfx(unittest.TestCase):
     pl.AddCyl(geom.Vec3(0,0,0),geom.Vec3(1,2,3),radius1=0.5,radius2=0.1,color1=gfx.BLUE,color2=gfx.GREEN)
     pl.AddText("foo",[0,2,3])
     pl.AddText("bar",[-2,0,0],color=gfx.WHITE,point_size=8)
+    if has_numpy:
+      pl.AddMesh(numpy.zeros((5,3),dtype=numpy.float32),
+                 numpy.zeros((5,3),dtype=numpy.float32),
+                 numpy.zeros((5,4),dtype=numpy.float32),
+                 numpy.zeros((2,3),dtype=numpy.uint32))
+      pl.AddMesh(numpy.zeros((7,3),dtype=numpy.float32),
+                 None,
+                 None,
+                 numpy.zeros((4,3),dtype=numpy.uint32))
+                 
 
 if __name__== '__main__':
   unittest.main()
diff --git a/modules/gfx/tests/test_gost_export.py b/modules/gfx/tests/test_gost_export.py
new file mode 100644
index 0000000000000000000000000000000000000000..efb56861b18f52fae0b92d25e62477b06901fdfe
--- /dev/null
+++ b/modules/gfx/tests/test_gost_export.py
@@ -0,0 +1,22 @@
+import desost_util as util
+
+e=io.LoadPDB("../../../examples/demos/data/sdh.pdb")
+
+s=util.CreateSurf(e.Select("chain=A"),density=4)
+
+scene.Add(gfx.Entity("trace",gfx.TUBE,e.Select("chain=A")))
+scene["trace"].tube_options.arc_detail=8
+scene["trace"].tube_options.spline_detail=8
+scene["trace"].tube_options.tube_radius=1.0
+grad=gfx.Gradient()
+grad.SetColorAt(0.0,gfx.RED)
+grad.SetColorAt(0.5,gfx.GREEN)
+grad.SetColorAt(1.0,gfx.BLUE)
+scene["trace"].ColorBy("rnum",grad)
+
+scene.Add(gfx.Surface("surf",s))
+scene["surf"].ColorBy("rnum",grad)
+
+if not gui_mode:
+  ge = gfx.GostExporter("test.gost")
+  scene.Export(ge)
diff --git a/modules/gfx/tests/test_gost_import.py b/modules/gfx/tests/test_gost_import.py
new file mode 100644
index 0000000000000000000000000000000000000000..deebd2d31d805c7c0cc190d5ad273262dc7728bf
--- /dev/null
+++ b/modules/gfx/tests/test_gost_import.py
@@ -0,0 +1,15 @@
+import struct
+
+with open("test.gost","rb") as gf:
+
+  header = gf.read(6)
+  if str(header[0:4]) != "GOST":
+    raise RuntimeError("file format mismatch")
+  raw = gf.read(16)
+
+  while raw:
+    (type, subtype,size) = struct.unpack("iiL",raw)
+    print "found type=%d, subtype=%d and blocksize=%u"%(type,subtype,size)
+    if size>0:
+      data = gf.read(size)
+    raw = gf.read(16)
diff --git a/modules/gui/src/CMakeLists.txt b/modules/gui/src/CMakeLists.txt
index 7c8f6d640e5dd6c18d85d42b686a7eb82396ae80..c8dc99f72669ed86d28e8cdd768b59ff18b3ad63 100644
--- a/modules/gui/src/CMakeLists.txt
+++ b/modules/gui/src/CMakeLists.txt
@@ -471,5 +471,13 @@ if (NOT WIN32)
   set(LINK LINK ${BOOST_PROGRAM_OPTIONS_LIBRARIES})
 endif()
 
-executable(NAME gosty SOURCES gosty.cc ${OST_GOSTY_MOC} ${OST_QT_RESOURCE} 
+executable_libexec(NAME gosty SOURCES gosty.cc ${OST_GOSTY_MOC} ${OST_QT_RESOURCE} 
            DEPENDS_ON ost_gui ${LINK})
+           
+file(GLOB MOC_CXX_FILES moc_*.cxx)
+
+if (MOC_CXX_FILES)
+  set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES
+                           "${MOC_CXX_FILES}")
+endif()
+
diff --git a/modules/gui/src/data_viewer/mask_overlay.cc b/modules/gui/src/data_viewer/mask_overlay.cc
index 6b52851831d44995a70eb3f6beffe518bada2447..c0c0e6560344c59f75cb95031a1a372086aba0ad 100644
--- a/modules/gui/src/data_viewer/mask_overlay.cc
+++ b/modules/gui/src/data_viewer/mask_overlay.cc
@@ -57,43 +57,46 @@ MaskOverlay::MaskOverlay(const MaskPtr& m):
 
 void MaskOverlay::OnDraw(QPainter& pnt, DataViewerPanel* dvp, bool is_active)
 {
+  QPainter::RenderHints render_hints=pnt.renderHints();
+  pnt.setRenderHints(render_hints | QPainter::Antialiasing);
   for (int i=0;i<static_cast<int>(polygons_.size());++i){
     if(is_active){
       if(i==active_){
-        pnt.setPen(QPen(QColor(255,255,0),2));
+        pnt.setPen(QPen(QColor(255,255,0),1));
         pnt.setBrush(QColor(255,255,0,30));
       }else{
-        pnt.setPen(QPen(QColor(255,0,0),2));
+        pnt.setPen(QPen(QColor(255,0,0),1));
         pnt.setBrush(QColor(255,0,0,30));
       }
     }else{
-      pnt.setPen(QPen(QColor(100,100,100),2));
+      pnt.setPen(QPen(QColor(100,100,100),1));
       pnt.setBrush(QColor(100,100,100,30));
     }
     geom::Polygon2 pol=polygons_[i];
     QPolygon qpol;
     for(int j=0;j<static_cast<int>(pol.GetNodeCount());++j){
       qpol << dvp->FracPointToWinCenter(pol.GetNode(j)+shift_);
-      pnt.drawEllipse(qpol.back(),3,3);
+      pnt.drawEllipse(qpol.back(),4,4);
     }
     pnt.drawPolygon(qpol);
   }
 
   if(add_mode_) {
     if(is_active){
-      pnt.setPen(QPen(QColor(255,0,255),3));
+      pnt.setPen(QPen(QColor(255,0,255),1));
       pnt.setBrush(QColor(255,0,255,30));
     }else{
-      pnt.setPen(QPen(QColor(100,100,100),2));
+      pnt.setPen(QPen(QColor(100,100,100),1));
       pnt.setBrush(QColor(100,100,100,30));
     }
     QPolygon qpol;
     for(int j=0;j<static_cast<int>(new_poly_.GetNodeCount());++j){
       qpol << dvp->FracPointToWinCenter(new_poly_.GetNode(j)+shift_);
-      pnt.drawEllipse(qpol.back(),3,3);
+      pnt.drawEllipse(qpol.back(),4,4);
     }
     pnt.drawPolygon(qpol);
   }
+  pnt.setRenderHints(render_hints);
 }
 
 bool MaskOverlay::OnMouseEvent(QMouseEvent* e,  DataViewerPanel* dvp, 
@@ -118,7 +121,7 @@ bool MaskOverlay::OnMouseEvent(QMouseEvent* e,  DataViewerPanel* dvp,
       if(active_>=0){
         geom::Polygon2 pol=polygons_[active_];
         for(unsigned int j=0;j<pol.GetNodeCount();++j){
-          if(Length(mousepos-(pol.GetNode(j)+shift_))<3){
+          if(Length(mousepos-(pol.GetNode(j)+shift_))<4){
             active_node_=j;
             return true;
           }
@@ -128,7 +131,7 @@ bool MaskOverlay::OnMouseEvent(QMouseEvent* e,  DataViewerPanel* dvp,
         if(i!=active_){
           geom::Polygon2 pol=polygons_[i];
           for(unsigned int j=0;j<pol.GetNodeCount();++j){
-            if(Length(mousepos-pol.GetNode(j))<3){
+            if(Length(mousepos-(pol.GetNode(j)+shift_))<4){
               active_=i;
               active_node_=j;
               return true;
@@ -142,7 +145,7 @@ bool MaskOverlay::OnMouseEvent(QMouseEvent* e,  DataViewerPanel* dvp,
     }
   }
   if(e->buttons() & Qt::LeftButton && active_>=0 && active_node_>=0 && ! (e->modifiers() & Qt::ShiftModifier)){
-    polygons_[active_].SetNode(active_node_,mousepos);
+    polygons_[active_].SetNode(active_node_,mousepos-shift_);
   }
   return false;
 }
diff --git a/modules/gui/src/data_viewer/overlay_manager_gui.cc b/modules/gui/src/data_viewer/overlay_manager_gui.cc
index 74d24415c5bc1431389b8437becad5e4db400782..ba9d884cbd88b0f603c670a93dcfb995eb168177 100644
--- a/modules/gui/src/data_viewer/overlay_manager_gui.cc
+++ b/modules/gui/src/data_viewer/overlay_manager_gui.cc
@@ -135,6 +135,7 @@ void OverlayManagerGUI::OnAddOverlay(OverlayManager* m, int id)
   OverlayPtr ov = m->RetrieveOverlay(id);
   connect(ov.get(),SIGNAL(InfoTextChanged(const QString&)),this,SLOT(SetInfoText(const QString&)));
   OverlayEntry oe;
+  oe.row=0.0;
   oe.a=new OverlayCustomActCheckBox(id,m);
   connect(oe.a,SIGNAL(toggled(bool)),oe.a,SLOT(OnToggle(bool)));
   active_group_->addButton(oe.a);
diff --git a/modules/gui/src/gosty.cc b/modules/gui/src/gosty.cc
index cb1ed73843039048077f703cf36820dcf32cdc47..3ea2bdda6e64bb18677c0cb86ac08fb303bddf95 100644
--- a/modules/gui/src/gosty.cc
+++ b/modules/gui/src/gosty.cc
@@ -82,13 +82,27 @@ String get_ost_root()
 {
   QDir dir(QApplication::applicationDirPath());
 
+#if OST_DEBIAN_STYLE_LIBEXEC  
   #ifdef _MSC_VER
     dir.cdUp();
     dir.cdUp();
+    dir.cdUp();
+    dir.cdUp();
   #else
     dir.cdUp();
+    dir.cdUp();
+    dir.cdUp();
   #endif
-
+#else
+  #ifdef _MSC_VER
+    dir.cdUp();
+    dir.cdUp();
+    dir.cdUp();
+  #else
+    dir.cdUp();
+    dir.cdUp();
+  #endif
+#endif
   return dir.path().toStdString();
 }
 
@@ -186,10 +200,11 @@ void prepare_scripts(int argc, char** argv, PythonInterpreter& py)
 int main(int argc, char** argv)
 {
   int dummy_argc=1;
+  
   QApplication app(dummy_argc,argv);
   QCoreApplication::setOrganizationName("OpenStructure");
   QCoreApplication::setOrganizationDomain("openstructure.org");
-  QCoreApplication::setApplicationName(argv[0]);
+  QCoreApplication::setApplicationName(QString(argv[2]));
 	app.setLibraryPaths(QStringList());
   if (int rv=setup_resources(app)<0) {
     return rv;
diff --git a/modules/io/pymod/export_map_io.cc b/modules/io/pymod/export_map_io.cc
index beb7601bc63916a64e52e74035c853ebbb778662..afe494d1997b4d1720fe49592b35c36e51976980 100644
--- a/modules/io/pymod/export_map_io.cc
+++ b/modules/io/pymod/export_map_io.cc
@@ -27,6 +27,7 @@
 #include  <ost/io/img/map_io_dat_handler.hh>
 #include  <ost/io/img/map_io_jpk_handler.hh>
 #include  <ost/io/img/map_io_nanoscope_handler.hh>
+#include  <ost/io/img/map_io_ipl_handler.hh>
 #include  <ost/io/img/image_format.hh>
 #include  <ost/io/img/load_map.hh>
 
@@ -79,18 +80,17 @@ void export_map_io()
         .export_values()
   ;
 
-  enum_<Subformat>("Format")
+  enum_<Subformat>("Subformat")
         .value("MRC_NEW_FORMAT", MRC_NEW_FORMAT)
         .value("MRC_OLD_FORMAT", MRC_OLD_FORMAT)
         .value("MRC_AUTO_FORMAT", MRC_AUTO_FORMAT)
         .export_values()
   ;
 
+
   class_<ImageFormatBase>("ImageFormatBase",no_init)
     .def("GetMaximum", &ImageFormatBase::GetMaximum)
-    .def("SetMaximum", &ImageFormatBase::GetMaximum)
     .def("GetMinimum", &ImageFormatBase::GetMinimum)
-    .def("SetMinimum", &ImageFormatBase::GetMinimum)
   ;
 
   class_<DX, bases<ImageFormatBase> >("DX", init<bool>(arg("normalize_on_save") = false))
@@ -154,6 +154,13 @@ void export_map_io()
     .def("GetBitDepth", &DAT::GetBitDepth)
   ;
 
+  class_<IPL, bases<ImageFormatBase> >("IPL", init<bool,Format>((arg("normalize_on_save") = true,arg("format")=OST_DEFAULT_FORMAT)))
+    .def("SetNormalizeOnSave", &IPL::SetNormalizeOnSave)
+    .def("GetNormalizeOnSave", &IPL::GetNormalizeOnSave)
+    .def("SetBitDepth", &IPL::SetBitDepth)
+    .def("GetBitDepth", &IPL::GetBitDepth)
+  ;
+
   class_<JPK, bases<TIF> >("JPK", init<boost::logic::tribool,Format,bool,bool,int>
            ((arg("normalize_on_save") =  boost::logic::tribool(boost::logic::indeterminate),arg("format")=OST_DEFAULT_FORMAT,arg("signed")=false,arg("phasecolor")=false,arg("subimage") = -1)))
   ;
diff --git a/modules/io/src/img/CMakeLists.txt b/modules/io/src/img/CMakeLists.txt
index 8fa9a30ffd45564867fef83e5b17ef7bee0250b0..d17f46e8ec5e043b1a74c67ee900e5e01271ccd7 100644
--- a/modules/io/src/img/CMakeLists.txt
+++ b/modules/io/src/img/CMakeLists.txt
@@ -7,6 +7,7 @@ map_io_mrc_handler.cc
 map_io_dm3_handler.cc
 map_io_tiff_handler.cc
 map_io_dat_handler.cc
+map_io_ipl_handler.cc
 map_io_jpk_handler.cc
 map_io_nanoscope_handler.cc
 map_io_png_handler.cc
@@ -28,6 +29,7 @@ map_io_situs_handler.hh
 map_io_handler.hh
 map_io_mrc_handler.hh
 map_io_dat_handler.hh
+map_io_ipl_handler.hh
 map_io_jpk_handler.hh
 map_io_nanoscope_handler.hh
 map_io_png_handler.hh
diff --git a/modules/io/src/img/map_io_ipl_handler.cc b/modules/io/src/img/map_io_ipl_handler.cc
new file mode 100644
index 0000000000000000000000000000000000000000..dd1fb2981a1f8c95f407331086508253a425f450
--- /dev/null
+++ b/modules/io/src/img/map_io_ipl_handler.cc
@@ -0,0 +1,416 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+// Copyright (C) 2003-2010 by the IPLT authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software FounIPLion; 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 FounIPLion, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110String::npos301  USA
+//------------------------------------------------------------------------------
+#include <cassert>
+#include <ctime>
+#include <iomanip>
+#include <cstring>
+
+#include <boost/shared_array.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/fstream.hpp>
+#include <ost/stdint.hh>
+#include <ost/units.hh>
+#include <ost/log.hh>
+#include <ost/img/image.hh>
+#include <ost/img/alg/normalizer_factory.hh>
+#include <ost/img/progress.hh>
+#include <ost/io/io_exception.hh>
+#include <ost/io/convert.hh>
+#include <ost/io/converting_streams.hh>
+#include <ost/img/alg/discrete_shrink.hh>
+
+#include "map_io_ipl_handler.hh"
+
+namespace ost { namespace io {
+
+String IPL::FORMAT_STRING = "defined_ipl";
+
+IPL::IPL(bool normalize_on_save, Format bit_depth):
+    ImageFormatBase(FORMAT_STRING),
+    normalize_on_save_(normalize_on_save),
+    bit_depth_(OST_DEFAULT_FORMAT)
+{
+  this->SetBitDepth(bit_depth);
+}
+
+Format IPL::GetBitDepth() const
+{
+  return bit_depth_;
+}
+
+void IPL::SetBitDepth (Format bitdepth)
+{
+  if( ! (bitdepth==OST_BIT16_FORMAT || bitdepth==OST_BIT32_FORMAT || bitdepth==OST_DEFAULT_FORMAT))
+  {
+    throw IOException("Unsupported bit depth for IPL file format.");
+  }
+
+  bit_depth_ = bitdepth;
+}
+
+bool IPL::GetNormalizeOnSave() const
+{
+  return normalize_on_save_;
+}
+
+void IPL::SetNormalizeOnSave(bool normalize_on_save)
+{
+  normalize_on_save_ = normalize_on_save;
+}
+
+Real IPL::GetMaximum() const
+{
+  switch(bit_depth_){
+  case OST_BIT32_FORMAT:
+    return 4294967295.0;
+  default:
+    return 65535.0;
+  }
+}
+
+Real IPL::GetMinimum() const
+{
+  return 0.0;
+}
+
+bool MapIOIPLHandler::MatchContent(unsigned char* header)
+{
+  String magic_token("DITABIS micron Data File");
+  if(magic_token.compare(0,magic_token.size(),reinterpret_cast<char*>(header),magic_token.size())==0)
+  {
+    return true;
+  }
+  return false;
+}
+
+namespace detail{
+
+class IPLHeader{
+public:
+  IPLHeader():
+    date(),
+    header_length(2048),
+    size_x(),
+    size_y(),
+    bit_depth(),
+    resolution_x(),
+    resolution_y(),
+    magnification(1),
+    thumb_nail_zoom(10),
+    channel("PMT LOWSENS"),
+    params("dummy.set"),
+    format("2 2 2 2  Standard.fmt"),
+    laser(30),
+    gain(20000),
+    offset_correction(true),
+    offset(0),
+    comment()
+  {}
+  IPLHeader(const img::ConstImageHandle& im,Format bit_depth):
+    date(),
+    header_length(2048),
+    size_x(im.GetSize()[0]),
+    size_y(im.GetSize()[1]),
+    bit_depth(bit_depth==OST_BIT32_FORMAT ? 4: 2),
+    resolution_x(im.GetSpatialSampling()[0]),
+    resolution_y(im.GetSpatialSampling()[1]),
+    magnification(1),
+    thumb_nail_zoom(10),
+    channel("PMT LOWSENS"),
+    params("dummy.set"),
+    format("2 2 2 2  Standard.fmt"),
+    laser(30),
+    gain(20000),
+    offset_correction(true),
+    offset(0),
+    comment()
+  {}
+  String date;
+  int header_length;
+  int size_x;
+  int size_y;
+  int bit_depth;
+  Real resolution_x;
+  Real resolution_y;
+  int magnification;
+  int thumb_nail_zoom;
+  String channel;
+  String params;
+  String format;
+  int laser;
+  int gain;
+  bool offset_correction;
+  int offset;
+  String comment;
+};
+
+std::ostream& operator<< (std::ostream& out, const IPLHeader& h )
+{
+  uint start_pos = out.tellp();
+  out << "DITABIS micron Data File\r\n";
+  time_t rawtime=time(NULL);
+  char * timestr = asctime(localtime(&rawtime));
+  timestr[strlen(timestr)-1] = '\0';
+  out << "CREATED = "<< timestr <<" \r\n";
+  out << "HEADER = "<< h.header_length <<" \r\n";
+  // x and y get swapped here (follows the behaviour of the original conversion software)
+  out << "YPIXEL = "<< h.size_x <<" \r\n";
+  out << "XPIXEL = "<< h.size_y <<" \r\n";
+  out << "BYTE PER PIXEL = "<< h.bit_depth <<" \r\n";
+  // x and y get swapped here (follows the behaviour of the original conversion software)
+  out << "XRESOLUTION = "<< std::setprecision(0)<< h.resolution_y/Units::nm <<" (" << std::setprecision(2)<< h.resolution_y/Units::nm<<") \r\n";
+  out << "YRESOLUTION = "<< std::setprecision(0)<< h.resolution_x/Units::nm <<" (" << std::setprecision(2)<< h.resolution_x/Units::nm<<") \r\n";
+  out << "MAGNIFICATION = "<< h.magnification <<" \r\n";
+  out << "THUMB-NAIL-ZOOM = "<< h.thumb_nail_zoom <<" \r\n";
+  out << "CHANNEL = "<< h.channel <<" \r\n";
+  out << "PARAMS = "<< h.params <<" \r\n";
+  out << "FORMAT = "<< h.format <<" \r\n";
+  out << "LASER = "<< h.laser <<" \r\n";
+  out << "GAIN = "<< h.gain <<" \r\n";
+  if(h.offset_correction){
+    out << "OFFSET CORRECTION = YES \r\n";
+  }else{
+    out << "OFFSET CORRECTION = NO \r\n";
+  }
+  out << "OFFSET = "<< h.offset <<" \r\n";
+  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);
+  return out;
+}
+
+std::istream& operator>> (std::istream& in, IPLHeader& h)
+{
+  String line;
+  uint start_pos = in.tellg();
+  do{
+    std::getline(in,line);
+    if(line.find("DITABIS micron Data File")!=String::npos){
+      //ignore
+    }else if(line.find("CREATED")!=String::npos){
+      h.date=line.substr(line.find("=")+2);
+    }else if(line.find("HEADER")!=String::npos){
+      std::istringstream ( line.substr(line.find("=")+2) ) >> h.header_length;
+    // x and y get swapped here (follows the behaviour of the original conversion software)
+    }else if(line.find("XPIXEL")!=String::npos){
+      std::istringstream ( line.substr(line.find("=")+2) ) >> h.size_y;
+    }else if(line.find("YPIXEL")!=String::npos){
+      std::istringstream ( line.substr(line.find("=")+2) ) >> h.size_x;
+    }else if(line.find("BYTE PER PIXEL")!=String::npos){
+      std::istringstream ( line.substr(line.find("=")+2) ) >> h.bit_depth;
+      // x and y get swapped here (follows the behaviour of the original conversion software)
+    }else if(line.find("XRESOLUTION")!=String::npos){
+      std::istringstream ( line.substr(line.find("(")+1) ) >> h.resolution_y;
+      h.resolution_y*=Units::nm;
+    }else if(line.find("YRESOLUTION")!=String::npos){
+      std::istringstream ( line.substr(line.find("(")+1) ) >> h.resolution_x;
+      h.resolution_x*=Units::nm;
+    }else if(line.find("MAGNIFICATION")!=String::npos){
+      std::istringstream ( line.substr(line.find("=")+2) ) >> h.magnification;
+    }else if(line.find("THUMB-NAIL-ZOOM")!=String::npos){
+      std::istringstream ( line.substr(line.find("=")+2) ) >> h.thumb_nail_zoom;
+    }else if(line.find("CHANNEL")!=String::npos){
+      h.channel=line.substr(line.find("=")+2);
+    }else if(line.find("PARAMS")!=String::npos){
+      h.params=line.substr(line.find("=")+2);
+    }else if(line.find("FORMAT")!=String::npos){
+      h.format=line.substr(line.find("=")+2);
+    }else if(line.find("LASER")!=String::npos){
+      std::istringstream ( line.substr(line.find("=")+2) ) >> h.laser;
+    }else if(line.find("GAIN")!=String::npos){
+      std::istringstream ( line.substr(line.find("=")+2) ) >> h.gain;
+    }else if(line.find("OFFSET CORRECTION")!=String::npos){
+      if(line.substr(line.find("=")+2).find("YES")!=String::npos){
+        h.offset_correction=true;
+      }else{
+        h.offset_correction=false;
+      }
+    }else if(line.find("OFFSET")!=String::npos){
+      std::istringstream ( line.substr(line.find("=")+2) ) >> h.offset;
+    }else if(line.find("COMMENT")!=String::npos){
+      h.comment=line.substr(line.find("=")+2);
+    }else if(line.find(" ")!=String::npos){
+      //ignore
+    }else{
+      LOG_ERROR("IPL import: unknown header line: " << line);
+    }
+  }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);
+  return in;
+}
+
+}//ns
+
+bool MapIOIPLHandler::MatchType(const ImageFormatBase& type)
+{
+  if(type.GetFormatString()==IPL::FORMAT_STRING) {
+    return true;
+  }
+  return false;
+}
+
+bool MapIOIPLHandler::MatchSuffix(const String& loc)
+{
+    if(detail::FilenameEndsWith(loc,".IPL") || detail::FilenameEndsWith(loc,".ipl") ) {
+      return true;
+    }
+    return false;
+}
+
+void MapIOIPLHandler::Import(img::MapHandle& sh, const boost::filesystem::path& loc,const ImageFormatBase& formatstruct )
+{
+  boost::filesystem::ifstream infile(loc, std::ios::binary);
+  if(!infile) {
+    throw IOException("could not open "+loc.string());
+  }
+  this->Import(sh,infile,formatstruct);
+  infile.close();
+}
+
+template <typename DATATYPE>
+void real_filler(img::image_state::RealSpatialImageState&  isi, std::istream& file)
+{
+  BinaryIStream<OST_LITTLE_ENDIAN> file_bin(file);
+  img::Size size = isi.GetSize();
+  char this_dummy; //create dummy variable to give to img::Progress as this
+  img::Progress::Instance().Register(&this_dummy,size[1],100);
+  for(unsigned int row=0;row<size[1];row++) {
+    for(unsigned int column=0;column<size[0];column++) {
+      DATATYPE value;
+      file_bin >> value;
+      isi.Value(img::Point(column,row))=static_cast<Real>(value);
+    }
+    img::Progress::Instance().AdvanceProgress(&this_dummy);
+  }
+  img::Progress::Instance().DeRegister(&this_dummy);
+}
+
+template <typename DATATYPE>
+void real_dumper( const img::ConstImageHandle& sh, std::ostream& file, const IPL& formatIPL, int shrinksize)
+{
+  img::image_state::RealSpatialImageState *isi=dynamic_cast<img::image_state::RealSpatialImageState*>(sh.ImageStatePtr().get());
+  if(! isi){
+    throw(IOException("IPL export: dynamic cast failed in real dumper."));
+  }
+  BinaryOStream<OST_LITTLE_ENDIAN> file_bin(file);
+  img::alg::Normalizer norm = img::alg::CreateNoOpNormalizer();
+  if (formatIPL.GetNormalizeOnSave() == true) {
+    norm = img::alg::CreateLinearRangeNormalizer(sh,formatIPL.GetMinimum(),formatIPL.GetMaximum());
+  }
+  img::Size size = isi->GetSize();
+  img::ImageHandle thumbnail=sh.Apply(img::alg::DiscreteShrink(img::Size(shrinksize,shrinksize,1)));
+  img::image_state::RealSpatialImageState *thumb_isi=dynamic_cast<img::image_state::RealSpatialImageState*>(thumbnail.ImageStatePtr().get());
+  if(! thumb_isi){
+    throw(IOException("IPL export: dynamic cast failed in real dumper."));
+  }
+
+  char this_dummy; //create dummy variable to give to img::Progress as this
+  img::Progress::Instance().Register(&this_dummy,size[1]+1,100);
+  for(unsigned int row=0;row<size[1];row++) {
+    for(unsigned int column=0;column<size[0];column++)
+    {
+      file_bin << static_cast<DATATYPE>(norm.Convert(isi->Value(ost::img::Point(column,row,0))));
+    }
+    img::Progress::Instance().AdvanceProgress(&this_dummy);
+  }
+  img::Progress::Instance().AdvanceProgress(&this_dummy);
+  img::Size thumb_size = thumb_isi->GetSize();
+  for(unsigned int row=0;row<thumb_size[1];row++) {
+    for(unsigned int column=0;column<thumb_size[0];column++)
+    {
+      file_bin << static_cast<DATATYPE>(norm.Convert(thumb_isi->Value(ost::img::Point(column,row,0))));
+    }
+    img::Progress::Instance().AdvanceProgress(&this_dummy);
+  }
+  img::Progress::Instance().DeRegister(&this_dummy);
+}
+
+
+void MapIOIPLHandler::Import(img::MapHandle& sh, std::istream& file, const ImageFormatBase& formatstruct)
+{
+
+  IPL form;
+  IPL& formatIPL = form;
+  if (formatstruct.GetFormatString()==IPL::FORMAT_STRING) {
+    formatIPL = formatstruct.As<IPL>();
+  } else {
+    assert (formatstruct.GetFormatString()==UndefinedImageFormat::FORMAT_STRING);
+  }
+
+  detail::IPLHeader header;
+  file >> header;
+
+  sh.Reset(img::Extent(img::Point(0,0),img::Size(header.size_x,header.size_y)), img::REAL, img::SPATIAL);
+  sh.SetSpatialSampling(geom::Vec3(header.resolution_x,header.resolution_y,1.0));
+  img::image_state::RealSpatialImageState * isi;
+  if(! (isi=dynamic_cast<img::image_state::RealSpatialImageState*>(sh.ImageStatePtr().get()))) {
+    throw IOException("internal error in IPL io: expected RealSpatialImageState");
+  }
+
+  if(header.bit_depth==4){
+    real_filler<uint32_t>(*isi,file);
+  }else{
+    real_filler<uint16_t>(*isi,file);
+  }
+}
+
+void MapIOIPLHandler::Export(const img::MapHandle& mh2,
+                                  const boost::filesystem::path& loc,const ImageFormatBase& formatstruct) const
+{
+  boost::filesystem::ofstream outfile(loc, std::ios::binary);
+  if(!outfile)
+  {
+    throw IOException("could not open "+loc.string());
+  }
+  this->Export(mh2,outfile,formatstruct);
+  outfile.close();
+}
+
+void MapIOIPLHandler::Export(const img::MapHandle& sh, std::ostream& file,const ImageFormatBase& formatstruct) const
+{
+
+  IPL form;
+  IPL& formatIPL = form;
+  if (formatstruct.GetFormatString()==IPL::FORMAT_STRING) {
+    formatIPL = formatstruct.As<IPL>();
+  } else {
+    assert (formatstruct.GetFormatString()==UndefinedImageFormat::FORMAT_STRING);
+  }
+  if (sh.GetSize()[2]!=1 || sh.GetDomain()!=img::SPATIAL || sh.GetType()!=img::REAL) {
+    throw IOException("IPL IO: IPL format only supports spatial 2D images.");
+  }
+  detail::IPLHeader header(sh,formatIPL.GetBitDepth());
+  file << header;
+  if(header.bit_depth==4){
+    real_dumper<uint32_t>(sh,file,formatIPL,header.thumb_nail_zoom);
+  }else{
+    real_dumper<uint16_t>(sh,file,formatIPL,header.thumb_nail_zoom);
+  }
+}
+
+}} // namespaces
+
+
diff --git a/modules/io/src/img/map_io_ipl_handler.hh b/modules/io/src/img/map_io_ipl_handler.hh
new file mode 100644
index 0000000000000000000000000000000000000000..3e76ac9895c0689defe002d0399359e03f3e09aa
--- /dev/null
+++ b/modules/io/src/img/map_io_ipl_handler.hh
@@ -0,0 +1,78 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+// Copyright (C) 2003-2010 by the IPLT authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+#ifndef OST_IO_MAP_IO_IPL_HANDLER_HH
+#define OST_IO_MAP_IO_IPL_HANDLER_HH
+
+
+/*
+Andreas Schenk
+*/
+
+#include "map_io_handler.hh"
+
+namespace ost { namespace io {
+
+class DLLEXPORT_OST_IO IPL: public ImageFormatBase
+{
+
+ public:
+
+  IPL(bool normalize_on_save = true, Format bit_depth = OST_DEFAULT_FORMAT);
+
+  Format GetBitDepth() const;
+  void SetBitDepth ( Format bitdepth);
+
+
+  bool GetNormalizeOnSave() const;
+  void SetNormalizeOnSave(bool normalize_on_save=true);
+  Real GetMaximum() const;
+  Real GetMinimum() const;
+  static String FORMAT_STRING;
+
+ private:
+  bool normalize_on_save_;
+  Format bit_depth_;
+
+};
+
+class DLLEXPORT_OST_IO MapIOIPLHandler: public MapIOHandler
+{
+  public:
+    /// \brief Map IO handler to read/write Ipl map files
+    ///
+    /// This map IO handler reads and writes Ipl formatted map files.
+    virtual void Import(img::MapHandle& sh, const boost::filesystem::path& loc,const ImageFormatBase& formatstruct );
+    virtual void Import(img::MapHandle& sh, std::istream& loc, const ImageFormatBase& formatstruct);
+    virtual void Export(const img::MapHandle& sh, const boost::filesystem::path& loc, const ImageFormatBase& formatstruct) const;
+    virtual void Export(const img::MapHandle& sh, std::ostream& loc,const ImageFormatBase& formatstruct) const;
+    static bool MatchContent(unsigned char* header);
+    static bool MatchType(const ImageFormatBase& type);
+    static bool MatchSuffix(const String& loc);
+    static bool ProvidesImport() { return true; }
+    static bool ProvidesExport() { return true; }
+    static String GetFormatName() { return String("IPL"); }
+    static String GetFormatDescription() {return String("Ditabis Micron Image Plate Scanner Format");}
+};
+
+typedef MapIOHandlerFactory<MapIOIPLHandler> MapIOIPLHandlerFactory;
+
+}} // ns
+
+#endif
diff --git a/modules/io/src/io_manager.cc b/modules/io/src/io_manager.cc
index 12e714fd63a0170d32c676bf60bde007571ff6f6..071be5c11461382803e8a3704bdbd32ba760ed18 100644
--- a/modules/io/src/io_manager.cc
+++ b/modules/io/src/io_manager.cc
@@ -38,6 +38,7 @@
 #  include  <ost/io/img/map_io_jpk_handler.hh>
 #  include  <ost/io/img/map_io_nanoscope_handler.hh>
 #  include  <ost/io/img/map_io_df3_handler.hh>
+#  include  <ost/io/img/map_io_ipl_handler.hh>
 #endif
 namespace ost { namespace io {
 
@@ -63,7 +64,8 @@ IOManager::IOManager()
   RegisterFactory(MapIOHandlerFactoryBasePtr(new MapIOJpkHandlerFactory));
   RegisterFactory(MapIOHandlerFactoryBasePtr(new MapIODatHandlerFactory));
   RegisterFactory(MapIOHandlerFactoryBasePtr(new MapIONanoscopeHandlerFactory));
-  RegisterFactory(MapIOHandlerFactoryBasePtr(new MapIODF3HandlerFactory));  
+  RegisterFactory(MapIOHandlerFactoryBasePtr(new MapIODF3HandlerFactory));
+  RegisterFactory(MapIOHandlerFactoryBasePtr(new MapIOIPLHandlerFactory));
 #endif
 }
 
diff --git a/modules/io/src/mol/entity_io_mae_handler.cc b/modules/io/src/mol/entity_io_mae_handler.cc
index a60b913f378db4b65a6043dfdf7959ef155d236a..6a5306b055c44f7d6c6ccc82f5defa8c1acd1d35 100644
--- a/modules/io/src/mol/entity_io_mae_handler.cc
+++ b/modules/io/src/mol/entity_io_mae_handler.cc
@@ -143,7 +143,13 @@ void MAEReader::Import(mol::EntityHandle& ent)
               else if(line2=="r_m_z_coord") i_atom_zpos=pid;
               else if(line2=="s_m_pdb_residue_name") i_res_name=pid;
               else if(line2=="i_m_residue_number") i_res_num=pid;
-              else if(line2=="s_m_pdb_segment_name") i_chain_name=pid;
+              else if(line2=="s_m_chain_name") i_chain_name=pid;
+              else if(line2=="s_m_pdb_segment_name") {
+                // only use this one if s_m_chain_name is not present
+                if(i_chain_name<0) {
+                  i_chain_name=pid;
+                }
+              }
             }
           }
         }
diff --git a/modules/io/src/mol/pdb_reader.cc b/modules/io/src/mol/pdb_reader.cc
index c136147a6d408e6c09a3b3a2c5414dc3108ccb2a..53433b1db8898a66fd614f8d916520b731868ee2 100644
--- a/modules/io/src/mol/pdb_reader.cc
+++ b/modules/io/src/mol/pdb_reader.cc
@@ -781,19 +781,21 @@ void PDBReader::ParseAndAddAtom(const StringRef& line, int line_num,
          << "residue with number " << res_num << " has more than one name.";
       throw IOException(ss.str());
     }
-    if (!warned_name_mismatch_) {
-      if (alt_loc==' ') {
-        LOG_WARNING("Residue with number " << res_num << " has more than one name."
-                    "Ignoring atoms for everything but the first");        
-      } else {
-        LOG_WARNING("Residue with number " << res_num 
-                    << " contains a microheterogeneity. Everything but atoms for "
-                    << "the residue '" << curr_residue_.GetName() 
-                    << "' will be ignored");
+    if(!profile_.quack_mode) {
+      if (!warned_name_mismatch_) {
+        if (alt_loc==' ') {
+          LOG_WARNING("Residue with number " << res_num << " has more than one name. "
+                      "Ignoring atoms for everything but the first");        
+        } else {
+          LOG_WARNING("Residue with number " << res_num 
+                      << " contains a microheterogeneity. Everything but atoms for "
+                      << "the residue '" << curr_residue_.GetName() 
+                      << "' will be ignored");
+        }
       }
+      warned_name_mismatch_=true;
+      return;
     }
-    warned_name_mismatch_=true;
-    return;
   }
   if (alt_loc!=' ') {
     // Check if there is already a atom with the same name.
diff --git a/modules/io/src/mol/star_parser.cc b/modules/io/src/mol/star_parser.cc
index 069deac0eb23216b02cd3f61a4ed8ec460f03f97..d8903a9de0baac3dfc3c037c20f449f9cabaa2da 100644
--- a/modules/io/src/mol/star_parser.cc
+++ b/modules/io/src/mol/star_parser.cc
@@ -37,7 +37,7 @@ StarParser::StarParser(std::istream& stream, bool items_as_row):
   items_row_values_()
 {
   items_as_row_ = items_as_row;
-
+  
   if (!stream) {
     file_open_ = false;
   }
@@ -51,8 +51,6 @@ StarParser::StarParser(const String& filename, bool items_as_row):
   items_row_header_(), file_open_(true), items_row_columns_(),
   items_row_values_()
 {
-  items_as_row_ = items_as_row;
-
   if (filename.length() >= 3 &&
       filename.substr(filename.length() - 3) == ".gz") {
     stream_.push(boost::iostreams::gzip_decompressor());
diff --git a/modules/io/tests/test_io_img.cc b/modules/io/tests/test_io_img.cc
index d8165dd76203ba7fcb1fc8e00fcce5a7df290a62..9f21257d3b942bef23e9043651bc0addf4f0232f 100644
--- a/modules/io/tests/test_io_img.cc
+++ b/modules/io/tests/test_io_img.cc
@@ -34,6 +34,7 @@
 #include  <ost/io/img/map_io_dat_handler.hh>
 #include  <ost/io/img/map_io_jpk_handler.hh>
 #include  <ost/io/img/map_io_nanoscope_handler.hh>
+#include  <ost/io/img/map_io_ipl_handler.hh>
 #include  <ost/img/alg/normalizer_factory.hh>
 
 using namespace ost;
@@ -82,6 +83,7 @@ BOOST_AUTO_TEST_CASE(test_io_img)
   }
   //int 16 formats
   std::map<String,ImageFormatBase*> int_formats;
+  int_formats["IPL (16 bit)"]=new IPL(true,OST_BIT16_FORMAT);
   int_formats["DAT (16 bit)"]=new DAT(true,OST_BIT16_FORMAT);
   int_formats["TIF (16 bit)"]=new TIF;
   int_formats["JPK (16 bit)"]=new JPK;
@@ -108,6 +110,31 @@ BOOST_AUTO_TEST_CASE(test_io_img)
     delete it->second;
   }
 
+  //int 32 formats
+  std::map<String,ImageFormatBase*> int32_formats;
+  int32_formats["IPL (16 bit)"]=new IPL(true,OST_BIT32_FORMAT);
+  for(std::map<String,ImageFormatBase*>::iterator it=int32_formats.begin();it!=int32_formats.end();++it){
+    ost::io::SaveImage(testimage,fname,*(it->second));
+    ost::img::ImageHandle loadedimage=ost::io::LoadImage(fname,*(it->second));
+    ost::img::alg::Normalizer norm=ost::img::alg::CreateLinearRangeNormalizer(testimage,0.0,4294967295.0);
+    ost::img::ImageHandle scaled_image=testimage.Apply(norm);
+    bool failed=false;
+    ost::img::ExtentIterator eit(scaled_image.GetExtent());
+    for(;!eit.AtEnd();++eit) {
+      if( static_cast<int>(scaled_image.GetReal(eit))!=static_cast<int>(loadedimage.GetReal(eit))){
+        failed=true;
+        break;
+      }
+    }
+    if(failed){
+      BOOST_ERROR("Image IO failed for plugin " << it->first << " at point "
+                  << ost::img::Point(eit)<< ". Should be "
+                  << static_cast<int>(scaled_image.GetReal(eit)) << ", but "
+                  << static_cast<int>(loadedimage.GetReal(eit)) << " found.");
+    }
+    delete it->second;
+  }
+
   //byte formats  
   std::map<String,ImageFormatBase*> byte_formats;
   byte_formats["DAT (byte)"]=new DAT(true,OST_BIT8_FORMAT);
diff --git a/modules/mol/alg/pymod/export_trajectory_analysis.cc b/modules/mol/alg/pymod/export_trajectory_analysis.cc
index 31377016a874dc6dcc42cc702d11a3a4058f0934..5671dbca091c49746976714679c04dd48a68fd36 100644
--- a/modules/mol/alg/pymod/export_trajectory_analysis.cc
+++ b/modules/mol/alg/pymod/export_trajectory_analysis.cc
@@ -46,4 +46,8 @@ void export_TrajectoryAnalysis()
   def("AnalyzeMinDistance", &AnalyzeMinDistance, (arg("traj"), arg("view1"), arg("view2"), arg("stride")=1));
   def("AnalyzeMinDistanceBetwCenterOfMassAndView", &AnalyzeMinDistanceBetwCenterOfMassAndView, (arg("traj"), arg("view_cm"), arg("view_atoms"), arg("stride")=1));
   def("AnalyzeAromaticRingInteraction", &AnalyzeAromaticRingInteraction, (arg("traj"), arg("view_ring1"), arg("view_ring2"), arg("stride")=1));
+  def("AnalyzeAlphaHelixAxis", &AnalyzeAlphaHelixAxis, (arg("traj"), arg("protein_segment"), arg("directions"), arg("centers"), arg("stride")=1));
+  def("AnalyzeBestFitLine", &AnalyzeBestFitLine, (arg("traj"), arg("protein_segment"), arg("directions"), arg("centers"), arg("stride")=1));
+  def("AnalyzeHelicity", &AnalyzeHelicity, (arg("traj"), arg("protein_segment"), arg("stride")=1));
+  def("CreateMeanStructure", &CreateMeanStructure, (arg("traj"), arg("selection"), arg("from")=0, arg("to")=-1, arg("stride")=1 ));
 }
diff --git a/modules/mol/alg/src/trajectory_analysis.cc b/modules/mol/alg/src/trajectory_analysis.cc
index 2c1225e753ba76adacfa3ccfd8dc6a2ccce18a95..7f81b91d13a68edaff14e5ea2fd3a20806443192 100644
--- a/modules/mol/alg/src/trajectory_analysis.cc
+++ b/modules/mol/alg/src/trajectory_analysis.cc
@@ -25,7 +25,9 @@
 #include <ost/geom/vec3.hh>
 #include <ost/base.hh>
 #include <ost/geom/geom.hh>
+#include <ost/gfx/entity.hh>
 #include <ost/mol/entity_view.hh>
+#include <ost/mol/view_op.hh>
 #include <ost/mol/coord_group.hh>
 #include "trajectory_analysis.hh"
 
@@ -230,4 +232,104 @@ std::vector<Real> AnalyzeAromaticRingInteraction(const CoordGroupHandle& traj, c
   }
   return dist;  
   }
+
+  void AnalyzeAlphaHelixAxis(const CoordGroupHandle& traj, const EntityView& prot_seg, geom::Vec3List& directions,
+                             geom::Vec3List& centers, unsigned int stride)
+  {
+    CheckHandleValidity(traj);
+    if (prot_seg.GetAtomCount()==0){
+      throw std::runtime_error("EntityView is empty");
+    }
+    std::vector<unsigned long> indices_ca;
+    geom::Line3 axis;
+    directions.reserve(ceil(traj.GetFrameCount()/float(stride)));
+    centers.reserve(ceil(traj.GetFrameCount()/float(stride)));
+    GetCaIndices(prot_seg, indices_ca);
+    for (size_t i=0; i<traj.GetFrameCount(); i+=stride) {
+      CoordFramePtr frame=traj.GetFrame(i);
+      axis=frame->FitCylinder(indices_ca);
+      directions.push_back(axis.GetDirection());
+      centers.push_back(axis.GetOrigin());
+    }
+    return;
+  }
+ 
+  //std::vector<geom::Line3> AnalyzeBestFitLine(const CoordGroupHandle& traj, const EntityView& prot_seg,
+  //                                               unsigned int stride)
+  void AnalyzeBestFitLine(const CoordGroupHandle& traj, const EntityView& prot_seg, geom::Vec3List& directions,
+                          geom::Vec3List& centers, unsigned int stride)
+  {
+    CheckHandleValidity(traj);
+    if (prot_seg.GetAtomCount()==0){
+      throw std::runtime_error("EntityView is empty");
+    }
+    std::vector<unsigned long> indices_ca;
+    geom::Line3 axis;
+    directions.reserve(ceil(traj.GetFrameCount()/float(stride)));
+    centers.reserve(ceil(traj.GetFrameCount()/float(stride)));
+    GetCaIndices(prot_seg, indices_ca);
+    for (size_t i=0; i<traj.GetFrameCount(); i+=stride) {
+      CoordFramePtr frame=traj.GetFrame(i);
+      axis=frame->GetODRLine(indices_ca);
+      directions.push_back(axis.GetDirection());
+      centers.push_back(axis.GetOrigin());
+    }
+    return;
+  }
+ 
+  std::vector<Real> AnalyzeHelicity(const CoordGroupHandle& traj, const EntityView& prot_seg,
+                                    unsigned int stride)
+  {
+    CheckHandleValidity(traj);
+    if (prot_seg.GetAtomCount()==0){
+      throw std::runtime_error("EntityView is empty");
+    }
+    std::vector<unsigned long> indices_c,indices_o, indices_n, indices_ca;
+    std::vector<Real> helicity;
+    helicity.reserve(ceil(traj.GetFrameCount()/float(stride)));
+    GetCaCONIndices(prot_seg, indices_ca, indices_c, indices_o, indices_n);
+    for (size_t i=0; i<traj.GetFrameCount(); i+=stride) {
+      CoordFramePtr frame=traj.GetFrame(i);
+      helicity.push_back(frame->GetAlphaHelixContent(indices_ca,indices_c,indices_o,indices_n));
+    }
+    return helicity;
+  }
+
+  //This function constructs mean structures from a trajectory
+  EntityHandle CreateMeanStructure(const CoordGroupHandle& traj, const EntityView& selection,
+                            int from, int to, unsigned int stride)
+  {
+    CheckHandleValidity(traj);
+    if (to==-1)to=traj.GetFrameCount();
+    unsigned int n_atoms=selection.GetAtomCount();
+    if (to<from) {
+      throw std::runtime_error("to smaller than from");
+    }
+    unsigned int n_frames=to-from;
+    if (n_atoms==0){
+      throw std::runtime_error("EntityView is empty");
+    }
+    if (n_frames<=stride) {
+      throw std::runtime_error("number of frames is too small");
+    }
+    std::vector<unsigned long> indices;
+    std::vector<geom::Vec3> mean_positions;
+    EntityHandle eh;
+    eh=CreateEntityFromView(selection,1);
+    GetIndices(selection,indices);
+    mean_positions.assign(n_atoms,geom::Vec3(0.0,0.0,0.0));
+    for (int i=from; i<to; i+=stride) {
+      CoordFramePtr frame=traj.GetFrame(i);
+      for (unsigned int j=0; j<n_atoms; ++j) {
+        mean_positions[j]+=(*frame)[indices[j]];
+      }
+    }
+    mol::XCSEditor edi=eh.EditXCS(mol::BUFFERED_EDIT);
+    AtomHandleList atoms=eh.GetAtomList();
+    for (unsigned int j=0; j<n_atoms; ++j) {
+      edi.SetAtomPos(atoms[j],mean_positions[j]/Real(n_frames));
+    }
+    return eh;
+  }
+
 }}} //ns
diff --git a/modules/mol/alg/src/trajectory_analysis.hh b/modules/mol/alg/src/trajectory_analysis.hh
index faa6c8ea06d657afe169ac688c8cd8e6b8148b11..d2ba49b6eb2862bb1f8fb7ec4a42da2d564aad26 100644
--- a/modules/mol/alg/src/trajectory_analysis.hh
+++ b/modules/mol/alg/src/trajectory_analysis.hh
@@ -43,5 +43,9 @@ namespace ost { namespace mol { namespace alg {
   std::vector<Real> DLLEXPORT_OST_MOL_ALG AnalyzeMinDistance(const CoordGroupHandle& traj, const EntityView& view1, const EntityView& view2,unsigned int stride=1);
   std::vector<Real> DLLEXPORT_OST_MOL_ALG AnalyzeMinDistanceBetwCenterOfMassAndView(const CoordGroupHandle& traj, const EntityView& view_cm, const EntityView& view_atoms,unsigned int stride=1);
   std::vector<Real> DLLEXPORT_OST_MOL_ALG AnalyzeAromaticRingInteraction(const CoordGroupHandle& traj, const EntityView& view_ring1, const EntityView& view_ring2,unsigned int stride=1);
+  void  DLLEXPORT_OST_MOL_ALG AnalyzeAlphaHelixAxis(const CoordGroupHandle& traj, const EntityView& prot_seg, geom::Vec3List& directions, geom::Vec3List& centers, unsigned int stride=1);
+  void  DLLEXPORT_OST_MOL_ALG AnalyzeBestFitLine(const CoordGroupHandle& traj, const EntityView& prot_seg, geom::Vec3List& directions, geom::Vec3List& centers, unsigned int stride=1);
+  EntityHandle  DLLEXPORT_OST_MOL_ALG CreateMeanStructure(const CoordGroupHandle& traj, const EntityView& selection, int from=0, int to=-1, unsigned int stride=1);
+  std::vector<Real> DLLEXPORT_OST_MOL_ALG AnalyzeHelicity(const CoordGroupHandle& traj, const EntityView& prot_seg, unsigned int stride=1);
 }}}//ns
 #endif
diff --git a/modules/mol/base/pymod/export_coord_frame.cc b/modules/mol/base/pymod/export_coord_frame.cc
index fdb41fce60b8032ecb6f527256b4b9c90d7cc5e1..6636421ad702ab8dc41f88f865ae8de3fd2ab451 100644
--- a/modules/mol/base/pymod/export_coord_frame.cc
+++ b/modules/mol/base/pymod/export_coord_frame.cc
@@ -34,7 +34,7 @@ geom::Vec3 (CoordFrame::*get_cm)(const mol::EntityView& sele) = &CoordFrame::Get
 Real (CoordFrame::*get_dist_cm)(const mol::EntityView& sele1, const mol::EntityView& sele2) = &CoordFrame::GetDistanceBetwCenterOfMass;
 Real (CoordFrame::*get_rmsd)(const mol::EntityView& Reference_View, const mol::EntityView& sele_View) = &CoordFrame::GetRMSD;
 Real (CoordFrame::*get_min_dist)(const mol::EntityView& view1, const mol::EntityView& view2) = &CoordFrame::GetMinDistance;
-
+Real (CoordFrame::*get_alpha)(const mol::EntityView& segment) = &CoordFrame::GetAlphaHelixContent;
 void export_CoordFrame()
 {
   class_<CoordFrame>("CoordFrame",no_init)
@@ -46,6 +46,8 @@ void export_CoordFrame()
     .def("GetDistanceBetwCenterOfMass", get_dist_cm)
     .def("GetRMSD",get_rmsd)
     .def("GetMinDistance",get_min_dist)
+    .def("GetODRLine",&geom::Vec3List::GetODRLine)
+    .def("GetAlphaHelixContent",get_alpha)
   ;
   def("CreateCoordFrame",CreateCoordFrame);
 }
diff --git a/modules/mol/base/pymod/export_residue.cc b/modules/mol/base/pymod/export_residue.cc
index c4c43e5d89ca06505a65a7b39035692d7150681e..75d74bdb577c618094ee18223102dfa56f932abe 100644
--- a/modules/mol/base/pymod/export_residue.cc
+++ b/modules/mol/base/pymod/export_residue.cc
@@ -43,15 +43,34 @@ namespace {
 
   void set_sec_struct1(ResidueBase* b, const SecStructure& s) {b->SetSecStructure(s);}
   void set_sec_struct2(ResidueBase* b, char c) {b->SetSecStructure(SecStructure(c));}
-  void set_chemclass1(ResidueBase* b, const ChemClass& cc) {b->SetChemClass(cc);}
-  void set_chemclass2(ResidueBase* b, char c) {b->SetChemClass(ChemClass(c));}
 
+  void set_chemclass(ResidueBase* b, object po)
+  {
+    extract<ChemClass> ex1(po);
+    if(ex1.check()) {
+      b->SetChemClass(ex1());
+    }
+    extract<char> ex2(po);
+    if(ex2.check()) {
+      b->SetChemClass(ChemClass(ex2()));
+    }
+    std::string st=extract<std::string>(po);
+    if(st.empty()) {
+      throw Error("expected non-empty string as chem class");
+    }
+    b->SetChemClass(ChemClass(st[0]));
+  }
 }
 
-//BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(X_insert_overloads,
-//                                       ResidueHandle::InsertAtom, 2, 3)
 void export_Residue()
 {
+  class_<ChemClass>("ChemClass", init<char>(args("chem_class")))
+    .def(self!=self)
+    .def(self==self)
+    .def("IsPeptideLinking", &ChemClass::IsPeptideLinking)
+    .def("IsNucleotideLinking", &ChemClass::IsNucleotideLinking)
+  ;
+  implicitly_convertible<char, ChemClass>();
   
   class_<ResNum>("ResNum", init<int>(args("num")))
     .def(init<int,char>(args("num", "ins_code")))
@@ -125,6 +144,11 @@ void export_Residue()
     .def("IsPeptideLinking", &ResidueBase::IsPeptideLinking)
     .add_property("peptide_linking", &ResidueBase::IsPeptideLinking)
     
+    .def("GetCentralAtom", &ResidueBase::GetCentralAtom)
+    .def("SetCentralAtom", &ResidueBase::SetCentralAtom)
+    .add_property("central_atom", &ResidueBase::GetCentralAtom, &ResidueBase::SetCentralAtom)
+    .add_property("central_normal", &ResidueBase::GetCentralNormal)
+
     .def("GetKey", &ResidueBase::GetKey,
          return_value_policy<copy_const_reference>())
      .def("GetName", &ResidueBase::GetName,
@@ -132,8 +156,8 @@ void export_Residue()
     .def("GetNumber", &ResidueBase::GetNumber,
          return_value_policy<copy_const_reference>())
     .def("GetChemClass", &ResidueBase::GetChemClass)
-    .def("SetChemClass", set_chemclass1)
-    .def("SetChemClass", set_chemclass2)
+    .add_property("chem_class", &ResidueBase::GetChemClass, set_chemclass)
+    .def("SetChemClass", set_chemclass)
     .add_property("is_ligand", &ResidueBase::IsLigand, &ResidueBase::SetIsLigand)
     .def("IsLigand", &ResidueBase::IsLigand)
     .def("SetIsLigand", &ResidueBase::SetIsLigand)
@@ -186,7 +210,6 @@ void export_Residue()
     .def("GetCenterOfMass", &ResidueHandle::GetCenterOfMass)
     .def("GetCenterOfAtoms", &ResidueHandle::GetCenterOfAtoms)
     .def("GetGeometricCenter", geom_center<ResidueHandle>)
-    .def("GetCentralAtom", &ResidueHandle::GetCentralAtom)
     .add_property("mass", &ResidueHandle::GetMass)
     .add_property("center_of_mass", &ResidueHandle::GetCenterOfMass)
     .add_property("center_of_atoms", &ResidueHandle::GetCenterOfAtoms)  
diff --git a/modules/mol/base/src/coord_frame.cc b/modules/mol/base/src/coord_frame.cc
index 80ef4f58f3ea3aed2b1ae691b6cc35c70107faf0..efeb37e20fc086ebb425751b258e74334f86d3d1 100644
--- a/modules/mol/base/src/coord_frame.cc
+++ b/modules/mol/base/src/coord_frame.cc
@@ -28,6 +28,7 @@
 #include <ost/mol/view_op.hh>
 #include <ost/mol/mol.hh>
 #include "coord_frame.hh"
+#include <ost/base.hh>
 
 namespace ost { namespace mol {
 
@@ -84,7 +85,52 @@ namespace ost { namespace mol {
       indices.push_back(i->GetIndex());
     }
   }
+
+  void GetCaIndices(const EntityView& segment, std::vector<unsigned long>& indices_ca){
+    mol::AtomView ca;
+    ResidueViewList residues=segment.GetResidueList();
+    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");
+    //}
+    for (ResidueViewList::const_iterator res=residues.begin(),
+         e=residues.end(); res!=e; ++res) {
+      ca=res->FindAtom("CA");
+      CheckHandleValidity(ca);
+      indices_ca.push_back(ca.GetIndex());
+      }
+  }
   
+  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){
+    mol::AtomView a,n,c,o;
+    ResidueViewList residues=segment.GetResidueList();
+    indices_ca.reserve(residues.size());
+    indices_n.reserve(residues.size());
+    indices_c.reserve(residues.size());
+    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");
+    }
+    for (ResidueViewList::const_iterator res=residues.begin(),
+         e=residues.end(); res!=e; ++res) {
+      a=res->FindAtom("CA");
+      CheckHandleValidity(a);
+      indices_ca.push_back(a.GetIndex());
+      c=res->FindAtom("C");
+      CheckHandleValidity(c);
+      indices_c.push_back(c.GetIndex());
+      o=res->FindAtom("O");
+      CheckHandleValidity(o);
+      indices_o.push_back(o.GetIndex());
+      n=res->FindAtom("N");
+      CheckHandleValidity(n);
+      indices_n.push_back(n.GetIndex());
+    }
+  }
+
   void GetMasses(const EntityView& sele, std::vector<Real>& masses){
   // 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
@@ -218,5 +264,110 @@ namespace ost { namespace mol {
     GetIndicesAndMasses(view_cm,indices_cm,masses_cm);
     return this->GetMinDistBetwCenterOfMassAndView(indices_cm,masses_cm,indices_atoms);
   }
+
+  geom::Line3 CoordFrame::GetODRLine(std::vector<unsigned long>& indices_ca){
+  //Returns the best fit line to atoms with indices in indices_ca
+    geom::Vec3List atoms_pos_list;
+    atoms_pos_list.reserve(indices_ca.size());
+    for (std::vector<unsigned long>::const_iterator i1=indices_ca.begin(),e=indices_ca.end(); i1!=e; ++i1) {
+      atoms_pos_list.push_back((*this)[*i1]);
+    }
+    return atoms_pos_list.GetODRLine();
+  }
+ 
+  geom::Line3 CoordFrame::FitCylinder(std::vector<unsigned long>& indices_ca){
+  //Returns a line which is the axis of a fitted cylinder to the atoms with indices given in indices_ca
+    geom::Vec3List atoms_pos_list;
+    atoms_pos_list.reserve(indices_ca.size());
+    for (std::vector<unsigned long>::const_iterator i1=indices_ca.begin(),e=indices_ca.end(); i1!=e; ++i1) {
+      atoms_pos_list.push_back((*this)[*i1]);
+    }
+    return atoms_pos_list.FitCylinder();
+  }
+ 
+  Real CoordFrame::GetAlphaHelixContent(const mol::EntityView& segment){
+    //Returns the percentage of residues in the EntityView (segment) that are in an alpha-helix
+    //Each residue is assigned as being in an alpha-helix or not, based on and backbone torsion angles
+    //and the hydrogen bonding (O-N) (this term is used only if the segment contains at least 8 residues
+    //The entity view should be a single segment with no gaps and no missing N,CA,C,O backbone atoms
+    //the first and last residues will not be asessed for helicity
+    CheckHandleValidity(segment);
+    std::vector<unsigned long> indices_c, indices_n, indices_ca, indices_o;
+    GetCaCONIndices(segment, indices_ca, indices_c, indices_o, indices_n);
+    return CoordFrame::GetAlphaHelixContent(indices_ca,indices_c,indices_o,indices_n);
+  }
+
+  Real Eval2AngleDist(Real phi, Real phi0, Real psi, Real psi0, Real delta){
+    //Returns a score between 0 and 1 measuring the distance between
+    //a pair of angles and a pair of reference angles
+    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 CoordFrame::GetAlphaHelixContent(std::vector<unsigned long>& indices_ca, std::vector<unsigned long>& indices_c,
+                                         std::vector<unsigned long>& indices_o, std::vector<unsigned long>& indices_n){
+  //See CoordFrame::GetAlphaHelixContent(const mol::EntityView) above.
+  unsigned long n_atoms=indices_ca.size();
+  geom::Vec3 c_previous,n,ca,c,n_next;
+  Real phi,psi,phi_0=-1.2,psi_0=-0.785,delta=0.8,d_0=3.3;
+  unsigned long n_helical_res=0;
+  std::vector<Real> score,dist,score2,dist2;
+  score.reserve(n_atoms-2);
+  score2.reserve(n_atoms-2);
+  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");
+  }
+  if (n_atoms<=5){
+    throw std::runtime_error("At least five residues are needed to calulate an alpha helix similarity");
+  }
+  c=(*this)[indices_c[0]];
+  n_next=(*this)[indices_n[1]];
+  for (unsigned long i=1; i!=n_atoms-1; ++i){
+    c_previous=c;
+    n=n_next;
+    ca=(*this)[indices_ca[i]];
+    c=(*this)[indices_c[i]];
+    n_next=(*this)[indices_n[i+1]];
+    phi=geom::DihedralAngle(c_previous,n,ca,c);
+    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.);
+  for (unsigned long i=1; i!=n_atoms-3; ++i){
+    score2[i]=score[i-1]*score[i]*score[i+1];
+  }
+  if (n_atoms>=8){
+    for (unsigned long i=1; i!=n_atoms-1; ++i){
+      if (i<n_atoms-4){
+        dist.push_back(geom::Distance((*this)[indices_o[i]],(*this)[indices_n[i+4]]));
+        if (i>=5) {
+          dist2.push_back(std::min(dist[i-1],dist[i-5]));
+        }
+        else dist2.push_back(dist[i-1]);
+      }
+      else dist2.push_back(geom::Distance((*this)[indices_n[i]],(*this)[indices_o[i-4]]));
+    }
+    for (unsigned long i=0; i!=n_atoms-2; ++i){
+      if (dist2[i]<=d_0 || score2[i]>=0.3)n_helical_res+=1;
+    }
+  }
+  else {
+    for (unsigned long i=0; i!=n_atoms-2; ++i){
+      if (score2[i]>=0.3)n_helical_res+=1;
+    }
+  }
+  return Real(n_helical_res)/Real(n_atoms-2);
+  }
+ 
+
+
 }}//ns
 
diff --git a/modules/mol/base/src/coord_frame.hh b/modules/mol/base/src/coord_frame.hh
index 8b34cc52acb31086b8ee02d074fe0aac526e22f8..db9645dc688ca66db3111d56f158bd9ae0d77766 100644
--- a/modules/mol/base/src/coord_frame.hh
+++ b/modules/mol/base/src/coord_frame.hh
@@ -60,13 +60,21 @@ public:
   Real GetMinDistBetwCenterOfMassAndView(std::vector<unsigned long>& indices_cm, std::vector<Real>& masses_cm,
                                          std::vector<unsigned long>& indices_atoms);
   Real GetMinDistBetwCenterOfMassAndView(const mol::EntityView& view_cm, const mol::EntityView& view_atoms);
+  geom::Line3 GetODRLine(std::vector<unsigned long>& indices_ca);
+  geom::Line3 FitCylinder(std::vector<unsigned long>& indices_ca);
+  Real GetAlphaHelixContent(std::vector<unsigned long>& indices_ca, std::vector<unsigned long>& indices_c,
+                             std::vector<unsigned long>& indices_o, std::vector<unsigned long>& indices_n);
+  Real GetAlphaHelixContent(const mol::EntityView& segment);
 };
   
   void GetIndices(const EntityView& sele, std::vector<unsigned long>& indices);
   void GetMasses(const EntityView& sele, std::vector<Real>& masses);
   void GetIndicesAndMasses(const EntityView& sele, std::vector<unsigned long>& indices,std::vector<Real>& masses);
   void GetPositions(const EntityView& sele, std::vector<geom::Vec3>& ref_pos);
-  
+  void GetCaIndices(const EntityView& segment, std::vector<unsigned long>& indices_ca);
+  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);
+
 typedef boost::shared_ptr<CoordFrame> CoordFramePtr;
 typedef std::vector<CoordFramePtr> CoordFrameList;
 
diff --git a/modules/mol/base/src/impl/residue_impl.cc b/modules/mol/base/src/impl/residue_impl.cc
index d8ce7f6d3f97b6c0bfe9e452d0c2760d54bbd01c..28f0cc6f9047616848e8d0a334da946a6fdfea9f 100644
--- a/modules/mol/base/src/impl/residue_impl.cc
+++ b/modules/mol/base/src/impl/residue_impl.cc
@@ -43,7 +43,8 @@ ResidueImpl::ResidueImpl(const EntityImplPtr& ent,
   atom_list_(),
   sec_structure_(SecStructure::COIL),
   olc_('?'),
-  protein_(false), ligand_(false)
+  protein_(false), ligand_(false),
+  central_atom_()
 {
 }
 
@@ -163,6 +164,7 @@ EntityImplPtr ResidueImpl::GetEntity() const
 
 AtomImplPtr ResidueImpl::GetCentralAtom() const
 {
+  if(central_atom_) return central_atom_;
   if (chem_class_.IsNucleotideLinking()) {
     for (AtomImplList::const_iterator it=atom_list_.begin();
          it!=atom_list_.end();++it) {
@@ -178,6 +180,12 @@ AtomImplPtr ResidueImpl::GetCentralAtom() const
   return AtomImplPtr();
 }
 
+void ResidueImpl::SetCentralAtom(const AtomImplPtr& a)
+{
+  central_atom_=a;
+}
+
+
 char ResidueImpl::GetOneLetterCode() const
 {
   return olc_;
diff --git a/modules/mol/base/src/impl/residue_impl.hh b/modules/mol/base/src/impl/residue_impl.hh
index 560571f87d1ac8f9c492704a54d5b3dcfe6bee15..8b01d32d2f3d8873f8098805dbe62028334dc2ec 100644
--- a/modules/mol/base/src/impl/residue_impl.hh
+++ b/modules/mol/base/src/impl/residue_impl.hh
@@ -72,6 +72,13 @@ public:
   ChainImplPtr GetChain() const;
 
   AtomImplPtr GetCentralAtom() const;
+  /*!
+    explicitely set central atom
+
+    if this is set, it will override the heuristic encoded
+    in GetCentralAtom; pass an invalid ptr to deactivate again
+  */
+  void SetCentralAtom(const AtomImplPtr& a);
 
   geom::Vec3 GetCentralNormal() const;
 
@@ -209,6 +216,7 @@ private:
   void AddAltAtom(const String& group, const AtomImplPtr& atom,
                   const geom::Vec3& position);
   void RemoveAltPositionsForAtom(const AtomImplPtr& atom);
+
   String                     curr_group_;
   AtomEntryGroups            alt_groups_;
   EntityImplW                ent_;
@@ -221,8 +229,13 @@ private:
   ChemClass                  chem_class_;
   char                       olc_;
   // whether the residue is part of the protein.
+  // TODO: this should be fixed to be a enum'ed type aka
+  // RESIDUE_TYPE type_;
+  // where enum is one of protein, ligand, dna, lipid, etc
   bool                       protein_;
   bool                       ligand_;
+  AtomImplPtr                central_atom_;
+ 
 };
 
 }}} // ns
diff --git a/modules/mol/base/src/residue_base.cc b/modules/mol/base/src/residue_base.cc
index a1d321dee00bf9a43b1a92634d88897099831ba7..7d15ad5f6fff00b62a223b8f41417f25d0703d8d 100644
--- a/modules/mol/base/src/residue_base.cc
+++ b/modules/mol/base/src/residue_base.cc
@@ -44,6 +44,23 @@ const GenericPropContainerImpl* ResidueBase::GpImpl() const
   return Impl().get();
 }
 
+AtomHandle ResidueBase::GetCentralAtom() const 
+{
+  this->CheckValidity();
+  return AtomHandle(Impl()->GetCentralAtom());
+}
+
+void ResidueBase::SetCentralAtom(const AtomHandle& a)
+{
+  this->CheckValidity();
+  impl_->SetCentralAtom(a.Impl());
+}
+
+geom::Vec3 ResidueBase::GetCentralNormal() const 
+{
+  this->CheckValidity();
+  return impl_->GetCentralNormal();
+}
 
 const ResNum& ResidueBase::GetNumber() const {
   this->CheckValidity();
diff --git a/modules/mol/base/src/residue_base.hh b/modules/mol/base/src/residue_base.hh
index ea5a5f01081787d3fe6e177894f288cfb8699f99..c994b9a3098b48479300c811d55583cc213ad16c 100644
--- a/modules/mol/base/src/residue_base.hh
+++ b/modules/mol/base/src/residue_base.hh
@@ -19,6 +19,8 @@
 #ifndef OST_RESIDUE_BASE_HH
 #define OST_RESIDUE_BASE_HH
 
+#include <ost/geom/geom.hh>
+
 #include <ost/mol/module_config.hh>
 #include <ost/mol/residue_prop.hh>
 #include <ost/mol/impl/residue_impl_fw.hh>
@@ -90,6 +92,20 @@ public:
   ///         residue name and residue number
   String GetQualifiedName() const;
 
+  /// \brief  returns main atom, ie CA for amino acids
+  AtomHandle GetCentralAtom() const;
+
+  /*!
+    \brief set explicit central atom
+
+    overrides the heuristic of GetCentralAtom to explicitely
+    use the given one as the central atom; passing in an
+    invalid handle reverts back to the heurstic determination
+  */
+  void SetCentralAtom(const AtomHandle& a);
+
+  /// \return return specific normal of residue, usually CA-CB dir for AA
+  geom::Vec3 GetCentralNormal() const;
 
   /// \brief whether the residue can form peptide bonds
   bool IsPeptideLinking() const;
diff --git a/modules/mol/base/src/residue_handle.cc b/modules/mol/base/src/residue_handle.cc
index 809dbb8c64b9a1d604753e2feaa79174a8f71c96..d2ef00da17cd22fed12270d1dc783e9d8cc5cbe4 100644
--- a/modules/mol/base/src/residue_handle.cc
+++ b/modules/mol/base/src/residue_handle.cc
@@ -130,18 +130,6 @@ bool ResidueHandle::operator!=(const ResidueHandle& ref) const
   return Impl()!=ref.Impl();
 }
 
-AtomHandle ResidueHandle::GetCentralAtom() const 
-{
-  this->CheckValidity();
-  return AtomHandle(Impl()->GetCentralAtom());
-}
-
-geom::Vec3 ResidueHandle::GetCentralNormal() const 
-{
-  this->CheckValidity();
-  return Impl()->GetCentralNormal();
-}
-
 int ResidueHandle::GetIndex() const 
 {
   this->CheckValidity();
diff --git a/modules/mol/base/src/residue_handle.hh b/modules/mol/base/src/residue_handle.hh
index 54b9092a001e34a45aacdfffddf0ac33cc389665..5048a0804c960f535a7213b2a93c2e7324dac241 100644
--- a/modules/mol/base/src/residue_handle.hh
+++ b/modules/mol/base/src/residue_handle.hh
@@ -61,21 +61,15 @@ public:
     : ResidueBase(impl) {}
   EntityHandle GetEntity() const;
 
-  /// \brief  returns main atom, ie CA for amino acids
-  AtomHandle GetCentralAtom() const;
-
-  /// \return return specific normal of residue, usually CA-CB dir for AA
-  geom::Vec3 GetCentralNormal() const;
-
-  /// \brief Get entity's mass
+  /// \brief Get residue's mass
   double GetMass() const;
   
-  /// \brief Get entity's center of mass (mass weighted)
+  /// \brief Get residue's center of mass (mass weighted)
   geom::Vec3 GetCenterOfMass() const;
   
-  /// \brief Get entity's center of atoms (not mass weighted)
+  /// \brief Get residue's center of atoms (not mass weighted)
   ///
-  /// Returns the center of all the atoms in an entity. This is
+  /// Returns the center of all the atoms in this residue. This is
   /// similar to GetCenterOfMass(), but the atoms are not mass weighted
   geom::Vec3 GetCenterOfAtoms() const;
   
diff --git a/modules/mol/base/src/residue_view.hh b/modules/mol/base/src/residue_view.hh
index 8c95c81c1fe372151a69a17f213ff6c398827072..8efe0c97f8739a5e8c64a1d1f84f3db357e94835 100644
--- a/modules/mol/base/src/residue_view.hh
+++ b/modules/mol/base/src/residue_view.hh
@@ -155,22 +155,20 @@ public:
   /// \brief    get parent chain view.
   ChainView GetChain() const;
   
-  
-  /// \brief Get entity's mass
+  /// \brief Get residue's mass
   double GetMass() const;
   
-  /// \brief Get entity's center of mass (mass weighted)
+  /// \brief Get residue's center of mass (mass weighted)
   geom::Vec3 GetCenterOfMass() const;
   
-  /// \brief Get entity's center of atoms (not mass weighted)
+  /// \brief Get residue's center of atoms (not mass weighted)
   ///
-  /// Returns the center of all the atoms in an entity. This is
+  /// Returns the center of all the atoms in this residue. This is
   /// similar to GetCenterOfMass(), but the atoms are not mass weighted
   geom::Vec3 GetCenterOfAtoms() const;
   
-  /// \brief Get entity's axis-aligned bounding box
+  /// \brief Get residue's axis-aligned bounding box
   geom::AlignedCuboid GetBounds() const;
-  
 
   /// \brief return view based on a query object
   /// \sa Query
diff --git a/modules/mol/base/tests/test_numpy.py b/modules/mol/base/tests/test_numpy.py
index 14496c0c0ef2d3cb3632ebbb620890d4a9e126a0..217ed89dd7adb6380b6fea22719e49f310b2c2cb 100644
--- a/modules/mol/base/tests/test_numpy.py
+++ b/modules/mol/base/tests/test_numpy.py
@@ -1,17 +1,25 @@
 import unittest
-from ost import *
+if __name__== '__main__':
+  import sys
+  sys.path.insert(0,"../../../../stage/lib64/openstructure/")
+  sys.path.insert(0,"../../../../stage/lib/openstructure/")
+  
+import ost
 
-has_numpy=True
-try:
-  import numpy
-except ImportError:
+if ost.WITH_NUMPY:
+  has_numpy=True
+  try:
+    import numpy
+  except ImportError, e:
+    has_numpy=False
+else:
   has_numpy=False
 
 def v2v(v):
-  return geom.Vec3(float(v[0]),float(v[1]),float(v[2]))
+  return ost.geom.Vec3(float(v[0]),float(v[1]),float(v[2]))
 
 def dd(v1,v2):
-  return geom.Distance(v1,v2)<1e-8
+  return ost.geom.Distance(v1,v2)<1e-8
 
 class TestNumpy(unittest.TestCase):
   def setUp(self):
@@ -20,46 +28,46 @@ class TestNumpy(unittest.TestCase):
   def test_(self):
     if not has_numpy:
       return
-    entity=mol.CreateEntity()
+    entity=ost.mol.CreateEntity()
     ed=entity.EditXCS()
     ch=ed.InsertChain("X")
     re=ed.AppendResidue(ch,"ALA")
-    a0=ed.InsertAtom(re,"A",geom.Vec3(0,0,0))
+    a0=ed.InsertAtom(re,"A",ost.geom.Vec3(0,0,0))
     self.assertEqual(a0.GetIndex(),0)
-    a1=ed.InsertAtom(re,"B",geom.Vec3(1,0,0))
+    a1=ed.InsertAtom(re,"B",ost.geom.Vec3(1,0,0))
     self.assertEqual(a1.GetIndex(),1)
-    a2=ed.InsertAtom(re,"C",geom.Vec3(2,0,0))
+    a2=ed.InsertAtom(re,"C",ost.geom.Vec3(2,0,0))
     self.assertEqual(a2.GetIndex(),2)
-    a3=ed.InsertAtom(re,"D",geom.Vec3(3,0,0))
+    a3=ed.InsertAtom(re,"D",ost.geom.Vec3(3,0,0))
     self.assertEqual(a3.GetIndex(),3)
 
-    self.assertTrue(dd(a0.pos,geom.Vec3(0,0,0)))
-    self.assertTrue(dd(a1.pos,geom.Vec3(1,0,0)))
-    self.assertTrue(dd(a2.pos,geom.Vec3(2,0,0)))
-    self.assertTrue(dd(a3.pos,geom.Vec3(3,0,0)))
+    self.assertTrue(dd(a0.pos,ost.geom.Vec3(0,0,0)))
+    self.assertTrue(dd(a1.pos,ost.geom.Vec3(1,0,0)))
+    self.assertTrue(dd(a2.pos,ost.geom.Vec3(2,0,0)))
+    self.assertTrue(dd(a3.pos,ost.geom.Vec3(3,0,0)))
 
     ed.SetAtomTransformedPos(entity.GetAtomList(),
                              numpy.array([[0,1,0],[0,2,0],[0,3,0],[0,4,0]], dtype=numpy.float32))
 
-    self.assertTrue(dd(a0.pos,geom.Vec3(0,1,0)))
-    self.assertTrue(dd(a1.pos,geom.Vec3(0,2,0)))
-    self.assertTrue(dd(a2.pos,geom.Vec3(0,3,0)))
-    self.assertTrue(dd(a3.pos,geom.Vec3(0,4,0)))
+    self.assertTrue(dd(a0.pos,ost.geom.Vec3(0,1,0)))
+    self.assertTrue(dd(a1.pos,ost.geom.Vec3(0,2,0)))
+    self.assertTrue(dd(a2.pos,ost.geom.Vec3(0,3,0)))
+    self.assertTrue(dd(a3.pos,ost.geom.Vec3(0,4,0)))
 
     na=entity.positions
 
-    self.assertTrue(dd(v2v(na[0]),geom.Vec3(0,1,0)))
-    self.assertTrue(dd(v2v(na[1]),geom.Vec3(0,2,0)))
-    self.assertTrue(dd(v2v(na[2]),geom.Vec3(0,3,0)))
-    self.assertTrue(dd(v2v(na[3]),geom.Vec3(0,4,0)))
+    self.assertTrue(dd(v2v(na[0]),ost.geom.Vec3(0,1,0)))
+    self.assertTrue(dd(v2v(na[1]),ost.geom.Vec3(0,2,0)))
+    self.assertTrue(dd(v2v(na[2]),ost.geom.Vec3(0,3,0)))
+    self.assertTrue(dd(v2v(na[3]),ost.geom.Vec3(0,4,0)))
 
     ed.SetAtomTransformedPos([3,99,2],
                              numpy.array([[0,0,-3],[-1,-1,-1],[0,0,-2]], dtype=numpy.float32))
 
-    self.assertTrue(dd(a0.pos,geom.Vec3(0,1,0)))
-    self.assertTrue(dd(a1.pos,geom.Vec3(0,2,0)))
-    self.assertTrue(dd(a2.pos,geom.Vec3(0,0,-2)))
-    self.assertTrue(dd(a3.pos,geom.Vec3(0,0,-3)))
+    self.assertTrue(dd(a0.pos,ost.geom.Vec3(0,1,0)))
+    self.assertTrue(dd(a1.pos,ost.geom.Vec3(0,2,0)))
+    self.assertTrue(dd(a2.pos,ost.geom.Vec3(0,0,-2)))
+    self.assertTrue(dd(a3.pos,ost.geom.Vec3(0,0,-3)))
 
 if __name__== '__main__':
     unittest.main()
diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt
index 6a936d2822952a53e1237dc26403718a23c303a8..f71f153277224ae97a8e7155b15e653ec504123d 100644
--- a/scripts/CMakeLists.txt
+++ b/scripts/CMakeLists.txt
@@ -1,4 +1,4 @@
-set(SUBST_DICT BUILD_TYPE=${CMAKE_BUILD_TYPE} PYTHON_BINARY=${PYTHON_BINARY} LIBDIR=${LIB_DIR})
+set(SUBST_DICT BUILD_TYPE=${CMAKE_BUILD_TYPE} PYTHON_BINARY=${PYTHON_BINARY} LIBDIR=${LIB_DIR} LIBEXEC_PATH=${LIBEXEC_PATH})
 message("${BUILD_TYPE}")
 add_custom_target(ost_scripts ALL)
 
@@ -19,7 +19,7 @@ if(WIN32)
   script(NAME gipltng.bat INPUT gipltng.bat.in SUBSTITUTE ${SUBST_DICT})
 else()
   script(NAME ost_config INPUT ost_config.in SUBSTITUTE ${SUBST_DICT}
-         TARGET ost_scripts OUTPUT_DIR libexec/openstructure)
+         TARGET ost_scripts OUTPUT_DIR ${LIBEXEC_PATH})
   script(NAME ost INPUT ost.in SUBSTITUTE ${SUBST_DICT} 
          TARGET ost_scripts)
   if (ENABLE_GUI)
diff --git a/scripts/dng.in b/scripts/dng.in
index e78b6511fa811758e7d42babe69437d2f0e19fd2..41e31bd636c0193f83bb87671df25e0feed39733 100755
--- a/scripts/dng.in
+++ b/scripts/dng.in
@@ -26,6 +26,6 @@ else
   SCRIPT_NAME="$0"
 fi
 BIN_DIR=`dirname "$SCRIPT_NAME"`
-source $BIN_DIR/../libexec/openstructure/ost_config
+source $BIN_DIR/../@LIBEXEC_PATH@/ost_config
 
-$DNG_BINDIR/gosty $DNG_INITDIR/init.py ost $opts
+$BIN_DIR/../@LIBEXEC_PATH@/gosty $DNG_INITDIR/init.py dng $opts
diff --git a/scripts/ost.in b/scripts/ost.in
index 3cf716f00d7e026ec9bbd92e7aa29bd6fa34d578..2891d37c28597c2fbdee3dbb05b1bd7bf20aca5c 100755
--- a/scripts/ost.in
+++ b/scripts/ost.in
@@ -29,7 +29,7 @@ else
 fi
 BIN_DIR=`dirname "$SCRIPT_NAME"`
 
-source $BIN_DIR/../libexec/openstructure/ost_config
+source $BIN_DIR/../@LIBEXEC_PATH@/ost_config
 
 $pyexec $interactive "$DNG_ROOT/@LIBDIR@/openstructure/init_cl.py" $opts
 RC=$?
diff --git a/scripts/ost_config.in b/scripts/ost_config.in
index bfd79f436a092a15e1909c1e616fface963b1b5a..b7b8b7c3ef001947e5310375c787e43e5d936aa6 100644
--- a/scripts/ost_config.in
+++ b/scripts/ost_config.in
@@ -26,10 +26,10 @@ export DNG_BINDIR="$DNG_ROOT/bin"
 export DNG_LIBDIR="$DNG_ROOT/@LIBDIR@"
 export DNG_INITDIR="$DNG_LIBDIR/openstructure"
 
-#export PATH="$DNG_BINDIR:$PATH"
-#export DYLD_FRAMEWORK_PATH="$BIN_LIBDIR:${DYLD_FRAMEWORK_PATH}"
-#export DYLD_LIBRARY_PATH="$BIN_LIBDIR:${DYLD_LIBRARY_PATH}"
-#export LD_LIBRARY_PATH="$DNG_LIBDIR:$LD_LIBRARY_PATH"
+export PATH="$DNG_BINDIR:$PATH"
+export DYLD_FRAMEWORK_PATH="$BIN_LIBDIR:${DYLD_FRAMEWORK_PATH}"
+export DYLD_LIBRARY_PATH="$BIN_LIBDIR:${DYLD_LIBRARY_PATH}"
+export LD_LIBRARY_PATH="$DNG_LIBDIR:$LD_LIBRARY_PATH"
 # set QT_PLUGIN_PATH PYTHONHOME and PYTHONPATH for bundle (commented except in linux bundles)
 # set QT_PLUGIN_PATH and pythonpath for bundle (commented except in linux bundles)
 #export QT_PLUGIN_PATH="$BIN_DIR/plugins"