diff --git a/modules/mol/alg/pymod/wrap_mol_alg.cc b/modules/mol/alg/pymod/wrap_mol_alg.cc
index 2989eb5da746c61f06f2c072f60b84c13ba98b12..81bdfe50c701abd142799a069331602b7e6cb44a 100644
--- a/modules/mol/alg/pymod/wrap_mol_alg.cc
+++ b/modules/mol/alg/pymod/wrap_mol_alg.cc
@@ -18,7 +18,7 @@
 //------------------------------------------------------------------------------
 
 #include <boost/python.hpp>
-#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
+#include <boost/python/suite/indexing/map_indexing_suite.hpp>
 #include <ost/config.hh>
 #include <ost/mol/alg/local_dist_test.hh>
 #include <ost/mol/alg/superpose_frames.hh>
@@ -36,7 +36,7 @@ void export_entity_to_density();
 
 namespace {
   
-Real (*ldt_a)(const mol::EntityView&, const mol::alg::GlobalDistanceList& , Real, const String&)=&mol::alg::LocalDistTest;
+Real (*ldt_a)(const mol::EntityView&, const mol::alg::GlobalRDMap& , std::vector<Real>, const String&)=&mol::alg::LocalDistTest;
 Real (*ldt_c)(const mol::EntityView&, const mol::EntityView& , Real, Real, const String&)=&mol::alg::LocalDistTest;
 Real (*ldt_b)(const seq::AlignmentHandle&,Real, Real, int, int)=&mol::alg::LocalDistTest;
 mol::EntityView (*fc_a)(const mol::EntityView&, const mol::alg::ClashingDistances&,bool)=&mol::alg::FilterClashes;
@@ -70,8 +70,19 @@ ost::mol::alg::ClashingDistances fill_clashing_distances_wrapper (const list& st
  return ost::mol::alg::FillClashingDistances(stereo_chemical_props_file_vector,min_default_distance,min_distance_tolerance);
 }
 
+ost::mol::alg::GlobalRDMap create_distance_list_from_multiple_references(const list& ref_list, Real cutoff, Real max_dist)
+{
+  int ref_list_length = boost::python::extract<int>(ref_list.attr("__len__")());
+  std::vector<ost::mol::EntityView> ref_list_vector(ref_list_length);
+  
+  for (int i=0; i<ref_list_length; i++) {
+    ref_list_vector[i] = boost::python::extract<ost::mol::EntityView>(ref_list[i]);
+  }
+ 
+  return ost::mol::alg::CreateDistanceListFromMultipleReferences(ref_list_vector, cutoff, max_dist);  	
 }
 
+}
 
 
 BOOST_PYTHON_MODULE(_ost_mol_alg)
@@ -92,6 +103,7 @@ BOOST_PYTHON_MODULE(_ost_mol_alg)
   def("CheckStereoChemistry", csc_b, (arg("ent"), arg("bonds"), arg("angles"), arg("bond_tolerance"), arg("angle_tolerance"), arg("always_remove_bb")=false));
   def("LDTHA",&mol::alg::LDTHA);
   def("CreateDistanceList",&mol::alg::CreateDistanceList);
+  def("CreateDistanceListFromMultipleReferences",&create_distance_list_from_multiple_references);
     
   def("SuperposeFrames", superpose_frames1, 
       (arg("source"), arg("sel")=ost::mol::EntityView(), arg("begin")=0, 
@@ -127,23 +139,18 @@ BOOST_PYTHON_MODULE(_ost_mol_alg)
   ;    
    
   
-  class_<mol::alg::ReferenceDistance> ("ReferenceDistance", init <const mol::alg::UniqueAtomIdentifier&,const mol::alg::UniqueAtomIdentifier&, Real, Real>())
-    .def("GetFirstAtom",&mol::alg::ReferenceDistance::GetFirstAtom)
-    .def("GetSecondAtom",&mol::alg::ReferenceDistance::GetSecondAtom)
-    .def("GetMinDistance",&mol::alg::ReferenceDistance::GetMinDistance)
-    .def("GetMaxDistance",&mol::alg::ReferenceDistance::GetMaxDistance)
-  ;
-  
-  class_<std::vector<mol::alg::ReferenceDistance> >("ResidueDistanceList")
-    .def(vector_indexing_suite<std::vector<mol::alg::ReferenceDistance > >())
+  class_<mol::alg::ResidueRDMap>("ResidueRDMap")
+    .def(map_indexing_suite<mol::alg::ResidueRDMap>())
   ;
   
-  class_<std::vector<mol::alg::ResidueDistanceList> >("GlobalDistanceList")
-    .def(vector_indexing_suite<std::vector<mol::alg::ResidueDistanceList > >())
+  class_<mol::alg::GlobalRDMap>("GlobalRDMap")
+    .def(map_indexing_suite<mol::alg::GlobalRDMap>())
   ;
   
   def("FillClashingDistances",&fill_clashing_distances_wrapper);
   def("FillStereoChemicalParams",&fill_stereochemical_params_wrapper);
   def("IsStandardResidue",&mol::alg::IsStandardResidue);
+  def("PrintGlobalRDMap",&mol::alg::PrintGlobalRDMap);
+  def("PrintResidueRDMap",&mol::alg::PrintResidueRDMap);
   
 }
diff --git a/modules/mol/alg/src/ldt.cc b/modules/mol/alg/src/ldt.cc
index 709adeb9909ecf5dd0b7187155ed7e74272b0113..23f11fd5fe714b66768687039a46a0ec2c1dc583 100644
--- a/modules/mol/alg/src/ldt.cc
+++ b/modules/mol/alg/src/ldt.cc
@@ -77,7 +77,7 @@ void usage()
   std::cerr << "   -e         print version" << std::endl;
 }
 
-std::pair<int,int> compute_coverage (const EntityView& v,const GlobalDistanceList& glob_dist_list)
+std::pair<int,int> compute_coverage (const EntityView& v,const GlobalRDMap& glob_dist_list)
 {
   int second=0;
   int first=0;
@@ -85,15 +85,12 @@ std::pair<int,int> compute_coverage (const EntityView& v,const GlobalDistanceLis
     return std::make_pair<int,int>(0,1);
   }
   ChainView vchain=v.GetChainList()[0];
-  for (std::vector<ResidueDistanceList>::const_iterator i=glob_dist_list.begin();i!=glob_dist_list.end();++i)
+  for (GlobalRDMap::const_iterator i=glob_dist_list.begin();i!=glob_dist_list.end();++i)
   {
-    ResNum rnum = (*i)[0].GetFirstAtom().GetResNum();
-    String rname = (*i)[0].GetFirstAtom().GetResidueName();
-    if (IsStandardResidue(rname)) {
-      second++;
-      if (vchain.FindResidue(rnum)) {
-        first++;
-      }
+    ResNum rnum = (*i).first;
+    second++;
+    if (vchain.FindResidue(rnum)) {
+      first++;
     }
   }
   return std::make_pair<int,int>(first,second);
@@ -200,7 +197,7 @@ int main (int argc, char **argv)
   }
   files.pop_back();
   EntityView ref_view=ref.Select(sel);
-  GlobalDistanceList glob_dist_list = CreateDistanceList(ref_view,radius);
+  GlobalRDMap glob_dist_list = CreateDistanceList(ref_view,radius);
   std::cout << "Verbosity level: " << verbosity_level << std::endl;
   if (structural_checks) {
     std::cout << "Stereo-chemical and steric clash checks: On " << std::endl;
@@ -296,22 +293,18 @@ int main (int argc, char **argv)
       std::cout << "Global LDT score: 0.0" << std::endl;
       return 0;
     }
-    Real ldt=LDTHA(v, glob_dist_list);
+    Real ldt=LDTHA(v, glob_dist_list);	
 
     std::cout << "Global LDT score: " << ldt << std::endl;
     std::cout << "Local LDT Score:" << std::endl;
     std::cout << "Chain\tResName\tResNum\tScore" << std::endl;
-    String labels[]={"localldt0.5","localldt1","localldt2","ldtlocal4"};
     for (ResidueViewIter rit=v.ResiduesBegin();rit!=v.ResiduesEnd();++rit){
       ResidueView ritv = *rit;
-      Real ldt_local_sum = 0;
-      if (ritv.HasProp("localldt0.5")) {
-        for (int n=0; n<4; ++n) {
-          ldt_local_sum+=ritv.GetFloatProp(labels[n]);
-        }
-        ldt_local_sum/=4.0;
-        std::cout << ritv.GetChain() << "\t" << ritv.GetName() << "\t" << ritv.GetNumber() << '\t' << ldt_local_sum << std::endl;
+      Real ldt_local = 0;
+      if (ritv.HasProp("localldt")) {
+          ldt_local=ritv.GetFloatProp("localldt");
       }
+      std::cout << ritv.GetChain() << "\t" << ritv.GetName() << "\t" << ritv.GetNumber() << '\t' << ldt_local << std::endl;
     }
     std::cout << std::endl;
   }
diff --git a/modules/mol/alg/src/local_dist_test.cc b/modules/mol/alg/src/local_dist_test.cc
index 89da8c9ae2255c3caa2793e0534761a8d6592288..9f508280d6cc5c26e615dee5dab8d77780fe1873 100644
--- a/modules/mol/alg/src/local_dist_test.cc
+++ b/modules/mol/alg/src/local_dist_test.cc
@@ -51,10 +51,10 @@ bool swappable(const String& rname, const String& aname)
   return false;
 }
 
-std::pair<bool,Real> within_tolerance(Real mdl_dist, const ReferenceDistance& ref_dist, Real tol)
+std::pair<bool,Real> within_tolerance(Real mdl_dist, std::pair<Real,Real>& values, Real tol)
 {
-  Real min = ref_dist.GetMaxDistance();
-  Real max = ref_dist.GetMaxDistance();
+  Real min = values.first;
+  Real max = values.second;
   bool within_tol = false;
   Real difference = 0;
   if (mdl_dist>=min && mdl_dist <=max) {
@@ -75,18 +75,18 @@ std::pair<bool,Real> within_tolerance(Real mdl_dist, const ReferenceDistance& re
 }      
 
 
-std::pair<Real, Real> calc_overlap1(const ResidueDistanceList& res_distance_list, 
+std::pair<Real, Real> calc_overlap1(const ResidueRDMap& res_distance_list, const ResNum& rnum,
                                     ChainView mdl_chain, 
-                                    Real tol, bool only_fixed, 
+                                    std::vector<Real>& tol_list, bool only_fixed, 
                                     bool swap,std::vector<std::pair<Real, Real> >& overlap_list, bool log )
 {
   std::pair<Real, Real> overlap(0.0, 0.0);
-
-  ResidueView mdl_res=mdl_chain.FindResidue(res_distance_list[0].GetFirstAtom().GetResNum()); 
-  for (ResidueDistanceList::const_iterator ai=res_distance_list.begin(),
-       ae=res_distance_list.end(); ai!=ae; ++ai) {
-    UniqueAtomIdentifier first_atom=ai->GetFirstAtom();
-    UniqueAtomIdentifier second_atom=ai->GetSecondAtom();
+  ResidueView mdl_res=mdl_chain.FindResidue(rnum); 
+  for (ResidueRDMap::const_iterator ai=res_distance_list.begin(); ai!=res_distance_list.end(); ++ai) {
+    UAtomIdentifiers uais = (*ai).first; 
+    std::pair <Real,Real> values = (*ai).second;
+    UniqueAtomIdentifier first_atom=uais.first;
+    UniqueAtomIdentifier second_atom=uais.second;
     String name=swap ? swapped_name(first_atom.GetAtomName()) : first_atom.GetAtomName();
     AtomView av1=mdl_res ? mdl_res.FindAtom(name) : AtomView();
  
@@ -94,58 +94,42 @@ std::pair<Real, Real> calc_overlap1(const ResidueDistanceList& res_distance_list
       if (swappable(second_atom.GetResidueName(), second_atom.GetAtomName())) {
           continue;
       }
-      AtomView av2=mdl_chain.FindAtom(second_atom.GetResNum(),second_atom.GetAtomName());
-      overlap.second+=1.0;
-      if (!(av1 && av2)) {
-        continue;
-      }
-      Real mdl_dist=geom::Length(av1.GetPos()-av2.GetPos());
-      ReferenceDistance ref_dist=*ai;
-      if (within_tolerance(mdl_dist,ref_dist,tol).first) {
+    }    
+    AtomView av2=mdl_chain.FindAtom(second_atom.GetResNum(),second_atom.GetAtomName());
+    overlap.second+=tol_list.size();
+    if (av1) {
+      overlap_list[av1.GetResidue().GetIndex()].second+=1.0;
+    }
+    if (av2) {
+      overlap_list[av2.GetResidue().GetIndex()].second+=1.0;
+    }  
+    if (!(av1 && av2)) {
+      continue;
+    }
+    Real mdl_dist=geom::Length(av1.GetPos()-av2.GetPos());
+    for (std::vector<Real>::const_reverse_iterator tol_list_it=tol_list.rbegin();tol_list_it!=tol_list.rend();++tol_list_it) {
+      Real tol = * tol_list_it; 
+      if (within_tolerance(mdl_dist,values,tol).first) {
         if (log) {
           LOG_VERBOSE("LDT:" << " " << av1.GetResidue().GetChain() << " " << av1.GetResidue().GetName() << " " << av1.GetResidue().GetNumber() << " " << av1.GetName() 
              << " " << av2.GetResidue().GetChain() << " " << av2.GetResidue().GetName() << " " << av2.GetResidue().GetNumber() << " " << av2.GetName() << " " 
-             << mdl_dist << " " << ref_dist.GetMinDistance() << " " << ref_dist.GetMaxDistance() << " " << tol << " " << "PASS")
+             << mdl_dist << " " << values.first << " " << values.second << " " << tol << " " << "PASS")
         }   
         overlap.first+=1;
+        overlap_list[av1.GetResidue().GetIndex()].first+=1;
+        overlap_list[av2.GetResidue().GetIndex()].first+=1;
       } else {
         if (log) {
           LOG_VERBOSE("LDT:" << " " << av1.GetResidue().GetChain() << " " << av1.GetResidue().GetName() << " " << av1.GetResidue().GetNumber() << " " << av1.GetName() 
              << " " << av2.GetResidue().GetChain() << " " << av2.GetResidue().GetName() << " " << av2.GetResidue().GetNumber() << " " << av2.GetName() << " " 
-             << mdl_dist << " " << ref_dist.GetMinDistance() << " " << mdl_dist-ref_dist.GetMinDistance() << " " << tol << " " << "FAIL")
+             << mdl_dist << " " << values.first << " " << values.second << " " << tol << " " << "FAIL")
         }  
+        break;  
       }
-      continue;
-    }
-    AtomView av2=mdl_chain.FindAtom(second_atom.GetResNum(), second_atom.GetAtomName());
-    overlap.second+=1.0;
-    if (av1) {
-      overlap_list[av1.GetResidue().GetIndex()].second+=1.0;
-    }
-    if (av2) {
-      overlap_list[av2.GetResidue().GetIndex()].second+=1.0;
-     }  
-    if (!(av1 && av2)) {
-      continue;
-    }
-    
-    Real mdl_dist=geom::Length(av1.GetPos()-av2.GetPos());
-    ReferenceDistance ref_dist=*ai;
-    if (within_tolerance(mdl_dist,ref_dist,tol).first) {
-      LOG_INFO("LDT:" << " " << av1.GetResidue().GetChain() << " " << av1.GetResidue().GetName() << " " << av1.GetResidue().GetNumber() << " " << av1.GetName() 
-           << " " << av2.GetResidue().GetChain() << " " << av2.GetResidue().GetName() << " " << av2.GetResidue().GetNumber() << " " << av2.GetName() << " " 
-           << mdl_dist << " " << ref_dist.GetMinDistance() << " " << mdl_dist-ref_dist.GetMinDistance() << " " << tol << " " << "PASS")
-      overlap.first+=1;
-      overlap_list[av1.GetResidue().GetIndex()].first+=1.0;
-      overlap_list[av2.GetResidue().GetIndex()].first+=1.0;
-    } else {
-      LOG_VERBOSE("LDT:" << " " << av1.GetResidue().GetChain() << " " << av1.GetResidue().GetName() << " " << av1.GetResidue().GetNumber() << " " << av1.GetName() 
-             << " " << av2.GetResidue().GetChain() << " " << av2.GetResidue().GetName() << " " << av2.GetResidue().GetNumber() << " " << av2.GetName() << " " 
-             << mdl_dist << " " << ref_dist.GetMinDistance() << " " << mdl_dist-ref_dist.GetMinDistance() << " " << tol << " " << "FAIL")
-    } 
-  }    
+    }    
+  }
   return overlap;
-}
+}  
 
 
 std::pair<Real, Real> calc_overlap2(const seq::ConstSequenceHandle& ref_seq,
@@ -232,8 +216,145 @@ std::pair<Real, Real> calc_overlap2(const seq::ConstSequenceHandle& ref_seq,
   return overlap;
 }
 
+void check_and_swap(const GlobalRDMap& glob_dist_list, const EntityView& mdl, std::vector<Real> cutoff_list,  std::vector<std::pair<Real, Real> > overlap_list)
+{
+  ChainView mdl_chain=mdl.GetChainList()[0]; 
+  XCSEditor edi=mdl.GetHandle().EditXCS(BUFFERED_EDIT);
+  for (GlobalRDMap::const_iterator i=glob_dist_list.begin(); i!=glob_dist_list.end(); ++i) {  
+    ResidueRDMap rdl = (*i).second;
+    ResNum rnum =  (*i).first;
+    if (rdl.size()==0) {
+      continue;
+    }
+    ResidueView mdl_res=mdl_chain.FindResidue(rnum); 
+    if (!mdl_res) {   
+      continue;
+    }
+    String rname = mdl_res.GetName();
+    if (!(rname=="GLU" || rname=="ASP" || rname=="VAL" || rname=="TYR" || rname=="PHE" || rname=="LYS" || rname=="ARG")) {
+      continue;
+    }
+    std::pair<Real, Real> ov1=calc_overlap1(rdl, rnum,mdl_chain, 
+                                          cutoff_list, true, 
+                                          false, overlap_list,false);
+ 
+    std::pair<Real, Real> ov2=calc_overlap1(rdl, rnum, mdl_chain, 
+                                          cutoff_list, true, 
+                                          true, overlap_list,false); 
+
+    if (ov1.first/ov1.second<ov2.first/ov2.second) {
+      AtomViewList atoms=mdl_res.GetAtomList();
+      for (AtomViewList::iterator j=atoms.begin(), e2=atoms.end(); j!=e2; ++j) {
+        if (swappable(rname, j->GetName())) {
+          edi.RenameAtom(j->GetHandle(), swapped_name(j->GetName()));
+        }
+      }
+    } 
+  }
+}
+
+void update_existence_map (ExistenceMap& ex_map, const EntityView& ev, int ref_counter)
+{
+  AtomViewList ev_atom=ev.GetAtomList();
+  for (AtomViewList::iterator ev_atom_it=ev_atom.begin(); ev_atom_it!=ev_atom.end();++ev_atom_it) {
+    AtomView ev_atom = (*ev_atom_it);
+    UniqueAtomIdentifier uai (ev_atom.GetResidue().GetChain().GetName(),ev_atom.GetResidue().GetNumber(),ev_atom.GetResidue().GetName(),ev_atom.GetName());
+    ExistenceMap::const_iterator find_uai_ci = ex_map.find(uai);
+    int uai_value = 0;
+    if (find_uai_ci!=ex_map.end()) {
+      uai_value=(*find_uai_ci).second;
+    } 
+	uai_value |= 1 << (ref_counter);   
+    ex_map[uai]=uai_value;     
+  }
+}
+
+int in_existence_map(const ExistenceMap& ex_map, const UniqueAtomIdentifier& uai) 
+{
+  ExistenceMap::const_iterator find_uai_ci = ex_map.find(uai);
+  int return_value = 0;
+  if (find_uai_ci!=ex_map.end()) {
+      return_value=(*find_uai_ci).second;
+  } 
+  return return_value;   
+}    
+
+void merge_distance_lists(GlobalRDMap& ref_dist_map, const GlobalRDMap& new_dist_map, ExistenceMap& ex_map, const EntityView& ref,int ref_counter)
+{
+  // iterate over the residues in the ref_dist_map   
+  for (GlobalRDMap::iterator ref_dist_map_it=ref_dist_map.begin();ref_dist_map_it!=ref_dist_map.end();++ref_dist_map_it) {
+    ResidueRDMap ref_res_map = (*ref_dist_map_it).second;  
+    ResNum ref_resnum = (*ref_dist_map_it).first;
+    GlobalRDMap::const_iterator find_new_res_ci = new_dist_map.find(ref_resnum);
+    //if the residue is found in new_dist_map,  
+    if (find_new_res_ci != new_dist_map.end()) {
+      ResidueRDMap found_res_new = (*find_new_res_ci).second;
+      //iterate over the the reference distances in the ResidueDistanceMap  
+      for (ResidueRDMap::iterator ref_res_map_it = ref_res_map.begin(); ref_res_map_it!=ref_res_map.end();++ref_res_map_it) {
+        UAtomIdentifiers ref_rd = (*ref_res_map_it).first;
+        std::pair<Real,Real> ref_minmax = (*ref_res_map_it).second;
+        ResidueRDMap::const_iterator find_new_rd_ci = found_res_new.find(ref_rd);
+        // if you find the distance in the residue new, udate min and max  
+        if (find_new_rd_ci != found_res_new.end()) {
+          std::pair <Real,Real> new_minmax = (*find_new_rd_ci).second;
+	      Real min = ref_minmax.first;
+	      Real max = ref_minmax.second;
+          if (new_minmax.first < min) min = new_minmax.first;  
+          if (new_minmax.second > max) max = new_minmax.second;
+          ref_res_map[ref_rd] = std::make_pair<Real,Real>(min,max);
+        } else {              
+          // if you don't find it in the residue new, check that it is not missing because it is too long  
+          UniqueAtomIdentifier first_atom_to_find = ref_rd.first;
+          UniqueAtomIdentifier second_atom_to_find = ref_rd.second;  
+          // if both atoms are there, remove the distance from the ref_dist_map,    
+          if ((ref.FindAtom(first_atom_to_find.GetChainName(),first_atom_to_find.GetResNum(),first_atom_to_find.GetAtomName()).IsValid() && 
+               ref.FindAtom(second_atom_to_find.GetChainName(),second_atom_to_find.GetResNum(),second_atom_to_find.GetAtomName()).IsValid()) ) {
+            ref_res_map.erase(ref_res_map_it);                   
+          }  
+        }
+      }
+      // now iterate over the the new  reference distances in residue new  
+      for (ResidueRDMap::const_iterator new_res_map_it = found_res_new.begin(); new_res_map_it!=found_res_new.end();++new_res_map_it) {
+        UAtomIdentifiers new_rd = (*new_res_map_it).first;
+        std::pair<Real,Real> new_minmax = (*new_res_map_it).second;
+        ResidueRDMap::const_iterator find_ref_rd_ci = ref_res_map.find(new_rd);
+        // if the distance is found in the residue ref, 
+        // it has been taken care of before. If not
+        if (find_ref_rd_ci==ref_res_map.end()) {
+          UniqueAtomIdentifier first_atom_to_find = new_rd.first;
+          UniqueAtomIdentifier second_atom_to_find = new_rd.second;
+          // check that there isn't a structure already processed where both atoms are in
+          // if there is none, add the distance to the residue ref map 
+          if (!(in_existence_map(ex_map,first_atom_to_find) & in_existence_map(ex_map,second_atom_to_find))) {
+            ref_res_map[new_rd]= new_minmax; 
+          }
+        }      
+      }      
+    }
+  // if the residue was not found in the new list, it means that it is 
+  // absent in the new structure, no new information
+  }
+
+  // now iterate over the residues in the new_list
+  for (GlobalRDMap::const_iterator new_dist_map_it=new_dist_map.begin();new_dist_map_it!=new_dist_map.end();++new_dist_map_it) {
+    ResidueRDMap new_res_map = (*new_dist_map_it).second;  
+    ResNum new_resnum = (*new_dist_map_it).first;
+    GlobalRDMap::const_iterator find_ref_res_ci = ref_dist_map.find(new_resnum);
+    // if the residue is found in new_dist_map, it has been taken care before,
+    // if not, add it to the res_dist_map:
+    if (find_ref_res_ci == ref_dist_map.end()) {
+      ResidueRDMap found_res_ref = (*find_ref_res_ci).second;       
+      ref_dist_map[new_resnum] = found_res_ref;           
+    }
+  }
+
+  // finally, update the existence map  
+  update_existence_map (ex_map,ref,ref_counter);  
+}
+
 }
 
+
 bool IsStandardResidue(String rn)
 {
   String upper_rn=rn;
@@ -263,6 +384,7 @@ bool IsStandardResidue(String rn)
   return false;
 }  
 
+
 bool UniqueAtomIdentifier::operator==(const UniqueAtomIdentifier& rhs) const
 {
   if (chain_ == rhs.GetChainName() && 
@@ -274,51 +396,47 @@ bool UniqueAtomIdentifier::operator==(const UniqueAtomIdentifier& rhs) const
   return false;   
 }
 
-bool ReferenceDistance::IsValid() const 
-{
-  if (mind_ == -1.0 && maxd_ == -1.0) {
-    return false;
-  } 
-  return true;
-}
-
-void ReferenceDistance::Print() const 
-{ 
-  if (this->IsValid() == true) {
-    std::cout << first_atom_.GetChainName() << " " << first_atom_.GetResNum() << " " << first_atom_.GetResidueName() << " " << first_atom_.GetAtomName() << " " <<
-                 second_atom_.GetChainName() << " " << second_atom_.GetResNum() << " " << second_atom_.GetResidueName() << " " << second_atom_.GetAtomName() << " " <<
-                 mind_ << " " << maxd_ << std::endl; 
-  } else {
-    std::cout << first_atom_.GetChainName() << " " << first_atom_.GetResNum() << " " << first_atom_.GetResidueName() << " Placeholder" << std::endl;
-  }
-}
-
-bool ReferenceDistance::operator==(const ReferenceDistance& rhs) const
+bool UniqueAtomIdentifier::operator<(const UniqueAtomIdentifier& rhs) const
 {
-  if (first_atom_ == rhs.GetFirstAtom() && 
-      second_atom_ == rhs.GetSecondAtom() &&
-      mind_ == rhs.GetMinDistance() &&
-      maxd_ == rhs.GetMaxDistance() ) {
+  if (chain_ < rhs.GetChainName()) {
     return true;
+  } else if (chain_ > rhs.GetChainName()) {
+	return false;
+  } else {
+    if (residue_ < rhs.GetResNum()) {
+      return true;
+    } else if (residue_ > rhs.GetResNum()) {
+	  return false;
+    } else {
+      if (residue_name_ < rhs.GetResidueName()) {
+        return true;
+      } else if (residue_name_ > rhs.GetResidueName()) {
+  	    return false;
+      } else {
+        if (atom_ < rhs.GetAtomName()) {
+          return true;
+        } else if (atom_ > rhs.GetAtomName()) {
+  	      return false;
+        } else {
+		  return false;	
+		}
+	  }  
+	}
   }
-  return false;
-}
-
-
+}	
 
-
-GlobalDistanceList CreateDistanceList(const EntityView& ref,Real max_dist)
+GlobalRDMap CreateDistanceList(const EntityView& ref,Real max_dist)
 {
- GlobalDistanceList dist_list; 
- ResidueViewList ref_residues=ref.GetChainList()[0].GetResidueList();
+ GlobalRDMap dist_list; 
+ ResidueViewList ref_residues=ref.GetChainList()[0].GetResidueList(); 
  for (ResidueViewList::iterator i=ref_residues.begin(), e=ref_residues.end(); i!=e; ++i) {
    ResidueView rview = (*i);
    if (IsStandardResidue(rview.GetName())) {
-     ResidueDistanceList res_dist_list;
+     ResidueRDMap res_dist_list;
+     ResNum rnum = rview.GetNumber();  
      AtomViewList ref_atoms=(*i).GetAtomList();
      AtomViewList within;
      if (max_dist<0){
-     dist_list.push_back(res_dist_list);
        within=ref.GetAtomList();
      }  
      for (AtomViewList::iterator ai=ref_atoms.begin(), ae=ref_atoms.end(); ai!=ae; ++ai) {
@@ -335,25 +453,60 @@ GlobalDistanceList CreateDistanceList(const EntityView& ref,Real max_dist)
          }
          if (aj->GetResidue().GetNumber()>i->GetNumber()) {
            Real dist=geom::Length(ai->GetPos()-aj->GetPos());
-           ReferenceDistance ref_dist(first_atom,second_atom,dist,dist);
-           res_dist_list.push_back(ref_dist);
+           UAtomIdentifiers atoms = std::make_pair<UniqueAtomIdentifier,UniqueAtomIdentifier>(first_atom,second_atom); 
+           std::pair<Real,Real> values = std::make_pair<Real,Real>(dist,dist);  
+           res_dist_list[atoms]=values;
          }
        }
-     }
-     if (res_dist_list.size()==0) {
-       UniqueAtomIdentifier current_residue_fake_atom(rview.GetChain().GetName(),rview.GetNumber(),rview.GetName(),"CA");
-       ReferenceDistance fake_ref_distance(current_residue_fake_atom,current_residue_fake_atom,-1.0,-1.0);
-       res_dist_list.push_back(fake_ref_distance);
-     }  
-     dist_list.push_back(res_dist_list);
+     }   
+     dist_list[rnum]=res_dist_list;
    }
- }  
+ } 
  return dist_list;
 } 
 
+GlobalRDMap CreateDistanceListFromMultipleReferences(const std::vector<EntityView>& ref_list, std::vector<Real> cutoff_list, Real max_dist)
+{	
+  int ref_counter=0;  
+  ExistenceMap ex_map;  
+  GlobalRDMap glob_dist_list = CreateDistanceList(ref_list[0],max_dist);
+  update_existence_map (ex_map,ref_list[0],ref_counter);
+  ref_counter++;  
+  for (std::vector<EntityView>::const_iterator ref_list_it=ref_list.begin()+1;ref_list_it!=ref_list.end();++ref_list_it) {
+       EntityView ref = *ref_list_it;
+       std::vector<std::pair<Real, Real> > overlap_list(ref.GetResidueCount(), std::pair<Real, Real>(0.0, 0.0));
+       check_and_swap(glob_dist_list,ref,cutoff_list,overlap_list);
+       GlobalRDMap new_dist_list=CreateDistanceList(ref,max_dist);
+       merge_distance_lists(glob_dist_list,new_dist_list,ex_map,ref,ref_counter);   
+       ref_counter++;
+  }    
+  return glob_dist_list;  
+}
 
-Real LocalDistTest(const EntityView& mdl, const GlobalDistanceList& glob_dist_list,
-                   Real cutoff, const String& local_ldt_property_string)
+void PrintResidueRDMap(const ResidueRDMap& res_dist_list)
+{
+  for (ResidueRDMap::const_iterator res_dist_list_it = res_dist_list.begin();res_dist_list_it!=res_dist_list.end();++res_dist_list_it) {
+    UAtomIdentifiers uais = (*res_dist_list_it).first;
+    std::pair<Real,Real> minmax = (*res_dist_list_it).second;
+    std::cout << uais.first.GetChainName() << " " << uais.first.GetResNum() << " " << uais.first.GetResidueName() << " " << uais.first.GetAtomName() << " " <<
+                 uais.second.GetChainName() << " " << uais.second.GetResNum() << " " << uais.second.GetResidueName() << " " << uais.second.GetAtomName() << " " <<
+                 minmax.first << " " << minmax.second << std::endl;       
+  }
+}
+
+
+void PrintGlobalRDMap(const GlobalRDMap& glob_dist_list){
+  for (GlobalRDMap::const_iterator glob_dist_list_it = glob_dist_list.begin();glob_dist_list_it!=glob_dist_list.end();++glob_dist_list_it) {
+    if ((*glob_dist_list_it).second.size()!=0) {  
+      PrintResidueRDMap((*glob_dist_list_it).second);
+    }    
+  }    
+}
+
+
+
+Real LocalDistTest(const EntityView& mdl, const GlobalRDMap& glob_dist_list,
+                   std::vector<Real> cutoff_list, const String& local_ldt_property_string)
 {
   if (!mdl.GetResidueCount()) {
     LOG_WARNING("model structures doesn't contain any residues");
@@ -364,60 +517,25 @@ Real LocalDistTest(const EntityView& mdl, const GlobalDistanceList& glob_dist_li
     return 0.0;
   }
   std::vector<std::pair<Real, Real> > overlap_list(mdl.GetResidueCount(), std::pair<Real, Real>(0.0, 0.0));
+  check_and_swap(glob_dist_list,mdl,cutoff_list,overlap_list);
   ChainView mdl_chain=mdl.GetChainList()[0];  
-  // Residues with symmetric side-chains require special treatment as there are 
-  // two possible ways to name the atoms. We calculate the overlap with the 
-  // fixed atoms and take the solution that gives bigger scores.
-  XCSEditor edi=mdl.GetHandle().EditXCS(BUFFERED_EDIT);
-  for (GlobalDistanceList::const_iterator i=glob_dist_list.begin(), e=glob_dist_list.end(); i!=e; ++i) {
-    ResidueDistanceList rdl = *i;
-    if (!rdl[0].IsValid()) {
-      continue;
-    }
-    
-    ResNum rnum =  rdl[0].GetFirstAtom().GetResNum() ;
-    String rname=rdl[0].GetFirstAtom().GetResidueName();
-    ResidueView mdl_res=mdl_chain.FindResidue(rnum);  
-    if (!mdl_res) {   
-      continue;
-    }
-    if (!(rname=="GLU" || rname=="ASP" || rname=="VAL" || rname=="TYR" || rname=="PHE" || rname=="LYS" || rname=="ARG")) {
-      continue;
-    }
-    std::pair<Real, Real> ov1=calc_overlap1(*i, mdl_chain, 
-                                          cutoff, true, 
-                                          false, overlap_list,false);
- 
-    std::pair<Real, Real> ov2=calc_overlap1(*i, mdl_chain, 
-                                          cutoff, true, 
-                                          true, overlap_list,false); 
-    if (ov1.first/ov1.second<ov2.first/ov2.second) {
-      AtomViewList atoms=mdl_res.GetAtomList();
-      for (AtomViewList::iterator j=atoms.begin(), e2=atoms.end(); j!=e2; ++j) {
-        if (swappable(rname, j->GetName())) {
-          edi.RenameAtom(j->GetHandle(), swapped_name(j->GetName()));
-        }
-      }
-    }
-  }
   overlap_list.clear();
   std::pair<Real, Real> total_ov(0.0, 0.0);
-  for (GlobalDistanceList::const_iterator i=glob_dist_list.begin(), e=glob_dist_list.end(); i!=e; ++i) {
-    ResidueDistanceList rdl = *i;
-    if (rdl[0].IsValid()) {
-      std::pair<Real, Real> ov1=calc_overlap1(*i, mdl_chain, cutoff, 
+  for (GlobalRDMap::const_iterator i=glob_dist_list.begin(), e=glob_dist_list.end(); i!=e; ++i) {
+    ResidueRDMap rdl = (*i).second;
+    ResNum rn = (*i).first;
+    if (rdl.size()!=0) {
+      std::pair<Real, Real> ov1=calc_overlap1(rdl, rn, mdl_chain, cutoff_list, 
                                             false, false, overlap_list,true);
       total_ov.first+=ov1.first;
       total_ov.second+=ov1.second;       
     }
     if(local_ldt_property_string!="") {
-      ResNum rn = rdl[0].GetFirstAtom().GetResNum();
       ResidueView mdlr=mdl_chain.FindResidue(rn);  
       if (mdlr.IsValid()) {
         int mdl_res_index =mdlr.GetIndex();
         Real local_ldt=overlap_list[mdl_res_index].first/(overlap_list[mdl_res_index].second ? overlap_list[mdl_res_index].second : 1);
-        ResidueView res_to_wr = mdl_chain.FindResidue((*i)[0].GetFirstAtom().GetResNum()); 
-        res_to_wr.SetFloatProp(local_ldt_property_string, local_ldt);
+        mdlr.SetFloatProp(local_ldt_property_string, local_ldt);
       }  
     }       
   }
@@ -427,8 +545,10 @@ Real LocalDistTest(const EntityView& mdl, const GlobalDistanceList& glob_dist_li
 
 Real LocalDistTest(const EntityView& mdl, const EntityView& target, Real cutoff, Real max_dist, const String& local_ldt_property_string)
 {
-   GlobalDistanceList glob_dist_list = CreateDistanceList(target,max_dist);
-   return LocalDistTest(mdl, glob_dist_list, cutoff, local_ldt_property_string);
+   std::vector<Real> cutoffs;
+   cutoffs.push_back(cutoff);
+   GlobalRDMap glob_dist_list = CreateDistanceList(target,max_dist);
+   return LocalDistTest(mdl, glob_dist_list, cutoffs, local_ldt_property_string);
 }
 
 
@@ -484,16 +604,41 @@ Real LocalDistTest(const ost::seq::AlignmentHandle& aln,
   return 0.0;
 }
 
-Real LDTHA(EntityView& v, const GlobalDistanceList& global_dist_list)
+Real LDTHA(EntityView& v, const GlobalRDMap& global_dist_list)
 {
-    
-    Real cutoffs[]={0.5,1,2,4};
-    String labels[]={"localldt0.5","localldt1","localldt2","ldtlocal4"};
-    Real ldt=0.0;   
-    for (int n=0; n<4; ++n) { 
-      ldt+=alg::LocalDistTest(v, global_dist_list, cutoffs[n], labels[n]);
-    }      
-    ldt/=4.0;    
+    std::vector<Real> cutoffs;
+    cutoffs.push_back(0.5);
+    cutoffs.push_back(1.0);
+    cutoffs.push_back(2.0);
+    cutoffs.push_back(4.0);
+    String label="localldt";
+    Real ldt=alg::LocalDistTest(v, global_dist_list, cutoffs, label);
+    return ldt;
+}
+
+Real OldStyleLDTHA(EntityView& v, const GlobalRDMap& global_dist_list)
+{
+    Real ldt =0;
+    std::vector<Real> cutoffs05;
+    cutoffs05.push_back(0.5);
+    Real ldt05=alg::LocalDistTest(v, global_dist_list, cutoffs05, "localldt0.5");
+    std::vector<Real> cutoffs1;
+    cutoffs1.push_back(1.0);
+    Real ldt1=alg::LocalDistTest(v, global_dist_list, cutoffs1, "localldt1");
+    std::vector<Real> cutoffs2;
+    cutoffs2.push_back(2.0);
+    Real ldt2=alg::LocalDistTest(v, global_dist_list, cutoffs2, "localldt2");
+    std::vector<Real> cutoffs4;
+    cutoffs4.push_back(4.0);
+    Real ldt4=alg::LocalDistTest(v, global_dist_list, cutoffs4, "localldt4");
+    ldt = (ldt05+ldt1+ldt2+ldt4)/4.0;
+    for (ResidueViewIter rit=v.ResiduesBegin();rit!=v.ResiduesEnd();++rit){
+      ResidueView ritv = *rit;
+      if (ritv.HasProp("localldt0.5")) {
+        Real ldt_local = (ritv.GetFloatProp("localldt0.5")+ritv.GetFloatProp("localldt1")+ritv.GetFloatProp("localldt2")+ritv.GetFloatProp("localldt4"))/4.0;
+        ritv.SetFloatProp("localldt",ldt_local);
+      }    
+    }    
     return ldt;
 }
 
diff --git a/modules/mol/alg/src/local_dist_test.hh b/modules/mol/alg/src/local_dist_test.hh
index 9c174f9698bb37ccd7e23f16febf77e1928624c4..8a26e1c7dbf8ef67f50a8fcfce326cd45abc16ce 100644
--- a/modules/mol/alg/src/local_dist_test.hh
+++ b/modules/mol/alg/src/local_dist_test.hh
@@ -31,12 +31,16 @@ class UniqueAtomIdentifier
   
 public:
   UniqueAtomIdentifier(const String& chain,const ResNum& residue,const String& residue_name, const String& atom): chain_(chain),residue_(residue),residue_name_(residue_name),atom_(atom) {}  
-  
+
+  // to make the compiler happy (boost python map suite)
+  UniqueAtomIdentifier(): chain_(""),residue_(ResNum(1)),residue_name_(""),atom_("") {}  
+    
   String GetChainName() const { return chain_; } 
   ResNum GetResNum() const { return residue_; }  
   String GetResidueName() const { return residue_name_; }
   String GetAtomName() const { return atom_; }
   bool operator==(const UniqueAtomIdentifier& rhs) const;
+  bool operator<(const UniqueAtomIdentifier& rhs) const;	
     
 private:
 
@@ -46,40 +50,19 @@ private:
   String atom_;    
 };
 
-class ReferenceDistance
-{
-  
-public:
-  
-  ReferenceDistance(const UniqueAtomIdentifier& first_atom, const UniqueAtomIdentifier& second_atom, Real mind, Real maxd):
-       first_atom_(first_atom),second_atom_(second_atom),mind_(mind),maxd_(maxd) {}
-  UniqueAtomIdentifier GetFirstAtom() const {return first_atom_;}
-  UniqueAtomIdentifier GetSecondAtom() const {return second_atom_;}
-  Real GetMinDistance() const {return mind_ ;}
-  Real GetMaxDistance() const {return maxd_ ;}
-  bool IsValid() const; 
-  void Print() const; 
-  bool operator==(const ReferenceDistance& rhs) const;
-  
-private:
-  
-  UniqueAtomIdentifier first_atom_;
-  UniqueAtomIdentifier second_atom_;
-  Real mind_;
-  Real maxd_;
-};
+typedef std::pair<UniqueAtomIdentifier,UniqueAtomIdentifier> UAtomIdentifiers;
+typedef std::map<std::pair<UniqueAtomIdentifier,UniqueAtomIdentifier>,std::pair<float,float> > ResidueRDMap;
+typedef std::map<ost::mol::ResNum,ResidueRDMap> GlobalRDMap;
+typedef std::map<UniqueAtomIdentifier,int> ExistenceMap;
 
-typedef std::vector<ReferenceDistance> ResidueDistanceList;
-typedef std::vector<ResidueDistanceList> GlobalDistanceList;
-  
 Real DLLEXPORT_OST_MOL_ALG LocalDistTest(const EntityView& mdl,
-                                         const GlobalDistanceList& dist_list,
-                                         Real cutoff, 
+                                         const GlobalRDMap& dist_list,
+                                         std::vector<Real> cutoff_list, 
                                          const String& local_ldt_property_string="");
 
 Real DLLEXPORT_OST_MOL_ALG LocalDistTest(const EntityView& mdl,
                                          const EntityView& target,
-                                         Real cutoff, 
+                                         Real cutoff_list, 
                                          Real max_dist,
                                          const String& local_ldt_property_string="");
 
@@ -88,12 +71,15 @@ Real DLLEXPORT_OST_MOL_ALG LocalDistTest(const ost::seq::AlignmentHandle& aln,
                                          int ref_index=0, int mdl_index=1);
 
 
-Real DLLEXPORT_OST_MOL_ALG LDTHA(EntityView& v, const GlobalDistanceList& global_dist_list);
-
-GlobalDistanceList CreateDistanceList(const EntityView& ref,Real max_dist);
-bool IsStandardResidue(String rn);
+Real DLLEXPORT_OST_MOL_ALG LDTHA(EntityView& v, const GlobalRDMap& global_dist_list);
+Real DLLEXPORT_OST_MOL_ALG OldStyleLDTHA(EntityView& v, const GlobalRDMap& global_dist_list);
 
 
+GlobalRDMap CreateDistanceList(const EntityView& ref,Real max_dist);
+GlobalRDMap CreateDistanceListFromMultipleReferences(const std::vector<EntityView>& ref_list,Real cutoff, Real max_dist);
+void PrintGlobalRDMap(const GlobalRDMap& glob_dist_list);
+void PrintResidueRDMap(const ResidueRDMap& res_dist_list);
+bool IsStandardResidue(String rn);
 
 }}}
 
diff --git a/modules/mol/base/src/residue_prop.hh b/modules/mol/base/src/residue_prop.hh
index e86eef5f11b16ba4eed55153e0cb38901faedd1e..4a411cca6e27250fdd23d4b538ffea6064b8d106 100644
--- a/modules/mol/base/src/residue_prop.hh
+++ b/modules/mol/base/src/residue_prop.hh
@@ -34,6 +34,12 @@ class DLLEXPORT ResNum: private
     boost::unit_steppable<ResNum> > > > >
 {
 public:
+ 
+  // needed to wrap certain map classes
+  ResNum():
+    num_(1),alt_('\0')	 
+  {}  
+
   ResNum(int n):
     num_(n), alt_('\0')
   { }