diff --git a/loop/src/all_atom_positions.cc b/loop/src/all_atom_positions.cc
index 42925e2b5921397231e1f2bbbaf6b95a2b31d3ce..2dad21d0e0c802bd81cc771af31c4de0127a6db5 100644
--- a/loop/src/all_atom_positions.cc
+++ b/loop/src/all_atom_positions.cc
@@ -7,10 +7,24 @@
 
 namespace promod3 { namespace loop {
 
+namespace {
+
 // default chem. type and class for amino acids
 const ost::mol::ChemClass aa_chem_class(ost::mol::ChemClass::L_PEPTIDE_LINKING);
 const ost::mol::ChemType aa_chem_type(ost::mol::ChemType::AMINOACIDS);
 
+// set residue props
+void SetResidueProps(ost::mol::ResidueHandle& res, char olc) {
+  res.SetOneLetterCode(olc);
+  res.SetChemClass(aa_chem_class);
+  res.SetChemType(aa_chem_type);
+  res.SetIsProtein(true);
+}
+
+} // anon ns
+
+///////////////////////////////////////////////////////////////////////////////
+
 AllAtomPositions::AllAtomPositions(const String& sequence)
                                   : aa_lookup_(AminoAcidLookup::GetInstance()) {
   Initialize(sequence);
@@ -245,9 +259,7 @@ ost::mol::EntityHandle AllAtomPositions::ToEntity() const {
       }
     }
     // set residue data
-    res.SetOneLetterCode(aa_lookup_.GetOLC(GetAA(res_idx)));
-    res.SetChemClass(aa_chem_class);
-    res.SetChemType(aa_chem_type);
+    SetResidueProps(res, aa_lookup_.GetOLC(GetAA(res_idx)));
   }
   // set connections
   ost::conop::HeuristicProcessor heu_proc;
@@ -285,9 +297,7 @@ void AllAtomPositions::InsertInto(uint res_idx, ost::mol::ChainHandle& chain,
     // rename if needed
     edi.RenameResidue(res, rname);
   }
-  res.SetOneLetterCode(aa_lookup_.GetOLC(aa));
-  res.SetChemClass(aa_chem_class);
-  res.SetChemType(aa_chem_type);
+  SetResidueProps(res, aa_lookup_.GetOLC(aa));
 
   // set new atom positions
   bool backbone_added = false;
diff --git a/loop/src/backbone.cc b/loop/src/backbone.cc
index 0a04aa1260134c0c718f9b05387d298886f9b754..edb4dd63c7dbbf09997f30d0395166e21a9104ad 100644
--- a/loop/src/backbone.cc
+++ b/loop/src/backbone.cc
@@ -6,10 +6,22 @@
 
 namespace promod3 { namespace loop {
 
+namespace {
+
 // default chem. type and class for amino acids
 const ost::mol::ChemClass aa_chem_class(ost::mol::ChemClass::L_PEPTIDE_LINKING);
 const ost::mol::ChemType aa_chem_type(ost::mol::ChemType::AMINOACIDS);
 
+// set residue props
+void SetResidueProps(ost::mol::ResidueHandle& res, char olc) {
+  res.SetOneLetterCode(olc);
+  res.SetChemClass(aa_chem_class);
+  res.SetChemType(aa_chem_type);
+  res.SetIsProtein(true);
+}
+
+} // anon ns
+
 ///////////////////////////////////////////////////////////////////////////////
 // Backbone public
 Backbone::Backbone(const geom::Vec3& n, const geom::Vec3& ca, 
@@ -131,7 +143,8 @@ BackboneList::BackboneList(const String& sequence,
   }
 }
 
-ost::mol::EntityHandle BackboneList::ToEntity() const{
+ost::mol::EntityHandle BackboneList::ToEntity() const {
+  // make entity
   ost::mol::EntityHandle ent = ost::mol::CreateEntity();
   ost::mol::XCSEditor edi = ent.EditXCS(ost::mol::BUFFERED_EDIT);
   ost::mol::ChainHandle chain = edi.InsertChain("A");
@@ -152,14 +165,14 @@ ost::mol::EntityHandle BackboneList::ToEntity() const{
       cb = edi.InsertAtom(res, "CB", GetCB(i), "C");
       edi.Connect(ca, cb);
     }
-    res.SetOneLetterCode(GetOLC(i));
-    res.SetChemClass(aa_chem_class);
-    res.SetChemType(aa_chem_type);
+    SetResidueProps(res, GetOLC(i));
     if (last.IsValid()) {
       edi.Connect(last.FindAtom("C"), n);
     }
     last = res;
   }
+  // set torsions
+  ost::conop::AssignBackboneTorsions(chain);
   return ent;
 }
 
@@ -286,9 +299,7 @@ void BackboneList::InsertInto(ost::mol::ChainHandle& chain,
     before = edi.AppendResidue(chain,
                                ost::conop::OneLetterCodeToResidueName(GetOLC(0)),
                                n_num);
-    before.SetOneLetterCode(GetOLC(0));
-    before.SetChemClass(aa_chem_class);
-    before.SetChemType(aa_chem_type);
+    SetResidueProps(before, GetOLC(0));
     ost::mol::AtomHandle n = edi.InsertAtom(before, "N", GetN(0), "N");
     ost::mol::AtomHandle ca = edi.InsertAtom(before, "CA", GetCA(0), "C");
     ost::mol::AtomHandle c = edi.InsertAtom(before, "C", GetC(0), "C");
@@ -358,9 +369,7 @@ void BackboneList::InsertInto(ost::mol::ChainHandle& chain,
   } else { // !after.IsValid()
 
     after = edi.AppendResidue(chain, ost::conop::OneLetterCodeToResidueName(GetOLC(last_idx)), c_num);
-    after.SetOneLetterCode(GetOLC(last_idx));
-    after.SetChemClass(aa_chem_class);
-    after.SetChemType(aa_chem_type);
+    SetResidueProps(after, GetOLC(last_idx));
     ost::mol::AtomHandle n = edi.InsertAtom(after, "N", GetN(last_idx), "N");
     ost::mol::AtomHandle ca = edi.InsertAtom(after, "CA", GetCA(last_idx), "C");
     ost::mol::AtomHandle c = edi.InsertAtom(after, "C", GetC(last_idx), "C");
@@ -399,9 +408,7 @@ void BackboneList::InsertInto(ost::mol::ChainHandle& chain,
     String rname = ost::conop::OneLetterCodeToResidueName(GetOLC(i));
     ost::mol::ResidueHandle res = edi.AppendResidue(chain, rname,
                                                     last.GetNumber() + 1);
-    res.SetOneLetterCode(GetOLC(i));
-    res.SetChemClass(aa_chem_class);
-    res.SetChemType(aa_chem_type);
+    SetResidueProps(res, GetOLC(i));
     ost::mol::AtomHandle n = edi.InsertAtom(res, "N", GetN(i), "N");
     ost::mol::AtomHandle ca = edi.InsertAtom(res, "CA", GetCA(i), "C");
     ost::mol::AtomHandle c = edi.InsertAtom(res, "C", GetC(i), "C");
diff --git a/loop/tests/test_all_atom_positions.cc b/loop/tests/test_all_atom_positions.cc
index a37fe16cd956b62324d1a60d2b5fecb14343e07a..bdecca598bd2d86da16db22ec0d2c440f6c818a8 100644
--- a/loop/tests/test_all_atom_positions.cc
+++ b/loop/tests/test_all_atom_positions.cc
@@ -74,6 +74,29 @@ void CompareResidues(const ost::mol::ResidueHandle& new_res,
   }
 }
 
+void CheckEntity(const ost::mol::EntityHandle& ent) {
+  // look at all residues
+  ost::mol::ResidueHandleList res_list = ent.GetResidueList();
+  for (uint res_idx = 0; res_idx < res_list.size(); ++res_idx) {
+    // get residues
+    const ost::mol::ResidueHandle& r = res_list[res_idx];
+    const ost::mol::ResidueHandle r_next = r.GetNext();
+    const ost::mol::ResidueHandle r_prev = r.GetPrev();
+    // check types
+    BOOST_CHECK(r.IsPeptideLinking());
+    BOOST_CHECK(r.IsProtein());
+    // peptide links checked in CompareResidues
+    // check torsions
+    if (r_prev.IsValid() && ost::mol::InSequence(r_prev, r)) {
+      BOOST_CHECK(r.GetPhiTorsion().IsValid());
+      BOOST_CHECK(r.GetOmegaTorsion().IsValid());
+    }
+    if (r_next.IsValid() && ost::mol::InSequence(r, r_next)) {
+      BOOST_CHECK(r.GetPsiTorsion().IsValid());
+    }
+  }
+}
+
 }
 
 BOOST_AUTO_TEST_CASE(test_aap_setup) {
@@ -410,6 +433,7 @@ BOOST_AUTO_TEST_CASE(test_aap_to_ost) {
   for (uint res_idx = 0; res_idx < res_list.size(); ++res_idx) {
     CompareResidues(new_res_list[res_idx], res_list[res_idx]);
   }
+  CheckEntity(new_prot);
 }
 
 BOOST_AUTO_TEST_CASE(test_aap_into_ost) {
@@ -469,6 +493,7 @@ BOOST_AUTO_TEST_CASE(test_aap_into_ost) {
     BOOST_CHECK_EQUAL(new_res.GetNumber(), res_list[res_idx].GetNumber());
     CompareResidues(new_res, res_list[res_idx]);
   }
+  CheckEntity(new_prot);
 
   // check overwrite of residue with killed sidechain atom
   geom::Vec3 new_pos = atoms.GetPos(2, BB_C_INDEX) + geom::Vec3(1,1,1);
diff --git a/loop/tests/test_backbone.cc b/loop/tests/test_backbone.cc
index e10dff36e70c62fa4e1d4dc91cf2d35cf2b762f4..4b82781ca072c3ebd504f4a502a59e13a30a4958 100644
--- a/loop/tests/test_backbone.cc
+++ b/loop/tests/test_backbone.cc
@@ -83,6 +83,65 @@ bool CheckBackbonePlausibility(const BackboneList& bb_list, bool skip_last){
 
   return true;
 }
+
+void CheckEntity(const ost::mol::EntityHandle& ent) {
+  // look at all residues
+  ost::mol::ResidueHandleList res_list = ent.GetResidueList();
+  for (uint res_idx = 0; res_idx < res_list.size(); ++res_idx) {
+    // get residues
+    const ost::mol::ResidueHandle& r = res_list[res_idx];
+    const ost::mol::ResidueHandle r_next = r.GetNext();
+    const ost::mol::ResidueHandle r_prev = r.GetPrev();
+    // check types
+    BOOST_CHECK(r.IsPeptideLinking());
+    BOOST_CHECK(r.IsProtein());
+    // check links
+    if (r_next.IsValid() && r_next.GetNumber() - 1 == r.GetNumber()) {
+      BOOST_CHECK(ost::mol::InSequence(r, r_next));
+    }
+    // check torsions
+    if (r_prev.IsValid() && ost::mol::InSequence(r_prev, r)) {
+      BOOST_CHECK(r.GetPhiTorsion().IsValid());
+      BOOST_CHECK(r.GetOmegaTorsion().IsValid());
+    }
+    if (r_next.IsValid() && ost::mol::InSequence(r, r_next)) {
+      BOOST_CHECK(r.GetPsiTorsion().IsValid());
+    }
+  }
+}
+
+void CheckEntityBB(const ost::mol::EntityHandle& ent,
+                   const BackboneList& bb_list) {
+  // look at all backbone atoms
+  ost::mol::ResidueHandleList res_list = ent.GetResidueList();
+  for (uint res_idx = 0; res_idx < res_list.size(); ++res_idx) {
+    // get atoms
+    const ost::mol::ResidueHandle& r = res_list[res_idx];
+    ost::mol::AtomHandle n = r.FindAtom("N");
+    ost::mol::AtomHandle ca = r.FindAtom("CA");
+    ost::mol::AtomHandle c = r.FindAtom("C");
+    ost::mol::AtomHandle o = r.FindAtom("O");
+    ost::mol::AtomHandle cb = r.FindAtom("CB");
+    // check validity
+    BOOST_CHECK(n.IsValid());
+    BOOST_CHECK(ca.IsValid());
+    BOOST_CHECK(c.IsValid());
+    BOOST_CHECK(o.IsValid());
+    // compare pos
+    BOOST_CHECK_EQUAL(n.GetPos(), bb_list.GetN(res_idx));
+    BOOST_CHECK_EQUAL(ca.GetPos(), bb_list.GetCA(res_idx));
+    BOOST_CHECK_EQUAL(c.GetPos(), bb_list.GetC(res_idx));
+    BOOST_CHECK_EQUAL(o.GetPos(), bb_list.GetO(res_idx));
+    // check CB
+    if (bb_list.GetAA(res_idx) == ost::conop::GLY) {
+      BOOST_CHECK(!cb.IsValid());
+    } else {
+      BOOST_CHECK(cb.IsValid());
+      BOOST_CHECK_EQUAL(cb.GetPos(), bb_list.GetCB(res_idx));
+    }
+  }
+}
+
 }
 
 BOOST_AUTO_TEST_CASE(test_initialization){
@@ -278,7 +337,7 @@ BOOST_AUTO_TEST_CASE(test_replace_fragment) {
 
 BOOST_AUTO_TEST_CASE(test_superpose) {
   
-  // get dummy backbone and fragment
+  // get dummy backbones
   String seq = "HELLYEAHEYECATCHER";
   BackboneList bb_list(seq);
   BackboneList bb_list2(seq);
@@ -296,4 +355,30 @@ BOOST_AUTO_TEST_CASE(test_superpose) {
   BOOST_CHECK(bb_list.CARMSD(bb_list, true) < 1e-4);
 }
 
+BOOST_AUTO_TEST_CASE(test_bb_to_ost) {
+  
+  // get dummy backbone and fragment
+  String seq = "HELLYEAHEYECATCHER";
+  BackboneList bb_list(seq);
+  BackboneList frag = bb_list.Extract(4, 9);
+
+  // extract OST entity
+  ost::mol::EntityHandle ent = bb_list.ToEntity();
+  CheckEntity(ent);
+  CheckEntityBB(ent, bb_list);
+
+  // insert fragment in position of 4th residue (fragment pos.)
+  ost::mol::ResidueHandleList res_list = ent.GetResidueList();
+  ost::mol::ResidueHandle res = res_list[4];
+  ost::mol::ChainHandle chain = res.GetChain();
+  frag.InsertInto(chain, res.GetNumber());
+  CheckEntity(ent);
+  CheckEntityBB(ent, bb_list);
+
+  // trigger exceptions
+  ost::mol::ChainHandle invalid_chain;
+  BOOST_CHECK_THROW(frag.InsertInto(invalid_chain, res.GetNumber()),
+                    promod3::Error);
+}
+
 BOOST_AUTO_TEST_SUITE_END();
diff --git a/modelling/src/model.cc b/modelling/src/model.cc
index 747513b72c839a16ffc1873ad9422932ea98aba7..4504b7ea1c18b08e6dbcd982f3a53a8e65b29921 100644
--- a/modelling/src/model.cc
+++ b/modelling/src/model.cc
@@ -1033,6 +1033,7 @@ void BuildRawChain(const ost::seq::AlignmentHandle& aln,
     }
     String name=conop::OneLetterCodeToResidueName(col[0]);    
     ResidueHandle dst_res=edi.AppendResidue(chain, name, ResNum(res_num));
+    dst_res.SetIsProtein(true);
     bool form_peptide_bond=false;
     if (last_num+1!=res_num) {
       // that's an insertion
diff --git a/modelling/tests/test_pipeline.py b/modelling/tests/test_pipeline.py
index 95cc8af15c240f72cf39c252556fb9ad759b74cf..b43d05a308e0530df362d3b3e4e2018b31cba31f 100644
--- a/modelling/tests/test_pipeline.py
+++ b/modelling/tests/test_pipeline.py
@@ -186,8 +186,25 @@ class PipelineTests(unittest.TestCase):
         return mhandle
 
     def checkFinalModel(self, mhandle, exp_gaps=0, num_chains=0):
-        '''Check if model has exp_gaps and that CheckFinalModel reports it.'''
-        # setup
+        '''Check if:
+        - model has exp_gaps and that CheckFinalModel reports it
+        - model residues are properly set (peptide_linking, protein, torsion)
+        '''
+        # check residue properties
+        for r in mhandle.model.residues:
+            # check types
+            self.assertTrue(r.peptide_linking)
+            self.assertTrue(r.is_protein)
+            # check links
+            if r.next.IsValid() and (r.next.number - r.number) == 1:
+                self.assertTrue(mol.InSequence(r, r.next))
+            # check torsions
+            if r.prev.IsValid() and mol.InSequence(r.prev, r):
+                self.assertTrue(r.phi_torsion.IsValid())
+                self.assertTrue(r.omega_torsion.IsValid())
+            if r.next.IsValid() and mol.InSequence(r, r.next):
+                self.assertTrue(r.psi_torsion.IsValid())
+        # setup gap check
         self.assertEqual(len(mhandle.gaps), exp_gaps)
         log = _FetchLog()
         ost.PushLogSink(log)