diff --git a/.gitignore b/.gitignore
index c098dd22237c9f9158350a5ad6d819e262ee92fa..156016aab9ca7cd1aabb380eb0ecd78ba2cda2c0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,6 +43,7 @@ components.cif
 compounds.chemlib
 /deployment/macos/openstructure.dmg
 /scripts/dng
+/modules/gui/src/module_config.hh
 *.vcproj
 /scripts/ost_config
 *.user
@@ -65,3 +66,6 @@ Debug
 /modules/io/tests/temp_img.tmp
 PYTEST-*.xml
 ost_*_tests_log.xml
+rules.ninja
+build.ninja
+modules/gui/src/dngr.qrc.depends
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 78fd252a379bf5cb9fd0dec1492a54672e1171c9..34244717a2e4676c37d1499e6c175e53dd3930f4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -195,6 +195,21 @@ if (ENABLE_INFO)
   find_package(Qt4 4.5.0 REQUIRED)
 endif()
 
+if (OPTIMIZE)
+  if (CXX_FLAGS)
+    set (CMAKE_CXX_FLAGS_RELEASE ${CXX_FLAGS})
+  endif()
+  if (C_FLAGS)
+    set (CMAKE_C_FLAGS_RELEASE ${C_FLAGS})
+  endif()
+else()
+  if (CXX_FLAGS)
+    set(CMAKE_CXX_FLAGS_DEBUG ${CXX_FLAGS})
+  endif()
+  if (C_FLAGS)
+    set(CMAKE_C_FLAGS_DEBUG ${C_FLAGS})
+  endif()
+endif()
 if (ENABLE_GFX)
   if(USE_MESA)
     find_package(Mesa REQUIRED)
@@ -312,6 +327,10 @@ set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES
 
 #ost_match_boost_python_version(${PYTHON_LIBRARIES})
 
+if (CMAKE_COMPILER_IS_GNUCXX)
+   set(HIDDEN_VIS_MSG 
+       "\n   Hidden object visibility  (-DHIDDEN_VISIBILITY) : ${_HIDDEN_VIS}")
+endif()
 message(STATUS 
         "OpenStructure will be built with the following options:\n"
         "   Install Prefix                       (-DPREFIX) : ${CMAKE_INSTALL_PREFIX}\n"
@@ -330,9 +349,6 @@ message(STATUS
         "   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}")
-if (CMAKE_COMPILER_IS_GNUCXX)
-   message(STATUS
-        "   Hidden object visibility  (-DHIDDEN_VISIBILITY) :        ${_HIDDEN_VIS}")
-endif()
+        "   Debian-style 'libexec' (-DDEBIAN_STYLE_LIBEXEC) : ${_DEBIAN_STYLE_LIBEXEC}"
+        ${HIDDEN_VIS_MSG})
 
diff --git a/modules/conop/doc/compoundlib.rst b/modules/conop/doc/compoundlib.rst
index 3e0e70d41bc5484965f7e2e0fed8e9870c6e7186..bf14500361e7aafcb2060df321e8592fd8054fff 100644
--- a/modules/conop/doc/compoundlib.rst
+++ b/modules/conop/doc/compoundlib.rst
@@ -6,7 +6,7 @@ The compound library
 Compound libraries contain information on chemical compounds, such as their 
 connectivity, chemical class and one-letter-code. The compound library has 
 several uses, but the most important one is to provide the connectivy 
-information for the :class:`rule-based builder <RuleBasedBuilder>`. 
+information for the :class:`rule-based processor <RuleBasedBuilder>`. 
 
 The compound definitions for standard PDB files are taken from the 
 components.cif dictionary provided by the PDB. The dictionary is updated with 
diff --git a/modules/conop/doc/connectivity.rst b/modules/conop/doc/connectivity.rst
index 98270b1aff31b7fa6d0f15f526e4dde56e8ef735..64a43bfd2e4060b6e8ce731242b5dbfcda484fd1 100644
--- a/modules/conop/doc/connectivity.rst
+++ b/modules/conop/doc/connectivity.rst
@@ -6,14 +6,16 @@ Connectivity
 
 Motivation
 --------------------------------------------------------------------------------
-Traditionally the connectivity between atoms has not been reliably described in
-a PDB file. Different programs adopted various ways of finding out if two atoms
-are connected. One way chosen is to rely on proper naming of the atoms. For 
-example, the backbone atoms of the standard amino acids are named as N, CA, C 
-and O and if atoms with these name appear in the same residue they are shown 
-connected. Another way is to apply additional heuristics to find out if a
-peptide bond between two consecutive residues is formed. Breaks in the backbone
-are indicated, e.g., by introducing a discontinuity in the numbering of the residue.
+
+
+The connectivity of atoms is notoriously difficult to come by for biological 
+macromolecules. PDB files, the de-factor standard exchange format for structural 
+information allows bonds to be specified in CONECT records. However, they are not
+mandatory. Many programs, especially the ones not requiring on connectivity of 
+atoms, do not write CONECT records. As a result, programs and structural biology 
+frameworks can't rely on connectivity information to be present. The connectivity
+information needs to be derived in the program itself.
+
 
 Loader heuristics are great if you are the one that implemented them but are 
 problematic if you are just the user of a software that has them. As time goes 
@@ -25,248 +27,110 @@ software wants to read in a PDB files as is without making any changes. A
 script in an automated pipeline, however, does want to either strictly reject 
 files that are incomplete or fill-in missing structural features. All these 
 aspects are implemented in the conop module, separated from the loading of the 
-PDB file, giving clients a fine grained control over the loading process.
+PDB file, giving clients a fine grained control over the loading process. The
+conop logic can thus be reused in code requiring the presence of 
 
-The conop module defines a :class:`Builder` interface, to run connectivity 
+The conop module defines a :class:`Processor` interface, to run connectivity 
 algorithms, that is to connect the atoms with bonds and perform basic clean up 
 of erroneous structures. The clients of the conop module can specify how the 
-Builder should treat unknown amino acids, missing atoms and chemically 
+Processor should treat unknown amino acids, missing atoms and chemically 
 infeasible bonds.
 
-The high-level interface
+Processors
 --------------------------------------------------------------------------------
 
+The exact behaviour for a processor is implementation-specific. So far, two
+classes implement the processor interface: A heuristic and a rule-based processor. 
+The processor mainly differ in the source of their connectivity information. The
+Heuristicprocessor uses a hard-coded heuristic connectivity table for the 20 
+standard amino acids as well as nucleotides.For other compounds such as ligands
+the HeuristicProcessor runs a distance-based connectivity algorithm that connects
+two atoms if they are closer than a  certain threshold. The RuleBasedProcessor
+uses a connectivity library containing  all molecular components present in the
+PDB files on PDB.org. The library can  easily be extended with custom 
+connectivity information, if required. If a :doc:`compound library <compoundlib>` is 
+present, the :class:`RuleBasedProcessor` is enabled by default, otherwise the 
+:class:`HeuristicProcessor` is used as a fallback.
 
-.. autofunction:: ConnectAll()
 
+The Processor base class
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+.. class:: Processor
 
-A call to :func:`ConnectAll` is sufficient to assign residue and atoms 
-properties as well as to connect atoms with bonds.
+  .. attribute:: connect
 
+    Whether to connect atoms by bonds. Enabled by default. Turn this off if you
+    would like to speed up the loading process and do not require connectivity
+    information to be present in your structures.
 
-.. code-block:: python
+    :type: :class:`bool`
 
-  # Suppose that BuildRawModel is a function that returns a protein structure
-  # with no atom properties assigned and no bonds formed.
-  ent=BuildRawModel(...)
-  print ent.bonds  # will return an empty list
-  # Call ConnectAll() to assign properties/connect atoms
-  conop.ConnectAll(ent)
-  print ent.bonds  # will print a list containing many bonds
+  .. attribute:: zero_occ_treatment
 
-For a more fine-grained control, consider using the :class:`Builder` interface.
+    Controls the behaviour of importing atoms with zero occupancy. By default, this 
+    is set to silent.
 
-The builder interface
---------------------------------------------------------------------------------
+    :type: :class:`str`
 
-The exact behaviour for a builder is implementation-specific. So far, two
-classes implement the Builder interface: A heuristic and a rule-based builder. The builders mainly differ in the source of their connectivity information. The
-HeuristicBuilder uses a hard-coded heuristic connectivity table for the 20
-standard amino acids as well as nucleotides.For other compounds such as ligands
-the HeuristicBuilder runs a distance-based connectivity algorithm that connects
-two atoms if they are closer than a  certain threshold. The RuleBasedBuilder
-uses a connectivity library containing  all molecular components present in the
-PDB files on PDB.org. The library can  easily be extended with custom 
-connectivity information, if required. If a :doc:`compound library <compoundlib>` is present, the :class:`RuleBasedBuilder` is enabled by default, otherwise the :class:`HeuristicBuilder` is used as a fallback.
+  .. attribute:: check_bond_feasibility
 
-The following 3 functions give you access to builders known to OpenStructure, 
-and allow you to set the default builder:
+    Whether an additional bond feasibility check is performed. Disabled by default.
+    Turn this on, if you would like to connect atoms by bonds only if they are 
+    within a reasonable distance.
 
+    :type: :class:`bool`
 
-.. autofunction:: GetBuilder()
+  .. attribute:: assign_torsions
 
-.. autofunction:: RegisterBuilder()
-  
-.. autofunction:: SetDefaultBuilder()
+    Whether backbone torsions should be added to the backbone. Disabled by default.
+    Set to true, to assign PHI, PSI and OMEGA torsions to the peptide residues.
 
-The Builder baseclass
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    :type: :class:`bool`
 
-.. class:: Builder
 
-  .. method:: CompleteAtoms(residue)
-  
-    add any missing atoms to the residue based on its key, with coordinates set
-    to zero.
-    
-    :param residue: must be a valid residue
-    :type  residue: mol.ResidueHandle
-    
-  .. method:: CheckResidueCompleteness(residue)
-  
-    verify that the given residue has all atoms it is supposed to have based on
-    its key.
-    
-    :param residue: must be a valid residue
-    :type  residue: mol.ResidueHandle
-    
-  .. method:: IsResidueComplete(residue)
-  
-    Check whether the residue has all atoms it is supposed to have. Hydrogen
-    atoms are not required for a residue to be complete.
-    
-    :param residue: must be a valid residue
-    :type  residue: mol.ResidueHandle
-    
-  .. method::   IdentifyResidue(residue)
-  
-    attempt to identify the residue based on its atoms, and return a suggestion
-    for the proper residue key.
-    
-    :param residue: must be a valid residue
-    :type  residue: mol.ResidueHandle
-    
-  .. method:: ConnectAtomsOfResidue(residue)
-  
-     Connects atoms of residue based on residue and atom name. This method does
-     not establish inter-residue bonds. To connect atoms that belong to 
-     different residues, use :meth:`ConnectResidueToPrev`, or
-     :meth:`ConnectResidueToNext`.
-     
-     :param residue: must be a valid residue
-     :type  residue: mol.ResidueHandle
-     
-  .. method:: ConnectResidueToPrev(residue, prev)
-  
-     Connect atoms of residue to previous. The order of the parameters is
-     important. In case of a polypeptide chain, the residues are thought to be
-     ordered from N- to C- terminus.
-     
-     :param residue: must be a valid residue
-     :type  residue: mol.ResidueHandle
-     :param prev: valid or invalid residue
-     :type  prev: mol.ResidueHandle
-     
-     
-  .. method:: DoesPeptideBondExist(n, c)
-  
-     Check if peptide bond should be formed between the `n` and `c` atom. This
-     method is called by ConnectResidueWithNext() after making sure that
-     both residues participating in the peptide bond are peptide linking
-     components.
-     
-     By default, :meth:`IsBondFeasible` is used to check whether the two atoms
-     form a peptide bond.
-     
-     :param n: backbone nitrogen atom (IUPAC name `N`). Must be valid.
-     :type  n: mol.AtomHandle
-     :param c: backbone C-atom (IUPAC name `C`). Must be valid.
-     :type  c: mol.AtomHandle
-     
-  .. method:: IsBondFeasible(atom_a, atom_b)
-  
-    Overloadable hook to check if bond between to atoms is feasible. The
-    default implementation uses a distance-based check to check if the
-    two atoms should be connected. The atoms are connected if they are in
-    the range of 0.8 to 1.2 times their van-der-WAALS radius.
-    
-    :param atom_a: a valid atom
-    :type  atom_b: mol.AtomHandle
-    :param atom_a: a valid atom
-    :type  atom_b: mol.AtomHandle
-    
-  .. method:: GuessAtomElement(atom_name, hetatm)
+  .. method:: Process(ent)
   
-    guess element of atom based on name and hetatm flag
-    
-    :param atom_name: IUPAC atom name, e.g. `CA`, `CB` or `N`.
-    :type  atom_name: string
-    :param    hetatm: Whether the atom is a hetatm or not
-    :type     hetatm: bool
-    
-  .. method:: AssignBackboneTorsionsToResidue(residue)
-  
-     For :meth:`peptide-linking residues <mol.ResidueHandle.IsPeptideLinking>`,
-     residues, assigns phi, psi and omega torsions to amino acid.
-     
-     :param residue: must be a valid residue
-     :type  residue: mol.ResidueHandle
-     
-  .. method:: GuessChemClass(residue)
-
-    Guesses the chemical class of the residue based on its atom and
-    connectivity.
-
-    So far, the method only guesses whether the residue is a peptide. A residue
-    is a peptide if all the backbone atoms N,CA,C,O are present, have the right
-    element and are in a suitable orientation to form bonds.
+    Processess the entity *ent* according to the current options.
 
 
-The RuleBasedBuilder class
+The RuleBasedProcessor class
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-.. class:: RuleBasedBuilder(compound_lib)
+.. class:: RuleBasedProcessor(compound_lib)
 
    :param compound_lib: The compound library
    :type compound_lib: :class:`CompoundLib`
    
-   The :class:`RuleBasedBuilder` implements the :class:`Builder` interface.
-   Refer to its documentation for a basic description of the methods.
-   
-   .. method:: CheckResidueCompleteness(residue)
-   
-      By using the description of the chemical compound, the completeness of
-      the residue is verified. The method distinguishes between required atoms
-      and atoms that are optional, like `OXT` that is only present, if not
-      peptide bond is formed. Whenever an unknown atom is encountered,
-      :meth:`OnUnknownAtom` is invoked. Subclasses of the
-      :class:`RuleBasedBuilder` may implement some additional logic to deal with
-      unknown atom. Likewise, whenever a required atom is missing,
-      :meth:`OnMissingAtom` is invoked. Hydrogen atoms are not considered as
-      required by default.
-      
-      :param residue: must be a valid residue
-      :type  residue: mol.ResidueHandle
-    
-   .. method:: IdentifyResidue(residue)
-    
-      Looks-up the residue in the database of chemical compounds and returns
-      the name of the residue or "UNK" if the residue has not been found in the
-      library.
-   
-      :param residue: must be a valid residue
-      :type  residue: mol.ResidueHandle
-   
-   
-   .. method:: OnUnknownAtom(atom)
-   
-      Invoked whenever an unkknown atom has been encountered during a residue
-      completeness check.
-      
-      The default implementation guesses the atom properties based on the name 
-      and returns false, meaning that it should be treated as an unknown atom.
-      
-      Custom implementations of this method may delete the atom, or modify it.
-      
-      :param atom: the unknown atom
-      :type  atom: mol.AtomHandle
-      
-   .. method:: OnMissingAtom(atom)
-    
-      Invoked whenever an atom is missing. It is up to the overloaded method
-      to deal with the missing atom, either by ignoring it or by inserting a
-      dummy atom.
-      
-      :param atom: The missing atom's name
-      :type  atom: string
-    
-   .. method:: GetUnknownAtoms(residue)
+   The :class:`RuleBasedProcessor` implements the :class:`Processor` interface.
+   Refer to its documentation for methods and accessors common to all processor.
+
    
-     Returns the unknown atoms of this residue, that is all atoms that 
-     are not part of the compound lib definition.
-     
-     :rtype: list of :class:`~ost.mol.AtomHandle` instances
+  .. attribute:: strict_hydrogens
+
+    Whether to use strict hydrogen naming rules outlined in the compound library.
+    Disabled by default.
+
+    :type: :class:`bool`
+
+  .. attribute:: unk_atom_treatment
+
+    Treatment upon encountering an unknown atom. Default: 'warn'.
+
+
+    :type: :class:`str`
+
+  .. attribute:: unk_res_treatment
+
+    Treatment upon encountering an unknown residue
+
+    :type: :class:`str`
+
+  .. attribute:: fix_elements
 
-Changing the default builder
----------------------------------------------------------------------------------
+    Whether the element of the atom should be changed to the atom defined in the 
+    compound library. Enabled by default.
 
-The default builder can be specified with :func:`SetDefaultBuilder`. Before being
-able to set a builder, it needs to be registered with :func:`RegisterBuilder`.
-By default, there is always a builder called "HEURISTIC" registered. If, for some
-reason your are currently using the :class:`RuleBasedBuilder` and you would like
-to switch to that builder, call
+    :type: :class:`bool`
 
-.. code-block:: python
 
-  conop.SetDefaultBuilder("HEURISTIC")
diff --git a/modules/conop/doc/conop.dox b/modules/conop/doc/conop.dox
index c59b5a5b1a78ec2a90b48bdda556c29dd8042e27..ee071624521fdfb5a308abcf38001fd3fca7226c 100644
--- a/modules/conop/doc/conop.dox
+++ b/modules/conop/doc/conop.dox
@@ -40,7 +40,7 @@ Builder should treat unknown amino acids, missing atoms and chemically
 infeasible bonds.
 
 So far, two classes implement the Builder interface: A heuristic and a 
-rule-based builder. The builders mainly differ in the source of their 
+rule-based processor. The builders mainly differ in the source of their 
 connectivity information. The HeuristicBuilder uses a hard-coded heuristic 
 connectivity table for the 20 standard amino acids as well as nucleotides. 
 For other compounds such as ligands the HeuristicBuilder runs a distance-based 
@@ -63,7 +63,7 @@ conop.Conopology.Instance().SetDefaultBuilder('rbb')
 
 All subsequent calls to io::LoadEntity will make use of the RuleBasedBuilder 
 instead of the heuristic builder. See \ref convert_mmcif "here" for more 
-information on how to create the neccessary files to use the rule-based builder.
+information on how to create the neccessary files to use the rule-based processor.
 
 \subsection connecting_atoms Connecting atoms
 
diff --git a/modules/conop/doc/conop.rst b/modules/conop/doc/conop.rst
index fb72db2645a92ea70f3db4f686c0f33a35c7e956..43cb41894f8c0ceab2392d04fe387025ac137da5 100644
--- a/modules/conop/doc/conop.rst
+++ b/modules/conop/doc/conop.rst
@@ -6,9 +6,10 @@
                connectivity information of molecules.
 
 
-The main task of the :mod:`~ost.conop` module is to connect atoms with bonds. 
-While the bond class is also part of the base module, the conop module deals 
-with setting up the correct bonds between atoms.
+
+The main task of the conop module is to interpret the topology and connectivity of 
+proteins, polynucleotides and small molecules, e.g. after importing a structure 
+from a PDB file. In addition, it provides an infrastructure for consistency checks. 
 
 
 In this module
@@ -20,4 +21,5 @@ In this module
  aminoacid
  connectivity
  compoundlib
- cleanup
\ No newline at end of file
+ cleanup
+ functions
diff --git a/modules/conop/doc/functions.rst b/modules/conop/doc/functions.rst
new file mode 100644
index 0000000000000000000000000000000000000000..ccd999f9b487fff58af3edc431eb29a6a4310d20
--- /dev/null
+++ b/modules/conop/doc/functions.rst
@@ -0,0 +1,34 @@
+Conop Functions
+=======================================================================
+
+
+.. function:: AssignBackboneTorsions(prev, res, next)
+              AssignBackboneTorsions(chain)
+              AssignBackboneTorsions(residues)
+   
+   Assigns the backbone torsions PHI, PSI and OMEGA. The backbone atoms 
+   are required to be connected for the torsions to be added. In addition, 
+   only residues for which :meth:`mol.ResidueHandle.IsPeptideLinking` returns 
+   true are considered.
+
+   The first signature assigns the torsions to *res*, assuming prev is 
+   the amino acid before, and *next* is the amino acid next to *res*.  
+   Both *next* and *prev* may be invalid residues.
+
+   The second and third signature assign the torsions to all peptidic 
+   residues of the chain/the residue list. The residues in the chain, 
+   the residue list are thought to run from N to C terminus.
+
+   :param prev: The amino acid before *res*
+   :type prev: :class:`~mol.ResidueHandle`
+   :type next: :class:`~mol.ResidueHandle`
+   :param next: The amino acid after *res*
+   :type res: :class:`~mol.ResidueHandle`
+   :type res: The central amino acid. Must be a valid handle
+
+.. function:: GetUnknownAtomsOfResidue(residue, compound, strict_hydrogens=False) 
+
+  Returns the list of atoms present in *residue* that are not part of the 
+  atom specifications in compound.
+
+  :param strict_hydrogens: When set to true, hydrogen atoms are checked as well.
diff --git a/modules/conop/pymod/CMakeLists.txt b/modules/conop/pymod/CMakeLists.txt
index c1bf89d0e29cda36f4b4bcb9b0b357449aaa8ad7..9c09906222fb97e1c935590ec22e81b536c94891 100644
--- a/modules/conop/pymod/CMakeLists.txt
+++ b/modules/conop/pymod/CMakeLists.txt
@@ -1,9 +1,13 @@
 set(OST_CONOP_PYMOD_SOURCES
   wrap_conop.cc
-  export_builder.cc
+  #  export_builder.cc
   export_compound.cc
+  export_processor.cc
+  export_heuristic.cc
   export_amino_acids.cc
   export_conop.cc
+  export_diag.cc
+  export_rule_based.cc
   export_non_standard.cc
   export_ring_finder.cc
 )
diff --git a/modules/conop/pymod/__init__.py b/modules/conop/pymod/__init__.py
index a24f5d2ec21b9333c7548cce372739a3c1753e6d..3b7856fe1634cd5d9ec3dfb7e22218618ae2655e 100644
--- a/modules/conop/pymod/__init__.py
+++ b/modules/conop/pymod/__init__.py
@@ -29,47 +29,16 @@ STANDARD_AMINOACIDS=(
  'HIS', 'PHE',
 )
 
-def ConnectAll(ent):
+def SetDefaultLib(compound_lib):
   '''
-  Uses the current default builder to connect the atoms of the entity, assign 
-  torsions, and fill in missing or correct erroneous information such as the 
-  chemical class of the residues and the atom's element.
-  
-  :param ent: A valid entity
-  :type ent: :class:`~ost.mol.EntityHandle`
+  Set the default compound library. The compound library is used by various
+  functions of the framework that requires knowledge of naming and 
+  connectivity of residues.
   '''
   conop_inst=Conopology.Instance()
-  conop_inst.ConnectAll(conop_inst.GetBuilder("DEFAULT"), ent, 0)
-  
-def GetBuilder(name='DEFAULT'):
-  '''
-  Get registered builder by name
-  
-  :param name: The name of the builder
-  
-  :returns: The builder or None, if the builder doesn't exist
-  '''
-  return Conopology.Instance().GetBuilder(name)  
+  conop_inst.SetDefaultLib(compound_lib)
 
-def RegisterBuilder(builder, name):
-  '''
-  Register builder to OpenStructure
-  
-  :param builder: A instance of :class:`Builder`
-  
-  :param name: The name of the builder
-  '''
+def GetDefaultLib():
   conop_inst=Conopology.Instance()
-  conop_inst.RegisterBuilder(builder, name)
-  
-def SetDefaultBuilder(builder_name):
-  '''
-  Set the builder with the given name as the default. You will have to register
-  a builder with :func:`RegisterBuilder` before you will be able to set it as
-  the default.
+  return conop_inst.GetDefaultLib()
 
-  :raises: :exc:`RuntimeError` when trying to set a builder as the default that
-    has not been registered yet.
-  '''
-  conop_inst=Conopology.Instance()
-  conop_inst.SetDefaultBuilder(builder_name)
diff --git a/modules/conop/pymod/cleanup.py b/modules/conop/pymod/cleanup.py
index 9ecf9c7ef12b8bb4fce889a5fb8062aab2364eda..1a51673d778e3e51237a3d576db8e67fca75279f 100644
--- a/modules/conop/pymod/cleanup.py
+++ b/modules/conop/pymod/cleanup.py
@@ -16,10 +16,9 @@ def Cleanup(entity, strip_water=True, canonicalize=True, remove_ligands=True):
   :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
+  lib = conop.GetDefaultLib()
+  if not lib:
+    raise RuntimeError("Cleanup requires a compound library.")
   clean_entity = entity.Copy()
   ed = clean_entity.EditXCS()
   #remove water residues
@@ -27,7 +26,7 @@ def Cleanup(entity, strip_water=True, canonicalize=True, remove_ligands=True):
     _StripWater(clean_entity, ed)
   #replace modified residues before removing ligands to avoid removing MSE and others
   if canonicalize:
-    _CanonicalizeResidues(clean_entity, ed, compound_lib)
+    _CanonicalizeResidues(clean_entity, ed, lib)
   #remove all hetatoms that are not water
   if remove_ligands:
     _RemoveLigands(clean_entity, ed)
diff --git a/modules/conop/pymod/export_builder.cc b/modules/conop/pymod/export_builder.cc
deleted file mode 100644
index 1897983f90b7c4065316633db738732c0ba4b93f..0000000000000000000000000000000000000000
--- a/modules/conop/pymod/export_builder.cc
+++ /dev/null
@@ -1,65 +0,0 @@
-//------------------------------------------------------------------------------
-// This file is part of the OpenStructure project <www.openstructure.org>
-//
-// Copyright (C) 2008-2011 by the OpenStructure authors
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License as published by the Free
-// Software Foundation; either version 3.0 of the License, or (at your option)
-// any later version.
-// This library is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with this library; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//------------------------------------------------------------------------------
-#include <boost/python.hpp>
-using namespace boost::python;
-#include <ost/conop/builder.hh>
-#include <ost/conop/heuristic_builder.hh>
-#include <ost/conop/rule_based_builder.hh>
-
-using namespace ost::conop;
-
-void export_Builder() {
-  
-  enum_<Dialect>("Dialect")
-    .value("PDB_DIALECT", PDB_DIALECT)
-    .value("CHARMM_DIALECT", CHARMM_DIALECT)
-    .export_values()
-  ;
-  //TODO Export virtual calls as Default* (see export_visitor.cc)
-  class_<Builder>("Builder", no_init)
-    .add_property("dialect", &Builder::GetDialect, &Builder::SetDialect)
-    .add_property("strict_hydrogens", &Builder::GetStrictHydrogenMode, 
-                  &Builder::SetStrictHydrogenMode)
-    .add_property("bond_feasibility_check", &Builder::GetBondFeasibilityCheck, 
-                  &Builder::SetBondFeasibilityCheck)
-    .def("GetDialect", &Builder::GetDialect)
-    .def("SetDialect", &Builder::SetDialect)
-    .def("CompleteAtoms", &Builder::CompleteAtoms)
-    .def("CheckResidueCompleteness", &Builder::CheckResidueCompleteness)
-    .def("IdentifyResidue", &Builder::IdentifyResidue)
-    .def("ConnectAtomsOfResidue", &Builder::ConnectAtomsOfResidue)
-    .def("ConnectResidueToNext", &Builder::ConnectResidueToNext)
-    .def("ConnectResidueToPrev", &Builder::ConnectResidueToPrev)
-    .def("AssignTorsions", &Builder::AssignTorsions)
-    .def("AssignTorsionsToResidue", &Builder::AssignTorsionsToResidue)
-    .def("FillAtomProps", &Builder::FillAtomProps)
-    .def("IsResidueComplete", &Builder::IsResidueComplete)
-    .def("SetBondFeasibilityFlag", &Builder::SetBondFeasibilityCheck)
-    .def("GetBondFeasibilityFlag", &Builder::GetBondFeasibilityCheck)    
-  ;
-
-  class_<HeuristicBuilder, bases<Builder> >("HeuristicBuilder", init<>())
-  ;
-  class_<RuleBasedBuilder, bases<Builder> >("RuleBasedBuilder", 
-                                            init<const CompoundLibPtr&>())
-     .add_property("compound_lib", &RuleBasedBuilder::GetCompoundLib)
-     .def("GetUnknownAtoms", &RuleBasedBuilder::GetUnknownAtoms)
- 
-  ;
-}
diff --git a/modules/conop/pymod/export_compound.cc b/modules/conop/pymod/export_compound.cc
index 6b8196e6768a608745c9c83608a7ddffc6ef50d3..33cbe0536ae7490f14edc9116ef2ea25adf4d430 100644
--- a/modules/conop/pymod/export_compound.cc
+++ b/modules/conop/pymod/export_compound.cc
@@ -127,7 +127,7 @@ void export_Compound() {
   class_<BondSpec>("BondSpec", no_init)
     .def_readonly("atom_one", &BondSpec::atom_one)
     .def_readonly("atom_two", &BondSpec::atom_two)    
-    .def_readonly("border", &BondSpec::order)
+    .def_readonly("order", &BondSpec::order)
 
   ;  
 
diff --git a/modules/conop/pymod/export_conop.cc b/modules/conop/pymod/export_conop.cc
index 309ce86b3572987be230a6badeb519a252c073db..39f006b45f96fc41a83403ab9363c7e5568cbd20 100644
--- a/modules/conop/pymod/export_conop.cc
+++ b/modules/conop/pymod/export_conop.cc
@@ -22,20 +22,15 @@
 using namespace boost::python;
 #include <ost/conop/conop.hh>
 #include <ost/mol/mol.hh>
-#include <ost/conop/builder.hh>
 
 using namespace ost::conop;
 
 void export_Conop() {
   class_<Conopology, boost::noncopyable>("Conopology", no_init)
     .def("Instance", &Conopology::Instance, return_value_policy<reference_existing_object>()).staticmethod("Instance")
-    .def("ConnectAll", &Conopology::ConnectAll)
-    .def("GetBuilder", &Conopology::GetBuilder)
-    .def("ConnectAll", &Conopology::ConnectAll)
-    .def("RegisterBuilder", &Conopology::RegisterBuilder)
-    .def("SetDefaultBuilder", &Conopology::SetDefaultBuilder)
+    .def("SetDefaultLib", &Conopology::SetDefaultLib)
+    .def("GetDefaultLib", &Conopology::GetDefaultLib)
     ;
-    register_ptr_to_python<BuilderP>();
 
 
 }
diff --git a/modules/conop/pymod/export_diag.cc b/modules/conop/pymod/export_diag.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6155d63c71854e76517aa7a1732feb30ce352a72
--- /dev/null
+++ b/modules/conop/pymod/export_diag.cc
@@ -0,0 +1,44 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+//
+#include <boost/python.hpp>
+#include <ost/conop/diag.hh>
+using namespace ost;
+
+using namespace boost::python;
+using namespace ost::conop;
+
+
+void export_diag() {
+
+  enum_<DiagType>("DiagType")
+    .value("DIAG_UNK_ATOM", DIAG_UNK_ATOM)
+    .value("DIAG_UNK_RESIDUE", DIAG_UNK_RESIDUE)
+    .value("(DIAG_MISSING_ATOM", DIAG_MISSING_ATOM)
+    .value("DIAG_NONSTD_RESIDUE", DIAG_NONSTD_RESIDUE)
+    .export_values()
+  ;
+
+  class_<Diag>("Diag", init<DiagType,const char*>())
+    .def("__str__(self)__", &Diag::Format)
+  ;
+  class_<Diagnostics, DiagnosticsPtr>("Diagnostics")
+  ;
+}
+
diff --git a/modules/conop/pymod/export_heuristic.cc b/modules/conop/pymod/export_heuristic.cc
new file mode 100644
index 0000000000000000000000000000000000000000..f25ca9814bf0e7589d58fa2db35c261acafee8cc
--- /dev/null
+++ b/modules/conop/pymod/export_heuristic.cc
@@ -0,0 +1,40 @@
+
+//------------------------------------------------------------------------------
+// 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/conop/heuristic.hh>
+
+using namespace ost::conop;
+
+void export_heuristic() {
+  
+  class_<HeuristicProcessor, HeuristicProcessorPtr, 
+         boost::noncopyable, bases<Processor> >("HeuristicProcessor", 
+         init<>())
+    .def(init<bool,bool,bool,bool,ConopAction>(
+         (arg("check_bond_feasibility")=false,
+         arg("assign_torsions")=false,
+         arg("connect")=true,
+         arg("peptide_bonds")=true,
+         arg("zero_occ_treatment")=CONOP_WARN)))
+  ;
+}
+
diff --git a/modules/conop/pymod/export_processor.cc b/modules/conop/pymod/export_processor.cc
new file mode 100644
index 0000000000000000000000000000000000000000..27317133e9eee11d724045b77d31ba5a1296e607
--- /dev/null
+++ b/modules/conop/pymod/export_processor.cc
@@ -0,0 +1,89 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+//
+#include <boost/python.hpp>
+#include <ost/conop/processor.hh>
+using namespace ost;
+
+using namespace ost::conop;
+using namespace boost::python;
+
+struct PyProcessor : public Processor {};
+struct WrappedProcessor : public PyProcessor, public wrapper<WrappedProcessor> {
+  WrappedProcessor(PyObject* self): self_(self)
+  { }
+  virtual void DoProcess(DiagnosticsPtr diag, mol::EntityHandle ent) const
+  {
+    call_method<void>(self_, "DoProcess", diag, ent);
+  }
+  DiagnosticsPtr DoProcessDefault(DiagnosticsPtr diag, 
+                                  mol::EntityHandle ent) const {
+    return DiagnosticsPtr();
+  }
+  ProcessorPtr Copy() const { 
+    return call_method<ProcessorPtr>(self_, "Copy"); 
+  }
+  virtual String ToString() const {
+    return call_method<String>(self_, "ToString");
+  }
+  String ToStringDefault() const { return ""; }
+  ProcessorPtr CopyDefault() const { return ProcessorPtr(); }
+  
+  PyObject* self_;
+};
+
+
+void export_processor() {
+  
+  enum_<Dialect>("Dialect")
+    .value("PDB_DIALECT", PDB_DIALECT)
+    .value("CHARMM_DIALECT", CHARMM_DIALECT)
+    .export_values()
+  ;
+  enum_<ConopAction>("ConopAction")
+    .value("CONOP_WARN", CONOP_WARN)
+    .value("CONOP_SILENT", CONOP_SILENT)
+    .value("CONOP_REMOVE", CONOP_REMOVE)
+    .value("CONOP_REMOVE_ATOM", CONOP_REMOVE_ATOM)
+    .value("CONOP_REMOVE_RESIDUE", CONOP_REMOVE_RESIDUE)
+    .value("CONOP_FATAL", CONOP_FATAL)
+    .export_values()
+  ;
+  class_<Processor, ProcessorPtr, boost::noncopyable>("_Processor", no_init)
+    .def("Copy", &Processor::Copy)
+    .add_property("check_bond_feasibility", 
+                  &Processor::GetCheckBondFeasibility,
+                  &Processor::SetCheckBondFeasibility)
+    .add_property("connect", &Processor::GetConnect,
+                 &Processor::SetConnect)
+    .add_property("assign_torsions", &Processor::GetAssignTorsions,
+                 &Processor::SetAssignTorsions)
+    .def("Process", &Processor::Process, 
+         (arg("ent"), arg("log_diags")=true))
+  ;
+  class_<PyProcessor, boost::noncopyable, 
+         boost::shared_ptr<WrappedProcessor>, 
+         bases<Processor> >("Processor")
+    .def("Copy", &WrappedProcessor::CopyDefault)
+    .def("DoProcess", &WrappedProcessor::DoProcessDefault)
+    .def("ToString", &WrappedProcessor::ToStringDefault)
+  ;
+  def("IsBondFeasible", &IsBondFeasible);
+}
+
diff --git a/modules/conop/pymod/export_rule_based.cc b/modules/conop/pymod/export_rule_based.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6fef009a0bd22913a8c850246e71176ff529a295
--- /dev/null
+++ b/modules/conop/pymod/export_rule_based.cc
@@ -0,0 +1,50 @@
+//------------------------------------------------------------------------------
+// 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/conop/rule_based.hh>
+
+using namespace ost::conop;
+
+void export_rule_based() {
+  
+  class_<RuleBasedProcessor, RuleBasedProcessorPtr, 
+         boost::noncopyable, bases<Processor> >("RuleBasedProcessor", 
+         init<CompoundLibPtr>())
+    .def(init<CompoundLibPtr,bool,bool,ConopAction,ConopAction,bool,bool,bool,bool,ConopAction>(
+         (arg("lib"), arg("fix_elements")=true, arg("strict_hydrogens")=false,
+         arg("unknown_res_treatment")=CONOP_WARN,
+         arg("unknown_atom_treatment")=CONOP_WARN,
+         arg("check_bond_feasibility")=false,
+         arg("assign_torsions")=false,
+         arg("connect")=true,
+         arg("peptide_bonds")=true,
+         arg("zero_occ_treatment")=CONOP_WARN)))
+    .add_property("fix_element", &RuleBasedProcessor::GetFixElement,
+                 &RuleBasedProcessor::SetFixElement)
+    .add_property("unk_res_treatment", &RuleBasedProcessor::GetUnkResidueTreatment,
+                 &RuleBasedProcessor::SetUnkResidueTreatment)
+    .add_property("unk_atom_treatment", &RuleBasedProcessor::GetUnkAtomTreatment,
+                 &RuleBasedProcessor::SetUnkAtomTreatment)
+    .add_property("strict_hydrogens", &RuleBasedProcessor::GetStrictHydrogens,
+                 &RuleBasedProcessor::SetStrictHydrogens)
+  ;
+}
+
diff --git a/modules/conop/pymod/wrap_conop.cc b/modules/conop/pymod/wrap_conop.cc
index 6573bf41a7e6c8fcb471cbf25a79be77b1b03dfa..119c86c325f3ce6fc48cf88298838f441cb04a36 100644
--- a/modules/conop/pymod/wrap_conop.cc
+++ b/modules/conop/pymod/wrap_conop.cc
@@ -19,20 +19,28 @@
 #include <boost/python.hpp>
 using namespace boost::python;
 
-void export_Builder();
+//void export_Builder();
 void export_Compound();
 void export_Sanitizer();
 void export_Conop();
 void export_RingFinder();
 void export_AminoAcids();
 void export_NonStandard();
+void export_processor();
+void export_rule_based();
+void export_heuristic();
+void export_diag();
 
 BOOST_PYTHON_MODULE(_ost_conop)
 {
-  export_Builder();
+ // export_Builder();
   export_Conop();
+  export_processor();
+  export_rule_based();
+  export_heuristic();
   export_Compound();
   export_RingFinder();
   export_AminoAcids();
   export_NonStandard();
+  export_diag();
 }
diff --git a/modules/conop/src/CMakeLists.txt b/modules/conop/src/CMakeLists.txt
index 1ae86c86f85c83aad9559a5811b6e99072309510..3709e846aa244c06bc2fbca34e8e848fe95d8d22 100644
--- a/modules/conop/src/CMakeLists.txt
+++ b/modules/conop/src/CMakeLists.txt
@@ -1,30 +1,33 @@
 set(OST_CONOP_HEADERS
-builder.hh
-builder_fw.hh
 conop.hh
-heuristic_builder.hh
+processor.hh
 amino_acids.hh
 diag.hh
 model_check.hh
+heuristic.hh
 compound.hh
 compound_lib.hh
 module_config.hh
+rule_based.hh
 nonstandard.hh
-rule_based_builder.hh
+minimal_compound_lib.hh
+compound_lib_base.hh
 ring_finder.hh
 )
 
 set(OST_CONOP_SOURCES
-builder.cc
+processor.cc
 amino_acids.cc
 conop.cc
+minimal_compound_lib.cc
+compound_lib_base.cc
+heuristic.cc
 diag.cc
+rule_based.cc
 model_check.cc
-heuristic_builder.cc
 compound.cc
 compound_lib.cc
 nonstandard.cc
-rule_based_builder.cc
 ring_finder.cc
 )
 
diff --git a/modules/conop/src/builder.cc b/modules/conop/src/builder.cc
deleted file mode 100644
index 0a24cf56fa398f19fb61e6a37d181e2fbd5ebb95..0000000000000000000000000000000000000000
--- a/modules/conop/src/builder.cc
+++ /dev/null
@@ -1,246 +0,0 @@
-//------------------------------------------------------------------------------
-// This file is part of the OpenStructure project <www.openstructure.org>
-//
-// Copyright (C) 2008-2011 by the OpenStructure authors
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License as published by the Free
-// Software Foundation; either version 3.0 of the License, or (at your option)
-// any later version.
-// This library is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with this library; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//------------------------------------------------------------------------------
-#include "builder.hh"
-
-/*
-   Author: Marco Biasini
- */
-
-namespace ost { namespace conop {
-
-Builder::~Builder() {}
-
-void Builder::CompleteAtoms(mol::ResidueHandle rh) {}
-
-void Builder::CheckResidueCompleteness(const mol::ResidueHandle& rh) {}
-
-mol::ResidueKey Builder::IdentifyResidue(const mol::ResidueHandle& rh) {
-  return mol::ResidueKey();
-}
-void Builder::FillResidueProps(mol::ResidueHandle residue){};
-void Builder::ConnectAtomsOfResidue(mol::ResidueHandle rh) {}
-
-void Builder::ConnectResidueToPrev(mol::ResidueHandle rh, 
-                                   mol::ResidueHandle p) {
-  this->ConnectResidueToNext(p, rh);
-}
-
-bool Builder::IsResidueComplete(const mol::ResidueHandle& rh)
-{
-  return true;
-}
-
-void Builder::ConnectResidueToNext(mol::ResidueHandle rh, 
-                                   mol::ResidueHandle n) {}
-
-void Builder::AssignTorsions(mol::ChainHandle ch) {}
-void Builder::AssignTorsionsToResidue(mol::ResidueHandle rh) {}
-
-void Builder::FillAtomProps(mol::AtomHandle atom) {}
-
-bool Builder::DoesPeptideBondExist(const mol::AtomHandle& n, 
-                                   const mol::AtomHandle& c)
-{
-  return this->IsBondFeasible(n, c);
-}
-
-bool Builder::IsBondFeasible(const mol::AtomHandle& atom_a,
-                             const mol::AtomHandle& atom_b)
-{
-  Real radii=0.0;
-  if (atom_a.GetRadius()>0.0) {
-    radii=atom_a.GetRadius();
-  } else {
-    return false;
-  }
-  if (atom_b.GetRadius()>0.0) {
-    radii+=atom_b.GetRadius();
-  } else {
-    return false;
-  } 
-  Real len=geom::Length2(atom_a.GetPos()-atom_b.GetPos());
-  Real lower_bound=radii*radii*0.0625;
-  Real upper_bound=lower_bound*6.0;
-  return (len<=upper_bound && len>=lower_bound);
-}
-
-String Builder::GuessAtomElement(const String& aname, bool hetatm)
-{
-  static String l1[] = {
-    "H","C","N","O","P","S","K"
-  };
-  static int l1c=7;
-  static String l2[] = {
-    "NA","MG","AL","SI","CL",
-    "CA","CR","MN","FE","CO","NI","CU","ZN","AS","SE","BR","MO"
-  };
-  static int l2c=17;
-  static String l3[] = {
-    "B","F","V"
-  };
-  static int l3c=3;
-  static String l4[] = {
-    "HE","LI","BE","AR","SC","TI","GA","GE","KR"
-  };
-  static int l4c=9;
-
-  String ele=aname.substr(0,2);
-  // hydrogen hack
-  if(ele[0]=='H') {
-    return "H";
-  }
-  if (hetatm==false) {
-    if (ele=="CA" || ele=="CB") {
-      return "C";
-    }
-  }
-
-  // two characters
-  if(aname.size()==2) {
-    for(int i=0;i<l2c;i++) {
-      if(ele==l2[i]) return ele;
-    }
-    // check second character for match
-    for(int i=0;i<l1c;i++) {
-      if(ele[1]==l1[i][0]) {
-        return l1[i];
-      }
-    }
-    // still no match, repeat with less likely tables
-    for(int i=0;i<l4c;i++) {
-      if(ele==l4[i]) return ele;
-    }
-    // check second character for match
-    for(int i=0;i<l3c;i++) {
-      if(ele[1]==l3[i][0]) {
-        return l3[i];
-      }
-    }
-    // check second character for match
-    for(int i=0;i<l1c;i++) {
-      if(ele[0]==l1[i][0]) {
-        return l1[i];
-      }
-    }
-  } else {
-    for(int i=0;i<l1c;i++) {
-      if(ele==l1[i]) return ele;
-    }
-    for(int i=0;i<l3c;i++) {
-      if(ele==l3[i]) return ele;
-    }
-  }
-  size_t i=0;
-  while (i<aname.size() && isdigit(aname[i])) {
-    ++i;
-  }
-  return i<aname.size() ? String(1, aname[i]) : "";
-}
-
-bool Builder::AreResiduesConsecutive(const mol::ResidueHandle& r1, 
-                                     const mol::ResidueHandle& r2)
-{
-  if (!r1 || !r2) return false; // protect against invalid handles
-  if(r1.GetChain() != r2.GetChain()) return false;
-  return r2.GetNumber().GetNum()==r1.GetNumber().GetNum()+1 ||
-         r2.GetNumber().GetInsCode()==r1.GetNumber().NextInsertionCode().GetInsCode();
-}
-
-void Builder::GuessChemClass(mol::ResidueHandle res)
-{
-  // try peptide
-  res.SetChemClass(mol::ChemClass());
-  mol::AtomHandle ca=res.FindAtom("CA");
-  if (!ca.IsValid() || ca.GetElement()!="C") return;
-  mol::AtomHandle n=res.FindAtom("N");
-  if (!n.IsValid() || n.GetElement()!="N") return;
-  mol::AtomHandle c=res.FindAtom("C");
-  if (!c.IsValid() || c.GetElement()!="C") return;
-  mol::AtomHandle o=res.FindAtom("O");
-  if (!o.IsValid() || o.GetElement()!="O") return;
-  if (this->IsBondFeasible(n, ca) && this->IsBondFeasible(ca, c) &&
-      this->IsBondFeasible(c, o)) {
-    res.SetChemClass(mol::ChemClass(mol::ChemClass::PEPTIDE_LINKING));
-  }
-}
-
-
-void Builder::AssignBackBoneTorsionsToResidue(mol::ResidueHandle res)
-{
-
-  mol::ResidueHandle prev=res.GetPrev();
-  mol::ResidueHandle next=res.GetNext();
-  mol::XCSEditor e=res.GetEntity().EditXCS(mol::BUFFERED_EDIT);
-  //psi
-  if (next.IsValid() && next.IsPeptideLinking()){
-    mol::AtomHandle ca_this=res.FindAtom("CA");
-    mol::AtomHandle n_this=res.FindAtom("N");
-    mol::AtomHandle c_this=res.FindAtom("C");
-    mol::AtomHandle n_next=next.FindAtom("N");
-    if ((ca_this && n_this && c_this && n_next &&  BondExists(c_this, n_next))
-        && !res.GetPsiTorsion()) {
-      e.AddTorsion("PSI", n_this, ca_this, c_this, n_next);
-    }
-  };
-  //phi
-  if (prev.IsValid() && prev.IsPeptideLinking()) {
-    mol::AtomHandle c_prev=prev.FindAtom("C");
-    mol::AtomHandle n_this=res.FindAtom("N");
-    mol::AtomHandle ca_this=res.FindAtom("CA");
-    mol::AtomHandle c_this=res.FindAtom("C");
-    if ((c_prev && n_this && ca_this && c_this && BondExists(c_prev, n_this))
-        && !res.GetPhiTorsion()) {
-      e.AddTorsion("PHI", c_prev, n_this, ca_this, c_this);
-    }
-  }
-  //omega
-  if (prev.IsValid() && prev.IsPeptideLinking()) {
-    mol::AtomHandle ca_prev=prev.FindAtom("CA");
-    mol::AtomHandle c_prev=prev.FindAtom("C");
-    mol::AtomHandle n=res.FindAtom("N");
-    mol::AtomHandle ca=res.FindAtom("CA");
-    if ((ca_prev && c_prev && n && ca && BondExists(c_prev, n))
-        && !res.GetOmegaTorsion()) {
-      e.AddTorsion("OMEGA",ca_prev , c_prev, n, ca);
-    }
-  }
-}
-
-
-
-void Builder::DistanceBasedConnect(mol::AtomHandle atom)
-{
-  mol::EntityHandle ent=atom.GetEntity();
-  mol::XCSEditor editor=ent.EditXCS(mol::BUFFERED_EDIT);
-  mol::AtomHandleList alist = ent.FindWithin(atom.GetPos(),4.0);
-  mol::ResidueHandle res_a=atom.GetResidue();
-  for (mol::AtomHandleList::const_iterator it=alist.begin(),
-       e=alist.end();it!=e;++it) {
-    if (*it!=atom) {
-      if (this->IsBondFeasible(atom, *it)) {
-        if (Builder::AreResiduesConsecutive(res_a, it->GetResidue()) || 
-            it->GetResidue()==res_a) {                      
-            editor.Connect(*it, atom);
-        }
-      }
-    }
-  }
-}
-
-}} // ns
diff --git a/modules/conop/src/builder.hh b/modules/conop/src/builder.hh
deleted file mode 100644
index 5cf1f63026a95df93569be1698455451997bbd92..0000000000000000000000000000000000000000
--- a/modules/conop/src/builder.hh
+++ /dev/null
@@ -1,162 +0,0 @@
-//------------------------------------------------------------------------------
-// This file is part of the OpenStructure project <www.openstructure.org>
-//
-// Copyright (C) 2008-2011 by the OpenStructure authors
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License as published by the Free
-// Software Foundation; either version 3.0 of the License, or (at your option)
-// any later version.
-// This library is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with this library; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//------------------------------------------------------------------------------
-#ifndef OST_CONOP_BUILDER_HH
-#define OST_CONOP_BUILDER_HH
-
-/*
-   Author: Marco Biasini
- */
-#include <ost/mol/mol.hh>
-
-#include <ost/conop/module_config.hh>
-#include <ost/conop/builder_fw.hh>
-
-namespace ost { namespace conop {
-
-typedef enum {
-  PDB_DIALECT,
-  CHARMM_DIALECT
-} Dialect;
-/// \brief  abstract builder interface
-/// 
-/// A builder serves several purposes: \li knows how to connect atoms of
-/// residues based on their name \li is able to identify as residue based on 
-/// its name \li knows whether a residue has all required atoms \li assigns
-/// named torsions to residues \li knows when to connect two consecutive
-/// residues.
-/// 
-/// The exact behaviour for a builder is implementation-specific. While some
-/// builders implement sophisticated checks to identity residues, other builders
-/// may only perform a name lookup. For two specific implementations of
-/// builders, HeuristicBuilder and RuleBasedBuilder.
-/// 
-/// Custom builders can be registered with Conopology::RegisterBuilder(). The
-/// default builder is set with Conopology::SetDefaultBuilder(). Since all
-/// entity loaders make use of the default builder to infer connectivity of the
-/// atoms, changing the default builder can largely affect the loading
-///  behaviour.
-class DLLEXPORT_OST_CONOP Builder {
-public:
-  
-  Builder(): dialect_(PDB_DIALECT), strict_(false), bond_feasibility_check_(false) { }
-  virtual ~Builder();
-  
-  ///  \brief add any missing atoms to the residue based on its key,
-  ///      with coordinates set to zero
-  virtual void CompleteAtoms(mol::ResidueHandle rh);
-
-  virtual void SetDialect(Dialect dialect) { dialect_=dialect; }
-  
-  virtual void SetStrictHydrogenMode(bool strict) { strict_=strict; }
-  bool GetStrictHydrogenMode() const { return strict_; }
-  
-  Dialect GetDialect() const { return dialect_; }
-  /// \brief verify that the given residue has all atoms it
-  ///     is supposed to have based on its key
-  virtual void CheckResidueCompleteness(const mol::ResidueHandle& rh);
-
-  /// \brief Check whether the residue has all atoms it is supposed to have
-  /// \todo Add hydrogen flag
-  virtual bool IsResidueComplete(const mol::ResidueHandle& rh);
-  
-  /// \brief attempt to identify the residue based on its atoms, and return a 
-  ///    suggestion for the proper residue key
-  virtual mol::ResidueKey IdentifyResidue(const mol::ResidueHandle& rh);
-
-  /// \brief Assign (correct) residue properties
-  /// 
-  /// Assign chemical class of the residue and one letter code.
-  virtual void FillResidueProps(mol::ResidueHandle residue);
-
-  virtual void FillAtomProps(mol::AtomHandle atom);
-  /// \brief connect atoms of one residue
-  /// 
-  /// Connects atoms of residue based on residue and atom name. This method does
-  /// not establish inter-residue bonds. To connect atoms that belong to 
-  /// different residues, use ConnectResidueToPrev(), or ConnectResidueToNext().
-  virtual void ConnectAtomsOfResidue(mol::ResidueHandle rh);
-  /// \brief connect atoms of residue to previous
-  /// 
-  /// The order of the parameters is important. In case of a polypeptide chain,
-  /// the residues are thought to be ordered from N- to C- terminus.
-  /// 
-  /// \sa ConnectResidueToNext
-  virtual void ConnectResidueToPrev(mol::ResidueHandle rh,
-                                    mol::ResidueHandle prev);
-  /// \sa ConnectResidueToPrev                                    
-  virtual void ConnectResidueToNext(mol::ResidueHandle rh, 
-                                    mol::ResidueHandle next);
-
-  /// \brief assign named torsions to a complete chain
-  virtual void AssignTorsions(mol::ChainHandle ch);
-  
-  /// \brief assign named torsions to single residue
-  virtual void AssignTorsionsToResidue(mol::ResidueHandle residue);
-  
-  /// \brief assign Backbone torsions to single residue  
-  void AssignBackBoneTorsionsToResidue(mol::ResidueHandle res);
-  
-  /// \brief  Check if peptide bond is formed between the two atoms.
-  /// 
-  /// This method is called by ConnectResidueWithNext() after making sure that
-  /// both residues participating in the peptide bond are peptide linking
-  /// components.
-  /// 
-  /// By default, IsBondFeasible() is used to check whether the two atoms form
-  /// a peptide bond.
-  virtual bool DoesPeptideBondExist(const mol::AtomHandle& n, 
-                                    const mol::AtomHandle& c);
-  
-  /// \brief Overloadable hook to check if bond between to atoms is feasible
-  /// 
-  /// The default implementation uses a distance-based check to check if the
-  /// two atoms should be connected. The atoms are connected if they are in
-  /// the range of 0.8 to 1.2 times their van-der-WAALS radius.
-  virtual bool IsBondFeasible(const mol::AtomHandle& atom_a,
-                              const mol::AtomHandle& atom_b);  
-
-  /// \brief guess element of atom based on name and hetatm flag
-  static String GuessAtomElement(const String& atom_name, bool hetatm);
-   
-  /// \brief whether the r1 and r2 have consecutive residue numbers
-  static bool AreResiduesConsecutive(const mol::ResidueHandle& r1, 
-                                     const mol::ResidueHandle& r2);
-  /// \brief guess and assign chemical class of residue based on atoms and
-  ///     connectivity
-  void GuessChemClass(mol::ResidueHandle res);
-  /// |brief Connect \p atom with all atoms for whith IsBondFeasible() and 
-  ///    AreResiduesConsecutive() returns true
-  void DistanceBasedConnect(mol::AtomHandle atom);
-   
-  /// \brief Set bond feasibility check flag
-  void SetBondFeasibilityCheck(bool b_feas_flag) { bond_feasibility_check_ = b_feas_flag; }
-  
-  /// \brief Get bond feasibility check flag
-  bool GetBondFeasibilityCheck() const { return bond_feasibility_check_; }  
-  
-private:
-  Dialect dialect_;
-  bool    strict_;
-  bool    bond_feasibility_check_; 
-};
-
-
-}} // ns
-
-#endif
diff --git a/modules/conop/src/compound.hh b/modules/conop/src/compound.hh
index 7e8c424571967ea5a7b0e339323561488b598d1e..c62c1aa801323cd669eca94e4f6ee0a8c3974135 100644
--- a/modules/conop/src/compound.hh
+++ b/modules/conop/src/compound.hh
@@ -20,6 +20,7 @@
 #define OST_CONOP_COMPOUND_HH
 
 #include <vector>
+#include <map>
 #include <boost/shared_ptr.hpp>
 #include <ost/string_ref.hh>
 #include <ost/conop/module_config.hh>
@@ -72,6 +73,9 @@ struct DLLEXPORT_OST_CONOP AtomSpec {
   AtomSpec()
     : ordinal(0), is_leaving(false) {
   }
+  AtomSpec(int o, const String& n, const String& a, const String& e,
+           bool l, bool r): ordinal(o), name(n), alt_name(a), element(e),
+    is_leaving(l), is_aromatic(r) {}
   int    ordinal;
   String name;
   String alt_name;
@@ -93,7 +97,7 @@ struct DLLEXPORT_OST_CONOP BondSpec {
     : atom_one(0), atom_two(0), order(1) {
 
   }
-
+  BondSpec(int a, int b, int o): atom_one(a), atom_two(b), order(o) {}
   bool operator==(const BondSpec& rhs) const {
     return atom_one==rhs.atom_one && atom_two==rhs.atom_two;
   }
@@ -247,6 +251,8 @@ private:
   Date                         mod_date_;
 };
 
+typedef std::map<String, CompoundPtr> CompoundMap;
+
 }}
 
 #endif
diff --git a/modules/conop/src/compound_lib.cc b/modules/conop/src/compound_lib.cc
index bc73c9d13811cfac427ddcb64f50293d8c150fc0..90e5df87c00ecc2aa8714bcb6df499ad878d4c09 100644
--- a/modules/conop/src/compound_lib.cc
+++ b/modules/conop/src/compound_lib.cc
@@ -362,7 +362,7 @@ CompoundLibPtr CompoundLib::Load(const String& database, bool readonly)
   return lib;
 }
 
-void CompoundLib::LoadAtomsFromDB(CompoundPtr comp, int pk) {
+void CompoundLib::LoadAtomsFromDB(CompoundPtr comp, int pk) const {
   String aq=str(format("SELECT name, alt_name, element, ordinal, is_leaving "
                        "FROM atoms WHERE compound_id=%d "
                        "ORDER BY ordinal ASC") % pk);  
@@ -391,7 +391,7 @@ void CompoundLib::ClearCache()
   compound_cache_.clear();
 }
 
-void CompoundLib::LoadBondsFromDB(CompoundPtr comp, int pk) {
+void CompoundLib::LoadBondsFromDB(CompoundPtr comp, int pk) const {
   sqlite3_stmt* stmt;
   String aq=str(format("SELECT a1.ordinal, a2.ordinal, b.bond_order FROM bonds AS b "
                        "LEFT JOIN atoms AS a1 ON b.atom_one=a1.id "
@@ -416,8 +416,8 @@ void CompoundLib::LoadBondsFromDB(CompoundPtr comp, int pk) {
 }
 
 CompoundPtr CompoundLib::FindCompound(const String& id, 
-                                      Compound::Dialect dialect) {
-  CompoundMap::iterator i=compound_cache_.find(id);
+                                      Compound::Dialect dialect) const {
+  CompoundMap::const_iterator i=compound_cache_.find(id);
   if (i!=compound_cache_.end()) {
     return i->second;
   }
diff --git a/modules/conop/src/compound_lib.hh b/modules/conop/src/compound_lib.hh
index c79463a6f28857e813c7c0e57050d4459a7714f9..fef48b1a766899cff3e4097fe68e70a0031291b8 100644
--- a/modules/conop/src/compound_lib.hh
+++ b/modules/conop/src/compound_lib.hh
@@ -25,41 +25,42 @@
 // our own local copy of sqlite3
 #include <ost/db/sqlite3.h>
 
-#include <ost/conop/module_config.hh>
-#include <ost/conop/compound.hh>
+#include "module_config.hh"
+#include "compound.hh"
+#include "compound_lib_base.hh"
 
 namespace ost { namespace conop {
 
 class CompoundLib;
 
 typedef boost::shared_ptr<CompoundLib> CompoundLibPtr;
-typedef std::map<String, CompoundPtr> CompoundMap;
 
-class DLLEXPORT_OST_CONOP CompoundLib {
+class DLLEXPORT_OST_CONOP CompoundLib : public CompoundLibBase {
 public:
   static CompoundLibPtr Load(const String& database, bool readonly=true);
   static CompoundLibPtr Create(const String& database);
   ~CompoundLib();
   
-  CompoundPtr FindCompound(const String& id, Compound::Dialect dialect);
-  Date GetCreationDate(void);
-  String GetOSTVersionUsed(void);
+  virtual CompoundPtr FindCompound(const String& id, 
+                                   Compound::Dialect dialect) const;
   void AddCompound(const CompoundPtr& compound);
   CompoundLibPtr Copy(const String& filename) const;
   void ClearCache();
+  Date GetCreationDate(void);
+  String GetOSTVersionUsed(void);
   void SetChemLibInfo(void);
 private:
     CompoundLib();
 
-    void LoadAtomsFromDB(CompoundPtr comp, int pk);
-    void LoadBondsFromDB(CompoundPtr comp, int pk);    
+    void LoadAtomsFromDB(CompoundPtr comp, int pk) const;
+    void LoadBondsFromDB(CompoundPtr comp, int pk) const;    
 private:
-  CompoundMap       compound_cache_;
-  sqlite3*          conn_;
-  bool              chem_type_available_; // weather pdbx_type is available in db
-  bool              name_available_; // weather name is available in db
-  Date              creation_date_;
-  String            ost_version_used_;
+  mutable CompoundMap       compound_cache_;
+  sqlite3*                  conn_;
+  bool                      chem_type_available_; // weather pdbx_type is available in db
+  bool                      name_available_; // weather name is available in db
+  Date                      creation_date_;
+  String                    ost_version_used_;
 };
 
 }}
diff --git a/modules/conop/src/compound_lib_base.cc b/modules/conop/src/compound_lib_base.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/modules/conop/src/compound_lib_base.hh b/modules/conop/src/compound_lib_base.hh
new file mode 100644
index 0000000000000000000000000000000000000000..350307eb52eb441aff4c4bac875a4344bbf5a319
--- /dev/null
+++ b/modules/conop/src/compound_lib_base.hh
@@ -0,0 +1,20 @@
+#ifndef OST_CONOP_COMPOUND_LIB_BASE_HH
+#define OST_CONOP_COMPOUND_LIB_BASE_HH
+
+#include "compound.hh"
+
+namespace ost { namespace conop {
+
+class CompoundLibBase;
+typedef boost::shared_ptr<CompoundLibBase> CompoundLibBasePtr;
+
+class DLLEXPORT_OST_CONOP CompoundLibBase {
+public:
+  virtual ~CompoundLibBase() {}
+  virtual CompoundPtr FindCompound(const String& id, 
+                                   Compound::Dialect dialect) const = 0;
+};
+
+}}
+#endif
+
diff --git a/modules/conop/src/conop.cc b/modules/conop/src/conop.cc
index e48b3444e16c4ac7bf1ba5ef70ea28ff8341f93a..58fc349b6df596e1bfc3de56396169ce2649eeef 100644
--- a/modules/conop/src/conop.cc
+++ b/modules/conop/src/conop.cc
@@ -21,7 +21,6 @@
 #include <ost/log.hh>
 
 #include "conop.hh"
-#include "heuristic_builder.hh"
 #include <ost/profile.hh>
 
 namespace ost { namespace conop {
@@ -33,11 +32,8 @@ Conopology& Conopology::Instance()
   return impl;
 }
 
-Conopology::Conopology():
-  builder_map_()
+Conopology::Conopology()
 {
-  builder_map_["HEURISTIC"]=BuilderP(new HeuristicBuilder());
-  builder_map_["DEFAULT"]=builder_map_["HEURISTIC"];
   
   known_elements_.insert("AC");
   known_elements_.insert("AG");
@@ -152,146 +148,6 @@ Conopology::Conopology():
   known_elements_.insert("ZR");
 }
 
-void Conopology::RegisterBuilder(const BuilderP& b, const String& name) {
-  if (!GetBuilder(name))
-  builder_map_[name]=b;
-}
-
-void Conopology::SetDefaultBuilder(const String& default_name) {
-  BuilderP builder=GetBuilder(default_name);
-  if (builder)
-    builder_map_["DEFAULT"]=builder;
-  else
-    throw ost::Error("trying to set unknown builder '"+
-                             default_name+"' as the default");
-}
-
-BuilderP Conopology::GetBuilder(const String& name)
-{
-  BuilderMap::iterator it=builder_map_.find(name);
-  if (it!=builder_map_.end()){
-    return (*it).second;
-  }
-  return BuilderP();
-}
-
-namespace {
-
-class PropAssigner: public mol::EntityVisitor {
-public:
-  PropAssigner(const BuilderP& builder): builder_(builder) {}
-  
-  virtual bool VisitResidue(const mol::ResidueHandle& res)
-  {
-    String key=builder_->IdentifyResidue(res);
-    if (key=="UNK" && res.GetKey()!="UNK" && res.GetKey()!="UNL") {
-      unk_res_[res.GetKey()]+=1;
-    }
-    builder_->FillResidueProps(res);
-    return true;
-  }
-  
-  virtual bool VisitAtom(const mol::AtomHandle& atom)
-  {
-    builder_->FillAtomProps(atom);
-    return false;
-  }
-  
-  virtual void OnExit()
-  {
-    for (std::map<String, int>::iterator i=unk_res_.begin(), 
-         e=unk_res_.end(); i!=e; ++i) {
-      if (i->second>1) {
-        LOG_WARNING("structure contains unknown residues with name " << i->first 
-                    << " ("<< i->second << "x)");
-      } else {        
-        LOG_WARNING("structure contains unknown residue with name " << i->first);
-      }
-
-    }
-  }
-private:
-  BuilderP builder_;
-  std::map<String, int>  unk_res_;  
-};
-
-class ChemClassAssigner : public mol::EntityVisitor {
-public:
-  ChemClassAssigner(BuilderP b): builder(b) { }
-  virtual bool VisitResidue(const mol::ResidueHandle& res)
-  {
-    if (res.GetChemClass()==mol::ChemClass()) {
-      builder->GuessChemClass(res);
-    }
-    return false;
-  }
-private:
-  BuilderP builder;
-};
-class Connector: public mol::EntityVisitor
-{
-public:
-  Connector(const BuilderP& b, bool peptide_bonds):
-    builder_(b),
-    prev_(),
-    peptide_bonds_(peptide_bonds)
-  {}
-
-  virtual bool VisitChain(const mol::ChainHandle& chain) {
-    prev_=mol::ResidueHandle(); // reset prev
-    return true;
-  }
-
-  virtual bool VisitResidue(const mol::ResidueHandle& res) {
-    builder_->ConnectAtomsOfResidue(res);
-    if (peptide_bonds_ && prev_) {
-      builder_->ConnectResidueToPrev(res,prev_);
-    }
-    prev_=res;
-    return false;
-  }
-
-private:
-  BuilderP builder_;
-  mol::ResidueHandle prev_;
-  bool peptide_bonds_;
-};
-
-class TorsionMaker: public mol::EntityVisitor
-{
-public:
-  TorsionMaker(const BuilderP& b):
-    builder_(b)
-  {}
-
-  virtual bool VisitChain(const mol::ChainHandle& chain) {
-    builder_->AssignTorsions(chain);
-    return false;
-  }
-
-private:
-  BuilderP builder_;
-};
-} // ns
-
-void Conopology::ConnectAll(const BuilderP& b, mol::EntityHandle eh, int flags)
-{
-  Profile profile_connect("ConnectAll");
-  LOG_DEBUG("Conopology: ConnectAll: building internal coordinate system");
-  mol::XCSEditor xcs_e=eh.EditXCS(mol::BUFFERED_EDIT);
-  PropAssigner a(b);
-  eh.Apply(a);
-  ChemClassAssigner cca(b);
-  eh.Apply(cca);
-  LOG_DEBUG("Conopology: ConnectAll: connecting all bonds");
-  Connector connector(b, !(flags & NO_PEPTIDE_BONDS));
-  eh.Apply(connector);
-
-  LOG_DEBUG("Conopology: ConnectAll: assigning all torsions");
-  TorsionMaker tmaker(b);
-  eh.Apply(tmaker);
-}
-
 bool Conopology::IsValidElement(const String& ele) const
 {
   String upper_ele=ele;
diff --git a/modules/conop/src/conop.hh b/modules/conop/src/conop.hh
index 1234a30fd0ae024a69eeeb0d2a4fa9227bdcb73a..34f58e080f97384df0bfc9ca7db6ee2ab3f6220c 100644
--- a/modules/conop/src/conop.hh
+++ b/modules/conop/src/conop.hh
@@ -22,8 +22,8 @@
 #include <map>
 #include <ost/conop/module_config.hh>
 #include <ost/mol/entity_handle.hh>
-#include "builder_fw.hh"
-
+#include "processor.hh"
+#include "compound_lib.hh"
 namespace ost { namespace conop {
 
 
@@ -33,35 +33,23 @@ typedef enum {
 
   
 class DLLEXPORT_OST_CONOP Conopology {
-  typedef std::map<String,BuilderP> BuilderMap;
-
 public:
   // singleton
   static Conopology& Instance();
 
-  // retrieve a builder by name
-  BuilderP GetBuilder(const String& name="DEFAULT");
-
-  /*
-    convenience function, connect all atoms with given coordinates,
-    such as after coordinate file import, based on a given builder
+  // returns the default compound library (if any)
+  CompoundLibPtr GetDefaultLib() const { return lib_; }
+  void SetDefaultLib(const CompoundLibPtr& lib) { lib_ = lib; }
 
-    does this need to live within Conopology ?
-  */
-  void ConnectAll(const BuilderP& b, mol::EntityHandle eh, 
-                  int flags=0);
-
-  void RegisterBuilder(const BuilderP& b, const String& name);
-  void SetDefaultBuilder(const String& default_name);
-  
   bool IsValidElement(const String& element) const;
+
 private:
   Conopology();
   Conopology(const Conopology&) {}
   Conopology& operator=(const Conopology&) {return *this;}
 
-  BuilderMap builder_map_;
   std::set<String> known_elements_;
+  CompoundLibPtr lib_;
 };
 
 }} //
diff --git a/modules/conop/src/diag.cc b/modules/conop/src/diag.cc
index 75245fc93aa9414b0a8e1229a3b106957dd8ec30..470673bf73f3c6bcb7acc0836839c25c7d740336 100644
--- a/modules/conop/src/diag.cc
+++ b/modules/conop/src/diag.cc
@@ -29,7 +29,7 @@ String Diag::Format(bool colored) const
    switch (i->type) {
      case DIAG_ARG_TYPE_ATOM:
        if (colored) {
-         strings.push_back("\033[0;30m"+
+         strings.push_back("\033[0;32m"+
                            atoms_[i->index].GetQualifiedName()+"\033[0m");
        } else {
          strings.push_back(atoms_[i->index].GetQualifiedName());
@@ -37,7 +37,7 @@ String Diag::Format(bool colored) const
        break;
      case DIAG_ARG_TYPE_RESIDUE:
         if (colored) {  
-          strings.push_back("\033[0;30m"+
+          strings.push_back("\033[0;32m"+
                             residues_[i->index].GetQualifiedName()+"\033[0m");
        } else {
           strings.push_back(residues_[i->index].GetQualifiedName());
@@ -45,7 +45,7 @@ String Diag::Format(bool colored) const
        break;
      case DIAG_ARG_TYPE_CHAIN:
         if (colored) {    
-          strings.push_back("\033[0;30m"+
+          strings.push_back("\033[0;32m"+
                             chains_[i->index].GetName()+"\033[0m");
        } else {
          strings.push_back(chains_[i->index].GetName());
diff --git a/modules/conop/src/diag.hh b/modules/conop/src/diag.hh
index 58f4765543c389b27c5925c9df7068bc2708e9dd..ba7297dd63766ede1e5dd067852b99b61fd14cae 100644
--- a/modules/conop/src/diag.hh
+++ b/modules/conop/src/diag.hh
@@ -1,4 +1,4 @@
-#//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 // This file is part of the OpenStructure project <www.openstructure.org>
 //
 // Copyright (C) 2008-2011 by the OpenStructure authors
@@ -18,6 +18,7 @@
 //------------------------------------------------------------------------------
 #ifndef OST_CONOP_DIAG_HH
 #define OST_CONOP_DIAG_HH
+
 #include <ost/mol/atom_handle.hh>
 #include <ost/mol/residue_handle.hh>
 #include <ost/mol/chain_handle.hh>
@@ -26,11 +27,11 @@
 namespace ost { namespace conop {
 
 typedef enum {
-	DIAG_ARG_TYPE_ATOM,
-	DIAG_ARG_TYPE_RESIDUE,
-	DIAG_ARG_TYPE_CHAIN,
-	DIAG_ARG_TYPE_STRING,
-	DIAG_ARG_TYPE_INT
+  DIAG_ARG_TYPE_ATOM,
+  DIAG_ARG_TYPE_RESIDUE,
+  DIAG_ARG_TYPE_CHAIN,
+  DIAG_ARG_TYPE_STRING,
+  DIAG_ARG_TYPE_INT
 } DiagArgType;
 
 typedef enum {
@@ -42,39 +43,39 @@ typedef enum {
 
 class DLLEXPORT_OST_CONOP Diag {
 public:
-	Diag(DiagType typ, const char* fmt): type_(typ), format_(fmt) {}
+  Diag(DiagType typ, const char* fmt): type_(typ), format_(fmt) {}
   DiagType GetType() const { return type_; }
-	Diag& AddAtom(mol::AtomHandle atom)
-	{
-		atoms_.push_back(atom);
-		args_.push_back(ArgDesc(atoms_.size()-1, DIAG_ARG_TYPE_ATOM));
-		return *this;
-	}
+  Diag& AddAtom(mol::AtomHandle atom)
+  {
+    atoms_.push_back(atom);
+    args_.push_back(ArgDesc(atoms_.size()-1, DIAG_ARG_TYPE_ATOM));
+    return *this;
+  }
 
-	Diag& AddResidue(mol::ResidueHandle res)
-	{
-		residues_.push_back(res);
-		args_.push_back(ArgDesc(residues_.size()-1, DIAG_ARG_TYPE_RESIDUE));
-		return *this;
-	}
-	Diag& AddChain(mol::ChainHandle chain)
-	{
-		chains_.push_back(chain);
-		args_.push_back(ArgDesc(chains_.size()-1, DIAG_ARG_TYPE_CHAIN));
-		return *this;
-	}
-	Diag& AddInt(int int_val)
-	{
-		ints_.push_back(int_val);
-		args_.push_back(ArgDesc(ints_.size()-1, DIAG_ARG_TYPE_INT));
-		return *this;
-	}
-	Diag& AddString(const String& str)
-	{
-		strings_.push_back(str);
-		args_.push_back(ArgDesc(strings_.size()-1, DIAG_ARG_TYPE_STRING));
-		return *this;
-	}
+  Diag& AddResidue(mol::ResidueHandle res)
+  {
+    residues_.push_back(res);
+    args_.push_back(ArgDesc(residues_.size()-1, DIAG_ARG_TYPE_RESIDUE));
+    return *this;
+  }
+  Diag& AddChain(mol::ChainHandle chain)
+  {
+    chains_.push_back(chain);
+    args_.push_back(ArgDesc(chains_.size()-1, DIAG_ARG_TYPE_CHAIN));
+    return *this;
+  }
+  Diag& AddInt(int int_val)
+  {
+    ints_.push_back(int_val);
+    args_.push_back(ArgDesc(ints_.size()-1, DIAG_ARG_TYPE_INT));
+    return *this;
+  }
+  Diag& AddString(const String& str)
+  {
+    strings_.push_back(str);
+    args_.push_back(ArgDesc(strings_.size()-1, DIAG_ARG_TYPE_STRING));
+    return *this;
+  }
   mol::AtomHandle GetAtom(size_t index) const
   {
     assert(index<args_.size());
@@ -90,44 +91,59 @@ public:
     assert(index<args_.size());
     return chains_[args_[index].index];
   }
-	String Format(bool colored=true) const;
+  String Format(bool colored=true) const;
 private:
-	struct ArgDesc {
-		ArgDesc(size_t i, DiagArgType t): index(i), type(t) { }
-		size_t      index;
-		DiagArgType type;
-	};
-	DiagType               type_;
-	String                 format_;
-	mol::AtomHandleList    atoms_;
-	mol::ResidueHandleList residues_;
+  struct ArgDesc {
+    ArgDesc(size_t i, DiagArgType t): index(i), type(t) { }
+    size_t      index;
+    DiagArgType type;
+  };
+  DiagType               type_;
+  String                 format_;
+  mol::AtomHandleList    atoms_;
+  mol::ResidueHandleList residues_;
   mol::ChainHandleList   chains_;
-	std::vector<String>    strings_;
-	std::vector<int>       ints_;
-	std::vector<ArgDesc>   args_;
+  std::vector<String>    strings_;
+  std::vector<int>       ints_;
+  std::vector<ArgDesc>   args_;
 };
 
-class DLLEXPORT_OST_CONOP DiagEngine {
+class Diagnostics;
+
+typedef boost::shared_ptr<Diagnostics> DiagnosticsPtr;
+
+
+class DLLEXPORT DiagError : public Error {
 public:
-	DiagEngine() {}
+  DiagError(const Diag& diag) : Error(diag.Format(false)) {}
+};
 
-	~DiagEngine()
-	{
-		for(std::vector<Diag*>::iterator
-				i=diags_.begin(), e=diags_.end(); i!=e;++i) {
-		  delete *i;
-		}
-	}
+class DLLEXPORT_OST_CONOP Diagnostics {
+public:
+  typedef std::vector<Diag*>::iterator diag_iterator;
+  typedef std::vector<Diag*>::const_iterator const_diag_iterator;
+  Diagnostics() {}
 
-	Diag& AddDiag(DiagType type, const char* fmt)
-	{
-		diags_.push_back(new Diag(type, fmt));
-		return *diags_.back();
-	}
+  ~Diagnostics()
+  {
+    for(std::vector<Diag*>::iterator
+        i=diags_.begin(), e=diags_.end(); i!=e;++i) {
+      delete *i;
+    }
+  }
 
-	const std::vector<Diag*>& GetDiags() const { return diags_; }
+  Diag& AddDiag(DiagType type, const char* fmt)
+  {
+    diags_.push_back(new Diag(type, fmt));
+    return *diags_.back();
+  }
+  diag_iterator diags_begin() { return diags_.begin(); } 
+  diag_iterator diags_end() { return diags_.end(); } 
+  const_diag_iterator diags_begin() const { return diags_.begin(); } 
+  const_diag_iterator diags_end() const { return diags_.end(); } 
+  size_t diag_count() const { return diags_.size(); }
 private:
-	std::vector<Diag*> diags_;
+  std::vector<Diag*> diags_;
 };
 
 }} /* ost::conop */
diff --git a/modules/conop/src/heuristic.cc b/modules/conop/src/heuristic.cc
new file mode 100644
index 0000000000000000000000000000000000000000..cecf6dcb2df8996a41b7685877e5c40518bac4b5
--- /dev/null
+++ b/modules/conop/src/heuristic.cc
@@ -0,0 +1,98 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+
+#include <ost/log.hh>
+#include <ost/profile.hh>
+#include <ost/mol/xcs_editor.hh>
+#include <ost/mol/bond_handle.hh>
+#include <ost/mol/torsion_handle.hh>
+#include <ost/mol/impl/residue_impl.hh>
+#include <ost/mol/impl/atom_impl.hh>
+#include <ost/mol/residue_handle.hh>
+#include "heuristic.hh"
+#include "conop.hh"
+
+namespace ost { namespace conop {
+
+void HeuristicProcessor::ProcessUnkResidue(DiagnosticsPtr diags, 
+                                           mol::ResidueHandle res) const {
+  res.SetChemClass(GuessChemClass(res));
+  mol::AtomHandleList atoms = res.GetAtomList(); 
+  for (mol::AtomHandleList::iterator 
+       i = atoms.begin(), e = atoms.end(); i != e; ++i) {
+    mol::AtomHandle a = *i;
+    if (!Conopology::Instance().IsValidElement(a.GetElement()))
+      a.SetElement(GuessAtomElement(a.GetName(), a.IsHetAtom()));
+  }
+  if (!this->GetConnect()) { return; }
+  for (mol::AtomHandleList::iterator 
+       i = atoms.begin(), e = atoms.end(); i != e; ++i) {
+    this->DistanceBasedConnect(*i);
+  }
+}
+
+void HeuristicProcessor::DoProcess(DiagnosticsPtr diags, 
+                                   mol::EntityHandle ent) const
+{
+  Profile prof("HeuristicProcessor::Process");
+  mol::ChainHandleList chains=ent.GetChainList();
+  for (mol::ChainHandleList::iterator 
+       i = chains.begin(), e = chains.end(); i!= e; ++i) {
+    mol::ChainHandle& chain = *i;
+    mol::ResidueHandleList residues = chain.GetResidueList();
+    mol::ResidueHandle prev;
+    for (mol::ResidueHandleList::iterator 
+         j = residues.begin(), e2 = residues.end(); j != e2; ++j) {
+      mol::ResidueHandle residue = *j;
+      CompoundPtr compound = lib_.FindCompound(residue.GetName(), Compound::PDB);
+      if (!compound) {
+        // process unknown residue...
+        this->ProcessUnkResidue(diags, residue);
+        continue;
+      }
+      this->ReorderAtoms(residue, compound, true);  
+      this->FillResidueProps(residue, compound);
+      if (this->GetConnect()) {
+        this->ConnectAtomsOfResidue(residue, compound, false);
+        if (this->GetConnectAminoAcids()) 
+          this->ConnectResidues(prev, residue);
+      }
+      prev = residue;
+      if (!this->GetConnect()) { continue; }
+      mol::AtomHandleList atoms = residue.GetAtomList();
+      for (mol::AtomHandleList::iterator 
+          i = atoms.begin(), e = atoms.end(); i != e; ++i) {
+        if (i->GetBondCount() == 0)
+          this->DistanceBasedConnect(*i);
+      }
+    }
+    if (residues.empty() || !this->GetAssignTorsions()) {
+      continue;
+    }
+    AssignBackboneTorsions(residues);
+  }
+}
+
+String HeuristicProcessor::ToString() const {
+  std::stringstream ss;
+  ss << "HeuristicProcessor(" << this->OptionsToString() << ")";
+  return ss.str();
+}
+
+}}
diff --git a/modules/conop/src/heuristic.hh b/modules/conop/src/heuristic.hh
new file mode 100644
index 0000000000000000000000000000000000000000..a0a7b60ff626b9e72c10f41b09237d14e00f8a6d
--- /dev/null
+++ b/modules/conop/src/heuristic.hh
@@ -0,0 +1,57 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+#ifndef OST_CONOP_HEURISTIC_HH
+#define OST_CONOP_HEURISTIC_HH
+
+#include <ost/mol/entity_handle.hh>
+#include "minimal_compound_lib.hh"
+#include "diag.hh"
+#include "processor.hh"
+
+namespace ost { namespace conop {
+
+
+class HeuristicProcessor;
+
+typedef boost::shared_ptr<HeuristicProcessor> HeuristicProcessorPtr;
+
+class DLLEXPORT_OST_CONOP HeuristicProcessor  : public Processor {
+public:
+  HeuristicProcessor() {
+  }
+  virtual ProcessorPtr Copy() const {
+    return ProcessorPtr(new HeuristicProcessor(*this));
+  }
+  HeuristicProcessor(bool bf, bool at, bool cn, bool aa, ConopAction zo): 
+    Processor(bf, at, cn, aa, zo) {}
+
+  virtual String ToString() const;
+protected:
+  void ProcessUnkResidue(DiagnosticsPtr diags, mol::ResidueHandle res) const;
+  virtual void DoProcess(DiagnosticsPtr diags, 
+                         mol::EntityHandle ent) const;
+private:
+  MinimalCompoundLib lib_;
+};
+
+
+}}
+
+#endif
+
diff --git a/modules/conop/src/heuristic_builder.cc b/modules/conop/src/heuristic_builder.cc
deleted file mode 100644
index 07922d6a2dab0aa5fd162323749ebb4c9a4efaaa..0000000000000000000000000000000000000000
--- a/modules/conop/src/heuristic_builder.cc
+++ /dev/null
@@ -1,531 +0,0 @@
-//------------------------------------------------------------------------------
-// This file is part of the OpenStructure project <www.openstructure.org>
-//
-// Copyright (C) 2008-2011 by the OpenStructure authors
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License as published by the Free
-// Software Foundation; either version 3.0 of the License, or (at your option)
-// any later version.
-// This library is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with this library; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//------------------------------------------------------------------------------
-#include <boost/algorithm/string/trim.hpp>
-
-#include <ost/log.hh>
-#include <ost/geom/geom.hh>
-#include "conop.hh"
-#include "heuristic_builder.hh"
-#include "heuristic_connect_table.hh"
-#include <ost/mol/residue_handle.hh>
-
-
-namespace ost { namespace conop {
-
-namespace detail {
-
-// internal helper class
-ConnResEntry::ConnResEntry(const String& rname, char single,
-                           const mol::ChemClass& chem_class):
-  rkey_(rname),
-  abbrev_(single),
-  chem_class_(chem_class),
-  pset_(),
-  prev_(""),
-  next_(""),
-  torsion_entry_list_()
-{}
-  
-int ConnResEntry::Check(const String& name1, const String& name2) const
-{
-  NamePair np1(name1,name2);
-  NamePair np2(name2,name1);
-  // does this pair exist?
-  if(pset_.find(np1)!=pset_.end()) {
-    return 1;
-  } else if(pset_.find(np2)!=pset_.end()) {
-    return 2;
-  }
-
-  return 0;
-}
-
-bool ConnResEntry::HasAtom(const String& name)
-{
-  for(PairSet::const_iterator it=pset_.begin();it!=pset_.end();++it) {
-    if(it->first==name || it->second==name) return true;
-  }
-  return false;
-}
-
-// add a connection entry
-void ConnResEntry::AddConn(const String& n1, const String& n2)
-{
-  pset_.insert(std::make_pair(n1,n2));
-}
-
-void ConnResEntry::AddTors(const String& a1, const String& a2, const String& a3,
-                           const String& a4, const String& name)
-{
-  TorsionEntry te={{a1,a2,a3,a4},name};
-  torsion_entry_list_.push_back(te);
-}
-
-// atom that connects to previous residue in chain
-void ConnResEntry::SetPrev(const String& n)
-{
-  prev_=n;
-}
-
-const String& ConnResEntry::GetPrev() const
-{
-  return prev_;
-}
-
-// atom that connects to next residue in chain
-void ConnResEntry::SetNext(const String& n)
-{
-  next_=n;
-}
-
-const String& ConnResEntry::GetNext() const
-{
-  return next_;
-}
-
-ConnResEntry::TorsionEntryList ConnResEntry::GetTorsionList() const
-{
-  return torsion_entry_list_;
-}
-
-} // ns
-
-// actual builder
-
-HeuristicBuilder::HeuristicBuilder():
-  emap_(),
-  default_peptide_()
-{
-  int def_entry_count = sizeof(heuristic_connect::def_entry_table)/sizeof(heuristic_connect::CONN_DEF_ENTRY);
-
-  LOG_DEBUG("importing internal connectivity tables");
-  for(int ec=0;ec<def_entry_count;++ec) {
-    heuristic_connect::CONN_DEF_ENTRY& def_entry = heuristic_connect::def_entry_table[ec];
-    detail::ConnResEntry entry(def_entry.abbrev, def_entry.single,
-                               def_entry.chem_class);
-    LOG_TRACE("creating table entry for " << def_entry.abbrev);
-    LOG_TRACE("working on bond entries");
-    for (int xx=0;xx<def_entry.name_count;++xx) {
-      String name=def_entry.name_list[xx];
-      if (name!="OXT")
-        entry.AddAtom(name);
-    }
-    // first the connectivity entries
-    for(int cc=0;cc<def_entry.conn_count;++cc) {
-      int conn_id[] = {def_entry.conn_list[cc][0],def_entry.conn_list[cc][1]};
-      String conn_nam[] = {"",""};
-      bool special=false;
-      for(int cid=0;cid<2;++cid) {
-        if(conn_id[cid]>0) {
-          conn_nam[cid]=def_entry.name_list[conn_id[cid]-1];
-        } else if (conn_id[cid]==-2) {
-          // PREV key
-          conn_nam[cid]="-";
-          special=true;
-        } else if (conn_id[cid]==-3) {
-          // NEXT key
-          conn_nam[cid]="+";
-          special=true;
-        } else {
-          // ignore
-          continue;
-        }
-      }
-      if(special) {
-        if(conn_nam[0]==String("-")) { entry.SetPrev(conn_nam[1]);}
-        else if(conn_nam[1]==String("-")) { entry.SetPrev(conn_nam[0]);}
-        else if(conn_nam[0]==String("+")) { entry.SetNext(conn_nam[1]);}
-        else if(conn_nam[1]==String("+")) { entry.SetNext(conn_nam[0]);}
-        LOG_TRACE(" " << conn_nam[0] << " " << conn_nam[1]);
-            } else {
-        LOG_TRACE(" " << conn_nam[0] << " " << conn_nam[1]);
-        entry.AddConn(conn_nam[0],conn_nam[1]);
-      }
-    }
-    // then the torsion entries
-    LOG_DEBUG("working on torsion entries");
-    for(int cc=0;cc<def_entry.tor_count;++cc) {
-      int tor_id[] = {def_entry.tor_list[cc].n1,
-                      def_entry.tor_list[cc].n2,
-                      def_entry.tor_list[cc].n3,
-                      def_entry.tor_list[cc].n4};
-      String tor_nam[] = {"","","",""};
-      String tor_nam2(def_entry.tor_list[cc].name);
-      for(int cid=0;cid<4;++cid) {
-        if(tor_id[cid]>0) {
-          tor_nam[cid]=def_entry.name_list[tor_id[cid]-1];
-        } else if (tor_id[cid]==-2) {
-          tor_nam[cid]="-";
-        } else if (tor_id[cid]==-3) {
-          tor_nam[cid]="+";
-        } else if (tor_id[cid]==-4) {
-          tor_nam[cid]=":";
-        }
-      }
-
-      entry.AddTors(tor_nam[0],tor_nam[1],tor_nam[2],tor_nam[3],tor_nam2);
-    }
-    if(ec==0) { 
-      default_peptide_=entry;
-    } else {
-      emap_[def_entry.abbrev]=entry;
-    }
-  }
-  default_nucleotide_=LookupResEntry("G").first;
-  LOG_DEBUG("done importing internal tables");
-}
-
-HeuristicBuilder::~HeuristicBuilder()
-{}
-
-
-void HeuristicBuilder::ConnectivityFromAtomNames(const mol::ResidueHandle& res,
-                                                 detail::ConnResEntry& centry,
-                                                 mol::AtomHandleList& unknown_atoms) {
- unknown_atoms.clear();
- mol::AtomHandleList atomlist=res.GetAtomList();
- mol::XCSEditor editor=res.GetEntity().EditXCS(mol::BUFFERED_EDIT);
- for (mol::AtomHandleList::iterator it1=atomlist.begin();it1!=atomlist.end();++it1) {
-   if (centry.HasAtom(it1->GetName())) {
-     mol::AtomHandleList::iterator it2=it1;
-     ++it2;
-     for (;it2!=atomlist.end();++it2) {
-       LOG_TRACE("checking for atom pair (" << it1->GetName() << ","
-                << it2->GetName() << ") in connectivity table of "
-                << res.GetKey() << "... ");
-       int conn=centry.Check(it1->GetName(),it2->GetName());
-       if (conn==1) {
-	 if (this->GetBondFeasibilityCheck()==false) {
-           LOG_TRACE( "found");
-           editor.Connect(*it1,*it2);
-	 } else {  
-	   if (this->IsBondFeasible(*it1, *it2)) {
-	     LOG_TRACE( "found");
-             editor.Connect(*it1,*it2);
-	   } else {
-             LOG_TRACE( "not found");
-	   }  
-	 }	 
-       } else if (conn==2) {
-	 if (this->GetBondFeasibilityCheck()==false) {
-             LOG_TRACE( "found (reversed)");
-             editor.Connect(*it2,*it1);
-	 } else {
-           if(this->IsBondFeasible(*it2, *it1)) {
-             LOG_TRACE( "found (reversed)");             
-             editor.Connect(*it2,*it1);
-           }
-         }  
-       } else {
-          LOG_TRACE( "not found");
-       }
-     }
-   } else {
-     unknown_atoms.push_back(*it1);
-     LOG_TRACE( "atom not found, pushing it to unknown atoms");
-   }	 
- }
-}
-
-void HeuristicBuilder::ConnectAtomsOfResidue(mol::ResidueHandle res)
-{
-  LOG_TRACE("HeuristicBuilder: ConnectAtomsOfResidue on " << res.GetKey() << " " << res.GetNumber());
-
-  mol::AtomHandleList atomlist = res.GetAtomList();
-  mol::AtomHandleList unk_atomlist;
-#if !defined(NDEBUG)
-  std::stringstream ss;
-  ss << "using atom list:";
-  for(mol::AtomHandleList::iterator it=atomlist.begin();it!=atomlist.end();++it) {
-    ss << " " << it->GetName() << " @" << it->GetPos();
-  }
-  LOG_TRACE(ss.str());
-#endif
-  std::pair<detail::ConnResEntry,bool> ret = LookupResEntry(res.GetKey());
-
-  if(ret.second) {
-    // residue entry found
-    this->ConnectivityFromAtomNames(res, ret.first, unk_atomlist);
-    // only run the distance based connectivity after the rest is done
-    for(mol::AtomHandleList::iterator it1=unk_atomlist.begin();
-        it1!=unk_atomlist.end();
-        ++it1) {
-      LOG_TRACE( "atom " << it1->GetName() << " not found, using distance based connect");
-      Builder::DistanceBasedConnect(*it1);
-    }
-  } else {
-    LOG_TRACE("no residue entry found, using distance based connect");
-    for(mol::AtomHandleList::iterator it1=atomlist.begin();
-        it1!=atomlist.end();
-        ++it1) {
-      Builder::DistanceBasedConnect(*it1);
-    }
-  }
-}
-
-namespace {
-
-template<bool flag> // false:=prev, true:=next
-void ConnectPrevNext(HeuristicBuilder* builder,mol::ResidueHandle res0, 
-                     mol::ResidueHandle res1)
-{
-  static String fname=flag ? "HeuristicBuilder: ConnectNextXCS" : "HeuristicBuilder: ConnectPrevXCS";
-  if(!res0) return; // return if invalid
-  mol::XCSEditor editor=res0.GetEntity().EditXCS(mol::BUFFERED_EDIT);
-  LOG_TRACE(fname << " on " << res0.GetKey() << " " << res0.GetNumber());
-
-  if(!res1) {
-    // auto-detect prev or next residue in chain
-    // and perform sequence check
-    if(flag) {
-      LOG_TRACE(fname << " autodecting next residue");
-      res1 = res0.GetChain().GetNext(res0);
-    } else {
-      LOG_TRACE(fname << " autodecting next residue");
-      res1 = res0.GetChain().GetPrev(res0);
-    }
-  } else {
-    if(res0.GetEntity() != res1.GetEntity()) return; // different entity handles
-  }
-  if (flag) {
-    if(!Builder::AreResiduesConsecutive(res0,res1)) return;
-  } else {
-    if(!Builder::AreResiduesConsecutive(res1, res0)) return;
-  }
-
-  if(!res1) return; // ignore if prev/next residue is invalid
-  LOG_TRACE(fname << " found second residue " << res1.GetKey() 
-            << " " << res1.GetNumber());
-
-  std::pair<detail::ConnResEntry,bool> res0_ret = builder->LookupResEntry(res0.GetKey());
-  std::pair<detail::ConnResEntry,bool> res1_ret = builder->LookupResEntry(res1.GetKey());
-
-  if(!res0_ret.second) {
-    if(res0.FindAtom("N") && res0.FindAtom("CA") && res0.FindAtom("C")) {
-      LOG_TRACE("using default peptide for " << res0.GetKey());
-      res0_ret.first=builder->DefaultPeptide();
-      res0_ret.second=true;
-    }
-    if (res0.FindAtom("C3'") && res0.FindAtom("P")) {
-      res0_ret.first=builder->DefaultNucleotide();
-      res0_ret.second=true;
-    }
-  }
-
-  if(!res1_ret.second) {
-    if(res1.FindAtom("N") && res1.FindAtom("CA") && res1.FindAtom("C")) {
-      LOG_TRACE("using default peptide for " << res1.GetKey());
-      res1_ret.first=builder->DefaultPeptide();
-      res1_ret.second=true;
-    }
-    if (res1.FindAtom("C3'") && res1.FindAtom("P")) {
-      res1_ret.first=builder->DefaultNucleotide();
-      res1_ret.second=true;
-    }
-  }
-
-  if(res0_ret.second && res1_ret.second) {
-    detail::ConnResEntry& res0_centry=res0_ret.first;
-    detail::ConnResEntry& res1_centry=res1_ret.first;
-    String res0_atom_name = res0_centry.GetPrev();
-    String res1_atom_name = res1_centry.GetNext();
-
-    if(res0_atom_name.empty() || res1_atom_name.empty()) return;
-    LOG_TRACE(fname << ": looking up atom names " << res0_atom_name << " " << res1_atom_name);
-
-    // lookup both atoms in their respective residues
-    mol::AtomHandle res0_atom = res0.FindAtom(res0_atom_name);
-    mol::AtomHandle res1_atom = res1.FindAtom(res1_atom_name);
-    if(res0_atom && res1_atom) {
-      LOG_TRACE(fname << ": found atoms, connecting");
-      if(flag) {
-        if (builder->DoesPeptideBondExist(res0_atom, res1_atom)) {
-          editor.Connect(res0_atom,res1_atom);
-          if (res0_ret.first.GetChemClass().IsPeptideLinking()) {
-            res0.SetIsProtein(true);
-            res1.SetIsProtein(true);
-          }
-        }
-      } else {
-        if (builder->DoesPeptideBondExist(res1_atom, res0_atom)) {
-          editor.Connect(res1_atom, res0_atom);
-          if (res0_ret.first.GetChemClass().IsPeptideLinking()) {
-            res0.SetIsProtein(true);
-            res1.SetIsProtein(true);
-          }
-        }
-      }
-    }
-  } else {
-    // could implement some sort of distance based heuristics here
-  }
-}
-
-}
-
-void HeuristicBuilder::AssignTorsionsToResidue(mol::ResidueHandle res)
-{
-
-  mol::XCSEditor editor=res.GetEntity().EditXCS(mol::BUFFERED_EDIT);
-  mol::ChainHandle chain=res.GetChain();
-  std::pair<detail::ConnResEntry,bool> centry2 = LookupResEntry(res.GetKey());
-  if (centry2.second) {
-    // residue entry found
-    detail::ConnResEntry& centry=centry2.first;
-
-    detail::ConnResEntry::TorsionEntryList tel=centry.GetTorsionList();
-    // for each entry in torsion list
-    for (unsigned int ti=0;ti<tel.size();++ti) {
-      // assign the four atom handles
-      mol::AtomHandle ah[4];
-      for (unsigned int ahi=0;ahi<4;++ahi) {
-        mol::ResidueHandle search_in=res;
-        String cur_name=tel[ti].a[ahi];
-        bool flag=false;
-        if (cur_name=="+") {
-          mol::ResidueHandle next=res.GetNext();
-          // NEXT
-          if (Builder::AreResiduesConsecutive(res, next)) {
-            centry2=LookupResEntry(next.GetKey());
-            if (centry2.second) {
-              cur_name=centry2.first.GetPrev();
-              search_in=next;
-              flag=true;
-            }
-          }
-        } else if (cur_name=="-") {
-          mol::ResidueHandle prev=res.GetPrev();
-          if (Builder::AreResiduesConsecutive(prev, res)) {
-            centry2=LookupResEntry(prev.GetKey());
-            if (centry2.second) {
-              cur_name=centry2.first.GetNext();
-              search_in=prev;
-              flag=true;
-            }
-          }
-        } else {
-          flag=true;
-        }
-        if (flag) {
-          // lookup atom based on cur_residue and cur_name
-          mol::AtomHandle a=search_in.FindAtom(cur_name);
-          if (!a.IsValid())
-            continue;
-          ah[ahi]=a;
-        }
-      } // ahi
-      if (ah[0] && ah[1] && ah[2] && ah[3]) {
-        mol::TorsionHandle th = editor.AddTorsion(tel[ti].name, ah[0], ah[1],
-                                             ah[2], ah[3]);
-        if(th) {
-          LOG_TRACE("added torsion entry for " << tel[ti].a[0] << " "
-                    << tel[ti].a[1] << " " << tel[ti].a[2] << " "
-                    << tel[ti].a[3]);
-        } else {
-          LOG_TRACE("no torsion entry for " << tel[ti].a[0] << " "
-                    << tel[ti].a[1] << " " << tel[ti].a[2]
-                    << " " << tel[ti].a[3]);
-        }
-      }
-    }
-  }
-}
-
-void HeuristicBuilder::AssignTorsions(mol::ChainHandle chain)
-{
-  if (chain.GetResidueCount()==0)
-    return;
-  std::vector<mol::ResidueHandle> rlist = chain.GetResidueList();
-  for(unsigned int ri=0;ri<rlist.size();++ri) {
-    mol::ResidueHandle res=rlist[ri];
-    this->AssignTorsionsToResidue(res);
-    if (!res.IsPeptideLinking()) {
-      return;
-    }
-    Builder::AssignBackBoneTorsionsToResidue(res);
-  }
-}
-
-void HeuristicBuilder::ConnectResidueToPrev(mol::ResidueHandle rh,
-                                            mol::ResidueHandle prev) {
-  ConnectPrevNext<false>(this, rh, prev);
-}
-
-void HeuristicBuilder::ConnectResidueToNext(mol::ResidueHandle rh,
-                                            mol::ResidueHandle next) {
-  ConnectPrevNext<true>(this, rh, next);
-}
-
-void HeuristicBuilder::FillResidueProps(mol::ResidueHandle residue) {
-  std::pair<detail::ConnResEntry,bool> ret = LookupResEntry(residue.GetKey());
-  if (ret.second) {
-    residue.SetChemClass(mol::ChemClass(ret.first.GetChemClass()));
-    residue.SetOneLetterCode(ret.first.GetOneLetterCode());    
-  } else {
-    if (residue.FindAtom("N") && residue.FindAtom("CA") && 
-        residue.FindAtom("C") && residue.FindAtom("O")) {
-      residue.SetChemClass(mol::ChemClass(mol::ChemClass::L_PEPTIDE_LINKING));
-    } else {
-      residue.SetChemClass(mol::ChemClass(mol::ChemClass::UNKNOWN));
-    }
-
-    residue.SetOneLetterCode('?');
-  }
-
-}
-
-std::pair<detail::ConnResEntry,bool> HeuristicBuilder::LookupResEntry(const mol::ResidueKey& key)
-{
-  static detail::ConnResEntry dummy;
-
-
-
-  detail::ConnResEntryMap::iterator pos = emap_.find(key);
-  if(pos!=emap_.end()) {
-    LOG_TRACE("reskey '" << key << "' found in connectivity map");
-    return std::make_pair(pos->second,true);
-  }
-  LOG_TRACE("reskey '" << key << "' not found connectivity map");
-  return std::make_pair(dummy,false);
-}
-
-bool HeuristicBuilder::IsResidueComplete(const mol::ResidueHandle& rh)
-{
-  std::pair<detail::ConnResEntry,bool> ret=LookupResEntry(rh.GetKey());  
-  if (!ret.second) {
-    // if the residue is unknown we return false...
-    return false;
-  }
-  for (std::vector<String>::const_iterator i=ret.first.GetReqAtoms().begin(),
-       e=ret.first.GetReqAtoms().end(); i!=e; ++i) {
-    if (!rh.FindAtom(*i)) {
-      return false;
-    }
-  }
-  return true;
-}
-
-void HeuristicBuilder::FillAtomProps(mol::AtomHandle atom)
-{
-  if (atom.GetElement()=="") {
-    atom.SetElement(Builder::GuessAtomElement(atom.GetName(), atom.IsHetAtom()));
-  }
-}
-
-}} // ns
diff --git a/modules/conop/src/heuristic_builder.hh b/modules/conop/src/heuristic_builder.hh
deleted file mode 100644
index 09a991345264b6031265c9bf2505a874f730daac..0000000000000000000000000000000000000000
--- a/modules/conop/src/heuristic_builder.hh
+++ /dev/null
@@ -1,127 +0,0 @@
-//------------------------------------------------------------------------------
-// This file is part of the OpenStructure project <www.openstructure.org>
-//
-// Copyright (C) 2008-2011 by the OpenStructure authors
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License as published by the Free
-// Software Foundation; either version 3.0 of the License, or (at your option)
-// any later version.
-// This library is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with this library; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//------------------------------------------------------------------------------
-#ifndef OST_CONOP_HEURISTIC_BUILDER_HH
-#define OST_CONOP_HEURISTIC_BUILDER_HH
-
-#include <set>
-#include <map>
-
-#include <ost/mol/chem_class.hh>
-
-#include "builder.hh"
-
-namespace ost { namespace conop {
-
-namespace detail {
-
-// internally used class
-class DLLEXPORT_OST_CONOP ConnResEntry {
-public:
-  typedef std::pair<String,String> NamePair;
-  typedef std::multiset<NamePair> PairSet;
-  struct TorsionEntry {
-    String a[4];
-    String name;
-  };
-  typedef std::vector<TorsionEntry> TorsionEntryList;
-
-public:
-  ConnResEntry(const String& rname="", char single='\0',
-               const mol::ChemClass& chem_class=mol::ChemClass(mol::ChemClass::UNKNOWN));
-  int Check(const String& name1, const String& name2) const;
-  bool HasAtom(const String& name);
-  void AddAtom(const String& atom) { required_atoms_.push_back(atom); }
-  void AddConn(const String& n1, const String& n2);
-  void AddTors(const String& a1, const String& a2,
-               const String& a3, const String& a4, const String& name);
-  void SetPrev(const String& n);
-  const String& GetPrev() const;
-  void SetNext(const String& n);
-  const String& GetNext() const;
-  TorsionEntryList GetTorsionList() const;
-  char GetOneLetterCode() const {return abbrev_;}
-  mol::ChemClass GetChemClass() const { return chem_class_; }
-  
-  std::vector<String> GetReqAtoms() const { return required_atoms_;}
-private:
-  mol::ResidueKey rkey_;
-  char       abbrev_;
-  mol::ChemClass  chem_class_;
-  PairSet pset_;
-  String prev_;
-  String next_;
-  std::vector<String> required_atoms_;
-  TorsionEntryList torsion_entry_list_;
-};
-
-typedef std::map<mol::ResidueKey,ConnResEntry> ConnResEntryMap;
-
-} // ns
-
-class DLLEXPORT_OST_CONOP HeuristicBuilder: public Builder {
-public:
-  HeuristicBuilder();
-  virtual ~HeuristicBuilder();
-
-  virtual void AssignTorsions(mol::ChainHandle ch);
-
-  //! \brief connect by using information in the heuristic connectivity table.
-  //
-  // This does not make any assumption on the correctness of internal or external
-  // coordinates. Only the atom names and residue need to be known.
-  virtual void ConnectAtomsOfResidue(mol::ResidueHandle rh);
-  
-  virtual bool IsResidueComplete(const mol::ResidueHandle& rh);
-//  virtual char GetOneLetterCode(const mol::ResidueKey& residue) const;
-
-  //!\brief connect to previous residue in chain.
-  virtual void ConnectResidueToPrev(mol::ResidueHandle rh, 
-                                    mol::ResidueHandle prev);
-  //!
-  virtual void AssignTorsionsToResidue(mol::ResidueHandle residue);
-
-  virtual void FillResidueProps(mol::ResidueHandle residue);
-
-  //!\brief connect to next residue in chain.
-  virtual void ConnectResidueToNext(mol::ResidueHandle rh, 
-                                    mol::ResidueHandle next);
-
-  //!\brief get connectivity table for residues
-  // Retrieve connectiviy information based on residue key. The returned
-  // \c pair->second is true, if an entry has been found and and false otherwise.
-  std::pair<detail::ConnResEntry,bool> LookupResEntry(const mol::ResidueKey& key);
-  
-  virtual void FillAtomProps(mol::AtomHandle atom);
-
-  const detail::ConnResEntry& DefaultPeptide() const {return default_peptide_;}
-  const detail::ConnResEntry& DefaultNucleotide() const {return default_nucleotide_;}
-protected:
-  void ConnectivityFromAtomNames(const mol::ResidueHandle& res,
-                                 detail::ConnResEntry& centry,
-                                 mol::AtomHandleList& unknown_atoms);
-private:
-  detail::ConnResEntryMap emap_;
-  detail::ConnResEntry default_peptide_;
-  detail::ConnResEntry default_nucleotide_;
-};
-
-
-}} // ns
-
-#endif
diff --git a/modules/conop/src/heuristic_connect_table.hh b/modules/conop/src/heuristic_connect_table.hh
deleted file mode 100644
index 15e0f1a25eeada4159f10cc60140eeaa4bea55fc..0000000000000000000000000000000000000000
--- a/modules/conop/src/heuristic_connect_table.hh
+++ /dev/null
@@ -1,304 +0,0 @@
-//------------------------------------------------------------------------------
-// This file is part of the OpenStructure project <www.openstructure.org>
-//
-// Copyright (C) 2008-2011 by the OpenStructure authors
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License as published by the Free
-// Software Foundation; either version 3.0 of the License, or (at your option)
-// any later version.
-// This library is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with this library; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//------------------------------------------------------------------------------
-#ifndef OST_HEURISTIC_CONNECT_TABLE_HH
-#define OST_HEURISTIC_CONNECT_TABLE_HH
-
-#include <string>
-
-namespace ost { namespace conop { namespace heuristic_connect {
-
-struct CONN_DEF_ENTRY {
-  char name[256];
-  char abbrev[16],single;
-  mol::ChemClass chem_class;
-  char name_list[48][8];
-  int name_count;
-  int conn_list[48][2];
-  int conn_count;
-  struct CONN_TORSION_TMP {
-    int n1,n2,n3,n4;
-    String name;
-  }tor_list[8];
-  int tor_count;
-  int flag_list[128];
-  int flag_count;
-};
-
-CONN_DEF_ENTRY def_entry_table[]={
-  // the first entry must be this generic one
-  {"Generic","___",'_', mol::ChemClass(mol::ChemClass::L_PEPTIDE_LINKING),
-   {"N","CA","C"},3,
-   {{-2,1}, {1,2}, {2,3}, {3,-3}},4,
-   {
-   },0,
-   {0, 0, 0, 0, 0, 0},6
-  },
-  {"Alanine","ALA",'A', mol::ChemClass(mol::ChemClass::L_PEPTIDE_LINKING),
-   {"N","CA","C","O","CB","OXT"},6,
-   {{-2,1}, {1,2}, {2,3}, {3,4}, {2,5}, {3,-3}, {6, 3}},7,
-   {
-   },0,
-   {0, 0, 0, 0, 0, 0},6
-  },
-  {"Cystein","CYS",'C', mol::ChemClass(mol::ChemClass::L_PEPTIDE_LINKING),
-   {"N","CA","C","O","CB","SG","OXT"},7,
-   {{-2,1},{1,2},{2,3},{3,4},{2,5},{5,6},{3,-3},{8, 3}},8,
-   {{1,2,5,6,"CHI1"}
-   },1,
-   {0, 0, 0, 0, 0, 0, 0},7
-  },
-  {"Aspartate","ASP",'D', mol::ChemClass(mol::ChemClass::L_PEPTIDE_LINKING),
-   {"N","CA","C","O","CB","CG","OD1","OD2","OXT"},9,
-   {{-2,1},{1,2},{2,3},{3,4},{2,5},{5,6},{6,7},{6,8},{3,-3},{9, 3}},10,
-   {
-    {1,2,5,6,"CHI1"},{2,5,6,7,"CHI2"}
-   },2,
-   {0, 0, 0, 0, 0, 0, 0, 0, 0},9
-  },
-  {"Glutamate","GLU",'E', mol::ChemClass(mol::ChemClass::L_PEPTIDE_LINKING),
-   {"N","CA","C","O","CB","CG","CD","OE1","OE2","OXT"},10,
-   {{-2,1},{1,2},{2,3},{3,4},{2,5},{5,6},{6,7},{7,8},{7,9},{3,-3},{10, 3}},11,
-   {
-    {1,2,5,6,"CHI1"},{2,5,6,7,"CHI2"},{5,6,7,8,"CHI3"}
-   },3,
-   {0},1
-  },
-  {"Phenylalanine","PHE",'F', mol::ChemClass(mol::ChemClass::L_PEPTIDE_LINKING),
-   {"N","CA","C","O","CB","CG","CD1","CD2","CE1","CE2","CZ","OXT"},12,
-   {{-2,1},{1,2},{2,3},{3,4},{2,5},{5,6},{6,7},{6,8},{7,9},{8,10},{9,11},{10,11},{3,-3},{12, 3}},14,
-   {
-    {1,2,5,6,"CHI1"},{2,5,6,7,"CHI2"}
-   },2,
-   {0},1
-  },
-  {"Glycin","GLY",'G', mol::ChemClass(mol::ChemClass::L_PEPTIDE_LINKING),
-   {"N","CA","C","O","OXT"},5,
-   {{-2,1},{1,2},{2,3},{3,4},{3,-3},{5, 3}},6,
-   {
-   },0,
-   {0},1
-  },
-  {"Histidine","HIS",'H', mol::ChemClass(mol::ChemClass::L_PEPTIDE_LINKING),
-   {"N","CA","C","O","CB","CG","ND1","CD2","CE1","NE2","OXT"},11,
-   {{-2,1},{1,2},{2,3},{3,4},{2,5},{5,6},{6,7},{6,8},{7,9},{8,10},{9,10},{3,-3},{11, 3}},13,
-   {
-    {1,2,5,6,"CHI1"},{2,5,6,7,"CHI2"}
-   },2,
-   {0},1
-  },
-  {"Isoleucine","ILE",'I', mol::ChemClass(mol::ChemClass::L_PEPTIDE_LINKING),
-   {"N","CA","C","O","CB","CG1","CG2","CD1","OXT"},9,
-   {{-2,1},{1,2},{2,3},{3,4},{2,5},{5,6},{5,7},{6,8},{3,-3},{9, 3}},10,
-   {
-    {1,2,5,6,"CHI1"},{2,5,6,8,"CHI2"}
-   },2,
-   {0},1
-  },
-  {"Lysin","LYS",'K', mol::ChemClass(mol::ChemClass::L_PEPTIDE_LINKING),
-   {"N","CA","C","O","CB","CG","CD","CE","NZ","OXT"},10,
-   {{-2,1},{1,2},{2,3},{3,4},{2,5},{5,6},{6,7},{7,8},{8,9},{3,-3},{10, 3}},11,
-   {
-    {1,2,5,6,"CHI1"},{2,5,6,7,"CHI2"},{5,6,7,8,"CHI3"},{6,7,8,9,"CHI4"}
-   },4,
-   {0},1
-  },
-  {"Leucin","LEU",'L', mol::ChemClass(mol::ChemClass::L_PEPTIDE_LINKING),
-   {"N","CA","C","O","CB","CG","CD1","CD2","OXT"},9,
-   {{-2,1},{1,2},{2,3},{3,4},{2,5},{5,6},{6,7},{6,8},{3,-3},{9, 3}},10,
-   {
-    {1,2,5,6,"CHI1"},{2,5,6,7,"CHI2"}
-   },2,
-   {0},1
-  },
-  {"Methionine","MET",'M', mol::ChemClass(mol::ChemClass::L_PEPTIDE_LINKING),
-   {"N","CA","C","O","CB","CG","SD","CE","OXT"},9,
-   {{-2,1},{1,2},{2,3},{3,4},{2,5},{5,6},{6,7},{7,8},{3,-3},{10, 3}},10,
-   {
-    {1,2,5,6,"CHI1"},{2,5,6,7,"CHI2"},{5,6,7,8,"CHI3"}
-   },3,
-   {0},1
-  },
-  {"Asparagine","ASN",'N', mol::ChemClass(mol::ChemClass::L_PEPTIDE_LINKING),
-   {"N","CA","C","O","CB","CG","OD1","ND2","OXT"},9,
-   {{-2,1},{1,2},{2,3},{3,4},{2,5},{5,6},{6,7},{6,8},{3,-3},{9, 3}},10,
-   {
-    {1,2,5,6,"CHI1"},{2,5,6,7,"CHI2"}
-   },2,
-   {0},1
-  },
-  {"Proline","PRO",'P', mol::ChemClass(mol::ChemClass::L_PEPTIDE_LINKING),
-   {"N","CA","C","O","CB","CG","CD","OXT"},8,
-   {{-2,1},{1,2},{2,3},{3,4},{2,5},{5,6},{6,7},{3,-3},{1,7},{8, 3}},10,
-   {
-    {1,2,5,6,"CHI1"},{2,5,6,7,"CHI2"}
-   },2,
-   {0},1
-  },
-  {"Glutamine","GLN",'Q', mol::ChemClass(mol::ChemClass::L_PEPTIDE_LINKING),
-   {"N","CA","C","O","CB","CG","CD","OE1","NE2","OXT"},10,
-   {{-2,1},{1,2},{2,3},{3,4},{2,5},{5,6},{6,7},{7,8},{7,9},{3,-3},{10, 3}},11,
-   {
-    {1,2,5,6,"CHI1"},{2,5,6,7,"CHI2"},{5,6,7,8,"CHI3"}
-   },3,
-   {0},1
-  },
-  {"Arginine","ARG",'R', mol::ChemClass(mol::ChemClass::L_PEPTIDE_LINKING),
-   {"N","CA","C","O","CB","CG","CD","NE","CZ","NH1","NH2","OXT"},12,
-   {{-2,1},{1,2},{2,3},{3,4},{2,5},{5,6},{6,7},{7,8},{8,9},{9,10},{9,11},{3,-3},{12, 3}},13,
-   {
-   {1,2,5,6,"CHI1"},{2,5,6,7,"CHI2"},{5,6,7,8,"CHI3"},{6,7,8,9,"CHI4"},{7,8,9,10,"CHI5"}
-   },5,
-   {0},1
-  },
-  {"Serine","SER",'S', mol::ChemClass(mol::ChemClass::L_PEPTIDE_LINKING),
-   {"N","CA","C","O","CB","OG","OXT"},7,
-   {{-2,1},{1,2},{2,3},{3,4},{2,5},{5,6},{3,-3},{7, 3}},8,
-   {
-    {1,2,5,6,"CHI1"}
-   },1,
-   {0},1
-  },
-  {"Threonine","THR",'T', mol::ChemClass(mol::ChemClass::L_PEPTIDE_LINKING),
-   {"N","CA","C","O","CB","OG1","CG2","OXT"},8,
-   {{-2,1},{1,2},{2,3},{3,4},{2,5},{5,6},{5,7},{3,-3},{8, 3}},9,
-   {
-    {1,2,5,6,"CHI1"}
-   },1,
-   {0},1
-  },
-  {"Valine","VAL",'V', mol::ChemClass(mol::ChemClass::L_PEPTIDE_LINKING),
-   {"N","CA","C","O","CB","CG1","CG2","OXT"},8,
-   {{-2,1},{1,2},{2,3},{3,4},{2,5},{5,6},{5,7},{3,-3},{8, 3}},9,
-   {
-    {1,2,5,6,"CHI1"}
-   },1,
-   {0},1
-  },
-  {"Tryptophan","TRP",'W', mol::ChemClass(mol::ChemClass::L_PEPTIDE_LINKING),
-   {"N","CA","C","O","CB","CG","CD1","CD2","NE1","CE2","CE3","CZ2","CZ3","CH2","OXT"},15,
-   {{-2,1},{1,2},{2,3},{3,4},{2,5},{5,6},{6,7},{6,8},{7,9},{8,10},{9,10},{8,11},{10,12},{11,13},{12,14},{13,14},{3,-3},{15, 3}},18,
-   {
-    {1,2,5,6,"CHI1"},{2,5,6,7,"CHI2"}
-   },2,
-   {0},1
-  },
-  {"Tyrosin","TYR",'Y', mol::ChemClass(mol::ChemClass::L_PEPTIDE_LINKING),
-   {"N","CA","C","O","CB","CG","CD1","CD2","CE1","CE2","CZ","OH","OXT"},13,
-   {{-2,1},{1,2},{2,3},{3,4},{2,5},{5,6},{6,7},{6,8},{7,9},{8,10},{9,11},{10,11},{11,12},{3,-3},{13, 3}},15,
-   {
-    {1,2,5,6,"CHI1"},{2,5,6,7,"CHI2"}
-   },2,
-   {0},1
-  },
-  /* NUCLEIC ACIDS */
-  {"Adenosin","A",'?', mol::ChemClass(mol::ChemClass::DNA_LINKING),
-   {"P","O5'","C5'","C4'","O4'","C3'","O3'","C2'","C1'","O1P","O2P","N9","C8","N7","C5","C6","N6","N1","C2","N3","C4","O2'"},12,
-   {{-2,1},{1,2},{2,3},{3,4},{4,5},{4,6},{6,7},{6,8},{8,9},{5,9},{1,10},{1,11},{8,22},{7,-3}},14,
-   {{0,0,0,0,""}},1,
-   {0},1
-  },
-  {"Cytosin","C",'?', mol::ChemClass(mol::ChemClass::DNA_LINKING),
-   {"P","O5'","C5'","C4'","O4'","C3'","O3'","C2'","C1'","O1P","O2P","O2'"},12,
-   {{-2,1},{1,2},{2,3},{3,4},{4,5},{4,6},{6,7},{6,8},{8,9},{5,9},{1,10},{1,11},{8,12},{7,-3}},14,
-   {{0,0,0,0,""}},1,
-   {0},1
-  },
-  {"Guanidin","G",'?', mol::ChemClass(mol::ChemClass::DNA_LINKING),
-   {"P","O5'","C5'","C4'","O4'","C3'","O3'","C2'","C1'","O1P","O2P","O2'"},12,
-   {{-2,1},{1,2},{2,3},{3,4},{4,5},{4,6},{6,7},{6,8},{8,9},{5,9},{7,-3},{1,10},{1,11},{8,12}},14,
-   {{0,0,0,0,""}},1,
-   {0},1
-  },
-  {"Thymidin","T",'?', mol::ChemClass(mol::ChemClass::DNA_LINKING),
-   {"P","O5'","C5'","C4'","O4'","C3'","O3'","C2'","C1'","O1P","O2P","O2'"},12,
-   {{-2,1},{1,2},{2,3},{3,4},{4,5},{4,6},{6,7},{6,8},{8,9},{5,9},{7,-3},{1,10},{8,12},{1,11}},15,
-   {{0,0,0,0,""}},1,
-   {0},1
-  },
-  {"Uracil","U",'?', mol::ChemClass(mol::ChemClass::DNA_LINKING),
-   {"P","O5'","C5'","C4'","O4'","C3'","O3'","C2'","C1'","O1P","O2P","O2'"},12,
-   {{-2,1},{1,2},{2,3},{3,4},{4,5},{4,6},{6,7},{6,8},{8,9},{5,9},{7,-3},{1,10},{1,11},{8,12}},14,
-   {{0,0,0,0,""}},1,
-   {0},1
-  },
-  {"Adenosin","ADE",'?', mol::ChemClass(mol::ChemClass::DNA_LINKING),
-   {"P","O5'","C5'","C4'","O4'","C3'","O3'","C2'","C1'","O1P","O2P","N9","C8","N7","C5","C6","N6","N1","C2","N3","C4","O2'"},12,
-   {{-2,1},{1,2},{2,3},{3,4},{4,5},{4,6},{6,7},{6,8},{8,9},{5,9},{1,10},{1,11},{8,22},{9,12},{7,-3}},15,
-   {{0,0,0,0,""}},1,
-   {0},1
-  },
-  {"Cytosin","CYT",'?', mol::ChemClass(mol::ChemClass::DNA_LINKING),
-   {"P","O5'","C5'","C4'","O4'","C3'","O3'","C2'","C1'","O1P","O2P","O2'"},12,
-   {{-2,1},{1,2},{2,3},{3,4},{4,5},{4,6},{6,7},{6,8},{8,9},{5,9},{1,10},{1,11},{8,12},{7,-3}},14,
-   {{0,0,0,0,""}},1,
-   {0},1
-  },
-  {"Guanidin","GUA",'?', mol::ChemClass(mol::ChemClass::DNA_LINKING),
-   {"P","O5'","C5'","C4'","O4'","C3'","O3'","C2'","C1'","O1P","O2P","O2'"},12,
-   {{-2,1},{1,2},{2,3},{3,4},{4,5},{4,6},{6,7},{6,8},{8,9},{5,9},{7,-3},{1,10},{1,11},{8,12}},14,
-   {{0,0,0,0,""}},1,
-   {0},1
-  },
-  {"Thymidin","THY",'?', mol::ChemClass(mol::ChemClass::DNA_LINKING),
-   {"P","O5'","C5'","C4'","O4'","C3'","O3'","C2'","C1'","O1P","O2P","O2'"},12,
-   {{-2,1},{1,2},{2,3},{3,4},{4,5},{4,6},{6,7},{6,8},{8,9},{5,9},{7,-3},{1,10},{8,12},{1,11}},15,
-   {{0,0,0,0,""}},1,
-   {0},1
-  },
-  {"Uracil","URI",'?', mol::ChemClass(mol::ChemClass::DNA_LINKING),
-   {"P","O5'","C5'","C4'","O4'","C3'","O3'","C2'","C1'","O1P","O2P","O2'"},12,
-   {{-2,1},{1,2},{2,3},{3,4},{4,5},{4,6},{6,7},{6,8},{8,9},{5,9},{7,-3},{1,10},{1,11},{8,12}},14,
-   {{0,0,0,0,""}},1,
-   {0},1
-  },
-  {"Adenosin","DA",'?', mol::ChemClass(mol::ChemClass::DNA_LINKING),
-   {"P","O5'","C5'","C4'","O4'","C3'","O3'","C2'","C1'","O1P","O2P","N9","C8","N7","C5","C6","N6","N1","C2","N3","C4","O2'"},12,
-   {{-2,1},{1,2},{2,3},{3,4},{4,5},{4,6},{6,7},{6,8},{8,9},{5,9},{1,10},{1,11},{8,22},{9,12},{7,-3}},15,
-   {{0,0,0,0,""}},1,
-   {0},1
-  },
-  {"Cytosin","DC",'?', mol::ChemClass(mol::ChemClass::DNA_LINKING),
-   {"P","O5'","C5'","C4'","O4'","C3'","O3'","C2'","C1'","O1P","O2P","O2'"},12,
-   {{-2,1},{1,2},{2,3},{3,4},{4,5},{4,6},{6,7},{6,8},{8,9},{5,9},{1,10},{1,11},{8,12},{7,-3}},14,
-   {{0,0,0,0,""}},1,
-   {0},1
-  },
-  {"Guanidin","DG",'?', mol::ChemClass(mol::ChemClass::DNA_LINKING),
-   {"P","O5'","C5'","C4'","O4'","C3'","O3'","C2'","C1'","O1P","O2P","O2'"},12,
-   {{-2,1},{1,2},{2,3},{3,4},{4,5},{4,6},{6,7},{6,8},{8,9},{5,9},{7,-3},{1,10},{1,11},{8,12}},14,
-   {{0,0,0,0,""}},1,
-   {0},1
-  },
-  {"Thymidin","DT",'?', mol::ChemClass(mol::ChemClass::DNA_LINKING),
-   {"P","O5'","C5'","C4'","O4'","C3'","O3'","C2'","C1'","O1P","O2P","O2'"},12,
-   {{-2,1},{1,2},{2,3},{3,4},{4,5},{4,6},{6,7},{6,8},{8,9},{5,9},{7,-3},{1,10},{8,12},{1,11}},15,
-   {{0,0,0,0,""}},1,
-   {0},1
-  },
-  {"Uracil","DU",'?', mol::ChemClass(mol::ChemClass::DNA_LINKING),
-   {"P","O5'","C5'","C4'","O4'","C3'","O3'","C2'","C1'","O1P","O2P","O2'"},12,
-   {{-2,1},{1,2},{2,3},{3,4},{4,5},{4,6},{6,7},{6,8},{8,9},{5,9},{7,-3},{1,10},{1,11},{8,12}},14,
-   {{0,0,0,0,""}},1,
-   {0},1
-  }
-};
-
-}}} // ns
-
-#endif
diff --git a/modules/conop/src/minimal_compound_lib.cc b/modules/conop/src/minimal_compound_lib.cc
new file mode 100644
index 0000000000000000000000000000000000000000..9eeb107539e70a34bcdfe9f66ec4917d8b2bcc56
--- /dev/null
+++ b/modules/conop/src/minimal_compound_lib.cc
@@ -0,0 +1,54 @@
+#include "minimal_compound_lib.hh"
+namespace ost { namespace conop {
+
+#include "standard_compounds.cc"
+
+CompoundMap MinimalCompoundLib::compounds_ = MinimalCompoundLib::InitCompounds();
+
+CompoundMap MinimalCompoundLib::InitCompounds() {
+  CompoundMap c;
+  c["ALA"] = MakeALACompound();
+  c["CYS"] = MakeCYSCompound();
+  c["ASP"] = MakeASPCompound();
+  c["GLU"] = MakeGLUCompound();
+  c["PHE"] = MakePHECompound();
+  c["GLY"] = MakeGLYCompound();
+  c["HIS"] = MakeHISCompound();
+  c["ILE"] = MakeILECompound();
+  c["LYS"] = MakeLYSCompound();
+  c["LEU"] = MakeLEUCompound();
+  c["MET"] = MakeMETCompound();
+  c["ASN"] = MakeASNCompound();
+  c["PRO"] = MakePROCompound();
+  c["GLN"] = MakeGLNCompound();
+  c["ARG"] = MakeARGCompound();
+  c["SER"] = MakeSERCompound();
+  c["THR"] = MakeTHRCompound();
+  c["VAL"] = MakeVALCompound();
+  c["TRP"] = MakeTRPCompound();
+  c["TYR"] = MakeTYRCompound();
+  c["G"] = MakeGCompound();
+  c["T"] = MakeTCompound();
+  c["A"] = MakeACompound();
+  c["C"] = MakeCCompound();
+  c["U"] = MakeUCompound();
+  c["DG"] = MakeDGCompound();
+  c["DT"] = MakeDTCompound();
+  c["DU"] = MakeDUCompound();
+  c["DC"] = MakeDCCompound();
+  c["DA"] = MakeDACompound();
+  return c;
+}
+
+
+CompoundPtr MinimalCompoundLib::FindCompound(const String& id, 
+                                             Compound::Dialect dialect) const
+{
+   CompoundMap::const_iterator i = MinimalCompoundLib::compounds_.find(id); 
+   if (i != MinimalCompoundLib::compounds_.end()) {
+     return i->second;
+   }
+   return CompoundPtr();
+}
+
+}}
diff --git a/modules/conop/src/minimal_compound_lib.hh b/modules/conop/src/minimal_compound_lib.hh
new file mode 100644
index 0000000000000000000000000000000000000000..208011545b6c7405c932207fdb2f5b2d83b4c289
--- /dev/null
+++ b/modules/conop/src/minimal_compound_lib.hh
@@ -0,0 +1,28 @@
+
+#ifndef OST_CONOP_MINIMAL_COMPOUND_LIB_HH
+#define OST_CONOP_MINIMAL_COMPOUND_LIB_HH
+
+#include "compound_lib_base.hh"
+
+namespace ost { namespace conop {
+
+class MinimalCompoundLib;
+typedef boost::shared_ptr<MinimalCompoundLib> MinimalCompoundLibPtr;
+
+// a minimal compound lib containing the definitions of the 20 standard 
+// amino acids and standard nucleotides
+class DLLEXPORT_OST_CONOP MinimalCompoundLib : public CompoundLibBase {
+public:
+  MinimalCompoundLib() {}
+  virtual CompoundPtr FindCompound(const String& id, 
+                                   Compound::Dialect dialect) const;
+private:
+  static CompoundMap InitCompounds();
+  // since this information is never going to change, it is shared 
+  // between instances of minimal compound lib.
+  static CompoundMap compounds_;
+};
+
+
+}}
+#endif
diff --git a/modules/conop/src/model_check.hh b/modules/conop/src/model_check.hh
index 3e56f45e97de7929177d5016396e15ecb821fcba..aedd7a0f54155d789bdde1766d72a4b7a1210936 100644
--- a/modules/conop/src/model_check.hh
+++ b/modules/conop/src/model_check.hh
@@ -9,21 +9,19 @@ namespace ost { namespace conop {
 class DLLEXPORT_OST_CONOP Checker {
 public:
   Checker(CompoundLibPtr lib, const mol::EntityHandle& ent,
-          DiagEngine& diags): lib_(lib), ent_(ent), diags_(diags),
-                              checked_unk_res_(false),
-                              residues_(ent_.GetResidueList())
-  { }
+          Diagnostics& diags): lib_(lib), ent_(ent), diags_(diags),
+          checked_unk_res_(false), residues_(ent_.GetResidueList())
+  {}
   void CheckForUnknownAtoms();
   void CheckForCompleteness(bool require_hydrogens=false);
   void CheckForNonStandard();
   mol::AtomHandleList GetHydrogens();
   mol::AtomHandleList GetZeroOccupancy();
   
-  const std::vector<Diag*>& GetDiags() const {  return diags_.GetDiags(); }
 private:
   CompoundLibPtr            lib_;
   mol::EntityHandle         ent_;
-  DiagEngine&               diags_;
+  Diagnostics&              diags_;
   bool                      checked_unk_res_;
   mol::ResidueHandleList    residues_;
 };
diff --git a/modules/conop/src/nonstandard.cc b/modules/conop/src/nonstandard.cc
index eeccdb60d16425dd1107629e41fb075100a7c0c3..eaf06680d087c05080f0e578828c7bad3fd68c66 100644
--- a/modules/conop/src/nonstandard.cc
+++ b/modules/conop/src/nonstandard.cc
@@ -26,7 +26,6 @@
 #include <ost/conop/conop.hh>
 #include <ost/mol/mol.hh>
 #include <ost/mol/alg/construct_cbeta.hh>
-#include <ost/conop/rule_based_builder.hh>
 #include <ost/conop/compound_lib.hh>
 #include "nonstandard.hh"
 using namespace ost::mol;
@@ -39,18 +38,19 @@ namespace ost { namespace conop {
 bool CopyResidue(ResidueHandle src_res, ResidueHandle dst_res, XCSEditor& edi)
 {
   // first let's get our hands on the component library
-  conop::BuilderP builder=conop::Conopology::Instance().GetBuilder("DEFAULT");
-  conop::RuleBasedBuilderPtr rbb=dyn_cast<conop::RuleBasedBuilder>(builder);
-  conop::CompoundLibPtr comp_lib=rbb->GetCompoundLib(); 
+  conop::CompoundLibPtr comp_lib=conop::Conopology::Instance().GetDefaultLib();
   return CopyResidue(src_res, dst_res, edi, comp_lib); 
 }
 
-bool CopyResidue(ResidueHandle src_res, ResidueHandle dst_res, XCSEditor& edi, CompoundLibPtr comp_lib)
+bool CopyResidue(ResidueHandle src_res, ResidueHandle dst_res, 
+                 XCSEditor& edi, CompoundLibPtr comp_lib)
 {
   bool has_cbeta = false;
   bool ret;
-  char parent_src = (comp_lib->FindCompound(src_res.GetName(),Compound::PDB))->GetOneLetterCode ();  
-  char parent_dst = (comp_lib->FindCompound(dst_res.GetName(),Compound::PDB))->GetOneLetterCode ();  
+  char parent_src = (comp_lib->FindCompound(src_res.GetName(),
+                                            Compound::PDB))->GetOneLetterCode ();  
+  char parent_dst = (comp_lib->FindCompound(dst_res.GetName(),
+                                            Compound::PDB))->GetOneLetterCode ();  
   if (parent_src==parent_dst) {
     ret = CopyConserved(src_res, dst_res, edi, has_cbeta, comp_lib);
   } else {
@@ -69,9 +69,7 @@ bool CopyConserved(ResidueHandle src_res, ResidueHandle dst_res, XCSEditor& edi,
                    bool& has_cbeta)
 {
   // first let's get our hands on the component library
-  conop::BuilderP builder=conop::Conopology::Instance().GetBuilder("DEFAULT");
-  conop::RuleBasedBuilderPtr rbb=dyn_cast<conop::RuleBasedBuilder>(builder);
-  conop::CompoundLibPtr comp_lib=rbb->GetCompoundLib(); 
+  conop::CompoundLibPtr comp_lib=conop::Conopology::Instance().GetDefaultLib();
   return CopyConserved(src_res,dst_res,edi,has_cbeta,comp_lib);
 }
 
diff --git a/modules/conop/src/processor.cc b/modules/conop/src/processor.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d8f5c269837dd4f38a892b5fc8996ee4e9986656
--- /dev/null
+++ b/modules/conop/src/processor.cc
@@ -0,0 +1,455 @@
+//------------------------------------------------------------------------------
+// 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 <limits>
+#include <ost/log.hh>
+#include <ost/mol/xcs_editor.hh>
+#include <ost/mol/bond_handle.hh>
+#include <ost/mol/torsion_handle.hh>
+#include <ost/mol/impl/residue_impl.hh>
+#include <ost/mol/impl/atom_impl.hh>
+#include <ost/mol/residue_handle.hh>
+#include "processor.hh"
+
+namespace ost { namespace conop {
+
+struct OrdinalAtomComp {
+  bool operator()(const mol::impl::AtomImplPtr& a,
+                  const mol::impl::AtomImplPtr& b) const {
+    return a->GetState()<b->GetState();
+  }
+};
+DiagnosticsPtr Processor::Process(mol::EntityHandle ent, 
+                                  bool log_diags) const
+{
+  DiagnosticsPtr diags(new Diagnostics);
+  if (!this->BeginProcessing(diags, ent)) {
+    return diags;
+  }
+  this->DoProcess(diags, ent);
+  
+  this->EndProcessing(diags, ent);
+  if (log_diags) {
+    for (Diagnostics::diag_iterator i = diags->diags_begin(),
+         e = diags->diags_end(); i != e; ++i) {
+      LOG_WARNING((*i)->Format(false));
+    }
+  }
+  return diags;
+}
+
+void AssignBackboneTorsions(mol::ChainHandle chain)
+{
+  AssignBackboneTorsions(chain.GetResidueList());
+}
+
+void AssignBackboneTorsions(mol::ResidueHandleList residues)
+{
+  if (residues.empty()) { return; }
+  mol::ResidueHandle r1;
+  mol::ResidueHandle r2;
+  mol::ResidueHandle r3 = residues.front();
+  for (mol::ResidueHandleList::iterator 
+        j = residues.begin()+1, e2 = residues.end(); j != e2; ++j) {
+    r1 = r2;
+    r2 = r3;
+    r3 = *j;
+    AssignBackboneTorsions(r1, r2, r3); 
+  }
+  AssignBackboneTorsions(r2, r3, mol::ResidueHandle());
+}
+
+
+void AssignBackboneTorsions(mol::ResidueHandle prev, 
+                            mol::ResidueHandle res, 
+                            mol::ResidueHandle next)
+{
+
+  mol::XCSEditor e=res.GetEntity().EditXCS(mol::BUFFERED_EDIT);
+  //psi
+  if (next.IsValid() && next.IsPeptideLinking()){
+    mol::AtomHandle ca_this=res.FindAtom("CA");
+    mol::AtomHandle n_this=res.FindAtom("N");
+    mol::AtomHandle c_this=res.FindAtom("C");
+    mol::AtomHandle n_next=next.FindAtom("N");
+    if ((ca_this && n_this && c_this && n_next &&  BondExists(c_this, n_next))
+        && !res.GetPsiTorsion()) {
+      e.AddTorsion("PSI", n_this, ca_this, c_this, n_next);
+    }
+  };
+  //phi
+  if (prev.IsValid() && prev.IsPeptideLinking()) {
+    mol::AtomHandle c_prev=prev.FindAtom("C");
+    mol::AtomHandle n_this=res.FindAtom("N");
+    mol::AtomHandle ca_this=res.FindAtom("CA");
+    mol::AtomHandle c_this=res.FindAtom("C");
+    if ((c_prev && n_this && ca_this && c_this && BondExists(c_prev, n_this))
+        && !res.GetPhiTorsion()) {
+      e.AddTorsion("PHI", c_prev, n_this, ca_this, c_this);
+    }
+  }
+  //omega
+  if (prev.IsValid() && prev.IsPeptideLinking()) {
+    mol::AtomHandle ca_prev=prev.FindAtom("CA");
+    mol::AtomHandle c_prev=prev.FindAtom("C");
+    mol::AtomHandle n=res.FindAtom("N");
+    mol::AtomHandle ca=res.FindAtom("CA");
+    if ((ca_prev && c_prev && n && ca && BondExists(c_prev, n))
+        && !res.GetOmegaTorsion()) {
+      e.AddTorsion("OMEGA",ca_prev , c_prev, n, ca);
+    }
+  }
+} 
+mol::ChemClass GuessChemClass(mol::ResidueHandle res)
+{
+  mol::AtomHandle ca=res.FindAtom("CA");
+  if (!ca.IsValid() || ca.GetElement()!="C") return mol::ChemClass();
+  mol::AtomHandle n=res.FindAtom("N");
+  if (!n.IsValid() || n.GetElement()!="N") return mol::ChemClass();
+  mol::AtomHandle c=res.FindAtom("C");
+  if (!c.IsValid() || c.GetElement()!="C") return mol::ChemClass();
+  mol::AtomHandle o=res.FindAtom("O");
+  if (!o.IsValid() || o.GetElement()!="O") return mol::ChemClass();
+  if (IsBondFeasible(n, ca) && IsBondFeasible(ca, c) &&
+      IsBondFeasible(c, o)) {
+    return mol::ChemClass(mol::ChemClass::PEPTIDE_LINKING);
+  }
+  return mol::ChemClass();
+}
+String GuessAtomElement(const String& aname, bool hetatm)
+{
+  static String l1[] = {
+    "H","C","N","O","P","S","K"
+  };
+  static int l1c=7;
+  static String l2[] = {
+    "NA","MG","AL","SI","CL",
+    "CA","CR","MN","FE","CO","NI","CU","ZN","AS","SE","BR","MO"
+  };
+  static int l2c=17;
+  static String l3[] = {
+    "B","F","V"
+  };
+  static int l3c=3;
+  static String l4[] = {
+    "HE","LI","BE","AR","SC","TI","GA","GE","KR"
+  };
+  static int l4c=9;
+
+  String ele=aname.substr(0,2);
+  // hydrogen hack
+  if(ele[0]=='H') {
+    return "H";
+  }
+  if (hetatm==false) {
+    if (ele=="CA" || ele=="CB") {
+      return "C";
+    }
+  }
+
+  // two characters
+  if(aname.size()==2) {
+    for(int i=0;i<l2c;i++) {
+      if(ele==l2[i]) return ele;
+    }
+    // check second character for match
+    for(int i=0;i<l1c;i++) {
+      if(ele[1]==l1[i][0]) {
+        return l1[i];
+      }
+    }
+    // still no match, repeat with less likely tables
+    for(int i=0;i<l4c;i++) {
+      if(ele==l4[i]) return ele;
+    }
+    // check second character for match
+    for(int i=0;i<l3c;i++) {
+      if(ele[1]==l3[i][0]) {
+        return l3[i];
+      }
+    }
+    // check second character for match
+    for(int i=0;i<l1c;i++) {
+      if(ele[0]==l1[i][0]) {
+        return l1[i];
+      }
+    }
+  } else {
+    for(int i=0;i<l1c;i++) {
+      if(ele==l1[i]) return ele;
+    }
+    for(int i=0;i<l3c;i++) {
+      if(ele==l3[i]) return ele;
+    }
+  }
+  size_t i=0;
+  while (i<aname.size() && isdigit(aname[i])) {
+    ++i;
+  }
+  return i<aname.size() ? String(1, aname[i]) : "";
+}
+
+bool IsBondFeasible(const mol::AtomHandle& atom_a,
+                    const mol::AtomHandle& atom_b)
+{
+  Real radii=0.0;
+  if (atom_a.GetRadius()>0.0) {
+    radii=atom_a.GetRadius();
+  } else {
+    return false;
+  }
+  if (atom_b.GetRadius()>0.0) {
+    radii+=atom_b.GetRadius();
+  } else {
+    return false;
+  } 
+  Real len=geom::Length2(atom_a.GetPos()-atom_b.GetPos());
+  Real lower_bound=radii*radii*0.0625;
+  Real upper_bound=lower_bound*6.0;
+  return (len<=upper_bound && len>=lower_bound);
+}
+
+void Processor::ConnectResidues(mol::ResidueHandle rh,
+                                mol::ResidueHandle next) const
+{
+  if (!next.IsValid() || !rh.IsValid()) {
+    return;
+  }
+
+  mol::XCSEditor e=rh.GetEntity().EditXCS(mol::BUFFERED_EDIT);
+
+  // check if both of the residues are able to form a peptide bond.
+  if (rh.IsPeptideLinking() && next.IsPeptideLinking()) {
+    // If we have an OXT then there is no peptide bond connecting the two
+    // residues.
+    if (rh.FindAtom("OXT"))
+      return;
+    mol::AtomHandle c=rh.FindAtom("C");
+    mol::AtomHandle n=next.FindAtom("N");
+    // Give subclasses a chance to give us their opinions on the feasibility of
+    // the peptide bond.
+    if (c.IsValid() && n.IsValid() && IsBondFeasible(c, n)) {
+      e.Connect(c, n, 1);
+      rh.SetIsProtein(true);
+      next.SetIsProtein(true);
+    }
+  } else if (rh.IsNucleotideLinking() && next.IsNucleotideLinking()) {
+    mol::AtomHandle c=rh.FindAtom("O3'");
+    mol::AtomHandle n=next.FindAtom("P");
+    if (c.IsValid() && n.IsValid() && IsBondFeasible(c, n)) {
+      e.Connect(c, n, 1);
+    }
+  }
+}
+
+
+mol::AtomHandle Processor::LocateAtom(const mol::AtomHandleList& ahl, 
+                                      int ordinal) const
+{
+  if (ahl.empty())
+    return mol::AtomHandle();
+  const mol::AtomHandle* r_it=&ahl.back();
+  if (static_cast<int>(ahl.size())>ordinal) {
+    r_it=&ahl.front()+ordinal;
+  }
+  while ((r_it>=&ahl.front()) &&
+         (static_cast<int>(r_it->Impl()->GetState())>ordinal)) {
+    --r_it;
+  }
+  bool not_found=(r_it<&ahl.front() ||
+                 static_cast<int>(r_it->Impl()->GetState())!=ordinal);
+  return  not_found ? mol::AtomHandle() : *r_it;
+}
+
+void Processor::FillResidueProps(mol::ResidueHandle residue,
+                                 CompoundPtr compound) const
+{
+  residue.SetChemClass(compound->GetChemClass());
+  residue.SetChemType(compound->GetChemType());
+  residue.SetOneLetterCode(compound->GetOneLetterCode());
+}
+
+void Processor::ConnectAtomsOfResidue(mol::ResidueHandle rh, 
+                                      CompoundPtr compound,
+                                      bool strict_hydrogens) const
+{
+
+  //if (!compound) {
+  //  dist_connect(this, rh.GetAtomList());
+  //  return;
+  //}
+  //if (unknown_atoms_) {
+  //  dist_connect(this, rh.GetAtomList());
+  //  return;
+  //}
+  mol::XCSEditor e=rh.GetEntity().EditXCS(mol::BUFFERED_EDIT);
+  BondSpecList::const_iterator j=compound->GetBondSpecs().begin();
+  mol::AtomHandleList atoms=rh.GetAtomList();
+  for(; j!=compound->GetBondSpecs().end(); ++j) {
+      const BondSpec& bond=*j;
+      mol::AtomHandle a1=this->LocateAtom(atoms, bond.atom_one);
+      mol::AtomHandle a2=this->LocateAtom(atoms, bond.atom_two);
+      if (a1.IsValid() && a2.IsValid()) { 
+        if (!this->GetCheckBondFeasibility()) {
+          if (strict_hydrogens && (a1.GetElement()=="H" || 
+                                   a2.GetElement()=="D")) {
+            continue;
+          }
+          e.Connect(a1, a2, bond.order);
+        } else { 
+          if (IsBondFeasible(a1, a2)) {
+            if (strict_hydrogens && (a1.GetElement()=="H" || 
+                                     a2.GetElement()=="D")) {
+              continue;
+            }
+            e.Connect(a1, a2, bond.order);
+          }
+        }
+      }
+  }
+}
+
+
+void Processor::ReorderAtoms(mol::ResidueHandle residue, 
+                             CompoundPtr compound, 
+                             bool fix_element) const
+{
+  mol::impl::ResidueImplPtr impl=residue.Impl();
+  mol::impl::AtomImplList::iterator i=impl->GetAtomList().begin();
+  for (; i!=impl->GetAtomList().end(); ++i) {
+    mol::impl::AtomImplPtr atom=*i;
+    atom->SetState(std::numeric_limits<unsigned int>::max());
+    int index=compound->GetAtomSpecIndex(atom->GetName());
+    if (index==-1) {
+      atom->SetState(std::numeric_limits<unsigned int>::max());
+      continue;
+    }
+    atom->SetState((compound->GetAtomSpecs())[index].ordinal);
+    // override element
+    if (fix_element) {
+      atom->SetElement((compound->GetAtomSpecs())[index].element);
+    }
+  }
+  std::sort(impl->GetAtomList().begin(), impl->GetAtomList().end(),
+            OrdinalAtomComp());
+}
+
+bool Processor::HasUnknownAtoms(mol::ResidueHandle res, 
+                                CompoundPtr compound,
+                                bool strict_hydrogens) const 
+{
+  AtomSpecList::const_iterator j=compound->GetAtomSpecs().begin();
+  mol::AtomHandleList atoms=res.GetAtomList();
+  mol::AtomHandleList::iterator i=atoms.begin();
+  for (mol::AtomHandleList::iterator 
+       i=atoms.begin(), e=atoms.end(); i!=e; ++i) {
+    if ((*i).Impl()->GetState()==std::numeric_limits<unsigned int>::max()) {
+      if (((*i).GetElement()=="H" || (*i).GetElement()=="D") && 
+          !strict_hydrogens) {
+        continue;
+      }
+      return true;
+    }
+  }
+  return false;
+}
+
+mol::AtomHandleList GetUnknownAtomsOfResidue(mol::ResidueHandle res, 
+                                             CompoundPtr compound,
+                                             bool strict_hydrogens)
+{
+  mol::AtomHandleList atoms=res.GetAtomList();
+  mol::AtomHandleList unks;
+  const AtomSpecList& atom_specs=compound->GetAtomSpecs();
+  for (mol::AtomHandleList::const_iterator
+        j=atoms.begin(), e2=atoms.end(); j!=e2; ++j) {
+    bool found=false;
+    for (AtomSpecList::const_iterator
+          k=atom_specs.begin(), e3=atom_specs.end(); k!=e3; ++k) {
+      if (k->name==j->GetName() || k->alt_name==j->GetName()) {
+        found=true;
+        break;
+      }
+    }
+    if (!found) {
+      unks.push_back(*j);
+    }
+  }
+  return unks;
+}
+
+void Processor::DistanceBasedConnect(mol::AtomHandle atom) const
+{
+  mol::EntityHandle ent=atom.GetEntity();
+  mol::XCSEditor editor=ent.EditXCS(mol::BUFFERED_EDIT);
+  mol::AtomHandleList alist = ent.FindWithin(atom.GetPos(),4.0);
+  mol::ResidueHandle res_a=atom.GetResidue();
+  for (mol::AtomHandleList::const_iterator it=alist.begin(),
+       e=alist.end();it!=e;++it) {
+    if (*it!=atom) {
+      if (IsBondFeasible(atom, *it)) {
+        if (Processor::AreResiduesConsecutive(res_a, it->GetResidue()) || 
+            it->GetResidue()==res_a) {                      
+            editor.Connect(*it, atom);
+        }
+      }
+    }
+  }
+}
+
+String StringFromConopAction(ConopAction action) {
+  switch (action) {
+    case CONOP_FATAL:
+      return "fatal";
+    case CONOP_SILENT:
+      return "silent";
+    case CONOP_REMOVE:
+      return "rm";
+    case CONOP_REMOVE_RESIDUE:
+      return "rm_residue";
+    case CONOP_REMOVE_ATOM:
+      return "rm_atom";
+    case CONOP_WARN:
+      return "warn";
+  }
+  assert(0 && "unhandled conop action");
+  return "unhandled conop action";
+}
+
+bool Processor::AreResiduesConsecutive(mol::ResidueHandle r1, 
+                                       mol::ResidueHandle r2)
+{
+  if (!r1 || !r2) return false; // protect against invalid handles
+  if(r1.GetChain() != r2.GetChain()) return false;
+  return r2.GetNumber().GetNum()==r1.GetNumber().GetNum()+1 ||
+         r2.GetNumber().GetInsCode()==r1.GetNumber().NextInsertionCode().GetInsCode();
+}
+
+
+String Processor::OptionsToString() const {
+  std::stringstream ss;
+  ss << "check_bond_feasibility=" << (check_bond_feasibility_ ? "True" : "False") << ", "
+     << "assign_torsions=" << (assign_torsions_ ? "True" : "False") << ", "
+     << "connect=" << (connect_ ? "True" : "False") << ", "
+     << "connect_peptides=" << (connect_aa_ ? "True" : "False")  << ", "
+     << "zero_occ_treatment='" << StringFromConopAction(zero_occ_treatment_) << "'";
+  return ss.str();
+}
+
+
+}}
diff --git a/modules/conop/src/processor.hh b/modules/conop/src/processor.hh
new file mode 100644
index 0000000000000000000000000000000000000000..6001b5cbfa32b8610ef73753256515276f583f43
--- /dev/null
+++ b/modules/conop/src/processor.hh
@@ -0,0 +1,152 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+#ifndef OST_CONOP_PROCESSOR_HH
+#define OST_CONOP_PROCESSOR_HH
+
+#include <ost/mol/entity_handle.hh>
+#include "module_config.hh"
+#include "diag.hh"
+#include "compound.hh"
+namespace ost { namespace conop {
+
+typedef enum {
+  PDB_DIALECT,
+  CHARMM_DIALECT
+} Dialect;
+
+enum ConopAction {
+  CONOP_WARN = 0,
+  CONOP_SILENT,
+  CONOP_REMOVE,
+  CONOP_REMOVE_ATOM,
+  CONOP_REMOVE_RESIDUE,
+  CONOP_FATAL
+};
+
+class Processor;
+typedef boost::shared_ptr<Processor> ProcessorPtr;
+// the base class for all options
+class DLLEXPORT_OST_CONOP Processor {
+public:
+  DiagnosticsPtr Process(mol::EntityHandle ent, bool log_diags=true) const;
+  virtual ProcessorPtr Copy() const = 0;
+  virtual ~Processor() {}
+protected:
+  virtual void DoProcess(DiagnosticsPtr diags, 
+                         mol::EntityHandle ent) const = 0;
+  virtual bool BeginProcessing(DiagnosticsPtr diags, 
+                               mol::EntityHandle ent) const { return true; }  
+  virtual bool EndProcessing(DiagnosticsPtr diags, 
+                             mol::EntityHandle ent) const { return true; }
+  bool HasUnknownAtoms(mol::ResidueHandle residue, CompoundPtr compound, 
+                       bool strict_hydrogens) const;
+  void ReorderAtoms(mol::ResidueHandle residue, CompoundPtr compound, 
+                    bool fix_element) const;
+  void FillResidueProps(mol::ResidueHandle residue, CompoundPtr compound) const;
+  void ConnectAtomsOfResidue(mol::ResidueHandle residue, 
+                             CompoundPtr compound, bool strict_hydrogens) const;
+  void ConnectResidues(mol::ResidueHandle residue, mol::ResidueHandle next) const;
+  static bool AreResiduesConsecutive(mol::ResidueHandle a, mol::ResidueHandle b);
+  void DistanceBasedConnect(mol::AtomHandle atom) const;
+  mol::AtomHandle LocateAtom(const mol::AtomHandleList&, int ordinal) const;
+public:
+  Processor(bool bf, bool at, bool cn, bool aa, ConopAction zo): check_bond_feasibility_(bf),
+    assign_torsions_(at), connect_(cn), connect_aa_(aa),
+    zero_occ_treatment_(zo) {}
+  Processor(): check_bond_feasibility_(false),
+    assign_torsions_(false), connect_(true), connect_aa_(true),
+    zero_occ_treatment_(CONOP_SILENT) {}
+  void SetConnect(bool connect) {
+    connect_ = connect;
+  }
+
+  bool GetConnect() const {
+    return connect_;
+  }
+  void SetAssignTorsions(bool flag) {
+    assign_torsions_ = flag;
+  }
+  bool GetAssignTorsions() const {
+    return assign_torsions_;
+  }
+
+  bool GetConnectAminoAcids() const {
+    return connect_aa_;
+  }
+  void SetConnectAminoAcids(bool c) {
+    connect_aa_ = c;
+  }
+  bool GetCheckBondFeasibility() const {
+    return check_bond_feasibility_;
+  }
+
+
+  void SetCheckBondFeasibility(bool flag) {
+    check_bond_feasibility_ = flag;
+  }
+
+
+  ConopAction GetZeroOccTreatment() const {
+    return zero_occ_treatment_;
+  }
+
+  void SetZeroOccTreatment(ConopAction action) {
+    zero_occ_treatment_ = action;
+  }
+  virtual String ToString() const = 0;
+protected:
+  String OptionsToString() const; 
+private:
+  bool check_bond_feasibility_;
+  bool assign_torsions_;
+  bool connect_;
+  bool connect_aa_;
+  ConopAction zero_occ_treatment_;
+};
+
+ConopAction DLLEXPORT_OST_CONOP ConopActionFromString(const String& name);
+
+String DLLEXPORT_OST_CONOP StringFromConopAction(ConopAction action);
+
+
+/// \brief guess element of atom based on name and hetatm flag
+String DLLEXPORT_OST_CONOP GuessAtomElement(const String& atom_name, bool hetatm);
+
+/// \brief guess chemclass based on atoms of residue
+mol::ChemClass DLLEXPORT_OST_CONOP GuessChemClass(mol::ResidueHandle res);
+
+/// \brief assigns phi/psi/omega to all residues marked peptide-linking of 
+///     the chain
+/// 
+/// Requires the atoms to be connected
+void DLLEXPORT_OST_CONOP AssignBackboneTorsions(mol::ChainHandle chain);
+void DLLEXPORT_OST_CONOP AssignBackboneTorsions(mol::ResidueHandleList residues);
+void DLLEXPORT_OST_CONOP AssignBackboneTorsions(mol::ResidueHandle prev, 
+                                                mol::ResidueHandle res, 
+                                                mol::ResidueHandle next);
+
+bool DLLEXPORT_OST_CONOP IsBondFeasible(const mol::AtomHandle&, 
+                                        const mol::AtomHandle&);
+mol::AtomHandleList DLLEXPORT_OST_CONOP 
+GetUnknownAtomsOfResidue(mol::ResidueHandle residue, 
+                         CompoundPtr compound,
+                         bool strict_hydrogens=false);
+}}
+
+#endif
diff --git a/modules/conop/src/rule_based.cc b/modules/conop/src/rule_based.cc
new file mode 100644
index 0000000000000000000000000000000000000000..11dac390e7cec4d3a773a6080ff0852040a6944d
--- /dev/null
+++ b/modules/conop/src/rule_based.cc
@@ -0,0 +1,193 @@
+//------------------------------------------------------------------------------
+// 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 <limits>
+#include <ost/log.hh>
+#include <ost/profile.hh>
+#include <ost/mol/xcs_editor.hh>
+#include <ost/mol/bond_handle.hh>
+#include <ost/mol/torsion_handle.hh>
+#include <ost/mol/impl/residue_impl.hh>
+#include <ost/mol/impl/atom_impl.hh>
+#include <ost/mol/residue_handle.hh>
+#include "rule_based.hh"
+#include "conop.hh"
+
+namespace ost { namespace conop {
+
+
+
+void RuleBasedProcessor::DoProcess(DiagnosticsPtr diags, 
+                                   mol::EntityHandle ent) const
+{
+  Profile prof("RuleBasedProcessor::Process");
+  mol::ChainHandleList chains=ent.GetChainList();
+  for (mol::ChainHandleList::iterator 
+       i = chains.begin(), e = chains.end(); i!= e; ++i) {
+    mol::ChainHandle& chain = *i;
+    mol::ResidueHandleList residues = chain.GetResidueList();
+    mol::ResidueHandle prev;
+    for (mol::ResidueHandleList::iterator 
+         j = residues.begin(), e2 = residues.end(); j != e2; ++j) {
+      mol::ResidueHandle residue = *j;
+      mol::AtomHandleList atoms_to_connect;
+      CompoundPtr compound = lib_->FindCompound(residue.GetName(), Compound::PDB);
+      if (!compound) {
+        // process unknown residue...
+        this->ProcessUnkResidue(diags, residue, atoms_to_connect);
+        for (mol::AtomHandleList::iterator k = atoms_to_connect.begin(),
+             e3=atoms_to_connect.end(); k!= e3; ++k) {
+          this->DistanceBasedConnect(*k);
+        }
+        continue;
+      }
+      this->ReorderAtoms(residue, compound, this->GetFixElement());  
+      bool unks = this->HasUnknownAtoms(residue, compound, 
+                                        this->GetStrictHydrogens());
+      if (unks) {
+        mol::AtomHandleList unk_atoms;
+        unk_atoms = GetUnknownAtomsOfResidue(residue, compound, 
+                                             this->GetStrictHydrogens());
+        this->ProcessUnkAtoms(diags, unk_atoms, atoms_to_connect);
+        residue.SetChemClass(mol::ChemClass(mol::ChemClass::UNKNOWN));
+        residue.SetChemType(mol::ChemType(mol::ChemType::UNKNOWN));
+        residue.SetOneLetterCode('?');
+      } else {
+        this->FillResidueProps(residue, compound);
+      }
+      if (this->GetConnect()) {
+        this->ConnectAtomsOfResidue(residue, compound, 
+                                    this->GetStrictHydrogens());
+        if (this->GetConnectAminoAcids())
+          this->ConnectResidues(prev, residue);
+        for (mol::AtomHandleList::iterator k = atoms_to_connect.begin(),
+             e3=atoms_to_connect.end(); k!= e3; ++k) {
+          this->DistanceBasedConnect(*k);
+        }
+      }
+      prev = residue;
+    }
+    if (residues.empty() || !this->GetAssignTorsions()) {
+      continue;
+    }
+    AssignBackboneTorsions(residues);
+  }
+}
+
+void RuleBasedProcessor::ProcessUnkResidue(DiagnosticsPtr diags,
+                                           mol::ResidueHandle res,
+                                           mol::AtomHandleList& remaining_atoms) const
+{
+  mol::AtomHandleList atoms = res.GetAtomList();    
+  if (this->GetUnkResidueTreatment() == CONOP_SILENT ||
+      this->GetUnkResidueTreatment() == CONOP_WARN) {
+    res.SetOneLetterCode('?');
+    res.SetChemClass(mol::ChemClass(mol::ChemClass::UNKNOWN));
+    for (mol::AtomHandleList::iterator i = atoms.begin(), 
+         e = atoms.end(); i !=e; ++i) {
+      remaining_atoms.push_back(*i);
+      if (!Conopology::Instance().IsValidElement(i->GetElement()))
+        i->SetElement(GuessAtomElement(i->GetName(), i->IsHetAtom()));
+    }
+  }
+  // Don't do anything if treatment is set to SILENT
+  if (this->GetUnkResidueTreatment() == CONOP_SILENT) {
+    return;
+  }
+  switch (this->GetUnkResidueTreatment()) {
+    case CONOP_WARN:
+      diags->AddDiag(DIAG_UNK_RESIDUE, "unknown residue %0")
+            .AddResidue(res);
+      break;
+    case CONOP_FATAL:
+      throw DiagError(Diag(DIAG_UNK_RESIDUE, "unknown residue %0").AddResidue(res));
+      break;
+    case CONOP_REMOVE_RESIDUE:
+    case CONOP_REMOVE:
+      diags->AddDiag(DIAG_UNK_RESIDUE, "removed unknown residue %0")
+           .AddResidue(res);
+      res.GetEntity().EditXCS().DeleteResidue(res);
+      return;
+    default:
+      assert(0 && "unhandled switch");
+  }
+}
+
+void RuleBasedProcessor::ProcessUnkAtoms(DiagnosticsPtr diags,
+                                         mol::AtomHandleList unks,
+                                         mol::AtomHandleList& remaining_atoms) const
+{
+  if (this->GetUnkAtomTreatment() == CONOP_SILENT ||
+      this->GetUnkAtomTreatment() == CONOP_WARN) {
+    for (mol::AtomHandleList::iterator i = unks.begin(), 
+         e = unks.end(); i !=e; ++i) {
+      remaining_atoms.push_back(*i);
+      if (!Conopology::Instance().IsValidElement(i->GetElement()))
+        i->SetElement(GuessAtomElement(i->GetName(), i->IsHetAtom()));
+    }
+  }
+
+  // Don't do anything if treatment is set to SILENT
+  if (this->GetUnkAtomTreatment() == CONOP_SILENT) {
+    return;
+  }
+ 
+  assert(!unks.empty() && "empty unk list");
+  mol::XCSEditor edi = unks.front().GetEntity().EditXCS();
+  for (mol::AtomHandleList::iterator 
+       i = unks.begin(), e = unks.end(); i != e; ++i) {
+    switch (this->GetUnkAtomTreatment()) {
+      case CONOP_REMOVE_ATOM:
+      case CONOP_REMOVE:
+        edi.DeleteAtom(*i);
+        diags->AddDiag(DIAG_UNK_ATOM, "removed unknown atom %0 from residue %1")
+             .AddString(i->GetName()).AddResidue(i->GetResidue());
+        break;
+      case CONOP_WARN:
+        diags->AddDiag(DIAG_UNK_ATOM, "residue %0 contains unknown atom %1")
+             .AddResidue(i->GetResidue()).AddString(i->GetName());
+        break;
+      case CONOP_FATAL:
+        throw DiagError(Diag(DIAG_UNK_ATOM, "unknown atom %0").AddAtom(*i));
+        break;
+      case CONOP_REMOVE_RESIDUE:
+        diags->AddDiag(DIAG_UNK_ATOM, "removed residue %0 with unknown atom %1")
+             .AddString(i->GetResidue().GetQualifiedName())
+             .AddString(i->GetName());
+        edi.DeleteResidue(i->GetResidue());
+        return;
+      default:
+        assert(0 && "unhandled switch");
+    }
+  }
+}
+
+String RuleBasedProcessor::ToString() const {
+  std::stringstream ss;
+  ss << "RuleBasedProcesor(" << this->OptionsToString() 
+     << ", fix_element=" << (fix_element_ ? "True" : "False")
+     << ", strict_hydrogens=" << (strict_hydrogens_ ? "True" : "False")
+     << ", unk_res_treatment='" << StringFromConopAction(unk_res_treatment_)
+     << ", unk_atom_treatment'=" << StringFromConopAction(unk_atom_treatment_)
+     << "')";
+  return ss.str();
+}
+
+
+
+}}
diff --git a/modules/conop/src/rule_based.hh b/modules/conop/src/rule_based.hh
new file mode 100644
index 0000000000000000000000000000000000000000..4275d7e40e15dfdd7b088fe5ceae437a32095aaa
--- /dev/null
+++ b/modules/conop/src/rule_based.hh
@@ -0,0 +1,104 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+#ifndef OST_CONOP_RULE_BASED_HH
+#define OST_CONOP_RULE_BASED_HH
+
+#include <ost/mol/entity_handle.hh>
+#include "compound_lib.hh"
+#include "diag.hh"
+#include "processor.hh"
+
+namespace ost { namespace conop {
+
+/// \brief returns all atoms not listed in  the specifictaion of compound
+mol::AtomHandleList DLLEXPORT_OST_CONOP GetUnknownAtoms(mol::ResidueHandle res, 
+                                                        CompoundPtr compound);
+
+class RuleBasedProcessor;
+
+typedef boost::shared_ptr<RuleBasedProcessor> RuleBasedProcessorPtr;
+
+class DLLEXPORT_OST_CONOP RuleBasedProcessor  : public Processor {
+public:
+  RuleBasedProcessor(CompoundLibPtr compound_lib): 
+    lib_(compound_lib), fix_element_(true), strict_hydrogens_(false), 
+    unk_res_treatment_(CONOP_WARN), unk_atom_treatment_(CONOP_WARN)
+  {
+  }
+
+  RuleBasedProcessor(CompoundLibPtr compound_lib, bool fe, bool sh, ConopAction ur, 
+                     ConopAction ua, bool bf, bool at, bool cn, bool aa, ConopAction zo): 
+    Processor(bf, at, cn, aa, zo), lib_(compound_lib), fix_element_(fe), 
+    strict_hydrogens_(sh), unk_res_treatment_(ur), 
+    unk_atom_treatment_(ua) {}
+  ConopAction GetUnkResidueTreatment() const {
+    return unk_res_treatment_;
+  }
+
+  ConopAction GetUnkAtomTreatment() const {
+    return unk_atom_treatment_;
+  }
+
+  bool GetFixElement() const {
+    return fix_element_;
+  }
+  void SetFixElement(bool flag) {
+    fix_element_ = flag;
+  }
+  bool GetStrictHydrogens() const {
+    return strict_hydrogens_;
+  }
+
+  void SetStrictHydrogens(bool flag) {
+    strict_hydrogens_ = flag;
+  }
+  void SetUnkResidueTreatment(ConopAction action) {
+    unk_res_treatment_ = action;
+  }
+
+  void SetUnkAtomTreatment(ConopAction action) {
+    unk_atom_treatment_ = action;
+  }
+  virtual ProcessorPtr Copy() const {
+    return ProcessorPtr(new RuleBasedProcessor(*this));
+  }
+
+  virtual String ToString() const;
+protected:
+  void ProcessUnkResidue(DiagnosticsPtr diags,
+                         mol::ResidueHandle res, 
+                         mol::AtomHandleList& remaining) const;
+  void ProcessUnkAtoms(DiagnosticsPtr diags,
+                       mol::AtomHandleList unks,
+                       mol::AtomHandleList& remaining) const;
+  virtual void DoProcess(DiagnosticsPtr diags, 
+                         mol::EntityHandle ent) const;
+private:
+  CompoundLibPtr lib_;
+  bool fix_element_;
+  bool strict_hydrogens_;
+  ConopAction unk_res_treatment_;
+  ConopAction unk_atom_treatment_;
+};
+
+
+
+}}
+#endif
+
diff --git a/modules/conop/src/rule_based_builder.cc b/modules/conop/src/rule_based_builder.cc
deleted file mode 100644
index 529fbcbc65f29be69c4b6391b346e45d9f382e3a..0000000000000000000000000000000000000000
--- a/modules/conop/src/rule_based_builder.cc
+++ /dev/null
@@ -1,379 +0,0 @@
-//------------------------------------------------------------------------------
-// This file is part of the OpenStructure project <www.openstructure.org>
-//
-// Copyright (C) 2008-2011 by the OpenStructure authors
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License as published by the Free
-// Software Foundation; either version 3.0 of the License, or (at your option)
-// any later version.
-// This library is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with this library; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//------------------------------------------------------------------------------
-/*
-   Author: Marco Biasini
- */
-#include <ost/log.hh>
-#include <ost/geom/geom.hh>
-#include <ost/mol/impl/atom_impl.hh>
-#include <ost/mol/impl/residue_impl.hh>
-#include <ost/conop/conop.hh>
-#include <limits>
-#include "rule_based_builder.hh"
-
-
-namespace ost { namespace conop {
-
-
-void RuleBasedBuilder::CompleteAtoms(mol::ResidueHandle rh) {}
-
-void RuleBasedBuilder::CheckResidueCompleteness(const mol::ResidueHandle& rh) 
-{
-  this->LookupCompound(rh);
-  if (!last_compound_) {
-    mol::AtomHandleList atoms=rh.GetAtomList();    
-    for (mol::AtomHandleList::const_iterator i=atoms.begin(), 
-         e=atoms.end(); i!=e; ++i) {
-      this->OnUnknownAtom(*i);
-    }
-    return;
-  }
-  this->ReorderAtoms(rh , last_compound_);
-  AtomSpecList::const_iterator j=last_compound_->GetAtomSpecs().begin();
-  mol::AtomHandleList atoms=rh.GetAtomList();
-  mol::AtomHandleList::iterator i=atoms.begin();
-  for (; j!=last_compound_->GetAtomSpecs().end() && i!=atoms.end(); ++j) {
-    if ((*j).is_leaving || (*j).element=="H" || (*j).element=="D")
-      continue;
-    if ((*j).ordinal!=static_cast<int>((*i).Impl()->GetState())) {
-      this->OnMissingAtom(rh, (*j).name);
-    } else {
-      ++i;
-    }
-  }
-}
-
-bool RuleBasedBuilder::HasUnknownAtoms(mol::ResidueHandle res)
-{
-  this->LookupCompound(res);
-  if (!last_compound_) {
-    return true;
-  }
-  this->ReorderAtoms(res, last_compound_);
-  AtomSpecList::const_iterator j=last_compound_->GetAtomSpecs().begin();
-  mol::AtomHandleList atoms=res.GetAtomList();
-  mol::AtomHandleList::iterator i=atoms.begin();
-  for (mol::AtomHandleList::iterator 
-       i=atoms.begin(), e=atoms.end(); i!=e; ++i) {
-    if ((*i).Impl()->GetState()==std::numeric_limits<unsigned int>::max()) {
-      if (((*i).GetElement()=="H" || (*i).GetElement()=="D") && 
-          this->GetStrictHydrogenMode()==false) {
-        continue;
-      }
-      return true;
-    }
-  }
-  return false;
-}
-
-mol::AtomHandleList RuleBasedBuilder::GetUnknownAtoms(mol::ResidueHandle res)
-{
-  mol::AtomHandleList unknown;
-  this->LookupCompound(res);
-  if (!last_compound_) {
-    return unknown;
-  }
-  mol::AtomHandleList atoms=res.GetAtomList();
-  last_residue_=mol::ResidueHandle();
-  this->ReorderAtoms(res, last_compound_);
-  AtomSpecList::const_iterator j=last_compound_->GetAtomSpecs().begin();
-  mol::AtomHandleList::iterator i=atoms.begin();
-  for (mol::AtomHandleList::iterator 
-       i=atoms.begin(), e=atoms.end(); i!=e; ++i) {
-    if ((*i).Impl()->GetState()==std::numeric_limits<unsigned int>::max()) {
-      if (((*i).GetElement()=="H" || (*i).GetElement()=="D") && 
-          this->GetStrictHydrogenMode()==false) {
-        continue;
-      }
-      unknown.push_back(*i);
-    }
-  }
-  return unknown;
-}
-
-void RuleBasedBuilder::FillAtomProps(mol::AtomHandle atom, const AtomSpec& spec) 
-{
-  Conopology& conop_inst=Conopology::Instance();
-  if (!conop_inst.IsValidElement(atom.GetElement())) {
-    atom.SetElement(spec.element);
-  } 
-}
-
-void RuleBasedBuilder::FillResidueProps(mol::ResidueHandle residue) 
-{
-  this->LookupCompound(residue);
-  if (!last_compound_)
-    return;
-  residue.SetChemClass(last_compound_->GetChemClass());
-  residue.SetChemType(last_compound_->GetChemType());
-  residue.SetOneLetterCode(last_compound_->GetOneLetterCode());
-};
-
-struct OrdinalComp {
-  bool operator()(const mol::impl::AtomImplPtr& a,
-                  const mol::impl::AtomImplPtr& b) const {
-    return a->GetState()<b->GetState();
-  }
-};
-
-
-void RuleBasedBuilder::LookupCompound(const mol::ResidueHandle& rh) 
-{
-  Compound::Dialect dialect=this->GetDialect()==PDB_DIALECT ? Compound::PDB : Compound::CHARMM;  
-  if ((last_compound_) && (rh.GetName()==last_compound_->GetID())) {
-   return;
-  }
-  last_compound_=compound_lib_->FindCompound(rh.GetName(), dialect);
-  if (!last_compound_ && this->GetDialect()!=PDB_DIALECT) {
-    last_compound_=compound_lib_->FindCompound(rh.GetName(), Compound::PDB);
-  }
-}
-
-void RuleBasedBuilder::ReorderAtoms(mol::ResidueHandle residue,
-                                    CompoundPtr compound) 
-{
-  if (last_residue_==residue) {
-    return;
-  }
-  mol::impl::ResidueImplPtr impl=residue.Impl();
-  mol::impl::AtomImplList::iterator i=impl->GetAtomList().begin();
-  for (; i!=impl->GetAtomList().end(); ++i) {
-    mol::impl::AtomImplPtr atom=*i;
-    atom->SetState(std::numeric_limits<unsigned int>::max());
-    int index=compound->GetAtomSpecIndex(atom->GetName());
-    if (index==-1) {
-      if (!this->OnUnknownAtom(mol::AtomHandle(atom))) {
-        atom->SetState(std::numeric_limits<unsigned int>::max());
-      }
-      continue;
-    }
-    atom->SetState((compound->GetAtomSpecs())[index].ordinal);
-  }
-  std::sort(impl->GetAtomList().begin(), impl->GetAtomList().end(),
-            OrdinalComp());
-  last_residue_=residue;
-  unknown_atoms_=this->HasUnknownAtoms(residue);
-  if (unknown_atoms_) {
-    LOG_WARNING("residue " << residue << " doesn't look like a standard " 
-                << residue.GetKey() << " (" << compound->GetFormula() << ")");
-    residue.SetChemClass(mol::ChemClass(mol::ChemClass::UNKNOWN));
-    residue.SetChemType(mol::ChemType(mol::ChemType::UNKNOWN));
-    residue.SetOneLetterCode('?');
-  }
-}
-
-
-
-mol::ResidueKey RuleBasedBuilder::IdentifyResidue(const mol::ResidueHandle& rh) 
-{
-  LookupCompound(rh);
-  if (last_compound_) {
-    return last_compound_->GetID();
-  } else {
-    return "UNK";
-  }
-}
-
-mol::AtomHandle RuleBasedBuilder::LocateAtom(const mol::AtomHandleList& ahl, 
-                                             int ordinal) 
-{
-  if (ahl.empty())
-    return mol::AtomHandle();
-  const mol::AtomHandle* r_it=&ahl.back();
-  if (static_cast<int>(ahl.size())>ordinal) {
-    r_it=&ahl.front()+ordinal;
-  }
-  while ((r_it>=&ahl.front()) &&
-         (static_cast<int>(r_it->Impl()->GetState())>ordinal)) {
-    --r_it;
-  }
-  bool not_found=(r_it<&ahl.front() ||
-                 static_cast<int>(r_it->Impl()->GetState())!=ordinal);
-  return  not_found ? mol::AtomHandle() : *r_it;
-}
-
-
-inline void dist_connect(RuleBasedBuilder* b, mol::AtomHandleList atoms)
-{
-  for (mol::AtomHandleList::const_iterator i=atoms.begin(), 
-       e=atoms.end(); i!=e; ++i) {
-    b->DistanceBasedConnect(*i);
-  }  
-}
-void RuleBasedBuilder::ConnectAtomsOfResidue(mol::ResidueHandle rh) 
-{
-
-  LookupCompound(rh);
-    
-  if (!last_compound_) {
-    dist_connect(this, rh.GetAtomList());
-    return;
-  }
-  this->ReorderAtoms(rh, last_compound_);
-  if (unknown_atoms_) {
-    dist_connect(this, rh.GetAtomList());
-    return;
-  }
-  mol::XCSEditor e=rh.GetEntity().EditXCS(mol::BUFFERED_EDIT);
-  BondSpecList::const_iterator j=last_compound_->GetBondSpecs().begin();
-  mol::AtomHandleList atoms=rh.GetAtomList();
-  for(; j!=last_compound_->GetBondSpecs().end(); ++j) {
-      const BondSpec& bond=*j;
-      mol::AtomHandle a1=this->LocateAtom(atoms, bond.atom_one);
-      mol::AtomHandle a2=this->LocateAtom(atoms, bond.atom_two);
-      if (a1.IsValid() && a2.IsValid()) { 
-        if (this->GetBondFeasibilityCheck()==false) {
-          if (this->GetStrictHydrogenMode() && (a1.GetElement()=="H" || 
-                                                a2.GetElement()=="D")) {
-            continue;
-          }
-          e.Connect(a1, a2, bond.order);
-        } else { 
-          if (IsBondFeasible(a1, a2)) {
-            if (this->GetStrictHydrogenMode() && (a1.GetElement()=="H" || 
-                                                  a2.GetElement()=="D")) {
-              continue;
-            }
-            e.Connect(a1, a2, bond.order);
-          }
-        }
-      }
-  }
-  for (mol::AtomHandleList::iterator i=atoms.begin(), e=atoms.end(); i!=e; ++i) {
-    if (((*i).GetElement()=="H" || (*i).GetElement()=="D") && 
-        (*i).GetBondCount()==0) {
-      this->DistanceBasedConnect(*i);
-    }
-  }
-}
-
-void RuleBasedBuilder::ConnectResidueToNext(mol::ResidueHandle rh,
-                                            mol::ResidueHandle next) 
-{
-  if (!next.IsValid()) {
-    return;
-  }
-
-  Compound::Dialect dialect=this->GetDialect()==PDB_DIALECT ? Compound::PDB : Compound::CHARMM;
-
-  mol::XCSEditor e=rh.GetEntity().EditXCS(mol::BUFFERED_EDIT);
-  CompoundPtr mc=compound_lib_->FindCompound(rh.GetName(), dialect);
-  CompoundPtr nc=compound_lib_->FindCompound(next.GetName(), dialect);
-  if (!(mc && nc))
-    return;
-
-  // check if both of the residues are able to form a peptide bond.
-  if (mc->IsPeptideLinking() && nc->IsPeptideLinking()) {
-    // If we have an OXT then there is no peptide bond connecting the two
-    // residues.
-    if (rh.FindAtom("OXT"))
-      return;
-    mol::AtomHandle c=rh.FindAtom("C");
-    mol::AtomHandle n=next.FindAtom("N");
-    // Give subclasses a chance to give us their opinions on the feasibility of
-    // the peptide bond.
-    if (c.IsValid() && n.IsValid() && this->DoesPeptideBondExist(c, n)) {
-      e.Connect(c, n, 1);
-      rh.SetIsProtein(true);
-      next.SetIsProtein(true);
-    }
-  } else if (mc->IsNucleotideLinking() && nc->IsNucleotideLinking()) {
-    mol::AtomHandle c=rh.FindAtom("O3'");
-    mol::AtomHandle n=next.FindAtom("P");
-    if (c.IsValid() && n.IsValid() && this->IsBondFeasible(c, n)) {
-      e.Connect(c, n, 1);
-    }
-  }
-}
-
-
-void RuleBasedBuilder::AssignTorsions(mol::ChainHandle chain) 
-{
-  if (chain.GetResidueCount()==0)
-    return;
-  std::vector<mol::ResidueHandle> rlist = chain.GetResidueList();
-  mol::AtomHandleList atom_list = rlist[0].GetAtomList();
-  for(unsigned int ri=0;ri<rlist.size();++ri) {
-    mol::ResidueHandle res=rlist[ri];
-    this->AssignTorsionsToResidue(res);
-  }
-}
-
-void RuleBasedBuilder::AssignTorsionsToResidue(mol::ResidueHandle residue) 
-{
-  /// The only components having named torsions are the standard set of amino
-  /// acids, plus some of compounds derived from them such as selenium
-  /// methionine. Things are simplified a lot by only storing the torsions
-  /// of the side chains in the database. PHI, PSI and OMEGA torsions are    
-  /// checked without a lookup in the database.
-  LookupCompound(residue);
-  if (!last_compound_)
-    return;  
-  if (!last_compound_->IsPeptideLinking()) {
-    return;
-  }
-  Builder::AssignBackBoneTorsionsToResidue(residue);
-}
-
-bool RuleBasedBuilder::IsResidueComplete(const mol::ResidueHandle& residue)
-{
-  LookupCompound(residue);
-  if (!last_compound_)
-    return false;
-  mol::AtomHandleList atoms=residue.GetAtomList();
-  mol::AtomHandleList::iterator i=atoms.begin();
-  for (AtomSpecList::const_iterator j=last_compound_->GetAtomSpecs().begin(),
-       e=last_compound_->GetAtomSpecs().end(); j!=e; ++j) {
-    if ((*j).is_leaving || (*j).element=="H" || (*j).element=="D") {
-      continue;      
-    }
-    if (!(residue.FindAtom(j->name) || residue.FindAtom(j->alt_name))) {
-      return false;
-    }
-  }  
-  return true;
-}
-
-
-void RuleBasedBuilder::FillAtomProps(mol::AtomHandle atom)
-{
-  LookupCompound(atom.GetResidue());
-  if (!last_compound_) {
-    this->OnUnknownAtom(atom);
-    return;
-  }
-  int index=last_compound_->GetAtomSpecIndex(atom.GetName());
-  if (index==-1) {
-    this->OnUnknownAtom(atom);
-    return;
-  }
-  const AtomSpec& atom_spec=last_compound_->GetAtomSpecs()[index];
-  this->FillAtomProps(atom, atom_spec);
-}
-
-bool RuleBasedBuilder::OnUnknownAtom(mol::AtomHandle atom)
-{
-  Conopology& conop_inst=Conopology::Instance();
-  if (!conop_inst.IsValidElement(atom.GetElement())) {
-    atom.SetElement(Builder::GuessAtomElement(atom.GetName(), atom.IsHetAtom()));
-  }
-  return false;
-}
-
-}}
diff --git a/modules/conop/src/rule_based_builder.hh b/modules/conop/src/rule_based_builder.hh
deleted file mode 100644
index 71a6fd03453ba9c418a6e39d8c0e011161f13be6..0000000000000000000000000000000000000000
--- a/modules/conop/src/rule_based_builder.hh
+++ /dev/null
@@ -1,150 +0,0 @@
-//------------------------------------------------------------------------------
-// This file is part of the OpenStructure project <www.openstructure.org>
-//
-// Copyright (C) 2008-2011 by the OpenStructure authors
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License as published by the Free
-// Software Foundation; either version 3.0 of the License, or (at your option)
-// any later version.
-// This library is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with this library; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//------------------------------------------------------------------------------
-#ifndef OST_CONOP_RULE_BASED_BUILDER_HH
-#define OST_CONOP_RULE_BASED_BUILDER_HH
-
-/*
-   Author: Marco Biasini
- */
-#include <set>
-#include <map>
-
-#include "builder.hh"
-#include "compound_lib.hh"
-
-namespace ost { namespace conop {
-
-/// \brief  Use library of chemical compounds to derive bonds and clean-up
-///         structural problems
-///
-/// \todo   Sorting of the residues directly uses impl layer of the base module.
-///         Would be much nicer if the order could be assigned in the public
-///         interface and then tell the residues to sort the atoms in ascending
-///         order.
-class DLLEXPORT_OST_CONOP RuleBasedBuilder: public Builder {
-public:
-  RuleBasedBuilder(const CompoundLibPtr& compound_lib)
-    : compound_lib_(compound_lib), last_compound_() {
-  }
-  
-  virtual void SetDialect(Dialect dialect) {
-    if (this->GetDialect()!=dialect) {
-      Builder::SetDialect(dialect);
-      last_compound_=CompoundPtr();
-      compound_lib_->ClearCache();
-    }
-  }
-  
-  /// \brief fill atom properties such as element and radius
-  virtual void FillAtomProps(mol::AtomHandle atom);
-  
-  virtual void CompleteAtoms(mol::ResidueHandle rh);
-
-  /// \brief  Check residue completeness
-  ///
-  ///  By using the description of the chemical compound, the completeness of
-  /// the residue is verified. The method distinguishes between required atoms
-  /// and atoms that are optional, like OXT that is only present, if not peptide
-  /// bond is formed. Whenever an unknown atom is encountered, OnUnknownAtom()
-  /// is invoked. Subclasses of the RuleBasedBuilder may implement some
-  /// additional logic to deal with unknown atom. Likewise, whenever a required
-  /// atom is missing, OnMissingAtom() is invoked. Hydrogen atoms are not
-  /// considered as required by default
-  virtual void CheckResidueCompleteness(const mol::ResidueHandle& rh);
-
-  /// \brief Identify residue by name
-  ///
-  /// Looks-up the residue in the database of chemical compounds and returns the
-  /// name of the residue or "UNK" if the residue has not been found in the
-  /// library.
-  virtual mol::ResidueKey IdentifyResidue(const mol::ResidueHandle& rh);
-
-
-  virtual void ConnectAtomsOfResidue(mol::ResidueHandle rh);
-
-  /// \brief  Connects the two residues together.
-  ///
-  /// Connections are established if both of the residues are peptide-linking
-  /// components and when PeptideBondExists() returns true.
-  /// \param rh
-  ///          is the N-terminal partner donating the C and O for the peptide
-  ///         bond.
-  /// \param next
-  ///          is the C-terminal partner, donating the nitrogen to the bond.
-  virtual void ConnectResidueToNext(mol::ResidueHandle rh,
-                                    mol::ResidueHandle next);
-  /// \brief requires chemical types
-  virtual void AssignTorsions(mol::ChainHandle ch);
-  virtual void AssignTorsionsToResidue(mol::ResidueHandle residue);
-  /// \brief  Invoked whenever an unkknown atom has been encountered during a
-  ///         residue completeness check.
-  ///
-  /// The default implementation guesses the atom properties based on the name 
-  /// and returns false, meaning that it should be treated as an unknown atom.
-  /// 
-  /// Custom implementations of this method may delete the atom, or modify it.
-  /// \todo   what should be done when the atom name is changed? it would be
-  ///         neccessary to rerun CheckResidueCompleteness().
-  virtual bool OnUnknownAtom(mol::AtomHandle atom);
-
-  /// \brief Invoked whenever an atom is missing
-  ///
-  /// It is up to the overloaded method to deal with the missing atom, either
-  /// by ignoring it or by inserting a dummy atom.
-  virtual void OnMissingAtom(const mol::ResidueHandle& residue,
-                              const String& atom_name) { }
-                              
-  /// \brief Fill in missing information based on atom name.
-  virtual void FillAtomProps(mol::AtomHandle atom, const AtomSpec& spec);
-
-  /// \brief Set residue properties such as chemical class
-  virtual void FillResidueProps(mol::ResidueHandle residue);
-
-  mol::AtomHandleList GetUnknownAtoms(mol::ResidueHandle res);
-  
-  /// \brief Check whether the residue has all required atoms. This does not
-  ///        include hydrogens and leaving atoms such as the terminal OXT.
-  virtual bool IsResidueComplete(const mol::ResidueHandle& residue);
-  
-  CompoundLibPtr GetCompoundLib() const { return compound_lib_; }
-    
-private:
-  CompoundLibPtr      compound_lib_;
-  CompoundPtr         last_compound_;
-  mol::ResidueHandle  last_residue_;
-  bool                unknown_atoms_;
-  /// \brief whether the residue has unknown atoms
-  bool HasUnknownAtoms(mol::ResidueHandle res);
-
-  void LookupCompound(const mol::ResidueHandle& rh);
-  /// Change internal order of atoms in residue to the order given by compound
-  void ReorderAtoms(mol::ResidueHandle residue, CompoundPtr compound);
-
-  mol::AtomHandle LocateAtom(const mol::AtomHandleList& ahl, int ordinal);
-
-  void AssignBackBoneTorsionsToResidue(mol::ResidueHandle residue);
-
-};
-
-typedef boost::shared_ptr<RuleBasedBuilder> RuleBasedBuilderPtr;
-
-}}
-
-#endif
-
diff --git a/modules/conop/src/standard_compounds.cc b/modules/conop/src/standard_compounds.cc
new file mode 100644
index 0000000000000000000000000000000000000000..7ce7302ffcc4f90e37a1f59e80595e54efbb4f24
--- /dev/null
+++ b/modules/conop/src/standard_compounds.cc
@@ -0,0 +1,1906 @@
+CompoundPtr MakeALACompound() {
+  CompoundPtr c( new Compound("ALA"));
+  c->SetOneLetterCode('A');
+  c->SetChemClass(mol::ChemClass('L'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C3 H7 N O2");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "N", "N", "N", false, true),
+    AtomSpec(1, "CA", "CA", "C", false, true),
+    AtomSpec(2, "C", "C", "C", false, true),
+    AtomSpec(3, "O", "O", "O", false, true),
+    AtomSpec(4, "CB", "CB", "C", false, true),
+    AtomSpec(5, "OXT", "OXT", "O", true, true),
+    AtomSpec(6, "H", "H", "H", false, true),
+    AtomSpec(7, "H2", "HN2", "H", true, true),
+    AtomSpec(8, "HA", "HA", "H", false, true),
+    AtomSpec(9, "HB1", "1HB", "H", false, true),
+    AtomSpec(10, "HB2", "2HB", "H", false, true),
+    AtomSpec(11, "HB3", "3HB", "H", false, true),
+    AtomSpec(12, "HXT", "HXT", "H", true, true)
+  };
+  for (int i=0; i<13; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 6, 1),
+    BondSpec(0, 7, 1),
+    BondSpec(1, 2, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(1, 8, 1),
+    BondSpec(2, 3, 2),
+    BondSpec(2, 5, 1),
+    BondSpec(4, 9, 1),
+    BondSpec(4, 10, 1),
+    BondSpec(4, 11, 1),
+    BondSpec(5, 12, 1)
+  };
+  for (int i=0; i<12; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakeCYSCompound() {
+  CompoundPtr c( new Compound("CYS"));
+  c->SetOneLetterCode('C');
+  c->SetChemClass(mol::ChemClass('L'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C3 H7 N O2 S");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "N", "N", "N", false, true),
+    AtomSpec(1, "CA", "CA", "C", false, true),
+    AtomSpec(2, "C", "C", "C", false, true),
+    AtomSpec(3, "O", "O", "O", false, true),
+    AtomSpec(4, "CB", "CB", "C", false, true),
+    AtomSpec(5, "SG", "SG", "S", false, true),
+    AtomSpec(6, "OXT", "OXT", "O", true, true),
+    AtomSpec(7, "H", "H", "H", false, true),
+    AtomSpec(8, "H2", "HN2", "H", true, true),
+    AtomSpec(9, "HA", "HA", "H", false, true),
+    AtomSpec(10, "HB2", "1HB", "H", false, true),
+    AtomSpec(11, "HB3", "2HB", "H", false, true),
+    AtomSpec(12, "HG", "HG", "H", false, true),
+    AtomSpec(13, "HXT", "HXT", "H", true, true)
+  };
+  for (int i=0; i<14; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 7, 1),
+    BondSpec(0, 8, 1),
+    BondSpec(1, 2, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(1, 9, 1),
+    BondSpec(2, 3, 2),
+    BondSpec(2, 6, 1),
+    BondSpec(4, 5, 1),
+    BondSpec(4, 10, 1),
+    BondSpec(4, 11, 1),
+    BondSpec(5, 12, 1),
+    BondSpec(6, 13, 1)
+  };
+  for (int i=0; i<13; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakeASPCompound() {
+  CompoundPtr c( new Compound("ASP"));
+  c->SetOneLetterCode('D');
+  c->SetChemClass(mol::ChemClass('L'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C4 H7 N O4");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "N", "N", "N", false, true),
+    AtomSpec(1, "CA", "CA", "C", false, true),
+    AtomSpec(2, "C", "C", "C", false, true),
+    AtomSpec(3, "O", "O", "O", false, true),
+    AtomSpec(4, "CB", "CB", "C", false, true),
+    AtomSpec(5, "CG", "CG", "C", false, true),
+    AtomSpec(6, "OD1", "OD1", "O", false, true),
+    AtomSpec(7, "OD2", "OD2", "O", false, true),
+    AtomSpec(8, "OXT", "OXT", "O", true, true),
+    AtomSpec(9, "H", "H", "H", false, true),
+    AtomSpec(10, "H2", "HN2", "H", true, true),
+    AtomSpec(11, "HA", "HA", "H", false, true),
+    AtomSpec(12, "HB2", "HB1", "H", false, true),
+    AtomSpec(13, "HB3", "HB2", "H", false, true),
+    AtomSpec(14, "HD2", "HD2", "H", false, true),
+    AtomSpec(15, "HXT", "HXT", "H", true, true)
+  };
+  for (int i=0; i<16; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 9, 1),
+    BondSpec(0, 10, 1),
+    BondSpec(1, 2, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(1, 11, 1),
+    BondSpec(2, 3, 2),
+    BondSpec(2, 8, 1),
+    BondSpec(4, 5, 1),
+    BondSpec(4, 12, 1),
+    BondSpec(4, 13, 1),
+    BondSpec(5, 6, 2),
+    BondSpec(5, 7, 1),
+    BondSpec(7, 14, 1),
+    BondSpec(8, 15, 1)
+  };
+  for (int i=0; i<15; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakeGLUCompound() {
+  CompoundPtr c( new Compound("GLU"));
+  c->SetOneLetterCode('E');
+  c->SetChemClass(mol::ChemClass('L'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C5 H9 N O4");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "N", "N", "N", false, true),
+    AtomSpec(1, "CA", "CA", "C", false, true),
+    AtomSpec(2, "C", "C", "C", false, true),
+    AtomSpec(3, "O", "O", "O", false, true),
+    AtomSpec(4, "CB", "CB", "C", false, true),
+    AtomSpec(5, "CG", "CG", "C", false, true),
+    AtomSpec(6, "CD", "CD", "C", false, true),
+    AtomSpec(7, "OE1", "OE1", "O", false, true),
+    AtomSpec(8, "OE2", "OE2", "O", false, true),
+    AtomSpec(9, "OXT", "OXT", "O", true, true),
+    AtomSpec(10, "H", "H", "H", false, true),
+    AtomSpec(11, "H2", "HN2", "H", true, true),
+    AtomSpec(12, "HA", "HA", "H", false, true),
+    AtomSpec(13, "HB2", "HB1", "H", false, true),
+    AtomSpec(14, "HB3", "HB2", "H", false, true),
+    AtomSpec(15, "HG2", "HG1", "H", false, true),
+    AtomSpec(16, "HG3", "HG2", "H", false, true),
+    AtomSpec(17, "HE2", "HE2", "H", false, true),
+    AtomSpec(18, "HXT", "HXT", "H", true, true)
+  };
+  for (int i=0; i<19; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 10, 1),
+    BondSpec(0, 11, 1),
+    BondSpec(1, 2, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(1, 12, 1),
+    BondSpec(2, 3, 2),
+    BondSpec(2, 9, 1),
+    BondSpec(4, 5, 1),
+    BondSpec(4, 13, 1),
+    BondSpec(4, 14, 1),
+    BondSpec(5, 6, 1),
+    BondSpec(5, 15, 1),
+    BondSpec(5, 16, 1),
+    BondSpec(6, 7, 2),
+    BondSpec(6, 8, 1),
+    BondSpec(8, 17, 1),
+    BondSpec(9, 18, 1)
+  };
+  for (int i=0; i<18; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakePHECompound() {
+  CompoundPtr c( new Compound("PHE"));
+  c->SetOneLetterCode('F');
+  c->SetChemClass(mol::ChemClass('L'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C9 H11 N O2");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "N", "N", "N", false, true),
+    AtomSpec(1, "CA", "CA", "C", false, true),
+    AtomSpec(2, "C", "C", "C", false, true),
+    AtomSpec(3, "O", "O", "O", false, true),
+    AtomSpec(4, "CB", "CB", "C", false, true),
+    AtomSpec(5, "CG", "CG", "C", false, true),
+    AtomSpec(6, "CD1", "CD1", "C", false, true),
+    AtomSpec(7, "CD2", "CD2", "C", false, true),
+    AtomSpec(8, "CE1", "CE1", "C", false, true),
+    AtomSpec(9, "CE2", "CE2", "C", false, true),
+    AtomSpec(10, "CZ", "CZ", "C", false, true),
+    AtomSpec(11, "OXT", "OXT", "O", true, true),
+    AtomSpec(12, "H", "H", "H", false, true),
+    AtomSpec(13, "H2", "HN2", "H", true, true),
+    AtomSpec(14, "HA", "HA", "H", false, true),
+    AtomSpec(15, "HB2", "1HB", "H", false, true),
+    AtomSpec(16, "HB3", "2HB", "H", false, true),
+    AtomSpec(17, "HD1", "HD1", "H", false, true),
+    AtomSpec(18, "HD2", "HD2", "H", false, true),
+    AtomSpec(19, "HE1", "HE1", "H", false, true),
+    AtomSpec(20, "HE2", "HE2", "H", false, true),
+    AtomSpec(21, "HZ", "HZ", "H", false, true),
+    AtomSpec(22, "HXT", "HXT", "H", true, true)
+  };
+  for (int i=0; i<23; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 12, 1),
+    BondSpec(0, 13, 1),
+    BondSpec(1, 2, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(1, 14, 1),
+    BondSpec(2, 3, 2),
+    BondSpec(2, 11, 1),
+    BondSpec(4, 5, 1),
+    BondSpec(4, 15, 1),
+    BondSpec(4, 16, 1),
+    BondSpec(5, 6, 2),
+    BondSpec(5, 7, 1),
+    BondSpec(6, 8, 1),
+    BondSpec(6, 17, 1),
+    BondSpec(7, 9, 2),
+    BondSpec(7, 18, 1),
+    BondSpec(8, 10, 2),
+    BondSpec(8, 19, 1),
+    BondSpec(9, 10, 1),
+    BondSpec(9, 20, 1),
+    BondSpec(10, 21, 1),
+    BondSpec(11, 22, 1)
+  };
+  for (int i=0; i<23; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakeGLYCompound() {
+  CompoundPtr c( new Compound("GLY"));
+  c->SetOneLetterCode('G');
+  c->SetChemClass(mol::ChemClass('P'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C2 H5 N O2");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "N", "N", "N", false, true),
+    AtomSpec(1, "CA", "CA", "C", false, true),
+    AtomSpec(2, "C", "C", "C", false, true),
+    AtomSpec(3, "O", "O", "O", false, true),
+    AtomSpec(4, "OXT", "OXT", "O", true, true),
+    AtomSpec(5, "H", "H", "H", false, true),
+    AtomSpec(6, "H2", "HN2", "H", true, true),
+    AtomSpec(7, "HA2", "HA1", "H", false, true),
+    AtomSpec(8, "HA3", "HA2", "H", false, true),
+    AtomSpec(9, "HXT", "HXT", "H", true, true)
+  };
+  for (int i=0; i<10; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 5, 1),
+    BondSpec(0, 6, 1),
+    BondSpec(1, 2, 1),
+    BondSpec(1, 7, 1),
+    BondSpec(1, 8, 1),
+    BondSpec(2, 3, 2),
+    BondSpec(2, 4, 1),
+    BondSpec(4, 9, 1)
+  };
+  for (int i=0; i<9; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakeHISCompound() {
+  CompoundPtr c( new Compound("HIS"));
+  c->SetOneLetterCode('H');
+  c->SetChemClass(mol::ChemClass('L'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C6 H10 N3 O2");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "N", "N", "N", false, true),
+    AtomSpec(1, "CA", "CA", "C", false, true),
+    AtomSpec(2, "C", "C", "C", false, true),
+    AtomSpec(3, "O", "O", "O", false, true),
+    AtomSpec(4, "CB", "CB", "C", false, true),
+    AtomSpec(5, "CG", "CG", "C", false, true),
+    AtomSpec(6, "ND1", "ND1", "N", false, true),
+    AtomSpec(7, "CD2", "CD2", "C", false, true),
+    AtomSpec(8, "CE1", "CE1", "C", false, true),
+    AtomSpec(9, "NE2", "NE2", "N", false, true),
+    AtomSpec(10, "OXT", "OXT", "O", true, true),
+    AtomSpec(11, "H", "H", "H", false, true),
+    AtomSpec(12, "H2", "HN2", "H", true, true),
+    AtomSpec(13, "HA", "HA", "H", false, true),
+    AtomSpec(14, "HB2", "1HB", "H", false, true),
+    AtomSpec(15, "HB3", "2HB", "H", false, true),
+    AtomSpec(16, "HD1", "HD1", "H", false, true),
+    AtomSpec(17, "HD2", "HD2", "H", false, true),
+    AtomSpec(18, "HE1", "HE1", "H", false, true),
+    AtomSpec(19, "HE2", "HE2", "H", false, true),
+    AtomSpec(20, "HXT", "HXT", "H", true, true)
+  };
+  for (int i=0; i<21; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 11, 1),
+    BondSpec(0, 12, 1),
+    BondSpec(1, 2, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(1, 13, 1),
+    BondSpec(2, 3, 2),
+    BondSpec(2, 10, 1),
+    BondSpec(4, 5, 1),
+    BondSpec(4, 14, 1),
+    BondSpec(4, 15, 1),
+    BondSpec(5, 6, 1),
+    BondSpec(5, 7, 2),
+    BondSpec(6, 8, 2),
+    BondSpec(6, 16, 1),
+    BondSpec(7, 9, 1),
+    BondSpec(7, 17, 1),
+    BondSpec(8, 9, 1),
+    BondSpec(8, 18, 1),
+    BondSpec(9, 19, 1),
+    BondSpec(10, 20, 1)
+  };
+  for (int i=0; i<21; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakeILECompound() {
+  CompoundPtr c( new Compound("ILE"));
+  c->SetOneLetterCode('I');
+  c->SetChemClass(mol::ChemClass('L'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C6 H13 N O2");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "N", "N", "N", false, true),
+    AtomSpec(1, "CA", "CA", "C", false, true),
+    AtomSpec(2, "C", "C", "C", false, true),
+    AtomSpec(3, "O", "O", "O", false, true),
+    AtomSpec(4, "CB", "CB", "C", false, true),
+    AtomSpec(5, "CG1", "CG1", "C", false, true),
+    AtomSpec(6, "CG2", "CG2", "C", false, true),
+    AtomSpec(7, "CD1", "CD1", "C", false, true),
+    AtomSpec(8, "OXT", "OXT", "O", true, true),
+    AtomSpec(9, "H", "H", "H", false, true),
+    AtomSpec(10, "H2", "HN2", "H", true, true),
+    AtomSpec(11, "HA", "HA", "H", false, true),
+    AtomSpec(12, "HB", "HB", "H", false, true),
+    AtomSpec(13, "HG12", "1HG1", "H", false, true),
+    AtomSpec(14, "HG13", "2HG1", "H", false, true),
+    AtomSpec(15, "HG21", "1HG2", "H", false, true),
+    AtomSpec(16, "HG22", "2HG2", "H", false, true),
+    AtomSpec(17, "HG23", "3HG2", "H", false, true),
+    AtomSpec(18, "HD11", "1HD1", "H", false, true),
+    AtomSpec(19, "HD12", "2HD1", "H", false, true),
+    AtomSpec(20, "HD13", "3HD1", "H", false, true),
+    AtomSpec(21, "HXT", "HXT", "H", true, true)
+  };
+  for (int i=0; i<22; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 9, 1),
+    BondSpec(0, 10, 1),
+    BondSpec(1, 2, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(1, 11, 1),
+    BondSpec(2, 3, 2),
+    BondSpec(2, 8, 1),
+    BondSpec(4, 5, 1),
+    BondSpec(4, 6, 1),
+    BondSpec(4, 12, 1),
+    BondSpec(5, 7, 1),
+    BondSpec(5, 13, 1),
+    BondSpec(5, 14, 1),
+    BondSpec(6, 15, 1),
+    BondSpec(6, 16, 1),
+    BondSpec(6, 17, 1),
+    BondSpec(7, 18, 1),
+    BondSpec(7, 19, 1),
+    BondSpec(7, 20, 1),
+    BondSpec(8, 21, 1)
+  };
+  for (int i=0; i<21; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakeLYSCompound() {
+  CompoundPtr c( new Compound("LYS"));
+  c->SetOneLetterCode('K');
+  c->SetChemClass(mol::ChemClass('L'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C6 H15 N2 O2");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "N", "N", "N", false, true),
+    AtomSpec(1, "CA", "CA", "C", false, true),
+    AtomSpec(2, "C", "C", "C", false, true),
+    AtomSpec(3, "O", "O", "O", false, true),
+    AtomSpec(4, "CB", "CB", "C", false, true),
+    AtomSpec(5, "CG", "CG", "C", false, true),
+    AtomSpec(6, "CD", "CD", "C", false, true),
+    AtomSpec(7, "CE", "CE", "C", false, true),
+    AtomSpec(8, "NZ", "NZ", "N", false, true),
+    AtomSpec(9, "OXT", "OXT", "O", true, true),
+    AtomSpec(10, "H", "H", "H", false, true),
+    AtomSpec(11, "H2", "HN2", "H", true, true),
+    AtomSpec(12, "HA", "HA", "H", false, true),
+    AtomSpec(13, "HB2", "1HB", "H", false, true),
+    AtomSpec(14, "HB3", "2HB", "H", false, true),
+    AtomSpec(15, "HG2", "1HG", "H", false, true),
+    AtomSpec(16, "HG3", "2HG", "H", false, true),
+    AtomSpec(17, "HD2", "1HD", "H", false, true),
+    AtomSpec(18, "HD3", "2HD", "H", false, true),
+    AtomSpec(19, "HE2", "1HE", "H", false, true),
+    AtomSpec(20, "HE3", "2HE", "H", false, true),
+    AtomSpec(21, "HZ1", "1HZ", "H", false, true),
+    AtomSpec(22, "HZ2", "2HZ", "H", false, true),
+    AtomSpec(23, "HZ3", "3HZ", "H", false, true),
+    AtomSpec(24, "HXT", "HXT", "H", true, true)
+  };
+  for (int i=0; i<25; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 10, 1),
+    BondSpec(0, 11, 1),
+    BondSpec(1, 2, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(1, 12, 1),
+    BondSpec(2, 3, 2),
+    BondSpec(2, 9, 1),
+    BondSpec(4, 5, 1),
+    BondSpec(4, 13, 1),
+    BondSpec(4, 14, 1),
+    BondSpec(5, 6, 1),
+    BondSpec(5, 15, 1),
+    BondSpec(5, 16, 1),
+    BondSpec(6, 7, 1),
+    BondSpec(6, 17, 1),
+    BondSpec(6, 18, 1),
+    BondSpec(7, 8, 1),
+    BondSpec(7, 19, 1),
+    BondSpec(7, 20, 1),
+    BondSpec(8, 21, 1),
+    BondSpec(8, 22, 1),
+    BondSpec(8, 23, 1),
+    BondSpec(9, 24, 1)
+  };
+  for (int i=0; i<24; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakeLEUCompound() {
+  CompoundPtr c( new Compound("LEU"));
+  c->SetOneLetterCode('L');
+  c->SetChemClass(mol::ChemClass('L'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C6 H13 N O2");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "N", "N", "N", false, true),
+    AtomSpec(1, "CA", "CA", "C", false, true),
+    AtomSpec(2, "C", "C", "C", false, true),
+    AtomSpec(3, "O", "O", "O", false, true),
+    AtomSpec(4, "CB", "CB", "C", false, true),
+    AtomSpec(5, "CG", "CG", "C", false, true),
+    AtomSpec(6, "CD1", "CD1", "C", false, true),
+    AtomSpec(7, "CD2", "CD2", "C", false, true),
+    AtomSpec(8, "OXT", "OXT", "O", true, true),
+    AtomSpec(9, "H", "H", "H", false, true),
+    AtomSpec(10, "H2", "HN2", "H", true, true),
+    AtomSpec(11, "HA", "HA", "H", false, true),
+    AtomSpec(12, "HB2", "1HB", "H", false, true),
+    AtomSpec(13, "HB3", "2HB", "H", false, true),
+    AtomSpec(14, "HG", "HG", "H", false, true),
+    AtomSpec(15, "HD11", "1HD1", "H", false, true),
+    AtomSpec(16, "HD12", "2HD1", "H", false, true),
+    AtomSpec(17, "HD13", "3HD1", "H", false, true),
+    AtomSpec(18, "HD21", "1HD2", "H", false, true),
+    AtomSpec(19, "HD22", "2HD2", "H", false, true),
+    AtomSpec(20, "HD23", "3HD2", "H", false, true),
+    AtomSpec(21, "HXT", "HXT", "H", true, true)
+  };
+  for (int i=0; i<22; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 9, 1),
+    BondSpec(0, 10, 1),
+    BondSpec(1, 2, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(1, 11, 1),
+    BondSpec(2, 3, 2),
+    BondSpec(2, 8, 1),
+    BondSpec(4, 5, 1),
+    BondSpec(4, 12, 1),
+    BondSpec(4, 13, 1),
+    BondSpec(5, 6, 1),
+    BondSpec(5, 7, 1),
+    BondSpec(5, 14, 1),
+    BondSpec(6, 15, 1),
+    BondSpec(6, 16, 1),
+    BondSpec(6, 17, 1),
+    BondSpec(7, 18, 1),
+    BondSpec(7, 19, 1),
+    BondSpec(7, 20, 1),
+    BondSpec(8, 21, 1)
+  };
+  for (int i=0; i<21; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakeMETCompound() {
+  CompoundPtr c( new Compound("MET"));
+  c->SetOneLetterCode('M');
+  c->SetChemClass(mol::ChemClass('L'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C5 H11 N O2 S");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "N", "N", "N", false, true),
+    AtomSpec(1, "CA", "CA", "C", false, true),
+    AtomSpec(2, "C", "C", "C", false, true),
+    AtomSpec(3, "O", "O", "O", false, true),
+    AtomSpec(4, "CB", "CB", "C", false, true),
+    AtomSpec(5, "CG", "CG", "C", false, true),
+    AtomSpec(6, "SD", "SD", "S", false, true),
+    AtomSpec(7, "CE", "CE", "C", false, true),
+    AtomSpec(8, "OXT", "OXT", "O", true, true),
+    AtomSpec(9, "H", "H", "H", false, true),
+    AtomSpec(10, "H2", "HN2", "H", true, true),
+    AtomSpec(11, "HA", "HA", "H", false, true),
+    AtomSpec(12, "HB2", "1HB", "H", false, true),
+    AtomSpec(13, "HB3", "2HB", "H", false, true),
+    AtomSpec(14, "HG2", "1HG", "H", false, true),
+    AtomSpec(15, "HG3", "2HG", "H", false, true),
+    AtomSpec(16, "HE1", "1HE", "H", false, true),
+    AtomSpec(17, "HE2", "2HE", "H", false, true),
+    AtomSpec(18, "HE3", "3HE", "H", false, true),
+    AtomSpec(19, "HXT", "HXT", "H", true, true)
+  };
+  for (int i=0; i<20; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 9, 1),
+    BondSpec(0, 10, 1),
+    BondSpec(1, 2, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(1, 11, 1),
+    BondSpec(2, 3, 2),
+    BondSpec(2, 8, 1),
+    BondSpec(4, 5, 1),
+    BondSpec(4, 12, 1),
+    BondSpec(4, 13, 1),
+    BondSpec(5, 6, 1),
+    BondSpec(5, 14, 1),
+    BondSpec(5, 15, 1),
+    BondSpec(6, 7, 1),
+    BondSpec(7, 16, 1),
+    BondSpec(7, 17, 1),
+    BondSpec(7, 18, 1),
+    BondSpec(8, 19, 1)
+  };
+  for (int i=0; i<19; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakeASNCompound() {
+  CompoundPtr c( new Compound("ASN"));
+  c->SetOneLetterCode('N');
+  c->SetChemClass(mol::ChemClass('L'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C4 H8 N2 O3");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "N", "N", "N", false, true),
+    AtomSpec(1, "CA", "CA", "C", false, true),
+    AtomSpec(2, "C", "C", "C", false, true),
+    AtomSpec(3, "O", "O", "O", false, true),
+    AtomSpec(4, "CB", "CB", "C", false, true),
+    AtomSpec(5, "CG", "CG", "C", false, true),
+    AtomSpec(6, "OD1", "OD1", "O", false, true),
+    AtomSpec(7, "ND2", "ND2", "N", true, true),
+    AtomSpec(8, "OXT", "OXT", "O", true, true),
+    AtomSpec(9, "H", "H", "H", false, true),
+    AtomSpec(10, "H2", "HN2", "H", true, true),
+    AtomSpec(11, "HA", "HA", "H", false, true),
+    AtomSpec(12, "HB2", "HB1", "H", false, true),
+    AtomSpec(13, "HB3", "HB2", "H", false, true),
+    AtomSpec(14, "HD21", "HD21", "H", true, true),
+    AtomSpec(15, "HD22", "HD22", "H", true, true),
+    AtomSpec(16, "HXT", "HXT", "H", true, true)
+  };
+  for (int i=0; i<17; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 9, 1),
+    BondSpec(0, 10, 1),
+    BondSpec(1, 2, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(1, 11, 1),
+    BondSpec(2, 3, 2),
+    BondSpec(2, 8, 1),
+    BondSpec(4, 5, 1),
+    BondSpec(4, 12, 1),
+    BondSpec(4, 13, 1),
+    BondSpec(5, 6, 2),
+    BondSpec(5, 7, 1),
+    BondSpec(7, 14, 1),
+    BondSpec(7, 15, 1),
+    BondSpec(8, 16, 1)
+  };
+  for (int i=0; i<16; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakePROCompound() {
+  CompoundPtr c( new Compound("PRO"));
+  c->SetOneLetterCode('P');
+  c->SetChemClass(mol::ChemClass('L'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C5 H9 N O2");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "N", "N", "N", false, true),
+    AtomSpec(1, "CA", "CA", "C", false, true),
+    AtomSpec(2, "C", "C", "C", false, true),
+    AtomSpec(3, "O", "O", "O", false, true),
+    AtomSpec(4, "CB", "CB", "C", false, true),
+    AtomSpec(5, "CG", "CG", "C", false, true),
+    AtomSpec(6, "CD", "CD", "C", false, true),
+    AtomSpec(7, "OXT", "OXT", "O", true, true),
+    AtomSpec(8, "H", "HT1", "H", true, true),
+    AtomSpec(9, "HA", "HA", "H", false, true),
+    AtomSpec(10, "HB2", "1HB", "H", false, true),
+    AtomSpec(11, "HB3", "2HB", "H", false, true),
+    AtomSpec(12, "HG2", "1HG", "H", false, true),
+    AtomSpec(13, "HG3", "2HG", "H", false, true),
+    AtomSpec(14, "HD2", "1HD", "H", false, true),
+    AtomSpec(15, "HD3", "2HD", "H", false, true),
+    AtomSpec(16, "HXT", "HXT", "H", true, true)
+  };
+  for (int i=0; i<17; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 6, 1),
+    BondSpec(0, 8, 1),
+    BondSpec(1, 2, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(1, 9, 1),
+    BondSpec(2, 3, 2),
+    BondSpec(2, 7, 1),
+    BondSpec(4, 5, 1),
+    BondSpec(4, 10, 1),
+    BondSpec(4, 11, 1),
+    BondSpec(5, 6, 1),
+    BondSpec(5, 12, 1),
+    BondSpec(5, 13, 1),
+    BondSpec(6, 14, 1),
+    BondSpec(6, 15, 1),
+    BondSpec(7, 16, 1)
+  };
+  for (int i=0; i<17; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakeGLNCompound() {
+  CompoundPtr c( new Compound("GLN"));
+  c->SetOneLetterCode('Q');
+  c->SetChemClass(mol::ChemClass('L'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C5 H10 N2 O3");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "N", "N", "N", false, true),
+    AtomSpec(1, "CA", "CA", "C", false, true),
+    AtomSpec(2, "C", "C", "C", false, true),
+    AtomSpec(3, "O", "O", "O", false, true),
+    AtomSpec(4, "CB", "CB", "C", false, true),
+    AtomSpec(5, "CG", "CG", "C", false, true),
+    AtomSpec(6, "CD", "CD", "C", false, true),
+    AtomSpec(7, "OE1", "OE1", "O", false, true),
+    AtomSpec(8, "NE2", "NE2", "N", false, true),
+    AtomSpec(9, "OXT", "OXT", "O", true, true),
+    AtomSpec(10, "H", "H", "H", false, true),
+    AtomSpec(11, "H2", "HN2", "H", true, true),
+    AtomSpec(12, "HA", "HA", "H", false, true),
+    AtomSpec(13, "HB2", "1HB", "H", false, true),
+    AtomSpec(14, "HB3", "2HB", "H", false, true),
+    AtomSpec(15, "HG2", "1HG", "H", false, true),
+    AtomSpec(16, "HG3", "2HG", "H", false, true),
+    AtomSpec(17, "HE21", "1HE2", "H", false, true),
+    AtomSpec(18, "HE22", "2HE2", "H", false, true),
+    AtomSpec(19, "HXT", "HXT", "H", true, true)
+  };
+  for (int i=0; i<20; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 10, 1),
+    BondSpec(0, 11, 1),
+    BondSpec(1, 2, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(1, 12, 1),
+    BondSpec(2, 3, 2),
+    BondSpec(2, 9, 1),
+    BondSpec(4, 5, 1),
+    BondSpec(4, 13, 1),
+    BondSpec(4, 14, 1),
+    BondSpec(5, 6, 1),
+    BondSpec(5, 15, 1),
+    BondSpec(5, 16, 1),
+    BondSpec(6, 7, 2),
+    BondSpec(6, 8, 1),
+    BondSpec(8, 17, 1),
+    BondSpec(8, 18, 1),
+    BondSpec(9, 19, 1)
+  };
+  for (int i=0; i<19; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakeARGCompound() {
+  CompoundPtr c( new Compound("ARG"));
+  c->SetOneLetterCode('R');
+  c->SetChemClass(mol::ChemClass('L'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C6 H15 N4 O2");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "N", "N", "N", false, true),
+    AtomSpec(1, "CA", "CA", "C", false, true),
+    AtomSpec(2, "C", "C", "C", false, true),
+    AtomSpec(3, "O", "O", "O", false, true),
+    AtomSpec(4, "CB", "CB", "C", false, true),
+    AtomSpec(5, "CG", "CG", "C", false, true),
+    AtomSpec(6, "CD", "CD", "C", false, true),
+    AtomSpec(7, "NE", "NE", "N", false, true),
+    AtomSpec(8, "CZ", "CZ", "C", false, true),
+    AtomSpec(9, "NH1", "NH1", "N", false, true),
+    AtomSpec(10, "NH2", "NH2", "N", false, true),
+    AtomSpec(11, "OXT", "OXT", "O", true, true),
+    AtomSpec(12, "H", "H", "H", false, true),
+    AtomSpec(13, "H2", "HN2", "H", true, true),
+    AtomSpec(14, "HA", "HA", "H", false, true),
+    AtomSpec(15, "HB2", "1HB", "H", false, true),
+    AtomSpec(16, "HB3", "2HB", "H", false, true),
+    AtomSpec(17, "HG2", "1HG", "H", false, true),
+    AtomSpec(18, "HG3", "2HG", "H", false, true),
+    AtomSpec(19, "HD2", "1HD", "H", false, true),
+    AtomSpec(20, "HD3", "2HD", "H", false, true),
+    AtomSpec(21, "HE", "HE", "H", false, true),
+    AtomSpec(22, "HH11", "1HH1", "H", false, true),
+    AtomSpec(23, "HH12", "2HH1", "H", false, true),
+    AtomSpec(24, "HH21", "1HH2", "H", false, true),
+    AtomSpec(25, "HH22", "2HH2", "H", false, true),
+    AtomSpec(26, "HXT", "HXT", "H", true, true)
+  };
+  for (int i=0; i<27; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 12, 1),
+    BondSpec(0, 13, 1),
+    BondSpec(1, 2, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(1, 14, 1),
+    BondSpec(2, 3, 2),
+    BondSpec(2, 11, 1),
+    BondSpec(4, 5, 1),
+    BondSpec(4, 15, 1),
+    BondSpec(4, 16, 1),
+    BondSpec(5, 6, 1),
+    BondSpec(5, 17, 1),
+    BondSpec(5, 18, 1),
+    BondSpec(6, 7, 1),
+    BondSpec(6, 19, 1),
+    BondSpec(6, 20, 1),
+    BondSpec(7, 8, 1),
+    BondSpec(7, 21, 1),
+    BondSpec(8, 9, 1),
+    BondSpec(8, 10, 2),
+    BondSpec(9, 22, 1),
+    BondSpec(9, 23, 1),
+    BondSpec(10, 24, 1),
+    BondSpec(10, 25, 1),
+    BondSpec(11, 26, 1)
+  };
+  for (int i=0; i<26; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakeSERCompound() {
+  CompoundPtr c( new Compound("SER"));
+  c->SetOneLetterCode('S');
+  c->SetChemClass(mol::ChemClass('L'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C3 H7 N O3");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "N", "N", "N", false, true),
+    AtomSpec(1, "CA", "CA", "C", false, true),
+    AtomSpec(2, "C", "C", "C", false, true),
+    AtomSpec(3, "O", "O", "O", false, true),
+    AtomSpec(4, "CB", "CB", "C", false, true),
+    AtomSpec(5, "OG", "OG", "O", false, true),
+    AtomSpec(6, "OXT", "OXT", "O", true, true),
+    AtomSpec(7, "H", "H", "H", false, true),
+    AtomSpec(8, "H2", "HN2", "H", true, true),
+    AtomSpec(9, "HA", "HA", "H", false, true),
+    AtomSpec(10, "HB2", "1HB", "H", false, true),
+    AtomSpec(11, "HB3", "2HB", "H", false, true),
+    AtomSpec(12, "HG", "HG", "H", false, true),
+    AtomSpec(13, "HXT", "HXT", "H", true, true)
+  };
+  for (int i=0; i<14; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 7, 1),
+    BondSpec(0, 8, 1),
+    BondSpec(1, 2, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(1, 9, 1),
+    BondSpec(2, 3, 2),
+    BondSpec(2, 6, 1),
+    BondSpec(4, 5, 1),
+    BondSpec(4, 10, 1),
+    BondSpec(4, 11, 1),
+    BondSpec(5, 12, 1),
+    BondSpec(6, 13, 1)
+  };
+  for (int i=0; i<13; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakeTHRCompound() {
+  CompoundPtr c( new Compound("THR"));
+  c->SetOneLetterCode('T');
+  c->SetChemClass(mol::ChemClass('L'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C4 H9 N O3");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "N", "N", "N", false, true),
+    AtomSpec(1, "CA", "CA", "C", false, true),
+    AtomSpec(2, "C", "C", "C", false, true),
+    AtomSpec(3, "O", "O", "O", false, true),
+    AtomSpec(4, "CB", "CB", "C", false, true),
+    AtomSpec(5, "OG1", "OG1", "O", false, true),
+    AtomSpec(6, "CG2", "CG2", "C", false, true),
+    AtomSpec(7, "OXT", "OXT", "O", true, true),
+    AtomSpec(8, "H", "H", "H", false, true),
+    AtomSpec(9, "H2", "HN2", "H", true, true),
+    AtomSpec(10, "HA", "HA", "H", false, true),
+    AtomSpec(11, "HB", "HB", "H", false, true),
+    AtomSpec(12, "HG1", "HG1", "H", false, true),
+    AtomSpec(13, "HG21", "1HG2", "H", false, true),
+    AtomSpec(14, "HG22", "2HG2", "H", false, true),
+    AtomSpec(15, "HG23", "3HG2", "H", false, true),
+    AtomSpec(16, "HXT", "HXT", "H", true, true)
+  };
+  for (int i=0; i<17; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 8, 1),
+    BondSpec(0, 9, 1),
+    BondSpec(1, 2, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(1, 10, 1),
+    BondSpec(2, 3, 2),
+    BondSpec(2, 7, 1),
+    BondSpec(4, 5, 1),
+    BondSpec(4, 6, 1),
+    BondSpec(4, 11, 1),
+    BondSpec(5, 12, 1),
+    BondSpec(6, 13, 1),
+    BondSpec(6, 14, 1),
+    BondSpec(6, 15, 1),
+    BondSpec(7, 16, 1)
+  };
+  for (int i=0; i<16; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakeVALCompound() {
+  CompoundPtr c( new Compound("VAL"));
+  c->SetOneLetterCode('V');
+  c->SetChemClass(mol::ChemClass('L'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C5 H11 N O2");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "N", "N", "N", false, true),
+    AtomSpec(1, "CA", "CA", "C", false, true),
+    AtomSpec(2, "C", "C", "C", false, true),
+    AtomSpec(3, "O", "O", "O", false, true),
+    AtomSpec(4, "CB", "CB", "C", false, true),
+    AtomSpec(5, "CG1", "CG1", "C", false, true),
+    AtomSpec(6, "CG2", "CG2", "C", false, true),
+    AtomSpec(7, "OXT", "OXT", "O", true, true),
+    AtomSpec(8, "H", "H", "H", false, true),
+    AtomSpec(9, "H2", "HN2", "H", true, true),
+    AtomSpec(10, "HA", "HA", "H", false, true),
+    AtomSpec(11, "HB", "HB", "H", false, true),
+    AtomSpec(12, "HG11", "1HG1", "H", false, true),
+    AtomSpec(13, "HG12", "2HG1", "H", false, true),
+    AtomSpec(14, "HG13", "3HG1", "H", false, true),
+    AtomSpec(15, "HG21", "1HG2", "H", false, true),
+    AtomSpec(16, "HG22", "2HG2", "H", false, true),
+    AtomSpec(17, "HG23", "3HG2", "H", false, true),
+    AtomSpec(18, "HXT", "HXT", "H", true, true)
+  };
+  for (int i=0; i<19; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 8, 1),
+    BondSpec(0, 9, 1),
+    BondSpec(1, 2, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(1, 10, 1),
+    BondSpec(2, 3, 2),
+    BondSpec(2, 7, 1),
+    BondSpec(4, 5, 1),
+    BondSpec(4, 6, 1),
+    BondSpec(4, 11, 1),
+    BondSpec(5, 12, 1),
+    BondSpec(5, 13, 1),
+    BondSpec(5, 14, 1),
+    BondSpec(6, 15, 1),
+    BondSpec(6, 16, 1),
+    BondSpec(6, 17, 1),
+    BondSpec(7, 18, 1)
+  };
+  for (int i=0; i<18; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakeTRPCompound() {
+  CompoundPtr c( new Compound("TRP"));
+  c->SetOneLetterCode('W');
+  c->SetChemClass(mol::ChemClass('L'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C11 H12 N2 O2");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "N", "N", "N", false, true),
+    AtomSpec(1, "CA", "CA", "C", false, true),
+    AtomSpec(2, "C", "C", "C", false, true),
+    AtomSpec(3, "O", "O", "O", false, true),
+    AtomSpec(4, "CB", "CB", "C", false, true),
+    AtomSpec(5, "CG", "CG", "C", false, true),
+    AtomSpec(6, "CD1", "CD1", "C", false, true),
+    AtomSpec(7, "CD2", "CD2", "C", false, true),
+    AtomSpec(8, "NE1", "NE1", "N", false, true),
+    AtomSpec(9, "CE2", "CE2", "C", false, true),
+    AtomSpec(10, "CE3", "CE3", "C", false, true),
+    AtomSpec(11, "CZ2", "CZ2", "C", false, true),
+    AtomSpec(12, "CZ3", "CZ3", "C", false, true),
+    AtomSpec(13, "CH2", "CH2", "C", false, true),
+    AtomSpec(14, "OXT", "OXT", "O", true, true),
+    AtomSpec(15, "H", "H", "H", false, true),
+    AtomSpec(16, "H2", "HN2", "H", true, true),
+    AtomSpec(17, "HA", "HA", "H", false, true),
+    AtomSpec(18, "HB2", "1HB", "H", false, true),
+    AtomSpec(19, "HB3", "2HB", "H", false, true),
+    AtomSpec(20, "HD1", "HD1", "H", false, true),
+    AtomSpec(21, "HE1", "HE1", "H", false, true),
+    AtomSpec(22, "HE3", "HE3", "H", false, true),
+    AtomSpec(23, "HZ2", "HZ2", "H", false, true),
+    AtomSpec(24, "HZ3", "HZ3", "H", false, true),
+    AtomSpec(25, "HH2", "HH2", "H", false, true),
+    AtomSpec(26, "HXT", "HXT", "H", true, true)
+  };
+  for (int i=0; i<27; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 15, 1),
+    BondSpec(0, 16, 1),
+    BondSpec(1, 2, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(1, 17, 1),
+    BondSpec(2, 3, 2),
+    BondSpec(2, 14, 1),
+    BondSpec(4, 5, 1),
+    BondSpec(4, 18, 1),
+    BondSpec(4, 19, 1),
+    BondSpec(5, 6, 2),
+    BondSpec(5, 7, 1),
+    BondSpec(6, 8, 1),
+    BondSpec(6, 20, 1),
+    BondSpec(7, 9, 2),
+    BondSpec(7, 10, 1),
+    BondSpec(8, 9, 1),
+    BondSpec(8, 21, 1),
+    BondSpec(9, 11, 1),
+    BondSpec(10, 12, 2),
+    BondSpec(10, 22, 1),
+    BondSpec(11, 13, 2),
+    BondSpec(11, 23, 1),
+    BondSpec(12, 13, 1),
+    BondSpec(12, 24, 1),
+    BondSpec(13, 25, 1),
+    BondSpec(14, 26, 1)
+  };
+  for (int i=0; i<28; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakeTYRCompound() {
+  CompoundPtr c( new Compound("TYR"));
+  c->SetOneLetterCode('Y');
+  c->SetChemClass(mol::ChemClass('L'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C9 H11 N O3");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "N", "N", "N", false, true),
+    AtomSpec(1, "CA", "CA", "C", false, true),
+    AtomSpec(2, "C", "C", "C", false, true),
+    AtomSpec(3, "O", "O", "O", false, true),
+    AtomSpec(4, "CB", "CB", "C", false, true),
+    AtomSpec(5, "CG", "CG", "C", false, true),
+    AtomSpec(6, "CD1", "CD1", "C", false, true),
+    AtomSpec(7, "CD2", "CD2", "C", false, true),
+    AtomSpec(8, "CE1", "CE1", "C", false, true),
+    AtomSpec(9, "CE2", "CE2", "C", false, true),
+    AtomSpec(10, "CZ", "CZ", "C", false, true),
+    AtomSpec(11, "OH", "OH", "O", false, true),
+    AtomSpec(12, "OXT", "OXT", "O", true, true),
+    AtomSpec(13, "H", "H", "H", false, true),
+    AtomSpec(14, "H2", "HN2", "H", true, true),
+    AtomSpec(15, "HA", "HA", "H", false, true),
+    AtomSpec(16, "HB2", "1HB", "H", false, true),
+    AtomSpec(17, "HB3", "2HB", "H", false, true),
+    AtomSpec(18, "HD1", "HD1", "H", false, true),
+    AtomSpec(19, "HD2", "HD2", "H", false, true),
+    AtomSpec(20, "HE1", "HE1", "H", false, true),
+    AtomSpec(21, "HE2", "HE2", "H", false, true),
+    AtomSpec(22, "HH", "HH", "H", false, true),
+    AtomSpec(23, "HXT", "HXT", "H", true, true)
+  };
+  for (int i=0; i<24; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 13, 1),
+    BondSpec(0, 14, 1),
+    BondSpec(1, 2, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(1, 15, 1),
+    BondSpec(2, 3, 2),
+    BondSpec(2, 12, 1),
+    BondSpec(4, 5, 1),
+    BondSpec(4, 16, 1),
+    BondSpec(4, 17, 1),
+    BondSpec(5, 6, 2),
+    BondSpec(5, 7, 1),
+    BondSpec(6, 8, 1),
+    BondSpec(6, 18, 1),
+    BondSpec(7, 9, 2),
+    BondSpec(7, 19, 1),
+    BondSpec(8, 10, 2),
+    BondSpec(8, 20, 1),
+    BondSpec(9, 10, 1),
+    BondSpec(9, 21, 1),
+    BondSpec(10, 11, 1),
+    BondSpec(11, 22, 1),
+    BondSpec(12, 23, 1)
+  };
+  for (int i=0; i<24; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakeGCompound() {
+  CompoundPtr c( new Compound("G"));
+  c->SetOneLetterCode('Y');
+  c->SetChemClass(mol::ChemClass('R'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C10 H14 N5 O8 P");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "OP3", "O3P", "O", true, true),
+    AtomSpec(1, "P", "P", "P", false, true),
+    AtomSpec(2, "OP1", "O1P", "O", false, true),
+    AtomSpec(3, "OP2", "O2P", "O", false, true),
+    AtomSpec(4, "O5'", "O5*", "O", false, true),
+    AtomSpec(5, "C5'", "C5*", "C", false, true),
+    AtomSpec(6, "C4'", "C4*", "C", false, true),
+    AtomSpec(7, "O4'", "O4*", "O", false, true),
+    AtomSpec(8, "C3'", "C3*", "C", false, true),
+    AtomSpec(9, "O3'", "O3*", "O", false, true),
+    AtomSpec(10, "C2'", "C2*", "C", false, true),
+    AtomSpec(11, "O2'", "O2*", "O", false, true),
+    AtomSpec(12, "C1'", "C1*", "C", false, true),
+    AtomSpec(13, "N9", "N9", "N", false, true),
+    AtomSpec(14, "C8", "C8", "C", false, true),
+    AtomSpec(15, "N7", "N7", "N", false, true),
+    AtomSpec(16, "C5", "C5", "C", false, true),
+    AtomSpec(17, "C6", "C6", "C", false, true),
+    AtomSpec(18, "O6", "O6", "O", false, true),
+    AtomSpec(19, "N1", "N1", "N", false, true),
+    AtomSpec(20, "C2", "C2", "C", false, true),
+    AtomSpec(21, "N2", "N2", "N", false, true),
+    AtomSpec(22, "N3", "N3", "N", false, true),
+    AtomSpec(23, "C4", "C4", "C", false, true),
+    AtomSpec(24, "HOP3", "3HOP", "H", false, true),
+    AtomSpec(25, "HOP2", "2HOP", "H", false, true),
+    AtomSpec(26, "H5'", "1H5*", "H", false, true),
+    AtomSpec(27, "H5''", "2H5*", "H", false, true),
+    AtomSpec(28, "H4'", "H4*", "H", false, true),
+    AtomSpec(29, "H3'", "H3*", "H", false, true),
+    AtomSpec(30, "HO3'", "H3T", "H", true, true),
+    AtomSpec(31, "H2'", "H2*", "H", false, true),
+    AtomSpec(32, "HO2'", "2HO*", "H", false, true),
+    AtomSpec(33, "H1'", "H1*", "H", false, true),
+    AtomSpec(34, "H8", "H8", "H", false, true),
+    AtomSpec(35, "H1", "H1", "H", false, true),
+    AtomSpec(36, "H21", "1H2", "H", false, true),
+    AtomSpec(37, "H22", "2H2", "H", false, true)
+  };
+  for (int i=0; i<38; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 24, 1),
+    BondSpec(1, 2, 2),
+    BondSpec(1, 3, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(3, 25, 1),
+    BondSpec(4, 5, 1),
+    BondSpec(5, 6, 1),
+    BondSpec(5, 26, 1),
+    BondSpec(5, 27, 1),
+    BondSpec(6, 7, 1),
+    BondSpec(6, 8, 1),
+    BondSpec(6, 28, 1),
+    BondSpec(7, 12, 1),
+    BondSpec(8, 9, 1),
+    BondSpec(8, 10, 1),
+    BondSpec(8, 29, 1),
+    BondSpec(9, 30, 1),
+    BondSpec(10, 11, 1),
+    BondSpec(10, 12, 1),
+    BondSpec(10, 31, 1),
+    BondSpec(11, 32, 1),
+    BondSpec(12, 13, 1),
+    BondSpec(12, 33, 1),
+    BondSpec(13, 14, 1),
+    BondSpec(13, 23, 1),
+    BondSpec(14, 15, 2),
+    BondSpec(14, 34, 1),
+    BondSpec(15, 16, 1),
+    BondSpec(16, 17, 1),
+    BondSpec(16, 23, 2),
+    BondSpec(17, 18, 2),
+    BondSpec(17, 19, 1),
+    BondSpec(19, 20, 1),
+    BondSpec(19, 35, 1),
+    BondSpec(20, 21, 1),
+    BondSpec(20, 22, 2),
+    BondSpec(21, 36, 1),
+    BondSpec(21, 37, 1),
+    BondSpec(22, 23, 1)
+  };
+  for (int i=0; i<40; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakeTCompound() {
+  CompoundPtr c( new Compound("T"));
+  c->SetOneLetterCode('Y');
+  c->SetChemClass(mol::ChemClass('S'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C10 H15 N2 O8 P");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "OP3", "O3P", "O", true, true),
+    AtomSpec(1, "P", "P", "P", false, true),
+    AtomSpec(2, "OP1", "O1P", "O", false, true),
+    AtomSpec(3, "OP2", "O2P", "O", false, true),
+    AtomSpec(4, "O5'", "O5*", "O", false, true),
+    AtomSpec(5, "C5'", "C5*", "C", false, true),
+    AtomSpec(6, "C4'", "C4*", "C", false, true),
+    AtomSpec(7, "O4'", "O4*", "O", false, true),
+    AtomSpec(8, "C3'", "C3*", "C", false, true),
+    AtomSpec(9, "O3'", "O3*", "O", false, true),
+    AtomSpec(10, "C2'", "C2*", "C", false, true),
+    AtomSpec(11, "C1'", "C1*", "C", false, true),
+    AtomSpec(12, "N1", "N1", "N", false, true),
+    AtomSpec(13, "C2", "C2", "C", false, true),
+    AtomSpec(14, "O2", "O2", "O", false, true),
+    AtomSpec(15, "N3", "N3", "N", false, true),
+    AtomSpec(16, "C4", "C4", "C", false, true),
+    AtomSpec(17, "O4", "O4", "O", false, true),
+    AtomSpec(18, "C5", "C5", "C", false, true),
+    AtomSpec(19, "C7", "C5M", "C", false, true),
+    AtomSpec(20, "C6", "C6", "C", false, true),
+    AtomSpec(21, "HOP3", "3HOP", "H", false, true),
+    AtomSpec(22, "HOP2", "2HOP", "H", false, true),
+    AtomSpec(23, "H5'", "1H5*", "H", false, true),
+    AtomSpec(24, "H5''", "2H5*", "H", false, true),
+    AtomSpec(25, "H4'", "H4*", "H", false, true),
+    AtomSpec(26, "H3'", "H3*", "H", false, true),
+    AtomSpec(27, "HO3'", "H3T", "H", true, true),
+    AtomSpec(28, "H2'", "1H2*", "H", false, true),
+    AtomSpec(29, "H2''", "2H2*", "H", false, true),
+    AtomSpec(30, "H1'", "H1*", "H", false, true),
+    AtomSpec(31, "H3", "H3", "H", false, true),
+    AtomSpec(32, "H71", "1H5M", "H", false, true),
+    AtomSpec(33, "H72", "2H5M", "H", false, true),
+    AtomSpec(34, "H73", "3H5M", "H", false, true),
+    AtomSpec(35, "H6", "H6", "H", false, true)
+  };
+  for (int i=0; i<36; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 21, 1),
+    BondSpec(1, 2, 2),
+    BondSpec(1, 3, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(3, 22, 1),
+    BondSpec(4, 5, 1),
+    BondSpec(5, 6, 1),
+    BondSpec(5, 23, 1),
+    BondSpec(5, 24, 1),
+    BondSpec(6, 7, 1),
+    BondSpec(6, 8, 1),
+    BondSpec(6, 25, 1),
+    BondSpec(7, 11, 1),
+    BondSpec(8, 9, 1),
+    BondSpec(8, 10, 1),
+    BondSpec(8, 26, 1),
+    BondSpec(9, 27, 1),
+    BondSpec(10, 11, 1),
+    BondSpec(10, 28, 1),
+    BondSpec(10, 29, 1),
+    BondSpec(11, 12, 1),
+    BondSpec(11, 30, 1),
+    BondSpec(12, 13, 1),
+    BondSpec(12, 20, 1),
+    BondSpec(13, 14, 2),
+    BondSpec(13, 15, 1),
+    BondSpec(15, 16, 1),
+    BondSpec(15, 31, 1),
+    BondSpec(16, 17, 2),
+    BondSpec(16, 18, 1),
+    BondSpec(18, 19, 1),
+    BondSpec(18, 20, 2),
+    BondSpec(19, 32, 1),
+    BondSpec(19, 33, 1),
+    BondSpec(19, 34, 1),
+    BondSpec(20, 35, 1)
+  };
+  for (int i=0; i<37; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakeACompound() {
+  CompoundPtr c( new Compound("A"));
+  c->SetOneLetterCode('Y');
+  c->SetChemClass(mol::ChemClass('R'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C10 H14 N5 O7 P");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "OP3", "O3P", "O", true, true),
+    AtomSpec(1, "P", "P", "P", false, true),
+    AtomSpec(2, "OP1", "O1P", "O", false, true),
+    AtomSpec(3, "OP2", "O2P", "O", false, true),
+    AtomSpec(4, "O5'", "O5*", "O", false, true),
+    AtomSpec(5, "C5'", "C5*", "C", false, true),
+    AtomSpec(6, "C4'", "C4*", "C", false, true),
+    AtomSpec(7, "O4'", "O4*", "O", false, true),
+    AtomSpec(8, "C3'", "C3*", "C", false, true),
+    AtomSpec(9, "O3'", "O3*", "O", false, true),
+    AtomSpec(10, "C2'", "C2*", "C", false, true),
+    AtomSpec(11, "O2'", "O2*", "O", false, true),
+    AtomSpec(12, "C1'", "C1*", "C", false, true),
+    AtomSpec(13, "N9", "N9", "N", false, true),
+    AtomSpec(14, "C8", "C8", "C", false, true),
+    AtomSpec(15, "N7", "N7", "N", false, true),
+    AtomSpec(16, "C5", "C5", "C", false, true),
+    AtomSpec(17, "C6", "C6", "C", false, true),
+    AtomSpec(18, "N6", "N6", "N", false, true),
+    AtomSpec(19, "N1", "N1", "N", false, true),
+    AtomSpec(20, "C2", "C2", "C", false, true),
+    AtomSpec(21, "N3", "N3", "N", false, true),
+    AtomSpec(22, "C4", "C4", "C", false, true),
+    AtomSpec(23, "HOP3", "3HOP", "H", false, true),
+    AtomSpec(24, "HOP2", "2HOP", "H", false, true),
+    AtomSpec(25, "H5'", "1H5*", "H", false, true),
+    AtomSpec(26, "H5''", "2H5*", "H", false, true),
+    AtomSpec(27, "H4'", "H4*", "H", false, true),
+    AtomSpec(28, "H3'", "H3*", "H", false, true),
+    AtomSpec(29, "HO3'", "H3T", "H", true, true),
+    AtomSpec(30, "H2'", "H2*", "H", false, true),
+    AtomSpec(31, "HO2'", "2HO*", "H", false, true),
+    AtomSpec(32, "H1'", "H1*", "H", false, true),
+    AtomSpec(33, "H8", "H8", "H", false, true),
+    AtomSpec(34, "H61", "1H6", "H", false, true),
+    AtomSpec(35, "H62", "2H6", "H", false, true),
+    AtomSpec(36, "H2", "H2", "H", false, true)
+  };
+  for (int i=0; i<37; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 23, 1),
+    BondSpec(1, 2, 2),
+    BondSpec(1, 3, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(3, 24, 1),
+    BondSpec(4, 5, 1),
+    BondSpec(5, 6, 1),
+    BondSpec(5, 25, 1),
+    BondSpec(5, 26, 1),
+    BondSpec(6, 7, 1),
+    BondSpec(6, 8, 1),
+    BondSpec(6, 27, 1),
+    BondSpec(7, 12, 1),
+    BondSpec(8, 9, 1),
+    BondSpec(8, 10, 1),
+    BondSpec(8, 28, 1),
+    BondSpec(9, 29, 1),
+    BondSpec(10, 11, 1),
+    BondSpec(10, 12, 1),
+    BondSpec(10, 30, 1),
+    BondSpec(11, 31, 1),
+    BondSpec(12, 13, 1),
+    BondSpec(12, 32, 1),
+    BondSpec(13, 14, 1),
+    BondSpec(13, 22, 1),
+    BondSpec(14, 15, 2),
+    BondSpec(14, 33, 1),
+    BondSpec(15, 16, 1),
+    BondSpec(16, 17, 1),
+    BondSpec(16, 22, 2),
+    BondSpec(17, 18, 1),
+    BondSpec(17, 19, 2),
+    BondSpec(18, 34, 1),
+    BondSpec(18, 35, 1),
+    BondSpec(19, 20, 1),
+    BondSpec(20, 21, 2),
+    BondSpec(20, 36, 1),
+    BondSpec(21, 22, 1)
+  };
+  for (int i=0; i<39; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakeCCompound() {
+  CompoundPtr c( new Compound("C"));
+  c->SetOneLetterCode('Y');
+  c->SetChemClass(mol::ChemClass('R'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C9 H14 N3 O8 P");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "OP3", "O3P", "O", true, true),
+    AtomSpec(1, "P", "P", "P", false, true),
+    AtomSpec(2, "OP1", "O1P", "O", false, true),
+    AtomSpec(3, "OP2", "O2P", "O", false, true),
+    AtomSpec(4, "O5'", "O5*", "O", false, true),
+    AtomSpec(5, "C5'", "C5*", "C", false, true),
+    AtomSpec(6, "C4'", "C4*", "C", false, true),
+    AtomSpec(7, "O4'", "O4*", "O", false, true),
+    AtomSpec(8, "C3'", "C3*", "C", false, true),
+    AtomSpec(9, "O3'", "O3*", "O", false, true),
+    AtomSpec(10, "C2'", "C2*", "C", false, true),
+    AtomSpec(11, "O2'", "O2*", "O", false, true),
+    AtomSpec(12, "C1'", "C1*", "C", false, true),
+    AtomSpec(13, "N1", "N1", "N", false, true),
+    AtomSpec(14, "C2", "C2", "C", false, true),
+    AtomSpec(15, "O2", "O2", "O", false, true),
+    AtomSpec(16, "N3", "N3", "N", false, true),
+    AtomSpec(17, "C4", "C4", "C", false, true),
+    AtomSpec(18, "N4", "N4", "N", false, true),
+    AtomSpec(19, "C5", "C5", "C", false, true),
+    AtomSpec(20, "C6", "C6", "C", false, true),
+    AtomSpec(21, "HOP3", "3HOP", "H", false, true),
+    AtomSpec(22, "HOP2", "2HOP", "H", false, true),
+    AtomSpec(23, "H5'", "1H5*", "H", false, true),
+    AtomSpec(24, "H5''", "2H5*", "H", false, true),
+    AtomSpec(25, "H4'", "H4*", "H", false, true),
+    AtomSpec(26, "H3'", "H3*", "H", false, true),
+    AtomSpec(27, "HO3'", "H3T", "H", true, true),
+    AtomSpec(28, "H2'", "H2*", "H", false, true),
+    AtomSpec(29, "HO2'", "2HO*", "H", false, true),
+    AtomSpec(30, "H1'", "H1*", "H", false, true),
+    AtomSpec(31, "H41", "1H4", "H", false, true),
+    AtomSpec(32, "H42", "2H4", "H", false, true),
+    AtomSpec(33, "H5", "H5", "H", false, true),
+    AtomSpec(34, "H6", "H6", "H", false, true)
+  };
+  for (int i=0; i<35; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 21, 1),
+    BondSpec(1, 2, 2),
+    BondSpec(1, 3, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(3, 22, 1),
+    BondSpec(4, 5, 1),
+    BondSpec(5, 6, 1),
+    BondSpec(5, 23, 1),
+    BondSpec(5, 24, 1),
+    BondSpec(6, 7, 1),
+    BondSpec(6, 8, 1),
+    BondSpec(6, 25, 1),
+    BondSpec(7, 12, 1),
+    BondSpec(8, 9, 1),
+    BondSpec(8, 10, 1),
+    BondSpec(8, 26, 1),
+    BondSpec(9, 27, 1),
+    BondSpec(10, 11, 1),
+    BondSpec(10, 12, 1),
+    BondSpec(10, 28, 1),
+    BondSpec(11, 29, 1),
+    BondSpec(12, 13, 1),
+    BondSpec(12, 30, 1),
+    BondSpec(13, 14, 1),
+    BondSpec(13, 20, 1),
+    BondSpec(14, 15, 2),
+    BondSpec(14, 16, 1),
+    BondSpec(16, 17, 2),
+    BondSpec(17, 18, 1),
+    BondSpec(17, 19, 1),
+    BondSpec(18, 31, 1),
+    BondSpec(18, 32, 1),
+    BondSpec(19, 20, 2),
+    BondSpec(19, 33, 1),
+    BondSpec(20, 34, 1)
+  };
+  for (int i=0; i<36; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakeUCompound() {
+  CompoundPtr c( new Compound("U"));
+  c->SetOneLetterCode('Y');
+  c->SetChemClass(mol::ChemClass('R'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C9 H13 N2 O9 P");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "OP3", "O3P", "O", true, true),
+    AtomSpec(1, "P", "P", "P", false, true),
+    AtomSpec(2, "OP1", "O1P", "O", false, true),
+    AtomSpec(3, "OP2", "O2P", "O", false, true),
+    AtomSpec(4, "O5'", "O5*", "O", false, true),
+    AtomSpec(5, "C5'", "C5*", "C", false, true),
+    AtomSpec(6, "C4'", "C4*", "C", false, true),
+    AtomSpec(7, "O4'", "O4*", "O", false, true),
+    AtomSpec(8, "C3'", "C3*", "C", false, true),
+    AtomSpec(9, "O3'", "O3*", "O", false, true),
+    AtomSpec(10, "C2'", "C2*", "C", false, true),
+    AtomSpec(11, "O2'", "O2*", "O", false, true),
+    AtomSpec(12, "C1'", "C1*", "C", false, true),
+    AtomSpec(13, "N1", "N1", "N", false, true),
+    AtomSpec(14, "C2", "C2", "C", false, true),
+    AtomSpec(15, "O2", "O2", "O", false, true),
+    AtomSpec(16, "N3", "N3", "N", false, true),
+    AtomSpec(17, "C4", "C4", "C", false, true),
+    AtomSpec(18, "O4", "O4", "O", false, true),
+    AtomSpec(19, "C5", "C5", "C", false, true),
+    AtomSpec(20, "C6", "C6", "C", false, true),
+    AtomSpec(21, "HOP3", "3HOP", "H", false, true),
+    AtomSpec(22, "HOP2", "2HOP", "H", false, true),
+    AtomSpec(23, "H5'", "1H5*", "H", false, true),
+    AtomSpec(24, "H5''", "2H5*", "H", false, true),
+    AtomSpec(25, "H4'", "H4*", "H", false, true),
+    AtomSpec(26, "H3'", "H3*", "H", false, true),
+    AtomSpec(27, "HO3'", "H3T", "H", true, true),
+    AtomSpec(28, "H2'", "H2*", "H", false, true),
+    AtomSpec(29, "HO2'", "2HO*", "H", false, true),
+    AtomSpec(30, "H1'", "H1*", "H", false, true),
+    AtomSpec(31, "H3", "H3", "H", false, true),
+    AtomSpec(32, "H5", "H5", "H", false, true),
+    AtomSpec(33, "H6", "H6", "H", false, true)
+  };
+  for (int i=0; i<34; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 21, 1),
+    BondSpec(1, 2, 2),
+    BondSpec(1, 3, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(3, 22, 1),
+    BondSpec(4, 5, 1),
+    BondSpec(5, 6, 1),
+    BondSpec(5, 23, 1),
+    BondSpec(5, 24, 1),
+    BondSpec(6, 7, 1),
+    BondSpec(6, 8, 1),
+    BondSpec(6, 25, 1),
+    BondSpec(7, 12, 1),
+    BondSpec(8, 9, 1),
+    BondSpec(8, 10, 1),
+    BondSpec(8, 26, 1),
+    BondSpec(9, 27, 1),
+    BondSpec(10, 11, 1),
+    BondSpec(10, 12, 1),
+    BondSpec(10, 28, 1),
+    BondSpec(11, 29, 1),
+    BondSpec(12, 13, 1),
+    BondSpec(12, 30, 1),
+    BondSpec(13, 14, 1),
+    BondSpec(13, 20, 1),
+    BondSpec(14, 15, 2),
+    BondSpec(14, 16, 1),
+    BondSpec(16, 17, 1),
+    BondSpec(16, 31, 1),
+    BondSpec(17, 18, 2),
+    BondSpec(17, 19, 1),
+    BondSpec(19, 20, 2),
+    BondSpec(19, 32, 1),
+    BondSpec(20, 33, 1)
+  };
+  for (int i=0; i<35; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakeDGCompound() {
+  CompoundPtr c( new Compound("DG"));
+  c->SetOneLetterCode('Y');
+  c->SetChemClass(mol::ChemClass('S'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C10 H14 N5 O7 P");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "OP3", "O3P", "O", true, true),
+    AtomSpec(1, "P", "P", "P", false, true),
+    AtomSpec(2, "OP1", "O1P", "O", false, true),
+    AtomSpec(3, "OP2", "O2P", "O", false, true),
+    AtomSpec(4, "O5'", "O5*", "O", false, true),
+    AtomSpec(5, "C5'", "C5*", "C", false, true),
+    AtomSpec(6, "C4'", "C4*", "C", false, true),
+    AtomSpec(7, "O4'", "O4*", "O", false, true),
+    AtomSpec(8, "C3'", "C3*", "C", false, true),
+    AtomSpec(9, "O3'", "O3*", "O", false, true),
+    AtomSpec(10, "C2'", "C2*", "C", false, true),
+    AtomSpec(11, "C1'", "C1*", "C", false, true),
+    AtomSpec(12, "N9", "N9", "N", false, true),
+    AtomSpec(13, "C8", "C8", "C", false, true),
+    AtomSpec(14, "N7", "N7", "N", false, true),
+    AtomSpec(15, "C5", "C5", "C", false, true),
+    AtomSpec(16, "C6", "C6", "C", false, true),
+    AtomSpec(17, "O6", "O6", "O", false, true),
+    AtomSpec(18, "N1", "N1", "N", false, true),
+    AtomSpec(19, "C2", "C2", "C", false, true),
+    AtomSpec(20, "N2", "N2", "N", false, true),
+    AtomSpec(21, "N3", "N3", "N", false, true),
+    AtomSpec(22, "C4", "C4", "C", false, true),
+    AtomSpec(23, "HOP3", "3HOP", "H", false, true),
+    AtomSpec(24, "HOP2", "2HOP", "H", false, true),
+    AtomSpec(25, "H5'", "1H5*", "H", false, true),
+    AtomSpec(26, "H5''", "2H5*", "H", false, true),
+    AtomSpec(27, "H4'", "H4*", "H", false, true),
+    AtomSpec(28, "H3'", "H3*", "H", false, true),
+    AtomSpec(29, "HO3'", "H3T", "H", true, true),
+    AtomSpec(30, "H2'", "1H2*", "H", false, true),
+    AtomSpec(31, "H2''", "2H2*", "H", false, true),
+    AtomSpec(32, "H1'", "H1*", "H", false, true),
+    AtomSpec(33, "H8", "H8", "H", false, true),
+    AtomSpec(34, "H1", "H1", "H", false, true),
+    AtomSpec(35, "H21", "1H2", "H", false, true),
+    AtomSpec(36, "H22", "2H2", "H", false, true)
+  };
+  for (int i=0; i<37; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 23, 1),
+    BondSpec(1, 2, 2),
+    BondSpec(1, 3, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(3, 24, 1),
+    BondSpec(4, 5, 1),
+    BondSpec(5, 6, 1),
+    BondSpec(5, 25, 1),
+    BondSpec(5, 26, 1),
+    BondSpec(6, 7, 1),
+    BondSpec(6, 8, 1),
+    BondSpec(6, 27, 1),
+    BondSpec(7, 11, 1),
+    BondSpec(8, 9, 1),
+    BondSpec(8, 10, 1),
+    BondSpec(8, 28, 1),
+    BondSpec(9, 29, 1),
+    BondSpec(10, 11, 1),
+    BondSpec(10, 30, 1),
+    BondSpec(10, 31, 1),
+    BondSpec(11, 12, 1),
+    BondSpec(11, 32, 1),
+    BondSpec(12, 13, 1),
+    BondSpec(12, 22, 1),
+    BondSpec(13, 14, 2),
+    BondSpec(13, 33, 1),
+    BondSpec(14, 15, 1),
+    BondSpec(15, 16, 1),
+    BondSpec(15, 22, 2),
+    BondSpec(16, 17, 2),
+    BondSpec(16, 18, 1),
+    BondSpec(18, 19, 1),
+    BondSpec(18, 34, 1),
+    BondSpec(19, 20, 1),
+    BondSpec(19, 21, 2),
+    BondSpec(20, 35, 1),
+    BondSpec(20, 36, 1),
+    BondSpec(21, 22, 1)
+  };
+  for (int i=0; i<39; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakeDTCompound() {
+  CompoundPtr c( new Compound("DT"));
+  c->SetOneLetterCode('Y');
+  c->SetChemClass(mol::ChemClass('S'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C10 H15 N2 O8 P");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "OP3", "O3P", "O", true, true),
+    AtomSpec(1, "P", "P", "P", false, true),
+    AtomSpec(2, "OP1", "O1P", "O", false, true),
+    AtomSpec(3, "OP2", "O2P", "O", false, true),
+    AtomSpec(4, "O5'", "O5*", "O", false, true),
+    AtomSpec(5, "C5'", "C5*", "C", false, true),
+    AtomSpec(6, "C4'", "C4*", "C", false, true),
+    AtomSpec(7, "O4'", "O4*", "O", false, true),
+    AtomSpec(8, "C3'", "C3*", "C", false, true),
+    AtomSpec(9, "O3'", "O3*", "O", false, true),
+    AtomSpec(10, "C2'", "C2*", "C", false, true),
+    AtomSpec(11, "C1'", "C1*", "C", false, true),
+    AtomSpec(12, "N1", "N1", "N", false, true),
+    AtomSpec(13, "C2", "C2", "C", false, true),
+    AtomSpec(14, "O2", "O2", "O", false, true),
+    AtomSpec(15, "N3", "N3", "N", false, true),
+    AtomSpec(16, "C4", "C4", "C", false, true),
+    AtomSpec(17, "O4", "O4", "O", false, true),
+    AtomSpec(18, "C5", "C5", "C", false, true),
+    AtomSpec(19, "C7", "C5M", "C", false, true),
+    AtomSpec(20, "C6", "C6", "C", false, true),
+    AtomSpec(21, "HOP3", "3HOP", "H", false, true),
+    AtomSpec(22, "HOP2", "2HOP", "H", false, true),
+    AtomSpec(23, "H5'", "1H5*", "H", false, true),
+    AtomSpec(24, "H5''", "2H5*", "H", false, true),
+    AtomSpec(25, "H4'", "H4*", "H", false, true),
+    AtomSpec(26, "H3'", "H3*", "H", false, true),
+    AtomSpec(27, "HO3'", "H3T", "H", true, true),
+    AtomSpec(28, "H2'", "1H2*", "H", false, true),
+    AtomSpec(29, "H2''", "2H2*", "H", false, true),
+    AtomSpec(30, "H1'", "H1*", "H", false, true),
+    AtomSpec(31, "H3", "H3", "H", false, true),
+    AtomSpec(32, "H71", "1H5M", "H", false, true),
+    AtomSpec(33, "H72", "2H5M", "H", false, true),
+    AtomSpec(34, "H73", "3H5M", "H", false, true),
+    AtomSpec(35, "H6", "H6", "H", false, true)
+  };
+  for (int i=0; i<36; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 21, 1),
+    BondSpec(1, 2, 2),
+    BondSpec(1, 3, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(3, 22, 1),
+    BondSpec(4, 5, 1),
+    BondSpec(5, 6, 1),
+    BondSpec(5, 23, 1),
+    BondSpec(5, 24, 1),
+    BondSpec(6, 7, 1),
+    BondSpec(6, 8, 1),
+    BondSpec(6, 25, 1),
+    BondSpec(7, 11, 1),
+    BondSpec(8, 9, 1),
+    BondSpec(8, 10, 1),
+    BondSpec(8, 26, 1),
+    BondSpec(9, 27, 1),
+    BondSpec(10, 11, 1),
+    BondSpec(10, 28, 1),
+    BondSpec(10, 29, 1),
+    BondSpec(11, 12, 1),
+    BondSpec(11, 30, 1),
+    BondSpec(12, 13, 1),
+    BondSpec(12, 20, 1),
+    BondSpec(13, 14, 2),
+    BondSpec(13, 15, 1),
+    BondSpec(15, 16, 1),
+    BondSpec(15, 31, 1),
+    BondSpec(16, 17, 2),
+    BondSpec(16, 18, 1),
+    BondSpec(18, 19, 1),
+    BondSpec(18, 20, 2),
+    BondSpec(19, 32, 1),
+    BondSpec(19, 33, 1),
+    BondSpec(19, 34, 1),
+    BondSpec(20, 35, 1)
+  };
+  for (int i=0; i<37; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakeDUCompound() {
+  CompoundPtr c( new Compound("DU"));
+  c->SetOneLetterCode('Y');
+  c->SetChemClass(mol::ChemClass('S'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C9 H13 N2 O8 P");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "OP3", "O3P", "O", true, true),
+    AtomSpec(1, "P", "P", "P", false, true),
+    AtomSpec(2, "OP1", "O1P", "O", false, true),
+    AtomSpec(3, "OP2", "O2P", "O", false, true),
+    AtomSpec(4, "O5'", "O5*", "O", false, true),
+    AtomSpec(5, "C5'", "C5*", "C", false, true),
+    AtomSpec(6, "C4'", "C4*", "C", false, true),
+    AtomSpec(7, "O4'", "O4*", "O", false, true),
+    AtomSpec(8, "C3'", "C3*", "C", false, true),
+    AtomSpec(9, "O3'", "O3*", "O", false, true),
+    AtomSpec(10, "C2'", "C2*", "C", false, true),
+    AtomSpec(11, "C1'", "C1*", "C", false, true),
+    AtomSpec(12, "N1", "N1", "N", false, true),
+    AtomSpec(13, "C2", "C2", "C", false, true),
+    AtomSpec(14, "O2", "O2", "O", false, true),
+    AtomSpec(15, "N3", "N3", "N", false, true),
+    AtomSpec(16, "C4", "C4", "C", false, true),
+    AtomSpec(17, "O4", "O4", "O", false, true),
+    AtomSpec(18, "C5", "C5", "C", false, true),
+    AtomSpec(19, "C6", "C6", "C", false, true),
+    AtomSpec(20, "HOP3", "3HOP", "H", false, true),
+    AtomSpec(21, "HOP2", "2HOP", "H", false, true),
+    AtomSpec(22, "H5'", "1H5*", "H", false, true),
+    AtomSpec(23, "H5''", "2H5*", "H", false, true),
+    AtomSpec(24, "H4'", "H4*", "H", false, true),
+    AtomSpec(25, "H3'", "H3*", "H", false, true),
+    AtomSpec(26, "HO3'", "H3T", "H", true, true),
+    AtomSpec(27, "H2'", "1H2*", "H", false, true),
+    AtomSpec(28, "H2''", "2H2*", "H", false, true),
+    AtomSpec(29, "H1'", "H1*", "H", false, true),
+    AtomSpec(30, "H3", "H3", "H", false, true),
+    AtomSpec(31, "H5", "H5", "H", false, true),
+    AtomSpec(32, "H6", "H6", "H", false, true)
+  };
+  for (int i=0; i<33; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 20, 1),
+    BondSpec(1, 2, 2),
+    BondSpec(1, 3, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(3, 21, 1),
+    BondSpec(4, 5, 1),
+    BondSpec(5, 6, 1),
+    BondSpec(5, 22, 1),
+    BondSpec(5, 23, 1),
+    BondSpec(6, 7, 1),
+    BondSpec(6, 8, 1),
+    BondSpec(6, 24, 1),
+    BondSpec(7, 11, 1),
+    BondSpec(8, 9, 1),
+    BondSpec(8, 10, 1),
+    BondSpec(8, 25, 1),
+    BondSpec(9, 26, 1),
+    BondSpec(10, 11, 1),
+    BondSpec(10, 27, 1),
+    BondSpec(10, 28, 1),
+    BondSpec(11, 12, 1),
+    BondSpec(11, 29, 1),
+    BondSpec(12, 13, 1),
+    BondSpec(12, 19, 1),
+    BondSpec(13, 14, 2),
+    BondSpec(13, 15, 1),
+    BondSpec(15, 16, 1),
+    BondSpec(15, 30, 1),
+    BondSpec(16, 17, 2),
+    BondSpec(16, 18, 1),
+    BondSpec(18, 19, 2),
+    BondSpec(18, 31, 1),
+    BondSpec(19, 32, 1)
+  };
+  for (int i=0; i<34; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakeDCCompound() {
+  CompoundPtr c( new Compound("DC"));
+  c->SetOneLetterCode('Y');
+  c->SetChemClass(mol::ChemClass('S'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C9 H14 N3 O7 P");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "OP3", "O3P", "O", true, true),
+    AtomSpec(1, "P", "P", "P", false, true),
+    AtomSpec(2, "OP1", "O1P", "O", false, true),
+    AtomSpec(3, "OP2", "O2P", "O", false, true),
+    AtomSpec(4, "O5'", "O5*", "O", false, true),
+    AtomSpec(5, "C5'", "C5*", "C", false, true),
+    AtomSpec(6, "C4'", "C4*", "C", false, true),
+    AtomSpec(7, "O4'", "O4*", "O", false, true),
+    AtomSpec(8, "C3'", "C3*", "C", false, true),
+    AtomSpec(9, "O3'", "O3*", "O", false, true),
+    AtomSpec(10, "C2'", "C2*", "C", false, true),
+    AtomSpec(11, "C1'", "C1*", "C", false, true),
+    AtomSpec(12, "N1", "N1", "N", false, true),
+    AtomSpec(13, "C2", "C2", "C", false, true),
+    AtomSpec(14, "O2", "O2", "O", false, true),
+    AtomSpec(15, "N3", "N3", "N", false, true),
+    AtomSpec(16, "C4", "C4", "C", false, true),
+    AtomSpec(17, "N4", "N4", "N", false, true),
+    AtomSpec(18, "C5", "C5", "C", false, true),
+    AtomSpec(19, "C6", "C6", "C", false, true),
+    AtomSpec(20, "HOP3", "3HOP", "H", false, true),
+    AtomSpec(21, "HOP2", "2HOP", "H", false, true),
+    AtomSpec(22, "H5'", "1H5*", "H", false, true),
+    AtomSpec(23, "H5''", "2H5*", "H", false, true),
+    AtomSpec(24, "H4'", "H4*", "H", false, true),
+    AtomSpec(25, "H3'", "H3*", "H", false, true),
+    AtomSpec(26, "HO3'", "H3T", "H", true, true),
+    AtomSpec(27, "H2'", "1H2*", "H", false, true),
+    AtomSpec(28, "H2''", "2H2*", "H", false, true),
+    AtomSpec(29, "H1'", "H1*", "H", false, true),
+    AtomSpec(30, "H41", "1H4", "H", false, true),
+    AtomSpec(31, "H42", "2H4", "H", false, true),
+    AtomSpec(32, "H5", "H5", "H", false, true),
+    AtomSpec(33, "H6", "H6", "H", false, true)
+  };
+  for (int i=0; i<34; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 20, 1),
+    BondSpec(1, 2, 2),
+    BondSpec(1, 3, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(3, 21, 1),
+    BondSpec(4, 5, 1),
+    BondSpec(5, 6, 1),
+    BondSpec(5, 22, 1),
+    BondSpec(5, 23, 1),
+    BondSpec(6, 7, 1),
+    BondSpec(6, 8, 1),
+    BondSpec(6, 24, 1),
+    BondSpec(7, 11, 1),
+    BondSpec(8, 9, 1),
+    BondSpec(8, 10, 1),
+    BondSpec(8, 25, 1),
+    BondSpec(9, 26, 1),
+    BondSpec(10, 11, 1),
+    BondSpec(10, 27, 1),
+    BondSpec(10, 28, 1),
+    BondSpec(11, 12, 1),
+    BondSpec(11, 29, 1),
+    BondSpec(12, 13, 1),
+    BondSpec(12, 19, 1),
+    BondSpec(13, 14, 2),
+    BondSpec(13, 15, 1),
+    BondSpec(15, 16, 2),
+    BondSpec(16, 17, 1),
+    BondSpec(16, 18, 1),
+    BondSpec(17, 30, 1),
+    BondSpec(17, 31, 1),
+    BondSpec(18, 19, 2),
+    BondSpec(18, 32, 1),
+    BondSpec(19, 33, 1)
+  };
+  for (int i=0; i<35; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
+CompoundPtr MakeDACompound() {
+  CompoundPtr c( new Compound("DA"));
+  c->SetOneLetterCode('Y');
+  c->SetChemClass(mol::ChemClass('S'));
+  c->SetChemType(mol::ChemType('U'));
+  c->SetFormula("C10 H14 N5 O6 P");
+  AtomSpec atoms[] = {
+    AtomSpec(0, "OP3", "O3P", "O", true, true),
+    AtomSpec(1, "P", "P", "P", false, true),
+    AtomSpec(2, "OP1", "O1P", "O", false, true),
+    AtomSpec(3, "OP2", "O2P", "O", false, true),
+    AtomSpec(4, "O5'", "O5*", "O", false, true),
+    AtomSpec(5, "C5'", "C5*", "C", false, true),
+    AtomSpec(6, "C4'", "C4*", "C", false, true),
+    AtomSpec(7, "O4'", "O4*", "O", false, true),
+    AtomSpec(8, "C3'", "C3*", "C", false, true),
+    AtomSpec(9, "O3'", "O3*", "O", false, true),
+    AtomSpec(10, "C2'", "C2*", "C", false, true),
+    AtomSpec(11, "C1'", "C1*", "C", false, true),
+    AtomSpec(12, "N9", "N9", "N", false, true),
+    AtomSpec(13, "C8", "C8", "C", false, true),
+    AtomSpec(14, "N7", "N7", "N", false, true),
+    AtomSpec(15, "C5", "C5", "C", false, true),
+    AtomSpec(16, "C6", "C6", "C", false, true),
+    AtomSpec(17, "N6", "N6", "N", false, true),
+    AtomSpec(18, "N1", "N1", "N", false, true),
+    AtomSpec(19, "C2", "C2", "C", false, true),
+    AtomSpec(20, "N3", "N3", "N", false, true),
+    AtomSpec(21, "C4", "C4", "C", false, true),
+    AtomSpec(22, "HOP3", "3HOP", "H", false, true),
+    AtomSpec(23, "HOP2", "2HOP", "H", false, true),
+    AtomSpec(24, "H5'", "1H5*", "H", false, true),
+    AtomSpec(25, "H5''", "2H5*", "H", false, true),
+    AtomSpec(26, "H4'", "H4*", "H", false, true),
+    AtomSpec(27, "H3'", "H3*", "H", false, true),
+    AtomSpec(28, "HO3'", "H3T", "H", true, true),
+    AtomSpec(29, "H2'", "1H2*", "H", false, true),
+    AtomSpec(30, "H2''", "2H2*", "H", false, true),
+    AtomSpec(31, "H1'", "H1*", "H", false, true),
+    AtomSpec(32, "H8", "H8", "H", false, true),
+    AtomSpec(33, "H61", "1H6", "H", false, true),
+    AtomSpec(34, "H62", "2H6", "H", false, true),
+    AtomSpec(35, "H2", "H2", "H", false, true)
+  };
+  for (int i=0; i<36; ++i) { c->AddAtom(atoms[i]); }
+  BondSpec bonds[] = {
+    BondSpec(0, 1, 1),
+    BondSpec(0, 22, 1),
+    BondSpec(1, 2, 2),
+    BondSpec(1, 3, 1),
+    BondSpec(1, 4, 1),
+    BondSpec(3, 23, 1),
+    BondSpec(4, 5, 1),
+    BondSpec(5, 6, 1),
+    BondSpec(5, 24, 1),
+    BondSpec(5, 25, 1),
+    BondSpec(6, 7, 1),
+    BondSpec(6, 8, 1),
+    BondSpec(6, 26, 1),
+    BondSpec(7, 11, 1),
+    BondSpec(8, 9, 1),
+    BondSpec(8, 10, 1),
+    BondSpec(8, 27, 1),
+    BondSpec(9, 28, 1),
+    BondSpec(10, 11, 1),
+    BondSpec(10, 29, 1),
+    BondSpec(10, 30, 1),
+    BondSpec(11, 12, 1),
+    BondSpec(11, 31, 1),
+    BondSpec(12, 13, 1),
+    BondSpec(12, 21, 1),
+    BondSpec(13, 14, 2),
+    BondSpec(13, 32, 1),
+    BondSpec(14, 15, 1),
+    BondSpec(15, 16, 1),
+    BondSpec(15, 21, 2),
+    BondSpec(16, 17, 1),
+    BondSpec(16, 18, 2),
+    BondSpec(17, 33, 1),
+    BondSpec(17, 34, 1),
+    BondSpec(18, 19, 1),
+    BondSpec(19, 20, 2),
+    BondSpec(19, 35, 1),
+    BondSpec(20, 21, 1)
+  };
+  for (int i=0; i<38; ++i) { c->AddBond(bonds[i]); }
+  return c;
+}
diff --git a/modules/conop/tests/CMakeLists.txt b/modules/conop/tests/CMakeLists.txt
index 6a832115b5933b66241c9dec5ce23c21dd532c48..29140807826e25e812d312371013f9ca96e2b3bd 100644
--- a/modules/conop/tests/CMakeLists.txt
+++ b/modules/conop/tests/CMakeLists.txt
@@ -1,10 +1,11 @@
 set(OST_CONOP_UNIT_TESTS
-  test_heuristic_builder.cc
-  test_rule_based_builder.cc
+  test_heuristic_conop.cc
   tests.cc
-  test_builder.cc
+  test_rule_based_conop.cc 
+  helper.cc 
   test_compound.py
   test_cleanup.py
+  test_processor.py
   test_nonstandard.py
 )
 
diff --git a/modules/conop/tests/test_rule_based_builder.cc b/modules/conop/tests/helper.cc
similarity index 77%
rename from modules/conop/tests/test_rule_based_builder.cc
rename to modules/conop/tests/helper.cc
index a287bc12426bf68e863be6388717855970fa14ee..bc3b4af781adbda8eae79437d0b9d552b28cb0fa 100644
--- a/modules/conop/tests/test_rule_based_builder.cc
+++ b/modules/conop/tests/helper.cc
@@ -1,38 +1,13 @@
-// -----------------------------------------------------------------------------
-// This file is part of the OpenStructure project <www.openstructure.org>
-
-// Copyright (C) 2008-2011 by the OpenStructure authors
-
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License as published by the Free
-// Software Foundation; either version 3.0 of the License, or (at your option)
-// any later version.
-// This library is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-// details.
-
-// You should have received a copy of the GNU Lesser General Public License
-// along with this library; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-// -----------------------------------------------------------------------------
-
-#include <ost/mol/mol.hh>
-#include <ost/platform.hh>
-#include <ost/conop/rule_based_builder.hh>
-#include <ost/conop/conop.hh>
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
-#include <boost/test/auto_unit_test.hpp>
+#include <ost/mol/xcs_editor.hh>
+#include <ost/mol/bond_handle.hh>
+
+#include "helper.hh"
 
-#include <ost/log.hh>
-using boost::unit_test_framework::test_suite;
-using namespace ost;
-using namespace ost::conop;
-//using namespace ost::io;
 using namespace ost::mol;
-namespace {
-} // anon ns
+
+namespace ost { namespace conop {
 
 ResidueHandle make_cytosine(ChainHandle chain) 
 {
@@ -148,7 +123,6 @@ ResidueHandle make_defective_uracil2(ChainHandle chain)
 
   return res;
 }
-
 ResidueHandle make_1zk(ChainHandle chain)
 {
   XCSEditor edi=chain.GetEntity().EditXCS();
@@ -215,73 +189,6 @@ ResidueHandle make_1zk(ChainHandle chain)
   return r;
 }
 
-void verify_1zk_connectivity(const ResidueHandle& r1) 
-{
-  BOOST_CHECK(BondExists(r1.FindAtom("C"), r1.FindAtom("CA")));
-  BOOST_CHECK(BondExists(r1.FindAtom("C"), r1.FindAtom("O")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CA"), r1.FindAtom("O1")));
-  BOOST_CHECK(BondExists(r1.FindAtom("C1"), r1.FindAtom("C2")));
-  BOOST_CHECK(BondExists(r1.FindAtom("C1"), r1.FindAtom("C1A")));
-  BOOST_CHECK(BondExists(r1.FindAtom("C1"), r1.FindAtom("O1")));
-  BOOST_CHECK(BondExists(r1.FindAtom("C2"), r1.FindAtom("C3")));
-  BOOST_CHECK(BondExists(r1.FindAtom("C3"), r1.FindAtom("C4")));
-  BOOST_CHECK(BondExists(r1.FindAtom("C4"), r1.FindAtom("C4A")));
-  BOOST_CHECK(BondExists(r1.FindAtom("C4A"), r1.FindAtom("C5")));
-  BOOST_CHECK(BondExists(r1.FindAtom("C4A"), r1.FindAtom("C1A")));
-  BOOST_CHECK(BondExists(r1.FindAtom("C5"), r1.FindAtom("C6")));
-  BOOST_CHECK(BondExists(r1.FindAtom("C6"), r1.FindAtom("C7")));
-  BOOST_CHECK(BondExists(r1.FindAtom("C7"), r1.FindAtom("C8")));
-  BOOST_CHECK(BondExists(r1.FindAtom("C8"), r1.FindAtom("C1A")));
-  BOOST_CHECK(BondExists(r1.FindAtom("N"), r1.FindAtom("CA1")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CA1"), r1.FindAtom("C9")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CA1"), r1.FindAtom("CB")));
-  BOOST_CHECK(BondExists(r1.FindAtom("C9"), r1.FindAtom("O2")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CB"), r1.FindAtom("CG")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CG"), r1.FindAtom("ND1")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CG"), r1.FindAtom("CD2")));
-  BOOST_CHECK(BondExists(r1.FindAtom("ND1"), r1.FindAtom("CE1")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CD2"), r1.FindAtom("NE2")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CE1"), r1.FindAtom("NE2")));
-  BOOST_CHECK(BondExists(r1.FindAtom("N1"), r1.FindAtom("CA2")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CA2"), r1.FindAtom("CB1")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CA2"), r1.FindAtom("CH")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CB1"), r1.FindAtom("CG1")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CG1"), r1.FindAtom("CD1")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CG1"), r1.FindAtom("CD21")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CD1"), r1.FindAtom("CE11")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CD21"), r1.FindAtom("CE2")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CE11"), r1.FindAtom("CZ")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CE2"), r1.FindAtom("CZ")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CH"), r1.FindAtom("OH")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CH"), r1.FindAtom("CB11")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CB11"), r1.FindAtom("CA'")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CB11"), r1.FindAtom("OB1")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CA'"), r1.FindAtom("CB'")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CA'"), r1.FindAtom("CC")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CB'"), r1.FindAtom("CG11")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CB'"), r1.FindAtom("CG2")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CC"), r1.FindAtom("O3")));
-  BOOST_CHECK(BondExists(r1.FindAtom("N2"), r1.FindAtom("CA3")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CA3"), r1.FindAtom("CD")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CA3"), r1.FindAtom("CB2")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CD"), r1.FindAtom("O4")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CB2"), r1.FindAtom("CG12")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CB2"), r1.FindAtom("CG21")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CG12"), r1.FindAtom("CD11")));
-  BOOST_CHECK(BondExists(r1.FindAtom("N3"), r1.FindAtom("CM")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CM"), r1.FindAtom("C21")));
-  BOOST_CHECK(BondExists(r1.FindAtom("C21"), r1.FindAtom("C31")));
-  BOOST_CHECK(BondExists(r1.FindAtom("C21"), r1.FindAtom("N11")));
-  BOOST_CHECK(BondExists(r1.FindAtom("C31"), r1.FindAtom("C41")));
-  BOOST_CHECK(BondExists(r1.FindAtom("C41"), r1.FindAtom("C51")));
-  BOOST_CHECK(BondExists(r1.FindAtom("C51"), r1.FindAtom("C61")));
-  BOOST_CHECK(BondExists(r1.FindAtom("C61"), r1.FindAtom("N11")));
-  BOOST_CHECK(BondExists(r1.FindAtom("C"), r1.FindAtom("N")));
-  BOOST_CHECK(BondExists(r1.FindAtom("C9"), r1.FindAtom("N1")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CC"), r1.FindAtom("N2")));
-  BOOST_CHECK(BondExists(r1.FindAtom("CD"), r1.FindAtom("N3")));
-}
-
 void verify_nucleotide_connectivity(const ResidueHandle& res) 
 {
   BOOST_CHECK(BondExists(res.FindAtom("P"),
@@ -353,106 +260,122 @@ void verify_nucleotide_connectivity(const ResidueHandle& res)
     // TODO: Check that no other atoms are connected!
   }
 }
-void verify_nucleotide_link(const ResidueHandle& p3, const ResidueHandle& p5) 
+void verify_1zk_connectivity(const ResidueHandle& r1) 
 {
-  BOOST_CHECK(BondExists(p3.FindAtom("O3'"),
-                         p5.FindAtom("P")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C"), r1.FindAtom("CA")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C"), r1.FindAtom("O")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CA"), r1.FindAtom("O1")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C1"), r1.FindAtom("C2")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C1"), r1.FindAtom("C1A")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C1"), r1.FindAtom("O1")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C2"), r1.FindAtom("C3")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C3"), r1.FindAtom("C4")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C4"), r1.FindAtom("C4A")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C4A"), r1.FindAtom("C5")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C4A"), r1.FindAtom("C1A")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C5"), r1.FindAtom("C6")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C6"), r1.FindAtom("C7")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C7"), r1.FindAtom("C8")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C8"), r1.FindAtom("C1A")));
+  BOOST_CHECK(BondExists(r1.FindAtom("N"), r1.FindAtom("CA1")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CA1"), r1.FindAtom("C9")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CA1"), r1.FindAtom("CB")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C9"), r1.FindAtom("O2")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CB"), r1.FindAtom("CG")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CG"), r1.FindAtom("ND1")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CG"), r1.FindAtom("CD2")));
+  BOOST_CHECK(BondExists(r1.FindAtom("ND1"), r1.FindAtom("CE1")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CD2"), r1.FindAtom("NE2")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CE1"), r1.FindAtom("NE2")));
+  BOOST_CHECK(BondExists(r1.FindAtom("N1"), r1.FindAtom("CA2")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CA2"), r1.FindAtom("CB1")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CA2"), r1.FindAtom("CH")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CB1"), r1.FindAtom("CG1")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CG1"), r1.FindAtom("CD1")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CG1"), r1.FindAtom("CD21")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CD1"), r1.FindAtom("CE11")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CD21"), r1.FindAtom("CE2")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CE11"), r1.FindAtom("CZ")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CE2"), r1.FindAtom("CZ")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CH"), r1.FindAtom("OH")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CH"), r1.FindAtom("CB11")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CB11"), r1.FindAtom("CA'")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CB11"), r1.FindAtom("OB1")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CA'"), r1.FindAtom("CB'")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CA'"), r1.FindAtom("CC")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CB'"), r1.FindAtom("CG11")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CB'"), r1.FindAtom("CG2")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CC"), r1.FindAtom("O3")));
+  BOOST_CHECK(BondExists(r1.FindAtom("N2"), r1.FindAtom("CA3")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CA3"), r1.FindAtom("CD")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CA3"), r1.FindAtom("CB2")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CD"), r1.FindAtom("O4")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CB2"), r1.FindAtom("CG12")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CB2"), r1.FindAtom("CG21")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CG12"), r1.FindAtom("CD11")));
+  BOOST_CHECK(BondExists(r1.FindAtom("N3"), r1.FindAtom("CM")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CM"), r1.FindAtom("C21")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C21"), r1.FindAtom("C31")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C21"), r1.FindAtom("N11")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C31"), r1.FindAtom("C41")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C41"), r1.FindAtom("C51")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C51"), r1.FindAtom("C61")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C61"), r1.FindAtom("N11")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C"), r1.FindAtom("N")));
+  BOOST_CHECK(BondExists(r1.FindAtom("C9"), r1.FindAtom("N1")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CC"), r1.FindAtom("N2")));
+  BOOST_CHECK(BondExists(r1.FindAtom("CD"), r1.FindAtom("N3")));
 }
 
-void verify_nucleotide_nolink(const ResidueHandle& p3, const ResidueHandle& p5) 
+ResidueHandle make_arg(ChainHandle chain) 
 {
-  BOOST_CHECK(!BondExists(p3.FindAtom("O3'"),
-                          p5.FindAtom("P")));
+  XCSEditor e=chain.GetEntity().EditXCS();
+  ResidueHandle res = e.AppendResidue(chain, "ARG");
+  e.InsertAtom(res, "N",geom::Vec3(20.202,33.112,58.011));
+  e.InsertAtom(res, "CA",geom::Vec3(19.396,31.903,58.033));
+  e.InsertAtom(res, "C",geom::Vec3(18.608,31.739,59.328));
+  e.InsertAtom(res, "O",geom::Vec3(17.651,30.965,59.381));
+  e.InsertAtom(res, "CB",geom::Vec3(20.284,30.681,57.801));
+  e.InsertAtom(res, "CG",geom::Vec3(20.665,30.488,56.342));
+  e.InsertAtom(res, "CD",geom::Vec3(21.557,29.281,56.154));
+  e.InsertAtom(res, "NE",geom::Vec3(22.931,29.557,56.551));
+  e.InsertAtom(res, "CZ",geom::Vec3(23.901,28.653,56.528));
+  e.InsertAtom(res, "NH1",geom::Vec3(23.640,27.417,56.130));
+  e.InsertAtom(res, "NH2",geom::Vec3(25.132,28.980,56.893));
+  return res;
 }
 
-BOOST_AUTO_TEST_SUITE( conop );
-
-
-BOOST_AUTO_TEST_CASE(nucleotide_based_connect) 
+ResidueHandle make_leu(ChainHandle chain) 
 {
-  SetPrefixPath(getenv("OST_ROOT"));
-  String lib_path=GetSharedDataPath()+"/compounds.chemlib";
-  CompoundLibPtr compound_lib=CompoundLib::Load(lib_path);  
-  if (!compound_lib) {
-    std::cout << "WARNING: skipping NUCLEOTIDE_BASED connect unit test. " 
-              << "Rule-based builder is required" << std::endl;
-    return;    
-  }
-  RuleBasedBuilder rb_builder = RuleBasedBuilder(compound_lib);
-
-  RuleBasedBuilder drb_builder = RuleBasedBuilder(compound_lib);
-  drb_builder.SetBondFeasibilityCheck(false);
-  
-  EntityHandle e=CreateEntity();
-  ChainHandle c=e.EditXCS().InsertChain("A");
-  ResidueHandle c0=make_cytosine(c);
-  ResidueHandle u1=make_uracil1(c);
-  ResidueHandle u2=make_uracil2(c);
-  
-  EntityHandle de=CreateEntity();  
-  ChainHandle dc=de.EditXCS().InsertChain("A");
-  ResidueHandle du2=make_defective_uracil2(dc);
-
-
-  AtomHandleList atoms = e.GetAtomList();
-  for (AtomHandleList::const_iterator i = atoms.begin(), e = atoms.end(); i!=e; ++i ){
-    rb_builder.FillAtomProps(*i);
-  }
-
-  atoms = de.GetAtomList();
-  for (AtomHandleList::const_iterator i = atoms.begin(), e = atoms.end(); i!=e; ++i ){
-    drb_builder.FillAtomProps(*i);
-  }
-  
-  // running positive test
-  BOOST_MESSAGE("running distance based checks on cytosine");
-  rb_builder.ConnectAtomsOfResidue(c0);
-  verify_nucleotide_connectivity(c0);
-  BOOST_MESSAGE("running distance based checks on first uracil");
-  rb_builder.ConnectAtomsOfResidue(u1);
-  verify_nucleotide_connectivity(u1);
-  BOOST_MESSAGE("running distance based checks on second uracil");
-  rb_builder.ConnectAtomsOfResidue(u2);
-  verify_nucleotide_connectivity(u2);
-  BOOST_MESSAGE("connecting cytosine to first uracil");
-  rb_builder.ConnectResidueToNext(c0, u1);
-  verify_nucleotide_link(c0, u1);
-  BOOST_MESSAGE("connecting first uracil to second uracil");
-  rb_builder.ConnectResidueToNext(u1, u2);
-  verify_nucleotide_link(u1, u2);
-  // one negative test
-  BOOST_MESSAGE("connecting cytosine to second uracil");
-  rb_builder.ConnectResidueToNext(c0, u2);
-  verify_nucleotide_nolink(c0, u2);
-  
-  // running positive test
-  BOOST_MESSAGE("running distance based checks on defective uracil");
-  drb_builder.ConnectAtomsOfResidue(du2);
-  verify_nucleotide_connectivity(du2);
-  
+  XCSEditor e=chain.GetEntity().EditXCS();  
+  ResidueHandle res=e.AppendResidue(chain, "LEU");
+
+  e.InsertAtom(res, "N", geom::Vec3(19.003,32.473,60.366));
+  e.InsertAtom(res, "CA", geom::Vec3(18.330,32.402,61.664));
+  e.InsertAtom(res, "C", geom::Vec3(17.884,33.787,62.117));
+  e.InsertAtom(res, "O", geom::Vec3(17.853,34.091,63.308));
+  e.InsertAtom(res, "CB", geom::Vec3(19.269,31.793,62.710));
+  e.InsertAtom(res, "CG", geom::Vec3(19.695,30.340,62.501));
+  e.InsertAtom(res, "CD1", geom::Vec3(20.585,29.897,63.648));
+  e.InsertAtom(res, "CD2", geom::Vec3(18.461,29.459,62.420));
+  return res;
 }
 
-BOOST_AUTO_TEST_CASE(rule_based_connect_1zk) 
+ResidueHandle make_defective_leu(ChainHandle chain) 
 {
-  SetPrefixPath(getenv("OST_ROOT"));
-  String lib_path=GetSharedDataPath()+"/compounds.chemlib";
-  CompoundLibPtr compound_lib=CompoundLib::Load(lib_path);  
-  if (!compound_lib) {
-    std::cout << "WARNING: skipping NUCLEOTIDE_BASED connect unit test. " 
-              << "Rule-based builder is required" << std::endl;
-    return;    
-  }
-
-  boost::shared_ptr<RuleBasedBuilder> drb_builder(new RuleBasedBuilder(compound_lib));
-  Conopology::Instance().RegisterBuilder(drb_builder, "RBB");
-  Conopology::Instance().SetDefaultBuilder("RBB");
-  drb_builder->SetBondFeasibilityCheck(false);
-  EntityHandle e=CreateEntity();
-  ChainHandle c=e.EditXCS().InsertChain("A");
-  ResidueHandle r1=make_1zk(c);
-  Conopology::Instance().ConnectAll(drb_builder, e);
-  Conopology::Instance().SetDefaultBuilder("HEURISTIC");
-  verify_1zk_connectivity(r1);
+  XCSEditor e=chain.GetEntity().EditXCS();  
+  ResidueHandle res=e.AppendResidue(chain, "LEU");
+
+  e.InsertAtom(res, "N", geom::Vec3(19.003,32.473,60.366));
+  e.InsertAtom(res, "CA", geom::Vec3(18.330,32.402,61.664));
+  e.InsertAtom(res, "C", geom::Vec3(17.884,33.787,62.117));
+  e.InsertAtom(res, "O", geom::Vec3(17.853,34.091,63.308));
+  e.InsertAtom(res, "CB", geom::Vec3(19.269,31.793,102.710));
+  e.InsertAtom(res, "CG", geom::Vec3(19.695,30.340,62.501));
+  e.InsertAtom(res, "CD1", geom::Vec3(20.585,29.897,63.648));
+  e.InsertAtom(res, "CD2", geom::Vec3(18.461,29.459,62.420));
+  return res;
 }
 
-BOOST_AUTO_TEST_SUITE_END( );
+}}
+
diff --git a/modules/conop/tests/helper.hh b/modules/conop/tests/helper.hh
new file mode 100644
index 0000000000000000000000000000000000000000..a4ad2309c340f35149579c58dc872ced07c27cf6
--- /dev/null
+++ b/modules/conop/tests/helper.hh
@@ -0,0 +1,27 @@
+#ifndef OST_CONOP_TEST_HELPERS_HH
+#define OST_CONOP_TEST_HELPERS_HH
+
+#include <ost/mol/entity_handle.hh>
+#include <ost/mol/residue_handle.hh>
+
+namespace ost { namespace conop {
+
+mol::ResidueHandle make_uracyl(mol::ChainHandle chain);
+void verify_1zk_connectivity(const mol::ResidueHandle& r1);
+mol::ResidueHandle make_cytosine(mol::ChainHandle chain); 
+mol::ResidueHandle make_uracil1(mol::ChainHandle chain); 
+mol::ResidueHandle make_uracil2(mol::ChainHandle chain); 
+mol::ResidueHandle make_defective_uracil2(mol::ChainHandle chain);
+mol::ResidueHandle make_leu(mol::ChainHandle chain);
+mol::ResidueHandle make_arg(mol::ChainHandle chain);
+mol::ResidueHandle make_defective_leu(mol::ChainHandle chain);
+mol::ResidueHandle make_1zk(mol::ChainHandle chain);
+void verify_1zk_connectivity(const mol::ResidueHandle& r1);
+void verify_nucleotide_connectivity(const mol::ResidueHandle& res);
+void verify_nucleotide_link(const mol::ResidueHandle& p3, 
+                            const mol::ResidueHandle& p5);
+void verify_nucleotide_nolink(const mol::ResidueHandle& p3, 
+                              const mol::ResidueHandle& p5);
+}}
+
+#endif
diff --git a/modules/conop/tests/test_builder.cc b/modules/conop/tests/test_builder.cc
deleted file mode 100644
index 0d5d6537145ea27dc63cbe2960afe7f9e6b293a2..0000000000000000000000000000000000000000
--- a/modules/conop/tests/test_builder.cc
+++ /dev/null
@@ -1,76 +0,0 @@
-//------------------------------------------------------------------------------
-// This file is part of the OpenStructure project <www.openstructure.org>
-//
-// Copyright (C) 2008-2011 by the OpenStructure authors
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License as published by the Free
-// Software Foundation; either version 3.0 of the License, or (at your option)
-// any later version.
-// This library is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with this library; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-//------------------------------------------------------------------------------
-#include <ost/mol/mol.hh>
-#include <ost/conop/builder.hh>
-#include <ost/conop/heuristic_builder.hh>
-#define BOOST_TEST_DYN_LINK
-#include <boost/test/unit_test.hpp>
-#include <boost/test/auto_unit_test.hpp>
-
-
-// using boost::unit_test_framework::test_suite;
-using namespace ost;
-using namespace ost::conop;
-using namespace ost::mol;
-
-BOOST_AUTO_TEST_SUITE( conop );
-
-BOOST_AUTO_TEST_CASE(test_guess_chem_class)
-{
-  HeuristicBuilder h;
-  EntityHandle ent=mol::CreateEntity();
-  XCSEditor edi=ent.EditXCS();
-  ChainHandle chain=edi.InsertChain("A");
-  ResidueHandle res=edi.AppendResidue(chain, "DUMMY");
-  AtomHandle n=edi.InsertAtom(res, "N", geom::Vec3(1, 0, 0), "N");
-  AtomHandle ca=edi.InsertAtom(res, "CA", geom::Vec3(2, 0, 0), "C");
-  AtomHandle c=edi.InsertAtom(res, "C", geom::Vec3(3, 0, 0), "C");
-  AtomHandle o=edi.InsertAtom(res, "O", geom::Vec3(4, 0, 0), "O");
-  h.GuessChemClass(res);
-  BOOST_CHECK(res.IsPeptideLinking());
-  res.SetChemClass(ChemClass());
-  edi.SetAtomPos(n, geom::Vec3(-1,0,0));
-  h.GuessChemClass(res);
-  BOOST_CHECK(!res.IsPeptideLinking());
-}
-
-BOOST_AUTO_TEST_CASE( test_builder )
-{
-  BOOST_CHECK_EQUAL(Builder::GuessAtomElement("CA", false), "C");
-  BOOST_CHECK_EQUAL(Builder::GuessAtomElement("CB", false), "C");
-  BOOST_CHECK_EQUAL(Builder::GuessAtomElement("N", false), "N");
-  BOOST_CHECK_EQUAL(Builder::GuessAtomElement("O", false), "O");
-  BOOST_CHECK_EQUAL(Builder::GuessAtomElement("CG1", false), "C");
-  BOOST_CHECK_EQUAL(Builder::GuessAtomElement("CG2", false), "C");
-  BOOST_CHECK_EQUAL(Builder::GuessAtomElement("OG1", false), "O");
-  BOOST_CHECK_EQUAL(Builder::GuessAtomElement("SG", false), "S");
-  BOOST_CHECK_EQUAL(Builder::GuessAtomElement("1HA", false), "H");
-  BOOST_CHECK_EQUAL(Builder::GuessAtomElement("1HB", false), "H");
-  BOOST_CHECK_EQUAL(Builder::GuessAtomElement("1DA", false), "D");
-  BOOST_CHECK_EQUAL(Builder::GuessAtomElement("1DB", false), "D");
-  BOOST_CHECK_EQUAL(Builder::GuessAtomElement("1HA", true), "H");
-  BOOST_CHECK_EQUAL(Builder::GuessAtomElement("1HB", true), "H");
-  BOOST_CHECK_EQUAL(Builder::GuessAtomElement("1DA", true), "D");
-  BOOST_CHECK_EQUAL(Builder::GuessAtomElement("1DB", true), "D");  
-  BOOST_CHECK_EQUAL(Builder::GuessAtomElement("CA", true), "CA");
-  BOOST_CHECK_EQUAL(Builder::GuessAtomElement("11", true), "");
-  BOOST_CHECK_EQUAL(Builder::GuessAtomElement("11", false), "");  
-}
-
-BOOST_AUTO_TEST_SUITE_END();
diff --git a/modules/conop/tests/test_cleanup.py b/modules/conop/tests/test_cleanup.py
index 11df64187377f67f636813c2218fb37256a449cd..9c5f0cf27fc1f340aef4b48c7753b1671bd86e04 100644
--- a/modules/conop/tests/test_cleanup.py
+++ b/modules/conop/tests/test_cleanup.py
@@ -6,7 +6,7 @@ from ost.conop import cleanup
 class TestCleanUp(unittest.TestCase):
 
   def setUp(self):
-    self.comp_lib=conop.GetBuilder().compound_lib
+    self.comp_lib=conop.GetDefaultLib()
     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")
@@ -156,8 +156,8 @@ class TestCleanUp(unittest.TestCase):
     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'
+if not conop.GetDefaultLib():
+  print 'No compound library available. Ignoring test_cleanup.py tests'
   sys.exit()
 
 if __name__== '__main__':
diff --git a/modules/conop/tests/test_compound.py b/modules/conop/tests/test_compound.py
index a215a78f7a5dd966c2619346aaabf0f084b7bbd7..700f52b286d6e7f842cd004c2dffff6006603436 100644
--- a/modules/conop/tests/test_compound.py
+++ b/modules/conop/tests/test_compound.py
@@ -5,7 +5,7 @@ from ost import conop
 class TestCompound(unittest.TestCase):
   
   def setUp(self):
-    self.compound_lib=conop.GetBuilder().compound_lib
+    self.compound_lib=conop.GetDefaultLib()
 
   def testFindCompound(self):
     compound=self.compound_lib.FindCompound('***')
@@ -22,9 +22,8 @@ class TestCompound(unittest.TestCase):
 
      
 if __name__=='__main__':
-  builder=conop.GetBuilder()
-  if not hasattr(builder, 'compound_lib'):
-    print 'default builder does not use compound library. ignoring unit tests'
+  if not conop.GetDefaultLib():
+    print 'No compound library available. ignoring compound unit tests'
   else:
     from ost import testutils
     testutils.RunTests()
diff --git a/modules/conop/tests/test_heuristic_conop.cc b/modules/conop/tests/test_heuristic_conop.cc
new file mode 100644
index 0000000000000000000000000000000000000000..4943393161d1e3f8911073d67a6f261ccc091f2f
--- /dev/null
+++ b/modules/conop/tests/test_heuristic_conop.cc
@@ -0,0 +1,144 @@
+// ------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+
+// Copyright (C) 2008-2011 by the OpenStructure authors
+
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+// ------------------------------------------------------------------------------
+
+#include <ost/log.hh>
+#include <ost/mol/mol.hh>
+#include <ost/conop/heuristic.hh>
+
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+#include <boost/test/auto_unit_test.hpp>
+#include "helper.hh"
+using boost::unit_test_framework::test_suite;
+using namespace ost;
+using namespace ost::conop;
+using namespace ost::mol;
+
+
+
+void verify_connectivity_x(const ResidueHandle& res) 
+{
+  BOOST_CHECK(BondExists(res.FindAtom("XN"),
+                         res.FindAtom("XCA")));
+  BOOST_CHECK(BondExists(res.FindAtom("XCA"),
+                         res.FindAtom("XC")));
+  BOOST_CHECK(BondExists(res.FindAtom("XC"),
+                         res.FindAtom("XO")));
+  BOOST_CHECK(BondExists(res.FindAtom("XCA"),
+                         res.FindAtom("XCB")));
+  BOOST_CHECK(BondExists(res.FindAtom("XCB"),
+                         res.FindAtom("XCG")));
+  if (res.GetKey()=="ARG") {
+
+    BOOST_CHECK(BondExists(res.FindAtom("XCB"),
+                           res.FindAtom("XCG")));
+    BOOST_CHECK(BondExists(res.FindAtom("XCG"),
+                           res.FindAtom("XCD")));
+    BOOST_CHECK(BondExists(res.FindAtom("XCD"),
+                           res.FindAtom("XNE")));
+    BOOST_CHECK(BondExists(res.FindAtom("XNE"),
+                           res.FindAtom("XCZ")));
+    BOOST_CHECK(BondExists(res.FindAtom("XCZ"),
+                           res.FindAtom("XNH1")));
+    BOOST_CHECK(BondExists(res.FindAtom("XCZ"),
+                           res.FindAtom("XNH2")));
+    // TODO: Check that no other atoms are connected!
+  }
+  if (res.GetKey()=="ILE") {
+    BOOST_CHECK(BondExists(res.FindAtom("XCG"),
+                           res.FindAtom("XCD1")));
+    BOOST_CHECK(BondExists(res.FindAtom("XCG"),
+                           res.FindAtom("XCD2")));
+    // TODO: Check that no other atoms are connected!
+  }
+}
+
+void verify_connectivity(const ResidueHandle& res) 
+{
+  BOOST_CHECK(BondExists(res.FindAtom("N"),
+                        res.FindAtom("CA")));
+  BOOST_CHECK(BondExists(res.FindAtom("CA"),
+                         res.FindAtom("C")));
+  BOOST_CHECK(BondExists(res.FindAtom("C"),
+                         res.FindAtom("O")));
+  BOOST_CHECK(BondExists(res.FindAtom("CA"),
+                         res.FindAtom("CB")));
+  BOOST_CHECK(BondExists(res.FindAtom("CB"),
+                         res.FindAtom("CG")));
+  if (res.GetKey()=="ARG") {
+
+    BOOST_CHECK(BondExists(res.FindAtom("CB"),
+                           res.FindAtom("CG")));
+    BOOST_CHECK(BondExists(res.FindAtom("CG"),
+                           res.FindAtom("CD")));
+    BOOST_CHECK(BondExists(res.FindAtom("CD"),
+                           res.FindAtom("NE")));
+    BOOST_CHECK(BondExists(res.FindAtom("NE"),
+                           res.FindAtom("CZ")));
+    BOOST_CHECK(BondExists(res.FindAtom("CZ"),
+                           res.FindAtom("NH1")));
+    BOOST_CHECK(BondExists(res.FindAtom("CZ"),
+                           res.FindAtom("NH2")));
+    // TODO: Check that no other atoms are connected!
+  }
+  if (res.GetKey()=="ILE") {
+    BOOST_CHECK(BondExists(res.FindAtom("CG"),
+                           res.FindAtom("CD1")));
+    BOOST_CHECK(BondExists(res.FindAtom("CG"),
+                           res.FindAtom("CD2")));
+    // TODO: Check that no other atoms are connected!
+  }
+}
+
+BOOST_AUTO_TEST_SUITE( conop );
+
+
+BOOST_AUTO_TEST_CASE(does_name_based_connect) 
+{
+  EntityHandle e=CreateEntity();
+  ChainHandle c=e.EditXCS().InsertChain("A");
+  ResidueHandle ile=make_leu(c);
+  ResidueHandle arg=make_arg(c);
+  HeuristicProcessor proc;
+  proc.Process(e);
+
+  verify_connectivity(arg);
+  verify_connectivity(ile);
+}
+
+BOOST_AUTO_TEST_CASE(does_assign_torsions) {
+  EntityHandle e=CreateEntity();
+  ChainHandle c=e.EditXCS().InsertChain("A");
+  ResidueHandle l1=make_leu(c);
+  ResidueHandle a2=make_arg(c);
+  ResidueHandle l3=make_leu(c);
+  e.EditXCS().Connect(l1.FindAtom("C"), a2.FindAtom("N"));
+  e.EditXCS().Connect(a2.FindAtom("C"), l3.FindAtom("N"));
+  HeuristicProcessor proc;
+  proc.SetAssignTorsions(true);
+  proc.Process(e);
+  BOOST_CHECK(a2.GetPhiTorsion().IsValid());
+  BOOST_CHECK(l3.GetPhiTorsion().IsValid());
+
+  BOOST_CHECK(l1.GetPsiTorsion().IsValid());
+  BOOST_CHECK(a2.GetPsiTorsion().IsValid());
+}
+
+BOOST_AUTO_TEST_SUITE_END();
+
diff --git a/modules/conop/tests/test_nonstandard.py b/modules/conop/tests/test_nonstandard.py
index 170749c6eacd73bc64f4b6826e4df5d80f104512..f10b7d9d0324b5783a8ad6b0e0c162c8b818c828 100644
--- a/modules/conop/tests/test_nonstandard.py
+++ b/modules/conop/tests/test_nonstandard.py
@@ -117,9 +117,8 @@ class TestNonStandard(unittest.TestCase):
     
 
 if __name__ == "__main__":
-  builder=conop.GetBuilder()
-  if not hasattr(builder, 'compound_lib'):
-    print 'default builder does not use compound library. ignoring unit tests'
+  if not conop.GetDefaultLib():
+    print 'No compound library available. Ignoring unit tests'
   else:
     from ost import testutils
     testutils.RunTests()
diff --git a/modules/conop/tests/test_processor.py b/modules/conop/tests/test_processor.py
new file mode 100644
index 0000000000000000000000000000000000000000..94a1a7c27d4009a86feeb5d97c671e0e6b5038f5
--- /dev/null
+++ b/modules/conop/tests/test_processor.py
@@ -0,0 +1,22 @@
+import unittest
+from ost import conop, mol
+
+
+class TestProcessor(unittest.TestCase):
+  def testPyWrap(self):
+    class MyProc(conop.Processor):
+      def __init__(self):
+        conop.Processor.__init__(self)
+        self.count =0
+      def DoProcess(self, diag, ent):
+        self.count+=1
+    p = MyProc()
+    ent = mol.CreateEntity()
+    p.Process(ent)
+    self.assertEqual(p.count, 1)
+
+if __name__ == "__main__":
+  from ost import testutils
+  testutils.RunTests()
+
+
diff --git a/modules/conop/tests/test_rule_based_conop.cc b/modules/conop/tests/test_rule_based_conop.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6444695d9f85cece9e06c9b4c6153ec8645963ba
--- /dev/null
+++ b/modules/conop/tests/test_rule_based_conop.cc
@@ -0,0 +1,200 @@
+
+// -----------------------------------------------------------------------------
+// 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
+// -----------------------------------------------------------------------------
+
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+#include <boost/test/auto_unit_test.hpp>
+
+#include <ost/mol/mol.hh>
+#include <ost/platform.hh>
+#include <ost/log.hh>
+#include <ost/conop/rule_based.hh>
+#include <ost/conop/conop.hh>
+#include "helper.hh"
+
+using boost::unit_test_framework::test_suite;
+using namespace ost;
+using namespace ost::conop;
+//using namespace ost::io;
+using namespace ost::mol;
+
+CompoundLibPtr load_lib()
+{
+  if (!getenv("OST_ROOT")) {
+    LOG_ERROR("OST_ROOT environment variable not set. Can't load "
+              "compound library without a proper OST_ROOT");
+    return CompoundLibPtr();
+  }
+  SetPrefixPath(getenv("OST_ROOT"));
+  String lib_path=GetSharedDataPath()+"/compounds.chemlib";
+  CompoundLibPtr compound_lib=CompoundLib::Load(lib_path);  
+  return compound_lib;
+}
+
+BOOST_AUTO_TEST_SUITE(conop);
+
+BOOST_AUTO_TEST_CASE(rule_based_set_get_flags)
+{
+   CompoundLibPtr lib=load_lib(); 
+   if (!lib) { return; }
+   RuleBasedProcessor rbc(lib);
+   // check the defaults
+   BOOST_CHECK_EQUAL(rbc.GetConnect(), true);
+   BOOST_CHECK_EQUAL(rbc.GetCheckBondFeasibility(), false);
+   BOOST_CHECK_EQUAL(rbc.GetUnkAtomTreatment(), CONOP_WARN);
+   BOOST_CHECK_EQUAL(rbc.GetUnkResidueTreatment(), CONOP_WARN);
+   BOOST_CHECK_EQUAL(rbc.GetStrictHydrogens(), false);
+   rbc.SetConnect(false);
+   rbc.SetStrictHydrogens(true);
+   rbc.SetCheckBondFeasibility(true);
+   rbc.SetUnkResidueTreatment(CONOP_FATAL);
+   rbc.SetUnkAtomTreatment(CONOP_REMOVE);
+   BOOST_CHECK_EQUAL(rbc.GetConnect(), false);
+   BOOST_CHECK_EQUAL(rbc.GetStrictHydrogens(), true);
+   BOOST_CHECK_EQUAL(rbc.GetCheckBondFeasibility(),true);
+   BOOST_CHECK_EQUAL(rbc.GetUnkResidueTreatment(),CONOP_FATAL);
+   BOOST_CHECK_EQUAL(rbc.GetUnkAtomTreatment(),CONOP_REMOVE);
+}
+
+
+BOOST_AUTO_TEST_CASE(rule_based_connect)
+{
+  CompoundLibPtr lib=load_lib();
+  if (!lib) { return; }
+  RuleBasedProcessor rbc(lib);
+  EntityHandle ent = CreateEntity();
+  ChainHandle ch=ent.EditXCS().InsertChain("A");
+  ResidueHandle r = make_cytosine(ch);
+  rbc.SetConnect(false); 
+  rbc.Process(ent);
+  BOOST_CHECK_EQUAL(static_cast<size_t>(0),
+                    ent.GetBondList().size());
+  rbc.SetConnect(true); 
+  rbc.Process(ent);
+  verify_nucleotide_connectivity(r);
+}
+
+
+BOOST_AUTO_TEST_CASE(rule_based_unk_atoms)
+{
+  CompoundLibPtr lib = load_lib(); 
+  if (!lib) { return; }
+  RuleBasedProcessor rbc(lib);
+  EntityHandle ent = CreateEntity();
+  XCSEditor edi=ent.EditXCS();
+  ChainHandle ch = edi.InsertChain("A");
+  ResidueHandle gly = edi.AppendResidue(ch, "GLY");
+  edi.InsertAtom(gly, "N", geom::Vec3());
+  edi.InsertAtom(gly, "CA", geom::Vec3());
+  edi.InsertAtom(gly, "C", geom::Vec3());
+  edi.InsertAtom(gly, "O", geom::Vec3());
+  edi.InsertAtom(gly, "CB", geom::Vec3());
+  EntityHandle ent2 = ent.Copy();
+  rbc.SetUnkAtomTreatment(CONOP_SILENT);
+  DiagnosticsPtr diags=rbc.Process(ent2);
+  BOOST_CHECK_EQUAL(diags->diag_count(), static_cast<size_t>(0));
+  rbc.SetUnkAtomTreatment(CONOP_WARN);
+  diags = rbc.Process(ent2);
+  BOOST_CHECK_EQUAL(diags->diag_count(), static_cast<size_t>(1));
+  ent2 = ent.Copy();
+  rbc.SetUnkAtomTreatment(CONOP_REMOVE);
+  rbc.Process(ent2);
+  BOOST_CHECK(!ent2.FindAtom("A", 1, "CB"));
+  ent2 = ent.Copy();
+  rbc.SetUnkAtomTreatment(CONOP_REMOVE_RESIDUE);
+  rbc.Process(ent2);
+  BOOST_CHECK_EQUAL(ent2.GetResidueCount(), 0);
+}
+
+BOOST_AUTO_TEST_CASE(guesses_elements_of_unknown_atoms)
+{
+  CompoundLibPtr lib = load_lib(); 
+  if (!lib) { return; }
+  RuleBasedProcessor rbc(lib);
+  EntityHandle ent = CreateEntity();
+  XCSEditor edi=ent.EditXCS();
+  ChainHandle ch = edi.InsertChain("A");
+  ResidueHandle gly = edi.AppendResidue(ch, "???");
+  ResidueHandle gly2 = edi.AppendResidue(ch, "GLY");
+  AtomHandle ca1 = edi.InsertAtom(gly, "CA", geom::Vec3(0,0,0));
+  AtomHandle ca2 = edi.InsertAtom(gly2, "CX", geom::Vec3(0,0,0));
+  DiagnosticsPtr diags=rbc.Process(ent);
+  BOOST_CHECK_EQUAL(ca1.GetElement(), "C");
+  BOOST_CHECK_EQUAL(ca2.GetElement(), "C");
+}
+
+BOOST_AUTO_TEST_CASE(fills_properties_of_unknown_residues)
+{
+  CompoundLibPtr lib = load_lib(); 
+  if (!lib) { return; }
+  RuleBasedProcessor rbc(lib);
+  EntityHandle ent = CreateEntity();
+  XCSEditor edi=ent.EditXCS();
+  ChainHandle ch = edi.InsertChain("A");
+  ResidueHandle gly = edi.AppendResidue(ch, "???");
+  gly.SetOneLetterCode('G');
+  gly.SetChemClass(ChemClass(ChemClass::PEPTIDE_LINKING));
+  DiagnosticsPtr diags=rbc.Process(ent);
+  BOOST_CHECK_EQUAL(gly.GetOneLetterCode(), '?');
+  BOOST_CHECK_EQUAL(gly.GetName(), "???");
+  BOOST_CHECK_EQUAL(gly.GetChemClass(), ChemClass(ChemClass::UNKNOWN));
+}
+
+BOOST_AUTO_TEST_CASE(connects_atoms_of_unknown_residues_based_on_distance) 
+{
+
+  CompoundLibPtr lib = load_lib(); 
+  if (!lib) { return; }
+  RuleBasedProcessor rbc(lib);
+  EntityHandle ent = CreateEntity();
+  XCSEditor edi=ent.EditXCS();
+  ChainHandle ch = edi.InsertChain("A");
+  ResidueHandle gly = edi.AppendResidue(ch, "???");
+  AtomHandle ca = edi.InsertAtom(gly, "CA", geom::Vec3(0,0,0));
+  AtomHandle c = edi.InsertAtom(gly, "C", geom::Vec3(1.54,0,0));
+  AtomHandle o = edi.InsertAtom(gly, "O", geom::Vec3(1.54,3,0));
+  DiagnosticsPtr diags=rbc.Process(ent);
+  BOOST_CHECK(BondExists(ca, c));
+  BOOST_CHECK(!BondExists(c, o));
+}
+
+BOOST_AUTO_TEST_CASE(rule_based_unk_res)
+{
+  CompoundLibPtr lib = load_lib(); 
+  if (!lib) { return; }
+  RuleBasedProcessor rbc(lib);
+  EntityHandle ent = CreateEntity();
+  XCSEditor edi=ent.EditXCS();
+  ChainHandle ch = edi.InsertChain("A");
+  ResidueHandle gly = edi.AppendResidue(ch, "???");
+  EntityHandle ent2 = ent.Copy();
+  rbc.SetUnkResidueTreatment(CONOP_SILENT); 
+  DiagnosticsPtr diags=rbc.Process(ent2);
+  BOOST_CHECK_EQUAL(diags->diag_count(), static_cast<size_t>(0));
+  rbc.SetUnkResidueTreatment(CONOP_WARN);
+  diags = rbc.Process(ent2);
+  BOOST_CHECK_EQUAL(diags->diag_count(), static_cast<size_t>(1));
+  ent2 = ent.Copy();
+  rbc.SetUnkResidueTreatment(CONOP_REMOVE);
+  rbc.Process(ent2);
+  BOOST_CHECK(!ent2.FindResidue("A", 1));
+}
+
+BOOST_AUTO_TEST_SUITE_END();
diff --git a/modules/geom/pymod/export_mat4.cc b/modules/geom/pymod/export_mat4.cc
index ec003a0e36105c29014fc8c93c1c80845cf5b805..c457eb2618833c699cc8dd925ee235dcb015d0ff 100644
--- a/modules/geom/pymod/export_mat4.cc
+++ b/modules/geom/pymod/export_mat4.cc
@@ -18,10 +18,12 @@
 //------------------------------------------------------------------------------
 #define BOOST_PYTHON_MAX_ARITY 20
 #include <boost/python.hpp>
+#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
 #include <boost/python/slice.hpp>
 using namespace boost::python;
 
 #include <ost/geom/geom.hh>
+#include <ost/geom/export_helper/vector.hh>
 using namespace geom;
 
 
@@ -138,4 +140,9 @@ void export_Mat4()
     .def("PasteTranslation",&Mat4::PasteTranslation)
     .add_property("data",mat4_data)
   ;
+
+  class_<Mat4List>("Mat4List", init<>())
+    .def(vector_indexing_suite<Mat4List>())
+    .def(geom::VectorAdditions<Mat4List>())
+  ;
 }
diff --git a/modules/geom/src/mat4.hh b/modules/geom/src/mat4.hh
index 998bbc485fe885d0f3734ef543dc4dec724d0a2c..95ca3d63270923145c57d0e56f61889ae31741d4 100644
--- a/modules/geom/src/mat4.hh
+++ b/modules/geom/src/mat4.hh
@@ -22,6 +22,7 @@
 #include <cassert>
 #include <cstddef> // for size_t
 #include <ostream>
+#include <vector>
 
 #include <boost/operators.hpp>
 
@@ -136,6 +137,8 @@ double i32, double i33);
 
 };
 
+typedef std::vector<Mat4> Mat4List;
+
 DLLEXPORT_OST_GEOM std::ostream& operator<<(std::ostream& os, const Mat4& m);
 
 } // ns geom
diff --git a/modules/gui/pymod/dng/init.py b/modules/gui/pymod/dng/init.py
index ffe73d8b77d085e6c9aeb6c0cbd4a0ea8d894b6f..4be7ed291f886c072dc9198d2ddbaf11dac9f438 100644
--- a/modules/gui/pymod/dng/init.py
+++ b/modules/gui/pymod/dng/init.py
@@ -35,17 +35,17 @@ def _my_exit(code):
 sys._exit=sys.exit
 sys.exit=_my_exit
 
-def _InitRuleBasedBuilder():
+def _InitRuleBasedProcessor():
   compound_lib_path=os.path.join(ost.GetSharedDataPath(), 'compounds.chemlib')
   if os.path.exists(compound_lib_path):
     conop_inst=conop.Conopology.Instance()
     compound_lib=conop.CompoundLib.Load(compound_lib_path)
-    conop_inst.RegisterBuilder(conop.RuleBasedBuilder(compound_lib), 'RBB')
-    conop_inst.SetDefaultBuilder('RBB')
+    conop_inst.SetDefaultLib(compound_lib)
+    io.profiles['DEFAULT'].processor = conop.RuleBasedProcessor(compound_lib)
 
-# switch to rule-based builder for high fidelity if compounds.chemlib is 
+# switch to rule-based processor for high fidelity if compounds.chemlib is 
 # available
-_InitRuleBasedBuilder()
+_InitRuleBasedProcessor()
 
 def _CheckRestore():
   settings = QtCore.QSettings()
@@ -165,8 +165,8 @@ parser.add_option("-v", "--verbosity_level", action="store", type="int", dest="v
                   help="sets the verbosity level [default: %default]")
 parser.add_option("-s", "--script", action="callback", default=[], dest="script", type="string", callback=parse_script_option, help="executes a script (syntax: -s SCRIPT [options] [args]) Anything that follows this option is passed to the script")
 parser.add_option("-p", "--pdb_id", dest="pdb_ids", default=[],action="append", help="PDB file ID. The file will be retrieved from PDB")
-parser.add_option("-b", "--builder", dest="builder", default="HEURISTIC", help="Type of builder used by the progam (either RULE_BASED or HEURISTIC) [default: %default]")
-parser.add_option("-c", "--compound_library", dest="complib", default="compounds.chemlib", help="Compound library for the RULE_BASED builder (only used if --builder option is set to RULE_BASED, otherwise ignored [default: %default]")
+parser.add_option("-b", "--processor", dest="processor", default="HEURISTIC", help="Type of processor used by the progam (either RULE_BASED or HEURISTIC) [default: %default]")
+parser.add_option("-c", "--compound_library", dest="complib", default="compounds.chemlib", help="Compound library for the RULE_BASED processor (only used if --processor option is set to RULE_BASED, otherwise ignored [default: %default]")
 parser.add_option("-q", "--query", dest="query", default="", help="Selection query to be highlighted automatically upon loading (only used together with -p option or when a PDB file is loaded, otherwise ignored [default: None]")
 parser.add_option("-S","--stereo", dest="try_stereo", default=False, action="store_true",help="try to get a quad-buffer stereo visual")
 parser.disable_interspersed_args()
@@ -184,12 +184,12 @@ if len(parser.rargs)!=0:
 if len(options.script)!=0:
   script_argv=options.script
 
-if options.builder=="RULE_BASED":
+if options.processor=="RULE_BASED":
   from ost import conop
-  compound_lib=conop.CompoundLib.Load(options.complib)
-  rbb=conop.RuleBasedBuilder(compound_lib)
-  conop.Conopology.Instance().RegisterBuilder(rbb,'rbb')
-  conop.Conopology.Instance().SetDefaultBuilder('rbb')
+  if os.path.exists(options.complib):
+    compound_lib=conop.CompoundLib.Load(options.complib)
+    conop.SetDefaultLib(compound_lib)
+    io.profiles['DEFAULT'].processor = conop.RuleBasedProcessor(compound_lib)
 
 home = os.getenv('HOME') or os.getenv('USERPROFILE')
 _ostrc=os.path.join(home, '.ostrc')
diff --git a/modules/gui/src/file_loader.cc b/modules/gui/src/file_loader.cc
index bc69ba7b852e035afa0c9417b46f2c4217d39f03..99a3da1f03ac99aa56bb75839c591db9b5159437 100644
--- a/modules/gui/src/file_loader.cc
+++ b/modules/gui/src/file_loader.cc
@@ -25,6 +25,7 @@
 
 #include <ost/io/io_manager.hh>
 #include <ost/io/mol/pdb_reader.hh>
+#include <ost/io/mol/io_profile.hh>
 #include <ost/io/mol/load_entity.hh>
 #include <ost/io/mol/load_surface.hh>
 #include <ost/io/mol/entity_io_pdb_handler.hh>
@@ -220,9 +221,11 @@ gfx::GfxObjP FileLoader::TryLoadEntity(const QString& filename, io::EntityIOHand
       mol::EntityHandle eh=mol::CreateEntity();
       mol::XCSEditor xcs_lock=eh.EditXCS(mol::BUFFERED_EDIT);
       handler->Import(eh,filename.toStdString());
-      if(handler->RequiresBuilder()) {
-          conop::BuilderP builder = conop::Conopology::Instance().GetBuilder();
-          conop::Conopology::Instance().ConnectAll(builder,eh,0);
+      if(handler->RequiresProcessor()) {
+          io::IOProfile& prof = io::IOProfileRegistry::Instance().GetDefault();
+          if (prof.processor) {
+            prof.processor->Process(eh);
+          }
       }
       gfx::GfxObjP obj(new gfx::Entity(file_info.baseName().toStdString(),
                        eh, mol::Query(selection.toStdString())));
@@ -353,7 +356,6 @@ void FileLoader::LoadPDB(const QString& filename, const QString& selection)
 {
   io::PDBReader reader(filename.toStdString(), io::IOProfile());
   QList<mol::EntityHandle> entities;
-  conop::BuilderP builder=conop::Conopology::Instance().GetBuilder("DEFAULT");
   while (reader.HasNext()){
     mol::EntityHandle ent=mol::CreateEntity();
     try {
@@ -362,7 +364,10 @@ void FileLoader::LoadPDB(const QString& filename, const QString& selection)
       LOG_ERROR(e.what());
       continue;
     }
-    conop::Conopology::Instance().ConnectAll(builder,ent,0);
+    io::IOProfile& prof = io::IOProfileRegistry::Instance().GetDefault();
+    if (prof.processor) {
+      prof.processor->Process(ent);
+    }
     entities.append(ent);
   }
   QFileInfo file_info(filename);
diff --git a/modules/io/doc/mmcif.rst b/modules/io/doc/mmcif.rst
index 50eb8cffed40ff887c236aa266a4f2304456a785..b8c63d9dedf7b0184ca835713de65b4ea5116f35 100644
--- a/modules/io/doc/mmcif.rst
+++ b/modules/io/doc/mmcif.rst
@@ -607,8 +607,7 @@ of the annotation available.
 
     Since this function is at the moment mainly used to create biounits from
     mmCIF files to be saved as PDBs, the function assumes that the
-    :ref:`ChainType` properties are set correctly. :func:`ost.conop.ConnectAll`
-    is used to derive connectivity.
+    :ref:`ChainType` properties are set correctly. 
 
     :param asu:  Asymmetric unit to work on. Should be created from a mmCIF
                  file.
@@ -994,6 +993,7 @@ of the annotation available.
 ..  LocalWords:  auth GetMMCifPDBChainTr AddPDBCMMCifhainTr GetPDBMMCifChainTr
 ..  LocalWords:  GetRevisions AddRevision SetRevisionsDateOriginal GetSize
 ..  LocalWords:  GetNum num GetStatus GetLastDate GetFirstRelease storable
+..  LocalWords:  cas isbn pubmed asu seqres conop casp COMPND OBSLTE
 ..  LocalWords:  SetChainList MMCifInfoTransOp ChainTypes MMCifInfoStructRef
 ..  LocalWords:  MMCifInfoRevisions bool difs MMCifInfoStructRefSeqDif rnum
 ..  LocalWords:  SetDateOriginal GetDateOriginal yyyy operationsintervalls
diff --git a/modules/io/pymod/__init__.py b/modules/io/pymod/__init__.py
index 179808c8d6452832329617ac22f86678cf556fdd..7fcf429230c8eeddcd1a5873286d0312a056c239 100644
--- a/modules/io/pymod/__init__.py
+++ b/modules/io/pymod/__init__.py
@@ -19,7 +19,7 @@
 import os, tempfile, ftplib, httplib
 
 from _ost_io import *
-from ost import mol, geom, conop
+from ost import mol, geom, conop, seq
 
 profiles=None
 
@@ -44,14 +44,16 @@ class IOProfiles:
 
 if not profiles:
   profiles=IOProfiles()
+  if conop.GetDefaultLib():
+    processor = conop.RuleBasedProcessor(conop.GetDefaultLib())
+  else:
+    processor = conop.HeuristicProcessor()
   profiles['STRICT']=IOProfile(dialect='PDB', fault_tolerant=False,
-                               strict_hydrogens=False, quack_mode=False)
+                               quack_mode=False, processor=processor.Copy())
   profiles['SLOPPY']=IOProfile(dialect='PDB', fault_tolerant=True,
-                               strict_hydrogens=False, quack_mode=True,
-                               bond_feasibility_check=True)
+                               quack_mode=True, processor=processor.Copy())
   profiles['CHARMM']=IOProfile(dialect='CHARMM', fault_tolerant=True,
-                               strict_hydrogens=False, quack_mode=False,
-                               bond_feasibility_check=True)
+                               quack_mode=False, processor=processor.Copy())
   profiles['DEFAULT']='STRICT'
 
 def _override(val1, val2):
@@ -64,7 +66,7 @@ def LoadPDB(filename, restrict_chains="", no_hetatms=None,
             fault_tolerant=None, load_multi=False, quack_mode=None,
             join_spread_atom_records=None, calpha_only=None,
             profile='DEFAULT', remote=False, dialect=None,
-            strict_hydrogens=None, seqres=False, bond_feasibility_check=None):
+            seqres=False, bond_feasibility_check=None):
   """
   Load PDB file from disk and return one or more entities. Several options 
   allow to customize the exact behaviour of the PDB import. For more information 
@@ -102,8 +104,6 @@ def LoadPDB(filename, restrict_chains="", no_hetatms=None,
 
   :type dialect: :class:`str`
   
-  :param strict_hydrogens: If set, overrides the value of 
-     :attr:`IOProfile.strict_hydrogens`.
 
   :raises: :exc:`~ost.io.IOException` if the import fails due to an erroneous or 
       inexistent file
@@ -126,9 +126,10 @@ def LoadPDB(filename, restrict_chains="", no_hetatms=None,
   prof.no_hetatms=_override(prof.no_hetatms, no_hetatms)
   prof.dialect=_override(prof.dialect, dialect)
   prof.quack_mode=_override(prof.quack_mode, quack_mode)
-  prof.strict_hydrogens=_override(prof.strict_hydrogens, strict_hydrogens)
+  if prof.processor:
+    prof.processor.check_bond_feasibility=_override(prof.processor.check_bond_feasibility, 
+                                                    bond_feasibility_check)
   prof.fault_tolerant=_override(prof.fault_tolerant, fault_tolerant)
-  prof.bond_feasibility_check=_override(prof.bond_feasibility_check, bond_feasibility_check)
   prof.join_spread_atom_records=_override(prof.join_spread_atom_records,
                                           join_spread_atom_records)
 
@@ -139,13 +140,11 @@ def LoadPDB(filename, restrict_chains="", no_hetatms=None,
     filename = tmp_file.name
   
   conop_inst=conop.Conopology.Instance()
-  builder=conop_inst.GetBuilder("DEFAULT")
-  if prof.dialect=='PDB':
-    builder.dialect=conop.PDB_DIALECT
-  elif prof.dialect=='CHARMM':
-    builder.dialect=conop.CHARMM_DIALECT
-  builder.strict_hydrogens=prof.strict_hydrogens
-  builder.bond_feasibility_check=prof.bond_feasibility_check
+  if prof.processor:
+    if prof.dialect=='PDB':
+      prof.processor.dialect=conop.PDB_DIALECT
+    elif prof.dialect=='CHARMM':
+      prof.processor.dialect=conop.CHARMM_DIALECT
   reader=PDBReader(filename, prof)
   reader.read_seqres=seqres
   try:
@@ -154,7 +153,8 @@ def LoadPDB(filename, restrict_chains="", no_hetatms=None,
       while reader.HasNext():
         ent=mol.CreateEntity()
         reader.Import(ent, restrict_chains)
-        conop_inst.ConnectAll(builder, ent, 0)
+        if prof.processor:
+          prof.processor.Process(ent)
         ent_list.append(ent)
       if len(ent_list)==0:
         raise IOError("File '%s' doesn't contain any entities" % filename)
@@ -163,7 +163,8 @@ def LoadPDB(filename, restrict_chains="", no_hetatms=None,
       ent=mol.CreateEntity()
       if reader.HasNext():
         reader.Import(ent, restrict_chains)
-        conop_inst.ConnectAll(builder, ent, 0)
+        if prof.processor:
+          prof.processor.Process(ent)
       else:
         raise IOError("File '%s' doesn't contain any entities" % filename)
       if seqres:
@@ -255,7 +256,7 @@ def LoadCHARMMTraj(crd, dcd_file=None, profile='CHARMM',
       raise ValueError("No DCD filename given")
   return LoadCHARMMTraj_(crd, dcd_file, stride, lazy_load, detect_swap, swap_bytes)
 
-def LoadMMCIF(filename, restrict_chains="", fault_tolerant=None, calpha_only=None, profile='DEFAULT', remote=False, strict_hydrogens=None, seqres=False, info=False):
+def LoadMMCIF(filename, restrict_chains="", fault_tolerant=None, calpha_only=None, profile='DEFAULT', remote=False, seqres=False, info=False):
   """
   Load MMCIF file from disk and return one or more entities. Several options 
   allow to customize the exact behaviour of the MMCIF import. For more
@@ -275,9 +276,6 @@ def LoadMMCIF(filename, restrict_chains="", fault_tolerant=None, calpha_only=Non
      
   :rtype: :class:`~ost.mol.EntityHandle`.
   
-  :param strict_hydrogens: If set, overrides the value of 
-     :attr:`IOProfile.strict_hydrogens`.
-
   :param seqres: Whether to read SEQRES records. If set to True, the loaded 
     entity and seqres entry will be returned as second item.
 
@@ -298,7 +296,6 @@ def LoadMMCIF(filename, restrict_chains="", fault_tolerant=None, calpha_only=Non
     prof = profile.Copy()
 
   prof.calpha_only=_override(prof.calpha_only, calpha_only)
-  prof.strict_hydrogens=_override(prof.strict_hydrogens, strict_hydrogens)
   prof.fault_tolerant=_override(prof.fault_tolerant, fault_tolerant)
 
   if remote:
@@ -308,18 +305,14 @@ def LoadMMCIF(filename, restrict_chains="", fault_tolerant=None, calpha_only=Non
     else:
       raise IOError('Can not load PDB %s from www.pdb.org'%filename) 
   
-  conop_inst = conop.Conopology.Instance()
-  builder = conop_inst.GetBuilder("DEFAULT")
-
-  builder.strict_hydrogens = prof.strict_hydrogens
-
   try:
     ent = mol.CreateEntity()
     reader = MMCifReader(filename, ent, prof)
     reader.read_seqres = seqres
     #if reader.HasNext():
     reader.Parse()
-    conop_inst.ConnectAll(builder, ent, 0)
+    if prof.processor:
+      prof.processor.Process(ent)
     #else:
     #  raise IOError("File doesn't contain any entities")
     if seqres and info:
@@ -340,39 +333,21 @@ def LoadMMCIF(filename, restrict_chains="", fault_tolerant=None, calpha_only=Non
 # MMCifInfoBioUnit.PDBize, since this function is not included in SPHINX.
 def _PDBize(biounit, asu, seqres=None, min_polymer_size=10,
             transformation=False):
-  def _CopyAtoms(src_res, dst_res, edi, trans=geom.Mat4()):
-    atom_pos_wrong = False
-    for atom in src_res.atoms:
-      tmp_pos = geom.Vec4(atom.pos)
-      new_atom=edi.InsertAtom(dst_res, atom.name, geom.Vec3(trans*tmp_pos), 
-                              element=atom.element,
-                              occupancy=atom.occupancy, 
-                              b_factor=atom.b_factor,
-                              is_hetatm=atom.is_hetatom)
-      for p in range(0,3):
-        if new_atom.pos[p] <= -1000:
-          atom_pos_wrong = True
-        elif new_atom.pos[p] >= 10000:
-          atom_pos_wrong = True
-    return atom_pos_wrong
-
-  chain_names='ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz'
-  cur_chain_name = 0
-  water_chain = mol.ChainHandle()
-  ligand_chain = mol.ChainHandle()
-  a_pos_wrong = False
-  pdb_bu = mol.CreateEntity()
-  edi = pdb_bu.EditXCS(mol.BUFFERED_EDIT)
+  pdbizer = mol.alg.PDBize(min_polymer_size=min_polymer_size)
+
   chains = biounit.GetChainList()
   c_intvls = biounit.GetChainIntervalList()
   o_intvls = biounit.GetOperationsIntervalList()
+  ss = seqres
+  if not ss:
+    ss = seq.CreateSequenceList()
   # create list of operations
   # for cartesian products, operations are stored in a list, multiplied with
   # the next list of operations and re-stored... until all lists of operations
   # are multiplied in an all-against-all manner.
   operations = biounit.GetOperations()
   for i in range(0,len(c_intvls)):
-    trans_matrices = list()
+    trans_matrices = geom.Mat4List()
     l_operations = operations[o_intvls[i][0]:o_intvls[i][1]]
     if len(l_operations) > 0:
       for op in l_operations[0]:
@@ -398,95 +373,10 @@ def _PDBize(biounit, asu, seqres=None, min_polymer_size=10,
         trans_matrices = tmp_ops
     # select chains into a view as basis for each transformation
     assu = asu.Select('cname='+','.join(chains[c_intvls[i][0]:c_intvls[i][1]]))
-    # use each transformation on the view, store as entity and transform, PDBize
-    # the result while adding everything to one large entity
-    for tr in trans_matrices:
-      # do a PDBize, add each new entity to the end product
-      for chain in assu.chains:
-        residue_count = len(chain.residues)
-        if seqres:
-          seqres_chain = seqres.FindSequence(chain.name)
-          if seqres_chain.IsValid():
-            residue_count = len(seqres_chain)
-        if chain.is_polymer and residue_count >= min_polymer_size:
-          if len(chain_names) == cur_chain_name:
-            raise RuntimeError('Running out of chain names')
-          new_chain = edi.InsertChain(chain_names[cur_chain_name])
-          cur_chain_name += 1
-          edi.SetChainDescription(new_chain, chain.description)
-          edi.SetChainType(new_chain, chain.type)
-          new_chain.SetStringProp('original_name', chain.name)
-          if chain.HasProp("pdb_auth_chain_name"):
-            new_chain.SetStringProp("pdb_auth_chain_name", 
-                                    chain.GetStringProp("pdb_auth_chain_name"))
-          for res in chain.residues:
-            new_res = edi.AppendResidue(new_chain, res.name, res.number)
-            a_b = _CopyAtoms(res, new_res, edi, tr)
-            if not a_pos_wrong:
-              a_pos_wrong = a_b
-        elif chain.type == mol.CHAINTYPE_WATER:
-          if not water_chain.IsValid():
-            # water gets '-' as name
-            water_chain = edi.InsertChain('-')
-            edi.SetChainDescription(water_chain, chain.description)
-            edi.SetChainType(water_chain, chain.type)
-          for res in chain.residues:
-            new_res = edi.AppendResidue(water_chain, res.name)
-            new_res.SetStringProp('type', mol.StringFromChainType(chain.type))
-            new_res.SetStringProp('description', chain.description)
-            a_b = _CopyAtoms(res, new_res, edi, tr)
-            if not a_pos_wrong:
-              a_pos_wrong = a_b
-        else:
-          if not ligand_chain.IsValid():
-            # all ligands, put in one chain, are named '_'
-            ligand_chain = edi.InsertChain('_')
-            last_rnum = 0
-          else:
-            last_rnum = ligand_chain.residues[-1].number.num
-          residues=chain.residues
-          ins_code='\0'
-          if len(residues)>1:
-            ins_code='A'
-          for res in chain.residues:
-            new_res = edi.AppendResidue(ligand_chain, res.name, 
-                                        mol.ResNum(last_rnum+1, ins_code))
-            new_res.SetStringProp('description', chain.description)
-            new_res.SetStringProp('type', mol.StringFromChainType(chain.type))
-            new_res.SetStringProp("original_name", chain.name)
-            if chain.HasProp("pdb_auth_chain_name"):
-              new_res.SetStringProp("pdb_auth_chain_name",
-                                    chain.GetStringProp("pdb_auth_chain_name"))
-            ins_code = chr(ord(ins_code)+1)
-            a_b = _CopyAtoms(res, new_res, edi, tr)
-            if not a_pos_wrong:
-              a_pos_wrong = a_b
-  move_to_origin = None
-  if a_pos_wrong:
-    start = pdb_bu.bounds.min
-    move_to_origin = geom.Mat4(1,0,0,(-999 - start[0]),
-                               0,1,0,(-999 - start[1]),
-                               0,0,1,(-999 - start[2]),
-                               0,0,0,1)
-    edi = pdb_bu.EditXCS(mol.UNBUFFERED_EDIT)
-    edi.ApplyTransform(move_to_origin)
-  conop.ConnectAll(pdb_bu)
+    pdbizer.Add(assu, trans_matrices, ss)
+  pdb_bu = pdbizer.Finish(transformation)
   if transformation:
-    return pdb_bu, move_to_origin
+    return pdb_bu, pdb_bu.GetTransformationMatrix()
   return pdb_bu
 
 MMCifInfoBioUnit.PDBize = _PDBize
-
-## \example fft_li.py
-#
-# This scripts loads one or more images and shows their Fourier Transforms on 
-# the screen. A viewer is opened for each loaded image. The Fourier Transform 
-# honors the origin of the reference system, which is assumed to be at the 
-# center of the image.
-#
-# Usage:
-#
-# \code giplt view_ft.py <image1> [<image2> <image3> .... ] \endcode
-#
-# <BR>
-# <BR>
diff --git a/modules/io/pymod/export_pdb_io.cc b/modules/io/pymod/export_pdb_io.cc
index 7d97682df3f006fc41959edc3f9c4e623041031e..c5062e20d92694a84a029346764bc55cbe4d41fe 100644
--- a/modules/io/pymod/export_pdb_io.cc
+++ b/modules/io/pymod/export_pdb_io.cc
@@ -36,22 +36,22 @@ void (PDBWriter::*write_b)(const mol::EntityView&)=&PDBWriter::Write;
 void export_pdb_io()
 {
   class_<IOProfile>("IOProfile",
-         init<String,bool,bool,bool,bool,bool,bool,bool>((arg("dialect")="PDB",
-                                                          arg("strict_hydrogens")=false,
-                                                          arg("quack_mode")=false,
-                                                          arg("fault_tolerant")=false,
-                                                          arg("join_spread_atom_records")=false,
-                                                          arg("no_hetatms")=false,
-                                                          arg("calpha_only")=false,
-						          arg("bond_feasibility_check")=false)))
+         init<String,bool,bool,bool,bool,bool,
+              conop::ProcessorPtr>((arg("dialect")="PDB",
+                                    arg("quack_mode")=false,
+                                    arg("fault_tolerant")=false,
+                                    arg("join_spread_atom_records")=false,
+                                    arg("no_hetatms")=false,
+                                    arg("calpha_only")=false,
+                                    arg("processor")=conop::ProcessorPtr())))
+    .def(init<const IOProfile&>())
     .def_readwrite("dialect", &IOProfile::dialect)
     .def_readwrite("fault_tolerant", &IOProfile::fault_tolerant)
     .def_readwrite("quack_mode", &IOProfile::quack_mode)
-    .def_readwrite("strict_hydrogens", &IOProfile::strict_hydrogens)
     .def_readwrite("no_hetatms", &IOProfile::no_hetatms)
     .def_readwrite("calpha_only", &IOProfile::calpha_only)
     .def_readwrite("join_spread_atom_records", &IOProfile::join_spread_atom_records)
-    .def_readwrite("bond_feasibility_check", &IOProfile::bond_feasibility_check)
+    .def_readwrite("processor", &IOProfile::processor)
     .def("Copy", &IOProfile::Copy)
     .def(self_ns::str(self))
   ;
diff --git a/modules/io/src/mol/entity_io_crd_handler.cc b/modules/io/src/mol/entity_io_crd_handler.cc
index d27feab99e3a5441eaf98b2f12c84f9e3d565bea..3d858fcc6243f21e7125234548e43e297892763c 100644
--- a/modules/io/src/mol/entity_io_crd_handler.cc
+++ b/modules/io/src/mol/entity_io_crd_handler.cc
@@ -36,6 +36,7 @@
 #include <ost/boost_filesystem_helper.hh>
 
 #include <ost/io/io_exception.hh>
+#include <ost/io/mol/io_profile.hh>
 #include <ost/io/swap_util.hh>
 
 #include "entity_io_crd_handler.hh"
@@ -345,8 +346,8 @@ bool CRDWriter::VisitAtom(const mol::AtomHandle& atom)
   return true;
 }
 
-/// \brief CHARMM file format requires builder
-bool EntityIOCRDHandler::RequiresBuilder() const
+/// \brief CHARMM file format requires processor
+bool EntityIOCRDHandler::RequiresProcessor() const
 {
   return true;
 }
@@ -406,12 +407,14 @@ bool EntityIOCRDHandler::ProvidesExport(const boost::filesystem::path& loc,
 mol::EntityHandle LoadCRD(const String& file_name) 
 {
   Profile profile_load("LoadCRD");
-  conop::BuilderP builder = conop::Conopology::Instance().GetBuilder();  
   CRDReader reader(file_name);
   mol::EntityHandle ent=mol::CreateEntity();
   mol::XCSEditor editor=ent.EditXCS(mol::BUFFERED_EDIT);
   reader.Import(ent);
-  conop::Conopology::Instance().ConnectAll(builder,ent);    
+  IOProfile& prof = IOProfileRegistry::Instance().GetDefault();
+  if (prof.processor) {
+    prof.processor->Process(ent);
+  }
   return ent;
 }
 
diff --git a/modules/io/src/mol/entity_io_crd_handler.hh b/modules/io/src/mol/entity_io_crd_handler.hh
index c0d625a804258e7bd8b16d547d228bf5589ed6d2..3781fcda4e3305307c7bf61b6fb65f38ed27736a 100644
--- a/modules/io/src/mol/entity_io_crd_handler.hh
+++ b/modules/io/src/mol/entity_io_crd_handler.hh
@@ -99,7 +99,7 @@ public:
                              const String& format="auto");
   static bool ProvidesExport(const boost::filesystem::path& loc, 
                              const String& format="auto");
-  virtual bool RequiresBuilder() const;
+  virtual bool RequiresProcessor() const;
 
   static String GetFormatName() { return String("Crd"); }
   static String GetFormatDescription() { return String("CARD format file used by the Charmm software package"); }
diff --git a/modules/io/src/mol/entity_io_handler.hh b/modules/io/src/mol/entity_io_handler.hh
index c65137e185e017ad01ec1d629c1b4dd88b453c0c..709b0762317192d4c6488534b1a52d03f3c6fd56 100644
--- a/modules/io/src/mol/entity_io_handler.hh
+++ b/modules/io/src/mol/entity_io_handler.hh
@@ -57,7 +57,7 @@ public:
   // export data from entity view to provided stream
   virtual void Export(const mol::EntityView& ent, 
                       std::ostream& stream) const=0;
-  virtual bool RequiresBuilder() const=0;
+  virtual bool RequiresProcessor() const=0;
 };
 
 typedef boost::shared_ptr<EntityIOHandler> EntityIOHandlerP;
diff --git a/modules/io/src/mol/entity_io_mae_handler.cc b/modules/io/src/mol/entity_io_mae_handler.cc
index f52a9b6b8681fc395590bf7d5f1bbaef758a7615..ca9590169c4b69e2399183a6fade389665789184 100644
--- a/modules/io/src/mol/entity_io_mae_handler.cc
+++ b/modules/io/src/mol/entity_io_mae_handler.cc
@@ -36,10 +36,9 @@
 
 #include <ost/log.hh>
 #include <ost/conop/conop.hh>
-#include <ost/conop/heuristic_builder.hh>
 #include <ost/mol/xcs_editor.hh>
 #include <ost/profile.hh>
-
+#include <ost/io/mol/io_profile.hh>
 #include <ost/io/io_exception.hh>
 #include <ost/io/swap_util.hh>
 
@@ -331,7 +330,7 @@ void MAEReader::parse_and_add_atom(mol::EntityHandle ent,
 
 
 
-bool EntityIOMAEHandler::RequiresBuilder() const
+bool EntityIOMAEHandler::RequiresProcessor() const
 {
   return true;
 }
@@ -381,13 +380,14 @@ bool EntityIOMAEHandler::ProvidesExport(const boost::filesystem::path& loc,
 
 mol::EntityHandle LoadMAE(const String& file_name) 
 {
-  //conop::BuilderP builder = conop::Conopology::Instance().GetBuilder();  
-  conop::BuilderP builder(new conop::HeuristicBuilder);
   MAEReader reader(file_name);
   mol::EntityHandle ent=mol::CreateEntity();
   mol::XCSEditor editor=ent.EditXCS(mol::BUFFERED_EDIT);
   reader.Import(ent);
-  conop::Conopology::Instance().ConnectAll(builder,ent);    
+  IOProfile& prof = IOProfileRegistry::Instance().GetDefault();
+  if (prof.processor) {
+    prof.processor->Process(ent);
+  }
   return ent;
 }
 
diff --git a/modules/io/src/mol/entity_io_mae_handler.hh b/modules/io/src/mol/entity_io_mae_handler.hh
index 8f09c375e7b3021073cc599ed524bda130c59900..7f923d3453ed60090a615b14fa2d44c20996d817 100644
--- a/modules/io/src/mol/entity_io_mae_handler.hh
+++ b/modules/io/src/mol/entity_io_mae_handler.hh
@@ -73,7 +73,7 @@ public:
                              const String& format="auto");
   static bool ProvidesExport(const boost::filesystem::path& loc, 
                              const String& format="auto");
-  virtual bool RequiresBuilder() const;
+  virtual bool RequiresProcessor() const;
 
   static String GetFormatName() { return String("Mae"); }
   static String GetFormatDescription() { return String("MAEstro coordinate file format"); }
diff --git a/modules/io/src/mol/entity_io_mmcif_handler.cc b/modules/io/src/mol/entity_io_mmcif_handler.cc
index 23e9ff3c52a1fd2652b1bbf7c1b7995eac487a11..a86d1dcebda7cc5ec73791d706b482bd6ecdb9e7 100644
--- a/modules/io/src/mol/entity_io_mmcif_handler.cc
+++ b/modules/io/src/mol/entity_io_mmcif_handler.cc
@@ -38,7 +38,7 @@ namespace ost { namespace io {
 using boost::format;
 
 
-bool EntityIOMMCIFHandler::RequiresBuilder() const
+bool EntityIOMMCIFHandler::RequiresProcessor() const
 {
   return true;
 }
diff --git a/modules/io/src/mol/entity_io_mmcif_handler.hh b/modules/io/src/mol/entity_io_mmcif_handler.hh
index 2fa262156d4867f665a8fc3f4d5ea8e71877f16f..e55a409b850f5ceae92f3b62830a8e895c0f4930 100644
--- a/modules/io/src/mol/entity_io_mmcif_handler.hh
+++ b/modules/io/src/mol/entity_io_mmcif_handler.hh
@@ -42,7 +42,7 @@ public:
                              const String& format="auto");
   static bool ProvidesExport(const boost::filesystem::path& loc, 
                              const String& format="auto");
-  virtual bool RequiresBuilder() const;
+  virtual bool RequiresProcessor() const;
 
   static String GetFormatName() { return String("mmCIF"); }
   static String GetFormatDescription() { 
diff --git a/modules/io/src/mol/entity_io_pdb_handler.cc b/modules/io/src/mol/entity_io_pdb_handler.cc
index fe70388346cf08c24c84bdb705774ec2cf4420b7..69e466a23b0c092aef483c7e1c62e18b719d2a2b 100644
--- a/modules/io/src/mol/entity_io_pdb_handler.cc
+++ b/modules/io/src/mol/entity_io_pdb_handler.cc
@@ -39,7 +39,7 @@ namespace ost { namespace io {
 using boost::format;
 
 
-bool EntityIOPDBHandler::RequiresBuilder() const
+bool EntityIOPDBHandler::RequiresProcessor() const
 {
   return true;
 }
diff --git a/modules/io/src/mol/entity_io_pdb_handler.hh b/modules/io/src/mol/entity_io_pdb_handler.hh
index 3ceea37f79a88fc7eac60a31e06e28adbcf93b4c..07bfca81e49714d6aaa5b5440820b30815baf1f0 100644
--- a/modules/io/src/mol/entity_io_pdb_handler.hh
+++ b/modules/io/src/mol/entity_io_pdb_handler.hh
@@ -45,7 +45,7 @@ public:
                              const String& format="auto");
   static bool ProvidesExport(const boost::filesystem::path& loc, 
                              const String& format="auto");
-  virtual bool RequiresBuilder() const;
+  virtual bool RequiresProcessor() const;
 
   static String GetFormatName() { return String("Pdb"); }
   static String GetFormatDescription() { return String("Protein Data Bank file format"); }
diff --git a/modules/io/src/mol/entity_io_pqr_handler.cc b/modules/io/src/mol/entity_io_pqr_handler.cc
index 5d2941c3351d9f9dd5bae11606044d742dc115bd..f1efaee3cc9da176584382cee45d26b2d530ed45 100644
--- a/modules/io/src/mol/entity_io_pqr_handler.cc
+++ b/modules/io/src/mol/entity_io_pqr_handler.cc
@@ -39,6 +39,7 @@
 
 #include <ost/io/io_exception.hh>
 #include <ost/io/swap_util.hh>
+#include <ost/io/mol/io_profile.hh>
 
 #include "entity_io_pqr_handler.hh"
 
@@ -315,12 +316,13 @@ bool EntityIOPQRHandler::ProvidesExport(const boost::filesystem::path& loc,
 mol::EntityHandle LoadPQR(const String& file_name) 
 {
   Profile profile_load("LoadPQR");
-  conop::BuilderP builder = conop::Conopology::Instance().GetBuilder();  
+  IOProfile default_profile=IOProfileRegistry::Instance().GetDefault();
   PQRReader reader(file_name);
   mol::EntityHandle ent=mol::CreateEntity();
   mol::XCSEditor editor=ent.EditXCS(mol::BUFFERED_EDIT);
   reader.Import(ent);
-  conop::Conopology::Instance().ConnectAll(builder,ent);    
+  if (default_profile.processor) 
+    default_profile.processor->Process(ent);
   return ent;
 }
 
diff --git a/modules/io/src/mol/entity_io_sdf_handler.cc b/modules/io/src/mol/entity_io_sdf_handler.cc
index 5a81405682952a05dd5452ddbae1c11e13af2fc7..31ba544b0214906993ae1fced35ebf1cbd6feffb 100644
--- a/modules/io/src/mol/entity_io_sdf_handler.cc
+++ b/modules/io/src/mol/entity_io_sdf_handler.cc
@@ -29,7 +29,7 @@
 namespace ost { namespace io {
 
 
-bool EntityIOSDFHandler::RequiresBuilder() const
+bool EntityIOSDFHandler::RequiresProcessor() const
 {
   return false;
 }
diff --git a/modules/io/src/mol/entity_io_sdf_handler.hh b/modules/io/src/mol/entity_io_sdf_handler.hh
index 66333e8d3c687fea30ad870ae7218e01ec40a9ec..55c20fc9675ed0df36494b11c456e7e8e4b49e0b 100644
--- a/modules/io/src/mol/entity_io_sdf_handler.hh
+++ b/modules/io/src/mol/entity_io_sdf_handler.hh
@@ -40,7 +40,7 @@ public:
   static bool ProvidesExport(const boost::filesystem::path& loc, 
                              const String& format="auto");
                              
-  virtual bool RequiresBuilder() const;
+  virtual bool RequiresProcessor() const;
 
   static String GetFormatName() { return String("Sdf"); }
   static String GetFormatDescription() { return String("Structure-data format from Molecular Design Limited"); }
diff --git a/modules/io/src/mol/io_profile.hh b/modules/io/src/mol/io_profile.hh
index ee880e31bb781681fbd244283f709a70a2d74ad9..abf37a6b22a2c1e389b9d58d1179e858ca9fe14a 100644
--- a/modules/io/src/mol/io_profile.hh
+++ b/modules/io/src/mol/io_profile.hh
@@ -23,47 +23,51 @@
 #include <map>
 #include <ost/mol/entity_handle.hh>
 #include <ost/io/module_config.hh>
+#include <ost/conop/processor.hh>
+
 namespace ost { namespace io {
 
+
 struct DLLEXPORT IOProfile {
 public:
-  IOProfile(String d, bool sh, bool qm, bool ft, bool js, bool nh, bool co, bool bf):
-    dialect(d), strict_hydrogens(sh), quack_mode(qm), fault_tolerant(ft),
-    join_spread_atom_records(js), no_hetatms(nh), calpha_only(co), bond_feasibility_check(bf)
-  { }
-  IOProfile(): dialect("PDB"), strict_hydrogens(true), quack_mode(false),
-    fault_tolerant(false), join_spread_atom_records(false), no_hetatms(false),
-    calpha_only(false), bond_feasibility_check(false)
+  IOProfile(String d, bool qm, bool ft, bool js, bool nh, 
+            bool co, conop::ProcessorPtr proc=conop::ProcessorPtr()):
+    dialect(d), quack_mode(qm), fault_tolerant(ft), join_spread_atom_records(js), 
+    no_hetatms(nh), calpha_only(co), processor(proc)
+  {
+  }
+
+  IOProfile(): dialect("PDB"), quack_mode(false), fault_tolerant(false), 
+    join_spread_atom_records(false), no_hetatms(false),
+    calpha_only(false), processor()
   { }
-  virtual ~IOProfile() { }
 
-  String dialect;
-  bool   strict_hydrogens;
-  bool   quack_mode;
-  bool   fault_tolerant;
-  bool   join_spread_atom_records;
-  bool   no_hetatms;
-  bool   calpha_only;
-  bool   bond_feasibility_check;
+  String              dialect;
+  bool                quack_mode;
+  bool                fault_tolerant;
+  bool                join_spread_atom_records;
+  bool                no_hetatms;
+  bool                calpha_only;
+  conop::ProcessorPtr processor;
 
   IOProfile Copy()
   {
-    return IOProfile(dialect, strict_hydrogens, quack_mode, fault_tolerant,
-                     join_spread_atom_records, no_hetatms, calpha_only, bond_feasibility_check);
+    return IOProfile(dialect, quack_mode, fault_tolerant, join_spread_atom_records, 
+                     no_hetatms, calpha_only,  
+                     processor ? processor->Copy() : conop::ProcessorPtr());
   }
-  virtual void PostImport(mol::EntityHandle ent) { }
 };
 
+
 inline  std::ostream& operator<<(std::ostream& stream, const IOProfile& p)
 {
-  stream << "IOProfile(dialect='" << p.dialect << "', strict_hydrogens="
-         << (p.strict_hydrogens ? "True" : "False") << ", quack_mode="
-         << (p.quack_mode ? "True" : "False") << ", join_spread_atom_records="
-         << (p.join_spread_atom_records ? "True" : "False") << ", no_hetatms="
-         << (p.no_hetatms ? "True" : "False") << ", calpha_only="
-         << (p.calpha_only ? "True" : "False") << ", fault_tolerant="
-         << (p.fault_tolerant ? "True" : "False") << ", bond_feasibility_check="
-	 << (p.bond_feasibility_check ? "True" : "False") << ")";
+  stream << "IOProfile(dialect='" << p.dialect
+         << "', quack_mode=" << (p.quack_mode ? "True" : "False") << ", "
+         << "join_spread_atom_records=" << (p.join_spread_atom_records ? "True" : "False") << ", "
+         << "calpha_only=" << (p.calpha_only ? "True" : "False") << ", "
+         << "fault_tolerant=" << (p.fault_tolerant ? "True" : "False") << ", "
+         << "no_hetatms=" << (p.no_hetatms ? "True" : "False") << ", "
+         << "processor=" << (p.processor ? p.processor->ToString() : "None") << ")";
   return stream;
 }
 
diff --git a/modules/io/src/mol/load_entity.cc b/modules/io/src/mol/load_entity.cc
index 6fdfa57576b4c655b744955ae02dd30809cd100e..98eea40f861a728340b8ad97b79997800bbd6119 100644
--- a/modules/io/src/mol/load_entity.cc
+++ b/modules/io/src/mol/load_entity.cc
@@ -22,6 +22,7 @@
 #include "load_entity.hh"
 #include <ost/mol/xcs_editor.hh>
 #include <ost/io/io_manager.hh>
+#include <ost/io/mol/io_profile.hh>
 #include <ost/io/mol/entity_io_handler.hh>
 #include <ost/profile.hh>
 
@@ -38,19 +39,15 @@ void Import(mol::EntityHandle& eh, const String& filename, int flag)
   // TODO: proper error handling
 
   LOG_DEBUG("calling import on entity io handle");
-  /*
-    This should probably allow various parameters to be passed
-    to adjust the loading behaviour for a particular filter.
-    Alternatively, these settings could be done outside via
-    the main IOManager interface, as global settings per import plugin
-  */
   ent_io->Import(eh,filename);
 
   LOG_DEBUG("running conopology");
 
-  if(ent_io->RequiresBuilder()) {
-    conop::BuilderP builder = conop::Conopology::Instance().GetBuilder();
-    conop::Conopology::Instance().ConnectAll(builder,eh,flag);
+  if(ent_io->RequiresProcessor()) {
+    IOProfile& prof = IOProfileRegistry::Instance().GetDefault();
+    if (prof.processor) {
+      prof.processor->Process(eh);
+    }
   }
 }
 
diff --git a/modules/io/src/mol/mmcif_reader.cc b/modules/io/src/mol/mmcif_reader.cc
index 91d46cb9b86646add1832a8ea972b6c316a3cba7..cd21e62a1318d4b93f77c8f3fb2d1d4a57f2c4cc 100644
--- a/modules/io/src/mol/mmcif_reader.cc
+++ b/modules/io/src/mol/mmcif_reader.cc
@@ -25,7 +25,6 @@
 #include <ost/mol/xcs_editor.hh>
 #include <ost/conop/conop.hh>
 
-#include <ost/conop/rule_based_builder.hh>
 #include <ost/io/mol/mmcif_reader.hh>
 
 namespace ost { namespace io {
@@ -678,17 +677,17 @@ void MMCifReader::ParseEntityPoly(const std::vector<StringRef>& columns)
       }
     } else if (indices_[PDBX_SEQ_ONE_LETTER_CODE] != -1) {
       seqres=columns[indices_[PDBX_SEQ_ONE_LETTER_CODE]];
-      conop::BuilderP builder=conop::Conopology::Instance().GetBuilder("DEFAULT");
-      conop::RuleBasedBuilderPtr rbb=dyn_cast<conop::RuleBasedBuilder>(builder);
-      if (!rbb) {
+
+      conop::CompoundLibPtr comp_lib=conop::Conopology::Instance()
+                                            .GetDefaultLib();
+      if (!comp_lib) {
         if (!warned_rule_based_) {
-          LOG_WARNING("SEQRES import requires the rule-based builder. Ignoring "
-                      "SEQRES records");      
+          LOG_WARNING("SEQRES import requires a compound library. "
+                       "Ignoring SEQRES records");      
         }
         warned_rule_based_=true;
         return;
       }
-      conop::CompoundLibPtr comp_lib=rbb->GetCompoundLib();
       edm_it->second.seqres = this->ConvertSEQRES(seqres.str_no_whitespace(),
                                                   comp_lib);
     } else {
diff --git a/modules/io/src/mol/pdb_reader.cc b/modules/io/src/mol/pdb_reader.cc
index 9f389786616e2437f4d96712390b2b99ff187f1b..ea81f65c1614de11d645e0d90e5412f41072a7c3 100644
--- a/modules/io/src/mol/pdb_reader.cc
+++ b/modules/io/src/mol/pdb_reader.cc
@@ -29,7 +29,6 @@
 #include <ost/message.hh>
 
 #include <ost/conop/conop.hh>
-#include <ost/conop/rule_based_builder.hh>
 #include <ost/geom/mat3.hh>
 #include <ost/io/io_exception.hh>
 #include "pdb_reader.hh"
@@ -235,17 +234,17 @@ void PDBReader::ParseCompndEntry (const StringRef& line, int line_num)
 
 void PDBReader::ParseSeqRes(const StringRef& line, int line_num)
 {
-  conop::BuilderP builder=conop::Conopology::Instance().GetBuilder("DEFAULT");
-  conop::RuleBasedBuilderPtr rbb=dyn_cast<conop::RuleBasedBuilder>(builder);
-  if (!rbb) {
+  conop::CompoundLibPtr comp_lib;
+  comp_lib = conop::Conopology::Instance().GetDefaultLib();
+   
+  if (!comp_lib) {
     if (!warned_rule_based_) {
-      LOG_WARNING("SEQRES import requires the rule-based builder. Ignoring "
+      LOG_WARNING("SEQRES import requires a compound library. Ignoring" 
                   "SEQRES records");      
     }
     warned_rule_based_=true;
     return;
   }
-  conop::CompoundLibPtr comp_lib=rbb->GetCompoundLib();  
   if (!seqres_.IsValid()) {
     seqres_=seq::CreateSequenceList();
   }
diff --git a/modules/io/tests/test_io_mmcif.py b/modules/io/tests/test_io_mmcif.py
index 313235d791e1921bf1bdb8d7b9d1756f33512425..4b64aa554988b298d3b8fd75a47d6f74f1d0dca0 100644
--- a/modules/io/tests/test_io_mmcif.py
+++ b/modules/io/tests/test_io_mmcif.py
@@ -199,9 +199,9 @@ class TestMMCifInfo(unittest.TestCase):
                                      seqres=True,
                                      info=True)
     pdb_ent, t = info.GetBioUnits()[0].PDBize(ent, transformation=True)
-    self.assertAlmostEquals(pdb_ent.GetCenterOfAtoms()[0], -915.8, 1)
-    self.assertAlmostEquals(pdb_ent.GetCenterOfAtoms()[1], -952.345, 2)
-    self.assertAlmostEquals(pdb_ent.GetCenterOfAtoms()[2], 3221.75, 2)
+    self.assertAlmostEquals(pdb_ent.GetCenterOfAtoms()[0], -915.759, 1)
+    self.assertAlmostEquals(pdb_ent.GetCenterOfAtoms()[1], -952.345, 1)
+    self.assertAlmostEquals(pdb_ent.GetCenterOfAtoms()[2], 3221.75, 1)
     self.assertEquals(geom.Equal(t,
                                  geom.Mat4(1,0,0,-920.462,
                                            0,1,0,-966.654,
diff --git a/modules/io/tests/test_io_pdb.cc b/modules/io/tests/test_io_pdb.cc
index 9268778ff080c3eb4b9ad071a492fe16bd9f5735..7d33d8bce38ecc45702b190cbb37439b2b94960d 100644
--- a/modules/io/tests/test_io_pdb.cc
+++ b/modules/io/tests/test_io_pdb.cc
@@ -29,7 +29,7 @@ using boost::unit_test_framework::test_suite;
 #include <ost/dyn_cast.hh>
 #include <ost/mol/mol.hh>
 #include <ost/conop/conop.hh>
-#include <ost/conop/rule_based_builder.hh>
+#include <ost/conop/heuristic.hh>
 
 #include <ost/io/mol/entity_io_pdb_handler.hh>
 #include <ost/io/pdb_reader.hh>
@@ -426,8 +426,8 @@ BOOST_AUTO_TEST_CASE(deuterium_import)
   mol::EntityHandle ent=mol::CreateEntity();
   reader.Import(ent);
   // we use conopology to mark amino acids as peptide-linking. 
-  conop::Conopology& conop_inst=conop::Conopology::Instance();
-  conop_inst.ConnectAll(conop_inst.GetBuilder(), ent);
+  conop::HeuristicProcessor heu_proc;
+  heu_proc.Process(ent);
   // this check makes sure that we correctly detect deal with the deuterium
   // atoms in the residue.
   BOOST_CHECK(ent.FindResidue("A", 297).IsPeptideLinking());
@@ -440,8 +440,8 @@ BOOST_AUTO_TEST_CASE(bzdng_318)
   mol::EntityHandle ent=mol::CreateEntity();
   reader.Import(ent);
   // we use conopology to mark amino acids as peptide-linking.
-  conop::Conopology& conop_inst=conop::Conopology::Instance();
-  conop_inst.ConnectAll(conop_inst.GetBuilder(), ent);
+  conop::HeuristicProcessor heu_proc;
+  heu_proc.Process(ent);
   {
     PDBWriter writer(std::string("testfiles/pdb/bzdng-318-out.pdb"),
                      IOProfile());
@@ -614,8 +614,9 @@ BOOST_AUTO_TEST_CASE(write_ter)
     reader.Import(ent);
     // we use conopology to mark amino acids as peptide-linking. this is require 
     // for proper TER output
-    conop::Conopology& conop_inst=conop::Conopology::Instance();
-    conop_inst.ConnectAll(conop_inst.GetBuilder(), ent);
+    conop::HeuristicProcessor heu_proc;
+
+    heu_proc.Process(ent);
     writer.Write(ent);
   }
   BOOST_CHECK(compare_files("testfiles/pdb/ter.pdb", 
@@ -635,8 +636,8 @@ BOOST_AUTO_TEST_CASE(write_ter2)
     reader.Import(ent);
     // we use conopology to mark amino acids as peptide-linking. this is 
     // require for proper TER output
-    conop::Conopology& conop_inst=conop::Conopology::Instance();
-    conop_inst.ConnectAll(conop_inst.GetBuilder(), ent);
+    conop::HeuristicProcessor heu_proc;
+    heu_proc.Process(ent);
     writer.Write(ent);
   }
   BOOST_CHECK(compare_files("testfiles/pdb/ter2.pdb", 
@@ -656,8 +657,8 @@ BOOST_AUTO_TEST_CASE(write_ter3)
     reader.Import(ent);
     // we use conopology to mark amino acids as peptide-linking. this is 
     // require for proper TER output
-    conop::Conopology& conop_inst=conop::Conopology::Instance();
-    conop_inst.ConnectAll(conop_inst.GetBuilder(), ent);
+    conop::HeuristicProcessor heu_proc;
+    heu_proc.Process(ent);
     writer.Write(ent);
   }
   BOOST_CHECK(compare_files("testfiles/pdb/ter3.pdb", 
@@ -677,8 +678,8 @@ BOOST_AUTO_TEST_CASE(write_ter4)
     mol::ResidueHandle r2=edi.AppendResidue(ch, "GLY");
     mol::AtomHandle a2=edi.InsertAtom(r2, "N", geom::Vec3(35.0, -99.0, -10.5));
     mol::ChainHandle ch2=edi.InsertChain("B");
-    conop::Conopology& conop_inst=conop::Conopology::Instance();
-    conop_inst.ConnectAll(conop_inst.GetBuilder(), ent);
+    conop::HeuristicProcessor heu_proc;
+    heu_proc.Process(ent);
     writer.Write(ent);
   }
   BOOST_CHECK(compare_files("testfiles/pdb/ter_emptychain.pdb",
@@ -698,8 +699,8 @@ BOOST_AUTO_TEST_CASE(write_ter5)
     mol::ResidueHandle r2=edi.AppendResidue(ch, "GLY");
     mol::AtomHandle a2=edi.InsertAtom(r2, "N", geom::Vec3(35.0, -99.0, -10.5));
     mol::ChainHandle ch2=edi.InsertChain("B");
-    conop::Conopology& conop_inst=conop::Conopology::Instance();
-    conop_inst.ConnectAll(conop_inst.GetBuilder(), ent);
+    conop::HeuristicProcessor heu_proc;
+    heu_proc.Process(ent);
     writer.Write(ent.Select(""));
   }
   BOOST_CHECK(compare_files("testfiles/pdb/ter_view-emptychain.pdb",
@@ -717,8 +718,8 @@ BOOST_AUTO_TEST_CASE(write_ter6)
     
     mol::EntityHandle ent=mol::CreateEntity();
     reader.Import(ent);
-    conop::Conopology& conop_inst=conop::Conopology::Instance();
-    conop_inst.ConnectAll(conop_inst.GetBuilder(), ent);
+    conop::HeuristicProcessor heu_proc;
+    heu_proc.Process(ent);
     writer.Write(ent);
   }
   BOOST_CHECK(compare_files("testfiles/pdb/ter4.pdb", 
@@ -734,8 +735,8 @@ BOOST_AUTO_TEST_CASE(write_conect)
     PDBWriter writer(String("testfiles/pdb/conect-out.pdb"), IOProfile());
     mol::EntityHandle ent=mol::CreateEntity();
     reader.Import(ent);
-    conop::Conopology& conop_inst=conop::Conopology::Instance();
-    conop_inst.ConnectAll(conop_inst.GetBuilder(), ent);
+    conop::HeuristicProcessor heu_proc;
+    heu_proc.Process(ent);
     writer.Write(ent);
   }
   BOOST_CHECK(compare_files("testfiles/pdb/conect.pdb",
@@ -855,21 +856,18 @@ BOOST_AUTO_TEST_CASE(seqres_import)
   char * ost_root=getenv("OST_ROOT");
   if(!ost_root){
     std::cout << "WARNING: skipping SEQRES import unit test. " 
-              << "Rule-based builder is required" << std::endl;
+              << "Rule-based processor is required" << std::endl;
     return;
   }
   SetPrefixPath(ost_root);
   String lib_path=GetSharedDataPath()+"/compounds.chemlib";
   conop::CompoundLibPtr compound_lib=conop::CompoundLib::Load(lib_path);  
   if (!compound_lib) {
-    std::cout << "WARNING: skipping SEQRES import unit test. " 
-              << "Rule-based builder is required" << std::endl;
+    std::cout << "WARNING: skipping SEQRES import unit test. Compound lib is " 
+              << "required" << std::endl;
     return;    
   }
-  conop::RuleBasedBuilderPtr rbb(new conop::RuleBasedBuilder(compound_lib));
-  conop::Conopology::Instance().RegisterBuilder(rbb, "RBB");
-  conop::Conopology::Instance().SetDefaultBuilder("RBB");
-
+  conop::Conopology::Instance().SetDefaultLib(compound_lib);
   String fname("testfiles/pdb/seqres.pdb");
   IOProfile profile;
   PDBReader reader(fname, profile);
@@ -927,8 +925,7 @@ BOOST_AUTO_TEST_CASE(charmm_rname)
 {
   {
     PDBWriter writer(String("testfiles/pdb/charmm_rname-out.pdb"),
-                     IOProfile("CHARMM", true, false, false,
-                               false, false, false, true));
+                     IOProfile("CHARMM", false, false, false, false, false));
 
     mol::EntityHandle ent=mol::CreateEntity();
     mol::XCSEditor edi=ent.EditXCS();
@@ -947,8 +944,7 @@ BOOST_AUTO_TEST_CASE(charmm_longcname)
 {
   {
     PDBWriter writer(String("testfiles/pdb/charmm_longcname-out.pdb"),
-                     IOProfile("CHARMM", true, false, false,
-                               false, false, false, true));
+                     IOProfile("CHARMM", false, false, false, false, false));
 
     mol::EntityHandle ent=mol::CreateEntity();
     mol::XCSEditor edi=ent.EditXCS();
@@ -967,8 +963,7 @@ BOOST_AUTO_TEST_CASE(write_charmm_ter)
 {
   {
     PDBWriter writer(String("testfiles/pdb/charmm_ter-out.pdb"),
-                     IOProfile("CHARMM", true, false, false,
-                               false, false, false, true));
+                     IOProfile("CHARMM", false, false, false, false, false));
 
     mol::EntityHandle ent=mol::CreateEntity();
     mol::XCSEditor edi=ent.EditXCS();
@@ -977,8 +972,8 @@ BOOST_AUTO_TEST_CASE(write_charmm_ter)
     mol::AtomHandle a=edi.InsertAtom(r, "N", geom::Vec3(32.0, -128.0, -2.5));
     mol::ResidueHandle r2=edi.AppendResidue(ch, "GLY");
     mol::AtomHandle a2=edi.InsertAtom(r2, "N", geom::Vec3(35.0, -99.0, -10.5));
-    conop::Conopology& conop_inst=conop::Conopology::Instance();
-    conop_inst.ConnectAll(conop_inst.GetBuilder(), ent);
+    conop::HeuristicProcessor heu_proc;
+    heu_proc.Process(ent);
     writer.Write(ent);
   }
   BOOST_CHECK(compare_files("testfiles/pdb/charmm_ter.pdb",
diff --git a/modules/io/tests/test_io_pdb.py b/modules/io/tests/test_io_pdb.py
index 17933f35a93f8c14b513c5bc417e186b4283dbdf..9beb684d952f60bbbaf35e4b9b2369ddc896395c 100644
--- a/modules/io/tests/test_io_pdb.py
+++ b/modules/io/tests/test_io_pdb.py
@@ -11,14 +11,9 @@ class TestPDB(unittest.TestCase):
     ch = e.FindChain("A");
     self.assertEquals(ch.GetIntProp("mol_id"), 1)
 
-class TestPDB(unittest.TestCase):
-  def setUp(self):
-    pass
-
-  def test_compnd_parser(self):
-    profiles=io.IOProfiles()
-    profiles['FEAS_CHECK']=io.IOProfile(bond_feasibility_check=True)
-    profiles['NO_FEAS_CHECK']=io.IOProfile(bond_feasibility_check=False)
+  def test_no_bond_feasibility(self):
+    io.profiles['FEAS_CHECK']=io.IOProfile(processor=conop.HeuristicProcessor(check_bond_feasibility=True))
+    io.profiles['NO_FEAS_CHECK']=io.IOProfile(processor=conop.HeuristicProcessor(check_bond_feasibility=False))
         
     e1=io.LoadPDB('testfiles/pdb/simple_defective.pdb', restrict_chains="A",profile='FEAS_CHECK')
     e2=io.LoadPDB('testfiles/pdb/simple_defective.pdb', restrict_chains="A",profile='NO_FEAS_CHECK')
diff --git a/modules/io/tests/test_mmcif_reader.cc b/modules/io/tests/test_mmcif_reader.cc
index 67ef53d8754fecc59ad3a7f61e87fdb755c61c02..0b9e94b5868815cb514d48c6a710711b49cf63c9 100644
--- a/modules/io/tests/test_mmcif_reader.cc
+++ b/modules/io/tests/test_mmcif_reader.cc
@@ -27,7 +27,6 @@
 #include <ost/io/io_exception.hh>
 #include <ost/io/mol/mmcif_reader.hh>
 #include <ost/conop/conop.hh>
-#include <ost/conop/rule_based_builder.hh>
 
 
 
@@ -143,20 +142,18 @@ BOOST_AUTO_TEST_CASE(mmcif_convert_seqres)
   char * ost_root=getenv("OST_ROOT");
   if(!ost_root){
     std::cout << "WARNING: skipping SEQRES import unit test. " 
-              << "Rule-based builder is required" << std::endl;
+              << "Rule-based processor is required" << std::endl;
     return;
   }
   SetPrefixPath(ost_root);
   String lib_path=GetSharedDataPath()+"/compounds.chemlib";
   conop::CompoundLibPtr compound_lib=conop::CompoundLib::Load(lib_path);  
   if (!compound_lib) {
-    std::cout << "WARNING: skipping SEQRES import unit test. " 
-              << "Rule-based builder is required" << std::endl;
+    std::cout << "WARNING: skipping SEQRES import unit test. Compound " 
+              << "library is required" << std::endl;
     return;    
   }
-  conop::RuleBasedBuilderPtr rbb(new conop::RuleBasedBuilder(compound_lib));
-  conop::Conopology::Instance().RegisterBuilder(rbb, "RBB");
-  conop::Conopology::Instance().SetDefaultBuilder("RBB");
+  conop::Conopology::Instance().SetDefaultLib(compound_lib);
   mol::EntityHandle eh=mol::CreateEntity();
   
   TestMMCifReaderProtected tmmcif_p("testfiles/mmcif/atom_site.mmcif", eh);
@@ -165,7 +162,6 @@ BOOST_AUTO_TEST_CASE(mmcif_convert_seqres)
   BOOST_CHECK_EQUAL(tmmcif_p.ConvertSEQRES("A(MSE)Y", compound_lib), "AMY");
   BOOST_CHECK_THROW(tmmcif_p.ConvertSEQRES("A(MSEY", compound_lib), 
                     IOException);
-  conop::Conopology::Instance().SetDefaultBuilder("HEURISTIC");
 }
 
 BOOST_AUTO_TEST_CASE(mmcif_onbeginloop)
@@ -409,18 +405,18 @@ BOOST_AUTO_TEST_CASE(mmcif_entity_poly_tests)
   char * ost_root=getenv("OST_ROOT");
   if(!ost_root){
     std::cout << "WARNING: skipping SEQRES import unit test. " 
-              << "Rule-based builder is required" << std::endl;
+              << "Rule-based processor is required" << std::endl;
     return;
   }
   SetPrefixPath(ost_root);
   String lib_path=GetSharedDataPath()+"/compounds.chemlib";
   conop::CompoundLibPtr compound_lib=conop::CompoundLib::Load(lib_path);
   if (!compound_lib) {
-    std::cout << "WARNING: skipping SEQRES import unit test. "
-              << "Rule-based builder is required" << std::endl;
+    std::cout << "WARNING: skipping SEQRES import unit test. Compound  " 
+              << "lib is required" << std::endl;
     return;
   }
-  conop::Conopology::Instance().SetDefaultBuilder("RBB");
+  conop::Conopology::Instance().SetDefaultLib(compound_lib);
   BOOST_MESSAGE("  Running mmcif_entity_poly_tests...");
   mol::ChainHandle ch;
   IOProfile profile;
@@ -575,7 +571,6 @@ columns.push_back(StringRef("polydeoxyribonucleotide/polyribonucleotide hybrid",
   BOOST_MESSAGE("          done.");
 
   BOOST_MESSAGE("  done.");
-  conop::Conopology::Instance().SetDefaultBuilder("HEURISTIC");  
 }
 
 BOOST_AUTO_TEST_CASE(mmcif_citation_tests)
diff --git a/modules/io/tests/testfiles/mmcif/3T6C.cif.gz b/modules/io/tests/testfiles/mmcif/3T6C.cif.gz
index afda31f696dd24fcbecee1d652b7431b93d5dca4..34c71d22898472c0415c49ce327c0e2e4a673281 100644
Binary files a/modules/io/tests/testfiles/mmcif/3T6C.cif.gz and b/modules/io/tests/testfiles/mmcif/3T6C.cif.gz differ
diff --git a/modules/io/tests/testfiles/pdb/ter4.pdb b/modules/io/tests/testfiles/pdb/ter4.pdb
index a088dd23a776b33aacab610917ab1cbb5b99c53a..cb2209f24a71bd13022a324d48fbeaafd679b6d6 100644
--- a/modules/io/tests/testfiles/pdb/ter4.pdb
+++ b/modules/io/tests/testfiles/pdb/ter4.pdb
@@ -1,24 +1,24 @@
-ATOM      1  CB  ARG A   5      54.221  28.817  46.886  1.00 80.23           C  
-ATOM      2  CG  ARG A   5      54.014  28.661  48.384  1.00 79.76           C  
-ATOM      3  CD  ARG A   5      53.901  29.993  49.091  1.00 79.93           C  
-ATOM      4  NE  ARG A   5      55.153  30.743  49.053  1.00 79.60           N  
-ATOM      5  CZ  ARG A   5      55.375  31.851  49.753  1.00 79.44           C  
-ATOM      6  NH1 ARG A   5      54.425  32.333  50.545  1.00 79.21           N  
-ATOM      7  NH2 ARG A   5      56.543  32.475  49.661  1.00 79.57           N  
-ATOM      8  C   ARG A   5      54.203  27.642  44.665  1.00 80.18           C  
-ATOM      9  O   ARG A   5      54.697  26.854  43.860  1.00 80.24           O  
-ATOM     10  N   ARG A   5      55.792  26.946  46.486  1.00 80.39           N  
-ATOM     11  CA  ARG A   5      54.437  27.479  46.167  1.00 80.33           C  
+ATOM      1  N   ARG A   5      55.792  26.946  46.486  1.00 80.39           N  
+ATOM      2  CA  ARG A   5      54.437  27.479  46.167  1.00 80.33           C  
+ATOM      3  C   ARG A   5      54.203  27.642  44.665  1.00 80.18           C  
+ATOM      4  O   ARG A   5      54.697  26.854  43.860  1.00 80.24           O  
+ATOM      5  CB  ARG A   5      54.221  28.817  46.886  1.00 80.23           C  
+ATOM      6  CG  ARG A   5      54.014  28.661  48.384  1.00 79.76           C  
+ATOM      7  CD  ARG A   5      53.901  29.993  49.091  1.00 79.93           C  
+ATOM      8  NE  ARG A   5      55.153  30.743  49.053  1.00 79.60           N  
+ATOM      9  CZ  ARG A   5      55.375  31.851  49.753  1.00 79.44           C  
+ATOM     10  NH1 ARG A   5      54.425  32.333  50.545  1.00 79.21           N  
+ATOM     11  NH2 ARG A   5      56.543  32.475  49.661  1.00 79.57           N  
 ATOM     12  N   SER A   6      53.441  28.666  44.297  1.00 80.44           N  
 ATOM     13  CA  SER A   6      53.129  28.922  42.897  1.00 80.22           C  
-ATOM     14  CB  SER A   6      52.450  30.285  42.745  1.00 79.46           C  
-ATOM     15  OG  SER A   6      52.075  30.513  41.398  1.00 79.08           O  
-ATOM     16  C   SER A   6      54.371  28.872  42.015  1.00 80.20           C  
-ATOM     17  O   SER A   6      54.274  28.620  40.812  1.00 80.66           O  
+ATOM     14  C   SER A   6      54.371  28.872  42.015  1.00 80.20           C  
+ATOM     15  O   SER A   6      54.274  28.620  40.812  1.00 80.66           O  
+ATOM     16  CB  SER A   6      52.450  30.285  42.745  1.00 79.46           C  
+ATOM     17  OG  SER A   6      52.075  30.513  41.398  1.00 79.08           O  
 TER      18      SER A   6                                                      
 ATOM     19  C44 MC3 B 264      39.239  27.459  24.810  1.00 79.54           C  
 ATOM     20  C43 MC3 B 264      38.743  26.476  23.747  1.00 80.47           C  
 ATOM     21  C44 MC3 C 265      62.635  29.009  23.846  1.00 81.10           C  
 ATOM     22  C43 MC3 C 265      63.065  29.658  22.529  1.00 79.41           C  
 ATOM     23  C42 MC3 C 265      61.857  29.941  21.636  1.00 79.32           C  
-END   
\ No newline at end of file
+END   
diff --git a/modules/mol/alg/pymod/wrap_mol_alg.cc b/modules/mol/alg/pymod/wrap_mol_alg.cc
index 248923beb4fb9598b4c3c918b106932532cd681e..a65e95457400b5ee4806c49e4bf0dc666ba398ad 100644
--- a/modules/mol/alg/pymod/wrap_mol_alg.cc
+++ b/modules/mol/alg/pymod/wrap_mol_alg.cc
@@ -26,6 +26,7 @@
 #include <ost/mol/alg/superpose_frames.hh>
 #include <ost/mol/alg/filter_clashes.hh>
 #include <ost/mol/alg/consistency_checks.hh>
+#include <ost/mol/alg/pdbize.hh>
 #include <ost/export_helper/pair_to_tuple_conv.hh>
 #include <ost/export_helper/vec_to_list_conv.hh>
 
@@ -165,6 +166,14 @@ BOOST_PYTHON_MODULE(_ost_mol_alg)
   def("PrintGlobalRDMap",&mol::alg::PrintGlobalRDMap);
   def("PrintResidueRDMap",&mol::alg::PrintResidueRDMap);
  
+
+  class_<mol::alg::PDBize>("PDBize",
+                           init<int>(arg("min_polymer_size")=10))
+    .def("Add", &mol::alg::PDBize::Add, 
+         (arg("asu"), arg("transformations"), arg("seqres")))
+    .def("Finish", &mol::alg::PDBize::Finish, arg("shift_to_fit")=true)
+  ;
+
   def("ResidueNamesMatch",&mol::alg::ResidueNamesMatch,
       (arg("probe"), arg("reference"), arg("log_as_error")=false));
 
diff --git a/modules/mol/alg/src/CMakeLists.txt b/modules/mol/alg/src/CMakeLists.txt
index f5df9362a0b02cdda2c32ca1057732947be452fa..b6a7f28922257cd548acd6355a0d8387a4a9f8d6 100644
--- a/modules/mol/alg/src/CMakeLists.txt
+++ b/modules/mol/alg/src/CMakeLists.txt
@@ -12,6 +12,7 @@ set(OST_MOL_ALG_HEADERS
   trajectory_analysis.hh
   structure_analysis.hh
   consistency_checks.hh
+  pdbize.hh
 )
 
 set(OST_MOL_ALG_SOURCES
@@ -27,6 +28,7 @@ set(OST_MOL_ALG_SOURCES
   trajectory_analysis.cc
   structure_analysis.cc
   consistency_checks.cc
+  pdbize.cc
 )
 
 set(MOL_ALG_DEPS ost_mol ost_seq)
diff --git a/modules/mol/alg/src/lddt.cc b/modules/mol/alg/src/lddt.cc
index da1d8b311eb4103f664eef7bf24d0eaff2f2aa46..2509a0af9371ef15d6ec18d9d744bc916340893d 100644
--- a/modules/mol/alg/src/lddt.cc
+++ b/modules/mol/alg/src/lddt.cc
@@ -25,25 +25,33 @@
 #include <boost/filesystem/convenience.hpp>
 #include <ost/base.hh>
 #include <ost/boost_filesystem_helper.hh>
+#include <ost/mol/chain_view.hh>
 #include <ost/mol/alg/local_dist_diff_test.hh>
 #include <ost/mol/alg/filter_clashes.hh>
 #include <ost/io/mol/pdb_reader.hh>
 #include <ost/io/io_exception.hh>
 #include <ost/conop/conop.hh>
+#include <ost/conop/compound_lib.hh>
 #include <ost/string_ref.hh>
 #include <ost/conop/amino_acids.hh>
+#include <ost/conop/rule_based.hh>
 #include <ost/platform.hh>
 #include <ost/log.hh>
 #include <ost/mol/alg/consistency_checks.hh>
 
-#include <ost/conop/rule_based_builder.hh>
+#if defined(__APPLE__)
+#include <mach-o/dyld.h>
+#endif
 #include <ost/dyn_cast.hh>
 
 using namespace ost;
 using namespace ost::io;
+using namespace ost::conop;
 using namespace ost::mol;
 using namespace ost::mol::alg;
+
 namespace po=boost::program_options;
+namespace fs=boost::filesystem;
 
 // loads a file
 EntityHandle load(const String& file, const IOProfile& profile)
@@ -53,9 +61,10 @@ EntityHandle load(const String& file, const IOProfile& profile)
     if (reader.HasNext()) {
       EntityHandle ent=CreateEntity();
       reader.Import(ent);
-      conop::Conopology& conop_inst=conop::Conopology::Instance();
-      conop_inst.GetBuilder()->SetBondFeasibilityCheck(profile.bond_feasibility_check);
-      conop_inst.ConnectAll(conop_inst.GetBuilder(), ent);
+      if (profile.processor) {
+        profile.processor->Process(ent);
+      }
+
       if (ent.GetChainList().size()!=1) {
         std::cout << "WARNING: File " << file << " has more than one chain" << std::endl;
       }    
@@ -113,6 +122,51 @@ std::pair<int,int> compute_coverage (const EntityView& v,const GlobalRDMap& glob
   return std::make_pair(first,second);
 }
 
+CompoundLibPtr load_compound_lib(const String& custom_path)
+{
+  if (custom_path!="") {
+    if (fs::exists(custom_path)) {  
+      return CompoundLib::Load(custom_path);
+    } else {
+      std::cerr << "Could not find compounds.chemlib at the provided location, trying other options" << std::endl;
+    }
+  } 
+  if (fs::exists("compounds.chemlib")) {
+    return CompoundLib::Load("compounds.chemlib");
+  }
+  char result[ 1024 ]; 
+  CompoundLibPtr lib;
+  String exe_path; 
+  #if defined(__APPLE__)
+  uint32_t size=1023;
+  if (!_NSGetExecutablePath(result, &size)) {
+    exe_path=String(result); 
+  }
+  #else 
+  ssize_t count = readlink( "/proc/self/exe", result, 1024 );
+  exe_path = std::string( result, (count > 0) ? count : 0 );
+  #endif
+  if (exe_path.empty()) { 
+    std::cerr << "Could not determine the path of the molck executable. Will only "
+       "look for compounds.chemlib in the current working directory" << std::endl;
+  } else {
+    fs::path path_and_exe(exe_path);
+    fs::path path_only=path_and_exe.branch_path();
+    fs::path share_path = path_only.branch_path();
+    share_path = share_path / "share" / "openstructure" / "compounds.chemlib";
+
+    String share_path_string=BFPathToString(share_path);
+      
+    if (fs::exists(share_path_string)) {
+      return CompoundLib::Load(share_path_string);
+    }  
+  }
+  if (!lib) {
+    std::cerr << "Could not load compounds.chemlib" << std::endl;
+    exit(-1);
+  }
+  return CompoundLibPtr();
+}
 bool is_resnum_in_globalrdmap(const ResNum& resnum, const GlobalRDMap& glob_dist_list)
 {
   for (GlobalRDMap::const_iterator i=glob_dist_list.begin(), e=glob_dist_list.end(); i!=e; ++i) {
@@ -135,10 +189,9 @@ int main (int argc, char **argv)
 
   // creates the required loading profile
   IOProfile profile;
-  profile.bond_feasibility_check=false;
-
   // parses options
   String sel;
+  String custom_path;
   bool structural_checks=false;
   bool consistency_checks=true;
   po::options_description desc("Options");
@@ -152,6 +205,7 @@ int main (int argc, char **argv)
     ("parameter-file,p", po::value<String>(), "stereo-chemical parameter file")
     ("verbosity,v", po::value<int>(), "verbosity level")
     ("bond_tolerance,b", po::value<Real>(), "tolerance in stddev for bonds")
+    ("complib", po::value<String>(&custom_path)->default_value(""),"location of the compound library file")       
     ("angle_tolerance,a", po::value<Real>(), "tolerance in stddev for angles")
     ("inclusion_radius,r", po::value<Real>(), "distance inclusion radius")
     ("sequence_separation,i", po::value<int>(), "sequence separation")
@@ -170,6 +224,12 @@ int main (int argc, char **argv)
     usage();
     exit(-1);
   }
+  conop::CompoundLibPtr lib = load_compound_lib(custom_path);
+  if (!lib) {
+    exit(0);
+  }
+  profile.processor = conop::RuleBasedProcessorPtr(new conop::RuleBasedProcessor(lib));
+  profile.processor->SetCheckBondFeasibility(false);
   po::notify(vm);
   if (vm.count("version")) {
     std::cout << "Version: " << version << std::endl;
diff --git a/modules/mol/alg/src/pdbize.cc b/modules/mol/alg/src/pdbize.cc
new file mode 100644
index 0000000000000000000000000000000000000000..c06dfa23057998368e64eb04545810d06c8a7188
--- /dev/null
+++ b/modules/mol/alg/src/pdbize.cc
@@ -0,0 +1,158 @@
+//------------------------------------------------------------------------------
+// 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 "pdbize.hh"
+#include <ost/mol/residue_handle.hh>
+#include <ost/mol/residue_view.hh>
+#include <ost/mol/atom_handle.hh>
+#include <ost/mol/atom_view.hh>
+#include <ost/mol/transfer_connectivity.hh>
+#include <ost/mol/chain_handle.hh>
+#include <ost/mol/chain_view.hh>
+#include <ost/mol/xcs_editor.hh>
+#include <ost/seq/sequence_handle.hh>
+
+namespace ost { namespace mol { namespace alg {
+
+DLLEXPORT const char* POLYPEPTIDE_CHAIN_NAMES="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
+DLLEXPORT const char* LIGAND_CHAIN_NAME="_";
+DLLEXPORT const char* WATER_CHAIN_NAME="-";
+
+
+namespace {
+
+bool copy_atoms(ResidueView src_res, ResidueHandle dst_res, XCSEditor& edi, 
+                const geom::Mat4 transform) {
+  bool needs_adjustment_ = false;
+  for (AtomViewList::const_iterator 
+       i = src_res.GetAtomList().begin(), 
+       e = src_res.GetAtomList().end(); i != e; ++i) {
+
+    AtomHandle new_atom = edi.InsertAtom(dst_res, i->GetName(), 
+                                         geom::Vec3(transform*i->GetPos()),
+                                         i->GetName(), i->GetOccupancy(), 
+                                         i->GetBFactor(), i->IsHetAtom());
+    geom::Vec3 pos = new_atom.GetPos();
+    for (int j = 0; j<3; ++j) {
+      needs_adjustment_|= pos[j]<=-1000 || pos[j]>=10000;
+    }
+  }
+  return needs_adjustment_;
+}
+
+}
+
+void PDBize::Add(EntityView asu, const geom::Mat4List& transforms, 
+                 seq::SequenceList seqres)
+{
+  XCSEditor edi = ent_.EditXCS(BUFFERED_EDIT);
+
+  ChainHandle ligand_chain;
+  ChainHandle water_chain;
+  int last_rnum = 0;
+  for (geom::Mat4List::const_iterator i = transforms.begin(), 
+       e = transforms.end(); i != e; ++i) {
+    for (ChainViewList::const_iterator j = asu.GetChainList().begin(),
+         e2 =asu.GetChainList().end(); j != e2; ++j) {
+      ChainView chain = *j; 
+      int chain_length = chain.GetResidueCount();
+      if (chain_length < min_polymer_size_ && seqres.IsValid()) {
+        seq::SequenceHandle s = seqres.FindSequence(chain.GetName());
+        if (s.IsValid())
+          chain_length = s.GetLength();
+      }
+      if (chain.IsPolymer() && chain_length >= min_polymer_size_) {
+        if (*curr_chain_name_ == 0) {
+          throw std::runtime_error("running out of chain names");
+        }
+        ChainHandle new_chain = edi.InsertChain(String(1, curr_chain_name_[0]));
+        curr_chain_name_++;
+        edi.SetChainDescription(new_chain, chain.GetDescription());
+        edi.SetChainType(new_chain, chain.GetType());
+        new_chain.SetStringProp("original_name", chain.GetName());
+        if (chain.HasProp("pdb_auth_chain_name"))
+          new_chain.SetStringProp("pdb_auth_chain_name",
+                                  chain.GetStringProp("pdb_auth_chain_name"));
+        
+        for (ResidueViewList::const_iterator k = chain.GetResidueList().begin(),
+             e3 = chain.GetResidueList().end(); k != e3; ++k) {
+          ResidueHandle new_res = edi.AppendResidue(new_chain, k->GetName(),
+                                                    k->GetNumber());
+          dst_to_src_map_[new_res] = k->GetHandle();
+          needs_adjustment_ |= copy_atoms(*k, new_res, edi, *i);
+        }
+        continue;
+      }
+      if (chain.GetType() == CHAINTYPE_WATER) {
+        if (!water_chain) {
+          water_chain = edi.InsertChain(WATER_CHAIN_NAME);
+          edi.SetChainDescription(water_chain, chain.GetDescription());
+          edi.SetChainType(water_chain, chain.GetType());
+        }
+        for (ResidueViewList::const_iterator k = chain.GetResidueList().begin(),
+             e3 = chain.GetResidueList().end(); k != e3; ++k) {
+          ResidueHandle new_res = edi.AppendResidue(water_chain, k->GetName());
+          new_res.SetStringProp("type", StringFromChainType(chain.GetType()));
+          new_res.SetStringProp("description", chain.GetDescription());
+          dst_to_src_map_[new_res] = k->GetHandle();
+          needs_adjustment_ |= copy_atoms(*k, new_res, edi, *i);
+        }
+        continue;
+      }
+      // deal with ligands...
+      if (!ligand_chain) {
+        ligand_chain = edi.InsertChain(LIGAND_CHAIN_NAME);
+        last_rnum = 0;
+      }
+      char ins_code = chain.GetResidueCount()>1 ? 'A' : '\0';
+     
+      for (ResidueViewList::const_iterator k = chain.GetResidueList().begin(),
+           e3 = chain.GetResidueList().end(); k != e3; ++k) {
+        ResidueHandle new_res = edi.AppendResidue(ligand_chain, k->GetName(),
+                                                  ResNum(last_rnum+1, ins_code));
+        new_res.SetStringProp("type", StringFromChainType(chain.GetType()));
+        new_res.SetStringProp("description", chain.GetDescription());
+        new_res.SetStringProp("original_name", chain.GetName());
+        if (chain.HasProp("pdb_auth_chain_name"))
+          new_res.SetStringProp("pdb_auth_chain_name", 
+                                chain.GetStringProp("pdb_auth_chain_name"));
+        dst_to_src_map_[new_res] = k->GetHandle();
+        ins_code += 1;
+        needs_adjustment_ |= copy_atoms(*k, new_res, edi, *i);
+      }
+      last_rnum+=1;
+    }
+  }
+}
+
+EntityHandle PDBize::Finish(bool shift_to_fit) {
+
+  if (needs_adjustment_ && shift_to_fit) {
+    geom::Vec3 min_coord = ent_.GetBounds().GetMin();
+    geom::Mat4 tf(1, 0, 0, -999 - min_coord[0],
+                  0, 1, 0, -999 - min_coord[1],
+                  0, 0, 1, -999 - min_coord[2],
+                  0, 0, 0, 1);
+    XCSEditor edi = ent_.EditXCS();
+    edi.ApplyTransform(tf);
+  }
+  TransferConnectivity(ent_, dst_to_src_map_);
+  return ent_;
+}
+
+}}}
diff --git a/modules/mol/alg/src/pdbize.hh b/modules/mol/alg/src/pdbize.hh
new file mode 100644
index 0000000000000000000000000000000000000000..92c5cbfc4408899df4c830849a94ba2f618b3afb
--- /dev/null
+++ b/modules/mol/alg/src/pdbize.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_MOL_ALG_PDBIZE_HH
+#define OST_MOL_ALG_PDBIZE_HH
+
+#include <ost/mol/entity_view.hh>
+#include <ost/mol/entity_handle.hh>
+#include <ost/mol/residue_handle.hh>
+#include <ost/seq/sequence_list.hh>
+#include "module_config.hh"
+
+namespace ost { namespace mol { namespace alg {
+
+
+extern const char* POLYPEPTIDE_CHAIN_NAMES;
+extern const char* LIGAND_CHAIN_NAME;
+extern const char* WATER_CHAIN_NAME;
+
+class DLLEXPORT_OST_MOL_ALG PDBize {
+public:
+  explicit PDBize(int min_polymer_size=10):
+    min_polymer_size_(min_polymer_size), ent_(mol::CreateEntity()),
+    curr_chain_name_(POLYPEPTIDE_CHAIN_NAMES), needs_adjustment_(false)
+  {}
+
+  void Add(mol::EntityView asu, const geom::Mat4List& transforms,
+           seq::SequenceList seqres);
+
+  EntityHandle Finish(bool shift_to_fit=true);
+private:
+  int                                   min_polymer_size_;
+  EntityHandle                          ent_;
+  const char*                           curr_chain_name_;
+  bool                                  needs_adjustment_;
+  std::map<ResidueHandle,ResidueHandle> dst_to_src_map_;
+};
+
+}}}
+#endif
+
diff --git a/modules/mol/base/pymod/export_bond.cc b/modules/mol/base/pymod/export_bond.cc
index fcad815704b856e8a86363e66c30f5cf18dfdb9b..c95268df47468b0ad1c717032091c7b35600d989 100644
--- a/modules/mol/base/pymod/export_bond.cc
+++ b/modules/mol/base/pymod/export_bond.cc
@@ -21,7 +21,6 @@
 
 using namespace boost::python;
 
-
 #include <ost/mol/mol.hh>
 
 using namespace ost;
@@ -62,4 +61,5 @@ void export_Bond()
     .def(vector_indexing_suite<BondHandleList>())
     .def(geom::VectorAdditions<BondHandleList>());  
   def("BondExists", &BondExists);
+
 }
diff --git a/modules/mol/base/pymod/export_editors.cc b/modules/mol/base/pymod/export_editors.cc
index 7ac51a75e0fe8459604c7fa90b23eafaeb26c45f..6a659d286e095a8436dc338b9f9492f70e857f45 100644
--- a/modules/mol/base/pymod/export_editors.cc
+++ b/modules/mol/base/pymod/export_editors.cc
@@ -83,6 +83,8 @@ void (ICSEditor::*rotate_torsion_b)(const AtomHandle&, const AtomHandle&,
                                     const AtomHandle&, const AtomHandle&,
                                     Real, bool)=&ICSEditor::RotateTorsionAngle;
 
+void (EditorBase::*renumber_chain_a)(ChainHandle,const ResNumList&)=&EditorBase::RenumberChain;
+void (EditorBase::*renumber_chain_b)(const ChainHandle&,int, bool)=&EditorBase::RenumberChain;
 #if OST_NUMPY_SUPPORT_ENABLED
 template<typename T, bool O>
 void set_pos2_nc_t(XCSEditor& e, const AtomHandleList& alist, PyArrayObject* na)
@@ -261,7 +263,8 @@ void export_Editors()
     .def("ReorderResidues",&EditorBase::ReorderResidues)
     .def("ReorderAllResidues",&EditorBase::ReorderAllResidues)
     .def("RenumberAllResidues",&EditorBase::RenumberAllResidues)
-    .def("RenumberChain",&EditorBase::RenumberChain)
+    .def("RenumberChain",renumber_chain_a)
+    .def("RenumberChain",renumber_chain_b)
   ;
   
   void (XCSEditor::*apply_transform1)(const geom::Mat4&) = &XCSEditor::ApplyTransform;
diff --git a/modules/mol/base/pymod/export_residue.cc b/modules/mol/base/pymod/export_residue.cc
index 284c2f0bc294825e5751a3f441e377d1d1666517..8f0e169944f856f6f47a0e6e37cf2068ddad9177 100644
--- a/modules/mol/base/pymod/export_residue.cc
+++ b/modules/mol/base/pymod/export_residue.cc
@@ -122,6 +122,10 @@ void export_Residue()
     .def(self+int())
     .def(self-int())    
   ;
+  class_<ResNumList>("ResNumList", init<>())
+    .def(vector_indexing_suite<ResNumList>())
+    .def(geom::VectorAdditions<ResNumList>())
+  ;
   implicitly_convertible<int, ResNum>();
   
   scope().attr("PEPTIDE_LINKING")=char(ChemClass::PEPTIDE_LINKING);
diff --git a/modules/mol/base/src/CMakeLists.txt b/modules/mol/base/src/CMakeLists.txt
index 86d5ccca6dc92350f948990f833e84f18f5d9da9..9434837dd7901790ba4103a6665c837f63934db8 100644
--- a/modules/mol/base/src/CMakeLists.txt
+++ b/modules/mol/base/src/CMakeLists.txt
@@ -29,6 +29,7 @@ residue_handle.cc
 residue_view.cc
 surface_builder.cc
 surface_handle.cc
+transfer_connectivity.cc
 torsion_handle.cc
 query_view_wrapper.cc
 view_op.cc
@@ -84,6 +85,7 @@ builder.hh
 surface_handle.hh
 surface_prop.hh
 torsion_handle.hh
+transfer_connectivity.hh
 query_view_wrapper.hh
 view_op.hh
 view_type_fw.hh
diff --git a/modules/mol/base/src/builder.hh b/modules/mol/base/src/builder.hh
index 0a652a8b010ac97182a50e79591c00f6c3c6b81d..d46ed485bbe0c8ebf3d2ccf54e62347034b66915 100644
--- a/modules/mol/base/src/builder.hh
+++ b/modules/mol/base/src/builder.hh
@@ -26,6 +26,7 @@
 #include "residue_handle.hh"
 #include "chain_handle.hh"
 #include "entity_handle.hh"
+#include "bond_handle.hh"
 #include "xcs_editor.hh"
 
 
@@ -62,6 +63,27 @@ public:
      edi_.InsertAtom(res_, name, pos);
      return *this;
    }
+   Builder& Gly(bool connect=true) {
+     this->Residue("GLY");
+     this->Atom("N");
+     this->Atom("CA");
+     this->Atom("C");
+     this->Atom("O");
+     if (connect) {
+       edi_.Connect(res_.FindAtom("N"), res_.FindAtom("CA"));
+       edi_.Connect(res_.FindAtom("CA"), res_.FindAtom("C"));
+       edi_.Connect(res_.FindAtom("C"), res_.FindAtom("O"));
+     }
+     return *this;
+   }
+   Builder& ConnectToPrev() {
+     AtomHandle ah = res_.FindAtom("N");
+     AtomHandle pa = res_.GetPrev().FindAtom("C");
+     if (pa) {
+       edi_.Connect(pa, ah);
+     }
+     return *this;
+   }
 private:
    EntityHandle  ent_;
    ChainHandle   chain_;
diff --git a/modules/mol/base/src/editor_base.cc b/modules/mol/base/src/editor_base.cc
index 9e8729d9374391321f511f8e17e1bef79b81d327..b6cc4ab455036672b612e2d37f4ccfa93414b9c5 100644
--- a/modules/mol/base/src/editor_base.cc
+++ b/modules/mol/base/src/editor_base.cc
@@ -180,6 +180,14 @@ void EditorBase::DeleteChain(const ChainHandle& chain)
   ent_.Impl()->DeleteChain(chain.Impl());
 }
 
+void EditorBase::DeleteAtoms(const AtomHandleList& atoms)
+{
+  for (AtomHandleList::const_iterator i = atoms.begin(), e = atoms.end();
+       i != e; ++i) {
+    i->GetResidue().Impl()->DeleteAtom(i->Impl());
+  }
+}
+
 void EditorBase::DeleteAtom(const AtomHandle& atom_handle) 
 {
   CheckHandleValidity(atom_handle);
@@ -246,6 +254,12 @@ BondHandle EditorBase::Connect(const AtomHandle& first,
   return this->Connect(first,second,0.0, 0.0, 0.0, 1);
 }
 
+void EditorBase::RenumberChain(ChainHandle chain, const ResNumList& new_numbers)
+{
+  CheckHandleValidity(chain);
+  chain.Impl()->RenumberAllResidues(new_numbers);
+}
+
 BondHandle EditorBase::Connect(const AtomHandle& first,
                                  const AtomHandle& second,
                                  Real len, Real theta, Real phi,
diff --git a/modules/mol/base/src/editor_base.hh b/modules/mol/base/src/editor_base.hh
index 05d82ddb0682e12737b629947f010947cb009842..255390c29dc3f3e7e286ad5ea966748b75ab72b2 100644
--- a/modules/mol/base/src/editor_base.hh
+++ b/modules/mol/base/src/editor_base.hh
@@ -216,7 +216,7 @@ public:
   void RenameResidue(ResidueHandle res, const String& new_name);
   
   void SetResidueNumber(ResidueHandle res, const ResNum& num);
-  
+   
   void RenameChain(ChainHandle chain, const String& new_name);
 
   /// \brief Assign type of chain according to ChainType.
@@ -244,6 +244,10 @@ public:
   ///         is the atom to remove. If no such atom exists, this method will
   ///         have no effect
   void DeleteAtom(const AtomHandle& atom);
+  /// \ brief Delete a set of atoms
+  ///
+  /// All associated torsions and bonds will be removed as well
+  void DeleteAtoms(const AtomHandleList& atoms);
   
   /// \brief Add named torsion to entity
   TorsionHandle AddTorsion(const String& name, const AtomHandle& a1,
@@ -279,6 +283,7 @@ public:
   void RenumberAllResidues(int start, bool keep_spacing);
 
 
+  void RenumberChain(ChainHandle chain, const ResNumList& new_numbers);
 
   /// \brief renumber residues of one chain
   ///
diff --git a/modules/mol/base/src/impl/chain_impl.cc b/modules/mol/base/src/impl/chain_impl.cc
index 8b3cbe271eef0e860d78ea5039ac7f00a35e191e..2ec5b8694668d91c207679a99de9c0b2a80157f9 100644
--- a/modules/mol/base/src/impl/chain_impl.cc
+++ b/modules/mol/base/src/impl/chain_impl.cc
@@ -516,6 +516,17 @@ void ChainImpl::RenumberAllResidues(int start, bool keep_spacing)
   UpdateShifts();
 }
 
+void ChainImpl::RenumberAllResidues(const ResNumList& new_numbers)
+{
+  if (new_numbers.size() != residue_list_.size()) {
+    throw Error("number of residues and residue numbers must match");
+  }
+  for (size_t i = 0; i<new_numbers.size(); ++i) {
+      residue_list_[i]->SetNumber(new_numbers[i]);
+  }
+  this->UpdateShifts();
+}
+
 void ChainImpl::SetInSequence(const int index)
 {
   ResNum num=residue_list_[index]->GetNumber();
diff --git a/modules/mol/base/src/impl/chain_impl.hh b/modules/mol/base/src/impl/chain_impl.hh
index a2c607ec4e2df3cca3783a8a14532e795536593e..82334c6fbb054eb200db5dacaec0587c9d5511d1 100644
--- a/modules/mol/base/src/impl/chain_impl.hh
+++ b/modules/mol/base/src/impl/chain_impl.hh
@@ -175,6 +175,8 @@ public:
 
   void RenumberAllResidues(int start, bool keep_spacing);
   
+  void RenumberAllResidues(const ResNumList& new_numbers);
+
   int GetIndex(const ResidueImplPtr& res) const;
   void AssignSecondaryStructure(SecStructure ss,
                                 const ResNum& start,
diff --git a/modules/mol/base/src/impl/entity_impl.cc b/modules/mol/base/src/impl/entity_impl.cc
index 852b9bebb1653110cde6610f94ef3a620f09c8b6..865ef7172ebf5452e9acdc737ea170f068ad01f3 100644
--- a/modules/mol/base/src/impl/entity_impl.cc
+++ b/modules/mol/base/src/impl/entity_impl.cc
@@ -35,6 +35,7 @@
 #include <ost/geom/geom.hh>
 
 #include <ost/log.hh>
+#include <ost/profile.hh>
 #include "atom_impl.hh"
 #include "entity_impl.hh"
 #include <ost/mol/entity_visitor.hh>
@@ -114,6 +115,7 @@ int EntityImpl::GetResidueCount() const
 
 EntityImplPtr EntityImpl::Copy()
 {
+  Profile prof("EntityImpl::Copy");
 #if MAKE_SHARED_AVAILABLE
   EntityImplPtr ent_p=boost::make_shared<EntityImpl>();  
 #else
diff --git a/modules/mol/base/src/residue_prop.hh b/modules/mol/base/src/residue_prop.hh
index 4a411cca6e27250fdd23d4b538ffea6064b8d106..d4d79fd688ed96cf6f197f13e4116270e84ff212 100644
--- a/modules/mol/base/src/residue_prop.hh
+++ b/modules/mol/base/src/residue_prop.hh
@@ -19,6 +19,7 @@
 #ifndef OST_RESIDUE_PROP_HH
 #define OST_RESIDUE_PROP_HH
 
+#include <vector>
 #include <boost/operators.hpp>
 
 #include <ost/mol/module_config.hh>
@@ -122,6 +123,7 @@ private:
 };
 
 typedef String ResidueKey;
+typedef std::vector<ResNum> ResNumList;
 
 inline std::ostream& operator<<(std::ostream& os, const ResNum& n)
 {
diff --git a/modules/mol/base/src/transfer_connectivity.cc b/modules/mol/base/src/transfer_connectivity.cc
new file mode 100644
index 0000000000000000000000000000000000000000..38b1d6f151043611eac09762f9fcf4ec2f00272c
--- /dev/null
+++ b/modules/mol/base/src/transfer_connectivity.cc
@@ -0,0 +1,119 @@
+//------------------------------------------------------------------------------
+// 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 "transfer_connectivity.hh"
+#include "entity_visitor.hh"
+#include "residue_handle.hh"
+#include "atom_handle.hh"
+#include "bond_handle.hh"
+#include "xcs_editor.hh"
+
+
+namespace ost { namespace mol {
+
+namespace {
+
+class ConnectivityTransferVisitor : public EntityVisitor {
+public:
+  ConnectivityTransferVisitor(EntityHandle dst,
+                              const std::map<ResidueHandle, ResidueHandle>* to_from):
+    edi_(dst.EditXCS(mol::BUFFERED_EDIT)), to_from_(to_from) {
+  }
+
+  bool VisitResidue(const ResidueHandle& dest_res) {
+    std::map<ResidueHandle, ResidueHandle>::const_iterator i = to_from_->find(dest_res);
+    if (i == to_from_->end()) {
+      return false;
+    }
+    const std::pair<ResidueHandle, ResidueHandle>& ft = *i;
+    if (!ft.second.IsValid()) {
+      return false;
+    }
+
+    // define a map from atom name to atom handle for the dest residue.
+    std::map<String, AtomHandle> name_to_handle;
+    AtomHandleList dest_atoms = dest_res.GetAtomList();
+    for (AtomHandleList::iterator j = dest_atoms.begin(), e = dest_atoms.end(); j !=e ; ++j) {
+      name_to_handle[j->GetName()] = *j;
+    }
+
+    AtomHandleList src_atoms =  ft.second.GetAtomList();
+    for (AtomHandleList::iterator j = src_atoms.begin(), e = src_atoms.end(); j !=e ; ++j) {
+      BondHandleList bonds = j->GetBondList();
+      for (BondHandleList::iterator k = bonds.begin(), e2 = bonds.end(); k !=e2; ++k) {
+        AtomHandle first = k->GetFirst();
+        AtomHandle second = k->GetSecond();
+        AtomHandle dst_frst = this->GetDestAtomForSrcAtom(first, ft.second, ft.first,
+                                                          name_to_handle);
+        AtomHandle dst_scnd = this->GetDestAtomForSrcAtom(second, ft.second, ft.first,
+                                                          name_to_handle);
+        // add bond...
+        if (!dst_frst || !dst_scnd) {
+          continue;
+        }
+        edi_.Connect(dst_frst, dst_scnd);
+      }
+    }
+    return false;
+  }
+
+  AtomHandle GetDestAtomForSrcAtom(AtomHandle src_atom, ResidueHandle src_res,
+                                   ResidueHandle dst_res,
+                                   const std::map<String, AtomHandle>& name_to_atom) {
+    ResidueHandle r = src_atom.GetResidue();
+    if (r == src_res) {
+      // fast track...
+      std::map<String, AtomHandle>::const_iterator i = name_to_atom.find(src_atom.GetName());
+      return i == name_to_atom.end() ? AtomHandle() : i->second;
+    }
+    // educated guess: we are trying to connect to the previous/next residue
+    std::map<ResidueHandle, ResidueHandle>::const_iterator j;
+    j = to_from_->find(dst_res.GetPrev());
+    if (j != to_from_->end()) {
+      if (j->second == r) {
+        return j->first.FindAtom(src_atom.GetName());
+      }
+    }
+    j = to_from_->find(dst_res.GetNext());
+    if (j != to_from_->end()) {
+      if (j->second == r) {
+        return j->first.FindAtom(src_atom.GetName());
+      }
+    }
+    // still nothing. scan linearly through all residues.
+    for ( j = to_from_->begin(); j != to_from_->end(); ++j) {
+      if (j->second == r) {
+        return j->first.FindAtom(src_atom.GetName());
+      }
+    }
+    return AtomHandle();
+  }
+private:
+  XCSEditor              edi_;
+  const std::map<ResidueHandle, ResidueHandle>* to_from_;
+};
+
+}
+void TransferConnectivity(EntityHandle dest,
+                          const std::map<ResidueHandle, ResidueHandle>& to_from) {
+  ConnectivityTransferVisitor visitor(dest, &to_from);
+  dest.Apply(visitor);
+}
+
+}}
diff --git a/modules/conop/src/builder_fw.hh b/modules/mol/base/src/transfer_connectivity.hh
similarity index 70%
rename from modules/conop/src/builder_fw.hh
rename to modules/mol/base/src/transfer_connectivity.hh
index c61de7becda4a9e3476a620a71da563d0c4c2f5c..e46691cd25d920ff1268f52d730ef70f2662d464 100644
--- a/modules/conop/src/builder_fw.hh
+++ b/modules/mol/base/src/transfer_connectivity.hh
@@ -16,16 +16,22 @@
 // along with this library; if not, write to the Free Software Foundation, Inc.,
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 //------------------------------------------------------------------------------
-#ifndef OST_CONOP_BUILDER_FW_HH
-#define OST_CONOP_BUILDER_FW_HH
+#ifndef OST_MOL_TRANSFER_CONNECTIVITY_HH
+#define OST_MOL_TRANSFER_CONNECTIVITY_HH
 
-#include <boost/shared_ptr.hpp>
 
-namespace ost { namespace conop {
+#include "module_config.hh"
+#include "entity_handle.hh"
+#include "residue_handle.hh"
 
-class Builder;
-typedef boost::shared_ptr<Builder> BuilderP;
+namespace ost { namespace mol {
+
+void DLLEXPORT_OST_MOL
+TransferConnectivity(EntityHandle dest, const std::map<ResidueHandle, ResidueHandle>& to_from);
 
-}}
 
+bool operator<(const ResidueHandle& lhs, const ResidueHandle& rhs) {
+  return lhs.GetHashCode()<rhs.GetHashCode();
+}
+}}
 #endif
diff --git a/modules/mol/base/tests/CMakeLists.txt b/modules/mol/base/tests/CMakeLists.txt
index de287b52cde367342ae188049c79d8c176dc4e12..1aa275c1adca3bbc7afed1f34b4b3518fcfa6593 100644
--- a/modules/mol/base/tests/CMakeLists.txt
+++ b/modules/mol/base/tests/CMakeLists.txt
@@ -11,6 +11,7 @@ set(OST_MOL_BASE_UNIT_TESTS
   test_surface.cc
   test_residue.cc
   test_view.cc
+  test_transfer_connectivity.cc
   test_view_op.cc
   tests.cc
 )
diff --git a/modules/mol/base/tests/test_transfer_connectivity.cc b/modules/mol/base/tests/test_transfer_connectivity.cc
new file mode 100644
index 0000000000000000000000000000000000000000..2f5dff1439bf64099a9e109d6336ac6dc54b8737
--- /dev/null
+++ b/modules/mol/base/tests/test_transfer_connectivity.cc
@@ -0,0 +1,78 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2011 by the OpenStructure authors
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License as published by the Free
+// Software Foundation; either version 3.0 of the License, or (at your option)
+// any later version.
+// This library is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+/*
+ *  Authors: Marco Biasini
+ */
+
+#include <ost/mol/builder.hh>
+#include <ost/mol/transfer_connectivity.hh>
+
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+#include <boost/test/auto_unit_test.hpp>
+
+using namespace ost;
+using namespace ost::mol;
+
+BOOST_AUTO_TEST_SUITE( mol_transfer_conn );
+
+BOOST_AUTO_TEST_CASE(test_transfer_conn)
+{
+  EntityHandle ent = Builder()
+                       .Chain("A")
+                         .Gly()
+                         .Gly()
+                         .ConnectToPrev()
+                         .Gly()
+                         .ConnectToPrev()
+                   ;
+
+  ent.EditXCS().Connect(ent.FindAtom("A", 1, "O"), ent.FindAtom("A", 3, "O"));
+
+  EntityHandle ent2 = Builder()
+                       .Chain("A")
+                         .Gly(false)
+                         .Gly(false)
+                         .Gly(false)
+                   ;
+  std::map<ResidueHandle, ResidueHandle> to_from;
+  ResidueHandleList r1 = ent.GetResidueList();
+  ResidueHandleList r2 = ent2.GetResidueList();
+  for (size_t i = 0;i<r1.size(); ++i) {
+    to_from[r2[i]] = r1[i];
+  }
+  TransferConnectivity(ent2, to_from);
+  BOOST_CHECK(BondExists(ent2.FindAtom("A", 1, "N"), ent2.FindAtom("A", 1, "CA")));
+  BOOST_CHECK(BondExists(ent2.FindAtom("A", 1, "CA"), ent2.FindAtom("A", 1, "C")));
+  BOOST_CHECK(BondExists(ent2.FindAtom("A", 1, "C"), ent2.FindAtom("A", 1, "O")));
+  BOOST_CHECK(BondExists(ent2.FindAtom("A", 1, "C"), ent2.FindAtom("A", 2, "N")));
+  BOOST_CHECK(BondExists(ent2.FindAtom("A", 2, "N"), ent2.FindAtom("A", 2, "CA")));
+  BOOST_CHECK(BondExists(ent2.FindAtom("A", 2, "CA"), ent2.FindAtom("A", 2, "C")));
+  BOOST_CHECK(BondExists(ent2.FindAtom("A", 2, "C"), ent2.FindAtom("A", 2, "O")));
+  BOOST_CHECK(BondExists(ent2.FindAtom("A", 2, "C"), ent2.FindAtom("A", 3, "N")));
+  BOOST_CHECK(BondExists(ent2.FindAtom("A", 3, "N"), ent2.FindAtom("A", 3, "CA")));
+  BOOST_CHECK(BondExists(ent2.FindAtom("A", 3, "CA"), ent2.FindAtom("A", 3, "C")));
+  BOOST_CHECK(BondExists(ent2.FindAtom("A", 3, "C"), ent2.FindAtom("A", 3, "O")));
+  BOOST_CHECK(BondExists(ent2.FindAtom("A", 1, "O"), ent2.FindAtom("A", 3, "O")));
+  BOOST_CHECK_EQUAL(12, ent2.GetBondCount());
+}
+
+
+
+BOOST_AUTO_TEST_SUITE_END();
diff --git a/modules/seq/alg/pymod/renumber.py b/modules/seq/alg/pymod/renumber.py
index f715f0bd6f1ef9dbbc60b3afc316502a9d462398..22873111e877c66da19ee2af80f49ce169ccd4ef 100644
--- a/modules/seq/alg/pymod/renumber.py
+++ b/modules/seq/alg/pymod/renumber.py
@@ -1,6 +1,43 @@
 from ost import io, seq, mol, conop
 from ost import *
 
+
+def _RenumberSeq(seq_handle):
+  if not seq_handle.HasAttachedView():
+    raise RuntimeError("Sequence Handle has no attached view")
+  ev = seq_handle.attached_view.CreateEmptyView()
+  new_numbers = mol.ResNumList()
+  for pos in range(len(seq_handle)):
+    if seq_handle[pos]!='-':
+      r=seq_handle.GetResidue(pos)
+      if r.IsValid():
+          #print seq_handle[pos],r.number.num,pos+1
+          ev.AddResidue(r, mol.INCLUDE_ALL)
+          new_numbers.append(pos+1)
+      else:
+        raise RuntimeError('Error: renumbering failed at position %s' %pos)
+  return ev, new_numbers
+
+def _RenumberAln(aln, seq_index):
+  if not aln.sequences[seq_index].HasAttachedView():
+    raise RuntimeError("Sequence Handle has no attached view")
+  counter=0
+  ev = aln.sequences[seq_index].attached_view.CreateEmptyView()
+  new_numbers = mol.ResNumList()
+  for col in aln:
+    if col[0]!='-' and col[seq_index]!='-':
+      if col[0]!=col[seq_index]:
+        raise RuntimeError("residue mismatch at position %d (%s vs %s) (renumbering failed)"%(counter, col[0],col[1]))
+      rnum=aln.GetSequence(seq_index).GetResidueIndex(counter)
+      r=aln.GetSequence(seq_index).GetResidue(counter)
+      if not r.IsValid():
+        raise RuntimeError("invalid residue at postion %s (renumbering failed)" %(counter))
+      ev.AddResidue(r, mol.INCLUDE_ALL)
+      new_numbers.append(counter+1)
+    counter+=1
+  return ev, new_numbers
+
+
 def Renumber(seq_handle, sequence_number_with_attached_view=1):
   """
   Function to renumber an entity according to an alignment between the model sequence 
@@ -21,65 +58,11 @@ def Renumber(seq_handle, sequence_number_with_attached_view=1):
    
   """
   if isinstance(seq_handle, seq.SequenceHandle):
-    if seq_handle.HasAttachedView()==False:
-      raise RuntimeError, "Sequence Handle has no attached view"
-    changed_residue_count=0
-    renumberingFlag = False
-    ent_n=mol.CreateEntity()
-    ed=ent_n.EditXCS()
-    c=ed.InsertChain(" ")
-    for pos in range(len(seq_handle)):
-      if seq_handle[pos]!='-':
-        r=seq_handle.GetResidue(pos)
-        if r.IsValid():
-            #print seq_handle[pos],r.number.num,pos+1
-            if r.number.num!=pos+1:
-              changed_residue_count+=1
-              renumberingFlag = True
-            r_n=ed.AppendResidue(c,r.name, mol.ResNum(pos+1))
-            for atom in r.atoms:
-              ed.InsertAtom(r_n,atom.name,atom.pos,element=atom.element)
-        else:
-          err='Error: renumbering failed at position %s' %pos
-          raise RuntimeError, err
-    if renumberingFlag == True:
-      err = 'Warning: %s residues have been renumbered!' %changed_residue_count
-      LogInfo(err)
-    conop.ConnectAll(ent_n)
-    return ent_n
-
+    ev, new_numbers = _RenumberSeq(seq_handle)
   elif isinstance(seq_handle, seq.AlignmentHandle):
-    if seq_handle.GetSequence(sequence_number_with_attached_view).HasAttachedView()==False:
-      raise RuntimeError, "Sequence Handle has no attached view"
-    dir(seq_handle)
-    counter=0
-    changed_residue_count=0
-    renumberingFlag = False
-    ent_n=mol.CreateEntity()
-    ed=ent_n.EditXCS()
-    c=ed.InsertChain(seq_handle.GetSequence(sequence_number_with_attached_view).GetAttachedView().chains[0].name)
-    for col in seq_handle:
-      if col[0]!='-' and col[1]!='-':
-        if col[0]==col[1]:
-          rnum=seq_handle.GetSequence(sequence_number_with_attached_view).GetResidueIndex(counter)
-          r=seq_handle.GetSequence(sequence_number_with_attached_view).GetResidue(counter)
-          if r.IsValid():
-            if r.number.num!=counter+1:
-              changed_residue_count+=1
-              renumberingFlag = True
-            r_n=ed.AppendResidue(c,r.name, mol.ResNum(counter+1))
-            for atom in r.atoms:
-              ed.InsertAtom(r_n,atom.name,atom.pos,atom.element, atom.b_factor, 
-                            atom.occupancy, atom.is_hetatom)
-
-          else:
-            raise RuntimeError("invalide residue at postion %s (renumbering failed)" %(counter))
-        else:
-          raise RuntimeError("residue mismatch at position %d (%s vs %s) (renumbering failed)"%(counter, col[0],col[1]))
-      counter+=1
-    if renumberingFlag == True:
-      err = 'Warning: %s residues have been renumbered!' %changed_residue_count
-      LogInfo(err)
-    conop.ConnectAll(ent_n)
-    return ent_n
+    ev, new_numbers = _RenumberAln(seq_handle, sequence_number_with_attached_view)
 
+  ev.AddAllInclusiveBonds()
+  new_ent = mol.CreateEntityFromView(ev,False);
+  new_ent.EditXCS().RenumberChain(new_ent.chains[0], new_numbers)
+  return new_ent
diff --git a/modules/seq/alg/tests/test_aligntoseqres.py b/modules/seq/alg/tests/test_aligntoseqres.py
index 6c390008e69d81d2613337a863503769b6da1872..126c7f0471b43b1898f0b010d73847a00aed7f92 100644
--- a/modules/seq/alg/tests/test_aligntoseqres.py
+++ b/modules/seq/alg/tests/test_aligntoseqres.py
@@ -68,9 +68,8 @@ class TestAlignToSeqRes(unittest.TestCase):
     self.assertEqual(seq.alg.ValidateSEQRESAlignment(seqres_aln, chain), False)
 
 if __name__ == "__main__":
-  builder=conop.GetBuilder()
-  if not hasattr(builder, 'compound_lib'):
-    print 'default builder does not use compound library. ignoring unit tests'
+  if not conop.GetDefaultLib():
+    print 'No compound library available. Ignoring unit tests'
   else:
     from ost import testutils
     testutils.RunTests()
diff --git a/modules/seq/alg/tests/test_renumber.py b/modules/seq/alg/tests/test_renumber.py
index 8f234f859624416d2533d8a9de3d0c9b6d5c86c2..0309f5a1b9166f1a2e4a2febd947832c06487218 100644
--- a/modules/seq/alg/tests/test_renumber.py
+++ b/modules/seq/alg/tests/test_renumber.py
@@ -6,6 +6,11 @@ from ost import seq
 from ost.bindings.clustalw import *
 from ost.seq.alg import renumber
 
+try:
+  clustalw_path=settings.Locate(('clustalw', 'clustalw2'))
+except(settings.FileNotFound):
+  clustalw_path=None
+
 class TestRenumber(unittest.TestCase):
   
   def setUp(self):
@@ -17,14 +22,53 @@ class TestRenumber(unittest.TestCase):
     self.peptide_del_4 = io.LoadEntity("testfiles/peptide_del_4.pdb")
     self.peptide_mutation_3 = io.LoadEntity("testfiles/peptide_mutation_3.pdb")
     
+  def testRenumbersChainsBasedOnSequence(self): 
+    aln_seq = seq.CreateSequence('A', 'MP-T---NA')
+    aln_seq.AttachView(self.peptide_original.Select(''))
+
+    renumbered = renumber.Renumber(aln_seq)
+
+    res = renumbered.residues
+    self.assertEqual(len(res), 5)
+    self.assertEqual(res[0].number, 1)
+    self.assertEqual(res[1].number, 2)
+    self.assertEqual(res[2].number, 4)
+    self.assertEqual(res[3].number, 8)
+    self.assertEqual(res[4].number, 9)
+
+  def testRenumbersChainsBasedOnAlignment(self): 
+    aln_seq = seq.CreateSequence('A', 'MP-T---NA')
+    aln_seq.AttachView(self.peptide_original.Select(''))
+    aln = seq.CreateAlignment(seq.CreateSequence('A', 'MP-T-XXNA'), aln_seq)
+
+    renumbered = renumber.Renumber(aln)
+
+    res = renumbered.residues
+    self.assertEqual(len(res), 5)
+    self.assertEqual(res[0].number, 1)
+    self.assertEqual(res[1].number, 2)
+    self.assertEqual(res[2].number, 4)
+    self.assertEqual(res[3].number, 8)
+    self.assertEqual(res[4].number, 9)
+
+  def testRenumberPreservesBonds(self):
+    aln_seq = seq.CreateSequence('A', 'MP-T---NA')
+    aln_seq.AttachView(self.peptide_original.Select(''))
+
+    renumbered = renumber.Renumber(aln_seq)
+
+    self.assertTrue(mol.BondExists(renumbered.chains[0].FindAtom(1, 'N'), 
+                                   renumbered.chains[0].FindAtom(1, 'CA')))
 
-  def testPeptidePlusFive(self):
+  def testClustalWPeptidePlusFive(self):
     """
     All residue numbers shifted by 5.
     Check whether internal atom order changes while renumbering
     (a new entity is generated in the edit_mode)
     TODO: add more basic tests: are all properties preserved?
     """
+    if not clustalw_path:
+      return
     model_seq=seq.SequenceFromChain(" ", self.peptide_plus_5.chains[0]) 
     model_seq.name="model"
     aln=ClustalW(self.target_seq,model_seq)
@@ -39,10 +83,12 @@ class TestRenumber(unittest.TestCase):
                 "Renumbering failed on atom level: restoring from ResNum+5"
   
 
-  def testPeptideRandom(self):
+  def testClustalWPeptideRandom(self):
     """
     Change residue names in random order
     """
+    if not clustalw_path:
+      return
     model_seq=seq.SequenceFromChain(" ", self.peptide_random.chains[0]) 
     model_seq.name="model"
     aln=ClustalW(self.target_seq,model_seq)
@@ -57,10 +103,12 @@ class TestRenumber(unittest.TestCase):
                "Renumbering failed on atom level: restoring from random residue numbers"
 
 
-  def testPeptideDel_1_2(self):
+  def testClustalWPeptideDel_1_2(self):
     """
     First two residues were removed
     """
+    if not clustalw_path:
+      return
     model_seq=seq.SequenceFromChain(" ", self.peptide_del_1_2.chains[0]) 
     model_seq.name="model"
     aln=ClustalW(self.target_seq,model_seq)
@@ -77,10 +125,12 @@ class TestRenumber(unittest.TestCase):
                "Renumbering failed on atom level: restoring from random residue numbers"
 
 
-  def testPeptideDel_4(self):
+  def testClustalWPeptideDel_4(self):
     """
     Residues in the middle (position 4) was removed
     """
+    if not clustalw_path:
+      return
     model_seq=seq.SequenceFromChain(" ", self.peptide_del_4.chains[0]) 
     model_seq.name="model"
     aln=ClustalW(self.target_seq,model_seq)
@@ -99,10 +149,12 @@ class TestRenumber(unittest.TestCase):
                "Renumbering failed on atom level: restoring from random residue numbers"
 
 
-  def testPeptideMutation_3(self):
+  def testClustalWPeptideMutation_3(self):
     """
     Mutation to GLY at postion 3
     """
+    if not clustalw_path:
+      return
     model_seq=seq.SequenceFromChain(" ", self.peptide_mutation_3.chains[0]) 
     model_seq.name="model"
     aln=ClustalW(self.target_seq,model_seq)
@@ -114,10 +166,7 @@ class TestRenumber(unittest.TestCase):
 if __name__ == "__main__":
   # test renumbering
   # test if clustalw package is available on system, otherwise ignore tests
-  try:
-    clustalw_path=settings.Locate(('clustalw', 'clustalw2'))
-  except(settings.FileNotFound):
-    print "Could not find clustalw executable: ignoring unit tests"
-    sys.exit(0)  
+  if not clustalw_path:
+    print "Could not find clustalw executable: ignoring some renumber unit tests"
   from ost import testutils
   testutils.RunTests()
diff --git a/modules/seq/base/src/sequence_handle.hh b/modules/seq/base/src/sequence_handle.hh
index 937387c797bc42f28b0fe902f1e9af256d6fa416..d7247cbd10abca25bdc9fc3c00b60dac7c6e9915 100644
--- a/modules/seq/base/src/sequence_handle.hh
+++ b/modules/seq/base/src/sequence_handle.hh
@@ -284,7 +284,7 @@ public:
   ///
   /// The sequence is mapped onto the chain with given name
   void AttachView(const mol::EntityView& view, const String& chain_name);
-  
+   
   /// \internal
   SequenceHandle(const impl::SequenceImplPtr& impl);  
   
diff --git a/scripts/ost_startup.py b/scripts/ost_startup.py
index 6671b51643e299cb81645fa9707ae4a714bb3d95..553d54cb906aa6a86e534881c181077f3d007e0e 100644
--- a/scripts/ost_startup.py
+++ b/scripts/ost_startup.py
@@ -37,16 +37,16 @@ from ost import *
 import ost
 
 ost.SetPrefixPath(_base_dir)
-def _InitRuleBasedBuilder():
+
+def _InitRuleBasedProcessor():
   compound_lib_path=os.path.join(ost.GetSharedDataPath(), 'compounds.chemlib')
   if os.path.exists(compound_lib_path):
     compound_lib=conop.CompoundLib.Load(compound_lib_path)
-    conop.RegisterBuilder(conop.RuleBasedBuilder(compound_lib), 'RBB')
-    conop.SetDefaultBuilder('RBB')
+    conop.SetDefaultLib(compound_lib)
+    io.profiles['DEFAULT'].processor = conop.RuleBasedProcessor(compound_lib)
 
-# switch to rule-based builder for high fidelity if compounds.chemlib is 
-# available
-_InitRuleBasedBuilder()
+# switch to rule-based processor, if compound library is available
+_InitRuleBasedProcessor()
 import os.path
 HistoryFile=os.path.expanduser('~/.ost_history')
 
diff --git a/tools/molck/main.cc b/tools/molck/main.cc
index 94e5a97f5120b9522a3d8678518c44fbe84f4cb7..09251bcfb6a29a38c36ba902498745bbf8ec23e5 100644
--- a/tools/molck/main.cc
+++ b/tools/molck/main.cc
@@ -67,14 +67,13 @@ CompoundLibPtr load_compound_lib(const String& custom_path)
   exe_path = std::string( result, (count > 0) ? count : 0 );
   #endif
   if (exe_path.empty()) { 
-    std::cerr << "Could not determine the path of the molck executable. Will only look for compounds.chemlib in the current working directory" << std::endl;
+    std::cerr << "Could not determine the path of the molck executable. Will only "
+       "look for compounds.chemlib in the current working directory" << std::endl;
   } else {
     fs::path path_and_exe(exe_path);
     fs::path path_only=path_and_exe.branch_path();
     fs::path share_path = path_only.branch_path();
-    share_path/="share";
-    share_path/="openstructure";
-    share_path/="compounds.chemlib";
+    share_path = share_path / "share" / "openstructure" / "compounds.chemlib";
 
     String share_path_string=BFPathToString(share_path);
       
@@ -89,37 +88,33 @@ CompoundLibPtr load_compound_lib(const String& custom_path)
   return CompoundLibPtr();
 }
 
+const char* USAGE=
+"this is molck - the molecule checker\n"
+"usage: molck [options] file1.pdb [file2.pdb [...]]\n"
+"options \n"
+"  --complib=path    location of the compound library file. If not provided, the \n"
+"    following locations are searched in this order: \n" 
+"    1. Working directory, 2. OpenStructure standard library location (if the \n"
+"    executable is part of a standard OpenStructure installation) \n"
+"  --rm=<a>,<b>      remove atoms and residues matching some criteria \n"
+"    zeroocc - Remove atoms with zero occupancy \n"
+"    hyd - Remove hydrogen atoms \n"
+"    oxt - Remove terminal oxygens \n"
+"    nonstd - Remove all residues not one of the 20 standard amino acids \n"
+"    unk - Remove unknown and atoms not following the nomenclature\n"
+"  --fix-ele         clean up element column\n"
+"  --stdout          write cleaned file(s) to stdout \n"
+"  --out=filename    write cleaned file(s) to disk. % characters in the filename are \n"
+"    replaced with the basename of the input file without extension. \n"
+"    Default: %-molcked.pdb \n"
+"  --color=auto|on|off \n"
+"    whether output should be colored\n"
+"  --map-nonstd   maps modified residues back to the parent amino acid, for example\n"
+"    MSE -> MET, SEP -> SER.\n";
+
 void usage()
 {
-  std::cerr << "usage: molck [options] file1.pdb [file2.pdb [...]]" << std::endl;
-  std::cerr << "options" << std::endl;
-  std::cerr << "  --complib=path   location of the compound library file" << std::endl;   
-  std::cerr << "                   If not provided, the following locations are searched" << std::endl;   
-  std::cerr << "                   in this order:" << std::endl;   
-  std::cerr << "                   1. Working directory" << std::endl;   
-  std::cerr << "                   2. OpenStructure standard library location" << std::endl;   
-  std::cerr << "                      (if the executable is part of a standard" << std::endl;
-  std::cerr << "                      OpenStructure installation)" << std::endl;
-  std::cerr << "  --rm=<a>,<b>   remove atoms and residues matching some criteria" << std::endl;
-  std::cerr << "          zeroocc  - Remove atoms with zero occupancy" << std::endl;
-  std::cerr << "          hyd      - Remove hydrogen atoms" << std::endl;
-  std::cerr << "          oxt      - Remove terminal oxygens" << std::endl;
-  std::cerr << "          nonstd   - Remove all residues not " << std::endl 
-            << "                     one of the 20 standard amino acids" << std::endl;
-  std::cerr << "          unk      - Remove unknown atoms and atoms that " << std::endl 
-            << "                     are not supposed to be part of a residue" << std::endl;
-  std::cerr << "  --fix-ele      clean up element column" << std::endl;
-  std::cerr << "  --stdout       write cleaned file(s) to stdout" << std::endl;
-  std::cerr << "  --fileout=blueprint   write cleaned file(s) to disk" << std::endl;  
-  std::cerr << "                        The blueprint string, which must contain a % character," << std::endl;
-  std::cerr << "                        is used to generate the output filename and path" << std::endl; 
-  std::cerr << "                        by replacing % with the input file name without" << std::endl;
-  std::cerr << "                        the extension. Output files automatically add" << std::endl; 
-  std::cerr << "                        '.pdb' extension" << std::endl;
-  std::cerr << "  --color=auto|on|off " << std::endl 
-            << "          whether output should be colored" << std::endl;
-  std::cerr << "  --map-nonstd   maps modified residues back to the parent amino " << std::endl 
-            << "          acid, e.g. MSE -> MET, SEP -> SER." << std::endl;
+  std::cerr << USAGE << std::endl;
   exit(0);
 }	
 
@@ -153,7 +148,8 @@ int main(int argc, char *argv[])
      "whether the output should be colored.")
     ("files", po::value< std::vector<String> >(), "input file(s)")
     ("stdout", "write cleaned file(s) to stdout")
-    ("fileout", po::value<String>(&output_blueprint_string), "write cleaned file to output using blueprint to determine path")
+    ("out,o", po::value<String>(&output_blueprint_string)->default_value("%-molcked.pdb"), 
+     "write cleaned file to output using blueprint to determine path")
     ("map-nonstd", "map non standard residues back to standard ones (e.g.: MSE->MET,SEP->SER,etc.)")
     ("fix-ele", "insert element") 
     ("complib", po::value<String>(&custom_path)->default_value(""),"location of the compound library file")       
@@ -184,11 +180,10 @@ int main(int argc, char *argv[])
   }    
   if (vm.count("stdout")) {
     write_to_stdout = true;
-  }
-  if (vm.count("fileout")) {
+  } else {
     write_to_file = true;
-    output_blueprint_string = vm["fileout"].as<String>();
-  }  
+    output_blueprint_string = vm["out"].as<String>();
+  }
   if (vm.count("map-nonstd")) {
     map_nonstd_res = true;
   }
@@ -266,7 +261,7 @@ int main(int argc, char *argv[])
     }
 
     XCSEditor edi=ent.EditXCS();
-    DiagEngine diags;
+    Diagnostics diags;
     Checker checker(lib, ent, diags);
     if (rm_zero_occ_atoms) {
       std::cerr << "removing atoms with zero occupancy" << std::endl;
@@ -306,8 +301,9 @@ int main(int argc, char *argv[])
     checker.CheckForCompleteness();
     checker.CheckForUnknownAtoms();
     checker.CheckForNonStandard();
-      for (size_t j=0; j<diags.GetDiags().size(); ++j) {
-      const Diag* diag=diags.GetDiags()[j];
+    for (Diagnostics::const_diag_iterator 
+         j = diags.diags_begin(), e = diags.diags_end(); j != e; ++j) {
+      const Diag* diag=*j;
       std::cerr << diag->Format(colored);
       switch (diag->GetType()) {
         case DIAG_UNK_ATOM:
@@ -360,24 +356,17 @@ int main(int argc, char *argv[])
     if (write_to_file) {
       fs::path input_file_path(files[i]);
       fs::path input_filename = BFPathStem(input_file_path);
- 
-
       String input_filename_string=BFPathToString(input_filename);
-
       size_t replstart =output_blueprint_string.find('%');	
-
-      if (replstart == String::npos) {
-        std::cerr << "The output blueprint string does not contain a % character" << std::endl;
-        exit(-1);
-      } 
       String output_blueprint_string_copy = output_blueprint_string;
-      output_blueprint_string_copy.replace(replstart,1,input_filename_string); 
-      output_blueprint_string_copy+=".pdb";
- 
+      if (replstart != String::npos) {
+        output_blueprint_string_copy.replace(replstart,1,input_filename_string); 
+      } 
       try {
         fs::path out_path(output_blueprint_string_copy);
-        if (!exists(out_path)) {
-          std::cerr << "Output path does not exist: " << output_blueprint_string_copy << std::endl;
+        if (out_path.has_parent_path() && !exists(out_path.parent_path())) {
+          std::cerr << "Output path does not exist: " 
+                    << output_blueprint_string_copy << std::endl;
           exit(-1);
         }
       } catch (std::exception& e) {
@@ -385,7 +374,8 @@ int main(int argc, char *argv[])
         size_t perden = String(e.what()).find("Permission denied");	
 
         if (perden != String::npos) {
-          std::cerr << "Cannot write into output directory: " << output_blueprint_string_copy << std::endl;
+          std::cerr << "Cannot write into output directory: " 
+                    << output_blueprint_string_copy << std::endl;
           exit(-1);
         } else {
           std::cerr << e.what() << std::endl;
@@ -394,7 +384,7 @@ int main(int argc, char *argv[])
       }
       std::cerr << "Writing out file: " << output_blueprint_string_copy << std::endl;
       PDBWriter writer(output_blueprint_string_copy, prof);
-       writer.Write(ent);
+      writer.Write(ent);
     }
   }