diff --git a/actions/doc/index.rst b/actions/doc/index.rst index 450ffa57d28ef1f491876e3f468880a55741713d..39c68baf7c8c46a2be6a8409d57b058c4060ce90 100644 --- a/actions/doc/index.rst +++ b/actions/doc/index.rst @@ -190,3 +190,8 @@ Several flags control the modelling behaviour: Dont do subrotamer optimization if flexible rotamer model is used +.. option:: -f, --energy_function + + The energy function to be used. Default is SCWRL4, can be any function + supported by :meth:`promod3.modelling.ReconstructSidechains`. + diff --git a/actions/pm-build-sidechains b/actions/pm-build-sidechains index 72a0ddfc6a57d9bdca6fd07d70269d47f570abce..2a57c5165c110c4ea5bdcfbf9bc9b6d1992d58df 100644 --- a/actions/pm-build-sidechains +++ b/actions/pm-build-sidechains @@ -54,6 +54,8 @@ parser.add_argument('-i', '--backbone-independent', action='store_true', parser.add_argument('-s', '--no-subrotamer-optimization', action='store_true', help='Dont do subrotamer optimization if flexible ' + 'rotamer model is used.') +parser.add_argument('-f', '--energy_function', action = 'store', + dest = "energy_function", default = "SCWRL4") opts = parser.Parse() @@ -80,7 +82,8 @@ modelling.ReconstructSidechains(prot, keep_sidechains=opts.keep_sidechains, build_disulfids=opts.no_disulfids==False, rotamer_model=rotamer_model, rotamer_library=lib, - optimize_subrotamers=opt_subrot) + optimize_subrotamers=opt_subrot, + energy_function = opts.energy_function) # output ost.PopVerbosityLevel() diff --git a/modelling/pymod/_reconstruct_sidechains.py b/modelling/pymod/_reconstruct_sidechains.py index b94c37c93c389fb54b3d8661777e7f720c58dced..2586ac8f7199b1ba46784b0d6b71851f346a944d 100644 --- a/modelling/pymod/_reconstruct_sidechains.py +++ b/modelling/pymod/_reconstruct_sidechains.py @@ -402,7 +402,8 @@ def ReconstructSidechains(ent, keep_sidechains=False, build_disulfids=True, rotamer_model="frm", consider_ligands=True, rotamer_library=None, optimize_subrotamers=True, graph_max_complexity=100000000, - graph_initial_epsilon=0.02): + graph_initial_epsilon=0.02, + energy_function = "SCWRL4"): '''Reconstruct sidechains for the given structure. :param ent: Structure for sidechain reconstruction. Note, that the sidechain @@ -445,6 +446,9 @@ def ReconstructSidechains(ent, keep_sidechains=False, build_disulfids=True, :param graph_intial_epsilon: Initial epsilon for :meth:`RotamerGraph.TreeSolve`. :type graph_intial_epsilon: :class:`float` + :param energy_function: What energy function to use can be any in + ["SCWRL4", "SCWRL3"] + :type energy_function: :class:`str` ''' prof_name = 'modelling::ReconstructSidechains' prof = core.StaticRuntimeProfiler.StartScoped(prof_name) @@ -463,8 +467,16 @@ def ReconstructSidechains(ent, keep_sidechains=False, build_disulfids=True, if type(rotamer_library) is sidechain.BBDepRotamerLib: bbdep = True - rotamer_constructor = sidechain.SCWRL4RotamerConstructor(False) - + rotamer_constructor = None + + if energy_function == "SCWRL4": + rotamer_constructor = sidechain.SCWRL4RotamerConstructor(False) + if energy_function == "SCWRL3": + rotamer_constructor = sidechain.SCWRL3RotamerConstructor(False) + + if rotamer_constructor == None: + raise RuntimeError("Invalid Energy function to reconstruct sidechains!") + # take out ligand chain and any non-peptides prot = ent.Select("peptide=true and cname!='_'") diff --git a/sidechain/pymod/export_rotamer_constructor.cc b/sidechain/pymod/export_rotamer_constructor.cc index cf28f603746dd64ab52ecb8a238057ee7081f05f..fdb91bb4ac3a745b6027141ff4c974e781c9ccf4 100644 --- a/sidechain/pymod/export_rotamer_constructor.cc +++ b/sidechain/pymod/export_rotamer_constructor.cc @@ -21,6 +21,7 @@ #include <promod3/sidechain/rotamer.hh> #include <promod3/sidechain/rotamer_group.hh> #include <promod3/sidechain/scwrl4_rotamer_constructor.hh> +#include <promod3/sidechain/scwrl3_rotamer_constructor.hh> using namespace boost::python; using namespace promod3::sidechain; @@ -34,6 +35,11 @@ SCWRL4RotamerConstructorPtr WrapSCWRL4RotamerConstructorInit(bool cb_in_sidechai return p; } +SCWRL3RotamerConstructorPtr WrapSCWRL3RotamerConstructorInit(bool cb_in_sidechain) { + SCWRL3RotamerConstructorPtr p(new SCWRL3RotamerConstructor(cb_in_sidechain)); + return p; +} + RRMRotamerGroupPtr WrapRRMGroup_res(RotamerConstructorPtr constructor, const ost::mol::ResidueHandle& res, RotamerID id, @@ -444,4 +450,10 @@ void export_RotamerConstructor(){ arg("comp_lib"))) ; + + class_<SCWRL3RotamerConstructor, SCWRL3RotamerConstructorPtr, + bases<RotamerConstructor> >("SCWRL3RotamerConstructor", no_init) + .def("__init__", boost::python::make_constructor(&WrapSCWRL3RotamerConstructorInit)) + ; + } diff --git a/sidechain/src/CMakeLists.txt b/sidechain/src/CMakeLists.txt index 953b809ad3108aa9ae82d9431483ecdc8e6eaedc..1c142e51635c10fc9c47042dd65b0bf78639a1e4 100644 --- a/sidechain/src/CMakeLists.txt +++ b/sidechain/src/CMakeLists.txt @@ -7,6 +7,7 @@ set(SIDECHAIN_HEADERS particle_scoring_base.hh particle_scoring.hh scwrl4_particle_scoring.hh + scwrl3_particle_scoring.hh rotamer.hh rotamer_cruncher.hh rotamer_density.hh @@ -20,6 +21,7 @@ set(SIDECHAIN_HEADERS rotamer_constructor.hh rotamer_lookup.hh scwrl4_rotamer_constructor.hh + scwrl3_rotamer_constructor.hh subrotamer_optimizer.hh ) @@ -29,6 +31,7 @@ set(SIDECHAIN_SOURCES frame.cc particle_scoring.cc scwrl4_particle_scoring.cc + scwrl3_particle_scoring.cc rotamer.cc rotamer_cruncher.cc rotamer_density.cc @@ -42,6 +45,7 @@ set(SIDECHAIN_SOURCES rotamer_constructor.cc rotamer_lookup.cc scwrl4_rotamer_constructor.cc + scwrl3_rotamer_constructor.cc subrotamer_optimizer.cc ) diff --git a/sidechain/src/particle_scoring.cc b/sidechain/src/particle_scoring.cc index c95fc241162e7acf48234422e7bf71537cb484ee..de558f3f89248257b506561b5e4ad329b9ea9a21 100644 --- a/sidechain/src/particle_scoring.cc +++ b/sidechain/src/particle_scoring.cc @@ -16,6 +16,7 @@ #include <promod3/core/message.hh> #include <promod3/sidechain/particle_scoring.hh> #include <promod3/sidechain/scwrl4_particle_scoring.hh> +#include <promod3/sidechain/scwrl3_particle_scoring.hh> namespace promod3{ namespace sidechain{ @@ -31,6 +32,10 @@ Real PairwiseParticleScore(PScoringParam* p_one, PScoringParam* p_two) { return SCWRL4PairwiseScore(reinterpret_cast<SCWRL4Param*>(p_one), reinterpret_cast<SCWRL4Param*>(p_two)); } + case SCWRL3: { + return SCWRL3PairwiseScore(reinterpret_cast<SCWRL3Param*>(p_one), + reinterpret_cast<SCWRL3Param*>(p_two)); + } default: { throw promod3::Error("Don't know what scoring function to call between " "particles... maybe a lazy developer forgot to " @@ -85,6 +90,16 @@ void PScoringParamContainer::PairwiseScores(const PScoringParamContainer& other, } break; } + case SCWRL3: { + scores.resize(idx.size()); + for(uint i = 0; i < idx.size(); ++i) { + scores[i] = + SCWRL3PairwiseScore(reinterpret_cast<SCWRL3Param*>(params_[idx[i].first]), + reinterpret_cast<SCWRL3Param*>(other.params_[idx[i].second])); + } + break; + + } default: { throw promod3::Error("Don't know what scoring function to call between " "particles... maybe a lazy developer forgot to " diff --git a/sidechain/src/particle_scoring_base.hh b/sidechain/src/particle_scoring_base.hh index 96cdb6d97b80353e3a5331d394d6e707db9ae501..e5cbdd167589f0a72df43d01dd9abd27ff8f9926 100644 --- a/sidechain/src/particle_scoring_base.hh +++ b/sidechain/src/particle_scoring_base.hh @@ -25,6 +25,7 @@ namespace promod3{ namespace sidechain{ // the available particle scoring functions enum PScoringFunction{ SCWRL4, +SCWRL3, INVALID_PSCORING_FUNCTION }; diff --git a/sidechain/src/scwrl3_particle_scoring.cc b/sidechain/src/scwrl3_particle_scoring.cc new file mode 100644 index 0000000000000000000000000000000000000000..9cf9b04e25e3b179af274489d2b32c8e0b9edb06 --- /dev/null +++ b/sidechain/src/scwrl3_particle_scoring.cc @@ -0,0 +1,65 @@ +// Copyright (c) 2013-2018, SIB - Swiss Institute of Bioinformatics and +// Biozentrum - University of Basel +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#include <promod3/sidechain/scwrl3_particle_scoring.hh> + + +namespace promod3 { namespace sidechain { + +void SCWRL3Param::ApplyTransform(const geom::Mat4& t) { + + // get transformed pos + Real a = t(0,0)*pos_[0] + t(0,1)*pos_[1] + t(0,2)*pos_[2] + t(0,3); + Real b = t(1,0)*pos_[0] + t(1,1)*pos_[1] + t(1,2)*pos_[2] + t(1,3); + Real c = t(2,0)*pos_[0] + t(2,1)*pos_[1] + t(2,2)*pos_[2] + t(2,3); + pos_ = geom::Vec3(a, b, c); +} + + +SCWRL3Param* SCWRL3Param::Copy() const { + SCWRL3Param* return_ptr = new SCWRL3Param(pos_, radius_); + return return_ptr; +} + + +bool SCWRL3Param::EqualTo(PScoringParam* other) const { + + if(other == NULL) return false; + if(other->GetScoringFunction() != SCWRL3) return false; + + // as the other scoring function is also SCWRL3, we can assume that + // the following dynamic cast is fine... + SCWRL3Param* p = dynamic_cast<SCWRL3Param*>(other); + + return pos_ == p->pos_ && + radius_ == p->radius_; +} + + +Real SCWRL3PairwiseScore(SCWRL3Param* p_one, SCWRL3Param* p_two) { + + Real d = geom::Distance(p_one->pos_, p_two->pos_); + Real R = p_one->radius_ + p_two->radius_; + Real e = 0.0; + if(d < Real(0.8254) * R) { + e = 10.0; + } else if(d <= R) { + e = 57.273 * (1 - d/R); + } + return e; +} + +}}//ns diff --git a/sidechain/src/scwrl3_particle_scoring.hh b/sidechain/src/scwrl3_particle_scoring.hh new file mode 100644 index 0000000000000000000000000000000000000000..1208dd43931b7922ab5e1cb91538fb02f8bb3cd8 --- /dev/null +++ b/sidechain/src/scwrl3_particle_scoring.hh @@ -0,0 +1,52 @@ +// Copyright (c) 2013-2018, SIB - Swiss Institute of Bioinformatics and +// Biozentrum - University of Basel +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef PROMOD3_SCWRL3_PARTICLE_SCORING_HH +#define PROMOD3_SCWRL3_PARTICLE_SCORING_HH + +#include <ost/geom/mat4.hh> +#include <ost/geom/vecmat3_op.hh> +#include <promod3/sidechain/particle_scoring_base.hh> + +namespace promod3{ namespace sidechain{ + +struct SCWRL3Param : public PScoringParam { + + SCWRL3Param(const geom::Vec3& pos, Real r): pos_(pos), radius_(r) { } + + virtual ~SCWRL3Param() { } + + virtual const geom::Vec3& GetPos() const { return pos_; } + + virtual Real GetCollisionDistance() const { return radius_; } + + virtual void ApplyTransform(const geom::Mat4& t); + + virtual SCWRL3Param* Copy() const; + + virtual bool EqualTo(PScoringParam* other) const; + + virtual PScoringFunction GetScoringFunction() const { return SCWRL3; } + + geom::Vec3 pos_; + Real radius_; +}; + + +Real SCWRL3PairwiseScore(SCWRL3Param* p_one, SCWRL3Param* p_two); + +}} //ns + +#endif diff --git a/sidechain/src/scwrl3_rotamer_constructor.cc b/sidechain/src/scwrl3_rotamer_constructor.cc new file mode 100644 index 0000000000000000000000000000000000000000..d5f9048bbb5cbcf1b220bff635983cdbfe94c694 --- /dev/null +++ b/sidechain/src/scwrl3_rotamer_constructor.cc @@ -0,0 +1,140 @@ +// Copyright (c) 2013-2018, SIB - Swiss Institute of Bioinformatics and +// Biozentrum - University of Basel +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#include <promod3/sidechain/scwrl3_rotamer_constructor.hh> +#include <promod3/sidechain/scwrl3_particle_scoring.hh> +#include <promod3/core/runtime_profiling.hh> +#include <promod3/core/message.hh> +#include <promod3/core/runtime_profiling.hh> +#include <ost/conop/conop.hh> + +namespace promod3 { namespace sidechain { + +struct SCWRL3RotamerParam : public RotamerLookupParam { + + SCWRL3RotamerParam() { + + // overwrite default internal_e_prefactor from base class + internal_e_prefactor[ost::conop::ARG] = 3.0; + internal_e_prefactor[ost::conop::ASN] = 3.0; + internal_e_prefactor[ost::conop::ASP] = 3.0; + internal_e_prefactor[ost::conop::GLN] = 3.0; + internal_e_prefactor[ost::conop::GLU] = 3.0; + internal_e_prefactor[ost::conop::LYS] = 3.0; + internal_e_prefactor[ost::conop::SER] = 3.0; + internal_e_prefactor[ost::conop::CYS] = 3.0; + internal_e_prefactor[ost::conop::MET] = 3.0; + internal_e_prefactor[ost::conop::TRP] = 3.0; + internal_e_prefactor[ost::conop::TYR] = 3.0; + internal_e_prefactor[ost::conop::THR] = 3.0; + internal_e_prefactor[ost::conop::VAL] = 3.0; + internal_e_prefactor[ost::conop::ILE] = 3.0; + internal_e_prefactor[ost::conop::LEU] = 3.0; + internal_e_prefactor[ost::conop::PRO] = 3.0; + internal_e_prefactor[ost::conop::HIS] = 3.0; + internal_e_prefactor[ost::conop::PHE] = 3.0; + } + + static const SCWRL3RotamerParam& Instance() { + static SCWRL3RotamerParam scwrl3_param; + return scwrl3_param; + } +}; + + +SCWRL3RotamerConstructor::SCWRL3RotamerConstructor(bool cb_in_sidechain): + RotamerConstructor(cb_in_sidechain, HEAVY_ATOM_MODE, + SCWRL3RotamerParam::Instance()) { } + +void SCWRL3RotamerConstructor::AssignInternalEnergies(RRMRotamerGroupPtr group, + RotamerID id, + uint residue_index, + Real phi, Real psi, + bool n_ter, bool c_ter) { + + core::ScopedTimerPtr prof = core::StaticRuntimeProfiler::StartScoped( + "SCWRL3RotamerConstructor::AssignInternalEnergies", 2); + + Real max_p = group->GetMaxP(); + for(uint i = 0; i < group->size(); ++i){ + RRMRotamerPtr r = (*group)[i]; + Real internal_e_prefactor = r->GetInternalEnergyPrefactor(); + Real probability = r->GetProbability(); + Real e = -internal_e_prefactor * std::log(probability/max_p); + r->SetInternalEnergy(e); + } +} + + +void SCWRL3RotamerConstructor::AssignInternalEnergies(FRMRotamerGroupPtr group, + RotamerID id, + uint residue_index, + Real phi, Real psi, + bool n_ter, bool c_ter) { + + core::ScopedTimerPtr prof = core::StaticRuntimeProfiler::StartScoped( + "SCWRL3RotamerConstructor::AssignInternalEnergies", 2); + + Real max_p = group->GetMaxP(); + for(uint i = 0; i < group->size(); ++i){ + FRMRotamerPtr r = (*group)[i]; + Real internal_e_prefactor = r->GetInternalEnergyPrefactor(); + Real probability = r->GetProbability(); + Real e = -internal_e_prefactor * std::log(probability/max_p); + r->SetInternalEnergy(e); + } +} + + +void SCWRL3RotamerConstructor::ParametrizeParticle(int at_idx, + bool is_hydrogen, + Particle& particle) { + + if(is_hydrogen) { + throw promod3::Error("Expect no hydrogen in SCWRL3RotamerConstructor!"); + } + + geom::Vec3 pos; + Real radius = 0.0; + + if(at_idx == -2) { + pos = terminal_o_pos_; + radius = 1.3; + } else if (at_idx == -1){ + pos = terminal_oxt_pos_; + radius = 1.3; + } else { + pos = pos_buffer_->GetPos(id_, at_idx); + ost::conop::AminoAcid aa = RotIDToAA(id_); + promod3::loop::AminoAcidAtom aaa = + promod3::loop::AminoAcidLookup::GetInstance().GetAAA(aa, at_idx); + String ele = promod3::loop::AminoAcidLookup::GetInstance().GetElement(aaa); + if(ele == "C") { + radius = 1.6; + } else if(ele == "N") { + radius = 1.3; + } else if(ele == "O") { + radius = 1.3; + } else if (ele == "S") { + radius = 1.7; + } + } + + SCWRL3Param* p = new SCWRL3Param(pos, radius); + particle.SetSParam(p); +} + +}} //ns diff --git a/sidechain/src/scwrl3_rotamer_constructor.hh b/sidechain/src/scwrl3_rotamer_constructor.hh new file mode 100644 index 0000000000000000000000000000000000000000..4036ff20455bbb9d42e9b570d4467844ca145655 --- /dev/null +++ b/sidechain/src/scwrl3_rotamer_constructor.hh @@ -0,0 +1,59 @@ +// Copyright (c) 2013-2018, SIB - Swiss Institute of Bioinformatics and +// Biozentrum - University of Basel +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#ifndef PROMOD3_SCWRL3_ROTAMER_CONSTRUCTOR_HH +#define PROMOD3_SCWRL3_ROTAMER_CONSTRUCTOR_HH + +#include <promod3/sidechain/rotamer_constructor.hh> + +namespace promod3 { namespace sidechain { + +class SCWRL3RotamerConstructor; +typedef boost::shared_ptr<SCWRL3RotamerConstructor> SCWRL3RotamerConstructorPtr; + +class SCWRL3RotamerConstructor : public RotamerConstructor{ + +public: + + SCWRL3RotamerConstructor(bool cb_in_sidechain = false); + + virtual ~SCWRL3RotamerConstructor() { } + + // Assign internal energies to rotamer groups + virtual void AssignInternalEnergies(RRMRotamerGroupPtr group, + RotamerID id, + uint residue_index, + Real phi = -1.0472, + Real psi = -0.7854, + bool n_ter = false, + bool c_ter = false); + + virtual void AssignInternalEnergies(FRMRotamerGroupPtr group, + RotamerID id, + uint residue_index, + Real phi = -1.0472, + Real psi = -0.7854, + bool n_ter = false, + bool c_ter = false); + +private: + + void ParametrizeParticle(int atom_idx, bool is_hydrogen, Particle& p); +}; + +}} // ns + +#endif