diff --git a/modules/conop/pymod/CMakeLists.txt b/modules/conop/pymod/CMakeLists.txt index 97de72d7a52f1a74233a9782e746bd596620ffc7..650939bfd9aea21dac1925adadf6866f4db37e65 100644 --- a/modules/conop/pymod/CMakeLists.txt +++ b/modules/conop/pymod/CMakeLists.txt @@ -4,6 +4,7 @@ set(OST_CONOP_PYMOD_SOURCES export_compound.cc export_amino_acids.cc export_conop.cc + export_non_standard.cc export_ring_finder.cc ) diff --git a/modules/conop/pymod/export_non_standard.cc b/modules/conop/pymod/export_non_standard.cc new file mode 100644 index 0000000000000000000000000000000000000000..025d2819a100584c85f3b088ce5320fdf02d0762 --- /dev/null +++ b/modules/conop/pymod/export_non_standard.cc @@ -0,0 +1,50 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ +#include <boost/python.hpp> +#include <ost/mol/mol.hh> +#include <ost/conop/nonstandard.hh> + +using namespace boost::python; + +using namespace ost::conop; +using namespace ost::mol; + +object copy_conserved_handle(ResidueHandle src_res, ResidueHandle dst_res, + XCSEditor edi) { + bool has_cbeta = false; + bool ret = CopyConserved(src_res, dst_res, edi, has_cbeta); + return make_tuple(ret, has_cbeta); +} + +object copy_non_conserved_handle(ResidueHandle src_res, ResidueHandle dst_res, + XCSEditor edi) { + bool has_cbeta = false; + bool ret = CopyNonConserved(src_res, dst_res, edi, has_cbeta); + return make_tuple(ret, has_cbeta); +} + + + +void export_NonStandard() +{ + def("CopyNonConserved",©_non_conserved_handle); + def("CopyConserved", copy_conserved_handle); + def("CopyResidue", &CopyResidue); + } + diff --git a/modules/conop/pymod/wrap_conop.cc b/modules/conop/pymod/wrap_conop.cc index 2aba86654fb077bc42751b173a5185f22bb18ffc..6573bf41a7e6c8fcb471cbf25a79be77b1b03dfa 100644 --- a/modules/conop/pymod/wrap_conop.cc +++ b/modules/conop/pymod/wrap_conop.cc @@ -25,6 +25,8 @@ void export_Sanitizer(); void export_Conop(); void export_RingFinder(); void export_AminoAcids(); +void export_NonStandard(); + BOOST_PYTHON_MODULE(_ost_conop) { export_Builder(); @@ -32,4 +34,5 @@ BOOST_PYTHON_MODULE(_ost_conop) export_Compound(); export_RingFinder(); export_AminoAcids(); + export_NonStandard(); } diff --git a/modules/conop/src/CMakeLists.txt b/modules/conop/src/CMakeLists.txt index 127bd15ea7757eaaa50abeda7c7e07d3f295f3f0..344f5e00755d3ba733f1d6a877840037c8da802b 100644 --- a/modules/conop/src/CMakeLists.txt +++ b/modules/conop/src/CMakeLists.txt @@ -7,6 +7,7 @@ amino_acids.hh compound.hh compound_lib.hh module_config.hh +nonstandard.hh rule_based_builder.hh ring_finder.hh ) @@ -18,12 +19,13 @@ conop.cc heuristic_builder.cc compound.cc compound_lib.cc +nonstandard.cc rule_based_builder.cc ring_finder.cc ) module(NAME conop SOURCES ${OST_CONOP_SOURCES} - HEADERS ${OST_CONOP_HEADERS} DEPENDS_ON ost_mol ost_geom ost_db) + HEADERS ${OST_CONOP_HEADERS} DEPENDS_ON ost_mol ost_mol_alg ost_geom ost_db) executable(NAME chemdict_tool SOURCES chemdict_tool.cc DEPENDS_ON ost_io STATIC) diff --git a/modules/conop/src/nonstandard.cc b/modules/conop/src/nonstandard.cc new file mode 100644 index 0000000000000000000000000000000000000000..620cd9a1d5ef2d90c23deb950486dc2be0e34f30 --- /dev/null +++ b/modules/conop/src/nonstandard.cc @@ -0,0 +1,265 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ + +/* + Author: Marco Biasini, Juergen Haas + */ + +#include <ost/log.hh> +#include <ost/dyn_cast.hh> +#include <ost/conop/conop.hh> +#include <ost/mol/mol.hh> +#include <ost/mol/alg/construct_cbeta.hh> +#include <ost/conop/rule_based_builder.hh> +#include <ost/conop/compound_lib.hh> +#include "nonstandard.hh" +using namespace ost::mol; +using namespace ost; +using namespace ost::conop; + +namespace ost { namespace conop { + +namespace { + +bool CheckBackboneAtoms(ResidueHandle res) +{ + String atom_names[]={"N", "CA", "C", "O"}; + std::vector<String> missing; + for (int i =0; i<4; ++i) { + if (!res.FindAtom(atom_names[i])) { + missing.push_back(atom_names[i]); + } + } + if (!missing.empty()) { + std::stringstream ss; + ss << "residue " << res.GetQualifiedName() << " is missing atoms "; + for (std::vector<String>::const_iterator + i=missing.begin(), e=missing.end(); i!=e; ++i) { + if (i!=missing.begin()) { + ss << ", "; + } + ss << *i; + } + LOG_WARNING(ss.str()); + return false; + } + return true; +} + +bool CheckCalphaAtom(ResidueHandle res) +{ + String atom_names[]={"N", "CA", "C", "O"}; + std::vector<String> missing; + for (int i =0; i<4; ++i) { + if (!res.FindAtom(atom_names[i])) { + missing.push_back(atom_names[i]); + } + } + if (!res.FindAtom("CA")) { + LOG_WARNING("residue " << res.GetQualifiedName() << " is missing CA atom"); + return false; + } + return true; +} + +} + +bool CopyResidue(ResidueHandle src_res, ResidueHandle dst_res, XCSEditor& edi) +{ + bool has_cbeta = false; + bool ret; + if (src_res.GetName()==dst_res.GetName()) { + ret = CopyConserved(src_res, dst_res, edi, has_cbeta); + } else { + ret = CopyNonConserved(src_res, dst_res, edi, has_cbeta); + } + // insert Cbeta, unless dst residue is glycine. + if (!has_cbeta && dst_res.GetName()!="GLY") { + geom::Vec3 cbeta_pos=mol::alg::CBetaPosition(dst_res); + edi.InsertAtom(dst_res, "CB", cbeta_pos, "C"); + } + return ret; +} + +bool CopyConserved(ResidueHandle src_res, ResidueHandle dst_res, XCSEditor& edi, + bool& has_cbeta) +{ + // check if the residue name of dst and src are the same. In the easy + // case, the two residue names match and we just copy over all atoms. + // If they don't match, we are dealing with modified residues. + + //~ return copy_conserved(src_res, dst_res, edi, has_cbeta); + + if (dst_res.GetName()==src_res.GetName()) { + return CopyIdentical(src_res, dst_res, edi, has_cbeta); + } else if (src_res.GetName()=="MSE") { + return CopyMSE(src_res, dst_res, edi, has_cbeta); + } else { + return CopyModified(src_res, dst_res, edi, has_cbeta); + } +} + +bool CopyIdentical(ResidueHandle src_res, ResidueHandle dst_res, XCSEditor& edi, + bool& has_cbeta) +{ + //~ return copy_identical(); + AtomHandleList atoms=src_res.GetAtomList(); + for (AtomHandleList::const_iterator + a=atoms.begin(), e=atoms.end(); a!=e; ++a) { + if (a->GetName()=="CB") { + has_cbeta=true; + } + if (a->GetElement()=="D" || a->GetElement()=="H") { + continue; + } + edi.InsertAtom(dst_res, a->GetName(), a->GetPos(), a->GetElement(), + a->GetOccupancy(), a->GetBFactor()); + } + return true; +} + + +bool CopyMSE(ResidueHandle src_res, ResidueHandle dst_res, XCSEditor& edi, + bool& has_cbeta) +{ + // selenium methionine is easy. We copy all atoms and substitute the SE + // with SD + AtomHandleList atoms=src_res.GetAtomList(); + for (AtomHandleList::const_iterator + a=atoms.begin(), e=atoms.end(); a!=e; ++a) { + if (a->GetName()=="CB") { + has_cbeta=true; + } + if (a->GetElement()=="D" || a->GetElement()=="H") { + continue; + } + if (a->GetName()=="SE") { + edi.InsertAtom(dst_res, "SD", a->GetPos(), "S", + a->GetOccupancy(), a->GetBFactor()); + } else { + edi.InsertAtom(dst_res, a->GetName(), a->GetPos(), a->GetElement(), + a->GetOccupancy(), a->GetBFactor()); + } + } + return true; +} + +bool CopyModified(ResidueHandle src_res, ResidueHandle dst_res, + XCSEditor& edi, bool& has_cbeta) +{ + // FIXME: for now this functions ignores chirality changes of sidechain + // chiral atoms. To detect those changes, we would need to store the + // chirality of those centers in the compound library. + + // For now, this function just handles cases where the src_res contains + // additional atoms, but the dst_atom doesn't contain any atoms the src_res + // doesn't have. It these two requirements are not met, we fall back to + // CopyNonConserved. + + // first let's get our hands on the component library + conop::BuilderP builder=conop::Conopology::Instance().GetBuilder("DEFAULT"); + conop::RuleBasedBuilderPtr rbb=dyn_cast<conop::RuleBasedBuilder>(builder); + conop::CompoundLibPtr comp_lib=rbb->GetCompoundLib(); + + CompoundPtr src_compound=comp_lib->FindCompound(src_res.GetName(), + Compound::PDB); + if (!src_compound) { + // OK, that's bad. Let's copy the backbone and be done with it! + return CopyNonConserved(src_res, dst_res, edi, has_cbeta); + } + // since dst_res is one of the 20 amino acids, we don't have to check for + // existence of the compound. We know it is there! + CompoundPtr dst_compound=comp_lib->FindCompound(dst_res.GetName(), + Compound::PDB); + std::set<String> dst_atoms; + std::set<String> src_atoms; + // to compare the atoms of dst_res with those of src_res, let's create two + // sets containing all heavy atoms. + for (AtomSpecList::const_iterator i=dst_compound->GetAtomSpecs().begin(), + e=dst_compound->GetAtomSpecs().end(); i!=e; ++i) { + if (i->element=="H" || i->element=="D") { + continue; + } + dst_atoms.insert(i->name); + } + for (AtomSpecList::const_iterator i=src_compound->GetAtomSpecs().begin(), + e=src_compound->GetAtomSpecs().end(); i!=e; ++i) { + if (i->element=="H" || i->element=="D") { + continue; + } + src_atoms.insert(i->name); + } + for (std::set<String>::const_iterator i=dst_atoms.begin(), + e=dst_atoms.end(); i!=e; ++i) { + if (src_atoms.find(*i)==src_atoms.end()) { + return CopyNonConserved(src_res, dst_res, edi, has_cbeta); + } + } + // Muahaha, all is good. Let's copy the atoms. Muahaha + AtomHandleList atoms=src_res.GetAtomList(); + for (AtomHandleList::const_iterator + a=atoms.begin(), e=atoms.end(); a!=e; ++a) { + if (a->GetName()=="CB") { + if (dst_res.GetName()=="GLY") { + continue; + } + has_cbeta=true; + } + if (a->GetElement()=="D" || a->GetElement()=="H") { + continue; + } + if (dst_atoms.find(a->GetName())==dst_atoms.end()) { + continue; + } + edi.InsertAtom(dst_res, a->GetName(), a->GetPos(), a->GetElement(), + a->GetOccupancy(), a->GetBFactor()); + } + return true; +} + + +bool CopyNonConserved(ResidueHandle src_res, ResidueHandle dst_res, + XCSEditor& edi, bool& has_cbeta) +{ + AtomHandleList atoms=src_res.GetAtomList(); + for (AtomHandleList::const_iterator + a=atoms.begin(), e=atoms.end(); a!=e; ++a) { + String name=a->GetName(); + if (name=="CA" || name=="N" || name=="C" || name=="O" || name=="CB") { + if (name=="CB") { + if (dst_res.GetName()=="GLY") { + continue; + } + has_cbeta=true; + } + if (a->GetElement()=="D" || a->GetElement()=="H") { + continue; + } + edi.InsertAtom(dst_res, a->GetName(), a->GetPos(), a->GetElement(), + a->GetOccupancy(), a->GetBFactor()); + } + } + return false; +} + + + + + +}} diff --git a/modules/conop/src/nonstandard.hh b/modules/conop/src/nonstandard.hh new file mode 100644 index 0000000000000000000000000000000000000000..f8ad1cfa33d07b8d4c51db0b9019de340a882163 --- /dev/null +++ b/modules/conop/src/nonstandard.hh @@ -0,0 +1,97 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 of the License, or (at your option) +// any later version. +// This library is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ + +#ifndef OST_CONOP_NONSTANDARD_HH +#define OST_CONOP_NONSTANDARD_HH +/* + Author: Marco Biasini, Juergen Haas + */ +#include "module_config.hh" + + + + +namespace ost { namespace conop { + + +/// \brief copies all atom of src_res to dst_res +/// \param has_cbeta will be set to true if the src_res has a cbeta and the +/// dst_residue is not a glycine, it will be inserted if in the dst should +/// be one and in src it was not present + + +bool DLLEXPORT_OST_CONOP CopyResidue(ost::mol::ResidueHandle src_res, + ost::mol::ResidueHandle dst_res, + ost::mol::XCSEditor& edi); + +/// \brief copies all atom of src_res to dst_res +/// \param has_cbeta will be set to true if the src_res has a cbeta and the +/// dst_residue is not a glycine + + +bool DLLEXPORT_OST_CONOP CopyIdentical(ost::mol::ResidueHandle src_res, + ost::mol::ResidueHandle dst_res, + ost::mol::XCSEditor& edi, + bool& has_cbeta); + +/// \brief copies atoms of src_res to dst_res +/// +/// src_res and dst_res are thought to be conserved, e.g. the parent standard +/// amino acid of both residues is the same. This includes cases where e.g. the +/// src_rs is and MSE and the dst_res is a MET. This function automatically +/// tries to do the right thing an keep as many atoms as possible from src_res + + + +bool DLLEXPORT_OST_CONOP CopyConserved(ost::mol::ResidueHandle src_res, + ost::mol::ResidueHandle dst_res, + ost::mol::XCSEditor& edi, + bool& has_cbeta); + +/// \brief construct dst_res in case src_res and dst_res are not conserved. +/// +/// This essentially copies the backbone of src_res to dst_res. The CB atom is +/// only copied if dst_res is not equal to glycine. + + +bool DLLEXPORT_OST_CONOP CopyNonConserved(ost::mol::ResidueHandle src_res, + ost::mol::ResidueHandle dst_res, + ost::mol::XCSEditor& edi, + bool& has_cbeta); + +/// \brief construct dst_res from src_res when src_res is an MSE + +bool DLLEXPORT_OST_CONOP CopyMSE(ost::mol::ResidueHandle src_res, + ost::mol::ResidueHandle dst_res, + ost::mol::XCSEditor& edi, + bool& has_cbeta); + +/// \brief construct a dst_res with only atoms matching the standard aminoacid +/// from src_res when src_res is an is modified + +bool DLLEXPORT_OST_CONOP CopyModified(ost::mol::ResidueHandle src_res, + ost::mol::ResidueHandle dst_res, + ost::mol::XCSEditor& edi, + bool& has_cbeta); + + + +}} + +#endif diff --git a/modules/conop/tests/CMakeLists.txt b/modules/conop/tests/CMakeLists.txt index 1af92df10be705d46354506d72df5c0c645be732..6a832115b5933b66241c9dec5ce23c21dd532c48 100644 --- a/modules/conop/tests/CMakeLists.txt +++ b/modules/conop/tests/CMakeLists.txt @@ -5,6 +5,7 @@ set(OST_CONOP_UNIT_TESTS test_builder.cc test_compound.py test_cleanup.py + test_nonstandard.py ) ost_unittest(MODULE conop diff --git a/modules/conop/tests/test_nonstandard.py b/modules/conop/tests/test_nonstandard.py new file mode 100644 index 0000000000000000000000000000000000000000..202e47ac582093d35738fdd7b350573f6126db7d --- /dev/null +++ b/modules/conop/tests/test_nonstandard.py @@ -0,0 +1,123 @@ +import unittest +from ost import conop + + +class TestNonStandard(unittest.TestCase): + + def test_fastModified(self): + # phoshoserine: test if we correctly strip off modifications + tpl=io.LoadPDB('testfiles/sep.pdb') + new_hdl=mol.CreateEntity(); + ed=new_hdl.EditXCS() + c=ed.InsertChain('A') + ed.AppendResidue(c, 'SER') + + err, has_cbeta=conop.CopyConserved(tpl.residues[0], new_hdl.residues[0], ed) + self.assertTrue(err) + self.assertTrue(has_cbeta) + residues=new_hdl.residues + self.assertEqual(len(residues), 1) + self.assertEqual(len(residues[0].atoms), 6) + self.assertTrue(new_hdl.FindAtom("A", mol.ResNum(1), "N").IsValid()) + self.assertTrue(new_hdl.FindAtom("A", mol.ResNum(1), "CA").IsValid()) + self.assertTrue(new_hdl.FindAtom("A", mol.ResNum(1), "C").IsValid()) + self.assertTrue(new_hdl.FindAtom("A", mol.ResNum(1), "O").IsValid()) + self.assertTrue(new_hdl.FindAtom("A", mol.ResNum(1), "CB").IsValid()) + self.assertTrue(new_hdl.FindAtom("A", mol.ResNum(1), "OG").IsValid()) + + + def test_CBeta(self): + # test if the dst residues contain cbeta, unless they are glycines + tpl=io.LoadPDB('testfiles/cbeta.pdb') + new_hdl=mol.CreateEntity(); + ed=new_hdl.EditXCS() + c=ed.InsertChain('A') + ed.AppendResidue(c, 'MET') + ed.AppendResidue(c, 'GLY') + ed.AppendResidue(c, 'GLY') + ed.AppendResidue(c, 'HIS') + err, has_cbeta=conop.CopyConserved(tpl.residues[0], new_hdl.residues[0], ed) + self.assertTrue(has_cbeta) + self.assertTrue(err) + err, has_cbeta=conop.CopyConserved(tpl.residues[1], new_hdl.residues[1], ed) + self.assertFalse(has_cbeta) + self.assertTrue(err) + err, has_cbeta=conop.CopyConserved(tpl.residues[2], new_hdl.residues[2], ed) + self.assertFalse(has_cbeta) + self.assertTrue(err) + err, has_cbeta=conop.CopyConserved(tpl.residues[3], new_hdl.residues[3], ed) + self.assertTrue(has_cbeta) + self.assertTrue(err) + + residues=new_hdl.residues + self.assertEqual(len(residues), 4) + self.assertTrue(residues[0].FindAtom("CB").IsValid()) + self.assertFalse(residues[1].FindAtom("CB").IsValid()) + self.assertFalse(residues[2].FindAtom("CB").IsValid()) + self.assertTrue(residues[3].FindAtom("CB").IsValid()) + + + def test_CopyResidue(self): + tpl=io.LoadPDB('testfiles/cbeta.pdb') + new_hdl=mol.CreateEntity(); + ed=new_hdl.EditXCS() + c=ed.InsertChain('A') + ed.AppendResidue(c, 'MET') + ed.AppendResidue(c, 'GLY') + ed.AppendResidue(c, 'GLY') + ed.AppendResidue(c, 'HIS') + ed.AppendResidue(c, 'HIS') + ed.AppendResidue(c, 'GLY') + ed.AppendResidue(c, 'HIS') + ed.AppendResidue(c, 'MET') + + # MET to MET + err =conop.CopyResidue(tpl.residues[0], new_hdl.residues[0], ed) + self.assertTrue(err) + #GLY to GLY + err =conop.CopyResidue(tpl.residues[1], new_hdl.residues[1], ed) + self.assertTrue(err) + # GLY to GLY + err =conop.CopyResidue(tpl.residues[2], new_hdl.residues[2], ed) + self.assertTrue(err) + #now we copy a HIS to a HIS + err =conop.CopyResidue(tpl.residues[3], new_hdl.residues[3], ed) + self.assertTrue(err) + # copy a GLY to a HIS + err, has_cbeta=conop.CopyNonConserved(tpl.residues[1], new_hdl.residues[4], ed) + self.assertFalse(has_cbeta) + # copy a MET to a GLY + err =conop.CopyResidue(tpl.residues[0], new_hdl.residues[5], ed) + self.assertFalse(err) + # copy a MET to a HIS + err =conop.CopyResidue(tpl.residues[0], new_hdl.residues[6], ed) + self.assertFalse(err) + # copy a GLY to a MET with adding CB + err=conop.CopyResidue(tpl.residues[1], new_hdl.residues[7], ed) + self.assertFalse(err) + + residues=new_hdl.residues + self.assertEqual(len(residues), 8) + # MET to MET + self.assertTrue(residues[0].FindAtom("CB").IsValid()) + #GLY to GLY + self.assertFalse(residues[1].FindAtom("CB").IsValid()) + #now we copy a GLY to a GLY + self.assertFalse(residues[2].FindAtom("CB").IsValid()) + #now we copy a HIS to a HIS + self.assertTrue(residues[3].FindAtom("CB").IsValid()) + #now we copy a GLY to a HIS without adding CB + self.assertFalse(residues[4].FindAtom("CB").IsValid()) + #now we copy a MET to a GLY + self.assertFalse(residues[5].FindAtom("CB").IsValid()) + # copy a MET to a HIS + self.assertTrue(residues[6].FindAtom("CB").IsValid()) + # copy a GLY to a MET with adding CB + self.assertTrue(residues[7].FindAtom("CB").IsValid()) + + +if __name__ == "__main__": + suite = unittest.TestLoader().loadTestsFromTestCase(TestNonStandard) + unittest.TextTestRunner().run(suite) + + diff --git a/modules/conop/tests/testfiles/cbeta.pdb b/modules/conop/tests/testfiles/cbeta.pdb new file mode 100644 index 0000000000000000000000000000000000000000..fcb59f778ba67b568a83c99605d14f3c8cdc96a4 --- /dev/null +++ b/modules/conop/tests/testfiles/cbeta.pdb @@ -0,0 +1,27 @@ +ATOM 1 N MET A 55 -11.301 11.863 12.812 1.00 46.35 N +ATOM 2 CA MET A 55 -10.174 12.241 13.713 1.00 45.84 C +ATOM 3 C MET A 55 -9.595 11.051 14.465 1.00 44.35 C +ATOM 4 O MET A 55 -10.219 9.989 14.526 1.00 46.54 O +ATOM 5 CB MET A 55 -10.591 13.367 14.670 1.00 48.03 C +ATOM 6 CG MET A 55 -11.911 13.150 15.404 1.00 49.20 C +ATOM 7 SD MET A 55 -12.173 14.422 16.660 1.00 55.85 S +ATOM 8 CE MET A 55 -10.955 13.907 17.875 1.00 52.51 C +ATOM 9 N GLY A 56 -8.383 11.240 14.995 1.00 42.02 N +ATOM 10 CA GLY A 56 -7.611 10.243 15.755 1.00 39.04 C +ATOM 11 C GLY A 56 -7.093 9.042 14.960 1.00 35.73 C +ATOM 12 O GLY A 56 -7.875 8.322 14.336 1.00 35.25 O +ATOM 18 N GLY A 57 -5.757 8.838 14.934 1.00 32.59 N +ATOM 19 CA GLY A 57 -5.167 7.704 14.210 1.00 30.22 C +ATOM 20 C GLY A 57 -5.475 6.389 14.924 1.00 28.03 C +ATOM 21 O GLY A 57 -5.774 6.389 16.125 1.00 25.91 O +ATOM 25 N HIS A 58 -5.434 5.288 14.176 1.00 26.73 N +ATOM 26 CA HIS A 58 -5.705 3.960 14.726 1.00 26.95 C +ATOM 27 C HIS A 58 -4.622 3.524 15.706 1.00 27.12 C +ATOM 28 O HIS A 58 -3.426 3.545 15.366 1.00 27.18 O +ATOM 29 CB HIS A 58 -5.849 2.928 13.607 1.00 26.98 C +ATOM 30 CG HIS A 58 -7.149 3.014 12.872 1.00 27.32 C +ATOM 31 ND1 HIS A 58 -8.359 3.179 13.510 1.00 28.47 N +ATOM 32 CD2 HIS A 58 -7.428 2.948 11.552 1.00 26.86 C +ATOM 33 CE1 HIS A 58 -9.327 3.211 12.613 1.00 28.81 C +ATOM 34 NE2 HIS A 58 -8.789 3.073 11.416 1.00 28.59 N +END diff --git a/modules/conop/tests/testfiles/sep.pdb b/modules/conop/tests/testfiles/sep.pdb new file mode 100644 index 0000000000000000000000000000000000000000..f381b42b76b5bac59fc77925b742811410a8f157 --- /dev/null +++ b/modules/conop/tests/testfiles/sep.pdb @@ -0,0 +1,10 @@ +HETATM 2554 N SEP A 338 22.112 31.452 4.376 1.00 36.83 N +HETATM 2555 CA SEP A 338 21.303 32.489 4.986 1.00 35.62 C +HETATM 2556 CB SEP A 338 20.220 31.868 5.843 1.00 36.98 C +HETATM 2557 OG SEP A 338 19.529 32.909 6.526 1.00 38.75 O +HETATM 2558 C SEP A 338 22.121 33.517 5.710 1.00 36.32 C +HETATM 2559 O SEP A 338 23.245 32.996 6.389 1.00 28.28 O +HETATM 2560 P SEP A 338 18.280 33.605 5.779 1.00 36.73 P +HETATM 2561 O1P SEP A 338 17.256 33.885 6.849 1.00 38.47 O +HETATM 2562 O2P SEP A 338 17.811 32.606 4.750 1.00 39.29 O +HETATM 2563 O3P SEP A 338 18.956 34.824 5.189 1.00 32.24 O \ No newline at end of file