diff --git a/modules/base/pymod/table.py b/modules/base/pymod/table.py
index 87a425ebcf9e61852e8709ca26ab6bee526b0ce7..8258ad31685fa817326a89bf0243e9fef3b22b58 100644
--- a/modules/base/pymod/table.py
+++ b/modules/base/pymod/table.py
@@ -926,7 +926,10 @@ class Table:
vals1.append(v1)
vals2.append(v2)
try:
- return scipy.stats.mstats.spearmanr(vals1, vals2)[0]
+ correl = scipy.stats.mstats.spearmanr(vals1, vals2)[0]
+ if scipy.isnan(correl):
+ return None
+ return correl
except:
return None
@@ -1252,6 +1255,11 @@ class Table:
fp += 1
x.append(fp)
y.append(tp)
+
+ # if no false positives or false negatives values are found return None
+ if x[-1]==0 or y[-1]==0:
+ return None
+
x = [float(v)/x[-1] for v in x]
y = [float(v)/y[-1] for v in y]
return x,y
@@ -1265,10 +1273,12 @@ class Table:
try:
import numpy as np
- rocx, rocy = self.ComputeROC(score_col, class_col, score_dir,
- class_dir, class_cutoff)
+ roc = self.ComputeROC(score_col, class_col, score_dir,
+ class_dir, class_cutoff)
- return np.trapz(rocy, rocx)
+ if not roc:
+ return None
+ return np.trapz(roc[1], roc[0])
except ImportError:
LogError("Function needs numpy, but I could not import it.")
raise
@@ -1284,8 +1294,13 @@ class Table:
try:
import matplotlib.pyplot as plt
- enrx, enry = self.ComputeROC(score_col, class_col, score_dir,
+ roc = self.ComputeROC(score_col, class_col, score_dir,
class_dir, class_cutoff)
+
+ if not roc:
+ return None
+
+ enrx, enry = roc
if not title:
title = 'ROC of %s'%score_col
diff --git a/modules/base/src/string_ref.hh b/modules/base/src/string_ref.hh
index 48ab841055192522f2068cc91a4df79c97ac20c1..802dd594069257ba17213a02d73144018e635b32 100644
--- a/modules/base/src/string_ref.hh
+++ b/modules/base/src/string_ref.hh
@@ -28,7 +28,6 @@
#include <ost/base.hh>
#include <string.h>
#include <vector>
-#include <ost/message.hh>
#include <ost/module_config.hh>
@@ -60,8 +59,9 @@ public:
assert(!this->empty());
return *begin_;
}
- /// \brief find character in StringRef
- /// \return iterator position when found, else iterator pointing to the end
+
+ /// \brief find character in StringRef
+ /// \return iterator position when found, else iterator pointing to the end
const_iterator find(char p) const {
const char* s=begin_;
while (s!=end_) {
@@ -72,7 +72,7 @@ public:
}
return s;
}
-
+
/// \brief returns a substring of the string
///
/// \param pos the starting position of the substring
diff --git a/modules/base/tests/test_table.py b/modules/base/tests/test_table.py
index 4220de12fd65d5caa7d83b7d8a9973916dee24b4..e2a3060c62ae341f9f822a6d76403bd29e0cf8e5 100644
--- a/modules/base/tests/test_table.py
+++ b/modules/base/tests/test_table.py
@@ -985,7 +985,15 @@ class TestTable(unittest.TestCase):
img1 = Image.open(os.path.join("testfiles","roc-out.png"))
img2 = Image.open(os.path.join("testfiles","roc.png"))
self.CompareImages(img1, img2)
- #pl.show()
+
+ # no true positives
+ tab = Table(['classific', 'score'], 'bf',
+ classific=[False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False],
+ score=[0.9, 0.8, 0.7, 0.6, 0.55, 0.54, 0.53, 0.52, 0.51, 0.505, 0.4, 0.39, 0.38, 0.37, 0.36, 0.35, 0.34, 0.33, 0.30, 0.1])
+ pl = tab.PlotROC(score_col='score', score_dir='+',
+ class_col='classific',
+ save=os.path.join("testfiles","roc-out.png"))
+ self.assertEquals(pl, None)
def testPlotROCSameValues(self):
if not HAS_MPL or not HAS_PIL:
@@ -1011,7 +1019,14 @@ class TestTable(unittest.TestCase):
auc = tab.ComputeROCAUC(score_col='score', score_dir='+', class_col='classific')
self.assertAlmostEquals(auc, auc_ref)
- def testCalcROC(self):
+ # no true positives
+ tab = Table(['classific', 'score'], 'bf',
+ classific=[False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False],
+ score=[0.9, 0.8, 0.7, 0.6, 0.55, 0.54, 0.53, 0.52, 0.51, 0.505, 0.4, 0.39, 0.38, 0.37, 0.36, 0.35, 0.34, 0.33, 0.30, 0.1])
+ auc = tab.ComputeROCAUC(score_col='score', score_dir='+', class_col='classific')
+ self.assertEquals(auc, None)
+
+ def testCalcROCAUCWithCutoff(self):
if not HAS_NUMPY:
return
tab = Table(['classific', 'score'], 'ff',
@@ -1020,6 +1035,10 @@ class TestTable(unittest.TestCase):
auc = tab.ComputeROCAUC(score_col='score', class_col='classific', class_cutoff=0.5)
self.assertEquals(auc, 1.0)
+ # no true positives
+ auc = tab.ComputeROCAUC(score_col='score', class_col='classific', class_cutoff=1.0)
+ self.assertEquals(auc, None)
+
def testCalcROCFromFile(self):
tab = Table.Load(os.path.join('testfiles','roc_table.dat'))
auc = tab.ComputeROCAUC(score_col='prediction', class_col='reference', class_cutoff=0.4)
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..57de3864e87575ffde1c7bdd705b5549f488fa31
--- /dev/null
+++ b/modules/conop/tests/test_nonstandard.py
@@ -0,0 +1,127 @@
+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__":
+ builder=conop.GetBuilder()
+ if not hasattr(builder, 'compound_lib'):
+ print 'default builder does not use compound library. ignoring unit tests'
+ else:
+ 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
diff --git a/modules/img/alg/tests/test_stat.cc b/modules/img/alg/tests/test_stat.cc
index 9c9694a4caace6c7b79c14fd9d2fc2c9a1b57778..b736c6bd93d30aebbcc2eb05616e70c4d0d19f7e 100644
--- a/modules/img/alg/tests/test_stat.cc
+++ b/modules/img/alg/tests/test_stat.cc
@@ -52,7 +52,7 @@ void test() {
im.Apply(stat);
BOOST_CHECK_CLOSE(stat.GetMean(),Real(5.0),Real(0.0001));
BOOST_CHECK_CLOSE(stat.GetStandardDeviation(),Real(2.58198889747),Real(0.0001));
- BOOST_CHECK_CLOSE(stat.GetSkewness()+0.5,Real(0.5),Real(0.0001));
+ BOOST_CHECK_CLOSE(stat.GetSkewness()+Real(0.5),Real(0.5),Real(0.0001));
BOOST_CHECK_CLOSE(stat.GetKurtosis(),Real(1.77),Real(0.0001));
// check for rounding errors
@@ -60,7 +60,7 @@ void test() {
im.Apply(stat);
BOOST_CHECK_CLOSE(stat.GetMean(),Real(10005.0),Real(0.0001));
BOOST_CHECK_CLOSE(stat.GetStandardDeviation(),Real(2.58198889747),Real(0.01));
- BOOST_CHECK_CLOSE(stat.GetSkewness()+0.5,Real(0.5),Real(0.01));
+ BOOST_CHECK_CLOSE(stat.GetSkewness()+Real(0.5),Real(0.5),Real(0.01));
BOOST_CHECK_CLOSE(stat.GetKurtosis(),Real(1.77),Real(0.01));
@@ -72,7 +72,7 @@ void test() {
}
BOOST_CHECK_CLOSE(acc.GetMean(),Real(5.0),Real(0.0001));
BOOST_CHECK_CLOSE(acc.GetStandardDeviation(),Real(2.58198889747),Real(0.0001));
- BOOST_CHECK_CLOSE(acc.GetSkewness()+0.5,Real(0.5),Real(0.0001));
+ BOOST_CHECK_CLOSE(acc.GetSkewness()+Real(0.5),Real(0.5),Real(0.0001));
BOOST_CHECK_CLOSE(acc.GetKurtosis(),Real(1.77),Real(0.0001));
StatAccumulator<> acc1,acc2,acc3;
@@ -84,7 +84,7 @@ void test() {
StatAccumulator<> acc_c=acc1+acc2+acc3;
BOOST_CHECK_CLOSE(acc_c.GetMean(),Real(5.0),Real(0.0001));
BOOST_CHECK_CLOSE(acc_c.GetStandardDeviation(),Real(2.58198889747),Real(0.0001));
- BOOST_CHECK_CLOSE(acc_c.GetSkewness()+0.5,Real(0.5),Real(0.0001));
+ BOOST_CHECK_CLOSE(acc_c.GetSkewness()+Real(0.5),Real(0.5),Real(0.0001));
BOOST_CHECK_CLOSE(acc_c.GetKurtosis(),Real(1.77),Real(0.0001));
}
diff --git a/modules/io/pymod/wrap_io.cc b/modules/io/pymod/wrap_io.cc
index 1d9e3b93613dfb9ef2bb8d5d91e44ba8f460c533..53ba11f7c85173c3ebc56c14002db8443e5c229f 100644
--- a/modules/io/pymod/wrap_io.cc
+++ b/modules/io/pymod/wrap_io.cc
@@ -113,7 +113,6 @@ BOOST_PYTHON_MODULE(_ost_io)
def("LoadCRD", &LoadCRD);
def("LoadCHARMMTraj_", &LoadCHARMMTraj, (arg("ent"), arg("trj_filename"),
arg("stride")=1, arg("lazy_load")=false));
- def("SaveCHARMMTraj",SaveCHARMMTraj,save_charmm_trj_ov());
def("LoadMAE", &LoadMAE);
@@ -122,4 +121,7 @@ BOOST_PYTHON_MODULE(_ost_io)
#if OST_IMG_ENABLED
export_map_io();
#endif
+ def("SaveCHARMMTraj", &SaveCHARMMTraj,
+ (arg("traj"), arg("pdb_filename"), arg("dcd_filename"), arg("stride")=1,
+ arg("profile")=IOProfile()));
}
diff --git a/modules/io/src/mol/pdb_reader.cc b/modules/io/src/mol/pdb_reader.cc
index 7178667b3bc57cf337defa972c4371d830ce3b19..3d7bd37563205c8f4428791717fe068536241490 100644
--- a/modules/io/src/mol/pdb_reader.cc
+++ b/modules/io/src/mol/pdb_reader.cc
@@ -102,6 +102,9 @@ void PDBReader::Init(const boost::filesystem::path& loc)
hard_end_=false;
skip_next_=false;
data_continues_=false;
+ old_key_="";
+ mol_id_=std::make_pair(false, 0);
+
}
void PDBReader::ThrowFaultTolerant(const String& msg) {
@@ -114,7 +117,7 @@ void PDBReader::ThrowFaultTolerant(const String& msg) {
void PDBReader::ParseCompndEntry (const StringRef& line, int line_num)
{
- if (line.size()<20) {
+ if (line.size()<12) {
if (profile_.fault_tolerant) {
LOG_WARNING("invalid COMPND record on line " << line_num
<< ": record is too short");
@@ -147,11 +150,22 @@ void PDBReader::ParseCompndEntry (const StringRef& line, int line_num)
}
if((entry.find(':')!=entry.end())){
std::vector<StringRef> fields=entry.split(':');
- key=fields[0].trim();
- old_key_=key.str();
- data=fields[1].trim();
+ key=fields[0].trim();
+ old_key_=key.str();
+ if (fields.size()>1) {
+ data=fields[1].trim();
+ }
+
if(data.size()<1){
+ if (!(key.str()=="MOL_ID")&&!(key.str()=="CHAIN")){
+ LOG_WARNING("skipping unsupported COMPND record on line " << line_num<< ": record value"<< key.str()<<" too small");
+ if (data_continues_) {
+ skip_next_=true;
+ } else {
+ return;
+ }
+ }
ThrowFaultTolerant(str(format("invalid COMPND record on line %d, record after ':' too small")%line_num));
}
data_continues_=true;
@@ -179,7 +193,7 @@ void PDBReader::ParseCompndEntry (const StringRef& line, int line_num)
}
//currently only these are parsed
if (!(key.str()=="MOL_ID")&&!(key.str()=="CHAIN")){
- LOG_TRACE("reading COMPND record on line " << line_num<< "is not supported");
+ LOG_INFO("reading COMPND record on line " << line_num<< "is not supported");
if (data_continues_) {
skip_next_=true;
} else {
@@ -464,15 +478,18 @@ void PDBReader::AssignMolIds(mol::EntityHandle ent) {
for (std::vector<String>::const_iterator chain_iterator = compnd_iterator->chains.begin();
chain_iterator!= compnd_iterator->chains.end();
++chain_iterator) {
+ //~ std::cout << "chain: "<<*chain_iterator <<":: "<<std::endl;
if (restrict_chains_.size()==0 ||
(restrict_chains_.find(*chain_iterator)!=String::npos)) {
mol::ChainHandle chain=ent.FindChain(*chain_iterator);
if (chain) {
chain.SetIntProp("mol_id", compnd_iterator->mol_id);
}else{
+ std::cout << "failed to assign MOL_ID to chain: "<<*chain_iterator <<std::endl;
+
std::stringstream ss;
- ss << "could not map COMPND record MOL_ID onto chain "
- <<*chain_iterator;
+ ss << "could not map COMPND record MOL_ID onto chain";
+ ss <<*chain_iterator;
ThrowFaultTolerant(ss.str());
}
}
@@ -482,9 +499,13 @@ void PDBReader::AssignMolIds(mol::EntityHandle ent) {
mol::ChainHandleList ch_list=ent.GetChainList();
for (mol::ChainHandleList::const_iterator chain=ch_list.begin();
chain!=ch_list.end(); ++chain) {
+ //~ skip HETATM only chains!!
if(chain->IsValid()){
if (!chain->HasProp("mol_id")) {
- ThrowFaultTolerant("found chain without MOL_ID");
+ std::stringstream ss;
+ ss << "found chain without MOL_ID: ";
+ ss << chain->GetName();
+ LOG_WARNING(ss.str());
}
}
}
diff --git a/modules/io/tests/test_io_pdb.cc b/modules/io/tests/test_io_pdb.cc
index 0056bd194eb54d6624482acfdb2eca1e1605c68e..5bbfbf699a9684f0eee761fbe04f42698f77daa2 100644
--- a/modules/io/tests/test_io_pdb.cc
+++ b/modules/io/tests/test_io_pdb.cc
@@ -139,7 +139,45 @@ BOOST_AUTO_TEST_CASE(test_parse_compnd_record5)
PDBReader reader(fname, IOProfile());
mol::EntityHandle ent=mol::CreateEntity();
+ BOOST_CHECK_NO_THROW(reader.Import(ent));
+
+ mol::ChainHandle ch = ent.FindChain("A");
+ BOOST_CHECK(ch.HasProp("mol_id")==true);
+ BOOST_CHECK(ch.GetIntProp("mol_id")==1);
+
+ ch = ent.FindChain("B");
+ BOOST_CHECK(ch.HasProp("mol_id")==false);
+}
+
+//chain I in MOL_ID record but no chain I
+BOOST_AUTO_TEST_CASE(test_parse_compnd_record6)
+{
+ String fname("testfiles/pdb/1oax.pdb");
+ PDBReader reader(fname, IOProfile());
+ mol::EntityHandle ent=mol::CreateEntity();
+
BOOST_CHECK_THROW(reader.Import(ent), IOException);
+
+}
+
+// has an empy MOLECULE record (unsupported ATM anyway, but crashed ost)
+BOOST_AUTO_TEST_CASE(test_parse_compnd_record7)
+{
+ String fname("testfiles/pdb/2p6a.pdb");
+ PDBReader reader(fname, IOProfile());
+ mol::EntityHandle ent=mol::CreateEntity();
+
+ reader.Import(ent);
+ mol::ChainHandle ch = ent.FindChain("A");
+ BOOST_CHECK(ch.HasProp("mol_id")==true);
+ BOOST_CHECK(ch.GetIntProp("mol_id")==1);
+ ch = ent.FindChain("D");
+ BOOST_CHECK(ch.HasProp("mol_id")==true);
+ BOOST_CHECK(ch.GetIntProp("mol_id")==2);
+
+ ch = ent.FindChain("E");
+ BOOST_CHECK(ch.HasProp("mol_id")==true);
+ BOOST_CHECK(ch.GetIntProp("mol_id")==3);
}
diff --git a/modules/io/tests/testfiles/pdb/1oax.pdb b/modules/io/tests/testfiles/pdb/1oax.pdb
new file mode 100644
index 0000000000000000000000000000000000000000..8a61950e8a0970d2b719b35c65465907ff0b6f3d
--- /dev/null
+++ b/modules/io/tests/testfiles/pdb/1oax.pdb
@@ -0,0 +1,24 @@
+
+COMPND MOL_ID: 1;
+COMPND 2 MOLECULE: IMMUNOGLOBULIN E;
+COMPND 3 CHAIN: H, I, J, K;
+COMPND 4 FRAGMENT: FV REGION, RESIDUES 1-122;
+COMPND 5 ENGINEERED: YES;
+COMPND 6 MOL_ID: 2;
+COMPND 7 MOLECULE: IMMUNOGLOBULIN E;
+COMPND 8 CHAIN: L, M, N, O;
+COMPND 9 FRAGMENT: FV REGION, RESIDUES 1-110;
+COMPND 10 ENGINEERED: YES
+
+ATOM 961 CB ALA H 122 24.405 78.113 110.762 1.00 46.85 C
+TER 962 ALA H 122
+ATOM 1923 CB ALA J 122 -18.810 34.607 14.909 1.00 46.23 C
+TER 1924 ALA J 122
+ATOM 2722 CD2 LEU L 109 61.832 51.079 106.030 1.00 43.23 C
+TER 2723 LEU L 109
+ATOM 3521 CD2 LEU M 109 2.184 -0.589 68.108 1.00 43.23 C
+TER 3522 LEU M 109
+ATOM 4320 CD2 LEU N 109 7.889 -2.865 19.656 1.00 43.22 C
+TER 4321 LEU N 109
+ATOM 5113 CD2 LEU O 109 59.692 56.678 57.399 1.00 43.23 C
+TER 5114 LEU O 109
diff --git a/modules/io/tests/testfiles/pdb/2p6a.pdb b/modules/io/tests/testfiles/pdb/2p6a.pdb
new file mode 100644
index 0000000000000000000000000000000000000000..19935ba86c1e7b632bd02a2c50ac89a726f0e9cb
--- /dev/null
+++ b/modules/io/tests/testfiles/pdb/2p6a.pdb
@@ -0,0 +1,25 @@
+COMPND MOL_ID: 1;
+COMPND 2 MOLECULE: INHIBIN BETA A CHAIN;
+COMPND 3 CHAIN: A, B;
+COMPND 4 SYNONYM: ACTIVIN BETA-A CHAIN, ERYTHROID DIFFERENTIATION
+COMPND 5 PROTEIN, EDF;
+COMPND 6 ENGINEERED: YES;
+COMPND 7 MOL_ID: 2;
+COMPND 8 MOLECULE: FOLLISTATIN;
+COMPND 9 CHAIN: D, C;
+COMPND 10 SYNONYM: FS, ACTIVIN-BINDING PROTEIN;
+COMPND 11 ENGINEERED: YES;
+COMPND 12 MOL_ID: 3;
+COMPND 13 MOLECULE:;
+COMPND 14 CHAIN: E;
+COMPND 15 ENGINEERED: YES
+ATOM 882 OXT SER A 116 15.399 37.353 44.611 1.00 73.37 O
+TER 883 SER A 116
+ATOM 3870 OXT SER B 116 13.780 40.357 30.274 1.00 27.95 O
+TER 3871 SER B 116
+ATOM 2987 OE2 GLU D 299 33.348 36.499 4.332 1.00 81.88 O
+TER 2988 GLU D 299
+ATOM 5905 CB ILE C 290 46.026 -9.354 55.435 1.00233.79 C
+TER 5906 ILE C 290
+ATOM 5956 CB ALA E 10 30.651 13.129 53.296 1.00191.07 C
+TER 5957 ALA E 10
diff --git a/modules/mol/base/tests/test_ics.cc b/modules/mol/base/tests/test_ics.cc
index 0b19877c8a95b28e1230692c1a35a64cf7a0d8d6..4f84f6a78bf0882302f9d5edce87ed13656b6064 100644
--- a/modules/mol/base/tests/test_ics.cc
+++ b/modules/mol/base/tests/test_ics.cc
@@ -107,7 +107,7 @@ BOOST_AUTO_TEST_CASE(ics_update_icsbondlength)
{
TorsionStructure s;
mol::BondHandle bond = s.a2.FindBondToAtom(s.a3);
- BOOST_CHECK_CLOSE(bond.GetLength(), 1.0, EPSILON);
+ BOOST_CHECK_CLOSE(bond.GetLength(), Real(1.0), Real(EPSILON));
}
BOOST_AUTO_TEST_CASE(ics_settorsion_unbuffered)
@@ -115,20 +115,20 @@ BOOST_AUTO_TEST_CASE(ics_settorsion_unbuffered)
Real eps = 0.0001;
TorsionStructure s;
ICSEditor e = s.e.EditICS(mol::UNBUFFERED_EDIT);
- BOOST_CHECK_CLOSE(s.t1.GetAngle(), M_PI, eps);
+ BOOST_CHECK_CLOSE(s.t1.GetAngle(), Real(M_PI), Real(eps));
BOOST_CHECK_SMALL(s.t2.GetAngle(), eps);
e.SetTorsionAngle(s.t1,0);
BOOST_CHECK_SMALL(s.t1.GetAngle(), eps);
- BOOST_CHECK_CLOSE(s.t2.GetAngle(), M_PI, eps);
+ BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(M_PI), Real(eps));
e.SetTorsionAngle(s.t2,M_PI/4);
- BOOST_CHECK_CLOSE(s.t2.GetAngle(), M_PI/4, eps);
- BOOST_CHECK_CLOSE(s.t1.GetAngle(), -M_PI+M_PI/4, eps);
+ BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(M_PI/4), Real(eps));
+ BOOST_CHECK_CLOSE(s.t1.GetAngle(), Real(-M_PI+M_PI/4), Real(eps));
e.SetTorsionAngle(s.t1,-M_PI/4);
- BOOST_CHECK_CLOSE(s.t1.GetAngle(), -M_PI/4, eps);
- BOOST_CHECK_CLOSE(s.t2.GetAngle(), 3/4.*M_PI, eps);
+ BOOST_CHECK_CLOSE(s.t1.GetAngle(), Real(-M_PI/4), Real(eps));
+ BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(3/4.*M_PI), Real(eps));
e.RotateTorsionAngle(s.t1, M_PI/4);
BOOST_CHECK_SMALL(s.t1.GetAngle(), eps);
- BOOST_CHECK_CLOSE(std::abs(s.t2.GetAngle()), M_PI, eps);
+ BOOST_CHECK_CLOSE(std::abs(s.t2.GetAngle()), Real(M_PI), Real(eps));
}
BOOST_AUTO_TEST_CASE(ics_settorsion_buffered)
@@ -136,20 +136,20 @@ BOOST_AUTO_TEST_CASE(ics_settorsion_buffered)
Real eps = 0.0001;
TorsionStructure s;
ICSEditor e = s.e.EditICS(mol::BUFFERED_EDIT);
- BOOST_CHECK_CLOSE(s.t1.GetAngle(), M_PI, eps);
+ BOOST_CHECK_CLOSE(s.t1.GetAngle(), Real(M_PI), Real(eps));
BOOST_CHECK_SMALL(s.t2.GetAngle(), eps);
e.SetTorsionAngle(s.t1,0);
BOOST_CHECK_SMALL(s.t1.GetAngle(), eps);
- BOOST_CHECK_CLOSE(s.t2.GetAngle(), M_PI, eps);
+ BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(M_PI), Real(eps));
e.SetTorsionAngle(s.t2,M_PI/4);
- BOOST_CHECK_CLOSE(s.t2.GetAngle(), M_PI/4, eps);
- BOOST_CHECK_CLOSE(s.t1.GetAngle(), -M_PI+M_PI/4, eps);
+ BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(M_PI/4), Real(eps));
+ BOOST_CHECK_CLOSE(s.t1.GetAngle(), Real(-M_PI+M_PI/4), Real(eps));
e.SetTorsionAngle(s.t1,-M_PI/4);
- BOOST_CHECK_CLOSE(s.t1.GetAngle(), -M_PI/4, eps);
- BOOST_CHECK_CLOSE(s.t2.GetAngle(), 3/4.*M_PI, eps);
+ BOOST_CHECK_CLOSE(s.t1.GetAngle(), Real(-M_PI/4), Real(eps));
+ BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(3/4.*M_PI), Real(eps));
e.RotateTorsionAngle(s.t1, M_PI/4);
BOOST_CHECK_SMALL(s.t1.GetAngle(), eps);
- BOOST_CHECK_CLOSE(std::abs(s.t2.GetAngle()), M_PI, eps);
+ BOOST_CHECK_CLOSE(std::abs(s.t2.GetAngle()), Real(M_PI), Real(eps));
}
BOOST_AUTO_TEST_CASE(ics_settorsion_unbuffered_update_others)
@@ -157,20 +157,20 @@ BOOST_AUTO_TEST_CASE(ics_settorsion_unbuffered_update_others)
Real eps = 0.0001;
TorsionStructure s;
ICSEditor e = s.e.EditICS(mol::UNBUFFERED_EDIT);
- BOOST_CHECK_CLOSE(s.t1.GetAngle(), M_PI, eps);
+ BOOST_CHECK_CLOSE(s.t1.GetAngle(), Real(M_PI), Real(eps));
BOOST_CHECK_SMALL(s.t2.GetAngle(), eps);
e.SetTorsionAngle(s.t1,0,false);
BOOST_CHECK_SMALL(s.t1.GetAngle(), eps);
BOOST_CHECK_SMALL(s.t2.GetAngle(), eps);
e.SetTorsionAngle(s.t2,M_PI/4,false);
- BOOST_CHECK_CLOSE(s.t2.GetAngle(), M_PI/4, eps);
+ BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(M_PI/4), Real(eps));
BOOST_CHECK_SMALL(s.t1.GetAngle(), eps);
e.SetTorsionAngle(s.t1,-M_PI/4,false);
- BOOST_CHECK_CLOSE(s.t1.GetAngle(), -M_PI/4, eps);
- BOOST_CHECK_CLOSE(s.t2.GetAngle(), M_PI/4, eps);
+ BOOST_CHECK_CLOSE(s.t1.GetAngle(), Real(-M_PI/4), Real(eps));
+ BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(M_PI/4), Real(eps));
e.RotateTorsionAngle(s.t1, M_PI/4,false);
BOOST_CHECK_SMALL(s.t1.GetAngle(), eps);
- BOOST_CHECK_CLOSE(s.t2.GetAngle(), M_PI/4, eps);
+ BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(M_PI/4), Real(eps));
}
BOOST_AUTO_TEST_CASE(ics_settorsion_buffered_update_others)
@@ -178,20 +178,20 @@ BOOST_AUTO_TEST_CASE(ics_settorsion_buffered_update_others)
Real eps = 0.0001;
TorsionStructure s;
ICSEditor e = s.e.EditICS(mol::BUFFERED_EDIT);
- BOOST_CHECK_CLOSE(s.t1.GetAngle(), M_PI, eps);
+ BOOST_CHECK_CLOSE(s.t1.GetAngle(), Real(M_PI), Real(eps));
BOOST_CHECK_SMALL(s.t2.GetAngle(), eps);
e.SetTorsionAngle(s.t1,0,false);
BOOST_CHECK_SMALL(s.t1.GetAngle(), eps);
BOOST_CHECK_SMALL(s.t2.GetAngle(), eps);
e.SetTorsionAngle(s.t2,M_PI/4,false);
- BOOST_CHECK_CLOSE(s.t2.GetAngle(), M_PI/4, eps);
+ BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(M_PI/4), Real(eps));
BOOST_CHECK_SMALL(s.t1.GetAngle(), eps);
e.SetTorsionAngle(s.t1,-M_PI/4,false);
- BOOST_CHECK_CLOSE(s.t1.GetAngle(), -M_PI/4, eps);
- BOOST_CHECK_CLOSE(s.t2.GetAngle(), M_PI/4, eps);
+ BOOST_CHECK_CLOSE(s.t1.GetAngle(), Real(-M_PI/4), Real(eps));
+ BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(M_PI/4), Real(eps));
e.RotateTorsionAngle(s.t1, M_PI/4,false);
BOOST_CHECK_SMALL(s.t1.GetAngle(), eps);
- BOOST_CHECK_CLOSE(s.t2.GetAngle(), M_PI/4, eps);
+ BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(M_PI/4), Real(eps));
}
BOOST_AUTO_TEST_CASE(ics_settorsion_linear_unbuffered)
@@ -207,13 +207,13 @@ BOOST_AUTO_TEST_CASE(ics_settorsion_linear_unbuffered)
BOOST_CHECK_SMALL(s.t2.GetAngle(), eps);
e.SetTorsionAngle(s.t2,M_PI/4);
BOOST_CHECK_SMALL(s.t1.GetAngle(), eps);
- BOOST_CHECK_CLOSE(s.t2.GetAngle(), M_PI/4, eps);
+ BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(M_PI/4), Real(eps));
e.SetTorsionAngle(s.t1,-M_PI/4);
BOOST_CHECK_SMALL(s.t1.GetAngle(), eps);
BOOST_CHECK_SMALL(s.t2.GetAngle(), eps);
e.RotateTorsionAngle(s.t1, M_PI/4);
BOOST_CHECK_SMALL(s.t1.GetAngle(), eps);
- BOOST_CHECK_CLOSE(s.t2.GetAngle(), M_PI/4, eps);
+ BOOST_CHECK_CLOSE(s.t2.GetAngle(), Real(M_PI/4), Real(eps));
}
BOOST_AUTO_TEST_CASE(ics_angle_trivia)