From ee8e3193b9647774495fd846c7a8f7696ee46fb3 Mon Sep 17 00:00:00 2001 From: Gerardo Tauriello <gerardo.tauriello@unibas.ch> Date: Tue, 19 Sep 2017 18:23:36 +0200 Subject: [PATCH] SCHWED-1740: handle loops of length 1 in MM system creator --- loop/src/mm_system_creator.cc | 10 +- loop/src/mm_system_creator.hh | 19 ++-- loop/tests/test_mm_system_creator.cc | 133 +++++++++++++++++++++++---- 3 files changed, 136 insertions(+), 26 deletions(-) diff --git a/loop/src/mm_system_creator.cc b/loop/src/mm_system_creator.cc index 5ffe7a97..2395048d 100644 --- a/loop/src/mm_system_creator.cc +++ b/loop/src/mm_system_creator.cc @@ -557,8 +557,8 @@ MmSystemCreator::SetupTopology_(const DisulfidBridgeVector& disulfid_bridges) { masses = ff_lookup_->GetMasses(ff_aa, is_nter, is_cter); std::copy(masses.begin(), masses.end(), &atom_masses[first_idx]); // loop check - const IndexLocation_ i_loc = GetIndexLocation_(i_res); - if (i_loc == ON_N_STEM && !is_nter) { + const uint i_loc = GetIndexLocation_(i_res); + if ((i_loc & ON_N_STEM) && !is_nter) { // fix N-stem (only fix N, CA, CB) const uint idx_N = ff_lookup_->GetHeavyIndex(ff_aa, BB_N_INDEX); atom_masses[first_idx + idx_N] = 0; @@ -568,7 +568,8 @@ MmSystemCreator::SetupTopology_(const DisulfidBridgeVector& disulfid_bridges) { const uint idx_CB = ff_lookup_->GetHeavyIndex(ff_aa, BB_CB_INDEX); atom_masses[first_idx + idx_CB] = 0; } - } else if (i_loc == ON_C_STEM && !is_cter) { + } + if ((i_loc & ON_C_STEM) && !is_cter) { // fix C-stem (only fix CA, CB, C, O) const uint idx_CA = ff_lookup_->GetHeavyIndex(ff_aa, BB_CA_INDEX); atom_masses[first_idx + idx_CA] = 0; @@ -580,7 +581,8 @@ MmSystemCreator::SetupTopology_(const DisulfidBridgeVector& disulfid_bridges) { const uint idx_CB = ff_lookup_->GetHeavyIndex(ff_aa, BB_CB_INDEX); atom_masses[first_idx + idx_CB] = 0; } - } else if (i_loc == OUT_OF_LOOP) { + } + if (i_loc == OUT_OF_LOOP) { // fix surrounding (either all or only heavy atoms) if (fix_surrounding_hydrogens_) { std::fill_n(&atom_masses[first_idx], masses.size(), Real(0)); diff --git a/loop/src/mm_system_creator.hh b/loop/src/mm_system_creator.hh index 9ee72384..2602a27e 100644 --- a/loop/src/mm_system_creator.hh +++ b/loop/src/mm_system_creator.hh @@ -112,16 +112,23 @@ protected: // dealing with loops enum IndexLocation_ { - ON_N_STEM, ON_C_STEM, IN_LOOP, OUT_OF_LOOP + // to be or-ed + OUT_OF_LOOP = 0, + ON_N_STEM = 1, + ON_C_STEM = 2, + IN_LOOP = 4 }; - IndexLocation_ GetIndexLocation_(uint i_res) { - // check all loops + uint GetIndexLocation_(uint i_res) { + // check all loops (no loops of length 0 possible!) const uint num_loops = loop_start_indices_.size(); for (uint i_loop = 0; i_loop < num_loops; ++i_loop) { const uint tst = i_res - loop_start_indices_[i_loop]; - if (tst == 0) return ON_N_STEM; - if (tst == loop_lengths_[i_loop]-1) return ON_C_STEM; - if (tst < loop_lengths_[i_loop]-1) return IN_LOOP; + if (tst < loop_lengths_[i_loop]) { + uint res = IN_LOOP; + if (tst == 0) res |= ON_N_STEM; + if (tst == loop_lengths_[i_loop]-1) res |= ON_C_STEM; + return res; + } } return OUT_OF_LOOP; } diff --git a/loop/tests/test_mm_system_creator.cc b/loop/tests/test_mm_system_creator.cc index 48f14fcf..743cac93 100644 --- a/loop/tests/test_mm_system_creator.cc +++ b/loop/tests/test_mm_system_creator.cc @@ -365,6 +365,36 @@ void CheckLoopMinimize(const AllAtomPositions& all_pos, // check result AllAtomPositionsPtr new_pos = all_pos.Copy(); mm_sim.ExtractLoopPositions(*new_pos, res_indices); + const uint num_residues = all_pos.GetNumResidues(); + for (uint res_idx = 0; res_idx < num_residues; ++res_idx) { + // expect stems out-of-loop and parts of stems to be fixed and rest moving + const bool in_loop = (res_idx >= start_res_idx && res_idx <= end_res_idx); + const bool is_nstem = (start_res_idx > 0 && res_idx == start_res_idx); + const bool is_cstem = ( end_res_idx < num_residues - 1 + && res_idx == end_res_idx); + // check atoms + const uint first_idx = all_pos.GetFirstIndex(res_idx); + const uint last_idx = all_pos.GetLastIndex(res_idx); + for (uint i = first_idx; i <= last_idx; ++i) { + const uint atom_idx = i - first_idx; + const Real dist = geom::Distance(all_pos.GetPos(i), new_pos->GetPos(i)); + if (!in_loop) { + BOOST_CHECK_EQUAL(dist, Real(0)); + } else if (is_nstem && ( atom_idx == BB_N_INDEX + || atom_idx == BB_CA_INDEX + || atom_idx == BB_CB_INDEX)) { + BOOST_CHECK(dist < Real(1e-6)); + } else if (is_cstem && ( atom_idx == BB_CA_INDEX + || atom_idx == BB_CB_INDEX + || atom_idx == BB_C_INDEX + || atom_idx == BB_O_INDEX)) { + BOOST_CHECK(dist < Real(1e-6)); + } else { + BOOST_CHECK(dist > 1e-6); + } + } + } + // TEST uint num_moves = 0; for (uint i = 0; i < all_pos.GetNumAtoms(); ++i) { const Real dist = geom::Distance(all_pos.GetPos(i), new_pos->GetPos(i)); @@ -409,7 +439,9 @@ void CheckLoopMinimize(const AllAtomPositions& all_pos, void CheckLoopMinimize(const AllAtomPositions& all_pos, bool fix_surrounding_hydrogens, bool kill_es, Real cutoff) { + //////////////////////////////////////////////////////////////////////////// // run single loops + //////////////////////////////////////////////////////////////////////////// const uint num_residues = all_pos.GetNumResidues(); CheckLoopMinimize(all_pos, fix_surrounding_hydrogens, kill_es, cutoff, 0, num_residues-1); @@ -418,7 +450,17 @@ void CheckLoopMinimize(const AllAtomPositions& all_pos, CheckLoopMinimize(all_pos, fix_surrounding_hydrogens, kill_es, cutoff, num_residues-5, num_residues-1); + //////////////////////////////////////////////////////////////////////////// // set up multi-loop problem (follows CheckLoopMinimize/SetupLoopShift) + //////////////////////////////////////////////////////////////////////////// + // fix problem + const uint start_res_idx1 = 10; + const uint end_res_idx1 = 15; + const uint loop_length1 = end_res_idx1 - start_res_idx1 + 1; + const uint start_res_idx2 = num_residues-5; + const uint end_res_idx2 = num_residues-1; + const uint loop_length2 = end_res_idx2 - start_res_idx2 + 1; + // setup mm_sim ForcefieldLookupPtr ff_lookup = ForcefieldLookup::GetDefault(); MmSystemCreator mm_sim(ff_lookup, fix_surrounding_hydrogens, kill_es, cutoff); MmSystemCreator mm_sim_inaccurate(ff_lookup, fix_surrounding_hydrogens, @@ -430,10 +472,10 @@ void CheckLoopMinimize(const AllAtomPositions& all_pos, // same loops as above std::vector<uint> loop_start_indices; std::vector<uint> loop_lengths; - loop_start_indices.push_back(10); - loop_lengths.push_back(6); - loop_start_indices.push_back(num_residues-5); - loop_lengths.push_back(5); + loop_start_indices.push_back(start_res_idx1); + loop_lengths.push_back(loop_length1); + loop_start_indices.push_back(start_res_idx2); + loop_lengths.push_back(loop_length2); // get terminal info std::vector<bool> is_n_ter(num_residues, false); std::vector<bool> is_c_ter(num_residues, false); @@ -458,20 +500,38 @@ void CheckLoopMinimize(const AllAtomPositions& all_pos, // check result AllAtomPositionsPtr new_pos = all_pos.Copy(); mm_sim.ExtractLoopPositions(*new_pos, res_indices); - uint num_moves = 0; - const uint first_idx1 = all_pos.GetFirstIndex(10); - const uint last_idx1 = all_pos.GetLastIndex(15); - const uint first_idx2 = all_pos.GetFirstIndex(num_residues-5); - const uint last_idx2 = all_pos.GetLastIndex(num_residues-1); - for (uint i = 0; i < all_pos.GetNumAtoms(); ++i) { - const Real dist = geom::Distance(all_pos.GetPos(i), new_pos->GetPos(i)); - if ((i < first_idx1 || i > last_idx1) && (i < first_idx2 || i > last_idx2)) { - BOOST_CHECK_EQUAL(dist, Real(0)); - } else if (dist > 0) { - ++num_moves; + for (uint res_idx = 0; res_idx < num_residues; ++res_idx) { + // expect stems out-of-loop and parts of stems to be fixed and rest moving + const bool in_loop = ( ( res_idx >= start_res_idx1 + && res_idx <= end_res_idx1) + || (res_idx >= start_res_idx2 + && res_idx <= end_res_idx2)); + const bool is_nstem = ( res_idx == start_res_idx1 + || res_idx == start_res_idx2); + // HACK: end_res_idx2 is C-terminal! + const bool is_cstem = (res_idx == end_res_idx1); + // check atoms + const uint first_idx = all_pos.GetFirstIndex(res_idx); + const uint last_idx = all_pos.GetLastIndex(res_idx); + for (uint i = first_idx; i <= last_idx; ++i) { + const uint atom_idx = i - first_idx; + const Real dist = geom::Distance(all_pos.GetPos(i), new_pos->GetPos(i)); + if (!in_loop) { + BOOST_CHECK_EQUAL(dist, Real(0)); + } else if (is_nstem && ( atom_idx == BB_N_INDEX + || atom_idx == BB_CA_INDEX + || atom_idx == BB_CB_INDEX)) { + BOOST_CHECK(dist < Real(1e-6)); + } else if (is_cstem && ( atom_idx == BB_CA_INDEX + || atom_idx == BB_CB_INDEX + || atom_idx == BB_C_INDEX + || atom_idx == BB_O_INDEX)) { + BOOST_CHECK(dist < Real(1e-6)); + } else { + BOOST_CHECK(dist > 1e-6); + } } } - BOOST_CHECK(num_moves > 4*mm_sim.GetNumLoopResidues()); // repeat with inaccurate one mm_sim_inaccurate.SetupSystem(all_pos, res_indices, loop_start_indices, loop_lengths, is_n_ter, is_c_ter, @@ -485,6 +545,47 @@ void CheckLoopMinimize(const AllAtomPositions& all_pos, const Real dist = geom::Distance(new_pos->GetPos(i), new_pos2->GetPos(i)); BOOST_CHECK_EQUAL(dist, Real(0)); } + + //////////////////////////////////////////////////////////////////////////// + // try loop of length 1 (only sc should move!)//////////////////////////////////////////////////////////////////////////// + // find interesting case + uint loop_idx = 1; + for (; loop_idx < num_residues-1; ++loop_idx) { + const uint first_idx = all_pos.GetFirstIndex(loop_idx); + const uint last_idx = all_pos.GetLastIndex(loop_idx); + if (last_idx - first_idx > 4) break; + } + // build system + loop_start_indices.assign(1, loop_idx); + loop_lengths.assign(1, 1); + mm_sim.SetupSystem(all_pos, res_indices, loop_start_indices, loop_lengths, + is_n_ter, is_c_ter, disulfid_bridges); + // run it for a bit + sim = mm_sim.GetSimulation(); + pot_ref_loop = sim->GetPotentialEnergy(); + sim->ApplySD(0.01, 25); + BOOST_CHECK(sim->GetPotentialEnergy() < pot_ref_loop); + // check result + new_pos = all_pos.Copy(); + mm_sim.ExtractLoopPositions(*new_pos, res_indices); + const uint first_idx = all_pos.GetFirstIndex(loop_idx); + const uint last_idx = all_pos.GetLastIndex(loop_idx); + for (uint i = 0; i < all_pos.GetNumAtoms(); ++i) { + const Real dist = geom::Distance(all_pos.GetPos(i), new_pos->GetPos(i)); + if (i < first_idx || i > last_idx) { + BOOST_CHECK_EQUAL(dist, Real(0)); + } else { + // expect backbone to be fixed + const uint atom_idx = i - first_idx; + if ( atom_idx == BB_N_INDEX || atom_idx == BB_CA_INDEX + || atom_idx == BB_C_INDEX || atom_idx == BB_O_INDEX + || atom_idx == BB_CB_INDEX) { + BOOST_CHECK(dist < Real(1e-6)); + } else { + BOOST_CHECK(dist > 1e-6); + } + } + } } } // anon ns -- GitLab