diff --git a/doc/tests/scripts/loop_monte_carlo.py b/doc/tests/scripts/loop_monte_carlo.py
index ea54fce24dbd7c3ec503f58b42d7c22fafa3768f..dba23d61455d956443a5fb1b475535dcc2523a89 100644
--- a/doc/tests/scripts/loop_monte_carlo.py
+++ b/doc/tests/scripts/loop_monte_carlo.py
@@ -1,5 +1,5 @@
 from ost import io
-from promod3 import loop, modelling
+from promod3 import loop, scoring, modelling
 import numpy as np
 
 # setup protein
@@ -20,11 +20,16 @@ mc_sampler = modelling.SoftSampler(terminal_sequence, torsion_sampler,
 # setup mc_closer
 mc_closer = modelling.NTerminalCloser(prot.residues[n_terminal_length-1])
 
-# set up mc_scorer
-scorer = loop.LoadBackboneLoopScorer()
-scorer.Initialize(seqres)
-scorer.SetEnvironment(prot)
+# setup backbone scorer with clash and cbeta scoring
+score_env = scoring.BackboneScoreEnv(seqres)
+score_env.SetInitialEnvironment(prot)
+scorer = scoring.BackboneOverallScorer()
+scorer["cbeta"] = scoring.LoadCBetaScorer()
+scorer["cbeta"].AttachEnvironment(score_env)
+scorer["clash"] = scoring.ClashScorer()
+scorer["clash"].AttachEnvironment(score_env)
 
+# set up mc_scorer
 weights = dict()
 weights["cbeta"] = 10.0
 weights["clash"] = 0.1
diff --git a/doc/tests/scripts/modelling_close_small_deletions.py b/doc/tests/scripts/modelling_close_small_deletions.py
index c11ff7998c13d6c45dcf20da446d50212ea1e2be..54809c2fdb1591cce6257fcca98ceb1e47baaf5c 100644
--- a/doc/tests/scripts/modelling_close_small_deletions.py
+++ b/doc/tests/scripts/modelling_close_small_deletions.py
@@ -9,6 +9,6 @@ aln.AttachView(1, tpl.CreateFullView())
 mhandle = modelling.BuildRawModel(aln)
 # close small deletion
 print 'Number of gaps before: %d' % len(mhandle.gaps)
-scorer = modelling.SetupBackboneScorer(mhandle)
-modelling.CloseSmallDeletions(mhandle, scorer)
+modelling.SetupDefaultBackboneScorer(mhandle)
+modelling.CloseSmallDeletions(mhandle)
 print 'Number of gaps after: %d' % len(mhandle.gaps)
diff --git a/doc/tests/scripts/modelling_fill_loops_by_database.py b/doc/tests/scripts/modelling_fill_loops_by_database.py
index ed3035b30125a56fb0975c2fd66b4983f050e2e4..16f0944bbf7b86130d3e66412d089da6348cada5 100644
--- a/doc/tests/scripts/modelling_fill_loops_by_database.py
+++ b/doc/tests/scripts/modelling_fill_loops_by_database.py
@@ -11,8 +11,8 @@ aln.AttachView(1, tpl.CreateFullView())
 mhandle = modelling.BuildRawModel(aln)
 # merge gaps
 print 'Number of gaps before: %d' % len(mhandle.gaps)
-scorer = modelling.SetupBackboneScorer(mhandle)
-modelling.FillLoopsByDatabase(mhandle, scorer, loop.LoadFragDB(),
+modelling.SetupDefaultBackboneScorer(mhandle)
+modelling.FillLoopsByDatabase(mhandle, loop.LoadFragDB(),
                               loop.LoadStructureDB(),
                               loop.LoadTorsionSamplerCoil())
 print 'Number of gaps after: %d' % len(mhandle.gaps)
diff --git a/doc/tests/scripts/modelling_fill_loops_by_monte_carlo.py b/doc/tests/scripts/modelling_fill_loops_by_monte_carlo.py
index 184f6bfc22b0369b2e20613a1cb8721621dfa9d1..e8e02a052f0c533026c85afe3de68e109c24fc84 100644
--- a/doc/tests/scripts/modelling_fill_loops_by_monte_carlo.py
+++ b/doc/tests/scripts/modelling_fill_loops_by_monte_carlo.py
@@ -11,7 +11,7 @@ aln.AttachView(1, tpl.CreateFullView())
 mhandle = modelling.BuildRawModel(aln)
 # merge gaps
 print 'Number of gaps before: %d' % len(mhandle.gaps)
-scorer = modelling.SetupBackboneScorer(mhandle)
-modelling.FillLoopsByMonteCarlo(mhandle, scorer,
+modelling.SetupDefaultBackboneScorer(mhandle)
+modelling.FillLoopsByMonteCarlo(mhandle,
                               	loop.LoadTorsionSamplerCoil())
 print 'Number of gaps after: %d' % len(mhandle.gaps)
diff --git a/doc/tests/scripts/modelling_model_termini.py b/doc/tests/scripts/modelling_model_termini.py
index 5a557064bc0a866dadaa16fc30f44e5ef938eeac..464857d455f6cdba5a92b8e1ab6b1482322b74cd 100644
--- a/doc/tests/scripts/modelling_model_termini.py
+++ b/doc/tests/scripts/modelling_model_termini.py
@@ -11,7 +11,7 @@ aln.AttachView(1, tpl.CreateFullView())
 mhandle = modelling.BuildRawModel(aln)
 # merge gaps
 print 'Number of gaps before: %d' % len(mhandle.gaps)
-scorer = modelling.SetupBackboneScorer(mhandle)
-modelling.ModelTermini(mhandle, scorer,
+modelling.SetupDefaultBackboneScorer(mhandle)
+modelling.ModelTermini(mhandle,
                        loop.LoadTorsionSamplerCoil())
 print 'Number of gaps after: %d' % len(mhandle.gaps)
diff --git a/doc/tests/scripts/modelling_steps.py b/doc/tests/scripts/modelling_steps.py
index ac57bc1a1a1721ebd0dc3abcfaa1f7a4797a240c..93b4a65dc0aacc8c05b07550e6fd1d0c442a80de 100644
--- a/doc/tests/scripts/modelling_steps.py
+++ b/doc/tests/scripts/modelling_steps.py
@@ -14,27 +14,27 @@ aln.AttachView(1, tpl.CreateFullView())
 mhandle = modelling.BuildRawModel(aln)
 
 # perform loop modelling to close all gaps
-scorer = modelling.SetupBackboneScorer(mhandle)
+modelling.SetupDefaultBackboneScorer(mhandle)
 modelling.RemoveTerminalGaps(mhandle)
-modelling.CloseSmallDeletions(mhandle, scorer)
+modelling.CloseSmallDeletions(mhandle)
 for distance in range(merge_distance):
     modelling.MergeGapsByDistance(mhandle, distance)
-    modelling.FillLoopsByDatabase(mhandle, scorer, fragment_db,
+    modelling.FillLoopsByDatabase(mhandle, fragment_db,
                                   structure_db, torsion_sampler,
                                   min_loops_required=-1,
                                   max_res_extension=6)
 # if above fails, try DB-fill with less restrictions
-modelling.FillLoopsByDatabase(mhandle, scorer, fragment_db,
+modelling.FillLoopsByDatabase(mhandle, fragment_db,
                               structure_db, torsion_sampler,
                               min_loops_required=-1)
-modelling.FillLoopsByDatabase(mhandle, scorer, fragment_db,
+modelling.FillLoopsByDatabase(mhandle, fragment_db,
                               structure_db, torsion_sampler)
 # if above fails on some gaps, use Monte Carlo
-modelling.FillLoopsByMonteCarlo(mhandle, scorer, torsion_sampler)
+modelling.FillLoopsByMonteCarlo(mhandle, torsion_sampler)
 # as a last resort, try to close large deletions
-modelling.CloseLargeDeletions(mhandle, scorer, structure_db)
+modelling.CloseLargeDeletions(mhandle, structure_db)
 # build sidechains
-modelling.BuildSidechains(mhandle, merge_distance, scorer,
+modelling.BuildSidechains(mhandle, merge_distance,
                           fragment_db, structure_db,
                           torsion_sampler)
 # minimize energy of final model using molecular mechanics
diff --git a/modelling/pymod/_closegaps.py b/modelling/pymod/_closegaps.py
index bf9256ffecec255741e482109ae6cd5489fc7849..44e07d20085d5389ea8675456c6b8d8727d293fc 100644
--- a/modelling/pymod/_closegaps.py
+++ b/modelling/pymod/_closegaps.py
@@ -53,11 +53,10 @@ def _GetWeights():
     weights["reduced"] = 2.13535565
     weights["cbeta"] = 3.59177335
     weights["cb_packing"] = 1.17280667
-    weights["constraint"] = -0.7
+    weights["pairwise"] = -0.7
     return weights
 
-def _CloseLoopFrame(mhandle, scorer, gap_orig, actual_candidates,
-                    actual_extended_gaps):
+def _CloseLoopFrame(mhandle, gap_orig, actual_candidates, actual_extended_gaps):
     '''Rank candidates with "frame-approach".
     All found candidates are extended prior to scoring so they match in size.
     '''
@@ -99,35 +98,28 @@ def _CloseLoopFrame(mhandle, scorer, gap_orig, actual_candidates,
                 loop_candidate.bb_list, start_index, False)
             final_loop_candidates.Add(actual_frame_backbone_list)
             back_mapper.append((i, j))
+    
+    if len(final_loop_candidates) > 0:
+        # score them
+        scores = final_loop_candidates.CalculateLinearScores(\
+                    mhandle.backbone_scorer, _GetWeights(), min_before_resnum,
+                    actual_chain_idx)
+        min_score = min(scores)
+        min_idx = scores.index(min_score)
 
-    # score them
-    final_loop_candidates.AttachScorer(scorer)
-    final_loop_candidates.CalculateCombinedScores(_GetWeights(),
-                                                  min_before_resnum,
-                                                  actual_chain_idx)
-
-    # compare scores
-    min_score = float("inf")
-    optimal_candidate = -1
-    for i in range(len(final_loop_candidates)):
-        score = final_loop_candidates[i].combined_score
-        if score < min_score:
-            optimal_candidate = i
-            min_score = score
-
-    ost.LogVerbose("Gap %s - %d candidates, best (min) score %g" %
-                   (str(gap_orig), len(final_loop_candidates), min_score))
+        ost.LogVerbose("Gap %s - %d candidates, best (min) score %g" %
+                       (str(gap_orig), len(final_loop_candidates), min_score))
 
-    # finally resolve loop
-    if optimal_candidate != -1:
-        idx_a = back_mapper[optimal_candidate][0]
-        idx_b = back_mapper[optimal_candidate][1]
+        # resolve loop
+        idx_a = back_mapper[min_idx][0]
+        idx_b = back_mapper[min_idx][1]
         # update model
         start_resnum = actual_extended_gaps[idx_a].before.GetNumber()
         bb_list = actual_candidates[idx_a][idx_b].bb_list
         bb_list.InsertInto(mhandle.model.chains[actual_chain_idx], start_resnum)
-        # update scorer
-        scorer.SetEnvironment(bb_list, start_resnum, actual_chain_idx)
+        # update score env.
+        mhandle.backbone_scorer_env.SetEnvironment(bb_list, start_resnum,
+                                                   actual_chain_idx)
         ost.LogInfo("Resolved %s by filling %s (%d candidates)" % \
                     (str(gap_orig),
                      str(actual_extended_gaps[idx_a]),
@@ -139,8 +131,8 @@ def _CloseLoopFrame(mhandle, scorer, gap_orig, actual_candidates,
         return -2
 
 
-def _CloseLoopBare(mhandle, scorer, gap_orig, actual_candidates,
-                   actual_extended_gaps, penalize_length=True):
+def _CloseLoopBare(mhandle, gap_orig, actual_candidates, actual_extended_gaps,
+                   penalize_length=True):
     '''Rank candidates directly.
     All candidates are scored directly and optionally penalized for gap length.
     '''
@@ -149,31 +141,30 @@ def _CloseLoopBare(mhandle, scorer, gap_orig, actual_candidates,
     actual_chain = mhandle.model.chains[actual_chain_idx]
     
     # score loops as they are
+    scorer = mhandle.backbone_scorer
     weights = _GetWeights()
     min_score = float("inf")
     optimal_gap = None
     optimal_candidate = None
     n_candidates = 0
     for i, loop_candidates in enumerate(actual_candidates):
+        if len(loop_candidates) == 0: continue
         n_candidates += len(loop_candidates)
         # score them
         before_resnum = actual_extended_gaps[i].before.GetNumber().GetNum()
-        loop_candidates.AttachScorer(scorer)
-        loop_candidates.CalculateCombinedScores(weights,
-                                                before_resnum,
-                                                actual_chain_idx)
-        # any good ones?
-        gap_length = actual_extended_gaps[i].length
-        for loop_candidate in loop_candidates:
-            # penalized by gap length?
-            if penalize_length:
-                score = loop_candidate.combined_score * gap_length
-            else:
-                score = loop_candidate.combined_score
-            if score < min_score:
-                optimal_gap = actual_extended_gaps[i]
-                optimal_candidate = loop_candidate
-                min_score = score
+        scores = loop_candidates.CalculateLinearScores(\
+                    scorer, weights, before_resnum, actual_chain_idx)
+        # check best one
+        score = min(scores)
+        best_idx = scores.index(score)
+        if penalize_length:
+            # penalized by gap length
+            score = score * actual_extended_gaps[i].length
+        if score < min_score:
+            # keep best one
+            min_score = score
+            optimal_gap = actual_extended_gaps[i]
+            optimal_candidate = loop_candidates[best_idx]
 
     ost.LogVerbose("Gap %s - %d candidates, best (min) score %g" %
                    (str(gap_orig), n_candidates, min_score))
@@ -184,8 +175,9 @@ def _CloseLoopBare(mhandle, scorer, gap_orig, actual_candidates,
         start_resnum = optimal_gap.before.GetNumber()
         bb_list = optimal_candidate.bb_list
         bb_list.InsertInto(mhandle.model.chains[actual_chain_idx], start_resnum)
-        # update scorer
-        scorer.SetEnvironment(bb_list, start_resnum, actual_chain_idx)
+        # update score env.
+        mhandle.backbone_scorer_env.SetEnvironment(bb_list, start_resnum,
+                                                   actual_chain_idx)
         ost.LogInfo("Resolved %s by filling %s (%d candidates)" % \
                     (str(gap_orig), str(optimal_gap), n_candidates))
         # will return -1 if last gap removed
@@ -194,10 +186,9 @@ def _CloseLoopBare(mhandle, scorer, gap_orig, actual_candidates,
         ost.LogInfo("Failed at loop insertion (%s)" % str(gap_orig))
         return -2
 
-def _CloseLoop(mhandle, scorer, gap_orig, actual_candidates,
+def _CloseLoop(mhandle, gap_orig, actual_candidates,
                actual_extended_gaps, variant=0):
     '''Choose best scoring loop candidate and close loop in mhandle.
-    :param scorer: scorer dedicated to this model
     :param gap_orig: Gap we actually wanted to close
     :param actual_candidates: List of LoopCandidates
     :param actual_extended_gaps: List of gaps (same size as actual_candidates)
@@ -218,10 +209,10 @@ def _CloseLoop(mhandle, scorer, gap_orig, actual_candidates,
         return -2
     # choose variant
     if variant == 0:
-        return _CloseLoopFrame(mhandle, scorer, gap_orig, actual_candidates,
+        return _CloseLoopFrame(mhandle, gap_orig, actual_candidates,
                                actual_extended_gaps)
     elif variant in [1,2]:
-        return _CloseLoopBare(mhandle, scorer, gap_orig, actual_candidates,
+        return _CloseLoopBare(mhandle, gap_orig, actual_candidates,
                               actual_extended_gaps, variant == 2)
     else:
         raise RuntimeError("Unknown variant %d" % variant);
@@ -253,7 +244,7 @@ def _InRange(gap, chain_idx, resnum_range):
 
 ###############################################################################
 
-def CloseSmallDeletions(mhandle, scorer, max_extension=9, clash_thresh=1.0,
+def CloseSmallDeletions(mhandle, max_extension=9, clash_thresh=1.0,
                         e_thresh=200, use_scoring_extender=True,
                         use_full_extender=True, chain_idx=None,
                         resnum_range=None):
@@ -272,10 +263,6 @@ def CloseSmallDeletions(mhandle, scorer, max_extension=9, clash_thresh=1.0,
     :param mhandle: Modelling handle on which to apply change.
     :type mhandle:  :class:`ModellingHandle`
 
-    :param scorer: A scorer dedicated to this model.
-                   If gaps are closed, the *scorer* is updated.
-    :type scorer: :class:`~promod3.loop.BackboneLoopScorer`
-
     :param max_extension: Maximal number of gap extension steps to perform
                           (see :class:`GapExtender`)
     :type max_extension: :class:`int`
@@ -323,6 +310,7 @@ def CloseSmallDeletions(mhandle, scorer, max_extension=9, clash_thresh=1.0,
     else:
         return
 
+    clash_scorer = mhandle.backbone_scorer.Get("clash")
     current_gap_index = 0
 
     # iterating mhandle.gaps. The number of gaps may change during the process,
@@ -378,10 +366,10 @@ def CloseSmallDeletions(mhandle, scorer, max_extension=9, clash_thresh=1.0,
                 bb_relaxer = BackboneRelaxer(bb_list)
                 potential_e = bb_relaxer.Run(bb_list, 300, 0.1)
                 # check for clashes
-                score = scorer.CalculateClashScore(\
-                                        bb_list,
-                                        n_stem_resnum.GetNum(),
-                                        current_chain_index)
+                score = clash_scorer.CalculateScore(bb_list,
+                                                    n_stem_resnum.GetNum(),
+                                                    current_chain_index)
+
                 # if there is no clash and potential energy is low enough we
                 # just solved a gap, delete it and update the scorer for the
                 # changed model
@@ -392,8 +380,8 @@ def CloseSmallDeletions(mhandle, scorer, max_extension=9, clash_thresh=1.0,
                                 (mhandle.gaps[current_gap_index], current_gap))
                     chain = current_gap.before.GetChain()
                     bb_list.InsertInto(chain, n_stem_resnum)
-                    scorer.SetEnvironment(bb_list, n_stem_resnum,
-                                          current_chain_index)
+                    mhandle.backbone_scorer_env.SetEnvironment(\
+                        bb_list, n_stem_resnum, current_chain_index)
                     ClearGaps(mhandle, current_gap)
                     success = True
                     break
@@ -468,7 +456,7 @@ def MergeGapsByDistance(mhandle, distance):
                 try_again = True
                 break
 
-def FillLoopsByDatabase(mhandle, scorer, fragment_db, structure_db,
+def FillLoopsByDatabase(mhandle, fragment_db, structure_db,
                         torsion_sampler, max_loops_to_search=40,
                         min_loops_required=4, max_res_extension=-1,
                         extended_search=True, use_scoring_extender=True,
@@ -487,10 +475,6 @@ def FillLoopsByDatabase(mhandle, scorer, fragment_db, structure_db,
     :param mhandle: Modelling handle on which to apply change.
     :type mhandle:  :class:`ModellingHandle`
 
-    :param scorer: A scorer dedicated to this model.
-                   If gaps are closed, the *scorer* is updated.
-    :type scorer: :class:`~promod3.loop.BackboneLoopScorer`
-
     :param fragment_db: A fragment database coupled to the *structure_db*.
     :type fragment_db: :class:`~promod3.loop.FragDB`
 
@@ -679,7 +663,7 @@ def FillLoopsByDatabase(mhandle, scorer, fragment_db, structure_db,
         ##################################
         # close loop
         ##################################
-        new_idx = _CloseLoop(mhandle, scorer, gap_orig, actual_candidates,
+        new_idx = _CloseLoop(mhandle, gap_orig, actual_candidates,
                              actual_extended_gaps, score_variant)
         if new_idx == -2:
             # try next one if we failed
@@ -691,7 +675,7 @@ def FillLoopsByDatabase(mhandle, scorer, fragment_db, structure_db,
             gap_idx = new_idx
 
 
-def FillLoopsByMonteCarlo(mhandle, scorer, torsion_sampler, max_loops_to_search=6,
+def FillLoopsByMonteCarlo(mhandle, torsion_sampler, max_loops_to_search=6,
                           max_extension=30, mc_num_loops=2, mc_steps=5000,
                           use_scoring_extender=True, use_full_extender=True,
                           score_variant=0, ring_punch_detection=1,
@@ -715,10 +699,6 @@ def FillLoopsByMonteCarlo(mhandle, scorer, torsion_sampler, max_loops_to_search=
     :param mhandle: Modelling handle on which to apply change.
     :type mhandle:  :class:`ModellingHandle`
 
-    :param scorer: A scorer dedicated to this model.
-                   If gaps are closed, the *scorer* is updated.
-    :type scorer: :class:`~promod3.loop.BackboneLoopScorer`
-
     :param torsion_sampler: A sampler for torsion angles.
     :type torsion_sampler: :class:`~promod3.loop.TorsionSampler`
 
@@ -856,7 +836,7 @@ def FillLoopsByMonteCarlo(mhandle, scorer, torsion_sampler, max_loops_to_search=
                 weights["cb_packing"] = 2.0
                 weights["hbond"] = 1.0
                 weights["clash"] = 0.05
-                mc_scorer = LinearScorer(scorer,
+                mc_scorer = LinearScorer(mhandle.backbone_scorer,
                                          actual_gap.before.GetNumber().GetNum(),
                                          actual_chain_idx, weights)
 
@@ -902,7 +882,7 @@ def FillLoopsByMonteCarlo(mhandle, scorer, torsion_sampler, max_loops_to_search=
         ##################################
         # close loop
         ##################################
-        new_idx = _CloseLoop(mhandle, scorer, gap_orig, actual_candidates,
+        new_idx = _CloseLoop(mhandle, gap_orig, actual_candidates,
                              actual_extended_gaps, score_variant)
         if new_idx == -2:
             # try next one if we failed
@@ -914,7 +894,7 @@ def FillLoopsByMonteCarlo(mhandle, scorer, torsion_sampler, max_loops_to_search=
             gap_idx = new_idx
 
 
-def ModelTermini(mhandle, scorer, torsion_sampler, fragger_handles=None,
+def ModelTermini(mhandle, torsion_sampler, fragger_handles=None,
                  mc_num_loops=20, mc_steps=5000):
     '''Try to model termini with Monte Carlo sampling.
 
@@ -932,10 +912,6 @@ def ModelTermini(mhandle, scorer, torsion_sampler, fragger_handles=None,
     :param mhandle: Modelling handle on which to apply change.
     :type mhandle:  :class:`ModellingHandle`
 
-    :param scorer: A scorer dedicated to this model.
-                   If gaps are closed, the *scorer* is updated.
-    :type scorer: :class:`~promod3.loop.BackboneLoopScorer`
-
     :param torsion_sampler: A sampler for torsion angles.
     :type torsion_sampler: :class:`~promod3.loop.TorsionSampler`
 
@@ -996,8 +972,8 @@ def ModelTermini(mhandle, scorer, torsion_sampler, fragger_handles=None,
         scorer_weights["cb_packing"] = 2.0
         scorer_weights["hbond"] = 1.0
         scorer_weights["clash"] = 0.05
-        mc_scorer = LinearScorer(scorer, start_resnum, actual_chain_idx,
-                                 scorer_weights)
+        mc_scorer = LinearScorer(mhandle.backbone_scorer, start_resnum,
+                                 actual_chain_idx, scorer_weights)
 
         # setup cooler
         start_temperature = 100
@@ -1014,29 +990,19 @@ def ModelTermini(mhandle, scorer, torsion_sampler, fragger_handles=None,
                 actual_gap.full_seq, mc_num_loops, mc_steps, mc_sampler,
                 mc_closer, mc_scorer, mc_cooler)
 
-        # score candidates
-        candidates.AttachScorer(scorer)
-        candidates.CalculateCombinedScores(_GetWeights(), start_resnum,
-                                           actual_chain_idx)
-        # get best one
-        min_score = float("inf")
-        optimal_candidate = None
-        for candidate in candidates:
-            score = candidate.combined_score
-            if score < min_score:
-                optimal_candidate = candidate
-                min_score = score
-
-        ost.LogVerbose("Gap %s - %d candidates, best (min) score %g" %
-                       (str(actual_gap), len(candidates), min_score))
-
-        # finally resolve loop
-        if optimal_candidate is not None:
+        if len(candidates) > 0:
+            # score candidates
+            scores = candidates.CalculateLinearScores(\
+                       mhandle.backbone_scorer, _GetWeights(), start_resnum,
+                       actual_chain_idx)
+            min_score = min(scores)
+            min_idx = scores.index(min_score)
             # update model
-            bb_list = optimal_candidate.bb_list
+            bb_list = candidates[min_idx].bb_list
             bb_list.InsertInto(actual_chain, start_resnum)
-            # update scorer
-            scorer.SetEnvironment(bb_list, start_resnum, actual_chain_idx)
+            # update score env.
+            mhandle.backbone_scorer_env.SetEnvironment(bb_list, start_resnum,
+                                                       actual_chain_idx)
             ost.LogInfo("Resolved terminal gap %s (%d candidates)" % \
                         (str(actual_gap), len(candidates)))
             ClearGaps(mhandle, actual_gap)
@@ -1044,7 +1010,7 @@ def ModelTermini(mhandle, scorer, torsion_sampler, fragger_handles=None,
             ost.LogInfo("Failed to model terminal gap (%s)" % str(actual_gap))
             
 
-def CloseLargeDeletions(mhandle, scorer, structure_db, linker_length=8,
+def CloseLargeDeletions(mhandle, structure_db, linker_length=8,
                         num_fragments=500, use_scoring_extender=True,
                         use_full_extender=True):
 
@@ -1058,10 +1024,6 @@ def CloseLargeDeletions(mhandle, scorer, structure_db, linker_length=8,
     :param mhandle: Modelling handle on which to apply change.
     :type mhandle:  :class:`ModellingHandle`
 
-    :param scorer: A scorer dedicated to this model.
-                   If gaps are closed, the *scorer* is updated.
-    :type scorer: :class:`~promod3.loop.BackboneLoopScorer`
-
     :param structure_db: The database from which to extract fragments for
                          the linker region.
     :type structure_db: :class:`~promod3.loop.StructureDB`
@@ -1191,6 +1153,7 @@ def CloseLargeDeletions(mhandle, scorer, structure_db, linker_length=8,
         # the n-terminus
         best_score = float("inf")
         best_idx = 0
+        scorer_weights = {"clash": 1, "reduced": 1}
         for i in range(len(fragger)):
 
             fragment = fragger[i]
@@ -1207,10 +1170,8 @@ def CloseLargeDeletions(mhandle, scorer, structure_db, linker_length=8,
             bb_list.ApplyTransform(t)
 
             # a simple score gets calculated and best chosen
-            score = scorer.CalculateReducedScore(bb_list, first_num,
-                                                 actual_chain_idx)
-            score += scorer.CalculateClashScore(bb_list, first_num,
-                                                actual_chain_idx)
+            score = mhandle.backbone_scorer.CalculateLinearCombination(\
+                        scorer_weights, bb_list, first_num, actual_chain_idx)
             if score < best_score:
                 best_score = score
                 best_idx = i
@@ -1240,8 +1201,9 @@ def CloseLargeDeletions(mhandle, scorer, structure_db, linker_length=8,
         fragment = bb_list.Extract(frag_start_idx, len(bb_list))
         fragment.InsertInto(actual_chain, n_res_num)
 
-        # update scorer
-        scorer.SetEnvironment(bb_list, first_num, actual_chain_idx)
+        # update score env.
+        mhandle.backbone_scorer_env.SetEnvironment(bb_list, first_num,
+                                                   actual_chain_idx)
         # will return -1 if last gap removed
         gap_idx = ClearGaps(mhandle, actual_gap)
 
@@ -1252,11 +1214,3 @@ def CloseLargeDeletions(mhandle, scorer, structure_db, linker_length=8,
 # these methods will be exported into module
 __all__ = ('CloseSmallDeletions', 'MergeGapsByDistance', 'FillLoopsByDatabase',
            'FillLoopsByMonteCarlo', 'ModelTermini', 'CloseLargeDeletions')
-
-#  LocalWords:  modeling stereochemically param idx init
-#  LocalWords:  py ost pylint modelling promod CloseSmallDeletions
-#  LocalWords:  fillloopsbydb tpl aln trg TLNGFTVPAGNTLV LNPDKGATVTMA mhandle
-#  LocalWords:  NGGTLLIPNGTYHFLGIQMKSNVHIRVE AttachView CreateFullView len
-#  LocalWords:  BuildRawModel SetupBackboneScorer FillLoopsByDatabase
-#  LocalWords:  LoadFragDB LoadStructureDB LoadTorsionSamplerCoil dbs fasta
-#  LocalWords:  rtype
diff --git a/modelling/pymod/_pipeline.py b/modelling/pymod/_pipeline.py
index ea3a03393de733a10f604b55dc237b61775c9501..3dc87809edd398563101c250db684f54fb4b1847 100644
--- a/modelling/pymod/_pipeline.py
+++ b/modelling/pymod/_pipeline.py
@@ -162,7 +162,7 @@ def _GetSimEntity(sim):
     return ent
 ###############################################################################
 
-def BuildSidechains(mhandle, merge_distance=4, scorer=None, fragment_db=None,
+def BuildSidechains(mhandle, merge_distance=4, fragment_db=None,
                     structure_db=None, torsion_sampler=None):
     '''Build sidechains for model.
 
@@ -177,10 +177,6 @@ def BuildSidechains(mhandle, merge_distance=4, scorer=None, fragment_db=None,
     :param merge_distance:  Used as parameter for :func:`MergeGapsByDistance`
                             if ring punches are found.
     :type merge_distance:   :class:`int`
-    :param scorer:          Used as parameter for :func:`FillLoopsByDatabase`
-                            if ring punches are found. A default one is created
-                            if None.
-    :type scorer:           :class:`~promod3.loop.BackboneLoopScorer`
     :param fragment_db:     Used as parameter for :func:`FillLoopsByDatabase`
                             if ring punches are found. A default one is loaded
                             if None.
@@ -213,8 +209,8 @@ def BuildSidechains(mhandle, merge_distance=4, scorer=None, fragment_db=None,
             mygap = StructuralGap(res.prev, res.next, res.one_letter_code)
             mhandle.gaps.append(mygap)
         # load stuff if needed
-        if scorer is None:
-            scorer = SetupBackboneScorer(mhandle)
+        if not IsBackboneScorerSet(mhandle) or not IsBackboneScorerSet(mhandle):
+            SetupDefaultBackboneScorer(mhandle)
         if fragment_db is None:
             fragment_db = loop.LoadFragDB()
         if structure_db is None:
@@ -223,7 +219,7 @@ def BuildSidechains(mhandle, merge_distance=4, scorer=None, fragment_db=None,
             torsion_sampler = loop.LoadTorsionSamplerCoil()
         # fix it
         MergeGapsByDistance(mhandle, merge_distance)
-        FillLoopsByDatabase(mhandle, scorer, fragment_db, structure_db,
+        FillLoopsByDatabase(mhandle, fragment_db, structure_db,
                             torsion_sampler, ring_punch_detection=2)
         # re-build sidechains
         sidechain.Reconstruct(mhandle.model, keep_sidechains=True)
@@ -403,7 +399,7 @@ def CheckFinalModel(mhandle):
             ost.LogInfo("Stereo-chemical problem in sidechain " + \
                         "of residue " + str(res))
 
-def BuildFromRawModel(mhandle, scorer = None, use_amber_ff=False, extra_force_fields=list()):
+def BuildFromRawModel(mhandle, use_amber_ff=False, extra_force_fields=list()):
     '''Build a model starting with a raw model (see :func:`BuildRawModel`).
 
     This function implements a recommended pipeline to generate complete models
@@ -411,7 +407,13 @@ def BuildFromRawModel(mhandle, scorer = None, use_amber_ff=False, extra_force_fi
     :ref:`above <modelling_steps_example>`. If you wish to use your own
     pipeline, you can use that code as a starting point for your own custom
     modelling pipeline. For reproducibility, we recommend that you keep copies
-    of custom pipelines. 
+    of custom pipelines.
+
+    If you wish to use a custom scorer, you can attach your own scorers to the
+    `mhandle`. In that case you need to make sure that `mhandle.backbone_scorer`
+    and `mhandle.backbone_scorer_env` are both set and are consistent. You can
+    also call :meth:`SetupDefaultBackboneScorer` and adapt the default scorer
+    for your purposes.
 
     If the function fails to close all gaps, it will produce a warning and
     return an incomplete model.
@@ -453,30 +455,32 @@ def BuildFromRawModel(mhandle, scorer = None, use_amber_ff=False, extra_force_fi
     torsion_sampler = loop.LoadTorsionSamplerCoil()
     merge_distance = 4
 
-    if scorer == None:
-      scorer = SetupBackboneScorer(mhandle)
+    if IsBackboneScorerSet(mhandle) and IsBackboneScorerSet(mhandle):
+        ost.LogInfo("Using scorer which is already set in modelling handle.")
+    else:
+        SetupDefaultBackboneScorer(mhandle)
 
     # remove terminal gaps and close small deletions
     RemoveTerminalGaps(mhandle)
-    CloseSmallDeletions(mhandle, scorer)
+    CloseSmallDeletions(mhandle)
 
     # iteratively merge gaps of distance i and fill loops by database
     for distance in range(merge_distance):
         MergeGapsByDistance(mhandle, distance)
-        FillLoopsByDatabase(mhandle, scorer, fragment_db, structure_db,
+        FillLoopsByDatabase(mhandle, fragment_db, structure_db,
                             torsion_sampler, min_loops_required=-1,
                             max_res_extension=6)
-    FillLoopsByDatabase(mhandle, scorer, fragment_db, structure_db,
+    FillLoopsByDatabase(mhandle, fragment_db, structure_db,
                         torsion_sampler, min_loops_required=-1)
-    FillLoopsByDatabase(mhandle, scorer, fragment_db, structure_db,
+    FillLoopsByDatabase(mhandle, fragment_db, structure_db,
                         torsion_sampler)
 
     # close remaining gaps by Monte Carlo
-    FillLoopsByMonteCarlo(mhandle, scorer, torsion_sampler)
-    CloseLargeDeletions(mhandle, scorer, structure_db)
+    FillLoopsByMonteCarlo(mhandle, torsion_sampler)
+    CloseLargeDeletions(mhandle, structure_db)
 
     # build sidechains
-    BuildSidechains(mhandle, merge_distance, scorer, fragment_db,
+    BuildSidechains(mhandle, merge_distance, fragment_db,
                     structure_db, torsion_sampler)
 
     # minimize energy of final model using molecular mechanics
diff --git a/modelling/pymod/export_model.cc b/modelling/pymod/export_model.cc
index 1de295e835290e1b40506cd6cd89934a579bb608..6fb5a66c77274630eeaff52ffd47d2498b6567cc 100644
--- a/modelling/pymod/export_model.cc
+++ b/modelling/pymod/export_model.cc
@@ -23,35 +23,41 @@ int WrapCountEnclosedIns(ModellingHandle& mhandle, const StructuralGap& gap) {
 }
 
 promod3::scoring::BackboneOverallScorerPtr 
-WrapGetBackboneScorer(ModellingHandle& mhandle){
-  if(!mhandle.backbone_scorer){
-    String err = "backbone_scorer must first be properly initialized ";
-    err += "before it can be used!";
-    throw promod3::Error(err);
+WrapGetBackboneScorer(ModellingHandle& mhandle) {
+  if (!mhandle.backbone_scorer) {
+    throw promod3::Error("The backbone_scorer must be properly initialized "
+                         "before it can be used!");
   }
   return mhandle.backbone_scorer;
 }
 
 void WrapSetBackboneScorer(ModellingHandle& mhandle, 
-                         promod3::scoring::BackboneOverallScorerPtr scorer){
+                           promod3::scoring::BackboneOverallScorerPtr scorer) {
   mhandle.backbone_scorer = scorer;
 }
 
 promod3::scoring::BackboneScoreEnvPtr 
-WrapGetBackboneScorerEnv(ModellingHandle& mhandle){
-  if(!mhandle.backbone_scorer_env){
-    String err = "backbone_scorer_env must first be properly initialized ";
-    err += "before it can be used!";
-    throw promod3::Error(err);
+WrapGetBackboneScorerEnv(ModellingHandle& mhandle) {
+  if (!mhandle.backbone_scorer_env) {
+    throw promod3::Error("The backbone_scorer_env must be properly initialized "
+                         "before it can be used!");
   }
   return mhandle.backbone_scorer_env;
 }
 
 void WrapSetBackboneScorerEnv(ModellingHandle& mhandle, 
-                              promod3::scoring::BackboneScoreEnvPtr env){
+                              promod3::scoring::BackboneScoreEnvPtr env) {
   mhandle.backbone_scorer_env = env;
 }
 
+// not really needed in C++ as we can do the check below directly
+bool WrapIsBackboneScorerSet(ModellingHandle& mhandle) {
+  return bool(mhandle.backbone_scorer);
+}
+bool WrapIsBackboneScorerEnvSet(ModellingHandle& mhandle) {
+  return bool(mhandle.backbone_scorer_env);
+}
+
 } // anon ns
 
 void export_model()
@@ -71,7 +77,9 @@ void export_model()
   def("CountEnclosedInsertions", WrapCountEnclosedIns, (arg("mhandle"),arg("gap")));
   def("MergeGaps", MergeGaps, (arg("mhandle"),arg("index")));
   def("RemoveTerminalGaps", RemoveTerminalGaps, (arg("mhandle")));
-  def("SetupDefaultBackboneScorer", &SetupDefaultBackboneScorer,(arg("mhandle")));
+  def("SetupDefaultBackboneScorer", &SetupDefaultBackboneScorer, (arg("mhandle")));
+  def("IsBackboneScorerSet", &WrapIsBackboneScorerSet, (arg("mhandle")));
+  def("IsBackboneScorerEnvSet", &WrapIsBackboneScorerEnvSet, (arg("mhandle")));
   def("BuildRawModel", BuildRawModelHandle, 
       (arg("aln"),
        arg("include_ligands")=false,
diff --git a/modelling/src/model.cc b/modelling/src/model.cc
index 8d7b32f73eac5505089768162c2fe7c3e8b85189..1421da48ae2cb040d3ec09cc541e0df2e1f46e2e 100644
--- a/modelling/src/model.cc
+++ b/modelling/src/model.cc
@@ -218,7 +218,7 @@ void AttachScorer(BackboneOverallScorerPtr overall_scorer,
 
 void SetupDefaultBackboneScorer(ModellingHandle& mhandle){
   
-  //setup environment
+  // setup environment
   BackboneScoreEnvPtr env(new BackboneScoreEnv(mhandle.seqres));
   env->SetInitialEnvironment(mhandle.model);
 
@@ -236,6 +236,7 @@ void SetupDefaultBackboneScorer(ModellingHandle& mhandle){
 
   mhandle.backbone_scorer_env = env;
   mhandle.backbone_scorer = scorer;
+  LOG_INFO("Initialized default backbone scorer for modelling.");
 }
 
 bool CopyConserved(ResidueView src_res, ResidueHandle dst_res, XCSEditor& edi,
diff --git a/modelling/src/monte_carlo_scorer.hh b/modelling/src/monte_carlo_scorer.hh
index 0651af7b5c7bffa34e2ed60b3619af39cabed230..799f0e60a56e5df5b2d4eb96bf8d34d94274de9c 100644
--- a/modelling/src/monte_carlo_scorer.hh
+++ b/modelling/src/monte_carlo_scorer.hh
@@ -7,7 +7,7 @@
 #include <ost/mol/mol.hh>
 
 // TODO: follow define, kill backbone_loop_score
-// #define NEW_STYLE_SCORING
+#define NEW_STYLE_SCORING
 #include <promod3/loop/backbone_loop_score.hh>
 #include <promod3/scoring/backbone_overall_scorer.hh>
 
diff --git a/modelling/tests/test_close_gaps.py b/modelling/tests/test_close_gaps.py
index 7119e5a6a9f65774c920590edad8ea42b9bfdaac..49bb60b26bcdb791a373e85c1bf9751ab31f2c8a 100644
--- a/modelling/tests/test_close_gaps.py
+++ b/modelling/tests/test_close_gaps.py
@@ -161,10 +161,10 @@ class CloseGapsTests(unittest.TestCase):
         aln.AttachView(1, tpl.CreateFullView())
         mhandle = modelling.BuildRawModel(aln)
         self.assertEqual(len(mhandle.gaps), 1)
-        # obtain the scorer
-        scorer = modelling.SetupBackboneScorer(mhandle)
+        # close it
+        modelling.SetupDefaultBackboneScorer(mhandle)
         nlogs = len(self.log.messages['INFO'])
-        modelling.CloseSmallDeletions(mhandle, scorer)
+        modelling.CloseSmallDeletions(mhandle)
         self.assertEqual(len(mhandle.gaps), 0)
         # check backbone
         self.backboneCheck(mhandle.model, 'GGGGGG')
@@ -190,8 +190,8 @@ class CloseGapsTests(unittest.TestCase):
         mhandle = modelling.BuildRawModel(alns)
         self.assertEqual(len(mhandle.gaps), 2)
         # do it
-        scorer = modelling.SetupBackboneScorer(mhandle)
-        modelling.CloseSmallDeletions(mhandle, scorer)
+        modelling.SetupDefaultBackboneScorer(mhandle)
+        modelling.CloseSmallDeletions(mhandle)
         # check
         self.assertEqual(len(mhandle.gaps), 0)
         self.backboneCheckHandle(mhandle)
@@ -287,8 +287,8 @@ class CloseGapsTests(unittest.TestCase):
     def testFillGapsByDatabase(self):
         '''Get rid of 2 gaps by db.'''
         mhandle = self.getGapTest()
-        scorer = modelling.SetupBackboneScorer(mhandle)
-        modelling.FillLoopsByDatabase(mhandle, scorer, self.frag_db,
+        modelling.SetupDefaultBackboneScorer(mhandle)
+        modelling.FillLoopsByDatabase(mhandle, self.frag_db,
                                       self.structure_db,
                                       self.torsion_sampler)
         self.assertEqual(len(mhandle.gaps), 0)
@@ -299,8 +299,8 @@ class CloseGapsTests(unittest.TestCase):
     def testFillGapsByDatabaseDeletion(self):
         '''Get rid of deletion by db.'''
         mhandle = self.getGapTestDeletion()
-        scorer = modelling.SetupBackboneScorer(mhandle)
-        modelling.FillLoopsByDatabase(mhandle, scorer, self.frag_db,
+        modelling.SetupDefaultBackboneScorer(mhandle)
+        modelling.FillLoopsByDatabase(mhandle, self.frag_db,
                                       self.structure_db,
                                       self.torsion_sampler)
         self.assertEqual(len(mhandle.gaps), 0)
@@ -311,8 +311,8 @@ class CloseGapsTests(unittest.TestCase):
     def testFillGapsByDatabaseInsertion(self):
         '''Get rid of insertion by db.'''
         mhandle = self.getGapTestInsertion()
-        scorer = modelling.SetupBackboneScorer(mhandle)
-        modelling.FillLoopsByDatabase(mhandle, scorer, self.frag_db,
+        modelling.SetupDefaultBackboneScorer(mhandle)
+        modelling.FillLoopsByDatabase(mhandle, self.frag_db,
                                       self.structure_db,
                                       self.torsion_sampler)
         self.assertEqual(len(mhandle.gaps), 0)
@@ -323,8 +323,8 @@ class CloseGapsTests(unittest.TestCase):
     def testFillGapsByDatabaseInsertionTerminal(self):
         '''Get rid of insertion by db close to terminal (needs FullExtender).'''
         mhandle = self.getGapTestInsertionTerminal()
-        scorer = modelling.SetupBackboneScorer(mhandle)
-        modelling.FillLoopsByDatabase(mhandle, scorer, self.frag_db,
+        modelling.SetupDefaultBackboneScorer(mhandle)
+        modelling.FillLoopsByDatabase(mhandle, self.frag_db,
                                       self.structure_db,
                                       self.torsion_sampler,
                                       use_full_extender=True)
@@ -336,8 +336,8 @@ class CloseGapsTests(unittest.TestCase):
     def testFillGapsByDatabaseTerminal(self):
         '''Terminal loops are not altered.'''
         mhandle = self.getGapTestTerminal()
-        scorer = modelling.SetupBackboneScorer(mhandle)
-        modelling.FillLoopsByDatabase(mhandle, scorer, self.frag_db,
+        modelling.SetupDefaultBackboneScorer(mhandle)
+        modelling.FillLoopsByDatabase(mhandle, self.frag_db,
                                       self.structure_db,
                                       self.torsion_sampler)
         self.assertEqual(len(mhandle.gaps), 2)
@@ -345,8 +345,8 @@ class CloseGapsTests(unittest.TestCase):
     def testFillGapsByDatabaseNoSE(self):
         '''Get rid of 2 gaps by db (without scoring extender).'''
         mhandle = self.getGapTest()
-        scorer = modelling.SetupBackboneScorer(mhandle)
-        modelling.FillLoopsByDatabase(mhandle, scorer, self.frag_db,
+        modelling.SetupDefaultBackboneScorer(mhandle)
+        modelling.FillLoopsByDatabase(mhandle, self.frag_db,
                                       self.structure_db,
                                       self.torsion_sampler,
                                       use_scoring_extender=False)
@@ -358,8 +358,8 @@ class CloseGapsTests(unittest.TestCase):
     def testFillGapsByDatabaseDeletionNoSE(self):
         '''Get rid of deletion by db (without scoring extender).'''
         mhandle = self.getGapTestDeletion()
-        scorer = modelling.SetupBackboneScorer(mhandle)
-        modelling.FillLoopsByDatabase(mhandle, scorer, self.frag_db,
+        modelling.SetupDefaultBackboneScorer(mhandle)
+        modelling.FillLoopsByDatabase(mhandle, self.frag_db,
                                       self.structure_db,
                                       self.torsion_sampler,
                                       use_scoring_extender=False)
@@ -371,8 +371,8 @@ class CloseGapsTests(unittest.TestCase):
     def testFillGapsByDatabaseInsertionNoSE(self):
         '''Get rid of insertion by db (without scoring extender).'''
         mhandle = self.getGapTestInsertion()
-        scorer = modelling.SetupBackboneScorer(mhandle)
-        modelling.FillLoopsByDatabase(mhandle, scorer, self.frag_db,
+        modelling.SetupDefaultBackboneScorer(mhandle)
+        modelling.FillLoopsByDatabase(mhandle, self.frag_db,
                                       self.structure_db,
                                       self.torsion_sampler,
                                       use_scoring_extender=False)
@@ -384,8 +384,8 @@ class CloseGapsTests(unittest.TestCase):
     def testFillGapsByDatabaseTerminalNoSE(self):
         '''Terminal loops are not altered (without scoring extender).'''
         mhandle = self.getGapTestTerminal()
-        scorer = modelling.SetupBackboneScorer(mhandle)
-        modelling.FillLoopsByDatabase(mhandle, scorer, self.frag_db,
+        modelling.SetupDefaultBackboneScorer(mhandle)
+        modelling.FillLoopsByDatabase(mhandle, self.frag_db,
                                       self.structure_db,
                                       self.torsion_sampler,
                                       use_scoring_extender=False)
@@ -394,8 +394,8 @@ class CloseGapsTests(unittest.TestCase):
     def testFillGapsByDatabaseHomoOligomer(self):
         '''Get rid of 2 gaps by db for homo oligomers.'''
         mhandle = self.getRawModelOligo("data/2aoh-1_cut")
-        scorer = modelling.SetupBackboneScorer(mhandle)
-        modelling.FillLoopsByDatabase(mhandle, scorer, self.frag_db,
+        modelling.SetupDefaultBackboneScorer(mhandle)
+        modelling.FillLoopsByDatabase(mhandle, self.frag_db,
                                       self.structure_db,
                                       self.torsion_sampler)
         self.assertEqual(len(mhandle.gaps), 0)
@@ -404,8 +404,8 @@ class CloseGapsTests(unittest.TestCase):
     def testFillGapsByDatabaseHeteroOligomer(self):
         '''Get rid of 2 gaps by db for hetero oligomers.'''
         mhandle = self.getRawModelOligo("data/5d52-1_cut")
-        scorer = modelling.SetupBackboneScorer(mhandle)
-        modelling.FillLoopsByDatabase(mhandle, scorer, self.frag_db,
+        modelling.SetupDefaultBackboneScorer(mhandle)
+        modelling.FillLoopsByDatabase(mhandle, self.frag_db,
                                       self.structure_db,
                                       self.torsion_sampler)
         self.assertEqual(len(mhandle.gaps), 0)
@@ -416,8 +416,8 @@ class CloseGapsTests(unittest.TestCase):
     def testFillGapsByMonteCarlo(self):
         '''Get rid of 2 gaps by MC.'''
         mhandle = self.getGapTest()
-        scorer = modelling.SetupBackboneScorer(mhandle)
-        modelling.FillLoopsByMonteCarlo(mhandle, scorer, self.torsion_sampler,
+        modelling.SetupDefaultBackboneScorer(mhandle)
+        modelling.FillLoopsByMonteCarlo(mhandle, self.torsion_sampler,
                                         mc_steps=100)
         self.assertEqual(len(mhandle.gaps), 0)
         # check backbone
@@ -427,8 +427,8 @@ class CloseGapsTests(unittest.TestCase):
     def testFillGapsByMonteCarloDeletion(self):
         '''Get rid of deletion by MC.'''
         mhandle = self.getGapTestDeletion()
-        scorer = modelling.SetupBackboneScorer(mhandle)
-        modelling.FillLoopsByMonteCarlo(mhandle, scorer, self.torsion_sampler,
+        modelling.SetupDefaultBackboneScorer(mhandle)
+        modelling.FillLoopsByMonteCarlo(mhandle, self.torsion_sampler,
                                         mc_steps=100)
         self.assertEqual(len(mhandle.gaps), 0)
         # check backbone
@@ -438,8 +438,8 @@ class CloseGapsTests(unittest.TestCase):
     def testFillGapsByMonteCarloInsertion(self):
         '''Get rid of insertion by MC.'''
         mhandle = self.getGapTestInsertion()
-        scorer = modelling.SetupBackboneScorer(mhandle)
-        modelling.FillLoopsByMonteCarlo(mhandle, scorer, self.torsion_sampler,
+        modelling.SetupDefaultBackboneScorer(mhandle)
+        modelling.FillLoopsByMonteCarlo(mhandle, self.torsion_sampler,
                                         mc_steps=100)
         self.assertEqual(len(mhandle.gaps), 0)
         # check backbone
@@ -449,16 +449,16 @@ class CloseGapsTests(unittest.TestCase):
     def testFillGapsByMonteCarloTerminal(self):
         '''Terminal loops are not altered.'''
         mhandle = self.getGapTestTerminal()
-        scorer = modelling.SetupBackboneScorer(mhandle)
-        modelling.FillLoopsByMonteCarlo(mhandle, scorer, self.torsion_sampler,
+        modelling.SetupDefaultBackboneScorer(mhandle)
+        modelling.FillLoopsByMonteCarlo(mhandle, self.torsion_sampler,
                                         mc_steps=100)
         self.assertEqual(len(mhandle.gaps), 2)
         
     def testFillGapsByMonteCarloHomoOligomer(self):
         '''Get rid of 2 gaps by db for homo oligomers.'''
         mhandle = self.getRawModelOligo("data/2aoh-1_cut")
-        scorer = modelling.SetupBackboneScorer(mhandle)
-        modelling.FillLoopsByMonteCarlo(mhandle, scorer, self.torsion_sampler,
+        modelling.SetupDefaultBackboneScorer(mhandle)
+        modelling.FillLoopsByMonteCarlo(mhandle, self.torsion_sampler,
                                         mc_steps=100)
         self.assertEqual(len(mhandle.gaps), 0)
         self.backboneCheckHandle(mhandle)
@@ -466,8 +466,8 @@ class CloseGapsTests(unittest.TestCase):
     def testFillGapsByMonteCarloHeteroOligomer(self):
         '''Get rid of 2 gaps by db for hetero oligomers.'''
         mhandle = self.getRawModelOligo("data/5d52-1_cut")
-        scorer = modelling.SetupBackboneScorer(mhandle)
-        modelling.FillLoopsByMonteCarlo(mhandle, scorer, self.torsion_sampler,
+        modelling.SetupDefaultBackboneScorer(mhandle)
+        modelling.FillLoopsByMonteCarlo(mhandle, self.torsion_sampler,
                                         mc_steps=100)
         self.assertEqual(len(mhandle.gaps), 0)
         self.backboneCheckHandle(mhandle)
@@ -482,14 +482,14 @@ class CloseGapsTests(unittest.TestCase):
         mhandle = modelling.BuildRawModel(aln)
         self.assertEqual(len(mhandle.gaps), 3)
         # model termini
-        scorer = modelling.SetupBackboneScorer(mhandle)
-        modelling.ModelTermini(mhandle, scorer, self.torsion_sampler,
+        modelling.SetupDefaultBackboneScorer(mhandle)
+        modelling.ModelTermini(mhandle, self.torsion_sampler,
                                mc_steps=100)
         self.assertEqual(len(mhandle.gaps), 1)
         myseq = ''.join([r.one_letter_code for r in mhandle.model.residues])
         self.assertEqual(myseq, 'AAAAGGGGGGGGGGGGGGGGGGGGAAAAAA')
         # model rest
-        modelling.FillLoopsByDatabase(mhandle, scorer, self.frag_db,
+        modelling.FillLoopsByDatabase(mhandle, self.frag_db,
                                       self.structure_db,
                                       self.torsion_sampler)
         self.assertEqual(len(mhandle.gaps), 0)
@@ -512,8 +512,8 @@ class CloseGapsTests(unittest.TestCase):
         mhandle = modelling.BuildRawModel(alns)
         self.assertEqual(len(mhandle.gaps), 4)
         # model termini
-        scorer = modelling.SetupBackboneScorer(mhandle)
-        modelling.ModelTermini(mhandle, scorer, self.torsion_sampler,
+        modelling.SetupDefaultBackboneScorer(mhandle)
+        modelling.ModelTermini(mhandle, self.torsion_sampler,
                                mc_steps=100)
         self.assertEqual(len(mhandle.gaps), 0)
         self.assertEqual(mhandle.model.residue_count, 63)
@@ -529,9 +529,9 @@ class CloseGapsTests(unittest.TestCase):
             seq.CreateSequence('tpl', 'NGGTLLIPNGTYHFLGIQMKSNVHIRVE'))
         aln.AttachView(1, tpl.CreateFullView())
         mhandle = modelling.BuildRawModel(aln)
-        scorer = modelling.SetupBackboneScorer(mhandle)
+        modelling.SetupDefaultBackboneScorer(mhandle)
         self.assertEqual(len(mhandle.gaps), 1)
-        modelling.CloseLargeDeletions(mhandle, scorer, self.structure_db,
+        modelling.CloseLargeDeletions(mhandle, self.structure_db,
                                       num_fragments=100)
         self.assertEqual(len(mhandle.gaps), 0)
         # check backbone
@@ -545,10 +545,10 @@ class CloseGapsTests(unittest.TestCase):
             seq.CreateSequence('tpl', 'NGGTLLIPNGTYHFLGIQMKSNVHIRVE'))
         aln.AttachView(1, tpl.CreateFullView())
         mhandle = modelling.BuildRawModel(aln)
-        scorer = modelling.SetupBackboneScorer(mhandle)
+        modelling.SetupDefaultBackboneScorer(mhandle)
         modelling.MergeGapsByDistance(mhandle, 1)
         self.assertEqual(len(mhandle.gaps), 1)
-        modelling.CloseLargeDeletions(mhandle, scorer, self.structure_db,
+        modelling.CloseLargeDeletions(mhandle, self.structure_db,
                                       num_fragments=100)
         self.assertEqual(len(mhandle.gaps), 0)
         # check backbone
@@ -562,9 +562,9 @@ class CloseGapsTests(unittest.TestCase):
             seq.CreateSequence('tpl', 'NGGTLLIPNGTYHFLGIQMKSNVHIRVE'))
         aln.AttachView(1, tpl.CreateFullView())
         mhandle = modelling.BuildRawModel(aln)
-        scorer = modelling.SetupBackboneScorer(mhandle)
+        modelling.SetupDefaultBackboneScorer(mhandle)
         self.assertEqual(len(mhandle.gaps), 1)
-        modelling.CloseLargeDeletions(mhandle, scorer, self.structure_db,
+        modelling.CloseLargeDeletions(mhandle, self.structure_db,
                                       num_fragments=100)
         self.assertEqual(len(mhandle.gaps), 0)
         # check backbone
@@ -579,9 +579,9 @@ class CloseGapsTests(unittest.TestCase):
         aln.AttachView(1, tpl.CreateFullView())
         mhandle = modelling.BuildRawModel(aln)
         modelling.RemoveTerminalGaps(mhandle)
-        scorer = modelling.SetupBackboneScorer(mhandle)
+        modelling.SetupDefaultBackboneScorer(mhandle)
         self.assertEqual(len(mhandle.gaps), 1)
-        modelling.CloseLargeDeletions(mhandle, scorer, self.structure_db,
+        modelling.CloseLargeDeletions(mhandle, self.structure_db,
                                       num_fragments=100)
         self.assertEqual(len(mhandle.gaps), 0)
         # check backbone
@@ -602,9 +602,9 @@ class CloseGapsTests(unittest.TestCase):
         alns.append(aln_A)
         alns.append(aln_B)
         mhandle = modelling.BuildRawModel(alns)
-        scorer = modelling.SetupBackboneScorer(mhandle)
+        modelling.SetupDefaultBackboneScorer(mhandle)
         self.assertEqual(len(mhandle.gaps), 2)
-        modelling.CloseLargeDeletions(mhandle, scorer, self.structure_db,
+        modelling.CloseLargeDeletions(mhandle, self.structure_db,
                                       num_fragments=100)
         self.assertEqual(len(mhandle.gaps), 0)
         # check backbone
diff --git a/modelling/tests/test_pipeline.py b/modelling/tests/test_pipeline.py
index 1afff3ac00b237a201f872fa9bfc8f41a0f855bf..acaa032be02e4ae2ac086480aa5b89fcf505e37c 100644
--- a/modelling/tests/test_pipeline.py
+++ b/modelling/tests/test_pipeline.py
@@ -44,11 +44,11 @@ from promod3 import loop, modelling, core
 # io.SavePDB(final_model, 'data/1crn_build.pdb')
 # # step-by-step - loop
 # mhandle = modelling.BuildRawModel(aln)
-# scorer = modelling.SetupBackboneScorer(mhandle)
+# modelling.SetupDefaultBackboneScorer(mhandle)
 # frag_db = loop.LoadFragDB()
 # structure_db = loop.LoadStructureDB()
 # torsion_sampler = loop.LoadTorsionSamplerCoil()
-# modelling.FillLoopsByDatabase(mhandle, scorer, frag_db,
+# modelling.FillLoopsByDatabase(mhandle, frag_db,
 #                               structure_db,
 #                               torsion_sampler)
 # io.SavePDB(mhandle.model, 'data/1crn_rec.pdb')
@@ -218,8 +218,8 @@ class PipelineTests(unittest.TestCase):
     def testLoopReconstruction(self):
         '''Check loop reconstruction.'''
         mhandle = self.getRawModel()
-        scorer = modelling.SetupBackboneScorer(mhandle)
-        modelling.FillLoopsByDatabase(mhandle, scorer, self.frag_db,
+        modelling.SetupDefaultBackboneScorer(mhandle)
+        modelling.FillLoopsByDatabase(mhandle, self.frag_db,
                                       self.structure_db,
                                       self.torsion_sampler)
         self.assertEqual(len(mhandle.gaps), 0)
diff --git a/scoring/pymod/export_backbone_score.cc b/scoring/pymod/export_backbone_score.cc
index 0715d3bf958a7bdb94c35f123e230a8c559e4a95..ad460ebf25cd2ee75a999a05e073756928903aff 100644
--- a/scoring/pymod/export_backbone_score.cc
+++ b/scoring/pymod/export_backbone_score.cc
@@ -18,18 +18,45 @@ using namespace boost::python;
 
 namespace {
 
-  BackboneScoreEnvPtr WrapInitOne(const ost::seq::SequenceHandle& seqres){
+  BackboneScoreEnvPtr WrapInitSeq(const ost::seq::SequenceHandle& seqres) {
     ost::seq::SequenceList seq_list = ost::seq::CreateSequenceList();
     seq_list.AddSequence(seqres);
     BackboneScoreEnvPtr env(new BackboneScoreEnv(seq_list));
     return env;
   }
 
-  BackboneScoreEnvPtr WrapInitTwo(const ost::seq::SequenceList& seqres){
+  BackboneScoreEnvPtr WrapInitSeqList(const ost::seq::SequenceList& seqres) {
     BackboneScoreEnvPtr env(new BackboneScoreEnv(seqres));
     return env;
   }
 
+  BackboneScoreEnvPtr WrapInitStr(const String& seqres) {
+    ost::seq::SequenceList seq_list = ost::seq::CreateSequenceList();
+    ost::seq::SequenceHandle s = ost::seq::CreateSequence("A", seqres);
+    seq_list.AddSequence(s);
+    BackboneScoreEnvPtr env(new BackboneScoreEnv(seq_list));
+    return env;
+  }
+
+  BackboneScoreEnvPtr WrapInitStrList(const boost::python::list& seqres) {
+    ost::seq::SequenceList seq_list = ost::seq::CreateSequenceList();
+    for (uint i = 0; i < boost::python::len(seqres); ++i) {
+      String s = boost::python::extract<String>(seqres[i]);
+      ost::seq::SequenceHandle sh = ost::seq::CreateSequence("A", s);
+      seq_list.AddSequence(sh);
+    }
+    BackboneScoreEnvPtr env(new BackboneScoreEnv(seq_list));
+    return env;
+  }
+  
+  void WrapSetEnvironmentResNum(BackboneScoreEnvPtr env,
+                                const promod3::loop::BackboneList& bb_list,
+                                const ost::mol::ResNum& start_resnum,
+                                uint chain_index) {
+    uint num = start_resnum.GetNum();
+    env->SetEnvironment(bb_list, num, chain_index);
+  }
+
   void WrapSetPsipredPrediction(BackboneScoreEnvPtr env,
                                 loop::PsipredPredictionPtr pp){
     env->SetPsipredPrediction(pp);
@@ -108,16 +135,27 @@ void export_BackboneScore() {
 
   // score environment
   class_<BackboneScoreEnv, BackboneScoreEnvPtr>("BackboneScoreEnv", no_init)
-    .def("__init__", make_constructor(&WrapInitOne))
-    .def("__init__", make_constructor(&WrapInitTwo))
-    .def("SetInitialEnvironment", &BackboneScoreEnv::SetInitialEnvironment,(arg("env_structure")))
-    .def("SetEnvironment", &BackboneScoreEnv::SetEnvironment,(arg("env_bb_list"), arg("start_resnum"), arg("chain_idx") = 0))
-    .def("ClearEnvironment", &BackboneScoreEnv::ClearEnvironment,(arg("start_resnum"), arg("num_residues"), arg("chain_idx") = 0))
-    .def("SetPsipredPrediction", &WrapSetPsipredPrediction,("pred"))
-    .def("SetPsipredPrediction", &WrapSetPsipredPredictionList,("pred"))
-    .def("SetMap", &BackboneScoreEnv::SetMap,(arg("map"),arg("resolution"),arg("all_atom")=false))
-    .def("AddPairwiseFunction", &BackboneScoreEnv::AddPairwiseFunction,(arg("function"),arg("function_type")))
-    .def("ApplyPairwiseFunction", &BackboneScoreEnv::ApplyPairwiseFunction,(arg("chain_idx_one"),arg("resnum_one"),arg("chain_idx_two"),arg("resnum_two"),arg("f_idx")))
+    .def("__init__", make_constructor(&WrapInitSeq))
+    .def("__init__", make_constructor(&WrapInitSeqList))
+    .def("__init__", make_constructor(&WrapInitStr))
+    .def("__init__", make_constructor(&WrapInitStrList))
+    .def("SetInitialEnvironment", &BackboneScoreEnv::SetInitialEnvironment,
+         (arg("env_structure")))
+    .def("SetEnvironment", &BackboneScoreEnv::SetEnvironment,
+         (arg("bb_list"), arg("start_resnum"), arg("chain_idx") = 0))
+    .def("SetEnvironment", &WrapSetEnvironmentResNum,
+         (arg("bb_list"), arg("start_resnum"), arg("chain_idx") = 0))
+    .def("ClearEnvironment", &BackboneScoreEnv::ClearEnvironment,
+         (arg("start_resnum"), arg("num_residues"), arg("chain_idx") = 0))
+    .def("SetPsipredPrediction", &WrapSetPsipredPrediction, (arg("pred")))
+    .def("SetPsipredPrediction", &WrapSetPsipredPredictionList, (arg("pred")))
+    .def("SetMap", &BackboneScoreEnv::SetMap,
+         (arg("map"), arg("resolution"), arg("all_atom")=false))
+    .def("AddPairwiseFunction", &BackboneScoreEnv::AddPairwiseFunction,
+         (arg("function"), arg("function_type")))
+    .def("ApplyPairwiseFunction", &BackboneScoreEnv::ApplyPairwiseFunction,
+         (arg("chain_idx_one"), arg("resnum_one"), arg("chain_idx_two"),
+          arg("resnum_two"), arg("f_idx")))
     .def("GetSeqres", &BackboneScoreEnv::GetSeqres)
   ;
 
@@ -129,6 +167,7 @@ void export_BackboneScore() {
   class_<BackboneOverallScorer, BackboneOverallScorerPtr>
     ("BackboneOverallScorer", init<>())
     .def("Contains", &BackboneOverallScorer::Contains, (arg("key")))
+    .def("Get", &BackboneOverallScorer::Get, (arg("key")))
     .def("__getitem__", &bos_getitem, (arg("key")))
     .def("__setitem__", &bos_setitem, (arg("key"), arg("scorer")))
     .def("Calculate", &WrapCalculate,
diff --git a/scoring/src/backbone_score_base.cc b/scoring/src/backbone_score_base.cc
index f5304698a83de4f9e94bae6ace7136ebd61709e0..deff570cc255807cd69b4b8c408b674af38223bc 100644
--- a/scoring/src/backbone_score_base.cc
+++ b/scoring/src/backbone_score_base.cc
@@ -53,7 +53,7 @@ void IdxHandler::SetupScoreCalculation(const loop::BackboneList& bb_list,
   end_idx = start_idx + bb_list_size - 1;
 
   // let's finally check the range of the end_idx
-  if (end_idx >= chain_sizes_[chain_idx]) {
+  if (end_idx >= chain_start_idx_[chain_idx] + chain_sizes_[chain_idx]) {
     throw promod3::Error("Invalid End ResNum!");
   }
 }