diff --git a/doc/contributing.rst b/doc/contributing.rst
index 0081bf3de447a6ad5495f15f134ce248d2a51fff..ac0a15f3733e58afcf3c8aaaceeae0e9fa25343a 100644
--- a/doc/contributing.rst
+++ b/doc/contributing.rst
@@ -203,7 +203,7 @@ good practice to develop new functionality along tests and that right from the
 beginning. At some point, new code needs testing anyway to see if it does what
 it should, so just do this by writing unit tests. Test sources are stored in
 files with a prefix :file:`test_` and usually come per submodule instead of
-sporting a single monolithic :file:`test_sidechain.py`.
+sporting a single monolithic :file:`test_sidechain_reconstruction.py`.
 
 |python| code is evaluated using its own :py_docs:`unit testing framework
 <library/unittest.html>` with a little help from |ost_s|_ (|C++| uses the
@@ -211,14 +211,14 @@ sporting a single monolithic :file:`test_sidechain.py`.
 <http://www.boost.org/doc/libs/1_47_0/libs/test/doc/html/index.html>`_). The
 basic scheme is to import your module, subclass :class:`unittest.TestCase` and
 make the whole file runnable as script using the most common |nameattr|_
-attribute. As an example we test the :func:`promod3.sidechain.Reconstruct`
-function:
+attribute. As an example we test the 
+:func:`promod3.modelling.ReconstructSidechains` function:
 
-.. literalinclude:: ../../tests/doc/scripts/unittest_sidechain.py
+.. literalinclude:: ../../tests/doc/scripts/unittest_sidechain_reconstruction.py
   :linenos:
 
 To hook up your tests with ``make codetest`` (and to create a
-``test_reconstruct.py_run`` target), everything has to be introduced to |cmake|.
+``test_reconstruct_sidechains.py_run`` target), everything has to be introduced to |cmake|.
 First, tell |cmake| to search :file:`tests` for a :file:`CMakeLists.txt` file
 by extending the list of sub-directories in :file:`sidechain/CMakeLists.txt`:
 
@@ -237,7 +237,7 @@ you.
   :linenos:
 
   set(SIDECHAIN_UNIT_TESTS
-    test_reconstruct.py
+    test_reconstruct_sidechains.py
   )
 
   set(SIDECHAIN_TEST_DATA
@@ -253,7 +253,7 @@ Note how we listed the test data that we require in the unit test by defining
 ``SIDECHAIN_TEST_DATA``.
 
 Now tests should be available by ``make check``, ``make codetest`` and
-``make test_reconstruct.py_run``.
+``make test_reconstruct_sidechains.py_run``.
 
 --------------------------------------------------------------------------------
 How To Start Your Own Action
diff --git a/doc/gettingstarted.rst b/doc/gettingstarted.rst
index 489002a8f6a3bb03c67692a740cf0de9c259ba65..9b2b8024b6cb6e7cd2e98aa10c3c86df5754f645 100644
--- a/doc/gettingstarted.rst
+++ b/doc/gettingstarted.rst
@@ -35,7 +35,7 @@ the desired target sequence. The modelling steps then are:
 - Build a raw model from a template by copying the part of the template which
   is conserved
 - Perform loop modelling to close all gaps (see :mod:`~promod3.loop` module)
-- Reconstruct sidechains (see :mod:`~promod3.sidechain` module)
+- Reconstruct sidechains (using :mod:`~promod3.sidechain` module)
 - Minimize energy of final model using molecular mechanics
   (using :mod:`ost.mol.mm` from |ost_s|)
 
diff --git a/doc/tests/CMakeLists.txt b/doc/tests/CMakeLists.txt
index 43cbacf95851201921dbc7b940d9c2b68371326e..89bd4fcbd87a66d1c824e9dcf25a2dca530c6412 100644
--- a/doc/tests/CMakeLists.txt
+++ b/doc/tests/CMakeLists.txt
@@ -24,7 +24,7 @@ set (DOC_TEST_SCRIPTS
   scripts/core_file_checks.py
 
   scripts/hello_world.py
-  scripts/unittest_sidechain.py
+  scripts/unittest_sidechain_reconstruction.py
 
   scripts/loop_main.py
   scripts/loop_backbone.py
@@ -47,9 +47,9 @@ set (DOC_TEST_SCRIPTS
   scripts/modelling_monte_carlo.py
   scripts/modelling_loop_candidates.py
   scripts/modelling_loop_scoring.py
+  scripts/modelling_reconstruct_sidechains.py
+  scripts/modelling_sidechain_reconstructor.py
 
-  scripts/sidechain_reconstruct.py
-  scripts/sidechain_reconstructor.py
   scripts/sidechain_steps.py
 )
 
diff --git a/doc/tests/scripts/sidechain_reconstruct.py b/doc/tests/scripts/modelling_reconstruct_sidechains.py
similarity index 75%
rename from doc/tests/scripts/sidechain_reconstruct.py
rename to doc/tests/scripts/modelling_reconstruct_sidechains.py
index f1e12512bebdb16081a0c3116b120776faab9f0d..de157d80189522346e502e0c4b3d8f985c0b995f 100644
--- a/doc/tests/scripts/sidechain_reconstruct.py
+++ b/doc/tests/scripts/modelling_reconstruct_sidechains.py
@@ -1,5 +1,5 @@
 from ost import io, mol
-from promod3 import sidechain
+from promod3 import modelling
 
 # load a protein 
 prot = io.LoadPDB('data/1CRN.pdb')
@@ -7,5 +7,5 @@ prot = io.LoadPDB('data/1CRN.pdb')
 prot = mol.CreateEntityFromView(prot.Select("peptide=true"), True)
 io.SavePDB(prot, 'sidechain_test_orig.pdb')
 # reconstruct sidechains
-sidechain.Reconstruct(prot, keep_sidechains=False)
+modelling.ReconstructSidechains(prot, keep_sidechains=False)
 io.SavePDB(prot, 'sidechain_test_rec.pdb')
diff --git a/doc/tests/scripts/sidechain_reconstructor.py b/doc/tests/scripts/modelling_sidechain_reconstructor.py
similarity index 85%
rename from doc/tests/scripts/sidechain_reconstructor.py
rename to doc/tests/scripts/modelling_sidechain_reconstructor.py
index 254d7656c2c2f912b12490a6bfd85ea9a5517f8d..199c885643193333441080e8176c57a59b4a5f07 100644
--- a/doc/tests/scripts/sidechain_reconstructor.py
+++ b/doc/tests/scripts/modelling_sidechain_reconstructor.py
@@ -1,5 +1,5 @@
 from ost import io
-from promod3 import sidechain, loop
+from promod3 import loop, modelling
 
 # load example (has res. numbering starting at 1)
 prot = io.LoadPDB('data/1CRN.pdb')
@@ -9,7 +9,7 @@ seqres_str = ''.join([r.one_letter_code for r in res_list])
 # initialize AllAtom environment and sidechain reconstructor
 env = loop.AllAtomEnv(seqres_str)
 env.SetInitialEnvironment(prot)
-sc_rec = sidechain.SidechainReconstructor(keep_sidechains=False)
+sc_rec = modelling.SidechainReconstructor(keep_sidechains=False)
 sc_rec.AttachEnvironment(env)
 
 # reconstruct subset (res. num. 6..10)
diff --git a/doc/tests/scripts/unittest_sidechain.py b/doc/tests/scripts/unittest_sidechain_reconstruction.py
similarity index 84%
rename from doc/tests/scripts/unittest_sidechain.py
rename to doc/tests/scripts/unittest_sidechain_reconstruction.py
index 65452ad64636191635200bb117cbadba574409fc..083416eb7b838380f457bf217d1d53a8dbea4494 100644
--- a/doc/tests/scripts/unittest_sidechain.py
+++ b/doc/tests/scripts/unittest_sidechain_reconstruction.py
@@ -1,5 +1,5 @@
 import unittest
-from promod3 import sidechain
+from promod3 import modelling
 from ost import io,mol
 import os
 
@@ -9,7 +9,7 @@ class ReconstructTests(unittest.TestCase):
     	ref_file = os.path.join('data', '1eye_rec.pdb')
     	# get and reconstruct 1eye
     	prot = io.LoadPDB(in_file)
-    	sidechain.Reconstruct(prot, keep_sidechains=False)
+    	modelling.ReconstructSidechains(prot, keep_sidechains=False)
     	# compare with reference solution
     	prot_rec = io.LoadPDB(ref_file)
         self.assertEqual(prot.GetAtomCount(), prot_rec.GetAtomCount())
diff --git a/doc/tests/test_doctests.py b/doc/tests/test_doctests.py
index 3dce5f46206a43393964190df33c37b32a24160f..01a1b196890cd3ecc7a00ddd8351104a5bc7fe48 100644
--- a/doc/tests/test_doctests.py
+++ b/doc/tests/test_doctests.py
@@ -152,7 +152,7 @@ class DocTests(unittest.TestCase):
 
     def testUnittestSidechain(self):
         # run it
-        script_path = os.path.join('scripts', 'unittest_sidechain.py')
+        script_path = os.path.join('scripts', 'unittest_sidechain_reconstruction.py')
         rcode, sout, serr = self.runPM(script_path)
         # check return code and last line of output
         self.assertEqual(rcode, 0)
@@ -367,11 +367,9 @@ class DocTests(unittest.TestCase):
         # clean up
         os.remove('model.pdb')
 
-    ################################################################
-
-    def testSidechainReconstruct(self):
+    def testModellingReconstructSidechains(self):
         # run it
-        self.checkPMRun('sidechain_reconstruct.py', [], 0)
+        self.checkPMRun('modelling_reconstruct_sidechains.py', [], 0)
         # check that result exists and is readable
         io.LoadPDB('sidechain_test_orig.pdb')
         io.LoadPDB('sidechain_test_rec.pdb')
@@ -379,14 +377,16 @@ class DocTests(unittest.TestCase):
         os.remove('sidechain_test_orig.pdb')
         os.remove('sidechain_test_rec.pdb')
 
-    def testSidechainReconstructor(self):
+    def testModellingSidechainReconstructor(self):
         # run it
-        self.checkPMRun('sidechain_reconstructor.py', [], 0)
+        self.checkPMRun('modelling_sidechain_reconstructor.py', [], 0)
         # check that result exists and is readable
         io.LoadPDB('sc_rec_test.pdb')
         # clean up
         os.remove('sc_rec_test.pdb')
 
+    ################################################################
+
     def testSidechainSteps(self):
         # run it
         self.checkPMRun('sidechain_steps.py', [], 0)
diff --git a/extras/scoring_weight_training/generate_bft_chunks.py b/extras/scoring_weight_training/generate_bft_chunks.py
index f589f9323086811ee9c4ed9959f1dc7c37123119..835e0368e05dd637bb16720c8080c24b7c8ff102 100644
--- a/extras/scoring_weight_training/generate_bft_chunks.py
+++ b/extras/scoring_weight_training/generate_bft_chunks.py
@@ -26,7 +26,7 @@ USAGE: pm generate_bft_chunks.py MODE OPTIONS
 
 import math, json, os, sys, resource, time
 from ost import io, seq
-from promod3 import core, loop, modelling, scoring, sidechain
+from promod3 import core, loop, modelling, scoring, modelling
 
 ###############################################################################
 # SETUP
@@ -317,7 +317,7 @@ for fragment in fragments[frag_start:frag_end]:
   # get sidechain reconstructor
   aa_sc_env = loop.AllAtomEnv(seqres)
   aa_sc_env.SetInitialEnvironment(ent)
-  sc_rec = sidechain.SidechainReconstructor(graph_max_complexity=10000000)
+  sc_rec = modelling.SidechainReconstructor(graph_max_complexity=10000000)
   sc_rec.AttachEnvironment(aa_sc_env)
   # precompute sidechains for chain with reference loop in it?
   if reconstruct_full_chain_sc:
diff --git a/loop/doc/structure_db.rst b/loop/doc/structure_db.rst
index d0af15cb30e81a8e8f9610de2531ec2833e516c1..c66f6078056355fe223ef14b688723fa41caf794 100644
--- a/loop/doc/structure_db.rst
+++ b/loop/doc/structure_db.rst
@@ -513,8 +513,10 @@ In some cases you might want to use the :class:`StructureDB` to search
 for fragments that possibly represent the structural conformation of interest.
 The :class:`Fragger` searches a :class:`StructureDB` for n fragments, 
 that maximize a certain score and gathers a set of fragments with a guaranteed 
-structural diversity based on an rmsd_threshold. The score can be built using an 
-arbitrary linear combination of following components:
+structural diversity based on an rmsd_threshold. You can use the :class:`Fragger`
+wrapped in a full fletched pipeline implemented in 
+:class:`~promod3.modelling.FraggerHandle` or search for fragments from scratch 
+using an arbitrary linear combination of scores:
 
 * **SeqID**:
   Calculates the fraction of amino acids being identical when comparing
diff --git a/modelling/doc/CMakeLists.txt b/modelling/doc/CMakeLists.txt
index 3b237e21ea7ee72744f5f9eb2a400140d0a05925..33a9a8784cae59fa511d7c610f260c578fdcdc2e 100644
--- a/modelling/doc/CMakeLists.txt
+++ b/modelling/doc/CMakeLists.txt
@@ -6,6 +6,7 @@ set(MODELLING_RST
   loop_candidates.rst
   loop_closing.rst
   monte_carlo.rst
+  sidechain_reconstruction.rst
   algorithms.rst
 )
 
diff --git a/modelling/doc/index.rst b/modelling/doc/index.rst
index bd0657433a21296755af0d2e751e334f3d3881f6..27ed61013a17190ebef7f0afb0027241c0e19294 100644
--- a/modelling/doc/index.rst
+++ b/modelling/doc/index.rst
@@ -27,5 +27,6 @@ The various steps involved in protein modelling are described here:
   loop_candidates
   loop_closing
   monte_carlo
+  sidechain_reconstruction
   algorithms
-  
\ No newline at end of file
+  
diff --git a/modelling/doc/loop_closing.rst b/modelling/doc/loop_closing.rst
index 1e2b9bc07a274c88a5e203049f0a9e39e8d76093..bd8484293aa93e1cfca17386073bc1a53bd5549e 100644
--- a/modelling/doc/loop_closing.rst
+++ b/modelling/doc/loop_closing.rst
@@ -309,8 +309,8 @@ Relaxing All Atom Loops
 --------------------------------------------------------------------------------
 
 After the reconstruction of loop sidechains with the
-:meth:`~promod3.sidechain.SidechainReconstructor.Reconstruct` method of
-:class:`~promod3.sidechain.SidechainReconstructor`, it may be desired to
+:meth:`~promod3.modelling.SidechainReconstructor.Reconstruct` method of
+:class:`~promod3.modelling.SidechainReconstructor`, it may be desired to
 quickly relax the loop. The :class:`AllAtomRelaxer` class takes care of that.
 
 .. class:: AllAtomRelaxer(sc_data, mm_system_creator)
@@ -321,7 +321,7 @@ quickly relax the loop. The :class:`AllAtomRelaxer` class takes care of that.
   N/C stems of loop are fixed if they are non-terminal.
 
   :param sc_data: Sidechain reconstruction result
-  :type sc_data:  :class:`~promod3.sidechain.SidechainReconstructionData`
+  :type sc_data:  :class:`~promod3.modelling.SidechainReconstructionData`
   :param mm_system_creator: System creator to be used here
   :type mm_system_creator:  :class:`~promod3.loop.MmSystemCreator`
 
@@ -331,7 +331,7 @@ quickly relax the loop. The :class:`AllAtomRelaxer` class takes care of that.
     *sc_data.env_pos.all_pos*.
 
     :param sc_data: Sidechain reconstruction result to be updated
-    :type sc_data:  :class:`~promod3.sidechain.SidechainReconstructionData`
+    :type sc_data:  :class:`~promod3.modelling.SidechainReconstructionData`
     :param steps: Number of steepest descent steps
     :type steps:  :class:`int`
     :param stop_criterion: If maximum force acting on a particle falls below
@@ -351,7 +351,7 @@ quickly relax the loop. The :class:`AllAtomRelaxer` class takes care of that.
     the same disulfid bridges as the one given in the constructor.
 
     :param sc_data: Get new positions from *sc_data.env_pos.all_pos*
-    :type sc_data:  :class:`~promod3.sidechain.SidechainReconstructionData`
+    :type sc_data:  :class:`~promod3.modelling.SidechainReconstructionData`
 
     :raises: :exc:`~exceptions.RuntimeError` if *sc_data* is incompatible with
              the one given in the constructor.
diff --git a/modelling/doc/pipeline.rst b/modelling/doc/pipeline.rst
index c7f9dea8df790c3586e393586df0b6531a4a2369..71c5ba32fa69b29e237b75621211fa15018a9a15 100644
--- a/modelling/doc/pipeline.rst
+++ b/modelling/doc/pipeline.rst
@@ -124,7 +124,7 @@ Build Raw Modelling Handle
     scoring. A default one is set with :func:`SetupDefaultAllAtomScoring` when
     needed.
 
-    :type: :class:`~promod3.sidechain.SidechainReconstructor`
+    :type: :class:`~promod3.modelling.SidechainReconstructor`
 
   .. method:: Copy()
 
diff --git a/sidechain/doc/reconstruct.rst b/modelling/doc/sidechain_reconstruction.rst
similarity index 94%
rename from sidechain/doc/reconstruct.rst
rename to modelling/doc/sidechain_reconstruction.rst
index 69ba71554fb7ada1006a4b7abf6037b9db3d40b6..e844b8839669f5c78f0b91f9b54d9524b49e4ed6 100644
--- a/sidechain/doc/reconstruct.rst
+++ b/modelling/doc/sidechain_reconstruction.rst
@@ -1,19 +1,27 @@
 Sidechain Reconstruction
 ================================================================================
 
-.. currentmodule:: promod3.sidechain
+.. currentmodule:: promod3.modelling
 
 Two methods are provided to fully reconstruct sidechains of residues:
 
-- the :func:`Reconstruct` function handles a full OST
+- the :func:`ReconstructSidechains` function handles a full OST
   :class:`~ost.mol.EntityHandle`
 - the :class:`SidechainReconstructor` is linked to an all atom environment
   and used to reconstruct sidechains of single loops
 
+Example usage:
+
+.. literalinclude:: ../../../tests/doc/scripts/sidechain_reconstruct.py
+
+.. literalinclude:: ../../../tests/doc/scripts/sidechain_reconstructor.py
+
+
+
 Reconstruct Function
 --------------------------------------------------------------------------------
 
-.. autofunction:: Reconstruct
+.. autofunction:: ReconstructSidechains
 
 
 SidechainReconstructor Class
@@ -51,10 +59,10 @@ SidechainReconstructor Class
   :type cutoff:  :class:`float`
 
   :param graph_max_complexity: Max. complexity for
-                               :meth:`RotamerGraph.TreeSolve`.
+                               :meth:`promod3.sidechain.RotamerGraph.TreeSolve`.
   :type graph_max_complexity:  :class:`int`
   :param graph_intial_epsilon: Initial epsilon for
-                               :meth:`RotamerGraph.TreeSolve`.
+                               :meth:`promod3.sidechain.RotamerGraph.TreeSolve`.
   :type graph_intial_epsilon:  :class:`float`
 
   :param disulfid_score_thresh: If :meth:`DisulfidScore` between two CYS is
diff --git a/modelling/pymod/CMakeLists.txt b/modelling/pymod/CMakeLists.txt
index 09d856ed425ceff0042c2ef66d8bcaf57ebb89a6..16bed15943d08107aee1bbf4161823170bf48707 100644
--- a/modelling/pymod/CMakeLists.txt
+++ b/modelling/pymod/CMakeLists.txt
@@ -10,6 +10,7 @@ set(MODELLING_CPP
   export_score_container.cc
   export_scoring_weights.cc
   export_el_enumerador.cc
+  export_sidechain_reconstructor.cc
   wrap_modelling.cc
 )
 
@@ -21,6 +22,7 @@ set(MODELLING_PYMOD
   _ring_punches.py
   _denovo.py
   _fragger_handle.py
+  _reconstruct_sidechains.py
 )
 
 pymod(NAME modelling
diff --git a/modelling/pymod/__init__.py b/modelling/pymod/__init__.py
index e92e7ff5e6f8290b8edc42c57e1fec420c99d2e0..cdd41d485e453d2089b76a5a34c710559cd86a87 100644
--- a/modelling/pymod/__init__.py
+++ b/modelling/pymod/__init__.py
@@ -3,6 +3,7 @@ from _modelling import *
 from _closegaps import *
 from _molprobity import *
 from _pipeline import *
+from _reconstruct_sidechains import *
 from _ring_punches import *
 from _denovo import *
 from _fragger_handle import *
diff --git a/modelling/pymod/_closegaps.py b/modelling/pymod/_closegaps.py
index 40d2dc1e6434c216e5ee522ef21a7cb0028d9a6b..96b5f819145b8c3fbd48d8b05127ba4d95e8a5c2 100644
--- a/modelling/pymod/_closegaps.py
+++ b/modelling/pymod/_closegaps.py
@@ -4,9 +4,10 @@ as argument.
 '''
 
 # internal
-from promod3 import loop, sidechain, core, scoring
+from promod3 import loop, core, scoring
 from _modelling import *
 from _ring_punches import *
+from _reconstruct_sidechains import *
 # external
 import ost
 import sys
@@ -821,7 +822,7 @@ def FillLoopsByDatabase(mhandle, fragment_db, structure_db,
         else:
             # all good: fix sidechains if we're in ring-punch-mode and continue
             if ring_punch_detection == 2:
-                sidechain.Reconstruct(mhandle.model, keep_sidechains=True)
+                ReconstructSidechains(mhandle.model, keep_sidechains=True)
             gap_idx = new_idx
 
 
@@ -1051,7 +1052,7 @@ def FillLoopsByMonteCarlo(mhandle, torsion_sampler, max_loops_to_search=6,
         else:
             # all good: fix sidechains if we're in ring-punch-mode and continue
             if ring_punch_detection == 2:
-                sidechain.Reconstruct(mhandle.model, keep_sidechains=True)
+                ReconstructSidechains(mhandle.model, keep_sidechains=True)
             gap_idx = new_idx
 
 
diff --git a/modelling/pymod/_fragger_handle.py b/modelling/pymod/_fragger_handle.py
index 3f5bc038311270695decbdf46c99bde90476427e..95dee6db0f9c33dcdaf0bd3f5e78ba31c5202487 100644
--- a/modelling/pymod/_fragger_handle.py
+++ b/modelling/pymod/_fragger_handle.py
@@ -111,7 +111,8 @@ def _SetupFragger_four(frag_sequence, frag_profile,
                        
 
 class FraggerHandle:
-    '''Handler for Fragger objects linked to a specific chain.
+    '''Handler for :class:`~promod3.loop.Fragger` objects linked to a 
+    specific chain.
 
     Tries to get the most accurate fragments given your input.
     You can only provide a SEQRES, the returned fragments are
diff --git a/modelling/pymod/_pipeline.py b/modelling/pymod/_pipeline.py
index 92e8dacdfcb643149ab6814693ae3873b07e8f82..6f149369b31259b54dada119733bac167d7da50f 100644
--- a/modelling/pymod/_pipeline.py
+++ b/modelling/pymod/_pipeline.py
@@ -6,6 +6,7 @@ as argument.
 # internal
 from promod3 import loop, sidechain, core
 from _modelling import *
+from _reconstruct_sidechains import *
 from _closegaps import *
 from _ring_punches import *
 # external
@@ -166,10 +167,10 @@ def BuildSidechains(mhandle, merge_distance=4, fragment_db=None,
                     structure_db=None, torsion_sampler=None):
     '''Build sidechains for model.
 
-    This is a wrapper for :func:`promod3.sidechain.Reconstruct`, followed
-    by a check for ring punches. If ring punches are found it introduces gaps
-    for the residues with punched rings and tries to fill them with 
-    :func:`FillLoopsByDatabase` with *ring_punch_detection=2*.
+    This is a wrapper for :func:`promod3.modelling.ReconstructSidechains`, 
+    followed by a check for ring punches. If ring punches are found it 
+    introduces gaps for the residues with punched rings and tries to fill them 
+    with :func:`FillLoopsByDatabase` with *ring_punch_detection=2*.
 
     :param mhandle: Modelling handle on which to apply change.
     :type mhandle:  :class:`ModellingHandle`
@@ -192,7 +193,7 @@ def BuildSidechains(mhandle, merge_distance=4, fragment_db=None,
     '''
     prof = core.StaticRuntimeProfiler.StartScoped('pipeline::BuildSidechains')
     ost.LogInfo("Rebuilding sidechains.")
-    sidechain.Reconstruct(mhandle.model, keep_sidechains=True)
+    ReconstructSidechains(mhandle.model, keep_sidechains=True)
     # check for ring punches
     rings = GetRings(mhandle.model)
     ring_punches = GetRingPunches(rings, mhandle.model)
@@ -220,7 +221,7 @@ def BuildSidechains(mhandle, merge_distance=4, fragment_db=None,
         FillLoopsByDatabase(mhandle, fragment_db, structure_db,
                             torsion_sampler, ring_punch_detection=2)
         # re-build sidechains
-        sidechain.Reconstruct(mhandle.model, keep_sidechains=True)
+        ReconstructSidechains(mhandle.model, keep_sidechains=True)
         # restore gaps
         mhandle.gaps = StructuralGapList()
         for g in old_gaps:
diff --git a/sidechain/pymod/_reconstruct_sidechains.py b/modelling/pymod/_reconstruct_sidechains.py
similarity index 97%
rename from sidechain/pymod/_reconstruct_sidechains.py
rename to modelling/pymod/_reconstruct_sidechains.py
index b43b7027a0ab0d5082b7f851a48606d3c056f371..aaf1a0eba7b70091746350ca101f31991f5b32ed 100644
--- a/sidechain/pymod/_reconstruct_sidechains.py
+++ b/modelling/pymod/_reconstruct_sidechains.py
@@ -1,6 +1,5 @@
-from . import _sidechain as sidechain
 from ost import geom, mol, conop
-from promod3 import core
+from promod3 import core, sidechain
 
 ###############################################################################
 # helper functions
@@ -352,10 +351,11 @@ def _GetDisulfidBridges(frame_residues, cystein_indices, res_list, rotamer_libra
 
 ###############################################################################
 
-def Reconstruct(ent, keep_sidechains=False, build_disulfids=True,
-                rotamer_model="frm", consider_ligands=True, 
-                rotamer_library=None, optimize_subrotamers=True,
-                graph_max_complexity=100000000, graph_initial_epsilon=0.02):
+def ReconstructSidechains(ent, keep_sidechains=False, build_disulfids=True,
+                          rotamer_model="frm", consider_ligands=True, 
+                          rotamer_library=None, optimize_subrotamers=True,
+                          graph_max_complexity=100000000, 
+                          graph_initial_epsilon=0.02):
     '''Reconstruct sidechains for the given structure.
 
     :param ent: Structure for sidechain reconstruction. Note, that the sidechain
@@ -400,7 +400,7 @@ def Reconstruct(ent, keep_sidechains=False, build_disulfids=True,
                                  :meth:`RotamerGraph.TreeSolve`.
     :type graph_intial_epsilon:  :class:`float`
     '''
-    prof_name = 'sidechain::Reconstruct'
+    prof_name = 'modelling::ReconstructSidechains'
     prof = core.StaticRuntimeProfiler.StartScoped(prof_name)
 
     # setup settings
@@ -503,4 +503,4 @@ def Reconstruct(ent, keep_sidechains=False, build_disulfids=True,
                   res_handle.GetQualifiedName()
 
 # these methods will be exported into module
-__all__ = ('Reconstruct',)
+__all__ = ('ReconstructSidechains',)
diff --git a/modelling/pymod/_ring_punches.py b/modelling/pymod/_ring_punches.py
index 1df9561548d87fe4e6f85f36f4a5623da899e489..969aca39d8b7daabb2dc354350314bc18ac13f80 100644
--- a/modelling/pymod/_ring_punches.py
+++ b/modelling/pymod/_ring_punches.py
@@ -1,7 +1,8 @@
 '''Helper functions to deal with ring punchings.'''
 import ost
 from ost import geom
-from promod3 import sidechain, core
+from promod3 import core
+from _reconstruct_sidechains import ReconstructSidechains
 from collections import namedtuple
 
 def _AddRing(rings, res, atom_names):
@@ -218,7 +219,7 @@ def FilterCandidatesWithSC(candidates, model, gap, orig_indices=[]):
         bb_list = candidates[lc_idx]
         bb_list.InsertInto(cur_model.chains[chain_idx], start_resnum)
         # add sidechains and check for clashes
-        sidechain.Reconstruct(cur_model, keep_sidechains=True)
+        ReconstructSidechains(cur_model, keep_sidechains=True)
         models_new = cur_model.Select(myqueryin)
         rings_new = GetRings(models_new)
         check_punches = HasRingPunches(rings_out, models_new) or\
diff --git a/modelling/pymod/export_loop_closure.cc b/modelling/pymod/export_loop_closure.cc
index 1f819340ea40964405d202003a78c9119c47e2bd..a6aa1a0da761152f0fab494f034725b1746c7205 100644
--- a/modelling/pymod/export_loop_closure.cc
+++ b/modelling/pymod/export_loop_closure.cc
@@ -99,7 +99,7 @@ void export_loop_closure() {
   ;
 
   class_<AllAtomRelaxer, AllAtomRelaxerPtr>("AllAtomRelaxer", no_init)
-    .def(init<sidechain::SidechainReconstructionDataPtr,
+    .def(init<modelling::SidechainReconstructionDataPtr,
               loop::MmSystemCreatorPtr>(
          (arg("sc_data"), arg("mm_system_creator"))))
     .def("UpdatePositions", &AllAtomRelaxer::UpdatePositions, (arg("sc_data")))
diff --git a/modelling/pymod/export_model.cc b/modelling/pymod/export_model.cc
index c1b705e6f397f67b83c40a630959aa599c5e085a..db325e3d416a5b436da212f4ee0f550ac222a106 100644
--- a/modelling/pymod/export_model.cc
+++ b/modelling/pymod/export_model.cc
@@ -93,7 +93,7 @@ void WrapSetAllAtomSidechainEnv(ModellingHandle& mhandle,
   mhandle.all_atom_sidechain_env = env;
 }
 
-promod3::sidechain::SidechainReconstructorPtr
+promod3::modelling::SidechainReconstructorPtr
 WrapGetSidechainRec(ModellingHandle& mhandle) {
   if (!mhandle.sidechain_reconstructor) {
     throw promod3::Error("The sidechain_reconstructor must be properly "
@@ -103,7 +103,7 @@ WrapGetSidechainRec(ModellingHandle& mhandle) {
 }
 
 void WrapSetSidechainRec(ModellingHandle& mhandle,
-                         promod3::sidechain::SidechainReconstructorPtr sc_rec) {
+                         promod3::modelling::SidechainReconstructorPtr sc_rec) {
   mhandle.sidechain_reconstructor = sc_rec;
 }
 
diff --git a/sidechain/pymod/export_sidechain_reconstructor.cc b/modelling/pymod/export_sidechain_reconstructor.cc
similarity index 94%
rename from sidechain/pymod/export_sidechain_reconstructor.cc
rename to modelling/pymod/export_sidechain_reconstructor.cc
index b550dd262b642207b070d661a8aa1b3413e7c514..e55efdfac96dc871146f1ea7f6888568c09fd151 100644
--- a/sidechain/pymod/export_sidechain_reconstructor.cc
+++ b/modelling/pymod/export_sidechain_reconstructor.cc
@@ -1,9 +1,9 @@
 #include <boost/python.hpp>
 #include <promod3/core/export_helper.hh>
-#include <promod3/sidechain/sidechain_reconstructor.hh>
+#include <promod3/modelling/sidechain_reconstructor.hh>
 
 using namespace promod3;
-using namespace promod3::sidechain;
+using namespace promod3::modelling;
 using namespace boost::python;
 
 namespace {
@@ -105,9 +105,9 @@ void export_SidechainReconstructor() {
          (arg("start_resnum_list"), arg("num_residues_list"), arg("chain_idx_list")))
     .def("AttachEnvironment", WrapAttachEnvironment<bool>,
          (arg("env"), arg("use_frm")=true, arg("use_bbdep_lib")=true))
-    .def("AttachEnvironment", WrapAttachEnvironment<BBDepRotamerLibPtr>,
+    .def("AttachEnvironment", WrapAttachEnvironment<sidechain::BBDepRotamerLibPtr>,
          (arg("env"), arg("use_frm"), arg("rotamer_library")))
-    .def("AttachEnvironment", WrapAttachEnvironment<RotamerLibPtr>,
+    .def("AttachEnvironment", WrapAttachEnvironment<sidechain::RotamerLibPtr>,
          (arg("env"), arg("use_frm"), arg("rotamer_library")))
   ;
 }
diff --git a/modelling/pymod/wrap_modelling.cc b/modelling/pymod/wrap_modelling.cc
index 189db19076ad719ae1466579bb78a2ea7d0fbd5a..69f69a6b0bb621f9ec87412755c0742eb14c5efc 100644
--- a/modelling/pymod/wrap_modelling.cc
+++ b/modelling/pymod/wrap_modelling.cc
@@ -10,6 +10,7 @@ void export_monte_carlo();
 void export_rigid_blocks();
 void export_score_container();
 void export_scoring_weights();
+void export_SidechainReconstructor();
 void export_el_enumerador();
 
 BOOST_PYTHON_MODULE(_modelling)
@@ -24,5 +25,6 @@ BOOST_PYTHON_MODULE(_modelling)
   export_rigid_blocks();
   export_score_container();
   export_scoring_weights();
+  export_SidechainReconstructor();
   export_el_enumerador();
 }
diff --git a/modelling/src/CMakeLists.txt b/modelling/src/CMakeLists.txt
index 21619bf0e5ff25111d52dad95cbb2b8b0c694382..6dd633e24927c4b93dd6232df2ce07705a0d6203 100644
--- a/modelling/src/CMakeLists.txt
+++ b/modelling/src/CMakeLists.txt
@@ -16,6 +16,8 @@ set(MODELLING_SOURCES
   rigid_blocks.cc
   score_container.cc
   scoring_weights.cc
+  sidechain_reconstructor.cc
+  sidechain_env_listener.cc
   el_enumerador.cc
 )
 
@@ -37,6 +39,8 @@ set(MODELLING_HEADERS
   rigid_blocks.hh
   score_container.hh
   scoring_weights.hh
+  sidechain_reconstructor.hh
+  sidechain_env_listener.hh
   el_enumerador.hh
 )
 
diff --git a/modelling/src/all_atom_relaxer.hh b/modelling/src/all_atom_relaxer.hh
index dc7965c8736ecd61bebdfe4d7ebced6bb7ca3d1d..9235a13f7980d05b37a06d51ef09c41637bd39ed 100644
--- a/modelling/src/all_atom_relaxer.hh
+++ b/modelling/src/all_atom_relaxer.hh
@@ -2,7 +2,7 @@
 #define PROMOD3_MODELLING_ALL_ATOM_RELAXER_HH
 
 #include <promod3/loop/mm_system_creator.hh>
-#include <promod3/sidechain/sidechain_reconstructor.hh>
+#include <promod3/modelling/sidechain_reconstructor.hh>
 
 namespace promod3 { namespace modelling {
 
@@ -12,8 +12,8 @@ typedef boost::shared_ptr<AllAtomRelaxer> AllAtomRelaxerPtr;
 /// \brief Relax loops returned by SidechainReconstructor
 class AllAtomRelaxer {
   // for convenience
-  typedef sidechain::SidechainReconstructionData ScRecData;
-  typedef sidechain::SidechainReconstructionDataPtr ScRecDataPtr;
+  typedef SidechainReconstructionData ScRecData;
+  typedef SidechainReconstructionDataPtr ScRecDataPtr;
 public:
   // create relaxer for this data set (will be ready for Run)
   AllAtomRelaxer(ScRecDataPtr sc_data, loop::MmSystemCreatorPtr mm_sys_creator);
diff --git a/modelling/src/el_enumerador.cc b/modelling/src/el_enumerador.cc
index 35c13546c1a5445cf50355956a5046cd94870e29..980cb01183b83fad2b3db76f17820e24f859cc2f 100644
--- a/modelling/src/el_enumerador.cc
+++ b/modelling/src/el_enumerador.cc
@@ -1,6 +1,6 @@
 #include <promod3/modelling/el_enumerador.hh>
 #include <promod3/scoring/scoring_object_loader.hh>
-#include <promod3/sidechain/sidechain_reconstructor.hh>
+#include <promod3/modelling/sidechain_reconstructor.hh>
 #include <promod3/core/enumerator.hh>
 #include <promod3/core/graph.hh>
 #include <promod3/core/tree.hh>
@@ -135,8 +135,9 @@ ScorerContainer(const promod3::modelling::ModellingHandle& mhandle, bool all_ato
     aa_sc_env_ = promod3::loop::AllAtomEnvPtr(
       new promod3::loop::AllAtomEnv(mhandle.seqres));
     aa_sc_env_->SetInitialEnvironment(mhandle.model);
-    aa_sc_rec_ = promod3::sidechain::SidechainReconstructorPtr(
-      new promod3::sidechain::SidechainReconstructor(true, true, true, 18.0));
+    aa_sc_rec_ = promod3::modelling::SidechainReconstructorPtr(
+      new promod3::modelling::SidechainReconstructor(true, true, 
+                                                     true, 18.0));
     aa_sc_rec_->AttachEnvironment(*aa_sc_env_, false);
     aa_scorer_env_ = promod3::loop::AllAtomEnvPtr(
       new promod3::loop::AllAtomEnv(mhandle.seqres));
@@ -174,7 +175,7 @@ Real GetScore(const promod3::loop::BackboneList& bb_list,
                                                   start_resnum,
                                                   chain_idx);
   if(all_atom_){
-    promod3::sidechain::SidechainReconstructionDataPtr sc_rec_data = 
+    promod3::modelling::SidechainReconstructionDataPtr sc_rec_data = 
     aa_sc_rec_->Reconstruct(start_resnum, bb_list.size(), chain_idx);
     aa_scorer_env_->SetEnvironment(*(sc_rec_data->env_pos));
     score += aa_scorer_->CalculateLinearCombination(aa_weights_,
@@ -208,7 +209,7 @@ Real GetScore(const std::vector<promod3::loop::BackboneList*>& bb_list_ptrs,
       bb_list_sizes[i] = bb_list_ptrs[i]->size();
     }
 
-    promod3::sidechain::SidechainReconstructionDataPtr sc_rec_data = 
+    promod3::modelling::SidechainReconstructionDataPtr sc_rec_data = 
     aa_sc_rec_->Reconstruct(start_resnums, bb_list_sizes, chain_indices);
     aa_scorer_env_->SetEnvironment(*(sc_rec_data->env_pos));
 
@@ -252,7 +253,7 @@ promod3::scoring::BackboneScoreEnvPtr bb_env_;
 promod3::scoring::BackboneOverallScorerPtr bb_scorer_;
 
 promod3::loop::AllAtomEnvPtr aa_sc_env_;
-promod3::sidechain::SidechainReconstructorPtr aa_sc_rec_;
+promod3::modelling::SidechainReconstructorPtr aa_sc_rec_;
 
 promod3::loop::AllAtomEnvPtr aa_scorer_env_;
 promod3::scoring::AllAtomOverallScorerPtr aa_scorer_;
diff --git a/modelling/src/loop_candidate.cc b/modelling/src/loop_candidate.cc
index b3e728334797e4c22d56a0508f58f30e0557819c..49885a31c854a2fa4edec7558196c8ac21f07ac9 100644
--- a/modelling/src/loop_candidate.cc
+++ b/modelling/src/loop_candidate.cc
@@ -484,8 +484,8 @@ void LoopCandidates::CalculateAllAtomScores(
   loop::AllAtomEnvPtr aa_score_env = mhandle.all_atom_scorer_env;
   scoring::AllAtomOverallScorerPtr aa_scorer = mhandle.all_atom_scorer;
   loop::AllAtomEnvPtr aa_sc_env = mhandle.all_atom_sidechain_env;
-  sidechain::SidechainReconstructorPtr sc_rec = mhandle.sidechain_reconstructor;
-  sidechain::SidechainReconstructionDataPtr sc_result;
+  SidechainReconstructorPtr sc_rec = mhandle.sidechain_reconstructor;
+  SidechainReconstructionDataPtr sc_result;
 
   // prepare storage for all scores
   std::vector< std::vector<Real> > aa_scores(keys.size());
diff --git a/modelling/src/model.cc b/modelling/src/model.cc
index d4c79287bc349cc56b94cac9fbf8564c68d607af..491a2d9ad3f66a3d455bde3a641743ce8b3d930d 100644
--- a/modelling/src/model.cc
+++ b/modelling/src/model.cc
@@ -306,8 +306,8 @@ void SetupDefaultAllAtomScoring(ModellingHandle& mhandle){
   // setup sidechaining needed for scoring
   loop::AllAtomEnvPtr env_sc(new loop::AllAtomEnv(mhandle.seqres));
   env_sc->SetInitialEnvironment(mhandle.model);
-  sidechain::SidechainReconstructorPtr sc_rec;
-  sc_rec.reset(new sidechain::SidechainReconstructor);
+  SidechainReconstructorPtr sc_rec;
+  sc_rec.reset(new SidechainReconstructor);
   sc_rec->AttachEnvironment(*env_sc);
 
   // set mhandle values
diff --git a/modelling/src/model.hh b/modelling/src/model.hh
index 58e81493452c64dcb2901d0dc9eaeef114ba7e84..e42a2c8db6ee029ad4f7547faf6511b9f5be4fd2 100644
--- a/modelling/src/model.hh
+++ b/modelling/src/model.hh
@@ -12,7 +12,7 @@
 #include <promod3/scoring/all_atom_overall_scorer.hh>
 #include <promod3/scoring/backbone_overall_scorer.hh>
 #include <promod3/scoring/backbone_score_base.hh>
-#include <promod3/sidechain/sidechain_reconstructor.hh>
+#include <promod3/modelling/sidechain_reconstructor.hh>
 
 namespace promod3 { namespace modelling {
 
@@ -45,7 +45,7 @@ struct ModellingHandle {
   promod3::loop::AllAtomEnvPtr all_atom_scorer_env; // tmp only for scoring
   promod3::scoring::AllAtomOverallScorerPtr all_atom_scorer;
   promod3::loop::AllAtomEnvPtr all_atom_sidechain_env;
-  promod3::sidechain::SidechainReconstructorPtr sidechain_reconstructor;
+  SidechainReconstructorPtr sidechain_reconstructor;
 };
 
 // see Python doc
diff --git a/sidechain/src/sidechain_env_listener.cc b/modelling/src/sidechain_env_listener.cc
similarity index 83%
rename from sidechain/src/sidechain_env_listener.cc
rename to modelling/src/sidechain_env_listener.cc
index 89519e04bece2de9fd057828019fe6c7f6b44eeb..18a1297eef220f6b2aa55227a17038b918216282 100644
--- a/sidechain/src/sidechain_env_listener.cc
+++ b/modelling/src/sidechain_env_listener.cc
@@ -1,8 +1,8 @@
-#include <promod3/sidechain/sidechain_env_listener.hh>
+#include <promod3/modelling/sidechain_env_listener.hh>
 #include <promod3/sidechain/sidechain_object_loader.hh>
 #include <promod3/core/runtime_profiling.hh>
 
-namespace promod3 { namespace sidechain {
+namespace promod3 { namespace modelling {
 
 SidechainEnvListener::SidechainEnvListener(bool use_frm, bool use_bbdep_lib,
                                            bool add_cyd_rotamers,
@@ -17,13 +17,13 @@ SidechainEnvListener::SidechainEnvListener(bool use_frm, bool use_bbdep_lib,
     throw promod3::Error("Cannot use PenultimateLib with FRMRotamers!");
   }
   // setup library
-  if (use_bbdep_lib_) bbdep_library_ = LoadDunbrackLib();
-  else library_ = LoadPenultimateLib();
+  if (use_bbdep_lib_) bbdep_library_ = sidechain::LoadDunbrackLib();
+  else library_ = sidechain::LoadPenultimateLib();
 
 }
 
 SidechainEnvListener::SidechainEnvListener(bool use_frm,
-                                           BBDepRotamerLibPtr bbdep_library,
+                                           sidechain::BBDepRotamerLibPtr bbdep_library,
                                            bool add_cyd_rotamers,
                                            bool all_rotamers)
                                            : all_rotamers_(all_rotamers)
@@ -33,7 +33,8 @@ SidechainEnvListener::SidechainEnvListener(bool use_frm,
                                            , bbdep_library_(bbdep_library)
                                            , env_(20.0), env_data_(NULL) { }
 
-SidechainEnvListener::SidechainEnvListener(bool use_frm, RotamerLibPtr library,
+SidechainEnvListener::SidechainEnvListener(bool use_frm, 
+                                           sidechain::RotamerLibPtr library,
                                            bool add_cyd_rotamers,
                                            bool all_rotamers)
                                            : all_rotamers_(all_rotamers)
@@ -80,20 +81,23 @@ void SidechainEnvListener::Init(const loop::AllAtomEnv& base_env) {
   }
 
   // set rotamer IDs (fixed based on AA in all_pos)
-  r_id_.assign(num_residues, ALA);
+  r_id_.assign(num_residues, sidechain::ALA);
   for (uint res_idx = 0; res_idx < num_residues; ++res_idx) {
-    r_id_[res_idx] = AAToRotID(all_pos->GetAA(res_idx));
+    r_id_[res_idx] = sidechain::AAToRotID(all_pos->GetAA(res_idx));
   }
 
   // initialize rotamer data (all false / NULL for now)
   phi_angle_.assign(num_residues, 0);
   psi_angle_.assign(num_residues, 0);
-  bb_frame_residue_.assign(num_residues, FrameResiduePtr());
-  sc_frame_residue_.assign(num_residues, FrameResiduePtr());
-  if (use_frm_) frm_rotamer_group_.assign(num_residues, FRMRotamerGroupPtr());
-  else          rrm_rotamer_group_.assign(num_residues, RRMRotamerGroupPtr());
+  bb_frame_residue_.assign(num_residues, sidechain::FrameResiduePtr());
+  sc_frame_residue_.assign(num_residues, sidechain::FrameResiduePtr());
+  if (use_frm_) {
+    frm_rotamer_group_.assign(num_residues, sidechain::FRMRotamerGroupPtr());
+  } else {         
+    rrm_rotamer_group_.assign(num_residues, sidechain::RRMRotamerGroupPtr());
+  }
   if (add_cyd_rotamers_) {
-    cyd_frm_rotamer_group_.assign(num_residues, FRMRotamerGroupPtr());
+    cyd_frm_rotamer_group_.assign(num_residues, sidechain::FRMRotamerGroupPtr());
   }
 }
 
@@ -132,7 +136,7 @@ void SidechainEnvListener::UpdateEnvironment(
 
 void SidechainEnvListener::SetResidue_(loop::ConstAllAtomPositionsPtr all_pos,
                                        const uint res_idx) {
-  const RotamerID r_id = r_id_[res_idx];
+  const sidechain::RotamerID r_id = r_id_[res_idx];
   // get atom indices for backbone
   const uint idx_N  = all_pos->GetIndex(res_idx, loop::BB_N_INDEX);
   const uint idx_CA = all_pos->GetIndex(res_idx, loop::BB_CA_INDEX);
@@ -141,7 +145,7 @@ void SidechainEnvListener::SetResidue_(loop::ConstAllAtomPositionsPtr all_pos,
   const uint idx_CB = all_pos->GetIndex(res_idx, loop::BB_CB_INDEX);
   const bool bb_set =   all_pos->IsSet(idx_N) && all_pos->IsSet(idx_CA)
                      && all_pos->IsSet(idx_C) && all_pos->IsSet(idx_O)
-                     && (r_id == GLY || all_pos->IsSet(idx_CB));
+                     && (r_id == sidechain::GLY || all_pos->IsSet(idx_CB));
   const bool all_set = all_pos->IsAllSet(res_idx);
   // we only add data if BB is set
   if (bb_set) {
@@ -151,17 +155,17 @@ void SidechainEnvListener::SetResidue_(loop::ConstAllAtomPositionsPtr all_pos,
     const geom::Vec3& c_pos  = all_pos->GetPos(idx_C);
     const geom::Vec3& o_pos  = all_pos->GetPos(idx_O);
     geom::Vec3 cb_pos;
-    if (r_id != GLY)  cb_pos = all_pos->GetPos(idx_CB);
+    if (r_id != sidechain::GLY)  cb_pos = all_pos->GetPos(idx_CB);
     
     // update spatial organizer
     if (bb_frame_residue_[res_idx]) {
       // update
       const geom::Vec3 old_pos = env_data_[res_idx].pos;
-      env_data_[res_idx].pos = (r_id == GLY) ? ca_pos : cb_pos;
+      env_data_[res_idx].pos = (r_id == sidechain::GLY) ? ca_pos : cb_pos;
       env_.Reset(&env_data_[res_idx], old_pos, env_data_[res_idx].pos);
     } else {
       // set
-      env_data_[res_idx].pos = (r_id == GLY) ? ca_pos : cb_pos;
+      env_data_[res_idx].pos = (r_id == sidechain::GLY) ? ca_pos : cb_pos;
       env_.Add(&env_data_[res_idx], env_data_[res_idx].pos);
     }
 
@@ -181,7 +185,7 @@ void SidechainEnvListener::SetResidue_(loop::ConstAllAtomPositionsPtr all_pos,
                                                        c_ter_[res_idx]);
     
     // do we have a sidechain?
-    if (r_id != ALA && r_id != GLY) {
+    if (r_id != sidechain::ALA && r_id != sidechain::GLY) {
       // set sidechain frame res. if all set
       if (all_set) {
         sc_frame_residue_[res_idx]
@@ -198,9 +202,9 @@ void SidechainEnvListener::SetResidue_(loop::ConstAllAtomPositionsPtr all_pos,
         else          rrm_rotamer_group_[res_idx].reset();
       }
       // set extra cystein rotamer if needed
-      if (add_cyd_rotamers_ && r_id == CYS) {
+      if (add_cyd_rotamers_ && r_id == sidechain::CYS) {
         CreateRotamerGroup(cyd_frm_rotamer_group_[res_idx], n_pos, ca_pos,
-                           cb_pos, CYD, res_idx);
+                           cb_pos, sidechain::CYD, res_idx);
       }
     }
   } else {
@@ -223,17 +227,17 @@ void SidechainEnvListener::SetRotamer_(loop::ConstAllAtomPositionsPtr all_pos,
                                        const geom::Vec3& n_pos,
                                        const geom::Vec3& ca_pos,
                                        const geom::Vec3& cb_pos,
-                                       const RotamerID r_id,
+                                       const sidechain::RotamerID r_id,
                                        const uint res_idx) {
   // add rotamer anyways -> potentially need to change ID
-  RotamerID rg_r_id = r_id;
-  if (r_id == CYS) rg_r_id = CYH;
-  if (r_id == PRO) {
+  sidechain::RotamerID rg_r_id = r_id;
+  if (r_id == sidechain::CYS) rg_r_id = sidechain::CYH;
+  if (r_id == sidechain::PRO) {
     // check omega torsion
     Real omega = 4;
     if (!n_ter_[res_idx]) omega = all_pos->GetOmegaTorsion(res_idx, 4);
     if (omega != 4) {
-      rg_r_id = (std::abs(omega) < 1.57) ? CPR : TPR;
+      rg_r_id = (std::abs(omega) < 1.57) ? sidechain::CPR : sidechain::TPR;
     }
   }
   // note: most time spent here to construct new and destruct old
diff --git a/sidechain/src/sidechain_env_listener.hh b/modelling/src/sidechain_env_listener.hh
similarity index 74%
rename from sidechain/src/sidechain_env_listener.hh
rename to modelling/src/sidechain_env_listener.hh
index ad0b411f0ef343e3691b28cf0490aad34b10c0b2..a35a0b36b8f18f7a497ec8c27f70739fda4576bf 100644
--- a/sidechain/src/sidechain_env_listener.hh
+++ b/modelling/src/sidechain_env_listener.hh
@@ -10,7 +10,7 @@
 #include <promod3/sidechain/bb_dep_rotamer_lib.hh>
 #include <promod3/sidechain/scwrl_rotamer_constructor.hh>
 
-namespace promod3 { namespace sidechain {
+namespace promod3 { namespace modelling {
 
 class SidechainEnvListener;
 typedef boost::shared_ptr<SidechainEnvListener> SidechainEnvListenerPtr;
@@ -31,9 +31,9 @@ public:
   // construct: global options can only be set here!
   SidechainEnvListener(bool use_frm = true, bool use_bbdep_lib = true,
                        bool add_cyd_rotamers = true, bool all_rotamers = false);
-  SidechainEnvListener(bool use_frm, BBDepRotamerLibPtr bbdep_library,
+  SidechainEnvListener(bool use_frm, sidechain::BBDepRotamerLibPtr bbdep_library,
                        bool add_cyd_rotamers = true, bool all_rotamers = false);
-  SidechainEnvListener(bool use_frm, RotamerLibPtr library,
+  SidechainEnvListener(bool use_frm, sidechain::RotamerLibPtr library,
                        bool add_cyd_rotamers = true, bool all_rotamers = false);
 
   // AllAtomEnvListener interface
@@ -61,62 +61,67 @@ public:
   uint GetNumResidues() const { return phi_angle_.size(); }
   bool IsNTerminal(uint res_idx) const { return n_ter_[res_idx]; }
   bool IsCTerminal(uint res_idx) const { return c_ter_[res_idx]; }
-  RotamerID GetRotamerID(uint res_idx) const { return r_id_[res_idx]; }
+  sidechain::RotamerID GetRotamerID(uint res_idx) const { return r_id_[res_idx]; }
   Real GetPhiAngle(uint res_idx) const { return phi_angle_[res_idx]; }
   Real GetPsiAngle(uint res_idx) const { return psi_angle_[res_idx]; }
-  FrameResiduePtr GetBbFrameResidue(uint res_idx) const {
+  sidechain::FrameResiduePtr GetBbFrameResidue(uint res_idx) const {
     return bb_frame_residue_[res_idx];
   }
-  FrameResiduePtr GetScFrameResidue(uint res_idx) const {
+  sidechain::FrameResiduePtr GetScFrameResidue(uint res_idx) const {
     return sc_frame_residue_[res_idx];
   }
-  FRMRotamerGroupPtr GetFRMRotamerGroup(uint res_idx) const {
+  sidechain::FRMRotamerGroupPtr GetFRMRotamerGroup(uint res_idx) const {
     if (!use_frm_) {
       throw promod3::Error("SidechainEnvListener doesn't have FRMRotamers!");
     }
     return frm_rotamer_group_[res_idx];
   }
-  RRMRotamerGroupPtr GetRRMRotamerGroup(uint res_idx) const {
+  sidechain::RRMRotamerGroupPtr GetRRMRotamerGroup(uint res_idx) const {
     if (use_frm_) {
       throw promod3::Error("SidechainEnvListener doesn't have RRMRotamers!");
     }
     return rrm_rotamer_group_[res_idx];
   }
-  FRMRotamerGroupPtr GetCydFRMRotamerGroup(uint res_idx) const {
+  sidechain::FRMRotamerGroupPtr GetCydFRMRotamerGroup(uint res_idx) const {
     return cyd_frm_rotamer_group_[res_idx];
   }
-  RRMRotamerGroupPtr GetCydRRMRotamerGroup(uint res_idx) const {
+  sidechain::RRMRotamerGroupPtr GetCydRRMRotamerGroup(uint res_idx) const {
     // typically all disulfid evaluations are done with FRM disulfids
     // (even when use_frm is false), so this is just a nasty fallback
     uint num_rotamers = cyd_frm_rotamer_group_[res_idx]->size();
-    std::vector<RRMRotamerPtr> rrm_rotamers(num_rotamers);
+    std::vector<sidechain::RRMRotamerPtr> rrm_rotamers(num_rotamers);
     for(uint i = 0; i < num_rotamers; ++i){
       rrm_rotamers[i] = (*cyd_frm_rotamer_group_[res_idx])[i]->ToRRMRotamer(); 
     }
-    RRMRotamerGroupPtr p(new RRMRotamerGroup(rrm_rotamers, res_idx));
+    sidechain::RRMRotamerGroupPtr 
+    p(new sidechain::RRMRotamerGroup(rrm_rotamers, res_idx));
     
     return p;
   }
   
   // for convenience: use overload to set rot_group based on type
-  void GetRotamerGroup(FRMRotamerGroupPtr& rot_group, uint res_idx) const {
+  void GetRotamerGroup(sidechain::FRMRotamerGroupPtr& rot_group, 
+                       uint res_idx) const {
     rot_group = GetFRMRotamerGroup(res_idx);
   }
-  void GetRotamerGroup(RRMRotamerGroupPtr& rot_group, uint res_idx) const {
+  void GetRotamerGroup(sidechain::RRMRotamerGroupPtr& rot_group, 
+                       uint res_idx) const {
     rot_group = GetRRMRotamerGroup(res_idx);
   }
-  void GetCydRotamerGroup(FRMRotamerGroupPtr& rot_group, uint res_idx) const {
+  void GetCydRotamerGroup(sidechain::FRMRotamerGroupPtr& rot_group, 
+                          uint res_idx) const {
     rot_group = GetCydFRMRotamerGroup(res_idx);
   }
-  void GetCydRotamerGroup(RRMRotamerGroupPtr& rot_group, uint res_idx) const {
+  void GetCydRotamerGroup(sidechain::RRMRotamerGroupPtr& rot_group, 
+                          uint res_idx) const {
     rot_group = GetCydRRMRotamerGroup(res_idx);
   }
 
   // create a rotamer group based on internal settings (no use_frm_ check!)
-  void CreateRotamerGroup(FRMRotamerGroupPtr& rot_group,
+  void CreateRotamerGroup(sidechain::FRMRotamerGroupPtr& rot_group,
                           const geom::Vec3& n_pos, const geom::Vec3& ca_pos,
-                          const geom::Vec3& cb_pos, const RotamerID r_id,
-                          const uint res_idx) {
+                          const geom::Vec3& cb_pos, 
+                          const sidechain::RotamerID r_id, const uint res_idx) {
     if (use_bbdep_lib_) {
       rot_group = rot_constructor_.ConstructFRMRotamerGroup(n_pos, ca_pos, 
                                                             cb_pos, r_id, 
@@ -131,9 +136,11 @@ public:
     }
     rot_constructor_.AssignInternalEnergies(rot_group);
   }
-  void CreateRotamerGroup(RRMRotamerGroupPtr& rot_group,
-                          const geom::Vec3& n_pos, const geom::Vec3& ca_pos,
-                          const geom::Vec3& cb_pos, const RotamerID r_id,
+  void CreateRotamerGroup(sidechain::RRMRotamerGroupPtr& rot_group,
+                          const geom::Vec3& n_pos, 
+                          const geom::Vec3& ca_pos,
+                          const geom::Vec3& cb_pos, 
+                          const sidechain::RotamerID r_id,
                           const uint res_idx) {
     if (use_bbdep_lib_) {
       rot_group = rot_constructor_.ConstructRRMRotamerGroup(n_pos, ca_pos, 
@@ -157,7 +164,7 @@ private:
   void SetResidue_(loop::ConstAllAtomPositionsPtr all_pos, const uint res_idx);
   void SetRotamer_(loop::ConstAllAtomPositionsPtr all_pos,
                    const geom::Vec3& n_pos, const geom::Vec3& ca_pos,
-                   const geom::Vec3& cb_pos, const RotamerID r_id,
+                   const geom::Vec3& cb_pos, const sidechain::RotamerID r_id,
                    const uint res_idx);
 
   // global data
@@ -166,15 +173,15 @@ private:
   bool use_frm_;       // use FRMRotamerGroup instead of RRMRotamerGroup
   bool use_bbdep_lib_; // use BBDepRotamerLib instead of RotamerLib
   bool add_cyd_rotamers_;  // build extra rotamers with r_id = CYD for cysteins
-  RotamerLibPtr library_;
-  BBDepRotamerLibPtr bbdep_library_;
-  SCWRLRotamerConstructor rot_constructor_;
+  sidechain::RotamerLibPtr library_;
+  sidechain::BBDepRotamerLibPtr bbdep_library_;
+  sidechain::SCWRLRotamerConstructor rot_constructor_;
   ScCBetaSpatialOrganizer env_;
 
   // fixed data per residue (same numbering as base_env.GetAllPosData())
   std::vector<bool> n_ter_;
   std::vector<bool> c_ter_;
-  std::vector<RotamerID> r_id_;
+  std::vector<sidechain::RotamerID> r_id_;
   
   // dynamic data per residue
   // -> any data only set if BB set ("if (bb_frame_residue_[res_idx]) ...")
@@ -185,14 +192,14 @@ private:
   ScCBetaSpatialOrganizerItem* env_data_;
   std::vector<Real> phi_angle_;
   std::vector<Real> psi_angle_;
-  std::vector<FrameResiduePtr> bb_frame_residue_;
-  std::vector<FrameResiduePtr> sc_frame_residue_;
-  std::vector<FRMRotamerGroupPtr> frm_rotamer_group_;
-  std::vector<RRMRotamerGroupPtr> rrm_rotamer_group_;
+  std::vector<sidechain::FrameResiduePtr> bb_frame_residue_;
+  std::vector<sidechain::FrameResiduePtr> sc_frame_residue_;
+  std::vector<sidechain::FRMRotamerGroupPtr> frm_rotamer_group_;
+  std::vector<sidechain::RRMRotamerGroupPtr> rrm_rotamer_group_;
 
   // extra rotamer groups (r_id == CYD) for cysteins to handle disulfid bridges
   // -> constructed for res. with r_id == CYS indep. of all_rotamers_ setting!
-  std::vector<FRMRotamerGroupPtr> cyd_frm_rotamer_group_;
+  std::vector<sidechain::FRMRotamerGroupPtr> cyd_frm_rotamer_group_;
 };
 
 }} // ns
diff --git a/sidechain/src/sidechain_reconstructor.cc b/modelling/src/sidechain_reconstructor.cc
similarity index 89%
rename from sidechain/src/sidechain_reconstructor.cc
rename to modelling/src/sidechain_reconstructor.cc
index 0fa9cfb9dae8e9f0e2c61ed728ea3e5a69cd5dab..8ab263f3b82f5674a5ce2bf9e8aa7a17ef39e80d 100644
--- a/sidechain/src/sidechain_reconstructor.cc
+++ b/modelling/src/sidechain_reconstructor.cc
@@ -1,11 +1,11 @@
-#include <promod3/sidechain/sidechain_reconstructor.hh>
+#include <promod3/modelling/sidechain_reconstructor.hh>
 #include <promod3/sidechain/disulfid.hh>
 #include <promod3/sidechain/rotamer_graph.hh>
 #include <promod3/sidechain/subrotamer_optimizer.hh>
 #include <promod3/core/message.hh>
 #include <promod3/core/runtime_profiling.hh>
 
-namespace promod3 { namespace sidechain {
+namespace promod3 { namespace modelling {
 
 namespace {
 
@@ -101,7 +101,8 @@ void SidechainReconstructor::AttachEnvironment(loop::AllAtomEnv& env,
 }
 void SidechainReconstructor::AttachEnvironment(loop::AllAtomEnv& env,
                                                bool use_frm,
-                                               BBDepRotamerLibPtr bbdep_library) {
+                                               sidechain::BBDepRotamerLibPtr 
+                                               bbdep_library) {
   loop::AllAtomEnvListenerPtr tst = env.GetListener("SidechainEnvListener");
   if (tst) {
     env_ = boost::dynamic_pointer_cast<SidechainEnvListener>(tst);
@@ -116,7 +117,8 @@ void SidechainReconstructor::AttachEnvironment(loop::AllAtomEnv& env,
 }
 void SidechainReconstructor::AttachEnvironment(loop::AllAtomEnv& env,
                                                bool use_frm,
-                                               RotamerLibPtr library) {
+                                               sidechain::RotamerLibPtr 
+                                               library) {
   loop::AllAtomEnvListenerPtr tst = env.GetListener("SidechainEnvListener");
   if (tst) {
     env_ = boost::dynamic_pointer_cast<SidechainEnvListener>(tst);
@@ -173,8 +175,8 @@ SidechainReconstructor::ReconstructFromIndices(const std::vector<uint>& indices)
   }
 
   // solve system
-  if (env_->HasFRMRotamers()) SolveSystem_<FRMRotamerGroup>(res);
-  else                        SolveSystem_<RRMRotamerGroup>(res);
+  if (env_->HasFRMRotamers()) SolveSystem_<sidechain::FRMRotamerGroup>(res);
+  else                        SolveSystem_<sidechain::RRMRotamerGroup>(res);
   return res;
 }
 
@@ -204,7 +206,7 @@ void SidechainReconstructor::SetEnvData_(loop::AllAtomEnv& env) {
 template<typename RotamerGroup> void SidechainReconstructor::BuildDisulfids_(
                        SidechainReconstructionDataPtr res,
                        std::vector<uint>& cys_indices,
-                       std::vector<FrameResiduePtr>& frame_residues,
+                       std::vector<sidechain::FrameResiduePtr>& frame_residues,
                        std::vector<bool>& has_sidechain) const {
   // setup
   std::vector<uint>& res_indices = res->env_pos->res_indices;
@@ -213,7 +215,7 @@ template<typename RotamerGroup> void SidechainReconstructor::BuildDisulfids_(
   loop::AllAtomPositions& out_pos = *(res->env_pos->all_pos);
 
   // collect rotamers and data required to resolve the disulfid bridges
-  FramePtr frame(new Frame(frame_residues));
+  sidechain::FramePtr frame(new sidechain::Frame(frame_residues));
   std::vector<RotamerGroupPtr> cys_rotamer_groups;
   std::vector<geom::Vec3> ca_pos;
   std::vector<geom::Vec3> cb_pos;
@@ -285,7 +287,8 @@ template<typename RotamerGroup> void SidechainReconstructor::BuildDisulfids_(
       if(is_bonded[i] == 0){
         const uint idx = cys_with_rot_groups[i];
         const uint global_idx = res_indices[idx];
-        FrameResiduePtr frame_res = env_->GetScFrameResidue(global_idx);
+        sidechain::FrameResiduePtr frame_res = 
+        env_->GetScFrameResidue(global_idx);
         if(frame_res) {
           frame_residues.push_back(frame_res);
           has_sidechain[idx] = true;
@@ -322,19 +325,21 @@ void SidechainReconstructor::CollectRotamerGroups_(
   }
 }
 
-void ApplySubrotamerOptimization(std::vector<FRMRotamerGroupPtr>& rotamer_groups,
+void ApplySubrotamerOptimization(std::vector<sidechain::FRMRotamerGroupPtr>& 
+                                 rotamer_groups,
                                  const std::vector<int>& solution) {
 
   uint num_rotamer_groups = rotamer_groups.size();
 
-  std::vector<FRMRotamerPtr> rotamers(rotamer_groups.size());
+  std::vector<sidechain::FRMRotamerPtr> rotamers(rotamer_groups.size());
   for(uint i = 0; i < num_rotamer_groups; ++i){
     rotamers[i] = (*rotamer_groups[i])[solution[i]];
   }
-  SubrotamerOptimizer(rotamers);
+  sidechain::SubrotamerOptimizer(rotamers);
 }
 
-void ApplySubrotamerOptimization(std::vector<RRMRotamerGroupPtr>& rotamer_groups,
+void ApplySubrotamerOptimization(std::vector<sidechain::RRMRotamerGroupPtr>& 
+                                 rotamer_groups,
                                  const std::vector<int>& solution) {
   //there's nothing to do... 
 }
@@ -352,16 +357,16 @@ void SidechainReconstructor::SolveSystem_(
   loop::AllAtomPositions& out_pos = *(res->env_pos->all_pos);
   
   // collect frame residues and cysteins (if needed)
-  std::vector<FrameResiduePtr> frame_residues;
+  std::vector<sidechain::FrameResiduePtr> frame_residues;
   std::vector<bool> has_sidechain(res_indices.size(), false);
   std::vector<uint> cys_indices;
   for (uint i = 0; i < res_indices.size(); ++i) {
     const uint res_idx = res_indices[i];
     // add backbone frame residue if available
-    FrameResiduePtr frame_res = env_->GetBbFrameResidue(res_idx);
+    sidechain::FrameResiduePtr frame_res = env_->GetBbFrameResidue(res_idx);
     if (frame_res) frame_residues.push_back(frame_res);
     // check sidechain
-    if (build_disulfids_ && env_->GetRotamerID(res_idx) == CYS) {
+    if (build_disulfids_ && env_->GetRotamerID(res_idx) == sidechain::CYS) {
       cys_indices.push_back(i);
     } else if (keep_sidechains_) {
       frame_res = env_->GetScFrameResidue(res_idx);
@@ -376,8 +381,8 @@ void SidechainReconstructor::SolveSystem_(
   res->disulfid_bridges.clear();
   if (build_disulfids_) {
     // we use the FRM rotamer model in any case for reconstructing disulfids
-    BuildDisulfids_<FRMRotamerGroup>(res, cys_indices, frame_residues,
-                                     has_sidechain);
+    BuildDisulfids_<sidechain::FRMRotamerGroup>(res, cys_indices, 
+                                                frame_residues, has_sidechain);
   }
   
   // collect rotamers
@@ -386,14 +391,15 @@ void SidechainReconstructor::SolveSystem_(
   CollectRotamerGroups_(res, rotamer_groups, has_sidechain);
 
   // set frame energies in rotamers (note: internal energies are precomputed)
-  FramePtr frame(new Frame(frame_residues));
+  sidechain::FramePtr frame(new sidechain::Frame(frame_residues));
   for (uint i = 0; i < rotamer_groups.size(); ++i) {
     rotamer_groups[i]->SetFrameEnergy(frame);
     rotamer_groups[i]->ApplySelfEnergyThresh();
   }
 
   // solve graph
-  RotamerGraphPtr graph = RotamerGraph::CreateFromList(rotamer_groups);
+  sidechain::RotamerGraphPtr graph = 
+  sidechain::RotamerGraph::CreateFromList(rotamer_groups);
   std::pair<std::vector<int>,Real> solution = 
     graph->TreeSolve(graph_max_complexity_, graph_intial_epsilon_);
 
diff --git a/sidechain/src/sidechain_reconstructor.hh b/modelling/src/sidechain_reconstructor.hh
similarity index 94%
rename from sidechain/src/sidechain_reconstructor.hh
rename to modelling/src/sidechain_reconstructor.hh
index bd405ec35454703603f16a38cd1015ecf5fd369c..565b830a0d5ba40236310aa79d8026193e75ef67 100644
--- a/sidechain/src/sidechain_reconstructor.hh
+++ b/modelling/src/sidechain_reconstructor.hh
@@ -2,9 +2,9 @@
 #define PM3_SIDECHAIN_RECONSTRUCTOR_HH
 
 #include <promod3/loop/all_atom_env.hh>
-#include <promod3/sidechain/sidechain_env_listener.hh>
+#include <promod3/modelling/sidechain_env_listener.hh>
 
-namespace promod3 { namespace sidechain {
+namespace promod3 { namespace modelling {
 
 class SidechainReconstructionData;
 class SidechainReconstructor;
@@ -66,9 +66,9 @@ public:
   void AttachEnvironment(loop::AllAtomEnv& env, bool use_frm = true,
                          bool use_bbdep_lib = true);
   void AttachEnvironment(loop::AllAtomEnv& env, bool use_frm,
-                         BBDepRotamerLibPtr bbdep_library);
+                         sidechain::BBDepRotamerLibPtr bbdep_library);
   void AttachEnvironment(loop::AllAtomEnv& env, bool use_frm,
-                         RotamerLibPtr library);
+                         sidechain::RotamerLibPtr library);
 
 private:
 
@@ -87,7 +87,7 @@ private:
   template<typename RotamerGroup>
   void BuildDisulfids_(SidechainReconstructionDataPtr res,
                        std::vector<uint>& cys_indices,
-                       std::vector<FrameResiduePtr>& frame_residues,
+                       std::vector<sidechain::FrameResiduePtr>& frame_residues,
                        std::vector<bool>& has_sidechain) const;
 
   // collects rotamers for residues with has_sidechain[i] = false
diff --git a/modelling/tests/CMakeLists.txt b/modelling/tests/CMakeLists.txt
index 5d222f9ccef8a87f16fed2b37f0977979adc1d35..41792a8b7cd90a6cec0593b801e8cd39df877696 100644
--- a/modelling/tests/CMakeLists.txt
+++ b/modelling/tests/CMakeLists.txt
@@ -4,8 +4,10 @@ set(MODELLING_UNIT_TESTS
   test_modelling.py
   test_pipeline.py
   test_ring_punches.py
+  test_sidechain_reconstruction.py
   test_loop_candidates.cc
   test_loop_closing.cc
+  test_sidechain_reconstructor.cc
   tests.cc
 )
 
@@ -19,7 +21,11 @@ set(MODELLING_TEST_DATA
   data/1crn_final.pdb
   data/1crn_rec.pdb
   data/1crn_sc.pdb
+  data/1crn_sc_test.pdb
   data/1CRNA.hhm
+  data/1eye.pdb
+  data/1eye_rec.pdb
+  data/1eye_sc_test.pdb
   data/1ITX-A-11_sidechain.pdb
   data/1K5C-A-16_clash.pdb
   data/1mcg.pdb
diff --git a/sidechain/tests/data/1crn_sc_test.pdb b/modelling/tests/data/1crn_sc_test.pdb
similarity index 100%
rename from sidechain/tests/data/1crn_sc_test.pdb
rename to modelling/tests/data/1crn_sc_test.pdb
diff --git a/sidechain/tests/data/1eye.pdb b/modelling/tests/data/1eye.pdb
similarity index 100%
rename from sidechain/tests/data/1eye.pdb
rename to modelling/tests/data/1eye.pdb
diff --git a/sidechain/tests/data/1eye_rec.pdb b/modelling/tests/data/1eye_rec.pdb
similarity index 100%
rename from sidechain/tests/data/1eye_rec.pdb
rename to modelling/tests/data/1eye_rec.pdb
diff --git a/sidechain/tests/data/1eye_sc_test.pdb b/modelling/tests/data/1eye_sc_test.pdb
similarity index 100%
rename from sidechain/tests/data/1eye_sc_test.pdb
rename to modelling/tests/data/1eye_sc_test.pdb
diff --git a/modelling/tests/test_ring_punches.py b/modelling/tests/test_ring_punches.py
index 1a41db71628502426970e4b64955a67028c1d2ba..901cfbc04e10a7dedbb7e7ebb3f5e1e738cacd2a 100644
--- a/modelling/tests/test_ring_punches.py
+++ b/modelling/tests/test_ring_punches.py
@@ -3,7 +3,7 @@ Unit tests to detect ring punchings.
 """
 import unittest
 import ost
-from promod3 import modelling, loop, sidechain
+from promod3 import modelling, loop
 
 class RingPunchTests(unittest.TestCase):
     def testRings(self):
@@ -24,7 +24,7 @@ class RingPunchTests(unittest.TestCase):
         self.assertEqual(str(rings[2].residue), "A.PRO7")
         self.assertEqual(str(rings[3].residue), "A.PRO8")
         # add sidechains
-        sidechain.Reconstruct(model, keep_sidechains=False)
+        modelling.ReconstructSidechains(model, keep_sidechains=False)
         rings = modelling.GetRings(model)
         self.assertEqual(len(rings), 9)
         self.assertAlmostEqual(rings[0].radius, 1.31, places=1)
diff --git a/sidechain/tests/test_sidechain.py b/modelling/tests/test_sidechain_reconstruction.py
similarity index 89%
rename from sidechain/tests/test_sidechain.py
rename to modelling/tests/test_sidechain_reconstruction.py
index 9211fbfc40b97739b3542f6ccb995d1c2879f183..37c82e652036a155f409d6f1e7ce4c9f45e88d4d 100644
--- a/sidechain/tests/test_sidechain.py
+++ b/modelling/tests/test_sidechain_reconstruction.py
@@ -1,6 +1,6 @@
 import unittest
-from promod3 import sidechain, loop
 from ost import io, mol, geom
+from promod3 import loop, sidechain, modelling
 import os
 
 class SidechainTests(unittest.TestCase):
@@ -27,14 +27,14 @@ class SidechainTests(unittest.TestCase):
                      rotamer_model, rotamer_library):
         # reconstruct sidechains for full OST entity
         ent_py = ent.Copy()
-        sidechain.Reconstruct(ent_py, keep_sidechains=keep_sidechains,
-                              build_disulfids=build_disulfids,
-                              optimize_subrotamers=optimize_subrotamers,
-                              rotamer_model=rotamer_model,
-                              rotamer_library=rotamer_library)
+        modelling.ReconstructSidechains(ent_py, keep_sidechains=keep_sidechains,
+                                        build_disulfids=build_disulfids,
+                                        optimize_subrotamers=optimize_subrotamers,
+                                        rotamer_model=rotamer_model,
+                                        rotamer_library=rotamer_library)
 
         # same with SidechainReconstructor
-        sc_rec = sidechain.SidechainReconstructor( \
+        sc_rec = modelling.SidechainReconstructor( \
                                keep_sidechains=keep_sidechains,
                                build_disulfids=build_disulfids,
                                optimize_subrotamers=optimize_subrotamers)
@@ -50,8 +50,8 @@ class SidechainTests(unittest.TestCase):
         outfile = os.path.join('data', '1eye_rec.pdb')
         # get and reconstruct 1eye
         prot = io.LoadPDB(infile)
-        sidechain.Reconstruct(prot, keep_sidechains=False,
-                              rotamer_library=self.bbdep_rotamer_library)
+        modelling.ReconstructSidechains(prot, keep_sidechains=False,
+                                        rotamer_library=self.bbdep_rotamer_library)
         # compare with reference solution
         prot_rec = io.LoadPDB(outfile)
         self.assertEqual(prot.GetAtomCount(), prot_rec.GetAtomCount())
diff --git a/sidechain/tests/test_sidechain_reconstructor.cc b/modelling/tests/test_sidechain_reconstructor.cc
similarity index 98%
rename from sidechain/tests/test_sidechain_reconstructor.cc
rename to modelling/tests/test_sidechain_reconstructor.cc
index 3b09654d2fabe17438a67ded7f06d6cdfd1e88be..247914105081faef82d7e32a44d8e197e7758842 100644
--- a/sidechain/tests/test_sidechain_reconstructor.cc
+++ b/modelling/tests/test_sidechain_reconstructor.cc
@@ -1,5 +1,5 @@
 
-#include <promod3/sidechain/sidechain_reconstructor.hh>
+#include <promod3/modelling/sidechain_reconstructor.hh>
 #include <promod3/core/message.hh>
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
@@ -12,7 +12,7 @@
 BOOST_AUTO_TEST_SUITE( sidechain );
 
 using namespace promod3;
-using namespace promod3::sidechain;
+using namespace promod3::modelling;
 
 namespace {
 
diff --git a/sidechain/doc/CMakeLists.txt b/sidechain/doc/CMakeLists.txt
index 09dbdca6be55cf02fa7774e38edd120219130931..4c1d117225741bb404070a93a0bd5be100acf99f 100644
--- a/sidechain/doc/CMakeLists.txt
+++ b/sidechain/doc/CMakeLists.txt
@@ -1,6 +1,5 @@
 set(SIDECHAIN_RST
 index.rst
-reconstruct.rst
 rotamer.rst
 rotamer_id.rst
 frame.rst
diff --git a/sidechain/doc/index.rst b/sidechain/doc/index.rst
index 69da3d9180dc58002e0e340b08ad2d7d482d9b89..c0a24dce4ca854bcd16c85d29094dcd1ff799f71 100644
--- a/sidechain/doc/index.rst
+++ b/sidechain/doc/index.rst
@@ -12,21 +12,12 @@ the modelling of sidechains using two different rotamer models. A rigid model,
 as well as a flexible model. Both models are implemented in PROMOD3 and can be
 applied in flexible ways.
 
-The simplest usage of the module is provided by the :func:`Reconstruct`
-function:
-
-.. literalinclude:: ../../../tests/doc/scripts/sidechain_reconstruct.py
-
-For use during loop modelling, the :class:`SidechainReconstructor` can be used:
-
-.. literalinclude:: ../../../tests/doc/scripts/sidechain_reconstructor.py
-
 The following code fragment shows an example of a basic sidechain reconstruction
 algorithm using the functionality in the module. Note, that this code will crash
 as soon as you have structures containing all the weirdness the PDB throws at
-us. In this case, you should use the :func:`Reconstruct`  function above. An
-overview of the full provided functionality can be found at  the bottom of this
-page.
+us. In this case, you should use the full fletched sidechain reconstruction
+pipelines available in the modelling module. 
+
 
 .. literalinclude:: ../../../tests/doc/scripts/sidechain_steps.py
 
@@ -35,7 +26,6 @@ Contents:
 .. toctree::
    :maxdepth: 2
 
-   reconstruct
    rotamer_id
    rotamer
    frame
diff --git a/sidechain/pymod/CMakeLists.txt b/sidechain/pymod/CMakeLists.txt
index 3a745384883693f4c46e412d53182e2549b84501..df22822d3ac6a7be57ccc00fcdcf588d77ecf03d 100644
--- a/sidechain/pymod/CMakeLists.txt
+++ b/sidechain/pymod/CMakeLists.txt
@@ -10,7 +10,6 @@ export_rotamer_density.cc
 export_rotamer_ids.cc
 export_rotamer_lib.cc
 export_sidechain_object_loader.cc
-export_sidechain_reconstructor.cc
 export_scwrl_rotamer_constructor.cc
 export_subrotamer_optimizer.cc
 wrap_sidechain.cc
@@ -18,7 +17,6 @@ wrap_sidechain.cc
 
 set(SIDECHAIN_PYMOD
 __init__.py
-_reconstruct_sidechains.py
 )
 
 pymod(NAME sidechain CPP ${SIDECHAIN_CPP} PY ${SIDECHAIN_PYMOD}
diff --git a/sidechain/pymod/__init__.py b/sidechain/pymod/__init__.py
index 8e7127cca4ffe791c136fcca89e1c2c9ee516c70..a915c37e3d03af93e9e14a35f2d00d40c3deae7b 100644
--- a/sidechain/pymod/__init__.py
+++ b/sidechain/pymod/__init__.py
@@ -1,2 +1,2 @@
 from _sidechain import *
-from _reconstruct_sidechains import *
+
diff --git a/sidechain/pymod/wrap_sidechain.cc b/sidechain/pymod/wrap_sidechain.cc
index 5e3f80d7a2b0d6834f4c742a24392b3a15359183..14a3fc9b574d295b970f0fdd6eb874bed7328e81 100644
--- a/sidechain/pymod/wrap_sidechain.cc
+++ b/sidechain/pymod/wrap_sidechain.cc
@@ -11,7 +11,6 @@ void export_RotamerDensity();
 void export_RotamerIDs();
 void export_RotamerLib();
 void export_SidechainObjectLoader();
-void export_SidechainReconstructor();
 void export_SCWRLRotamerConstructor();
 void export_SubrotamerOptimizer();
 
@@ -30,7 +29,6 @@ BOOST_PYTHON_MODULE(_sidechain)
   export_RotamerIDs();
   export_RotamerLib(); 
   export_SidechainObjectLoader();
-  export_SidechainReconstructor();
   export_SCWRLRotamerConstructor();
   export_SubrotamerOptimizer();
 }
diff --git a/sidechain/src/CMakeLists.txt b/sidechain/src/CMakeLists.txt
index 34a9a875640fc05ecd20e24c7bb0067f078de118..dfa815fc9ea3d7b5580e11caa46f4eac78534a2b 100644
--- a/sidechain/src/CMakeLists.txt
+++ b/sidechain/src/CMakeLists.txt
@@ -13,9 +13,7 @@ set(SIDECHAIN_HEADERS
   rotamer_lib_entry.hh
   rotamer_lib_reader.hh
   sidechain_connector.hh
-  sidechain_env_listener.hh
   sidechain_object_loader.hh
-  sidechain_reconstructor.hh
   scwrl_rotamer_constructor.hh
   subrotamer_optimizer.hh
 )
@@ -35,9 +33,7 @@ set(SIDECHAIN_SOURCES
   rotamer_lib_entry.cc
   rotamer_lib_reader.cc
   sidechain_connector.cc
-  sidechain_env_listener.cc
   sidechain_object_loader.cc
-  sidechain_reconstructor.cc
   scwrl_rotamer_constructor.cc
   subrotamer_optimizer.cc
 )
diff --git a/sidechain/tests/CMakeLists.txt b/sidechain/tests/CMakeLists.txt
index 13d46c0de952ad3a4dc58f6fd702778c2a976d29..e5cd99e067512667e2edef9e367bf10f07f2eecd 100644
--- a/sidechain/tests/CMakeLists.txt
+++ b/sidechain/tests/CMakeLists.txt
@@ -1,16 +1,10 @@
 set(SIDECHAIN_UNIT_TESTS
-  test_sidechain.py
   test_frame_construction.cc
   test_rotamers.cc
-  test_sidechain_reconstructor.cc
   tests.cc
 )
 
 set(SIDECHAIN_TEST_DATA
-  data/1crn_sc_test.pdb
-  data/1eye.pdb
-  data/1eye_rec.pdb
-  data/1eye_sc_test.pdb
   data/all_sc.pdb
 )