diff --git a/sidechain/doc/CMakeLists.txt b/sidechain/doc/CMakeLists.txt
index b38d2f0a696ad677f23cc4361c77cf83ce9cfe90..09dbdca6be55cf02fa7774e38edd120219130931 100644
--- a/sidechain/doc/CMakeLists.txt
+++ b/sidechain/doc/CMakeLists.txt
@@ -9,6 +9,7 @@ rotamer_constructor.rst
 graph.rst
 disulfid.rst
 loading.rst
+subrotamer_optimizer.rst
 )
 
 add_doc_source(NAME sidechain RST ${SIDECHAIN_RST})
diff --git a/sidechain/doc/index.rst b/sidechain/doc/index.rst
index a1ba3806d3fff16687944b8a4067be5401680f96..69da3d9180dc58002e0e340b08ad2d7d482d9b89 100644
--- a/sidechain/doc/index.rst
+++ b/sidechain/doc/index.rst
@@ -44,6 +44,7 @@ Contents:
    graph
    disulfid
    loading
+   subrotamer_optimizer
 
 
 .. [krivov2009] Krivov GG, Shapovalov MV and Dunbrack RL Jr. (2009). Improved prediction of protein side-chain conformations with SCWRL4. Proteins.
diff --git a/sidechain/doc/subrotamer_optimizer.rst b/sidechain/doc/subrotamer_optimizer.rst
new file mode 100644
index 0000000000000000000000000000000000000000..e4124466394f2bdc0248aa40056a590f5b556dcb
--- /dev/null
+++ b/sidechain/doc/subrotamer_optimizer.rst
@@ -0,0 +1,45 @@
+Subrotamer Optimization
+================================================================================
+
+.. currentmodule:: promod3.sidechain
+
+The idea of the flexible rotamer model is to have several subrotamers
+representing one single rotamer. 
+One subrotamer is the representative (the active subrotamer).
+Thats the one that gets inserted in the structure once the reconstruction has
+finished. This is not necessarily the optimal one. The SubrotamerOptimizer
+takes a list of flexible rotamers, converts every single flexible rotamer 
+in a rotamer group of rigid rotamers, solves the sidechain reconstruction
+problem and assigns the optimal subrotamers as active in the original 
+flexible rotamers. In terms of energies, the SubrotamerOptimizer expects
+the energy of the flexible rotamers towards the rigid frame already to be set.
+The internal energies can be controlled as parameters and a constant value is
+set for rotamers that are currently active or not. The reason for that is
+that you might want to prefer the currently active subrotamers if no
+pairwise energies to other rotamers are observed. 
+
+.. method:: SubrotamerOptimizer(rotamers, [active_internal_energy=-2.0, \
+                                inactive_internal_energy=0.0, \
+                                max_complexity=100000000, initial_epsilon=0.02)
+
+  Takes the **rotamers** of type :class:`FRMRotamer`, converts all their 
+  subrotamers into rigid rotamers, solves the sidechain reconstruction problem
+  and assigns the ideal subrotamers as active in the input **rotamers**.
+
+  :param rotamers:      The rotamers to be optimized               
+  :type rotamers:       :class:`list` of :class:`FRMRotamer`
+
+  :param active_internal_energy: Internal energy that gets assigned to all
+                                 currently active subrotamers
+  :type active_internal_energy:  :class:`float`
+
+  :param inactive_internal_energy: Internal energy that gets assigned to all
+                                   currently inactive subrotamers
+  :type inactive_internal_energy: :class:`float`
+
+  :param max_complexity: Max complexity of the internal :class:`RotamerGraph`
+  :type max_complexity: :class:`int`
+
+  :param initial_epsilon: Epsilon value controlling the pruning of 
+                          internal :class:`RotamerGraph`
+  :type initial_epsilon: :class:`float`
diff --git a/sidechain/pymod/CMakeLists.txt b/sidechain/pymod/CMakeLists.txt
index afc814bac04e1dbe04614a30e51cf5be5ef65cbf..3a745384883693f4c46e412d53182e2549b84501 100644
--- a/sidechain/pymod/CMakeLists.txt
+++ b/sidechain/pymod/CMakeLists.txt
@@ -12,6 +12,7 @@ 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
 )
 
diff --git a/sidechain/pymod/_reconstruct_sidechains.py b/sidechain/pymod/_reconstruct_sidechains.py
index eacf17c86804661c502f8340f3cba8df63b9f129..2b1601a98a380f3f293fc2c48f7e3dada105662e 100644
--- a/sidechain/pymod/_reconstruct_sidechains.py
+++ b/sidechain/pymod/_reconstruct_sidechains.py
@@ -350,35 +350,6 @@ def _GetDisulfidBridges(frame_residues, cystein_indices, res_list, rotamer_libra
     return disulfid_indices, disulfid_rotamers
 
 
-def RefineFRMRotamerGroups(solution, frm_rotamer_groups,
-                           graph_max_complexity=100000000 , 
-                           graph_initial_epsilon=0.02):
-    
-    rrm_rotamer_groups = list()
-    for i, rg in enumerate(frm_rotamer_groups):
-        frm_rotamer = rg[solution[i]]
-        rrm_rotamers = list()
-        original_active_subrotamer = frm_rotamer.GetActiveSubrotamer()
-        for j in range(frm_rotamer.GetNumSubrotamers()):
-            frm_rotamer.SetActiveSubrotamer(j)
-            new_rrm_rotamer = frm_rotamer.ToRRMRotamer()
-            if(j != original_active_subrotamer):
-                new_rrm_rotamer.SetInternalEnergy(0.0)
-            else:
-                new_rrm_rotamer.SetInternalEnergy(-0.5)
-            rrm_rotamers.append(new_rrm_rotamer)
-        new_rotamer_group = sidechain.RRMRotamerGroup(rrm_rotamers, 0)
-        rrm_rotamer_groups.append(new_rotamer_group)
-    graph = sidechain.RotamerGraph.CreateFromRRMList(rrm_rotamer_groups)
-
-    solution = graph.TreeSolve(max_complexity=graph_max_complexity,
-                              initial_epsilon=graph_initial_epsilon)[0]
-
-    return (solution, rrm_rotamer_groups)
-
-
-
-
 ###############################################################################
 
 def Reconstruct(ent, keep_sidechains=False, build_disulfids=True,
@@ -417,16 +388,10 @@ def Reconstruct(ent, keep_sidechains=False, build_disulfids=True,
     :param optimize_subrotamers: Only considered when **rotamer_model** 
                                  is "frm".
                                  If set to True, the FRM solution undergoes 
-                                 some postprocessing. The final FRM rotamers get 
-                                 turned into :class:`RRMRotamerGroup` objects 
-                                 and fed into a second run of graph solving to 
-                                 find the optimal subrotamers from the FRM 
-                                 model. This mainly improves the reconstruction 
-                                 performance of bulky sidechains such as 
-                                 PHE/TYR/TRP. Internal energies of the 
-                                 :class:`RRMRotamer` objects are set to 0.0,
-                                 -0.5 if they represent the active subrotamer 
-                                 in the :class:`FRMRotamer`.
+                                 some postprocessing by calling 
+                                 :func:`SubrotamerOptimizer` with default 
+                                 parametrization.
+    :type optimize_subrotamers: :class:`bool`
 
     :param graph_max_complexity: Max. complexity for
                                  :meth:`RotamerGraph.TreeSolve`.
@@ -520,10 +485,11 @@ def Reconstruct(ent, keep_sidechains=False, build_disulfids=True,
                                initial_epsilon=graph_initial_epsilon)[0]
 
     if use_frm and optimize_subrotamers:
-        solution, rotamer_groups = RefineFRMRotamerGroups(solution, 
-                                                          rotamer_groups,
-                                                          graph_max_complexity,
-                                                          graph_initial_epsilon)
+        rotamers_to_optimize = list()
+
+        for rot_group, sol in zip(rotamer_groups, solution): 
+            rotamers_to_optimize.append(rot_group[sol])
+        sidechain.SubrotamerOptimizer(rotamers_to_optimize)
 
     # update structure
     for i, rot_group, sol in zip(residues_with_rotamer_group, rotamer_groups,
diff --git a/sidechain/pymod/export_subrotamer_optimizer.cc b/sidechain/pymod/export_subrotamer_optimizer.cc
new file mode 100644
index 0000000000000000000000000000000000000000..1b168786700daca626ac00b535921e04c6808663
--- /dev/null
+++ b/sidechain/pymod/export_subrotamer_optimizer.cc
@@ -0,0 +1,47 @@
+#include <boost/python.hpp>
+#include <boost/python/iterator.hpp>
+#include <boost/python/register_ptr_to_python.hpp>
+
+#include <promod3/core/export_helper.hh>
+#include <promod3/sidechain/subrotamer_optimizer.hh>
+
+
+using namespace promod3;
+using namespace promod3::sidechain;
+using namespace boost::python;
+
+
+namespace{
+
+void WrapOptimizer(boost::python::list& rotamers,
+                   Real active_internal_energy,
+                   Real inactive_internal_energy,
+                   uint max_complexity,
+                   Real initial_epsilon) {
+
+  std::vector<FRMRotamerPtr> v_rotamers;
+  promod3::core::ConvertListToVector(rotamers, v_rotamers);
+
+  promod3::sidechain::SubrotamerOptimizer(v_rotamers, 
+                                          active_internal_energy,
+                                          inactive_internal_energy, 
+                                          max_complexity,
+                                          initial_epsilon);
+}
+
+}
+
+void export_SubrotamerOptimizer() {
+
+  def("SubrotamerOptimizer", &WrapOptimizer,(arg("rotamers"),
+                                             arg("active_internal_energy")=-2.0,
+                                             arg("inactive_internal_energy")=0.0,
+                                             arg("max_complexity")=100000000,
+                                             arg("initial_epsilon")=0.02));
+}
+
+
+
+
+
+
diff --git a/sidechain/pymod/wrap_sidechain.cc b/sidechain/pymod/wrap_sidechain.cc
index 0b5547b1c38bbd0f0fb4c18a053455a01bb8a580..5e3f80d7a2b0d6834f4c742a24392b3a15359183 100644
--- a/sidechain/pymod/wrap_sidechain.cc
+++ b/sidechain/pymod/wrap_sidechain.cc
@@ -13,6 +13,7 @@ void export_RotamerLib();
 void export_SidechainObjectLoader();
 void export_SidechainReconstructor();
 void export_SCWRLRotamerConstructor();
+void export_SubrotamerOptimizer();
 
 using namespace boost::python;
 
@@ -31,4 +32,5 @@ BOOST_PYTHON_MODULE(_sidechain)
   export_SidechainObjectLoader();
   export_SidechainReconstructor();
   export_SCWRLRotamerConstructor();
+  export_SubrotamerOptimizer();
 }
diff --git a/sidechain/src/CMakeLists.txt b/sidechain/src/CMakeLists.txt
index 8175397ca8ba5a012fd47888ec739fd865987f6b..34a9a875640fc05ecd20e24c7bb0067f078de118 100644
--- a/sidechain/src/CMakeLists.txt
+++ b/sidechain/src/CMakeLists.txt
@@ -17,6 +17,7 @@ set(SIDECHAIN_HEADERS
   sidechain_object_loader.hh
   sidechain_reconstructor.hh
   scwrl_rotamer_constructor.hh
+  subrotamer_optimizer.hh
 )
 
 set(SIDECHAIN_SOURCES
@@ -38,6 +39,7 @@ set(SIDECHAIN_SOURCES
   sidechain_object_loader.cc
   sidechain_reconstructor.cc
   scwrl_rotamer_constructor.cc
+  subrotamer_optimizer.cc
 )
 
 module(NAME sidechain HEADERS ${SIDECHAIN_HEADERS} SOURCES ${SIDECHAIN_SOURCES}
diff --git a/sidechain/src/subrotamer_optimizer.cc b/sidechain/src/subrotamer_optimizer.cc
new file mode 100644
index 0000000000000000000000000000000000000000..64067573a88c06f741216c3faf6ef8f7254bd788
--- /dev/null
+++ b/sidechain/src/subrotamer_optimizer.cc
@@ -0,0 +1,54 @@
+#include <promod3/sidechain/subrotamer_optimizer.hh>
+
+namespace promod3{ namespace sidechain{
+
+void SubrotamerOptimizer(std::vector<FRMRotamerPtr>& rotamers,
+                         Real active_internal_energy,
+                         Real inactive_internal_energy,
+                         uint max_complexity,
+                         Real initial_epsilon) {
+
+  // buildup a list of RRMRotamer groups
+  std::vector<RRMRotamerGroupPtr> rrm_rotamer_groups;
+
+  for(uint rot_idx = 0; rot_idx < rotamers.size(); ++rot_idx) {
+    
+    // extract all subrotamers of current FRMRotamer as RRMRotamers
+    FRMRotamerPtr frm_rotamer = rotamers[rot_idx];
+    std::vector<RRMRotamerPtr> rrm_rotamers;
+    uint active_idx = frm_rotamer->GetActiveSubrotamer();
+
+    for(uint subrot_idx = 0; subrot_idx < frm_rotamer->subrotamer_size(); 
+        ++subrot_idx) {
+      
+      frm_rotamer->SetActiveSubrotamer(subrot_idx);
+      RRMRotamerPtr new_rrm_rotamer = frm_rotamer->ToRRMRotamer();
+
+      if(subrot_idx == active_idx) {
+        new_rrm_rotamer->SetInternalEnergy(active_internal_energy);
+      }   
+      else {
+        new_rrm_rotamer->SetInternalEnergy(inactive_internal_energy);
+      }
+      rrm_rotamers.push_back(new_rrm_rotamer);
+    }
+    
+    RRMRotamerGroupPtr rrm_rotamer_group(new RRMRotamerGroup(rrm_rotamers, 0));
+    rrm_rotamer_groups.push_back(rrm_rotamer_group);
+  }
+
+  // generate a graph from the RRMRotamerGroups to find the optimal subrotamers
+  RotamerGraphPtr graph = RotamerGraph::CreateFromRRMList(rrm_rotamer_groups);
+
+  std::pair<std::vector<int>, Real> full_solution = 
+  graph->TreeSolve(max_complexity, initial_epsilon);
+
+  const std::vector<int>& solution = full_solution.first;
+
+  // activate the appropriate subrotamers
+  for(uint rot_idx = 0; rot_idx < solution.size(); ++rot_idx) {
+     rotamers[rot_idx]->SetActiveSubrotamer(solution[rot_idx]); 
+  }
+}
+
+}} // ns
diff --git a/sidechain/src/subrotamer_optimizer.hh b/sidechain/src/subrotamer_optimizer.hh
new file mode 100644
index 0000000000000000000000000000000000000000..594d3ffd7aa87b07d95569aa2729b6b27022c28b
--- /dev/null
+++ b/sidechain/src/subrotamer_optimizer.hh
@@ -0,0 +1,18 @@
+#ifndef PROMOD3_SUBROTAMER_OPTIMIZER_HH
+#define PROMOD3_SUBROTAMER_OPTIMIZER_HH
+
+#include <vector>
+
+#include <promod3/sidechain/rotamer_graph.hh>
+
+
+namespace promod3{ namespace sidechain{
+
+void SubrotamerOptimizer(std::vector<FRMRotamerPtr>& rotamers,
+                         Real active_internal_energy = -0.5,
+                         Real inactive_internal_energy = 0.0,
+                         uint max_complexity = 100000000,
+                         Real initial_epsilon = 0.02);
+}} // ns
+
+#endif