From d756490f7d762ee2872347d16ad1afecb9b72874 Mon Sep 17 00:00:00 2001 From: Paolo Tosco Date: Thu, 7 Sep 2017 14:45:45 +0100 Subject: [PATCH 01/44] - Fixes failing build with MSVC (#1547) --- Code/GraphMol/RGroupDecomposition/Wrap/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/GraphMol/RGroupDecomposition/Wrap/CMakeLists.txt b/Code/GraphMol/RGroupDecomposition/Wrap/CMakeLists.txt index 8700b8058..32d54d979 100644 --- a/Code/GraphMol/RGroupDecomposition/Wrap/CMakeLists.txt +++ b/Code/GraphMol/RGroupDecomposition/Wrap/CMakeLists.txt @@ -3,7 +3,7 @@ rdkit_python_extension(rdRGroupDecomposition DEST Chem LINK_LIBRARIES RGroupDecomposition FMCS ChemTransforms SubstructMatch SmilesParse GraphMol - RDGeometryLib RDBoost + RDGeneral RDGeometryLib RDBoost ${RDKit_THREAD_LIBS}) From 3d75f5c78f68de69196708adcc07d7a875b8714a Mon Sep 17 00:00:00 2001 From: Brian Kelley Date: Thu, 7 Sep 2017 14:43:08 -0400 Subject: [PATCH 02/44] =?UTF-8?q?Fixes=20blanking=20of=20non-query=20atom?= =?UTF-8?q?=20data=20when=20QueryAtomData=20was=20being=20pi=E2=80=A6=20(#?= =?UTF-8?q?1541)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fixes blanking of non-query atom data when QueryAtomData was being pickled * Adds old version pickle test for properties * Makes pickle py2 and py3 compatible --- Code/GraphMol/MolPickler.cpp | 24 ------- Code/GraphMol/MolPickler.h | 14 ++-- Code/GraphMol/Wrap/rough_test.py | 55 +++++++++++++++ Code/RDGeneral/StreamOps.h | 111 ++++++++++++++++++++++++++----- 4 files changed, 156 insertions(+), 48 deletions(-) diff --git a/Code/GraphMol/MolPickler.cpp b/Code/GraphMol/MolPickler.cpp index b556df250..05e33f574 100644 --- a/Code/GraphMol/MolPickler.cpp +++ b/Code/GraphMol/MolPickler.cpp @@ -881,15 +881,6 @@ void MolPickler::_pickle(const ROMol *mol, std::ostream &ss, streamWrite(ss, ENDPROPS); } - if (propertyFlags & PicklerOps::QueryAtomData) { - streamWrite(ss, BEGINQUERYATOMDATA); - for (ROMol::ConstAtomIterator atIt = mol->beginAtoms(); - atIt != mol->endAtoms(); ++atIt) { - _pickleQueryAtomData(ss, *atIt); - } - streamWrite(ss, ENDPROPS); - } - streamWrite(ss, ENDMOL); } @@ -1182,21 +1173,6 @@ void MolPickler::_unpickleAtomData(std::istream &ss, Atom *atom, int version) { } } -void MolPickler::_pickleQueryAtomData(std::ostream &ss, const Atom *atom) { - if (atom->hasQuery()) { - std::stringstream tss(std::ios_base::binary | std::ios_base::out | - std::ios_base::in); - - int32_t propFlags = _pickleAtomData(tss, atom); - streamWrite(ss, propFlags); - ss.write(tss.str().c_str(), tss.str().size()); - } else { - // not a query so do nothing - int32_t propFlags = 0; - streamWrite(ss, propFlags); - } -} - // T refers to the type of the atom indices written template void MolPickler::_pickleAtom(std::ostream &ss, const Atom *atom) { diff --git a/Code/GraphMol/MolPickler.h b/Code/GraphMol/MolPickler.h index 56ce60922..f2c6ae541 100644 --- a/Code/GraphMol/MolPickler.h +++ b/Code/GraphMol/MolPickler.h @@ -15,7 +15,7 @@ #include #include #include - +#include // Std stuff #include #include @@ -45,12 +45,12 @@ class MolPicklerException : public std::exception { namespace PicklerOps { typedef enum { NoProps = 0, // no data pickled - MolProps = 0x1, // only public non computed properties - AtomProps = 0x10, - BondProps = 0x100, - QueryAtomData = 0x100, - PrivateProps = 0x10000, - ComputedProps = 0x100000, + MolProps = BOOST_BINARY(1), // only public non computed properties + AtomProps = BOOST_BINARY(10), + BondProps = BOOST_BINARY(100), + QueryAtomData = BOOST_BINARY(10), // n.b. DEPRECATED and set to AtomProps (does the same work) + PrivateProps = BOOST_BINARY(10000), + ComputedProps = BOOST_BINARY(100000), AllProps = 0x7FFFFFFF, // all data pickled (only 31 bit flags in case enum==int) } PropertyPickleOptions; diff --git a/Code/GraphMol/Wrap/rough_test.py b/Code/GraphMol/Wrap/rough_test.py index 5afc0504e..f7d19653c 100644 --- a/Code/GraphMol/Wrap/rough_test.py +++ b/Code/GraphMol/Wrap/rough_test.py @@ -4305,6 +4305,61 @@ M END m = Chem.MolFromSmiles("c1ccccc1C=O") self.assertTrue(m.HasSubstructMatch(pattern)) + def testGithub1320(self): + import pickle + mol = Chem.MolFromSmiles('N[C@@H](C)O') + mol2 = pickle.loads(pickle.dumps(mol)) + self.assertEqual(Chem.MolToSmiles(mol, isomericSmiles=True), + Chem.MolToSmiles(mol2,isomericSmiles=True)) + Chem.SetDefaultPickleProperties(Chem.PropertyPickleOptions.AtomProps | + Chem.PropertyPickleOptions.BondProps | + Chem.PropertyPickleOptions.MolProps | + Chem.PropertyPickleOptions.PrivateProps | + Chem.PropertyPickleOptions.ComputedProps ) + mol3 = pickle.loads(pickle.dumps(mol)) + + for a1, a2 in zip(mol.GetAtoms(), mol3.GetAtoms()): + d1 = a1.GetPropsAsDict() + d2 = a2.GetPropsAsDict() + if "__computedProps" in d1: + c1 = list(d1["__computedProps"]) + c2 = list(d2["__computedProps"]) + del d1["__computedProps"] + del d2["__computedProps"] + self.assertEqual( c1, c2 ) + + assert d1 == d2 + + for a1, a2 in zip(mol.GetBonds(), mol3.GetBonds()): + d1 = a1.GetPropsAsDict() + d2 = a2.GetPropsAsDict() + if "__computedProps" in d1: + c1 = list(d1["__computedProps"]) + c2 = list(d2["__computedProps"]) + del d1["__computedProps"] + del d2["__computedProps"] + self.assertEqual( c1, c2 ) + + assert d1 == d2 + + self.assertEqual(Chem.MolToSmiles(mol, isomericSmiles=True), + Chem.MolToSmiles(mol3,isomericSmiles=True)) + + def testOldPropPickles(self): + data = 'crdkit.Chem.rdchem\nMol\np0\n(S\'\\xef\\xbe\\xad\\xde\\x00\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00)\\x00\\x00\\x00-\\x00\\x00\\x00\\x80\\x01\\x06\\x00`\\x00\\x00\\x00\\x01\\x03\\x07\\x00`\\x00\\x00\\x00\\x02\\x01\\x06 4\\x00\\x00\\x00\\x01\\x01\\x04\\x06\\x00`\\x00\\x00\\x00\\x01\\x03\\x06\\x00(\\x00\\x00\\x00\\x03\\x04\\x08\\x00(\\x00\\x00\\x00\\x03\\x02\\x07\\x00h\\x00\\x00\\x00\\x03\\x02\\x01\\x06 4\\x00\\x00\\x00\\x02\\x01\\x04\\x06\\x00(\\x00\\x00\\x00\\x03\\x04\\x08\\x00(\\x00\\x00\\x00\\x03\\x02\\x07\\x00(\\x00\\x00\\x00\\x03\\x03\\x06\\x00`\\x00\\x00\\x00\\x02\\x02\\x06 4\\x00\\x00\\x00\\x01\\x01\\x04\\x08\\x00(\\x00\\x00\\x00\\x03\\x02\\x06@(\\x00\\x00\\x00\\x03\\x04\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06\\x00`\\x00\\x00\\x00\\x02\\x02\\x06 4\\x00\\x00\\x00\\x01\\x01\\x04\\x06\\x00(\\x00\\x00\\x00\\x03\\x04\\x08\\x00(\\x00\\x00\\x00\\x03\\x02\\x07\\x00h\\x00\\x00\\x00\\x03\\x02\\x01\\x06 4\\x00\\x00\\x00\\x02\\x01\\x04\\x06\\x00`\\x00\\x00\\x00\\x02\\x02\\x06\\x00`\\x00\\x00\\x00\\x02\\x02\\x06\\x00`\\x00\\x00\\x00\\x02\\x02\\x06@(\\x00\\x00\\x00\\x03\\x04\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@(\\x00\\x00\\x00\\x03\\x04\\x06\\x00`\\x00\\x00\\x00\\x03\\x01\\x06\\x00`\\x00\\x00\\x00\\x02\\x02\\x06\\x00`\\x00\\x00\\x00\\x02\\x02\\x06\\x00`\\x00\\x00\\x00\\x02\\x02\\x06\\x00`\\x00\\x00\\x00\\x02\\x02\\x06\\x00`\\x00\\x00\\x00\\x02\\x02\\x0b\\x00\\x01\\x00\\x01\\x02\\x00\\x02\\x03\\x00\\x02\\x04\\x00\\x04\\x05(\\x02\\x04\\x06 \\x06\\x07\\x00\\x07\\x08\\x00\\x08\\t(\\x02\\x08\\n \\n\\x0b\\x00\\x0b\\x0c\\x00\\x0c\\r\\x00\\r\\x0e \\x0e\\x0fh\\x0c\\x0f\\x10h\\x0c\\x10\\x11h\\x0c\\x11\\x12h\\x0c\\x12\\x13h\\x0c\\x0c\\x14\\x00\\x14\\x15\\x00\\x15\\x16\\x00\\x16\\x17(\\x02\\x16\\x18 \\x18\\x19\\x00\\x19\\x1a\\x00\\x1a\\x1b\\x00\\x1b\\x1c\\x00\\x1c\\x1d\\x00\\x1d\\x1eh\\x0c\\x1e\\x1fh\\x0c\\x1f h\\x0c !h\\x0c!"h\\x0c\\x07#\\x00#$\\x00$%\\x00%&\\x00&\\\'\\x00\\\'(\\x00\\x15\\n\\x00"\\x19\\x00(#\\x00\\x13\\x0eh\\x0c"\\x1dh\\x0c\\x14\\x05\\x05\\x0b\\n\\x15\\x14\\x0c\\x06\\x0f\\x10\\x11\\x12\\x13\\x0e\\x06\\x1a\\x1b\\x1c\\x1d"\\x19\\x06\\x1e\\x1f !"\\x1d\\x06$%&\\\'(#\\x17\\x00\\x00\\x00\\x00\\x12\\x03\\x00\\x00\\x00\\x07\\x00\\x00\\x00numArom\\x01\\x02\\x00\\x00\\x00\\x0f\\x00\\x00\\x00_StereochemDone\\x01\\x01\\x00\\x00\\x00\\x03\\x00\\x00\\x00foo\\x00\\x03\\x00\\x00\\x00bar\\x13:\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x12\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x01\\x00\\x00\\x000\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x1d\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x01\\x00\\x00\\x001\\x04\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x15\\x00\\x00\\x00\\x12\\x00\\x00\\x00_ChiralityPossible\\x01\\x01\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPCode\\x00\\x01\\x00\\x00\\x00S\\x05\\x00\\x00\\x00myidx\\x00\\x01\\x00\\x00\\x002\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x00\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x01\\x00\\x00\\x003\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x1a\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x01\\x00\\x00\\x004\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02"\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x01\\x00\\x00\\x005\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x1f\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x01\\x00\\x00\\x006\\x04\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x16\\x00\\x00\\x00\\x12\\x00\\x00\\x00_ChiralityPossible\\x01\\x01\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPCode\\x00\\x01\\x00\\x00\\x00S\\x05\\x00\\x00\\x00myidx\\x00\\x01\\x00\\x00\\x007\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x1c\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x01\\x00\\x00\\x008\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02$\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x01\\x00\\x00\\x009\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02 \\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0010\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x13\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0011\\x04\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x18\\x00\\x00\\x00\\x12\\x00\\x00\\x00_ChiralityPossible\\x01\\x01\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPCode\\x00\\x01\\x00\\x00\\x00S\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0012\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02!\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0013\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x19\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0014\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x0f\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0015\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x0b\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0016\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x08\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0017\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x0b\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0018\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x0f\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0019\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x07\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0020\\x04\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x17\\x00\\x00\\x00\\x12\\x00\\x00\\x00_ChiralityPossible\\x01\\x01\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPCode\\x00\\x01\\x00\\x00\\x00S\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0021\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x1b\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0022\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02#\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0023\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x1e\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0024\\x04\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x14\\x00\\x00\\x00\\x12\\x00\\x00\\x00_ChiralityPossible\\x01\\x01\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPCode\\x00\\x01\\x00\\x00\\x00R\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0025\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x06\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0026\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x03\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0027\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x05\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0028\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x10\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0029\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x0c\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0030\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\t\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0031\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\n\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0032\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\r\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0033\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x11\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0034\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x0e\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0035\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x04\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0036\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x02\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0037\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x01\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0038\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x02\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0039\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x04\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0040\\x13\\x16\'\np1\ntp2\nRp3\n.' + from rdkit.six.moves import cPickle + # bonds were broken in v1 + m2 = cPickle.loads(data.encode("utf-8"), encoding='bytes') + + self.assertEqual(m2.GetProp("foo"),"bar") + for atom in m2.GetAtoms(): + self.assertEqual(atom.GetProp("myidx"), str(atom.GetIdx())) + + self.assertEqual(Chem.MolToSmiles(m2, True), + Chem.MolToSmiles(Chem.MolFromSmiles( + "CN[C@@H](C)C(=O)N[C@H](C(=O)N1C[C@@H](Oc2ccccc2)C[C@H]1C(=O)N[C@@H]1CCCc2ccccc21)C1CCCCC1"), + True)) + if __name__ == '__main__': if "RDTESTCASE" in os.environ: suite = unittest.TestSuite() diff --git a/Code/RDGeneral/StreamOps.h b/Code/RDGeneral/StreamOps.h index e13736dd3..abfcc1249 100644 --- a/Code/RDGeneral/StreamOps.h +++ b/Code/RDGeneral/StreamOps.h @@ -231,6 +231,13 @@ inline void streamWrite(std::ostream &ss, const std::string &what) { ss.write(what.c_str(), sizeof(char) * l); }; +template +void streamWriteVec(std::ostream &ss, const T &val) { + streamWrite(ss, static_cast(val.size())); + for(size_t i=0;i void streamRead(std::istream &ss, T &loc) { @@ -258,6 +265,25 @@ inline void streamRead(std::istream &ss, std::string &what, int version) { }; +template +void streamReadVec(std::istream &ss, T &val) { + boost::uint64_t size; + streamRead(ss, size); + val.resize(size); + + for(size_t i=0;i &val, int version) { + boost::uint64_t size; + streamRead(ss, size); + val.resize(size); + + for(size_t i=0;i(pair.val)); break; + + case RDTypeTag::VecStringTag: + streamWrite(ss, DTags::VecStringTag); + streamWriteVec(ss, rdvalue_cast >(pair.val)); + break; + case RDTypeTag::VecDoubleTag: + streamWrite(ss, DTags::VecDoubleTag); + streamWriteVec(ss, rdvalue_cast >(pair.val)); + break; + case RDTypeTag::VecFloatTag: + streamWrite(ss, DTags::VecFloatTag); + streamWriteVec(ss, rdvalue_cast >(pair.val)); + break; + case RDTypeTag::VecIntTag: + streamWrite(ss, DTags::VecIntTag); + streamWriteVec(ss, rdvalue_cast >(pair.val)); + break; + case RDTypeTag::VecUnsignedIntTag: + streamWrite(ss, DTags::VecUIntTag); + streamWriteVec(ss, rdvalue_cast >(pair.val)); + break; default: std::cerr << "Failed to write " << pair.key << std::endl; return false; @@ -365,12 +417,14 @@ inline bool streamWriteProps(std::ostream &ss, const RDProps &props, for(Dict::DataType::const_iterator it = dict.getData().begin(); it != dict.getData().end(); ++it) { - if(isSerializable(*it) && propnames.find(it->key) != propnames.end()) { - // note - not all properties are serializable, this may be - // a null op - if(streamWriteProp(ss, *it)) { - writtenCount++; - } + if(propnames.find(it->key) != propnames.end()) { + if(isSerializable(*it)) { + // note - not all properties are serializable, this may be + // a null op + if(streamWriteProp(ss, *it)) { + writtenCount++; + } + } } } POSTCONDITION(count==writtenCount, "Estimated property count not equal to written"); @@ -384,6 +438,13 @@ void readRDValue(std::istream &ss, RDValue &value) { value = v; } +template +void readRDVecValue(std::istream &ss, RDValue &value) { + std::vector v; + streamReadVec(ss, v); + value = v; +} + inline void readRDValueString(std::istream &ss, RDValue &value) { std::string v; int version=0; @@ -391,6 +452,15 @@ inline void readRDValueString(std::istream &ss, RDValue &value) { value = v; } + +inline void readRDStringVecValue(std::istream &ss, RDValue &value) { + std::vector v; + int version=0; + streamReadStringVec(ss, v, version); + value = v; +} + + inline bool streamReadProp(std::istream &ss, Dict::Pair &pair) { int version=0; streamRead(ss, pair.key, version); @@ -404,6 +474,13 @@ inline bool streamReadProp(std::istream &ss, Dict::Pair &pair) { case DTags::BoolTag: readRDValue(ss, pair.val); break; case DTags::FloatTag: readRDValue(ss, pair.val); break; case DTags::DoubleTag: readRDValue(ss, pair.val); break; + + case DTags::VecStringTag: readRDStringVecValue(ss, pair.val); break; + case DTags::VecIntTag: readRDVecValue(ss, pair.val); break; + case DTags::VecUIntTag: readRDVecValue(ss, pair.val); break; + case DTags::VecFloatTag: readRDVecValue(ss, pair.val); break; + case DTags::VecDoubleTag: readRDVecValue(ss, pair.val); break; + default: return false; } From 9af90524a41825b67ffb19cdbff9b363d5a7ca7e Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Fri, 8 Sep 2017 10:52:01 +0200 Subject: [PATCH 03/44] Provide support for color palettes in MolDraw2D (#1546) * first steps towards flexible colour palettes * add B&W palette and a test for it * add python support; this is, once again, not the best API due to the inability to auto-translate boost::tuples at this point * more palette control from python * rename some of the swig-wrapped types to make them more consistent * handle palettes that do not have a default value --- Code/GraphMol/MolDraw2D/MolDraw2D.cpp | 51 ++++---------- Code/GraphMol/MolDraw2D/MolDraw2D.h | 66 ++++++++++++------ Code/GraphMol/MolDraw2D/Wrap/rdMolDraw2D.cpp | 46 ++++++++++--- Code/GraphMol/MolDraw2D/Wrap/testMolDraw2D.py | 68 +++++++++++++++++++ Code/GraphMol/MolDraw2D/test1.cpp | 39 +++++++++++ Code/JavaWrappers/MolDraw2D.i | 6 +- 6 files changed, 203 insertions(+), 73 deletions(-) diff --git a/Code/GraphMol/MolDraw2D/MolDraw2D.cpp b/Code/GraphMol/MolDraw2D/MolDraw2D.cpp index 011daa9e5..004d47ef9 100644 --- a/Code/GraphMol/MolDraw2D/MolDraw2D.cpp +++ b/Code/GraphMol/MolDraw2D/MolDraw2D.cpp @@ -1069,46 +1069,19 @@ DrawColour MolDraw2D::getColour( // **************************************************************************** DrawColour MolDraw2D::getColourByAtomicNum(int atomic_num) { - // RGB values taken from Qt's QColor. The seem to work pretty well on my - // machine. Using them as fractions of 255, as that's the way Cairo does it. - DrawColour res(0., 0., 0.); // default to black - - switch (atomic_num) { - case 0: - res = DrawColour(0.5, 0.5, 0.5); - break; - case 1: // Hs and Carbons are the same colour - case 6: - res = DrawColour(0.0, 0.0, 0.0); - break; - case 7: - res = DrawColour(0.0, 0.0, 1.0); - break; - case 8: - res = DrawColour(1.0, 0.0, 0.0); - break; - case 9: - res = DrawColour(0.2, 0.8, 0.8); - break; - case 15: - res = DrawColour(1.0, 0.5, 0.0); - break; - case 16: - res = DrawColour(0.8, 0.8, 0.0); - break; - case 17: - res = DrawColour(0.0, 0.802, 0.0); - break; - case 35: - res = DrawColour(0.5, 0.3, 0.1); - break; - case 53: - res = DrawColour(0.63, 0.12, 0.94); - break; - default: - break; + DrawColour res; + if (drawOptions().atomColourPalette.find(atomic_num) != + drawOptions().atomColourPalette.end()) { + res = drawOptions().atomColourPalette[atomic_num]; + } else if (atomic_num != -1 && + drawOptions().atomColourPalette.find(-1) != + drawOptions().atomColourPalette.end()) { + // if -1 is in the palette, we use that for undefined colors + res = drawOptions().atomColourPalette[-1]; + } else { + // if all else fails, default to black: + res = DrawColour(0, 0, 0); } - return res; } diff --git a/Code/GraphMol/MolDraw2D/MolDraw2D.h b/Code/GraphMol/MolDraw2D/MolDraw2D.h index a84ec5188..c0c781add 100644 --- a/Code/GraphMol/MolDraw2D/MolDraw2D.h +++ b/Code/GraphMol/MolDraw2D/MolDraw2D.h @@ -36,8 +36,29 @@ using RDGeom::Point2D; namespace RDKit { typedef boost::tuple DrawColour; +typedef std::map ColourPalette; typedef std::vector DashPattern; +inline void assignDefaultPalette(ColourPalette &palette) { + palette.clear(); + palette[-1] = DrawColour(0, 0, 0); + palette[0] = DrawColour(0.5, 0.5, 0.5); + palette[1] = palette[6] = DrawColour(0.0, 0.0, 0.0); + palette[7] = DrawColour(0.0, 0.0, 1.0); + palette[8] = DrawColour(1.0, 0.0, 0.0); + palette[9] = DrawColour(0.2, 0.8, 0.8); + palette[15] = DrawColour(1.0, 0.5, 0.0); + palette[16] = DrawColour(0.8, 0.8, 0.0); + palette[17] = DrawColour(0.0, 0.802, 0.0); + palette[35] = DrawColour(0.5, 0.3, 0.1); + palette[53] = DrawColour(0.63, 0.12, 0.94); +}; + +inline void assignBWPalette(ColourPalette &palette) { + palette.clear(); + palette[-1] = DrawColour(0, 0, 0); +}; + struct MolDrawOptions { bool atomLabelDeuteriumTritium; // toggles replacing 2H with D and 3H with T bool dummiesAreAttachments; // draws "breaks" at dummy atoms @@ -66,9 +87,12 @@ struct MolDrawOptions { std::vector > atomRegions; // regions DrawColour symbolColour; // color to be used for the symbols and arrows in reactions - std::vector highlightColourPalette; // defining 10 default colors - // for highlighting atoms and bonds - //or reactants in a reactions + std::vector highlightColourPalette; // defining 10 default colors + // for highlighting atoms and bonds + // or reactants in a reactions + ColourPalette atomColourPalette; // the palette used to assign + // colors to atoms based on + // atomic number. -1 is the default value MolDrawOptions() : atomLabelDeuteriumTritium(false), @@ -85,19 +109,20 @@ struct MolDrawOptions { multipleBondOffset(0.15), padding(0.05), additionalAtomLabelPadding(0.0), - symbolColour(0, 0, 0){ - highlightColourPalette.push_back(DrawColour(1., 1., .67)); // popcorn yellow - highlightColourPalette.push_back(DrawColour(1., .8, .6)); // sand - highlightColourPalette.push_back(DrawColour(1., .71, .76)); // light pink - highlightColourPalette.push_back(DrawColour(.8, 1., .8)); // offwhitegreen - highlightColourPalette.push_back(DrawColour(.87, .63, .87)); // plum - highlightColourPalette.push_back(DrawColour(.76, .94, .96)); // pastel blue - highlightColourPalette.push_back(DrawColour(.67, .67, 1.)); // periwinkle - highlightColourPalette.push_back(DrawColour(.64, .76, .34)); // avocado - highlightColourPalette.push_back(DrawColour(.56, .93, .56)); // light green - highlightColourPalette.push_back(DrawColour(.20, .63, .79)); // peacock + symbolColour(0, 0, 0) { + highlightColourPalette.push_back( + DrawColour(1., 1., .67)); // popcorn yellow + highlightColourPalette.push_back(DrawColour(1., .8, .6)); // sand + highlightColourPalette.push_back(DrawColour(1., .71, .76)); // light pink + highlightColourPalette.push_back(DrawColour(.8, 1., .8)); // offwhitegreen + highlightColourPalette.push_back(DrawColour(.87, .63, .87)); // plum + highlightColourPalette.push_back(DrawColour(.76, .94, .96)); // pastel blue + highlightColourPalette.push_back(DrawColour(.67, .67, 1.)); // periwinkle + highlightColourPalette.push_back(DrawColour(.64, .76, .34)); // avocado + highlightColourPalette.push_back(DrawColour(.56, .93, .56)); // light green + highlightColourPalette.push_back(DrawColour(.20, .63, .79)); // peacock + assignDefaultPalette(atomColourPalette); }; - }; //! MolDraw2D is the base class for doing 2D renderings of molecules @@ -215,15 +240,16 @@ class MolDraw2D { \param highlightByReactant : (optional) if this is set, atoms and bonds will be highlighted based on which reactant they come from. Atom map numbers will not be shown. - \param highlightColorsReactants : (optional) provide a vector of colors for the + \param highlightColorsReactants : (optional) provide a vector of colors for + the reactant highlighting. \param confIds : (optional) vector of confIds to use for rendering. These are numbered by reactants, then agents, then products. */ - virtual void drawReaction(const ChemicalReaction &rxn, - bool highlightByReactant = false, - const std::vector* highlightColorsReactants = NULL, - const std::vector *confIds = NULL); + virtual void drawReaction( + const ChemicalReaction &rxn, bool highlightByReactant = false, + const std::vector *highlightColorsReactants = NULL, + const std::vector *confIds = NULL); //! \name Transformations //@{ diff --git a/Code/GraphMol/MolDraw2D/Wrap/rdMolDraw2D.cpp b/Code/GraphMol/MolDraw2D/Wrap/rdMolDraw2D.cpp index 0062483df..13ab64307 100644 --- a/Code/GraphMol/MolDraw2D/Wrap/rdMolDraw2D.cpp +++ b/Code/GraphMol/MolDraw2D/Wrap/rdMolDraw2D.cpp @@ -27,7 +27,7 @@ namespace python = boost::python; namespace RDKit { namespace { -void pyDictToColourMap(python::object pyo, std::map &res) { +void pyDictToColourMap(python::object pyo, ColourPalette &res) { python::dict tDict = python::extract(pyo); for (unsigned int i = 0; i < python::extract(tDict.keys().attr("__len__")()); ++i) { @@ -39,10 +39,10 @@ void pyDictToColourMap(python::object pyo, std::map &res) { res[python::extract(tDict.keys()[i])] = clr; } } -std::map *pyDictToColourMap(python::object pyo) { - std::map *res = NULL; +ColourPalette *pyDictToColourMap(python::object pyo) { + ColourPalette *res = NULL; if (pyo) { - res = new std::map; + res = new ColourPalette; pyDictToColourMap(pyo, *res); } return res; @@ -98,7 +98,7 @@ void drawMoleculeHelper1(MolDraw2D &self, const ROMol &mol, std::string legend) { rdk_auto_ptr > highlightAtoms = pythonObjectToVect(highlight_atoms, static_cast(mol.getNumAtoms())); - std::map *ham = pyDictToColourMap(highlight_atom_map); + ColourPalette *ham = pyDictToColourMap(highlight_atom_map); std::map *har = pyDictToDoubleMap(highlight_atom_radii); self.drawMolecule(mol, legend, highlightAtoms.get(), ham, har, confId); @@ -118,8 +118,8 @@ void drawMoleculeHelper2(MolDraw2D &self, const ROMol &mol, rdk_auto_ptr > highlightBonds = pythonObjectToVect(highlight_bonds, static_cast(mol.getNumBonds())); // FIX: support these - std::map *ham = pyDictToColourMap(highlight_atom_map); - std::map *hbm = pyDictToColourMap(highlight_bond_map); + ColourPalette *ham = pyDictToColourMap(highlight_atom_map); + ColourPalette *hbm = pyDictToColourMap(highlight_bond_map); std::map *har = pyDictToDoubleMap(highlight_atom_radii); self.drawMolecule(mol, legend, highlightAtoms.get(), highlightBonds.get(), @@ -165,7 +165,7 @@ void drawMoleculesHelper2(MolDraw2D &self, python::object pmols, } } - rdk_auto_ptr > > highlightAtomMap; + rdk_auto_ptr > highlightAtomMap; if (highlight_atom_map) { if (python::extract(highlight_atom_map.attr("__len__")()) != nThere) { @@ -173,12 +173,12 @@ void drawMoleculesHelper2(MolDraw2D &self, python::object pmols, "If highlightAtomMap is provided it must be the same length as the " "molecule list."); } - highlightAtomMap.reset(new std::vector >(nThere)); + highlightAtomMap.reset(new std::vector(nThere)); for (unsigned int i = 0; i < nThere; ++i) { pyDictToColourMap(highlight_atom_map[i], (*highlightAtomMap)[i]); } } - rdk_auto_ptr > > highlightBondMap; + rdk_auto_ptr > highlightBondMap; if (highlight_bond_map) { if (python::extract(highlight_bond_map.attr("__len__")()) != nThere) { @@ -186,7 +186,7 @@ void drawMoleculesHelper2(MolDraw2D &self, python::object pmols, "If highlightBondMap is provided it must be the same length as the " "molecule list."); } - highlightBondMap.reset(new std::vector >(nThere)); + highlightBondMap.reset(new std::vector(nThere)); for (unsigned int i = 0; i < nThere; ++i) { pyDictToColourMap(highlight_bond_map[i], (*highlightBondMap)[i]); } @@ -278,6 +278,19 @@ void setBgColour(RDKit::MolDrawOptions &self, python::tuple tpl) { void setHighlightColour(RDKit::MolDrawOptions &self, python::tuple tpl) { self.highlightColour = pyTupleToDrawColour(tpl); } +void useDefaultAtomPalette(RDKit::MolDrawOptions &self) { + assignDefaultPalette(self.atomColourPalette); +} +void useBWAtomPalette(RDKit::MolDrawOptions &self) { + assignBWPalette(self.atomColourPalette); +} +void updateAtomPalette(RDKit::MolDrawOptions &self, python::object cmap) { + pyDictToColourMap(cmap, self.atomColourPalette); +} +void setAtomPalette(RDKit::MolDrawOptions &self, python::object cmap) { + self.atomColourPalette.clear(); + updateAtomPalette(self, cmap); +} } BOOST_PYTHON_MODULE(rdMolDraw2D) { @@ -305,6 +318,17 @@ BOOST_PYTHON_MODULE(rdMolDraw2D) { "method for setting the background colour") .def("setHighlightColour", &RDKit::setHighlightColour, "method for setting the highlight colour") + .def("useDefaultAtomPalette", &RDKit::useDefaultAtomPalette, + "use the default colour palette for atoms and bonds") + .def("useBWAtomPalette", &RDKit::useBWAtomPalette, + "use the black & white palette for atoms and bonds") + .def("updateAtomPalette", &RDKit::updateAtomPalette, + "updates the palette for atoms and bonds from a dictionary mapping " + "ints to 3-tuples") + .def( + "setAtomPalette", &RDKit::setAtomPalette, + "sets the palette for atoms and bonds from a dictionary mapping ints " + "to 3-tuples") .def_readwrite("atomLabels", &RDKit::MolDrawOptions::atomLabels, "maps indices to atom labels") .def_readwrite("atomLabelDeuteriumTritium", diff --git a/Code/GraphMol/MolDraw2D/Wrap/testMolDraw2D.py b/Code/GraphMol/MolDraw2D/Wrap/testMolDraw2D.py index 9bb98bdb1..5a693f763 100644 --- a/Code/GraphMol/MolDraw2D/Wrap/testMolDraw2D.py +++ b/Code/GraphMol/MolDraw2D/Wrap/testMolDraw2D.py @@ -221,5 +221,73 @@ M END""") d = Draw.MolDraw2DSVG(900, 300) self.assertRaises(ValueError, d.DrawReaction, rxn, True, colors) + def testBWDrawing(self): + m = Chem.MolFromSmiles('CCOCNCCl') + dm = Draw.PrepareMolForDrawing(m) + d = Draw.MolDraw2DSVG(300, 300) + d.DrawMolecule(dm) + d.FinishDrawing() + txt = d.GetDrawingText() + self.assertTrue(txt.find("stroke:#000000")>=0) + self.assertTrue(txt.find("stroke:#00CC00")>=0) + + d = Draw.MolDraw2DSVG(300, 300) + d.drawOptions().useBWAtomPalette() + d.DrawMolecule(dm) + d.FinishDrawing() + txt = d.GetDrawingText() + self.assertTrue(txt.find("stroke:#000000")>=0) + self.assertTrue(txt.find("stroke:#00CC00")==-1) + + def testUpdatePalette(self): + m = Chem.MolFromSmiles('CCOCNCCl') + dm = Draw.PrepareMolForDrawing(m) + d = Draw.MolDraw2DSVG(300, 300) + d.DrawMolecule(dm) + d.FinishDrawing() + txt = d.GetDrawingText() + self.assertTrue(txt.find("stroke:#000000")>=0) + self.assertTrue(txt.find("stroke:#00CC00")>=0) + + d = Draw.MolDraw2DSVG(300, 300) + d.drawOptions().updateAtomPalette({6:(1,1,0)}) + d.DrawMolecule(dm) + d.FinishDrawing() + txt = d.GetDrawingText() + self.assertTrue(txt.find("stroke:#000000")==-1) + self.assertTrue(txt.find("stroke:#00CC00")>=0) + self.assertTrue(txt.find("stroke:#FFFF00")>=0) + + + def testSetPalette(self): + m = Chem.MolFromSmiles('CCOCNCCl') + dm = Draw.PrepareMolForDrawing(m) + d = Draw.MolDraw2DSVG(300, 300) + d.DrawMolecule(dm) + d.FinishDrawing() + txt = d.GetDrawingText() + self.assertTrue(txt.find("stroke:#000000")>=0) + self.assertTrue(txt.find("stroke:#00CC00")>=0) + + d = Draw.MolDraw2DSVG(300, 300) + d.drawOptions().setAtomPalette({-1:(1,1,0)}) + d.DrawMolecule(dm) + d.FinishDrawing() + txt = d.GetDrawingText() + self.assertTrue(txt.find("stroke:#000000")==-1) + self.assertTrue(txt.find("stroke:#00CC00")==-1) + self.assertTrue(txt.find("stroke:#FFFF00")>=0) + + # try a palette that doesn't have a default: + d = Draw.MolDraw2DSVG(300, 300) + d.drawOptions().setAtomPalette({0:(1,1,0)}) + d.DrawMolecule(dm) + d.FinishDrawing() + txt = d.GetDrawingText() + self.assertTrue(txt.find("stroke:#000000")>=0) + self.assertTrue(txt.find("stroke:#00CC00")==-1) + self.assertTrue(txt.find("stroke:#FFFF00")==-1) + + if __name__ == "__main__": unittest.main() diff --git a/Code/GraphMol/MolDraw2D/test1.cpp b/Code/GraphMol/MolDraw2D/test1.cpp index 9d9365bec..e6153884a 100644 --- a/Code/GraphMol/MolDraw2D/test1.cpp +++ b/Code/GraphMol/MolDraw2D/test1.cpp @@ -2013,6 +2013,44 @@ void testGithub565() { std::cerr << " Done" << std::endl; } +void test14BWPalette() { + std::cout << " ----------------- Testing use of a black & white palette" + << std::endl; + { + std::string smiles = "CNC(Cl)C(=O)O"; + RWMol *m1 = SmilesToMol(smiles); + TEST_ASSERT(m1); + MolDraw2DUtils::prepareMolForDrawing(*m1); + + { // start with color + MolDraw2DSVG drawer(200, 200); + drawer.drawMolecule(*m1, "m1"); + drawer.finishDrawing(); + std::string text = drawer.getDrawingText(); + + TEST_ASSERT(text.find("stroke:#00CC00") != std::string::npos); + + std::ofstream outs("test14_1.svg"); + outs << text; + outs.flush(); + } + { // now B&W + MolDraw2DSVG drawer(200, 200); + assignBWPalette(drawer.drawOptions().atomColourPalette); + drawer.drawMolecule(*m1, "m1"); + drawer.finishDrawing(); + std::string text = drawer.getDrawingText(); + + TEST_ASSERT(text.find("stroke:#00CC00") == std::string::npos); + + std::ofstream outs("test14_2.svg"); + outs << text; + outs.flush(); + } + } + std::cerr << " Done" << std::endl; +} + int main() { RDLog::InitLogs(); #if 1 @@ -2046,4 +2084,5 @@ int main() { testGithub1271(); testGithub1322(); testGithub565(); + test14BWPalette(); } diff --git a/Code/JavaWrappers/MolDraw2D.i b/Code/JavaWrappers/MolDraw2D.i index 03362148e..cc415d353 100644 --- a/Code/JavaWrappers/MolDraw2D.i +++ b/Code/JavaWrappers/MolDraw2D.i @@ -42,9 +42,9 @@ #include %} -%template(INT_STRING_MAP) std::map< int, std::string >; -%template(INT_DRAWCOLOUR_MAP) std::map< int, RDKit::DrawColour >; -%template(INT_DOUBLE_MAP) std::map< int, double >; +%template(Int_String_Map) std::map< int, std::string >; +%template(Int_DrawColour_Map) std::map< int, RDKit::DrawColour >; +%template(Int_Double_Map) std::map< int, double >; %template(DrawColour) boost::tuple; %template(Float_Pair) std::pair; %template(Float_Pair_Vect) std::vector< std::pair >; From f36877b2b283e2079fc90b373cb08f208d5afa51 Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Fri, 8 Sep 2017 13:47:19 +0200 Subject: [PATCH 04/44] A few reaction drawing tweaks (#1549) * add svg support to Draw.ReactionToImage * jupyter support --- rdkit/Chem/Draw/IPythonConsole.py | 12 ++++++++++-- rdkit/Chem/Draw/__init__.py | 16 +++++++++++----- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/rdkit/Chem/Draw/IPythonConsole.py b/rdkit/Chem/Draw/IPythonConsole.py index 557c4ffb3..a3266b19c 100644 --- a/rdkit/Chem/Draw/IPythonConsole.py +++ b/rdkit/Chem/Draw/IPythonConsole.py @@ -38,7 +38,7 @@ from IPython.display import SVG molSize = (450, 150) highlightSubstructs = True kekulizeStructures = True - +highlightByReactant = False ipython_useSVG = False ipython_3d = False molSize_3d = (400, 400) @@ -148,11 +148,18 @@ def _toSVG(mol): def _toReactionPNG(rxn): rc = copy.deepcopy(rxn) - img = Draw.ReactionToImage(rc, subImgSize=(int(molSize[0] / 3), molSize[1])) + img = Draw.ReactionToImage(rc, subImgSize=(int(molSize[0] / 3), molSize[1]), + highlightByReactant=highlightByReactant) bio = BytesIO() img.save(bio, format='PNG') return bio.getvalue() +def _toReactionSVG(rxn): + if not ipython_useSVG: + return None + rc = copy.deepcopy(rxn) + return Draw.ReactionToImage(rc, subImgSize=(int(molSize[0] / 3), molSize[1]), + useSVG=True,highlightByReactant=highlightByReactant) def _GetSubstructMatch(mol, query, **kwargs): res = mol.__GetSubstructMatch(query, **kwargs) @@ -205,6 +212,7 @@ def InstallIPythonRenderer(): if _canUse3D: rdchem.Mol._repr_html_ = _toJSON rdChemReactions.ChemicalReaction._repr_png_ = _toReactionPNG + rdChemReactions.ChemicalReaction._repr_svg_ = _toReactionSVG if not hasattr(rdchem.Mol, '__GetSubstructMatch'): rdchem.Mol.__GetSubstructMatch = rdchem.Mol.GetSubstructMatch rdchem.Mol.GetSubstructMatch = _GetSubstructMatch diff --git a/rdkit/Chem/Draw/__init__.py b/rdkit/Chem/Draw/__init__.py index 1100c276f..3b7d027d4 100644 --- a/rdkit/Chem/Draw/__init__.py +++ b/rdkit/Chem/Draw/__init__.py @@ -447,15 +447,21 @@ def _legacyReactionToImage(rxn, subImgSize=(200, 200), **kwargs): return res -def ReactionToImage(rxn, subImgSize=(200, 200), **kwargs): - if not hasattr(rdMolDraw2D, 'MolDraw2DCairo'): +def ReactionToImage(rxn, subImgSize=(200, 200), useSVG=False, **kwargs): + if not useSVG and not hasattr(rdMolDraw2D, 'MolDraw2DCairo'): return _legacyReactionToImage(rxn,subImgSize=subImgSize,**kwargs) else: width = subImgSize[0] * (rxn.GetNumReactantTemplates() + rxn.GetNumProductTemplates() + 1) - d = rdMolDraw2D.MolDraw2DCairo(width, subImgSize[1]) - d.DrawReaction(rxn) + if useSVG: + d = rdMolDraw2D.MolDraw2DSVG(width, subImgSize[1]) + else: + d = rdMolDraw2D.MolDraw2DCairo(width, subImgSize[1]) + d.DrawReaction(rxn,**kwargs) d.FinishDrawing() - return _drawerToImage(d) + if useSVG: + return d.GetDrawingText().replace('svg:', '') + else: + return _drawerToImage(d) def MolToQPixmap(mol, size=(300, 300), kekulize=True, wedgeBonds=True, fitImage=False, options=None, **kwargs): From 5a06022704a49f1d71542d95ed8b07c5600ea204 Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Fri, 8 Sep 2017 13:49:05 +0200 Subject: [PATCH 05/44] R group improvements (#1552) * Fixes #1550 * might as well update properties on the r groups too * add option to remove Hs from sidechains; expose a few more parameters to python; expose ctor with parameter object to python --- .../RGroupDecomposition/RGroupDecomp.cpp | 8 ++ .../RGroupDecomposition/RGroupDecomp.h | 124 ++++++++++-------- .../Wrap/rdRGroupComposition.cpp | 22 ++++ .../RGroupDecomposition/Wrap/test_rgroups.py | 42 ++++-- .../RGroupDecomposition/testRGroupDecomp.cpp | 87 +++++++++++- 5 files changed, 214 insertions(+), 69 deletions(-) diff --git a/Code/GraphMol/RGroupDecomposition/RGroupDecomp.cpp b/Code/GraphMol/RGroupDecomposition/RGroupDecomp.cpp index f70a505bb..78b0b1be1 100644 --- a/Code/GraphMol/RGroupDecomposition/RGroupDecomp.cpp +++ b/Code/GraphMol/RGroupDecomposition/RGroupDecomp.cpp @@ -600,6 +600,7 @@ struct RGroupDecompData { mol.addAtom(atomsToAdd[i].second, false, true); mol.addBond(atomsToAdd[i].first, atomsToAdd[i].second, Bond::SINGLE); } + mol.updatePropertyCache(false); // this was github #1550 } void relabelRGroup(RGroupData &rgroup, const std::map &mappings) { @@ -642,6 +643,13 @@ struct RGroupDecompData { mol.addAtom(atomsToAdd[i].second, false, true); mol.addBond(atomsToAdd[i].first, atomsToAdd[i].second, Bond::SINGLE); } + if (params.removeHydrogensPostMatch) { + bool implicitOnly = false; + bool updateExplicitCount = false; + bool sanitize = false; + MolOps::removeHs(mol, implicitOnly, updateExplicitCount, sanitize); + } + mol.updatePropertyCache(false); // this was github #1550 } // relabel the core and sidechains using the specified user labels diff --git a/Code/GraphMol/RGroupDecomposition/RGroupDecomp.h b/Code/GraphMol/RGroupDecomposition/RGroupDecomp.h index 2679d9672..4e8ee07a8 100644 --- a/Code/GraphMol/RGroupDecomposition/RGroupDecomp.h +++ b/Code/GraphMol/RGroupDecomposition/RGroupDecomp.h @@ -24,29 +24,29 @@ namespace RDKit { \return the set of degenerative points (set) */ -typedef enum { - IsotopeLabels = 0x01, - AtomMapLabels = 0x02, - AtomIndexLabels = 0x04, +typedef enum { + IsotopeLabels = 0x01, + AtomMapLabels = 0x02, + AtomIndexLabels = 0x04, RelabelDuplicateLabels = 0x08, - AutoDetect = 0x0F, + AutoDetect = 0x0F, } RGroupLabels; -typedef enum { - Greedy = 0x01, - GreedyChunks = 0x02, - Exhaustive = 0x04, // not really useful for large sets +typedef enum { + Greedy = 0x01, + GreedyChunks = 0x02, + Exhaustive = 0x04, // not really useful for large sets } RGroupMatching; -typedef enum { - AtomMap = 0x01, - Isotope = 0x02, - MDLRGroup = 0x04, +typedef enum { + AtomMap = 0x01, + Isotope = 0x02, + MDLRGroup = 0x04, } RGroupLabelling; -typedef enum { - None = 0x0, - MCS = 0x01, +typedef enum { + None = 0x0, + MCS = 0x01, } RGroupCoreAlignment; struct RGroupDecompositionParameters { @@ -54,59 +54,65 @@ struct RGroupDecompositionParameters { unsigned int matchingStrategy; unsigned int rgroupLabelling; unsigned int alignment; - + unsigned int chunkSize; bool onlyMatchAtRGroups; bool removeAllHydrogenRGroups; + bool removeHydrogensPostMatch; - RGroupDecompositionParameters(unsigned int labels=AutoDetect, - unsigned int strategy=GreedyChunks, - unsigned int labelling=AtomMap | MDLRGroup, - unsigned int alignment=MCS, - unsigned int chunkSize=5, - bool matchOnlyAtRGroups=false, - bool removeHydrogenOnlyGroups=true) : - labels(labels), - matchingStrategy(strategy), - rgroupLabelling(labelling), - alignment(alignment), - chunkSize(chunkSize), - onlyMatchAtRGroups(matchOnlyAtRGroups), - removeAllHydrogenRGroups(removeHydrogenOnlyGroups), - indexOffset(-1) { - } + RGroupDecompositionParameters(unsigned int labels = AutoDetect, + unsigned int strategy = GreedyChunks, + unsigned int labelling = AtomMap | MDLRGroup, + unsigned int alignment = MCS, + unsigned int chunkSize = 5, + bool matchOnlyAtRGroups = false, + bool removeHydrogenOnlyGroups = true, + bool removeHydrogensPostMatch = false) + : labels(labels), + matchingStrategy(strategy), + rgroupLabelling(labelling), + alignment(alignment), + chunkSize(chunkSize), + onlyMatchAtRGroups(matchOnlyAtRGroups), + removeAllHydrogenRGroups(removeHydrogenOnlyGroups), + removeHydrogensPostMatch(removeHydrogensPostMatch), + indexOffset(-1) {} bool prepareCore(RWMol &, const RWMol *alignCore); - void SetRGroupLabels(unsigned int rgroupLabels) { - labels = rgroupLabels; - } + void SetRGroupLabels(unsigned int rgroupLabels) { labels = rgroupLabels; } void SetRGroupLabelling(unsigned int labelling) { rgroupLabelling = labelling; } - void SetRGroupMatching(unsigned int matching) { - matchingStrategy = matching; - } + void SetRGroupMatching(unsigned int matching) { matchingStrategy = matching; } void SetRGroupCoreAlignment(unsigned int coreAlignment) { alignment = coreAlignment; } void SetChunkSize(unsigned int size) { chunkSize = size; } - void SetOnlyMatchAtRGroups(bool matchAtRGroups) { onlyMatchAtRGroups = matchAtRGroups; } - void SetRemoveRGroupsThatAreAllHydrogen( bool remove ) { removeAllHydrogenRGroups = remove; } + void SetOnlyMatchAtRGroups(bool matchAtRGroups) { + onlyMatchAtRGroups = matchAtRGroups; + } + void SetRemoveRGroupsThatAreAllHydrogen(bool remove) { + removeAllHydrogenRGroups = remove; + } + void SetRemoveHydrogensPostMatch(bool remove) { + removeHydrogensPostMatch = remove; + } unsigned int GetRGroupLabels() const { return labels; } unsigned int GetRGroupLabelling() const { return matchingStrategy; } unsigned int GetRGroupMatching() const { return rgroupLabelling; } unsigned int GetRGroupCoreAlignment() const { return alignment; } - unsigned int GetChunkSize() const { return chunkSize; } + unsigned int GetChunkSize() const { return chunkSize; } bool GetOnlyMatchAtRGroups() const { return onlyMatchAtRGroups; } - bool GetRemoveRGroupsThatAreAllHydrogen() const { return removeAllHydrogenRGroups; } - - + bool GetRemoveRGroupsThatAreAllHydrogen() const { + return removeAllHydrogenRGroups; + } + bool GetRemoveHydrogensPostMatch() const { return removeHydrogensPostMatch; } private: int indexOffset; }; -typedef std::map > RGroupRow; +typedef std::map > RGroupRow; typedef std::vector > RGroupColumn; typedef std::vector RGroupRows; @@ -114,27 +120,29 @@ typedef std::map RGroupColumns; struct RGroupDecompData; class RGroupDecomposition { - RGroupDecompData *data; // implementation details - RGroupDecomposition(const RGroupDecomposition &); // no copy construct - RGroupDecomposition& operator=(const RGroupDecomposition&); // Prevent assignment + RGroupDecompData *data; // implementation details + RGroupDecomposition(const RGroupDecomposition &); // no copy construct + RGroupDecomposition &operator=( + const RGroupDecomposition &); // Prevent assignment -public: + public: RGroupDecomposition(const ROMol &core, - const RGroupDecompositionParameters ¶ms=RGroupDecompositionParameters()); + const RGroupDecompositionParameters ¶ms = + RGroupDecompositionParameters()); RGroupDecomposition(const std::vector &cores, - const RGroupDecompositionParameters ¶ms=RGroupDecompositionParameters()); - - ~RGroupDecomposition(); - - int add(const ROMol &mol); + const RGroupDecompositionParameters ¶ms = + RGroupDecompositionParameters()); + + ~RGroupDecomposition(); + + int add(const ROMol &mol); bool process(); - + //! return rgroups in row order group[row][attachment_point] = ROMol RGroupRows getRGroupsAsRows() const; //! return rgroups in column order group[attachment_point][row] = ROMol RGroupColumns getRGroupsAsColumns() const; }; - } #endif diff --git a/Code/GraphMol/RGroupDecomposition/Wrap/rdRGroupComposition.cpp b/Code/GraphMol/RGroupDecomposition/Wrap/rdRGroupComposition.cpp index b916948f7..8231728f5 100644 --- a/Code/GraphMol/RGroupDecomposition/Wrap/rdRGroupComposition.cpp +++ b/Code/GraphMol/RGroupDecomposition/Wrap/rdRGroupComposition.cpp @@ -166,6 +166,24 @@ struct rgroupdecomp_wrapper { &RDKit::RGroupDecompositionParameters::SetRGroupCoreAlignment) .def("GetRGroupCoreAlignment", &RDKit::RGroupDecompositionParameters::GetRGroupCoreAlignment) + .def("SetChunkSize", + &RDKit::RGroupDecompositionParameters::SetChunkSize) + .def("GetChunkSize", + &RDKit::RGroupDecompositionParameters::GetChunkSize) + .def("SetOnlyMatchAtRGroups", + &RDKit::RGroupDecompositionParameters::SetOnlyMatchAtRGroups) + .def("GetOnlyMatchAtRGroups", + &RDKit::RGroupDecompositionParameters::GetOnlyMatchAtRGroups) + .def("SetRemoveRGroupsThatAreAllHydrogen", + &RDKit::RGroupDecompositionParameters:: + SetRemoveRGroupsThatAreAllHydrogen) + .def("GetRemoveRGroupsThatAreAllHydrogen", + &RDKit::RGroupDecompositionParameters:: + GetRemoveRGroupsThatAreAllHydrogen) + .def("SetRemoveHydrogensPostMatch", + &RDKit::RGroupDecompositionParameters::SetRemoveHydrogensPostMatch) + .def("GetRemoveHydrogensPostMatch", + &RDKit::RGroupDecompositionParameters::GetRemoveHydrogensPostMatch) ; @@ -173,6 +191,10 @@ struct rgroupdecomp_wrapper { "RGroupDecomposition", docString.c_str(), python::init( "Construct from a molecule or sequence of molecules")) + .def( + python::init( + "Construct from a molecule or sequence of molecules and a " + "parameters object")) .def("Add", &RGroupDecompositionHelper::Add) .def("Process", &RGroupDecompositionHelper::Process, "Process the rgroups (must be done prior to " diff --git a/Code/GraphMol/RGroupDecomposition/Wrap/test_rgroups.py b/Code/GraphMol/RGroupDecomposition/Wrap/test_rgroups.py index 7e9e96f44..5a4869724 100644 --- a/Code/GraphMol/RGroupDecomposition/Wrap/test_rgroups.py +++ b/Code/GraphMol/RGroupDecomposition/Wrap/test_rgroups.py @@ -1,18 +1,18 @@ # Copyright (c) 2017, Novartis Institutes for BioMedical Research Inc. # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are -# met: +# met: # -# * Redistributions of source code must retain the above copyright +# * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided # with the distribution. -# * Neither the name of Novartis Institutes for BioMedical Research Inc. -# nor the names of its contributors may be used to endorse or promote +# * Neither the name of Novartis Institutes for BioMedical Research Inc. +# nor the names of its contributors may be used to endorse or promote # products derived from this software without specific prior written # permission. # @@ -37,7 +37,7 @@ from rdkit.six.moves import cPickle from rdkit import rdBase from rdkit import Chem -from rdkit.Chem.rdRGroupDecomposition import RGroupDecomposition +from rdkit.Chem.rdRGroupDecomposition import RGroupDecomposition, RGroupDecompositionParameters from collections import OrderedDict class TestCase(unittest.TestCase) : @@ -118,6 +118,30 @@ C1CCO[C@@](S)(P)1 columns = rgroups.GetRGroupsAsColumns() for k,v in columns.items(): print("%s:%s"%(k, " ".join([Chem.MolToSmiles(m,True) for m in v]))) - + + def test_h_options(self): + core = Chem.MolFromSmiles("O=c1oc2ccccc2cc1") + smiles = ("O=c1cc(Cn2ccnc2)c2ccc(Oc3ccccc3)cc2o1", + "O=c1oc2ccccc2c(Cn2ccnc2)c1-c1ccccc1", + "COc1ccc2c(Cn3cncn3)cc(=O)oc2c1") + params = RGroupDecompositionParameters() + rgd = RGroupDecomposition(core,params) + for smi in smiles: + m = Chem.MolFromSmiles(smi) + rgd.Add(m) + rgd.Process() + columns = rgd.GetRGroupsAsColumns() + self.assertEqual(columns['R2'][0].GetNumAtoms(),12) + + params.SetRemoveHydrogensPostMatch(True) + rgd = RGroupDecomposition(core,params) + for smi in smiles: + m = Chem.MolFromSmiles(smi) + rgd.Add(m) + rgd.Process() + columns = rgd.GetRGroupsAsColumns() + self.assertEqual(columns['R2'][0].GetNumAtoms(),7) + + if __name__ == '__main__': unittest.main() diff --git a/Code/GraphMol/RGroupDecomposition/testRGroupDecomp.cpp b/Code/GraphMol/RGroupDecomposition/testRGroupDecomp.cpp index 0bb99060c..515bb754e 100644 --- a/Code/GraphMol/RGroupDecomposition/testRGroupDecomp.cpp +++ b/Code/GraphMol/RGroupDecomposition/testRGroupDecomp.cpp @@ -312,18 +312,101 @@ void testMultiCore() { } } +void testGithub1550() { + BOOST_LOG(rdInfoLog) + << "********************************************************\n"; + BOOST_LOG(rdInfoLog) + << "test Github #1550: Kekulization error from R-group decomposition" + << std::endl; + + RWMol *core = SmilesToMol("O=c1oc2ccccc2cc1"); + RGroupDecompositionParameters params; + + RGroupDecomposition decomp(*core, params); + const char *smilesData[3] = {"O=c1cc(Cn2ccnc2)c2ccc(Oc3ccccc3)cc2o1", + "O=c1oc2ccccc2c(Cn2ccnc2)c1-c1ccccc1", + "COc1ccc2c(Cn3cncn3)cc(=O)oc2c1"}; + for (int i = 0; i < 3; ++i) { + ROMol *mol = SmilesToMol(smilesData[i]); + int res = decomp.add(*mol); + delete mol; + TEST_ASSERT(res == i); + } + + decomp.process(); + RGroupColumns groups = decomp.getRGroupsAsColumns(); + RWMol *coreRes = (RWMol *)groups["Core"][0].get(); + TEST_ASSERT(coreRes->getNumAtoms() == 14); + MolOps::Kekulize(*coreRes); + RWMol *rg2 = (RWMol *)groups["R2"][0].get(); + TEST_ASSERT(rg2->getNumAtoms() == 12); + MolOps::Kekulize(*rg2); +} + +void testRemoveHs() { + BOOST_LOG(rdInfoLog) + << "********************************************************\n"; + BOOST_LOG(rdInfoLog) << "test remove sidechain Hs" << std::endl; + + RWMol *core = SmilesToMol("O=c1oc2ccccc2cc1"); + + { + RGroupDecompositionParameters params; + RGroupDecomposition decomp(*core, params); + const char *smilesData[3] = {"O=c1cc(Cn2ccnc2)c2ccc(Oc3ccccc3)cc2o1", + "O=c1oc2ccccc2c(Cn2ccnc2)c1-c1ccccc1", + "COc1ccc2c(Cn3cncn3)cc(=O)oc2c1"}; + for (int i = 0; i < 3; ++i) { + ROMol *mol = SmilesToMol(smilesData[i]); + int res = decomp.add(*mol); + delete mol; + TEST_ASSERT(res == i); + } + + decomp.process(); + RGroupColumns groups = decomp.getRGroupsAsColumns(); + RWMol *rg2 = (RWMol *)groups["R2"][0].get(); + TEST_ASSERT(rg2->getNumAtoms() == 12); + } + { + RGroupDecompositionParameters params; + params.removeHydrogensPostMatch = true; + RGroupDecomposition decomp(*core, params); + const char *smilesData[3] = {"O=c1cc(Cn2ccnc2)c2ccc(Oc3ccccc3)cc2o1", + "O=c1oc2ccccc2c(Cn2ccnc2)c1-c1ccccc1", + "COc1ccc2c(Cn3cncn3)cc(=O)oc2c1"}; + for (int i = 0; i < 3; ++i) { + ROMol *mol = SmilesToMol(smilesData[i]); + int res = decomp.add(*mol); + delete mol; + TEST_ASSERT(res == i); + } + + decomp.process(); + RGroupColumns groups = decomp.getRGroupsAsColumns(); + RWMol *rg2 = (RWMol *)groups["R2"][0].get(); + TEST_ASSERT(rg2->getNumAtoms() == 7); + } +} + int main() { RDLog::InitLogs(); BOOST_LOG(rdInfoLog) << "********************************************************\n"; - BOOST_LOG(rdInfoLog) << "Testing Chemical Transforms \n"; - + BOOST_LOG(rdInfoLog) << "Testing R-Group Decomposition \n"; +#if 1 testSymmetryMatching(); testRGroupOnlyMatching(); testRingMatching(); testRingMatching2(); testRingMatching3(); testMultiCore(); +#endif + testGithub1550(); + testRemoveHs(); + + BOOST_LOG(rdInfoLog) + << "********************************************************\n"; return 0; } From 83691e4f16459e85426fcfa9f1a4bacbe4e94d4d Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Fri, 8 Sep 2017 18:10:07 +0200 Subject: [PATCH 06/44] Fixes #1281 in a way (#1553) This actually just causes the molecule processing to fail in a reasonable amount of time; it is not an actual fix to the underlying ring-finding problem --- Code/GraphMol/FindRings.cpp | 29 +++++++++++++++++++----- Code/GraphMol/molopstest.cpp | 44 ++++++++++++++++++++++++++++++++++-- 2 files changed, 65 insertions(+), 8 deletions(-) diff --git a/Code/GraphMol/FindRings.cpp b/Code/GraphMol/FindRings.cpp index d3ea36175..8c5d7d4a3 100644 --- a/Code/GraphMol/FindRings.cpp +++ b/Code/GraphMol/FindRings.cpp @@ -26,6 +26,8 @@ typedef RINGINVAR_SET::const_iterator RINGINVAR_SET_CI; typedef std::vector RINGINVAR_VECT; namespace RingUtils { +const size_t MAX_BFSQ_SIZE = 200000; // arbitrary huge value + using namespace RDKit; boost::uint32_t computeRingInvariant(INT_VECT ring, unsigned int nAtoms) { @@ -645,6 +647,14 @@ int smallestRingsBfs(const ROMol &mol, int root, VECT_INT_VECT &rings, int curr = -1; unsigned int curSize = UINT_MAX; while (bfsq.size() > 0) { + if (bfsq.size() >= RingUtils::MAX_BFSQ_SIZE) { + std::string msg = + "Maximum BFS search size exceeded.\nThis is likely due to a highly " + "symmetric fused ring system."; + BOOST_LOG(rdErrorLog) << msg << std::endl; + throw ValueErrorException(msg); + } + curr = bfsq.front(); bfsq.pop_front(); @@ -737,6 +747,13 @@ bool _atomSearchBFS(const ROMol &tMol, unsigned int startAtomIdx, tv.push_back(startAtomIdx); bfsq.push_back(tv); while (!bfsq.empty()) { + if (bfsq.size() >= RingUtils::MAX_BFSQ_SIZE) { + std::string msg = + "Maximum BFS search size exceeded.\nThis is likely due to a highly " + "symmetric fused ring system."; + BOOST_LOG(rdErrorLog) << msg << std::endl; + throw ValueErrorException(msg); + } tv = bfsq.front(); bfsq.pop_front(); @@ -884,8 +901,7 @@ int findSSSR(const ROMol &mol, VECT_INT_VECT &res) { VECT_INT_VECT fragRes; curFrag = frags[fi]; - if (curFrag.size() < 3) - continue; + if (curFrag.size() < 3) continue; // the following is the list of atoms that are useful in the next round of // trimming @@ -907,13 +923,14 @@ int findSSSR(const ROMol &mol, VECT_INT_VECT &res) { } // check to see if this fragment can even have a possible ring - CHECK_INVARIANT(bndcnt_with_zero_order_bonds % 2 == 0, "fragment graph has a dangling degree"); + CHECK_INVARIANT(bndcnt_with_zero_order_bonds % 2 == 0, + "fragment graph has a dangling degree"); bndcnt_with_zero_order_bonds = bndcnt_with_zero_order_bonds / 2; int num_possible_rings = bndcnt_with_zero_order_bonds - curFrag.size() + 1; - if (num_possible_rings < 1) - continue; + if (num_possible_rings < 1) continue; - CHECK_INVARIANT(nbnds % 2 == 0, "fragment graph problem when including zero-order bonds"); + CHECK_INVARIANT(nbnds % 2 == 0, + "fragment graph problem when including zero-order bonds"); nbnds = nbnds / 2; boost::dynamic_bitset<> doneAts(nats); diff --git a/Code/GraphMol/molopstest.cpp b/Code/GraphMol/molopstest.cpp index 4d2cbc2a1..fe3e19bd6 100644 --- a/Code/GraphMol/molopstest.cpp +++ b/Code/GraphMol/molopstest.cpp @@ -6830,6 +6830,46 @@ void testGithub1439() { BOOST_LOG(rdInfoLog) << "Finished" << std::endl; } +void testGithub1281() { + BOOST_LOG(rdInfoLog) + << "-----------------------\n Testing github issue 1281: " << std::endl + << "RDKit gets stuck on PubChem CID 102128817" << std::endl; + { // basics + std::string smiles = + "COC1=CC=C(C=C1)C2C3=C(C=CC4=CC=CC=C43)OC5=CC6=C(C=C5)C7=NC8=C9C=CC1=" + "CC9=C(N8)N=C3C4=C5C=CC(=C4)OC4=C(C(C8=C(C=CC9=CC=CC=C98)OC8=CC9=C(C=" + "C8)C8=NC9=NC9=C%10C=C(C=CC%10=C(N9)N=C9C%10=C(C=C(C=C%10)OC%10=C2C2=" + "CC=CC=C2C=C%10)C(=N9)NC2=NC(=N8)C8=C2C=C(C=C8)OC2=C(C(C8=C(C=CC9=CC=" + "CC=C98)OC8=CC9=C(C=C8)C(=NC5=N3)N=C9NC6=N7)C3=CC=C(C=C3)OC)C3=CC=CC=" + "C3C=C2)OC2=C(C(C3=C(O1)C=CC1=CC=CC=C13)C1=CC=C(C=C1)OC)C1=CC=CC=C1C=" + "C2)C1=CC=C(C=C1)OC)C1=CC=CC=C1C=C4"; + { + RWMol *m = SmilesToMol(smiles, 0, false); + TEST_ASSERT(m); + TEST_ASSERT(m->getNumAtoms() == 204); + TEST_ASSERT(m->getNumBonds() == 244); + bool ok = false; + try { + MolOps::findSSSR(*m); + } catch (const ValueErrorException &) { + ok = true; + } + TEST_ASSERT(ok); + delete m; + } + { + bool ok = false; + try { + RWMol *m = SmilesToMol(smiles); + } catch (const ValueErrorException &) { + ok = true; + } + TEST_ASSERT(ok); + } + } + BOOST_LOG(rdInfoLog) << "Finished" << std::endl; +} + int main() { RDLog::InitLogs(); // boost::logging::enable_logs("rdApp.debug"); @@ -6927,11 +6967,11 @@ int main() { testGithubIssue1204(); testPotentialStereoBonds(); testSetBondStereo(); -#endif testBondSetStereoAtoms(); testGithub1478(); testGithub1439(); - +#endif + testGithub1281(); return 0; } From 769e6648e48a8a29f12d1fe10dfbb9f03aeb33c6 Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Mon, 11 Sep 2017 14:34:25 +0200 Subject: [PATCH 07/44] Fixes #1489 (#1556) * move the describeQuery functions to the RDKit namespace. They are generally useful * Fixes #1489 --- Code/GraphMol/QueryAtom.h | 23 +++++ Code/GraphMol/QueryBond.h | 23 +++++ Code/GraphMol/SmilesParse/SmilesParseOps.cpp | 50 +++++++++-- Code/GraphMol/Substruct/SubstructMatch.h | 4 +- Code/GraphMol/Substruct/SubstructUtils.cpp | 9 +- Code/GraphMol/Substruct/test1.cpp | 94 +++++++++++++++++++- Code/GraphMol/Wrap/Atom.cpp | 25 +----- Code/GraphMol/Wrap/Bond.cpp | 29 +----- 8 files changed, 193 insertions(+), 64 deletions(-) diff --git a/Code/GraphMol/QueryAtom.h b/Code/GraphMol/QueryAtom.h index 4e82dd90b..c35d583da 100644 --- a/Code/GraphMol/QueryAtom.h +++ b/Code/GraphMol/QueryAtom.h @@ -78,6 +78,29 @@ class QueryAtom : public Atom { }; // end o' class +namespace detail { +inline std::string qhelper(Atom::QUERYATOM_QUERY *q, unsigned int depth) { + std::string res = ""; + if (q) { + for (unsigned int i = 0; i < depth; ++i) res += " "; + res += q->getFullDescription() + "\n"; + for (Atom::QUERYATOM_QUERY::CHILD_VECT_CI ci = q->beginChildren(); + ci != q->endChildren(); ++ci) { + res += qhelper((*ci).get(), depth + 1); + } + } + return res; +} +} // end of detail namespace +inline std::string describeQuery(const Atom *atom) { + PRECONDITION(atom, "bad atom"); + std::string res = ""; + if (atom->hasQuery()) { + res = detail::qhelper(atom->getQuery(), 0); + } + return res; +} + }; // end o' namespace #endif diff --git a/Code/GraphMol/QueryBond.h b/Code/GraphMol/QueryBond.h index f24302b9e..fbbe0d2b8 100644 --- a/Code/GraphMol/QueryBond.h +++ b/Code/GraphMol/QueryBond.h @@ -91,6 +91,29 @@ class QueryBond : public Bond { protected: QUERYBOND_QUERY *dp_query; }; + +namespace detail { +inline std::string qhelper(Bond::QUERYBOND_QUERY *q, unsigned int depth) { + std::string res; + if (q) { + for (unsigned int i = 0; i < depth; ++i) res += " "; + res += q->getFullDescription() + "\n"; + for (Bond::QUERYBOND_QUERY::CHILD_VECT_CI ci = q->beginChildren(); + ci != q->endChildren(); ++ci) { + res += qhelper((*ci).get(), depth + 1); + } + } + return res; +} +} // end of detail namespace +inline std::string describeQuery(const Bond *bond) { + PRECONDITION(bond, "bad bond"); + std::string res = ""; + if (bond->hasQuery()) { + res = detail::qhelper(bond->getQuery(), 0); + } + return res; +} }; #endif diff --git a/Code/GraphMol/SmilesParse/SmilesParseOps.cpp b/Code/GraphMol/SmilesParse/SmilesParseOps.cpp index ce45cea1f..481b02d21 100644 --- a/Code/GraphMol/SmilesParse/SmilesParseOps.cpp +++ b/Code/GraphMol/SmilesParse/SmilesParseOps.cpp @@ -28,7 +28,7 @@ void CheckRingClosureBranchStatus(RDKit::Atom *atom, RDKit::RWMol *mp) { // and is currently degree two (protects against C1CN[C@](O)(N)1) if (atom->getIdx() != mp->getNumAtoms(true) - 1 && atom->getDegree() == 2 && (atom->getChiralTag() == Atom::CHI_TETRAHEDRAL_CW || - atom->getChiralTag() == Atom::CHI_TETRAHEDRAL_CCW) ) { + atom->getChiralTag() == Atom::CHI_TETRAHEDRAL_CCW)) { atom->invertChirality(); } } @@ -219,7 +219,7 @@ void _invChiralRingAtomWithHs(Atom *atom) { typedef std::pair SIZET_PAIR; typedef std::pair INT_PAIR; template -bool operator<(const std::pair &p1, const std::pair &p2) { +bool operator<(const std::pair &p1, const std::pair &p2) { return p1.first < p2.first; } namespace { @@ -233,7 +233,43 @@ bool isUnsaturated(const Atom *atom, const RWMol *mol) { } return false; } + +bool hasSingleHQuery(const Atom::QUERYATOM_QUERY *q) { + // list queries are series of nested ors of AtomAtomicNum queries + PRECONDITION(q, "bad query"); + bool res = false; + std::string descr = q->getDescription(); + if (descr == "AtomAnd") { + for (Atom::QUERYATOM_QUERY::CHILD_VECT_CI cIt = q->beginChildren(); + cIt != q->endChildren(); ++cIt) { + std::string descr = (*cIt)->getDescription(); + if (descr == "AtomHCount") { + if (!(*cIt)->getNegation() && + ((ATOM_EQUALS_QUERY *)(*cIt).get())->getVal() == 1) { + return true; + } + return false; + } else if (descr == "AtomAnd") { + res = hasSingleHQuery((*cIt).get()); + if (res) return true; + } + } + } + return res; } + +bool atomHasExplicitHs(const Atom *atom) { + if (atom->getNumExplicitHs()) return true; + if (atom->hasQuery()) { + // the SMARTS [C@@H] produces an atom with a H query, but we also + // need to treat this like an explicit H for chirality purposes + // This was Github #1489 + bool res = hasSingleHQuery(atom->getQuery()); + return res; + } + return false; +} +} // end of anonymous namespace void AdjustAtomChiralityFlags(RWMol *mol) { PRECONDITION(mol, "no molecule"); for (RWMol::AtomIterator atomIt = mol->beginAtoms(); @@ -253,10 +289,10 @@ void AdjustAtomChiralityFlags(RWMol *mol) { ringClosures); #if 0 - std::cout << "CLOSURES: "; - std::copy(ringClosures.begin(),ringClosures.end(), - std::ostream_iterator(std::cout," ")); - std::cout << std::endl; + std::cout << "CLOSURES: "; + std::copy(ringClosures.begin(), ringClosures.end(), + std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; #endif std::list neighbors; // push this atom onto the list of neighbors (we'll use this @@ -333,7 +369,7 @@ void AdjustAtomChiralityFlags(RWMol *mol) { if ((*atomIt)->getDegree() == 3 && (((*atomIt)->getNumExplicitHs() && (*atomIt)->hasProp(common_properties::_SmilesStart)) || - (!(*atomIt)->getNumExplicitHs() && ringClosures.size() == 1 && + (!atomHasExplicitHs(*atomIt) && ringClosures.size() == 1 && !isUnsaturated(*atomIt, mol)))) { ++nSwaps; } diff --git a/Code/GraphMol/Substruct/SubstructMatch.h b/Code/GraphMol/Substruct/SubstructMatch.h index 433b3bc0a..9bb7c55d3 100644 --- a/Code/GraphMol/Substruct/SubstructMatch.h +++ b/Code/GraphMol/Substruct/SubstructMatch.h @@ -7,8 +7,8 @@ // which is included in the file license.txt, found at the root // of the RDKit source tree. // -#ifndef _RD_SUBSTRUCTMATCH_H__ -#define _RD_SUBSTRUCTMATCH_H__ +#ifndef RD_SUBSTRUCTMATCH_H +#define RD_SUBSTRUCTMATCH_H // std bits #include diff --git a/Code/GraphMol/Substruct/SubstructUtils.cpp b/Code/GraphMol/Substruct/SubstructUtils.cpp index 4d05abf10..a6469ccab 100644 --- a/Code/GraphMol/Substruct/SubstructUtils.cpp +++ b/Code/GraphMol/Substruct/SubstructUtils.cpp @@ -30,13 +30,15 @@ bool atomCompat(const ATOM_SPTR &a1, const ATOM_SPTR &a2, res = a1->Match(a2); } return res; + std::cerr << "\t\tatomCompat: " << a1 << " " << a1->getIdx() << "-" << a2 + << " " << a2->getIdx() << std::endl; + std::cerr << "\t\t " << res << std::endl; + return res; } bool chiralAtomCompat(const ATOM_SPTR &a1, const ATOM_SPTR &a2) { PRECONDITION(a1, "bad atom"); PRECONDITION(a2, "bad atom"); - // std::cerr << "\t\tatomCompat: "<< a1 << " " << a1->getIdx() << "-" << a2 << - // " " << a2->getIdx() << std::endl; bool res = a1->Match(a2); if (res) { std::string s1, s2; @@ -46,6 +48,9 @@ bool chiralAtomCompat(const ATOM_SPTR &a1, const ATOM_SPTR &a2) { res = hascode1 && hascode2 && s1 == s2; } } + std::cerr << "\t\tchiralAtomCompat: " << a1 << " " << a1->getIdx() << "-" + << a2 << " " << a2->getIdx() << std::endl; + std::cerr << "\t\t " << res << std::endl; return res; } diff --git a/Code/GraphMol/Substruct/test1.cpp b/Code/GraphMol/Substruct/test1.cpp index 1168730f0..c3333a442 100644 --- a/Code/GraphMol/Substruct/test1.cpp +++ b/Code/GraphMol/Substruct/test1.cpp @@ -1361,6 +1361,96 @@ void testDativeMatch() { BOOST_LOG(rdErrorLog) << " done" << std::endl; } +void testGithubIssue1489() { + BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; + BOOST_LOG(rdErrorLog) << " Testing Github #1389: Substructure matching " + "with chirality failure when query is built from " + "SMARTS" + << std::endl; +#if 1 + { + std::string smi1 = "CCC[C@@H]1CN(CCC)CCN1"; + std::string smi2 = "CCC[C@H]1CN(CCC)CCN1"; + ROMol *mol1 = SmilesToMol(smi1); + TEST_ASSERT(mol1); + ROMol *mol2 = SmilesToMol(smi2); + TEST_ASSERT(mol2); + + bool recursionPossible = true; + bool useChirality = true; + + MatchVectType match; + // make sure self-matches work + TEST_ASSERT( + SubstructMatch(*mol1, *mol1, match, recursionPossible, useChirality)); + TEST_ASSERT( + SubstructMatch(*mol2, *mol2, match, recursionPossible, useChirality)); + + // check matches using the molecules from smiles: + TEST_ASSERT( + !SubstructMatch(*mol1, *mol2, match, recursionPossible, useChirality)); + TEST_ASSERT(SubstructMatch(*mol1, *mol2, match, recursionPossible, false)); + + { + ROMol *qmol1 = SmartsToMol(smi1); + + qmol1->updatePropertyCache(); + TEST_ASSERT(qmol1); + TEST_ASSERT( + SubstructMatch(*mol1, *qmol1, match, recursionPossible, false)); + TEST_ASSERT(SubstructMatch(*mol1, *qmol1, match, recursionPossible, + useChirality)); + TEST_ASSERT( + SubstructMatch(*mol2, *qmol1, match, recursionPossible, false)); + TEST_ASSERT(!SubstructMatch(*mol2, *qmol1, match, recursionPossible, + useChirality)); + delete qmol1; + } + delete mol1; + delete mol2; + } +#endif + { + std::string smi1 = "F([C@@H](Cl)Br)"; + ROMol *mol1 = SmilesToMol(smi1); + TEST_ASSERT(mol1); + + bool recursionPossible = true; + bool useChirality = true; + + MatchVectType match; + // make sure self-matches work + TEST_ASSERT( + SubstructMatch(*mol1, *mol1, match, recursionPossible, useChirality)); + { + ROMol *qmol1 = SmartsToMol(smi1); + + qmol1->updatePropertyCache(); + TEST_ASSERT(qmol1); + TEST_ASSERT( + SubstructMatch(*mol1, *qmol1, match, recursionPossible, false)); + TEST_ASSERT(SubstructMatch(*mol1, *qmol1, match, recursionPossible, + useChirality)); + delete qmol1; + } + { + std::string smi2 = "F([C@H](Br)Cl)"; + ROMol *qmol1 = SmartsToMol(smi2); + + qmol1->updatePropertyCache(); + TEST_ASSERT(qmol1); + TEST_ASSERT( + SubstructMatch(*mol1, *qmol1, match, recursionPossible, false)); + TEST_ASSERT(SubstructMatch(*mol1, *qmol1, match, recursionPossible, + useChirality)); + delete qmol1; + } + delete mol1; + } + + BOOST_LOG(rdErrorLog) << " done" << std::endl; +} + int main(int argc, char *argv[]) { #if 1 test1(); @@ -1380,8 +1470,8 @@ int main(int argc, char *argv[]) { testGitHubIssue688(); testDativeMatch(); testCisTransMatch(); - -#endif testCisTransMatch2(); +#endif + testGithubIssue1489(); return 0; } diff --git a/Code/GraphMol/Wrap/Atom.cpp b/Code/GraphMol/Wrap/Atom.cpp index 79d4e2d67..b405dafb5 100644 --- a/Code/GraphMol/Wrap/Atom.cpp +++ b/Code/GraphMol/Wrap/Atom.cpp @@ -1,6 +1,5 @@ -// $Id$ // -// Copyright (C) 2003-2013 Greg Landrum and Rational Discovery LLC +// Copyright (C) 2003-2017 Greg Landrum and Rational Discovery LLC // // @@ All Rights Reserved @@ // This file is part of the RDKit. @@ -28,27 +27,7 @@ namespace python = boost::python; namespace RDKit { -namespace { -std::string qhelper(Atom::QUERYATOM_QUERY *q, unsigned int depth) { - std::string res = ""; - if (q) { - for (unsigned int i = 0; i < depth; ++i) res += " "; - res += q->getFullDescription() + "\n"; - for (Atom::QUERYATOM_QUERY::CHILD_VECT_CI ci = q->beginChildren(); - ci != q->endChildren(); ++ci) { - res += qhelper((*ci).get(), depth + 1); - } - } - return res; -} -} // end of local namespace -std::string describeQuery(const Atom *atom) { - std::string res = ""; - if (atom->hasQuery()) { - res = qhelper(atom->getQuery(), 0); - } - return res; -} + void expandQuery(QueryAtom *self, const QueryAtom *other, Queries::CompositeQueryType how, bool maintainOrder) { if (other->hasQuery()) { diff --git a/Code/GraphMol/Wrap/Bond.cpp b/Code/GraphMol/Wrap/Bond.cpp index 2b857145c..4e8fac231 100644 --- a/Code/GraphMol/Wrap/Bond.cpp +++ b/Code/GraphMol/Wrap/Bond.cpp @@ -1,6 +1,5 @@ -// $Id$ // -// Copyright (C) 2003-2014 Rational Discovery LLC +// Copyright (C) 2003-2017 Rational Discovery LLC // // @@ All Rights Reserved @@ // This file is part of the RDKit. @@ -23,32 +22,6 @@ namespace python = boost::python; namespace RDKit { -namespace { -std::string qhelper(Bond::QUERYBOND_QUERY *q, unsigned int depth) { - std::ostringstream res; - - if (q) { - for (unsigned int i = 0; i < depth; ++i) res << " "; - res << q->getFullDescription(); - if (q->getNegation()) res << " ! "; - - res << "\n"; - for (Bond::QUERYBOND_QUERY::CHILD_VECT_CI ci = q->beginChildren(); - ci != q->endChildren(); ++ci) { - res << qhelper((*ci).get(), depth + 1); - } - } - return res.str(); -} -} // end of local namespace -std::string describeQuery(const Bond *bond) { - std::string res = ""; - if (bond->hasQuery()) { - res = qhelper(bond->getQuery(), 0); - } - return res; -} - void expandQuery(QueryBond *self, const QueryBond *other, Queries::CompositeQueryType how, bool maintainOrder) { if (other->hasQuery()) { From 64399a46f0f28b1ee4ec763afb2d10224e617a21 Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Mon, 11 Sep 2017 14:37:32 +0200 Subject: [PATCH 08/44] Fixes github1497 (#1555) * move detectBondStereoChemistry() into MolOps * switch more code over to using the new function * add an addStereoChemistryFrom3D() function. Needs testing still. * add some tests * cleanups and rename --- Code/GraphMol/Chirality.cpp | 454 ++++++++++++++++++ Code/GraphMol/FileParsers/Mol2FileParser.cpp | 12 +- Code/GraphMol/FileParsers/MolFileParser.cpp | 12 +- .../FileParsers/MolFileStereochem.cpp | 448 +---------------- Code/GraphMol/FileParsers/MolFileStereochem.h | 8 +- Code/GraphMol/MolOps.h | 28 +- .../StructChecker/StripSmallFragments.cpp | 60 +-- Code/GraphMol/Wrap/MolOps.cpp | 14 +- Code/GraphMol/testChirality.cpp | 58 +++ Code/GraphMol/test_data/stereochem.sdf | 92 ++++ rdkit/Chem/UnitTestMol3D.py | 2 +- 11 files changed, 692 insertions(+), 496 deletions(-) create mode 100644 Code/GraphMol/test_data/stereochem.sdf diff --git a/Code/GraphMol/Chirality.cpp b/Code/GraphMol/Chirality.cpp index 40f037651..e1de81abc 100644 --- a/Code/GraphMol/Chirality.cpp +++ b/Code/GraphMol/Chirality.cpp @@ -1336,6 +1336,460 @@ void assignChiralTypesFrom3D(ROMol &mol, int confId, bool replaceExistingTags) { } } +namespace { + +void setBondDirRelativeToAtom(Bond *bond, Atom *atom, Bond::BondDir dir, + bool reverse, boost::dynamic_bitset<> &needsDir) { + PRECONDITION(bond, "bad bond"); + PRECONDITION(atom, "bad atom"); + PRECONDITION(dir == Bond::ENDUPRIGHT || dir == Bond::ENDDOWNRIGHT, "bad dir"); + PRECONDITION(atom == bond->getBeginAtom() || atom == bond->getEndAtom(), + "atom doesn't belong to bond"); + // std::cerr << "\t\t>sbdra : bond " << bond->getIdx() << " atom " + // << atom->getIdx() << " dir : " << dir << " reverse: " << reverse + // << std::endl; + Atom *oAtom; + if (bond->getBeginAtom() != atom) { + reverse = !reverse; + oAtom = bond->getBeginAtom(); + } else { + oAtom = bond->getEndAtom(); + } + if (reverse) { + dir = (dir == Bond::ENDUPRIGHT ? Bond::ENDDOWNRIGHT : Bond::ENDUPRIGHT); + } + // to ensure maximum compatibility, even when a bond has unknown stereo (set + // explicitly and recorded in _UnknownStereo property), I will still let a + // direction to be computed. You must check the _UnknownStereo property to + // make sure whether this bond is explictly set to have no direction info. + // This makes sense because the direction info are all derived from + // coordinates, the _UnknownStereo property is like extra metadata to be + // used with the direction info. + bond->setBondDir(dir); + // std::cerr<<"\t\t\t\t -> dir "<getOwningMol().getAtomBonds(oAtom); + while (beg != end) { + Bond *nbrBond = oAtom->getOwningMol()[*beg].get(); + ++beg; + if (nbrBond != bond && nbrBond->getBondType() != Bond::DOUBLE && + needsDir[nbrBond->getIdx()]) { + Bond::BondDir nbrDir = Bond::NONE; + if ((nbrBond->getBeginAtom() == oAtom && bond->getBeginAtom() == oAtom) || + (nbrBond->getEndAtom() == oAtom && bond->getEndAtom() == oAtom)) { + // both bonds either start or end here; they *must* have different + // directions: + nbrDir = + (dir == Bond::ENDUPRIGHT ? Bond::ENDDOWNRIGHT : Bond::ENDUPRIGHT); + } else { + // one starts here, the other ends here, they need to have the same + // direction: + nbrDir = dir; + } + nbrBond->setBondDir(nbrDir); + needsDir[nbrBond->getIdx()] = 0; + // std::cerr << "\t\t\t\t update bond " << nbrBond->getIdx() << " to dir " + // << nbrDir << std::endl; + } + } +} + +bool isLinearArrangement(const RDGeom::Point3D &v1, const RDGeom::Point3D &v2, + double tol = 0.035) { // tolerance of 2 degrees + return fabs(v2.angleTo(v1) - M_PI) < tol; +} +void updateDoubleBondNeighbors(ROMol &mol, Bond *dblBond, const Conformer &conf, + boost::dynamic_bitset<> &needsDir, + std::vector &singleBondCounts, + const VECT_INT_VECT &singleBondNbrs) { + // we want to deal only with double bonds: + PRECONDITION(dblBond, "bad bond"); + PRECONDITION(dblBond->getBondType() == Bond::DOUBLE, "not a double bond"); + if (!needsDir[dblBond->getIdx()]) return; + needsDir.set(dblBond->getIdx(), 0); +#if 0 + std::cerr << "**********************\n"; + std::cerr << "**********************\n"; + std::cerr << "**********************\n"; + std::cerr << "UDBN: " << dblBond->getIdx() << " " + << dblBond->getBeginAtomIdx() << "=" << dblBond->getEndAtomIdx() + << "\n"; +#endif + + ROMol::OEDGE_ITER beg, end; + std::vector followupBonds; + + Bond *bond1 = 0, *obond1 = 0; + bool squiggleBondSeen = false; + boost::tie(beg, end) = mol.getAtomBonds(dblBond->getBeginAtom()); + while (beg != end) { + Bond *tBond = mol[*beg].get(); + if (tBond->getBondType() == Bond::SINGLE || + tBond->getBondType() == Bond::AROMATIC) { + // prefer bonds that already have their directionality set + // or that are adjacent to more double bonds: + if (!bond1) { + bond1 = tBond; + } else if (needsDir[tBond->getIdx()]) { + if (singleBondCounts[tBond->getIdx()] > + singleBondCounts[bond1->getIdx()]) { + obond1 = bond1; + bond1 = tBond; + } else { + obond1 = tBond; + } + } else { + obond1 = bond1; + bond1 = tBond; + } + } + if (tBond->getBondType() == Bond::SINGLE && + tBond->getBondDir() == Bond::UNKNOWN) { + squiggleBondSeen = true; + break; + } + + ++beg; + } + // Don't do any direction setting if we've seen a squiggle bond, but do mark + // the double bond as a crossed bond and return + if (!bond1 || squiggleBondSeen) { + dblBond->setBondDir(Bond::EITHERDOUBLE); + return; + } + + Bond *bond2 = 0, *obond2 = 0; + boost::tie(beg, end) = mol.getAtomBonds(dblBond->getEndAtom()); + while (beg != end) { + Bond *tBond = mol[*beg].get(); + if (tBond->getBondType() == Bond::SINGLE || + tBond->getBondType() == Bond::AROMATIC) { + if (!bond2) { + bond2 = tBond; + } else if (needsDir[tBond->getIdx()]) { + if (singleBondCounts[tBond->getIdx()] > + singleBondCounts[bond2->getIdx()]) { + obond2 = bond2; + bond2 = tBond; + } else { + obond2 = tBond; + } + } else { + // we already had a bond2 and we don't need to set the direction + // on the new one, so swap. + obond2 = bond2; + bond2 = tBond; + } + } + if (tBond->getBondType() == Bond::SINGLE && + tBond->getBondDir() == Bond::UNKNOWN) { + squiggleBondSeen = true; + break; + } + + ++beg; + } + // Don't do any direction setting if we've seen a squiggle bond, but do mark + // the double bond as a crossed bond and return + if (!bond2 || squiggleBondSeen) { + dblBond->setBondDir(Bond::EITHERDOUBLE); + return; + } + + CHECK_INVARIANT(bond1 && bond2, "no bonds found"); + RDGeom::Point3D beginP = conf.getAtomPos(dblBond->getBeginAtomIdx()); + RDGeom::Point3D endP = conf.getAtomPos(dblBond->getEndAtomIdx()); + RDGeom::Point3D bond1P = + conf.getAtomPos(bond1->getOtherAtomIdx(dblBond->getBeginAtomIdx())); + RDGeom::Point3D bond2P = + conf.getAtomPos(bond2->getOtherAtomIdx(dblBond->getEndAtomIdx())); + // check for a linear arrangement of atoms on either end: + bool linear = false; + RDGeom::Point3D p1; + RDGeom::Point3D p2; + p1 = bond1P - beginP; + p2 = endP - beginP; + if (isLinearArrangement(p1, p2)) { + if (!obond1) { + linear = true; + } else { + // one of the bonds was linear; what about the other one? + Bond *tBond = bond1; + bond1 = obond1; + obond1 = tBond; + bond1P = + conf.getAtomPos(bond1->getOtherAtomIdx(dblBond->getBeginAtomIdx())); + p1 = bond1P - beginP; + if (isLinearArrangement(p1, p2)) { + linear = true; + } + } + } + if (!linear) { + p1 = bond2P - endP; + p2 = beginP - endP; + if (isLinearArrangement(p1, p2)) { + if (!obond2) { + linear = true; + } else { + Bond *tBond = bond2; + bond2 = obond2; + obond2 = tBond; + bond2P = + conf.getAtomPos(bond2->getOtherAtomIdx(dblBond->getEndAtomIdx())); + p1 = bond2P - beginP; + if (isLinearArrangement(p1, p2)) { + linear = true; + } + } + } + } + if (linear) { + dblBond->setBondDir(Bond::EITHERDOUBLE); + return; + } + + double ang = RDGeom::computeDihedralAngle(bond1P, beginP, endP, bond2P); + bool sameTorsionDir; + if (ang < M_PI / 2) { + sameTorsionDir = false; + } else { + sameTorsionDir = true; + } + // std::cerr << " angle: " << ang << " sameTorsionDir: " << sameTorsionDir + // << "\n"; + + /* + Time for some clarificatory text, because this gets really + confusing really fast. + + The dihedral angle analysis above is based on viewing things + with an atom order as follows: + + 1 + \ + 2 = 3 + \ + 4 + + so dihedrals > 90 correspond to sameDir=true + + however, the stereochemistry representation is + based on something more like this: + + 2 + \ + 1 = 3 + \ + 4 + (i.e. we consider the direction-setting single bonds to be + starting at the double-bonded atom) + + */ + bool reverseBondDir = sameTorsionDir; + + Atom *atom1 = dblBond->getBeginAtom(), *atom2 = dblBond->getEndAtom(); + if (needsDir[bond1->getIdx()]) { + BOOST_FOREACH (int bidx, singleBondNbrs[bond1->getIdx()]) { + // std::cerr << " neighbor from: " << bond1->getIdx() << " " << bidx + // << ": " << needsDir[bidx] << std::endl; + if (needsDir[bidx]) followupBonds.push_back(mol.getBondWithIdx(bidx)); + } + } + if (needsDir[bond2->getIdx()]) { + BOOST_FOREACH (int bidx, singleBondNbrs[bond2->getIdx()]) { + // std::cerr << " neighbor from: " << bond2->getIdx() << " " << bidx + // << ": " << needsDir[bidx] << std::endl; + if (needsDir[bidx]) followupBonds.push_back(mol.getBondWithIdx(bidx)); + } + } + if (!needsDir[bond1->getIdx()]) { + if (!needsDir[bond2->getIdx()]) { + // check that we agree + } else { + if (bond1->getBeginAtom() != atom1) { + reverseBondDir = !reverseBondDir; + } + setBondDirRelativeToAtom(bond2, atom2, bond1->getBondDir(), + reverseBondDir, needsDir); + } + } else if (!needsDir[bond2->getIdx()]) { + if (bond2->getBeginAtom() != atom2) { + reverseBondDir = !reverseBondDir; + } + setBondDirRelativeToAtom(bond1, atom1, bond2->getBondDir(), reverseBondDir, + needsDir); + } else { + setBondDirRelativeToAtom(bond1, atom1, Bond::ENDDOWNRIGHT, false, needsDir); + setBondDirRelativeToAtom(bond2, atom2, Bond::ENDDOWNRIGHT, reverseBondDir, + needsDir); + } + needsDir[bond1->getIdx()] = 0; + needsDir[bond2->getIdx()] = 0; + if (obond1 && needsDir[obond1->getIdx()]) { + setBondDirRelativeToAtom(obond1, atom1, bond1->getBondDir(), + bond1->getBeginAtom() == atom1, needsDir); + needsDir[obond1->getIdx()] = 0; + } + if (obond2 && needsDir[obond2->getIdx()]) { + setBondDirRelativeToAtom(obond2, atom2, bond2->getBondDir(), + bond2->getBeginAtom() == atom2, needsDir); + needsDir[obond2->getIdx()] = 0; + } +#if 0 + std::cerr << " 1:" << bond1->getIdx() << " "; + if (obond1) + std::cerr << obond1->getIdx() << std::endl; + else + std::cerr << "N/A" << std::endl; + std::cerr << " 2:" << bond2->getIdx() << " "; + if (obond2) + std::cerr << obond2->getIdx() << std::endl; + else + std::cerr << "N/A" << std::endl; + std::cerr << "**********************\n"; + std::cerr << "**********************\n"; + std::cerr << "**********************\n"; +#endif + BOOST_FOREACH (Bond *oDblBond, followupBonds) { + // std::cerr << "FOLLOWUP: " << oDblBond->getIdx() << " " + // << needsDir[oDblBond->getIdx()] << std::endl; + updateDoubleBondNeighbors(mol, oDblBond, conf, needsDir, singleBondCounts, + singleBondNbrs); + } +} + +} // end of anonymous namespace + +void detectBondStereochemistry(ROMol &mol, int confId) { + if (!mol.getNumConformers()) return; + const Conformer &conf = mol.getConformer(confId); + + // used to store the number of single bonds a given + // single bond is adjacent to + std::vector singleBondCounts(mol.getNumBonds(), 0); + std::vector bondsInPlay; + // keeps track of which single bonds are adjacent to each double bond: + VECT_INT_VECT dblBondNbrs(mol.getNumBonds()); + // keeps track of which double bonds are adjacent to each single bond: + VECT_INT_VECT singleBondNbrs(mol.getNumBonds()); + // keeps track of which single bonds need a dir set and which double bonds + // need to have their neighbors' dirs set + boost::dynamic_bitset<> needsDir(mol.getNumBonds()); + + // find double bonds that should be considered for + // stereochemistry + // NOTE that we are explicitly excluding double bonds in rings + // with this test. + bool resetRings = false; + if (!mol.getRingInfo()->isInitialized()) { + resetRings = true; + MolOps::fastFindRings(mol); + } + + for (RWMol::BondIterator bondIt = mol.beginBonds(); bondIt != mol.endBonds(); + ++bondIt) { + if ((*bondIt)->getBondType() == Bond::DOUBLE && + (*bondIt)->getStereo() != Bond::STEREOANY && + (*bondIt)->getBondDir() != Bond::EITHERDOUBLE && + (*bondIt)->getBeginAtom()->getDegree() > 1 && + (*bondIt)->getEndAtom()->getDegree() > 1 && + !(mol.getRingInfo()->numBondRings((*bondIt)->getIdx()))) { + const Atom *a1 = (*bondIt)->getBeginAtom(); + const Atom *a2 = (*bondIt)->getEndAtom(); + + ROMol::OEDGE_ITER beg, end; + boost::tie(beg, end) = mol.getAtomBonds(a1); + while (beg != end) { + const Bond *nbrBond = mol[*beg].get(); + if (nbrBond->getBondType() == Bond::SINGLE || + nbrBond->getBondType() == Bond::AROMATIC) { + singleBondCounts[nbrBond->getIdx()] += 1; + needsDir[nbrBond->getIdx()] = 1; + needsDir[(*bondIt)->getIdx()] = 1; + dblBondNbrs[(*bondIt)->getIdx()].push_back(nbrBond->getIdx()); + // the search may seem inefficient, but these vectors are going to be + // at most 2 long (with very few exceptions). It's just not worth + // using a different data structure + if (std::find(singleBondNbrs[nbrBond->getIdx()].begin(), + singleBondNbrs[nbrBond->getIdx()].end(), + (*bondIt)->getIdx()) == + singleBondNbrs[nbrBond->getIdx()].end()) { + singleBondNbrs[nbrBond->getIdx()].push_back((*bondIt)->getIdx()); + } + } + ++beg; + } + boost::tie(beg, end) = mol.getAtomBonds(a2); + while (beg != end) { + const Bond *nbrBond = mol[*beg].get(); + if (nbrBond->getBondType() == Bond::SINGLE || + nbrBond->getBondType() == Bond::AROMATIC) { + singleBondCounts[nbrBond->getIdx()] += 1; + needsDir[nbrBond->getIdx()] = 1; + needsDir[(*bondIt)->getIdx()] = 1; + dblBondNbrs[(*bondIt)->getIdx()].push_back(nbrBond->getIdx()); + + // the search may seem inefficient, but these vectors are going to be + // at most 2 long (with very few exceptions). It's just not worth + // using a different data structure + if (std::find(singleBondNbrs[nbrBond->getIdx()].begin(), + singleBondNbrs[nbrBond->getIdx()].end(), + (*bondIt)->getIdx()) == + singleBondNbrs[nbrBond->getIdx()].end()) { + singleBondNbrs[nbrBond->getIdx()].push_back((*bondIt)->getIdx()); + } + } + ++beg; + } + bondsInPlay.push_back(*bondIt); + } + } + + if (!bondsInPlay.size()) { + if (resetRings) mol.getRingInfo()->reset(); + return; + } + + // order the double bonds based on the singleBondCounts of their neighbors: + std::vector > orderedBondsInPlay; + for (unsigned int i = 0; i < bondsInPlay.size(); ++i) { + Bond *dblBond = bondsInPlay[i]; + unsigned int countHere = + std::accumulate(dblBondNbrs[dblBond->getIdx()].begin(), + dblBondNbrs[dblBond->getIdx()].end(), 0); + // and favor double bonds that are *not* in rings. The combination of using + // the sum + // above (instead of the max) and this ring-membershipt test seem to fix + // sf.net issue 3009836 + if (!(mol.getRingInfo()->numBondRings(dblBond->getIdx()))) countHere *= 10; + orderedBondsInPlay.push_back(std::make_pair(countHere, dblBond)); + } + std::sort(orderedBondsInPlay.begin(), orderedBondsInPlay.end()); + + // oof, now loop over the double bonds in that order and + // update their neighbor directionalities: + std::vector >::reverse_iterator pairIter; + for (pairIter = orderedBondsInPlay.rbegin(); + pairIter != orderedBondsInPlay.rend(); ++pairIter) { + updateDoubleBondNeighbors(mol, pairIter->second, conf, needsDir, + singleBondCounts, singleBondNbrs); + } + if (resetRings) mol.getRingInfo()->reset(); +} + +void assignStereochemistryFrom3D(ROMol &mol, int confId, + bool replaceExistingTags) { + detectBondStereochemistry(mol, confId); + assignChiralTypesFrom3D(mol, confId, replaceExistingTags); + bool force = true; + bool flagPossibleStereoCenters = true; + assignStereochemistry(mol, replaceExistingTags, force, + flagPossibleStereoCenters); +} + void removeStereochemistry(ROMol &mol) { if (mol.hasProp(common_properties::_StereochemDone)) { mol.clearProp(common_properties::_StereochemDone); diff --git a/Code/GraphMol/FileParsers/Mol2FileParser.cpp b/Code/GraphMol/FileParsers/Mol2FileParser.cpp index 82ce34916..524c4256a 100644 --- a/Code/GraphMol/FileParsers/Mol2FileParser.cpp +++ b/Code/GraphMol/FileParsers/Mol2FileParser.cpp @@ -35,7 +35,6 @@ // #include "FileParsers.h" -#include "MolFileStereochem.h" #include #include #include @@ -205,7 +204,8 @@ void guessFormalCharges(RWMol *res) { res->getProp(common_properties::_Name, nm); BOOST_LOG(rdWarningLog) << nm << ": warning - aromatic N with 3 aromatic bonds - " - "skipping charge guess for this atom" << std::endl; + "skipping charge guess for this atom" + << std::endl; continue; } @@ -736,7 +736,8 @@ void ParseMol2AtomBlock(std::istream *inStream, RWMol *res, unsigned int nAtoms, res->getProp(common_properties::_Name, nm); BOOST_LOG(rdWarningLog) << nm << ": Warning - no explicit hydrogens in " "mol2 file but needed for formal charge " - "estimation." << std::endl; + "estimation." + << std::endl; } // create conformer based on 3DPoints and add to RWMol Conformer *conf = new Conformer(nAtoms - nLP); @@ -959,11 +960,10 @@ RWMol *Mol2DataStreamToMol(std::istream *inStream, bool sanitize, bool removeHs, MolOps::sanitizeMol(*res); } - // call DetectBondStereoChemistry after sanitization "because we need + // call detectBondStereochemistry after sanitization "because we need // the ring information". Also this will set the E/Z labels on the bond. // Similar in spirit to what happens in MolFileParser - const Conformer &conf = res->getConformer(); - DetectBondStereoChemistry(*res, &conf); + MolOps::detectBondStereochemistry(*res); } catch (MolSanitizeException &se) { BOOST_LOG(rdWarningLog) << "sanitise "; diff --git a/Code/GraphMol/FileParsers/MolFileParser.cpp b/Code/GraphMol/FileParsers/MolFileParser.cpp index fe137f1a3..f558bac97 100644 --- a/Code/GraphMol/FileParsers/MolFileParser.cpp +++ b/Code/GraphMol/FileParsers/MolFileParser.cpp @@ -1959,9 +1959,9 @@ void ParseV3000BondBlock(std::istream *inStream, unsigned int &line, bond->setIsAromatic(true); break; case 9: - bond = new Bond(Bond::DATIVE); - break; - case 0: + bond = new Bond(Bond::DATIVE); + break; + case 0: bond = new Bond(Bond::UNSPECIFIED); BOOST_LOG(rdWarningLog) << "bond with order 0 found on line " << line @@ -2549,9 +2549,9 @@ RWMol *MolDataStreamToMol(std::istream *inStream, unsigned int &line, // single bond dir flags: ClearSingleBondDirFlags(*res); - // unlike DetectAtomStereoChemistry we call DetectBondStereoChemistry + // unlike DetectAtomStereoChemistry we call detectBondStereochemistry // here after sanitization because we need the ring information: - DetectBondStereoChemistry(*res, &conf); + MolOps::detectBondStereochemistry(*res); } catch (...) { delete res; res = NULL; @@ -2561,7 +2561,7 @@ RWMol *MolDataStreamToMol(std::istream *inStream, unsigned int &line, } else { // we still need to do something about double bond stereochemistry // (was github issue 337) - DetectBondStereoChemistry(*res, &conf); + MolOps::detectBondStereochemistry(*res); } if (res->hasProp(common_properties::_NeedsQueryScan)) { diff --git a/Code/GraphMol/FileParsers/MolFileStereochem.cpp b/Code/GraphMol/FileParsers/MolFileStereochem.cpp index 5a8915230..54ac992ea 100644 --- a/Code/GraphMol/FileParsers/MolFileStereochem.cpp +++ b/Code/GraphMol/FileParsers/MolFileStereochem.cpp @@ -673,331 +673,6 @@ void DetectAtomStereoChemistry(RWMol &mol, const Conformer *conf) { } } -void setBondDirRelativeToAtom(Bond *bond, Atom *atom, Bond::BondDir dir, - bool reverse, boost::dynamic_bitset<> &needsDir) { - PRECONDITION(bond, "bad bond"); - PRECONDITION(atom, "bad atom"); - PRECONDITION(dir == Bond::ENDUPRIGHT || dir == Bond::ENDDOWNRIGHT, "bad dir"); - PRECONDITION(atom == bond->getBeginAtom() || atom == bond->getEndAtom(), - "atom doesn't belong to bond"); - // std::cerr << "\t\t>sbdra : bond " << bond->getIdx() << " atom " - // << atom->getIdx() << " dir : " << dir << " reverse: " << reverse - // << std::endl; - Atom *oAtom; - if (bond->getBeginAtom() != atom) { - reverse = !reverse; - oAtom = bond->getBeginAtom(); - } else { - oAtom = bond->getEndAtom(); - } - if (reverse) { - dir = (dir == Bond::ENDUPRIGHT ? Bond::ENDDOWNRIGHT : Bond::ENDUPRIGHT); - } - // to ensure maximum compatibility, even when a bond has unknown stereo (set - // explicitly and recorded in _UnknownStereo property), I will still let a - // direction to be computed. You must check the _UnknownStereo property to - // make sure whether this bond is explictly set to have no direction info. - // This makes sense because the direction info are all derived from - // coordinates, the _UnknownStereo property is like extra metadata to be - // used with the direction info. - bond->setBondDir(dir); - // std::cerr<<"\t\t\t\t -> dir "<getOwningMol().getAtomBonds(oAtom); - while (beg != end) { - Bond *nbrBond = oAtom->getOwningMol()[*beg].get(); - ++beg; - if (nbrBond != bond && nbrBond->getBondType() != Bond::DOUBLE && - needsDir[nbrBond->getIdx()]) { - Bond::BondDir nbrDir = Bond::NONE; - if ((nbrBond->getBeginAtom() == oAtom && bond->getBeginAtom() == oAtom) || - (nbrBond->getEndAtom() == oAtom && bond->getEndAtom() == oAtom)) { - // both bonds either start or end here; they *must* have different - // directions: - nbrDir = - (dir == Bond::ENDUPRIGHT ? Bond::ENDDOWNRIGHT : Bond::ENDUPRIGHT); - } else { - // one starts here, the other ends here, they need to have the same - // direction: - nbrDir = dir; - } - nbrBond->setBondDir(nbrDir); - needsDir[nbrBond->getIdx()] = 0; - // std::cerr << "\t\t\t\t update bond " << nbrBond->getIdx() << " to dir " - // << nbrDir << std::endl; - } - } -} - -bool isLinearArrangement(const RDGeom::Point3D &v1, const RDGeom::Point3D &v2, - double tol = 0.035) { // tolerance of 2 degrees - return fabs(v2.angleTo(v1) - M_PI) < tol; -} - -void updateDoubleBondNeighbors(ROMol &mol, Bond *dblBond, const Conformer *conf, - boost::dynamic_bitset<> &needsDir, - std::vector &singleBondCounts, - const VECT_INT_VECT &singleBondNbrs) { - // we want to deal only with double bonds: - PRECONDITION(dblBond, "bad bond"); - PRECONDITION(dblBond->getBondType() == Bond::DOUBLE, "not a double bond"); - PRECONDITION(conf, "no conformer"); - if (!needsDir[dblBond->getIdx()]) return; - needsDir.set(dblBond->getIdx(), 0); -#if 0 - std::cerr << "**********************\n"; - std::cerr << "**********************\n"; - std::cerr << "**********************\n"; - std::cerr << "UDBN: " << dblBond->getIdx() << " " - << dblBond->getBeginAtomIdx() << "=" << dblBond->getEndAtomIdx() - << "\n"; -#endif - - ROMol::OEDGE_ITER beg, end; - std::vector followupBonds; - - Bond *bond1 = 0, *obond1 = 0; - bool squiggleBondSeen = false; - boost::tie(beg, end) = mol.getAtomBonds(dblBond->getBeginAtom()); - while (beg != end) { - Bond *tBond = mol[*beg].get(); - if (tBond->getBondType() == Bond::SINGLE || - tBond->getBondType() == Bond::AROMATIC) { - // prefer bonds that already have their directionality set - // or that are adjacent to more double bonds: - if (!bond1) { - bond1 = tBond; - } else if (needsDir[tBond->getIdx()]) { - if (singleBondCounts[tBond->getIdx()] > - singleBondCounts[bond1->getIdx()]) { - obond1 = bond1; - bond1 = tBond; - } else { - obond1 = tBond; - } - } else { - obond1 = bond1; - bond1 = tBond; - } - } - if (tBond->getBondType() == Bond::SINGLE && - tBond->getBondDir() == Bond::UNKNOWN) { - squiggleBondSeen = true; - break; - } - - ++beg; - } - // Don't do any direction setting if we've seen a squiggle bond, but do mark - // the double bond as a crossed bond and return - if (!bond1 || squiggleBondSeen) { - dblBond->setBondDir(Bond::EITHERDOUBLE); - return; - } - - Bond *bond2 = 0, *obond2 = 0; - boost::tie(beg, end) = mol.getAtomBonds(dblBond->getEndAtom()); - while (beg != end) { - Bond *tBond = mol[*beg].get(); - if (tBond->getBondType() == Bond::SINGLE || - tBond->getBondType() == Bond::AROMATIC) { - if (!bond2) { - bond2 = tBond; - } else if (needsDir[tBond->getIdx()]) { - if (singleBondCounts[tBond->getIdx()] > - singleBondCounts[bond2->getIdx()]) { - obond2 = bond2; - bond2 = tBond; - } else { - obond2 = tBond; - } - } else { - // we already had a bond2 and we don't need to set the direction - // on the new one, so swap. - obond2 = bond2; - bond2 = tBond; - } - } - if (tBond->getBondType() == Bond::SINGLE && - tBond->getBondDir() == Bond::UNKNOWN) { - squiggleBondSeen = true; - break; - } - - ++beg; - } - // Don't do any direction setting if we've seen a squiggle bond, but do mark - // the double bond as a crossed bond and return - if (!bond2 || squiggleBondSeen) { - dblBond->setBondDir(Bond::EITHERDOUBLE); - return; - } - - CHECK_INVARIANT(bond1 && bond2, "no bonds found"); - RDGeom::Point3D beginP = conf->getAtomPos(dblBond->getBeginAtomIdx()); - RDGeom::Point3D endP = conf->getAtomPos(dblBond->getEndAtomIdx()); - RDGeom::Point3D bond1P = - conf->getAtomPos(bond1->getOtherAtomIdx(dblBond->getBeginAtomIdx())); - RDGeom::Point3D bond2P = - conf->getAtomPos(bond2->getOtherAtomIdx(dblBond->getEndAtomIdx())); - // check for a linear arrangement of atoms on either end: - bool linear = false; - RDGeom::Point3D p1; - RDGeom::Point3D p2; - p1 = bond1P - beginP; - p2 = endP - beginP; - if (isLinearArrangement(p1, p2)) { - if (!obond1) { - linear = true; - } else { - // one of the bonds was linear; what about the other one? - Bond *tBond = bond1; - bond1 = obond1; - obond1 = tBond; - bond1P = - conf->getAtomPos(bond1->getOtherAtomIdx(dblBond->getBeginAtomIdx())); - p1 = bond1P - beginP; - if (isLinearArrangement(p1, p2)) { - linear = true; - } - } - } - if (!linear) { - p1 = bond2P - endP; - p2 = beginP - endP; - if (isLinearArrangement(p1, p2)) { - if (!obond2) { - linear = true; - } else { - Bond *tBond = bond2; - bond2 = obond2; - obond2 = tBond; - bond2P = - conf->getAtomPos(bond2->getOtherAtomIdx(dblBond->getEndAtomIdx())); - p1 = bond2P - beginP; - if (isLinearArrangement(p1, p2)) { - linear = true; - } - } - } - } - if (linear) { - dblBond->setBondDir(Bond::EITHERDOUBLE); - return; - } - - double ang = RDGeom::computeDihedralAngle(bond1P, beginP, endP, bond2P); - bool sameTorsionDir; - if (ang < M_PI / 2) { - sameTorsionDir = false; - } else { - sameTorsionDir = true; - } - // std::cerr << " angle: " << ang << " sameTorsionDir: " << sameTorsionDir - // << "\n"; - - /* - Time for some clarificatory text, because this gets really - confusing really fast. - - The dihedral angle analysis above is based on viewing things - with an atom order as follows: - - 1 - \ - 2 = 3 - \ - 4 - - so dihedrals > 90 correspond to sameDir=true - - however, the stereochemistry representation is - based on something more like this: - - 2 - \ - 1 = 3 - \ - 4 - (i.e. we consider the direction-setting single bonds to be - starting at the double-bonded atom) - - */ - bool reverseBondDir = sameTorsionDir; - - Atom *atom1 = dblBond->getBeginAtom(), *atom2 = dblBond->getEndAtom(); - if (needsDir[bond1->getIdx()]) { - BOOST_FOREACH (int bidx, singleBondNbrs[bond1->getIdx()]) { - // std::cerr << " neighbor from: " << bond1->getIdx() << " " << bidx - // << ": " << needsDir[bidx] << std::endl; - if (needsDir[bidx]) followupBonds.push_back(mol.getBondWithIdx(bidx)); - } - } - if (needsDir[bond2->getIdx()]) { - BOOST_FOREACH (int bidx, singleBondNbrs[bond2->getIdx()]) { - // std::cerr << " neighbor from: " << bond2->getIdx() << " " << bidx - // << ": " << needsDir[bidx] << std::endl; - if (needsDir[bidx]) followupBonds.push_back(mol.getBondWithIdx(bidx)); - } - } - if (!needsDir[bond1->getIdx()]) { - if (!needsDir[bond2->getIdx()]) { - // check that we agree - } else { - if (bond1->getBeginAtom() != atom1) { - reverseBondDir = !reverseBondDir; - } - setBondDirRelativeToAtom(bond2, atom2, bond1->getBondDir(), - reverseBondDir, needsDir); - } - } else if (!needsDir[bond2->getIdx()]) { - if (bond2->getBeginAtom() != atom2) { - reverseBondDir = !reverseBondDir; - } - setBondDirRelativeToAtom(bond1, atom1, bond2->getBondDir(), reverseBondDir, - needsDir); - } else { - setBondDirRelativeToAtom(bond1, atom1, Bond::ENDDOWNRIGHT, false, needsDir); - setBondDirRelativeToAtom(bond2, atom2, Bond::ENDDOWNRIGHT, reverseBondDir, - needsDir); - } - needsDir[bond1->getIdx()] = 0; - needsDir[bond2->getIdx()] = 0; - if (obond1 && needsDir[obond1->getIdx()]) { - setBondDirRelativeToAtom(obond1, atom1, bond1->getBondDir(), - bond1->getBeginAtom() == atom1, needsDir); - needsDir[obond1->getIdx()] = 0; - } - if (obond2 && needsDir[obond2->getIdx()]) { - setBondDirRelativeToAtom(obond2, atom2, bond2->getBondDir(), - bond2->getBeginAtom() == atom2, needsDir); - needsDir[obond2->getIdx()] = 0; - } -#if 0 - std::cerr << " 1:" << bond1->getIdx() << " "; - if (obond1) - std::cerr << obond1->getIdx() << std::endl; - else - std::cerr << "N/A" << std::endl; - std::cerr << " 2:" << bond2->getIdx() << " "; - if (obond2) - std::cerr << obond2->getIdx() << std::endl; - else - std::cerr << "N/A" << std::endl; - std::cerr << "**********************\n"; - std::cerr << "**********************\n"; - std::cerr << "**********************\n"; -#endif - BOOST_FOREACH (Bond *oDblBond, followupBonds) { - // std::cerr << "FOLLOWUP: " << oDblBond->getIdx() << " " - // << needsDir[oDblBond->getIdx()] << std::endl; - updateDoubleBondNeighbors(mol, oDblBond, conf, needsDir, singleBondCounts, - singleBondNbrs); - } -} - void ClearSingleBondDirFlags(ROMol &mol) { for (RWMol::BondIterator bondIt = mol.beginBonds(); bondIt != mol.endBonds(); ++bondIt) { @@ -1011,125 +686,8 @@ void ClearSingleBondDirFlags(ROMol &mol) { void DetectBondStereoChemistry(ROMol &mol, const Conformer *conf) { PRECONDITION(conf, "no conformer"); -#if 0 - std::cerr << ">>>>>>>>>>>>>>>>>>>>>*\n"; - std::cerr << ">>>>>>>>>>>>>>>>>>>>>*\n"; - std::cerr << ">>>>>>>>>>>>>>>>>>>>>*\n"; - std::cerr << "DBSN: "<<"\n"; - std::cerr << ">>>>>>>>>>>>>>>>>>>>>*\n"; - std::cerr << ">>>>>>>>>>>>>>>>>>>>>*\n"; - std::cerr << ">>>>>>>>>>>>>>>>>>>>>*\n"; -#endif - // used to store the number of single bonds a given - // single bond is adjacent to - std::vector singleBondCounts(mol.getNumBonds(), 0); - std::vector bondsInPlay; - // keeps track of which single bonds are adjacent to each double bond: - VECT_INT_VECT dblBondNbrs(mol.getNumBonds()); - // keeps track of which double bonds are adjacent to each single bond: - VECT_INT_VECT singleBondNbrs(mol.getNumBonds()); - // keeps track of which single bonds need a dir set and which double bonds - // need to have their neighbors' dirs set - boost::dynamic_bitset<> needsDir(mol.getNumBonds()); - - // find double bonds that should be considered for - // stereochemistry - // NOTE that we are explicitly excluding double bonds in rings - // with this test. - bool resetRings = false; - if (!mol.getRingInfo()->isInitialized()) { - resetRings = true; - MolOps::fastFindRings(mol); - } - - for (RWMol::BondIterator bondIt = mol.beginBonds(); bondIt != mol.endBonds(); - ++bondIt) { - if ((*bondIt)->getBondType() == Bond::DOUBLE && - (*bondIt)->getStereo() != Bond::STEREOANY && - (*bondIt)->getBondDir() != Bond::EITHERDOUBLE && - (*bondIt)->getBeginAtom()->getDegree() > 1 && - (*bondIt)->getEndAtom()->getDegree() > 1 && - !(mol.getRingInfo()->numBondRings((*bondIt)->getIdx()))) { - const Atom *a1 = (*bondIt)->getBeginAtom(); - const Atom *a2 = (*bondIt)->getEndAtom(); - - ROMol::OEDGE_ITER beg, end; - boost::tie(beg, end) = mol.getAtomBonds(a1); - while (beg != end) { - const Bond *nbrBond = mol[*beg].get(); - if (nbrBond->getBondType() == Bond::SINGLE || - nbrBond->getBondType() == Bond::AROMATIC) { - singleBondCounts[nbrBond->getIdx()] += 1; - needsDir[nbrBond->getIdx()] = 1; - needsDir[(*bondIt)->getIdx()] = 1; - dblBondNbrs[(*bondIt)->getIdx()].push_back(nbrBond->getIdx()); - // the search may seem inefficient, but these vectors are going to be - // at most 2 long (with very few exceptions). It's just not worth - // using a different data structure - if (std::find(singleBondNbrs[nbrBond->getIdx()].begin(), - singleBondNbrs[nbrBond->getIdx()].end(), - (*bondIt)->getIdx()) == - singleBondNbrs[nbrBond->getIdx()].end()) { - singleBondNbrs[nbrBond->getIdx()].push_back((*bondIt)->getIdx()); - } - } - ++beg; - } - boost::tie(beg, end) = mol.getAtomBonds(a2); - while (beg != end) { - const Bond *nbrBond = mol[*beg].get(); - if (nbrBond->getBondType() == Bond::SINGLE || - nbrBond->getBondType() == Bond::AROMATIC) { - singleBondCounts[nbrBond->getIdx()] += 1; - needsDir[nbrBond->getIdx()] = 1; - needsDir[(*bondIt)->getIdx()] = 1; - dblBondNbrs[(*bondIt)->getIdx()].push_back(nbrBond->getIdx()); - - // the search may seem inefficient, but these vectors are going to be - // at most 2 long (with very few exceptions). It's just not worth - // using a different data structure - if (std::find(singleBondNbrs[nbrBond->getIdx()].begin(), - singleBondNbrs[nbrBond->getIdx()].end(), - (*bondIt)->getIdx()) == - singleBondNbrs[nbrBond->getIdx()].end()) { - singleBondNbrs[nbrBond->getIdx()].push_back((*bondIt)->getIdx()); - } - } - ++beg; - } - bondsInPlay.push_back(*bondIt); - } - } - - if (!bondsInPlay.size()) { - if (resetRings) mol.getRingInfo()->reset(); - return; - } - - // order the double bonds based on the singleBondCounts of their neighbors: - std::vector > orderedBondsInPlay; - for (unsigned int i = 0; i < bondsInPlay.size(); ++i) { - Bond *dblBond = bondsInPlay[i]; - unsigned int countHere = - std::accumulate(dblBondNbrs[dblBond->getIdx()].begin(), - dblBondNbrs[dblBond->getIdx()].end(), 0); - // and favor double bonds that are *not* in rings. The combination of using - // the sum - // above (instead of the max) and this ring-membershipt test seem to fix - // sf.net issue 3009836 - if (!(mol.getRingInfo()->numBondRings(dblBond->getIdx()))) countHere *= 10; - orderedBondsInPlay.push_back(std::make_pair(countHere, dblBond)); - } - std::sort(orderedBondsInPlay.begin(), orderedBondsInPlay.end()); - - // oof, now loop over the double bonds in that order and - // update their neighbor directionalities: - std::vector >::reverse_iterator pairIter; - for (pairIter = orderedBondsInPlay.rbegin(); - pairIter != orderedBondsInPlay.rend(); ++pairIter) { - updateDoubleBondNeighbors(mol, pairIter->second, conf, needsDir, - singleBondCounts, singleBondNbrs); - } - if (resetRings) mol.getRingInfo()->reset(); + PRECONDITION(&(conf->getOwningMol()) == &mol, + "conformer does not belong to molecule"); + MolOps::detectBondStereochemistry(mol, conf->getId()); } } diff --git a/Code/GraphMol/FileParsers/MolFileStereochem.h b/Code/GraphMol/FileParsers/MolFileStereochem.h index 955ccde5c..c3262f322 100644 --- a/Code/GraphMol/FileParsers/MolFileStereochem.h +++ b/Code/GraphMol/FileParsers/MolFileStereochem.h @@ -1,6 +1,5 @@ -// $Id$ // -// Copyright (C) 2004-2006 Rational Discovery LLC +// Copyright (C) 2004-2017 Rational Discovery LLC // // @@ All Rights Reserved @@ // This file is part of the RDKit. @@ -8,13 +7,14 @@ // which is included in the file license.txt, found at the root // of the RDKit source tree. // -#ifndef _RD_MOL_FILE_STEREOCHEM_H_ -#define _RD_MOL_FILE_STEREOCHEM_H_ +#ifndef RD_MOL_FILE_STEREOCHEM_H +#define RD_MOL_FILE_STEREOCHEM_H #include namespace RDKit { void DetectAtomStereoChemistry(RWMol &mol, const Conformer *conf); +//! deprecated, please use MolOps::detectBondStereoChemistry instead void DetectBondStereoChemistry(ROMol &mol, const Conformer *conf); void WedgeMolBonds(ROMol &mol, const Conformer *conf); INT_MAP_INT pickBondsToWedge(const ROMol &mol); diff --git a/Code/GraphMol/MolOps.h b/Code/GraphMol/MolOps.h index d27c1ea41..980dbbaf2 100644 --- a/Code/GraphMol/MolOps.h +++ b/Code/GraphMol/MolOps.h @@ -254,9 +254,9 @@ typedef enum { } AdjustQueryWhichFlags; namespace AdjustDegree { - const unsigned int NoAdjust = 0; - const unsigned int TotalDegree = 1; - const unsigned int HeavyDegree = 2; +const unsigned int NoAdjust = 0; +const unsigned int TotalDegree = 1; +const unsigned int HeavyDegree = 2; } struct AdjustQueryParameters { @@ -797,6 +797,28 @@ void cleanupChirality(RWMol &mol); void assignChiralTypesFrom3D(ROMol &mol, int confId = -1, bool replaceExistingTags = true); +//! \brief Uses a conformer to assign ChiralTypes to a molecule's atoms and +//! stereo flags to its bonds +/*! + + \param mol the molecule of interest + \param confId the conformer to use + \param replaceExistingTags if this flag is true, any existing info about + stereochemistry will be replaced + +*/ +void assignStereochemistryFrom3D(ROMol &mol, int confId = -1, + bool replaceExistingTags = true); + +//! \brief Uses a conformer to assign directionality to the single bonds +//! around double bonds +/*! + + \param mol the molecule of interest + \param confId the conformer to use +*/ +void detectBondStereochemistry(ROMol &mol, int confId = -1); + //! Assign stereochemistry tags to atoms (i.e. R/S) and bonds (i.e. Z/E) /*! diff --git a/Code/GraphMol/StructChecker/StripSmallFragments.cpp b/Code/GraphMol/StructChecker/StripSmallFragments.cpp index 40d4411b3..480a79c48 100644 --- a/Code/GraphMol/StructChecker/StripSmallFragments.cpp +++ b/Code/GraphMol/StructChecker/StripSmallFragments.cpp @@ -49,61 +49,60 @@ void AddMWMF(RWMol &mol, } bool StripSmallFragments(RWMol &mol, bool verbose) { - const bool sanitize=false; - std::vector > frags = MolOps::getMolFrags(mol, sanitize); - if (frags.size() <= 1) - return false; + const bool sanitize = false; + std::vector > frags = + MolOps::getMolFrags(mol, sanitize); + if (frags.size() <= 1) return false; size_t maxFragSize = 0; size_t maxFragIdx = 0; - - for(size_t i=0; igetNumAtoms(); - if(fragSize >= maxFragSize) { + if (fragSize >= maxFragSize) { maxFragSize = fragSize; maxFragIdx = i; } } - if(verbose) { + if (verbose) { std::string name = ""; mol.getPropIfPresent(common_properties::_Name, name); - for(size_t i=0; igetNumAtoms() << " atoms" << std::endl; + BOOST_LOG(rdWarningLog) << name << " removed fragment i=" << i + << " with " << frags[i].get()->getNumAtoms() + << " atoms" << std::endl; } } - } // we need to save chirality for checking later bool checkChiral = false; - if(mol.hasProp(RDKit::common_properties::_MolFileChiralFlag)) { - unsigned int chiralflag = mol.getProp( - RDKit::common_properties::_MolFileChiralFlag); + if (mol.hasProp(RDKit::common_properties::_MolFileChiralFlag)) { + unsigned int chiralflag = + mol.getProp(RDKit::common_properties::_MolFileChiralFlag); frags[maxFragIdx].get()->setProp( RDKit::common_properties::_MolFileChiralFlag, chiralflag); checkChiral = chiralflag != 0; } - + mol = *frags[maxFragIdx].get(); // We need to see if the mol file's chirality possibly came from this // fragment. if (checkChiral) { bool ischiral = false; - + RWMol copy(mol); try { MolOps::sanitizeMol(copy); ClearSingleBondDirFlags(copy); - const Conformer &conf = copy.getConformer(); - DetectBondStereoChemistry(copy, &conf); + MolOps::detectBondStereochemistry(copy); MolOps::assignStereochemistry(copy, true, true, true); - for (ROMol::AtomIterator atIt =copy.beginAtoms(); atIt != copy.endAtoms(); - ++atIt) { - if((*atIt)->hasProp(common_properties::_ChiralityPossible)) { + for (ROMol::AtomIterator atIt = copy.beginAtoms(); + atIt != copy.endAtoms(); ++atIt) { + if ((*atIt)->hasProp(common_properties::_ChiralityPossible)) { ischiral = true; checkChiral = false; break; @@ -113,18 +112,18 @@ bool StripSmallFragments(RWMol &mol, bool verbose) { } // are chiral tags set - if(checkChiral) { + if (checkChiral) { for (ROMol::AtomIterator atIt = mol.beginAtoms(); atIt != mol.endAtoms(); ++atIt) { - if ( (*atIt)->getChiralTag() == Atom::CHI_TETRAHEDRAL_CW || - (*atIt)->getChiralTag() == Atom::CHI_TETRAHEDRAL_CCW ) { + if ((*atIt)->getChiralTag() == Atom::CHI_TETRAHEDRAL_CW || + (*atIt)->getChiralTag() == Atom::CHI_TETRAHEDRAL_CCW) { ischiral = true; break; } } - - for (ROMol::BondIterator bondIt = mol.beginBonds(); bondIt != mol.endBonds(); - ++bondIt) { + + for (ROMol::BondIterator bondIt = mol.beginBonds(); + bondIt != mol.endBonds(); ++bondIt) { if ((*bondIt)->getBondDir() == Bond::BEGINDASH || (*bondIt)->getBondDir() == Bond::BEGINWEDGE) { ischiral = true; @@ -132,9 +131,10 @@ bool StripSmallFragments(RWMol &mol, bool verbose) { } } } - + if (!ischiral) { - mol.setProp(RDKit::common_properties::_MolFileChiralFlag, 0); + mol.setProp(RDKit::common_properties::_MolFileChiralFlag, + 0); } } return true; diff --git a/Code/GraphMol/Wrap/MolOps.cpp b/Code/GraphMol/Wrap/MolOps.cpp index 26a5501f3..f978e05db 100644 --- a/Code/GraphMol/Wrap/MolOps.cpp +++ b/Code/GraphMol/Wrap/MolOps.cpp @@ -803,7 +803,8 @@ struct molops_wrapper { // ------------------------------------------------------------------------ docString = - "Assign stereochemistry to bonds based on coordinates.\n\ + "Assign stereochemistry to bonds based on coordinates and a conformer.\n\ + DEPRECATED: Please use the version that takes a conformer ID instead.\n\ \n\ ARGUMENTS:\n\ \n\ @@ -813,6 +814,17 @@ struct molops_wrapper { python::def("DetectBondStereoChemistry", DetectBondStereoChemistry, (python::arg("mol"), python::arg("conformer")), docString.c_str()); + docString = + "Assign stereochemistry to bonds based on coordinates.\n\ + \n\ + ARGUMENTS:\n\ + \n\ + - mol: the molecule to be modified\n\ + - confId: Conformer to use for the coordinates\n\ +\n"; + python::def("DetectBondStereochemistry", MolOps::detectBondStereochemistry, + (python::arg("mol"), python::arg("confId") = -1), + docString.c_str()); // ------------------------------------------------------------------------ docString = diff --git a/Code/GraphMol/testChirality.cpp b/Code/GraphMol/testChirality.cpp index ff626f667..95fc7dc0d 100644 --- a/Code/GraphMol/testChirality.cpp +++ b/Code/GraphMol/testChirality.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -2373,6 +2374,62 @@ void testGithub1423() { } BOOST_LOG(rdInfoLog) << "done" << std::endl; } + +namespace { +void stereochemTester(RWMol *m, std::string expectedCIP, + Bond::BondStereo expectedStereo) { + TEST_ASSERT(m); + TEST_ASSERT(m->getNumAtoms() == 9) + MolOps::sanitizeMol(*m); + TEST_ASSERT(!m->getAtomWithIdx(1)->hasProp(common_properties::_CIPCode)); + TEST_ASSERT(m->getBondWithIdx(3)->getStereo() == Bond::STEREONONE); + // the mol file parser assigned bond dirs, get rid of them + for (ROMol::BondIterator bIt = m->beginBonds(); bIt != m->endBonds(); ++bIt) { + (*bIt)->setBondDir(Bond::NONE); + } + MolOps::assignStereochemistryFrom3D(*m); + TEST_ASSERT(m->getAtomWithIdx(1)->hasProp(common_properties::_CIPCode)); + TEST_ASSERT(m->getAtomWithIdx(1)->getProp( + common_properties::_CIPCode) == expectedCIP); + TEST_ASSERT(m->getBondWithIdx(3)->getStereo() == expectedStereo); +} +} +void testAssignStereochemistryFrom3D() { + BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl; + BOOST_LOG(rdInfoLog) << "Testing assignStereochemistryFrom3D" << std::endl; + + std::string pathName = getenv("RDBASE"); + pathName += "/Code/GraphMol/test_data/"; + { + SDMolSupplier suppl(pathName + "stereochem.sdf", false); // don't sanitize + { + RWMol *m = (RWMol *)suppl.next(); + TEST_ASSERT(m->getProp(common_properties::_Name) == "R-Z"); + stereochemTester(m, "R", Bond::STEREOZ); + delete m; + } + { + RWMol *m = (RWMol *)suppl.next(); + TEST_ASSERT(m->getProp(common_properties::_Name) == "R-E"); + stereochemTester(m, "R", Bond::STEREOE); + delete m; + } + { + RWMol *m = (RWMol *)suppl.next(); + TEST_ASSERT(m->getProp(common_properties::_Name) == "S-Z"); + stereochemTester(m, "S", Bond::STEREOZ); + delete m; + } + { + RWMol *m = (RWMol *)suppl.next(); + TEST_ASSERT(m->getProp(common_properties::_Name) == "S-E"); + stereochemTester(m, "S", Bond::STEREOE); + delete m; + } + } + BOOST_LOG(rdInfoLog) << "done" << std::endl; +} + int main() { RDLog::InitLogs(); // boost::logging::enable_logs("rdApp.debug"); @@ -2400,5 +2457,6 @@ int main() { testGithub1294(); #endif testGithub1423(); + testAssignStereochemistryFrom3D(); return 0; } diff --git a/Code/GraphMol/test_data/stereochem.sdf b/Code/GraphMol/test_data/stereochem.sdf new file mode 100644 index 000000000..4c524a418 --- /dev/null +++ b/Code/GraphMol/test_data/stereochem.sdf @@ -0,0 +1,92 @@ +R-Z + RDKit 3D + + 9 8 0 0 0 0 0 0 0 0999 V2000 + -1.0460 1.7452 -0.5977 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + -1.0774 0.0997 0.0649 C 0 0 1 0 0 0 0 0 0 0 0 0 + -2.0873 -0.5785 -0.5802 F 0 0 0 0 0 0 0 0 0 0 0 0 + 0.1949 -0.6320 -0.1847 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.3786 -0.1174 0.0683 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.4379 1.6532 0.7896 Br 0 0 0 0 0 0 0 0 0 0 0 0 + -1.2310 0.1444 1.1592 H 0 0 0 0 0 0 0 0 0 0 0 0 + 0.1672 -1.6444 -0.5962 H 0 0 0 0 0 0 0 0 0 0 0 0 + 2.2630 -0.6703 -0.1233 H 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 + 2 3 1 0 + 2 4 1 0 + 4 5 2 0 + 5 6 1 0 + 2 7 1 0 + 4 8 1 0 + 5 9 1 0 +M END +$$$$ +R-E + RDKit 3D + + 9 8 0 0 0 0 0 0 0 0999 V2000 + -1.3403 2.0030 0.6479 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + -1.1117 0.3430 0.0763 C 0 0 1 0 0 0 0 0 0 0 0 0 + -1.2152 0.3456 -1.2984 F 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2663 -0.0790 0.4553 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.0963 -0.5602 -0.4485 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.8485 -1.0949 0.0424 Br 0 0 0 0 0 0 0 0 0 0 0 0 + -1.8792 -0.3310 0.5045 H 0 0 0 0 0 0 0 0 0 0 0 0 + 0.5411 0.0303 1.4951 H 0 0 0 0 0 0 0 0 0 0 0 0 + 0.7943 -0.6568 -1.4746 H 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 + 2 3 1 0 + 2 4 1 0 + 4 5 2 0 + 5 6 1 0 + 2 7 1 0 + 4 8 1 0 + 5 9 1 0 +M END +$$$$ +S-Z + RDKit 3D + + 9 8 0 0 0 0 0 0 0 0999 V2000 + -0.6623 0.9792 1.7081 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + -0.9573 0.5208 -0.0063 C 0 0 2 0 0 0 0 0 0 0 0 0 + -2.2762 0.2018 -0.1229 F 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0609 -0.6386 -0.3255 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2315 -0.5522 -0.1274 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.9648 1.0488 0.5661 Br 0 0 0 0 0 0 0 0 0 0 0 0 + -0.6396 1.3857 -0.6116 H 0 0 0 0 0 0 0 0 0 0 0 0 + -0.4656 -1.5685 -0.7256 H 0 0 0 0 0 0 0 0 0 0 0 0 + 1.8656 -1.3770 -0.3549 H 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 + 2 3 1 0 + 2 4 1 0 + 4 5 2 0 + 5 6 1 0 + 2 7 1 0 + 4 8 1 0 + 5 9 1 0 +M END +$$$$ +S-E + RDKit 3D + + 9 8 0 0 0 0 0 0 0 0999 V2000 + -2.1828 -1.2531 -0.2708 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + -1.1254 0.0177 0.3922 C 0 0 2 0 0 0 0 0 0 0 0 0 + -1.7108 1.2367 0.0708 F 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2256 -0.1147 -0.2173 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.3426 0.1827 0.4000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0061 -0.0244 -0.4723 Br 0 0 0 0 0 0 0 0 0 0 0 0 + -1.1173 -0.1001 1.4915 H 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2431 -0.4898 -1.2544 H 0 0 0 0 0 0 0 0 0 0 0 0 + 1.3189 0.5449 1.4027 H 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 + 2 3 1 0 + 2 4 1 0 + 4 5 2 0 + 5 6 1 0 + 2 7 1 0 + 4 8 1 0 + 5 9 1 0 +M END +$$$$ diff --git a/rdkit/Chem/UnitTestMol3D.py b/rdkit/Chem/UnitTestMol3D.py index a0e66286f..d3d470546 100755 --- a/rdkit/Chem/UnitTestMol3D.py +++ b/rdkit/Chem/UnitTestMol3D.py @@ -176,7 +176,7 @@ class TestCase(unittest.TestCase): newmol.AddConformer(newconf) Chem.SanitizeMol(newmol) - Chem.DetectBondStereoChemistry(newmol, newconf) + Chem.DetectBondStereoChemistry(newmol, newmol.GetConformer()) # these aren't necessary for this specific test case, but are for # a more general conversion routine, so would like to see them From 8dc371619bd5af9ffd0f98c7793aa491b0cc1dfd Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Mon, 11 Sep 2017 14:46:42 +0200 Subject: [PATCH 09/44] Fixes github #1544 (#1545) --- .../GraphMol/ChemReactions/ReactionRunner.cpp | 13 ++++-- Code/GraphMol/ChemReactions/testReaction.cpp | 46 +++++++++++++++++++ 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/Code/GraphMol/ChemReactions/ReactionRunner.cpp b/Code/GraphMol/ChemReactions/ReactionRunner.cpp index 32180476e..727ff6c59 100644 --- a/Code/GraphMol/ChemReactions/ReactionRunner.cpp +++ b/Code/GraphMol/ChemReactions/ReactionRunner.cpp @@ -165,8 +165,8 @@ void updateImplicitAtomProperties(Atom *prodAtom, const Atom *reactAtom) { if (!prodAtom->hasProp(common_properties::_ReactionDegreeChanged)) { if (!prodAtom->hasProp(common_properties::_QueryHCount)) { prodAtom->setNumExplicitHs(reactAtom->getNumExplicitHs()); + prodAtom->setNoImplicit(reactAtom->getNoImplicit()); } - prodAtom->setNoImplicit(reactAtom->getNoImplicit()); } } @@ -222,6 +222,7 @@ RWMOL_SPTR convertTemplateToMol(const ROMOL_SPTR prodTemplateSptr) { } if (newAtom->getPropIfPresent(common_properties::_QueryHCount, val)) { newAtom->setNumExplicitHs(val); + newAtom->setNoImplicit(true); // this was github #1544 } if (newAtom->getPropIfPresent(common_properties::_QueryMass, val)) { // FIX: technically should do something with this @@ -1072,13 +1073,15 @@ ROMol *reduceProductToSideChains(const ROMOL_SPTR &product, if (nbr->hasProp(REACT_ATOM_IDX)) { if (nbr->hasProp(WAS_DUMMY)) { bonds_to_product.push_back(RGroup( - nbr, mol->getBondBetweenAtoms(scaffold_atom->getIdx(), *nbrIdx) - ->getBondType(), + nbr, + mol->getBondBetweenAtoms(scaffold_atom->getIdx(), *nbrIdx) + ->getBondType(), nbr->getProp(OLD_MAPNO))); } else { bonds_to_product.push_back(RGroup( - nbr, mol->getBondBetweenAtoms(scaffold_atom->getIdx(), *nbrIdx) - ->getBondType())); + nbr, + mol->getBondBetweenAtoms(scaffold_atom->getIdx(), *nbrIdx) + ->getBondType())); } } diff --git a/Code/GraphMol/ChemReactions/testReaction.cpp b/Code/GraphMol/ChemReactions/testReaction.cpp index 6c9aad761..48ca5489a 100644 --- a/Code/GraphMol/ChemReactions/testReaction.cpp +++ b/Code/GraphMol/ChemReactions/testReaction.cpp @@ -6485,6 +6485,51 @@ void test69Github1387() { BOOST_LOG(rdInfoLog) << "Done" << std::endl; } +void test70Github1544() { + BOOST_LOG(rdInfoLog) << "-------------------------------------" << std::endl; + BOOST_LOG(rdInfoLog) << "Tests github1544: ChemicalReaction code not calling " + "setNoImplicit() when H counts are set" + << std::endl; + { + const std::string smarts = "[CH3:1]>>[CH2:1]"; + + ChemicalReaction *rxn = RxnSmartsToChemicalReaction(smarts); + TEST_ASSERT(rxn); + rxn->initReactantMatchers(); + { + MOL_SPTR_VECT reacts; + std::vector prods; + reacts.push_back(ROMOL_SPTR(SmilesToMol("Cc1ccccc1"))); + prods = rxn->runReactants(reacts); + TEST_ASSERT(prods.size() == 1); + TEST_ASSERT(prods[0].size() == 1); + TEST_ASSERT(prods[0][0]->getAtomWithIdx(0)->getNoImplicit()); + TEST_ASSERT(MolToSmiles(*prods[0][0]) == "[CH2]c1ccccc1"); + } + delete rxn; + } + { // test that the change also works when the degree on the atom changes + const std::string smarts = "[CH3:1][*:2]>>[CH2:1].[*:2]"; + + ChemicalReaction *rxn = RxnSmartsToChemicalReaction(smarts); + TEST_ASSERT(rxn); + rxn->initReactantMatchers(); + { + MOL_SPTR_VECT reacts; + std::vector prods; + reacts.push_back(ROMOL_SPTR(SmilesToMol("Cc1ccccc1"))); + prods = rxn->runReactants(reacts); + TEST_ASSERT(prods.size() == 1); + TEST_ASSERT(prods[0].size() == 2); + TEST_ASSERT(prods[0][0]->getAtomWithIdx(0)->getNoImplicit()); + TEST_ASSERT(MolToSmiles(*prods[0][0]) == "[CH2]"); + TEST_ASSERT(MolToSmiles(*prods[0][1]) == "c1ccccc1"); + } + delete rxn; + } + BOOST_LOG(rdInfoLog) << "Done" << std::endl; +} + int main() { RDLog::InitLogs(); @@ -6567,6 +6612,7 @@ int main() { #endif test69Github1387(); + test70Github1544(); BOOST_LOG(rdInfoLog) << "*******************************************************\n"; From e38d42ca11e87d9bf82f18c280f9dd06b7fd7cf6 Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Mon, 11 Sep 2017 16:08:47 +0200 Subject: [PATCH 10/44] Fix problems in the SWIG wrappers caused by #1546 (#1558) * fix a couple problems in the java wrappers created by the changes * more tests --- Code/JavaWrappers/MolDraw2D.i | 2 +- .../src-test/org/RDKit/Chemv2Tests.java | 36 +++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/Code/JavaWrappers/MolDraw2D.i b/Code/JavaWrappers/MolDraw2D.i index cc415d353..804aaf343 100644 --- a/Code/JavaWrappers/MolDraw2D.i +++ b/Code/JavaWrappers/MolDraw2D.i @@ -43,7 +43,7 @@ %} %template(Int_String_Map) std::map< int, std::string >; -%template(Int_DrawColour_Map) std::map< int, RDKit::DrawColour >; +%template(ColourPalette) std::map< int, RDKit::DrawColour >; %template(Int_Double_Map) std::map< int, double >; %template(DrawColour) boost::tuple; %template(Float_Pair) std::pair; diff --git a/Code/JavaWrappers/gmwrapper/src-test/org/RDKit/Chemv2Tests.java b/Code/JavaWrappers/gmwrapper/src-test/org/RDKit/Chemv2Tests.java index 9a15300db..8d893f3e9 100644 --- a/Code/JavaWrappers/gmwrapper/src-test/org/RDKit/Chemv2Tests.java +++ b/Code/JavaWrappers/gmwrapper/src-test/org/RDKit/Chemv2Tests.java @@ -181,6 +181,42 @@ public class Chemv2Tests extends GraphMolTest { String svg=drawer.getDrawingText(); assertTrue(svg.indexOf("-1); assertTrue(svg.indexOf("")>-1); + } + @Test + public void testMolDraw2DHighlight() { + RWMol m = RWMol.MolFromSmiles("CCCCCOC"); + RDKFuncs.prepareMolForDrawing(m); + Int_Vect hats = new Int_Vect(); + hats.add(0); + hats.add(1); + hats.add(2); + + Int_Vect hbs = new Int_Vect(); + hbs.add(0); + hbs.add(1); + hbs.add(2); + + ColourPalette atCs = new ColourPalette(); + atCs.set(0,new DrawColour(1,1,0)); + atCs.set(1,new DrawColour(1,0,1)); + atCs.set(2,new DrawColour(0,1,1)); + ColourPalette bCs = new ColourPalette(); + + + MolDraw2DSVG drawer = new MolDraw2DSVG(300,300); + drawer.drawMolecule(m,"THE_LEGEND",hats,hbs,atCs,bCs); + drawer.finishDrawing(); + String svg=drawer.getDrawingText(); + //System.out.print(svg); + assertTrue(svg.indexOf("-1); + assertTrue(svg.indexOf("")>-1); + assertTrue(svg.indexOf("THE_LEGEND")>-1); + assertTrue(svg.indexOf("fill:#FFFF00;")>-1); + assertTrue(svg.indexOf("fill:#FF00FF;")>-1); + assertTrue(svg.indexOf("fill:#00FFFF;")>-1); + // default line color: + assertTrue(svg.indexOf("stroke:#FF7F7F;")>-1); + } public static void main(String args[]) { From bbd615497a4625186230956256c4cebcbc414b0a Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Mon, 11 Sep 2017 19:04:58 +0200 Subject: [PATCH 11/44] Add a MolBundle class (#1537) * very basics * add the version to get all matches * better exceptions, including tests * documentation and actually add the test code * responses to review --- Code/GraphMol/CMakeLists.txt | 4 + Code/GraphMol/MolBundle.h | 88 +++++++++++ Code/GraphMol/ROMol.h | 18 +-- Code/GraphMol/Substruct/SubstructMatch.cpp | 85 ++++++++++- Code/GraphMol/Substruct/SubstructMatch.h | 48 +++++- Code/GraphMol/testMolBundle.cpp | 163 +++++++++++++++++++++ 6 files changed, 391 insertions(+), 15 deletions(-) create mode 100644 Code/GraphMol/MolBundle.h create mode 100644 Code/GraphMol/testMolBundle.cpp diff --git a/Code/GraphMol/CMakeLists.txt b/Code/GraphMol/CMakeLists.txt index a49574e79..77701f2d2 100644 --- a/Code/GraphMol/CMakeLists.txt +++ b/Code/GraphMol/CMakeLists.txt @@ -39,6 +39,7 @@ rdkit_headers(Atom.h SanitException.h MonomerInfo.h new_canon.h + MolBundle.h DEST GraphMol) add_subdirectory(Depictor) @@ -118,3 +119,6 @@ rdkit_test(graphmolMemTest1 memtest1.cpp LINK_LIBRARIES SmilesParse GraphMol RDG rdkit_test(resMolSupplierTest resMolSupplierTest.cpp LINK_LIBRARIES SmilesParse GraphMol RDGeometryLib RDGeneral SubstructMatch FileParsers) + +rdkit_test(molBundleTest testMolBundle.cpp + LINK_LIBRARIES SmilesParse GraphMol RDGeometryLib RDGeneral SubstructMatch FileParsers) diff --git a/Code/GraphMol/MolBundle.h b/Code/GraphMol/MolBundle.h new file mode 100644 index 000000000..d39a011d9 --- /dev/null +++ b/Code/GraphMol/MolBundle.h @@ -0,0 +1,88 @@ +// +// Copyright (C) 2017 Greg Landrum +// +// @@ All Rights Reserved @@ +// This file is part of the RDKit. +// The contents are covered by the terms of the BSD license +// which is included in the file license.txt, found at the root +// of the RDKit source tree. +// +/*! \file MolBundle.h + + \brief Defines a class for managing bundles of molecules + +*/ + +#ifndef RD_MOLBUNDLE_AUG2017 +#define RD_MOLBUNDLE_AUG2017 + +/// Std stuff +#include + +// boost stuff +#include +#include +#include + +// our stuff +#include + +namespace RDKit { +class ROMol; + +//! MolBundle contains (conceptually) a collection of ROMols with the same +//! topology +/*! + This is designed to allow handling things like enhanced stereochemistry, + but can no doubt be (ab)used in other ways. +*/ +class MolBundle : public RDProps { + public: + MolBundle() : RDProps(){}; + + //! copy constructor + MolBundle(const MolBundle &other) : RDProps(other) { d_mols = other.d_mols; }; + // FIX: need serialization/deserialization + + virtual ~MolBundle(){}; + + //! returns our molecules + virtual const std::vector > &getMols() const { + return d_mols; + }; + + //! adds a new molecule and returns the total number of molecules + //! enforces that the new molecule has the same number of atoms and bonds + //! as the molecules that are already there. + virtual size_t addMol(boost::shared_ptr nmol) { + PRECONDITION(nmol.get(), "bad mol pointer"); + if (d_mols.size()) { + if (nmol->getNumAtoms() != d_mols[0]->getNumAtoms()) + throw ValueErrorException( + "all molecules in a bundle must have the same number of atoms"); + // REVIEW: should we allow different numbers of bonds? + if (nmol->getNumBonds() != d_mols[0]->getNumBonds()) + throw ValueErrorException( + "all molecules in a bundle must have the same number of bonds"); + } + d_mols.push_back(nmol); + return (d_mols.size()); + } + //! returns the number of molecules from the bundle + virtual size_t size() const { return d_mols.size(); }; + //! returns a particular molecule in the bundle + virtual const boost::shared_ptr getMol(size_t idx) const { + if (idx >= d_mols.size()) throw IndexErrorException(idx); + return d_mols[idx]; + }; + //! returns a particular molecule from the bundle + virtual const boost::shared_ptr operator[](size_t idx) const { + return getMol(idx); + }; + + private: + std::vector > d_mols; +}; + +}; // end of RDKit namespace +#endif diff --git a/Code/GraphMol/ROMol.h b/Code/GraphMol/ROMol.h index 7f391bb20..f6af770c7 100644 --- a/Code/GraphMol/ROMol.h +++ b/Code/GraphMol/ROMol.h @@ -42,11 +42,8 @@ typedef boost::shared_ptr ATOM_SPTR; typedef boost::shared_ptr BOND_SPTR; //! This is the BGL type used to store the topology: -typedef boost::adjacency_list< - boost::vecS, - boost::vecS, - boost::undirectedS, - ATOM_SPTR, BOND_SPTR> +typedef boost::adjacency_list MolGraph; class MolPickler; class RWMol; @@ -191,7 +188,8 @@ class ROMol : public RDProps { only the specified conformer from \c other. */ - ROMol(const ROMol &other, bool quickCopy = false, int confId = -1) : RDProps() { + ROMol(const ROMol &other, bool quickCopy = false, int confId = -1) + : RDProps() { dp_ringInfo = 0; initFromOther(other, quickCopy, confId); numBonds = rdcast(boost::num_edges(d_graph)); @@ -596,12 +594,10 @@ class ROMol : public RDProps { ROMol &operator=( const ROMol &); // disable assignment, RWMol's support assignment -protected: - unsigned int numBonds; + protected: + unsigned int numBonds; #ifndef WIN32 -private: - - + private: #endif void initMol(); virtual void destroy(); diff --git a/Code/GraphMol/Substruct/SubstructMatch.cpp b/Code/GraphMol/Substruct/SubstructMatch.cpp index 0064f5f78..7a305301a 100644 --- a/Code/GraphMol/Substruct/SubstructMatch.cpp +++ b/Code/GraphMol/Substruct/SubstructMatch.cpp @@ -1,5 +1,5 @@ // -// Copyright (C) 2001-2015 Greg Landrum and Rational Discovery LLC +// Copyright (C) 2001-2017 Greg Landrum and Rational Discovery LLC // // @@ All Rights Reserved @@ // This file is part of the RDKit. @@ -13,6 +13,8 @@ #include #include #include +#include + #include "SubstructMatch.h" #include "SubstructUtils.h" #include @@ -343,6 +345,41 @@ bool SubstructMatch(const ROMol &mol, const ROMol &query, return res; } +bool SubstructMatch(const MolBundle &bundle, const ROMol &query, + MatchVectType &matchVect, bool recursionPossible, + bool useChirality, bool useQueryQueryMatches) { + bool res = false; + for (unsigned int i = 0; i < bundle.size() && !res; ++i) { + res = SubstructMatch(*bundle[i], query, matchVect, recursionPossible, + useChirality, useQueryQueryMatches); + } + return res; +} + +bool SubstructMatch(const ROMol &mol, const MolBundle &bundle, + MatchVectType &matchVect, bool recursionPossible, + bool useChirality, bool useQueryQueryMatches) { + bool res = false; + for (unsigned int i = 0; i < bundle.size() && !res; ++i) { + res = SubstructMatch(mol, *bundle[i], matchVect, recursionPossible, + useChirality, useQueryQueryMatches); + } + return res; +} + +bool SubstructMatch(const MolBundle &bundle, const MolBundle &qbundle, + MatchVectType &matchVect, bool recursionPossible, + bool useChirality, bool useQueryQueryMatches) { + bool res = false; + for (unsigned int i = 0; i < bundle.size() && !res; ++i) { + for (unsigned int j = 0; j < bundle.size() && !res; ++j) { + res = + SubstructMatch(*bundle[i], *qbundle[j], matchVect, recursionPossible, + useChirality, useQueryQueryMatches); + } + } + return res; +} // ---------------------------------------------- // // find one match in ResonanceMolSupplier object @@ -435,6 +472,48 @@ unsigned int SubstructMatch(const ROMol &mol, const ROMol &query, return res; } +unsigned int SubstructMatch(const MolBundle &mol, const ROMol &query, + std::vector &matches, bool uniquify, + bool recursionPossible, bool useChirality, + bool useQueryQueryMatches, + unsigned int maxMatches) { + unsigned int res = 0; + for (unsigned int i = 0; i < mol.size() && !res; ++i) { + res = SubstructMatch(*mol[i], query, matches, uniquify, recursionPossible, + useChirality, useQueryQueryMatches, maxMatches); + } + return res; +} + +unsigned int SubstructMatch(const ROMol &mol, const MolBundle &query, + std::vector &matches, bool uniquify, + bool recursionPossible, bool useChirality, + bool useQueryQueryMatches, + unsigned int maxMatches) { + unsigned int res = 0; + for (unsigned int i = 0; i < query.size() && !res; ++i) { + res = SubstructMatch(mol, *query[i], matches, uniquify, recursionPossible, + useChirality, useQueryQueryMatches, maxMatches); + } + return res; +} + +unsigned int SubstructMatch(const MolBundle &mol, const MolBundle &query, + std::vector &matches, bool uniquify, + bool recursionPossible, bool useChirality, + bool useQueryQueryMatches, + unsigned int maxMatches) { + unsigned int res = 0; + for (unsigned int i = 0; i < mol.size() && !res; ++i) { + for (unsigned int j = 0; j < query.size() && !res; ++j) { + res = SubstructMatch(*mol[i], *query[j], matches, uniquify, + recursionPossible, useChirality, + useQueryQueryMatches, maxMatches); + } + } + return res; +} + // ---------------------------------------------- // // find all matches in a ResonanceMolSupplier object @@ -538,8 +617,8 @@ unsigned int RecursiveMatcher(const ROMol &mol, const ROMol &query, } } if (!found) { - BOOST_LOG(rdErrorLog) << "no match found for queryRootAtom" - << std::endl; + BOOST_LOG(rdErrorLog) + << "no match found for queryRootAtom" << std::endl; } } } diff --git a/Code/GraphMol/Substruct/SubstructMatch.h b/Code/GraphMol/Substruct/SubstructMatch.h index 9bb7c55d3..5dd7f1ea0 100644 --- a/Code/GraphMol/Substruct/SubstructMatch.h +++ b/Code/GraphMol/Substruct/SubstructMatch.h @@ -1,5 +1,5 @@ // -// Copyright (C) 2001-2015 Greg Landrum and Rational Discovery LLC +// Copyright (C) 2001-2017 Greg Landrum and Rational Discovery LLC // // @@ All Rights Reserved @@ // This file is part of the RDKit. @@ -18,6 +18,7 @@ class ROMol; class Atom; class Bond; class ResonanceMolSupplier; +class MolBundle; //! \brief used to return matches from substructure searching, //! The format is (queryAtomIdx, molAtomIdx) @@ -126,6 +127,51 @@ unsigned int SubstructMatch(ResonanceMolSupplier &resMolSuppl, bool useChirality = false, bool useQueryQueryMatches = false, unsigned int maxMatches = 1000, int numThreads = 1); + +//! \overload +//! finds the first match in the bundle +bool SubstructMatch(const MolBundle &bundle, const ROMol &query, + MatchVectType &matchVect, bool recursionPossible = true, + bool useChirality = false, + bool useQueryQueryMatches = false); +//! \overload +//! finds the first match in the bundle +bool SubstructMatch(const ROMol &bundle, const MolBundle &query, + MatchVectType &matchVect, bool recursionPossible = true, + bool useChirality = false, + bool useQueryQueryMatches = false); +//! \overload +//! finds the first match in the bundle +bool SubstructMatch(const MolBundle &bundle, const MolBundle &query, + MatchVectType &matchVect, bool recursionPossible = true, + bool useChirality = false, + bool useQueryQueryMatches = false); +//! \overload +//! finds all matches in the first molecule of the bundle that matches the query +unsigned int SubstructMatch(const MolBundle &mol, const ROMol &query, + std::vector &matchVect, + bool uniquify = true, bool recursionPossible = true, + bool useChirality = false, + bool useQueryQueryMatches = false, + unsigned int maxMatches = 1000); + +//! \overload +//! finds all matches in the first molecule of the bundle that matches +unsigned int SubstructMatch(const MolBundle &mol, const MolBundle &query, + std::vector &matchVect, + bool uniquify = true, bool recursionPossible = true, + bool useChirality = false, + bool useQueryQueryMatches = false, + unsigned int maxMatches = 1000); +//! \overload +//! finds all matches against the first molecule of the query bundle that +//! matches +unsigned int SubstructMatch(const ROMol &mol, const MolBundle &query, + std::vector &matchVect, + bool uniquify = true, bool recursionPossible = true, + bool useChirality = false, + bool useQueryQueryMatches = false, + unsigned int maxMatches = 1000); } #endif diff --git a/Code/GraphMol/testMolBundle.cpp b/Code/GraphMol/testMolBundle.cpp new file mode 100644 index 000000000..ac163fff5 --- /dev/null +++ b/Code/GraphMol/testMolBundle.cpp @@ -0,0 +1,163 @@ +// +// Copyright (C) 2017 Greg Landrum +// +// @@ All Rights Reserved @@ +// This file is part of the RDKit. +// The contents are covered by the terms of the BSD license +// which is included in the file license.txt, found at the root +// of the RDKit source tree. +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace RDKit; + +void testBaseFunctionality() { + BOOST_LOG(rdInfoLog) << "-----------------------\n" + << " testBaseFunctionality" << std::endl; + ROMOL_SPTR mol(SmilesToMol("CC[C@H](C)F")); + + MolBundle bundle; + TEST_ASSERT(bundle.size() == 0); + TEST_ASSERT(bundle.addMol(mol) == 1); + TEST_ASSERT(bundle.size() == 1); + TEST_ASSERT(bundle.addMol(ROMOL_SPTR(SmilesToMol("CC[C@@H](C)F"))) == 2); + TEST_ASSERT(bundle.size() == 2); + + MolBundle bundle2(bundle); + TEST_ASSERT(bundle2.size() == 2); + + TEST_ASSERT(bundle.getMol(0)->getNumAtoms() == 5); + TEST_ASSERT(bundle[0]->getNumAtoms() == 5); + + BOOST_LOG(rdInfoLog) << " Done." << std::endl; +} + +void testSubstructFunctionality() { + BOOST_LOG(rdInfoLog) << "-----------------------\n" + << " testSubstructFunctionality" << std::endl; + { + MolBundle bundle; + TEST_ASSERT(bundle.addMol(ROMOL_SPTR(SmilesToMol("CC[C@H](Cl)F"))) == 1); + TEST_ASSERT(bundle.addMol(ROMOL_SPTR(SmilesToMol("CC[C@@H](Cl)F"))) == 2); + + ROMOL_SPTR qry(SmilesToMol("C[C@@H](Cl)F")); + MatchVectType match; + TEST_ASSERT(SubstructMatch(bundle, *qry, match)); + TEST_ASSERT(SubstructMatch(bundle, *qry, match, true, true)); + ROMOL_SPTR qry2(SmilesToMol("C[C@@H](Br)F")); + TEST_ASSERT(!SubstructMatch(bundle, *qry2, match)); + TEST_ASSERT(!SubstructMatch(bundle, *qry2, match, true, true)); + + std::vector matches; + TEST_ASSERT(SubstructMatch(bundle, *qry, matches) == 1); + TEST_ASSERT(SubstructMatch(bundle, *qry, matches, false, true, true) == 1); + TEST_ASSERT(SubstructMatch(bundle, *qry2, matches) == 0); + TEST_ASSERT(SubstructMatch(bundle, *qry2, matches, false, true, true) == 0); + } + { + MolBundle bundle; + TEST_ASSERT(bundle.addMol(ROMOL_SPTR(SmilesToMol("C[C@H](Cl)F"))) == 1); + TEST_ASSERT(bundle.addMol(ROMOL_SPTR(SmilesToMol("C[C@@H](Cl)F"))) == 2); + + ROMOL_SPTR mol(SmilesToMol("CC[C@@H](Cl)F")); + MatchVectType match; + TEST_ASSERT(SubstructMatch(*mol, bundle, match)); + TEST_ASSERT(SubstructMatch(*mol, bundle, match, true, true)); + ROMOL_SPTR mol2(SmilesToMol("CC[C@@H](Br)F")); + TEST_ASSERT(!SubstructMatch(*mol2, bundle, match)); + TEST_ASSERT(!SubstructMatch(*mol2, bundle, match, true, true)); + + std::vector matches; + TEST_ASSERT(SubstructMatch(*mol, bundle, matches) == 1); + TEST_ASSERT(SubstructMatch(*mol, bundle, matches, false, true, true) == 1); + TEST_ASSERT(SubstructMatch(*mol2, bundle, matches) == 0); + TEST_ASSERT(SubstructMatch(*mol2, bundle, matches, false, true, true) == 0); + } + { + MolBundle bundle; + TEST_ASSERT(bundle.addMol(ROMOL_SPTR(SmilesToMol("CC[C@H](Cl)F"))) == 1); + TEST_ASSERT(bundle.addMol(ROMOL_SPTR(SmilesToMol("CC[C@@H](Cl)F"))) == 2); + + MolBundle qbundle; + TEST_ASSERT(qbundle.addMol(ROMOL_SPTR(SmilesToMol("C[13C@H](Cl)F"))) == 1); + TEST_ASSERT(qbundle.addMol(ROMOL_SPTR(SmilesToMol("C[C@@H](Cl)F"))) == 2); + + MatchVectType match; + TEST_ASSERT(SubstructMatch(bundle, qbundle, match)); + TEST_ASSERT(SubstructMatch(bundle, qbundle, match, true, true)); + + std::vector matches; + TEST_ASSERT(SubstructMatch(bundle, qbundle, matches) == 1); + TEST_ASSERT(SubstructMatch(bundle, qbundle, matches, false, true, true) == + 1); + } + BOOST_LOG(rdInfoLog) << " Done." << std::endl; +} + +void testExceptions() { + BOOST_LOG(rdInfoLog) << "-----------------------\n" + << " testExceptions" << std::endl; + ROMOL_SPTR mol(SmilesToMol("C1CCC1")); + + MolBundle bundle; + TEST_ASSERT(bundle.size() == 0); + TEST_ASSERT(bundle.addMol(mol) == 1); + TEST_ASSERT(bundle.size() == 1); + { + bool ok = false; + try { + bundle.addMol(ROMOL_SPTR(SmilesToMol("C1CC1"))); + } catch (const ValueErrorException &) { + ok = true; + } + TEST_ASSERT(ok); + } + { + bool ok = false; + try { + bundle.addMol(ROMOL_SPTR(SmilesToMol("CCCC"))); + } catch (const ValueErrorException &) { + ok = true; + } + TEST_ASSERT(ok); + } + { + bool ok = false; + try { + bundle.getMol(1); + } catch (const IndexErrorException &) { + ok = true; + } + TEST_ASSERT(ok); + } + { + bool ok = false; + try { + bundle[1]; + } catch (const IndexErrorException &) { + ok = true; + } + TEST_ASSERT(ok); + } + BOOST_LOG(rdInfoLog) << " Done." << std::endl; +} + +int main() { + RDLog::InitLogs(); +#if 1 + testBaseFunctionality(); + testSubstructFunctionality(); + testExceptions(); +#endif + return 0; +} From 7488840ac4e8e6fc5d001a0af6c4be34b1b48e06 Mon Sep 17 00:00:00 2001 From: Brian Kelley Date: Mon, 11 Sep 2017 15:17:33 -0400 Subject: [PATCH 12/44] Fix/urange check (#1506) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fixes atom documentation * Fixes #1461 This is a complicated one. Basically URANGE_CHECK when used on unsigned integers has a problem when the size of the range it’s checking is 0. The standard operations is to check URANGE(num, size-1) Which (for unsigned integers) obviously rolls over. This fixes all usage cases to be URANGE(num+1, size) And fixes the bugs found. (addBond and the mmff tests) * Fixes #1461 - Updates URANGE_CHECK to be 0<=x { */ void addEdge(unsigned int id1, unsigned int id2) { unsigned int nents = getNumEntries(); - URANGE_CHECK(id1, nents - 1); - URANGE_CHECK(id2, nents - 1); + URANGE_CHECK(id1, nents); + URANGE_CHECK(id2, nents); // FIX: if we boost::setS for the edgeList BGL will // do the checking for duplicity (parallel edges) // But for reasons unknown setS results in compile @@ -352,7 +352,7 @@ class HierarchCatalog : public Catalog { //------------------------------------ //! returns a pointer to our entry with a particular index const entryType *getEntryWithIdx(unsigned int idx) const { - URANGE_CHECK(idx, getNumEntries() - 1); + URANGE_CHECK(idx, getNumEntries()); int vd = static_cast(boost::vertex(idx, d_graph)); typename boost::property_map::const_type pMap = boost::get(vertex_entry_t(), d_graph); @@ -362,7 +362,7 @@ class HierarchCatalog : public Catalog { //------------------------------------ //! returns a pointer to our entry with a particular bit ID const entryType *getEntryWithBitId(unsigned int idx) const { - URANGE_CHECK(idx, this->getFPLength() - 1); + URANGE_CHECK(idx, this->getFPLength()); typename boost::property_map::const_type pMap = boost::get(vertex_entry_t(), d_graph); const entryType *res = NULL; @@ -379,7 +379,7 @@ class HierarchCatalog : public Catalog { //------------------------------------ //! returns the index of the entry with a particular bit ID int getIdOfEntryWithBitId(unsigned int idx) const { - URANGE_CHECK(idx, this->getFPLength() - 1); + URANGE_CHECK(idx, this->getFPLength()); typename boost::property_map::const_type pMap = boost::get(vertex_entry_t(), d_graph); int res = -1; diff --git a/Code/DistGeom/BoundsMatrix.h b/Code/DistGeom/BoundsMatrix.h index 59d9547c6..2ef45f08f 100644 --- a/Code/DistGeom/BoundsMatrix.h +++ b/Code/DistGeom/BoundsMatrix.h @@ -34,8 +34,8 @@ class BoundsMatrix : public RDNumeric::SquareMatrix { //! Get the upper bound between points i and j inline double getUpperBound(unsigned int i, unsigned int j) const { - URANGE_CHECK(i, d_nRows - 1); - URANGE_CHECK(j, d_nCols - 1); + URANGE_CHECK(i, d_nRows); + URANGE_CHECK(j, d_nCols); if (i < j) { return getVal(i, j); @@ -46,8 +46,8 @@ class BoundsMatrix : public RDNumeric::SquareMatrix { //! Set the lower bound between points i and j inline void setUpperBound(unsigned int i, unsigned int j, double val) { - URANGE_CHECK(i, d_nRows - 1); - URANGE_CHECK(j, d_nCols - 1); + URANGE_CHECK(i, d_nRows); + URANGE_CHECK(j, d_nCols); CHECK_INVARIANT(val >= 0.0, "Negative upper bound"); if (i < j) { setVal(i, j, val); @@ -67,8 +67,8 @@ class BoundsMatrix : public RDNumeric::SquareMatrix { //! Set the lower bound between points i and j inline void setLowerBound(unsigned int i, unsigned int j, double val) { - URANGE_CHECK(i, d_nRows - 1); - URANGE_CHECK(j, d_nCols - 1); + URANGE_CHECK(i, d_nRows); + URANGE_CHECK(j, d_nCols); CHECK_INVARIANT(val >= 0.0, "Negative lower bound"); if (i < j) { setVal(j, i, val); @@ -88,8 +88,8 @@ class BoundsMatrix : public RDNumeric::SquareMatrix { //! Get the lower bound between points i and j inline double getLowerBound(unsigned int i, unsigned int j) const { - URANGE_CHECK(i, d_nRows - 1); - URANGE_CHECK(j, d_nCols - 1); + URANGE_CHECK(i, d_nRows); + URANGE_CHECK(j, d_nCols); if (i < j) { return getVal(j, i); diff --git a/Code/DistGeom/ChiralViolationContrib.cpp b/Code/DistGeom/ChiralViolationContrib.cpp index 054614b60..316151660 100644 --- a/Code/DistGeom/ChiralViolationContrib.cpp +++ b/Code/DistGeom/ChiralViolationContrib.cpp @@ -14,10 +14,10 @@ ChiralViolationContrib::ChiralViolationContrib(ForceFields::ForceField *owner, PRECONDITION(owner, "bad owner"); PRECONDITION(cset, "bad chiral set") - URANGE_CHECK(cset->d_idx1, owner->positions().size() - 1); - URANGE_CHECK(cset->d_idx2, owner->positions().size() - 1); - URANGE_CHECK(cset->d_idx3, owner->positions().size() - 1); - URANGE_CHECK(cset->d_idx4, owner->positions().size() - 1); + URANGE_CHECK(cset->d_idx1, owner->positions().size()); + URANGE_CHECK(cset->d_idx2, owner->positions().size()); + URANGE_CHECK(cset->d_idx3, owner->positions().size()); + URANGE_CHECK(cset->d_idx4, owner->positions().size()); dp_forceField = owner; diff --git a/Code/DistGeom/DistViolationContrib.cpp b/Code/DistGeom/DistViolationContrib.cpp index 932ee8983..250fe1982 100644 --- a/Code/DistGeom/DistViolationContrib.cpp +++ b/Code/DistGeom/DistViolationContrib.cpp @@ -20,8 +20,8 @@ DistViolationContrib::DistViolationContrib(ForceFields::ForceField *owner, double ub, double lb, double weight) { PRECONDITION(owner, "bad owner"); - URANGE_CHECK(idx1, owner->positions().size() - 1); - URANGE_CHECK(idx2, owner->positions().size() - 1); + URANGE_CHECK(idx1, owner->positions().size()); + URANGE_CHECK(idx2, owner->positions().size()); dp_forceField = owner; d_end1Idx = idx1; diff --git a/Code/ForceField/ForceField.cpp b/Code/ForceField/ForceField.cpp index 6231933ab..1b3e656a9 100644 --- a/Code/ForceField/ForceField.cpp +++ b/Code/ForceField/ForceField.cpp @@ -92,8 +92,8 @@ ForceField::ForceField(const ForceField &other) double ForceField::distance(unsigned int i, unsigned int j, double *pos) { PRECONDITION(df_init, "not initialized"); - URANGE_CHECK(i, d_numPoints - 1); - URANGE_CHECK(j, d_numPoints - 1); + URANGE_CHECK(i, d_numPoints); + URANGE_CHECK(j, d_numPoints); if (j < i) { int tmp = j; j = i; @@ -133,8 +133,8 @@ double ForceField::distance(unsigned int i, unsigned int j, double *pos) { double ForceField::distance(unsigned int i, unsigned int j, double *pos) const { PRECONDITION(df_init, "not initialized"); - URANGE_CHECK(i, d_numPoints - 1); - URANGE_CHECK(j, d_numPoints - 1); + URANGE_CHECK(i, d_numPoints); + URANGE_CHECK(j, d_numPoints); if (j < i) { int tmp = j; j = i; diff --git a/Code/ForceField/MMFF/AngleBend.cpp b/Code/ForceField/MMFF/AngleBend.cpp index 2b2c87422..c384bd815 100644 --- a/Code/ForceField/MMFF/AngleBend.cpp +++ b/Code/ForceField/MMFF/AngleBend.cpp @@ -92,9 +92,9 @@ AngleBendContrib::AngleBendContrib(ForceField *owner, unsigned int idx1, PRECONDITION(owner, "bad owner"); PRECONDITION(((idx1 != idx2) && (idx2 != idx3) && (idx1 != idx3)), "degenerate points"); - URANGE_CHECK(idx1, owner->positions().size() - 1); - URANGE_CHECK(idx2, owner->positions().size() - 1); - URANGE_CHECK(idx3, owner->positions().size() - 1); + URANGE_CHECK(idx1, owner->positions().size()); + URANGE_CHECK(idx2, owner->positions().size()); + URANGE_CHECK(idx3, owner->positions().size()); dp_forceField = owner; d_at1Idx = idx1; diff --git a/Code/ForceField/MMFF/AngleConstraint.cpp b/Code/ForceField/MMFF/AngleConstraint.cpp index 22709928e..f5c6184c3 100644 --- a/Code/ForceField/MMFF/AngleConstraint.cpp +++ b/Code/ForceField/MMFF/AngleConstraint.cpp @@ -41,9 +41,9 @@ AngleConstraintContrib::AngleConstraintContrib( ForceField *owner, unsigned int idx1, unsigned int idx2, unsigned int idx3, double minAngleDeg, double maxAngleDeg, double forceConst) { PRECONDITION(owner, "bad owner"); - URANGE_CHECK(idx1, owner->positions().size() - 1); - URANGE_CHECK(idx2, owner->positions().size() - 1); - URANGE_CHECK(idx3, owner->positions().size() - 1); + URANGE_CHECK(idx1, owner->positions().size()); + URANGE_CHECK(idx2, owner->positions().size()); + URANGE_CHECK(idx3, owner->positions().size()); PRECONDITION(maxAngleDeg >= minAngleDeg, "allowedDeltaDeg must be >= 0.0"); _pretreatAngles(minAngleDeg, maxAngleDeg); @@ -61,9 +61,9 @@ AngleConstraintContrib::AngleConstraintContrib( bool relative, double minAngleDeg, double maxAngleDeg, double forceConst) { PRECONDITION(owner, "bad owner"); const RDGeom::PointPtrVect &pos = owner->positions(); - URANGE_CHECK(idx1, pos.size() - 1); - URANGE_CHECK(idx2, pos.size() - 1); - URANGE_CHECK(idx3, pos.size() - 1); + URANGE_CHECK(idx1, pos.size()); + URANGE_CHECK(idx2, pos.size()); + URANGE_CHECK(idx3, pos.size()); PRECONDITION(maxAngleDeg >= minAngleDeg, "allowedDeltaDeg must be >= 0.0"); double angle = 0.0; diff --git a/Code/ForceField/MMFF/BondStretch.cpp b/Code/ForceField/MMFF/BondStretch.cpp index d36b8f63d..53b474031 100644 --- a/Code/ForceField/MMFF/BondStretch.cpp +++ b/Code/ForceField/MMFF/BondStretch.cpp @@ -52,8 +52,8 @@ BondStretchContrib::BondStretchContrib(ForceField *owner, const unsigned int idx2, const MMFFBond *mmffBondParams) { PRECONDITION(owner, "bad owner"); - URANGE_CHECK(idx1, owner->positions().size() - 1); - URANGE_CHECK(idx2, owner->positions().size() - 1); + URANGE_CHECK(idx1, owner->positions().size()); + URANGE_CHECK(idx2, owner->positions().size()); dp_forceField = owner; d_at1Idx = idx1; diff --git a/Code/ForceField/MMFF/DistanceConstraint.cpp b/Code/ForceField/MMFF/DistanceConstraint.cpp index 76b9467bd..e2988e824 100644 --- a/Code/ForceField/MMFF/DistanceConstraint.cpp +++ b/Code/ForceField/MMFF/DistanceConstraint.cpp @@ -21,8 +21,8 @@ DistanceConstraintContrib::DistanceConstraintContrib( ForceField *owner, unsigned int idx1, unsigned int idx2, double minLen, double maxLen, double forceConst) { PRECONDITION(owner, "bad owner"); - URANGE_CHECK(idx1, owner->positions().size() - 1); - URANGE_CHECK(idx2, owner->positions().size() - 1); + URANGE_CHECK(idx1, owner->positions().size()); + URANGE_CHECK(idx2, owner->positions().size()); PRECONDITION(maxLen >= minLen, "bad bounds"); dp_forceField = owner; @@ -38,8 +38,8 @@ DistanceConstraintContrib::DistanceConstraintContrib( double minLen, double maxLen, double forceConst) { PRECONDITION(owner, "bad owner"); const RDGeom::PointPtrVect &pos = owner->positions(); - URANGE_CHECK(idx1, pos.size() - 1); - URANGE_CHECK(idx2, pos.size() - 1); + URANGE_CHECK(idx1, pos.size()); + URANGE_CHECK(idx2, pos.size()); PRECONDITION(maxLen >= minLen, "bad bounds"); double dist = 0.0; diff --git a/Code/ForceField/MMFF/Nonbonded.cpp b/Code/ForceField/MMFF/Nonbonded.cpp index 215d16dad..3a943ae74 100644 --- a/Code/ForceField/MMFF/Nonbonded.cpp +++ b/Code/ForceField/MMFF/Nonbonded.cpp @@ -96,8 +96,8 @@ VdWContrib::VdWContrib(ForceField *owner, unsigned int idx1, unsigned int idx2, const MMFFVdWRijstarEps *mmffVdWConstants) { PRECONDITION(owner, "bad owner"); PRECONDITION(mmffVdWConstants, "bad MMFFVdW parameters"); - URANGE_CHECK(idx1, owner->positions().size() - 1); - URANGE_CHECK(idx2, owner->positions().size() - 1); + URANGE_CHECK(idx1, owner->positions().size()); + URANGE_CHECK(idx2, owner->positions().size()); dp_forceField = owner; d_at1Idx = idx1; @@ -153,8 +153,8 @@ EleContrib::EleContrib(ForceField *owner, unsigned int idx1, unsigned int idx2, double chargeTerm, boost::uint8_t dielModel, bool is1_4) { PRECONDITION(owner, "bad owner"); - URANGE_CHECK(idx1, owner->positions().size() - 1); - URANGE_CHECK(idx2, owner->positions().size() - 1); + URANGE_CHECK(idx1, owner->positions().size()); + URANGE_CHECK(idx2, owner->positions().size()); dp_forceField = owner; d_at1Idx = idx1; diff --git a/Code/ForceField/MMFF/OopBend.cpp b/Code/ForceField/MMFF/OopBend.cpp index dd122d675..0e09af61d 100644 --- a/Code/ForceField/MMFF/OopBend.cpp +++ b/Code/ForceField/MMFF/OopBend.cpp @@ -58,10 +58,10 @@ OopBendContrib::OopBendContrib(ForceField *owner, unsigned int idx1, PRECONDITION((idx1 != idx2) && (idx1 != idx3) && (idx1 != idx4) && (idx2 != idx3) && (idx2 != idx4) && (idx3 != idx4), "degenerate points"); - URANGE_CHECK(idx1, owner->positions().size() - 1); - URANGE_CHECK(idx2, owner->positions().size() - 1); - URANGE_CHECK(idx3, owner->positions().size() - 1); - URANGE_CHECK(idx4, owner->positions().size() - 1); + URANGE_CHECK(idx1, owner->positions().size()); + URANGE_CHECK(idx2, owner->positions().size()); + URANGE_CHECK(idx3, owner->positions().size()); + URANGE_CHECK(idx4, owner->positions().size()); dp_forceField = owner; d_at1Idx = idx1; diff --git a/Code/ForceField/MMFF/PositionConstraint.cpp b/Code/ForceField/MMFF/PositionConstraint.cpp index c75e85c32..b766c2d3a 100644 --- a/Code/ForceField/MMFF/PositionConstraint.cpp +++ b/Code/ForceField/MMFF/PositionConstraint.cpp @@ -23,7 +23,7 @@ PositionConstraintContrib::PositionConstraintContrib(ForceField *owner, double forceConst) { PRECONDITION(owner, "bad owner"); const RDGeom::PointPtrVect &pos = owner->positions(); - URANGE_CHECK(idx, pos.size() - 1); + URANGE_CHECK(idx, pos.size()); dp_forceField = owner; d_atIdx = idx; diff --git a/Code/ForceField/MMFF/StretchBend.cpp b/Code/ForceField/MMFF/StretchBend.cpp index 95837cb8b..57f5ef03b 100644 --- a/Code/ForceField/MMFF/StretchBend.cpp +++ b/Code/ForceField/MMFF/StretchBend.cpp @@ -48,9 +48,9 @@ StretchBendContrib::StretchBendContrib( PRECONDITION(owner, "bad owner"); PRECONDITION(((idx1 != idx2) && (idx2 != idx3) && (idx1 != idx3)), "degenerate points"); - URANGE_CHECK(idx1, owner->positions().size() - 1); - URANGE_CHECK(idx2, owner->positions().size() - 1); - URANGE_CHECK(idx3, owner->positions().size() - 1); + URANGE_CHECK(idx1, owner->positions().size()); + URANGE_CHECK(idx2, owner->positions().size()); + URANGE_CHECK(idx3, owner->positions().size()); dp_forceField = owner; d_at1Idx = idx1; diff --git a/Code/ForceField/MMFF/TorsionAngle.cpp b/Code/ForceField/MMFF/TorsionAngle.cpp index 926d03709..ebefe0c15 100644 --- a/Code/ForceField/MMFF/TorsionAngle.cpp +++ b/Code/ForceField/MMFF/TorsionAngle.cpp @@ -99,10 +99,10 @@ TorsionAngleContrib::TorsionAngleContrib(ForceField *owner, unsigned int idx1, PRECONDITION((idx1 != idx2) && (idx1 != idx3) && (idx1 != idx4) && (idx2 != idx3) && (idx2 != idx4) && (idx3 != idx4), "degenerate points"); - URANGE_CHECK(idx1, owner->positions().size() - 1); - URANGE_CHECK(idx2, owner->positions().size() - 1); - URANGE_CHECK(idx3, owner->positions().size() - 1); - URANGE_CHECK(idx4, owner->positions().size() - 1); + URANGE_CHECK(idx1, owner->positions().size()); + URANGE_CHECK(idx2, owner->positions().size()); + URANGE_CHECK(idx3, owner->positions().size()); + URANGE_CHECK(idx4, owner->positions().size()); dp_forceField = owner; d_at1Idx = idx1; diff --git a/Code/ForceField/MMFF/TorsionConstraint.cpp b/Code/ForceField/MMFF/TorsionConstraint.cpp index b8e02e003..9ab7f6e88 100644 --- a/Code/ForceField/MMFF/TorsionConstraint.cpp +++ b/Code/ForceField/MMFF/TorsionConstraint.cpp @@ -37,10 +37,10 @@ TorsionConstraintContrib::TorsionConstraintContrib( unsigned int idx4, double minDihedralDeg, double maxDihedralDeg, double forceConst) { PRECONDITION(owner, "bad owner"); - URANGE_CHECK(idx1, owner->positions().size() - 1); - URANGE_CHECK(idx2, owner->positions().size() - 1); - URANGE_CHECK(idx3, owner->positions().size() - 1); - URANGE_CHECK(idx4, owner->positions().size() - 1); + URANGE_CHECK(idx1, owner->positions().size()); + URANGE_CHECK(idx2, owner->positions().size()); + URANGE_CHECK(idx3, owner->positions().size()); + URANGE_CHECK(idx4, owner->positions().size()); PRECONDITION((!(maxDihedralDeg < minDihedralDeg)) && ((maxDihedralDeg - minDihedralDeg) < 360.0), "bad bounds"); @@ -62,10 +62,10 @@ TorsionConstraintContrib::TorsionConstraintContrib( double maxDihedralDeg, double forceConst) { PRECONDITION(owner, "bad owner"); const RDGeom::PointPtrVect &pos = owner->positions(); - URANGE_CHECK(idx1, pos.size() - 1); - URANGE_CHECK(idx2, pos.size() - 1); - URANGE_CHECK(idx3, pos.size() - 1); - URANGE_CHECK(idx4, pos.size() - 1); + URANGE_CHECK(idx1, pos.size()); + URANGE_CHECK(idx2, pos.size()); + URANGE_CHECK(idx3, pos.size()); + URANGE_CHECK(idx4, pos.size()); PRECONDITION((!(maxDihedralDeg < minDihedralDeg)) && ((maxDihedralDeg - minDihedralDeg) < 360.0), "bad bounds"); diff --git a/Code/ForceField/UFF/AngleBend.cpp b/Code/ForceField/UFF/AngleBend.cpp index 0579ec950..a3976fb6b 100644 --- a/Code/ForceField/UFF/AngleBend.cpp +++ b/Code/ForceField/UFF/AngleBend.cpp @@ -76,9 +76,9 @@ AngleBendContrib::AngleBendContrib(ForceField *owner, unsigned int idx1, PRECONDITION(at3Params, "bad params pointer"); PRECONDITION((idx1 != idx2 && idx2 != idx3 && idx1 != idx3), "degenerate points"); - URANGE_CHECK(idx1, owner->positions().size() - 1); - URANGE_CHECK(idx2, owner->positions().size() - 1); - URANGE_CHECK(idx3, owner->positions().size() - 1); + URANGE_CHECK(idx1, owner->positions().size()); + URANGE_CHECK(idx2, owner->positions().size()); + URANGE_CHECK(idx3, owner->positions().size()); // the following is a hack to get decent geometries // with 3- and 4-membered rings incorporating sp2 atoms double theta0 = at2Params->theta0; diff --git a/Code/ForceField/UFF/AngleConstraint.cpp b/Code/ForceField/UFF/AngleConstraint.cpp index 0fd68fc0b..e58424e8c 100644 --- a/Code/ForceField/UFF/AngleConstraint.cpp +++ b/Code/ForceField/UFF/AngleConstraint.cpp @@ -41,9 +41,9 @@ AngleConstraintContrib::AngleConstraintContrib( ForceField *owner, unsigned int idx1, unsigned int idx2, unsigned int idx3, double minAngleDeg, double maxAngleDeg, double forceConst) { PRECONDITION(owner, "bad owner"); - URANGE_CHECK(idx1, owner->positions().size() - 1); - URANGE_CHECK(idx2, owner->positions().size() - 1); - URANGE_CHECK(idx3, owner->positions().size() - 1); + URANGE_CHECK(idx1, owner->positions().size()); + URANGE_CHECK(idx2, owner->positions().size()); + URANGE_CHECK(idx3, owner->positions().size()); PRECONDITION(maxAngleDeg >= minAngleDeg, "allowedDeltaDeg must be >= 0.0"); _pretreatAngles(minAngleDeg, maxAngleDeg); @@ -61,9 +61,9 @@ AngleConstraintContrib::AngleConstraintContrib( bool relative, double minAngleDeg, double maxAngleDeg, double forceConst) { PRECONDITION(owner, "bad owner"); const RDGeom::PointPtrVect &pos = owner->positions(); - URANGE_CHECK(idx1, pos.size() - 1); - URANGE_CHECK(idx2, pos.size() - 1); - URANGE_CHECK(idx3, pos.size() - 1); + URANGE_CHECK(idx1, pos.size()); + URANGE_CHECK(idx2, pos.size()); + URANGE_CHECK(idx3, pos.size()); PRECONDITION(maxAngleDeg >= minAngleDeg, "allowedDeltaDeg must be >= 0.0"); double angle = 0.0; diff --git a/Code/ForceField/UFF/BondStretch.cpp b/Code/ForceField/UFF/BondStretch.cpp index e6c0e3b86..119bf959e 100644 --- a/Code/ForceField/UFF/BondStretch.cpp +++ b/Code/ForceField/UFF/BondStretch.cpp @@ -54,8 +54,8 @@ BondStretchContrib::BondStretchContrib(ForceField *owner, unsigned int idx1, PRECONDITION(owner, "bad owner"); PRECONDITION(end1Params, "bad params pointer"); PRECONDITION(end2Params, "bad params pointer"); - URANGE_CHECK(idx1, owner->positions().size() - 1); - URANGE_CHECK(idx2, owner->positions().size() - 1); + URANGE_CHECK(idx1, owner->positions().size()); + URANGE_CHECK(idx2, owner->positions().size()); dp_forceField = owner; d_end1Idx = idx1; diff --git a/Code/ForceField/UFF/DistanceConstraint.cpp b/Code/ForceField/UFF/DistanceConstraint.cpp index 44ea7194a..fe461d279 100644 --- a/Code/ForceField/UFF/DistanceConstraint.cpp +++ b/Code/ForceField/UFF/DistanceConstraint.cpp @@ -21,8 +21,8 @@ DistanceConstraintContrib::DistanceConstraintContrib( ForceField *owner, unsigned int idx1, unsigned int idx2, double minLen, double maxLen, double forceConst) { PRECONDITION(owner, "bad owner"); - URANGE_CHECK(idx1, owner->positions().size() - 1); - URANGE_CHECK(idx2, owner->positions().size() - 1); + URANGE_CHECK(idx1, owner->positions().size()); + URANGE_CHECK(idx2, owner->positions().size()); PRECONDITION(maxLen >= minLen, "bad bounds"); dp_forceField = owner; @@ -38,8 +38,8 @@ DistanceConstraintContrib::DistanceConstraintContrib( double minLen, double maxLen, double forceConst) { PRECONDITION(owner, "bad owner"); const RDGeom::PointPtrVect &pos = owner->positions(); - URANGE_CHECK(idx1, pos.size() - 1); - URANGE_CHECK(idx2, pos.size() - 1); + URANGE_CHECK(idx1, pos.size()); + URANGE_CHECK(idx2, pos.size()); PRECONDITION(maxLen >= minLen, "bad bounds"); double dist = 0.0; diff --git a/Code/ForceField/UFF/Inversion.cpp b/Code/ForceField/UFF/Inversion.cpp index 2c672d452..2ce8d4c73 100644 --- a/Code/ForceField/UFF/Inversion.cpp +++ b/Code/ForceField/UFF/Inversion.cpp @@ -91,10 +91,10 @@ InversionContrib::InversionContrib(ForceField *owner, unsigned int idx1, unsigned int idx4, int at2AtomicNum, bool isCBoundToO, double oobForceScalingFactor) { PRECONDITION(owner, "bad owner"); - URANGE_CHECK(idx1, owner->positions().size() - 1); - URANGE_CHECK(idx2, owner->positions().size() - 1); - URANGE_CHECK(idx3, owner->positions().size() - 1); - URANGE_CHECK(idx4, owner->positions().size() - 1); + URANGE_CHECK(idx1, owner->positions().size()); + URANGE_CHECK(idx2, owner->positions().size()); + URANGE_CHECK(idx3, owner->positions().size()); + URANGE_CHECK(idx4, owner->positions().size()); dp_forceField = owner; d_at1Idx = idx1; diff --git a/Code/ForceField/UFF/Nonbonded.cpp b/Code/ForceField/UFF/Nonbonded.cpp index adb969918..6768bca5a 100644 --- a/Code/ForceField/UFF/Nonbonded.cpp +++ b/Code/ForceField/UFF/Nonbonded.cpp @@ -35,8 +35,8 @@ vdWContrib::vdWContrib(ForceField *owner, unsigned int idx1, unsigned int idx2, PRECONDITION(owner, "bad owner"); PRECONDITION(at1Params, "bad params pointer"); PRECONDITION(at2Params, "bad params pointer"); - URANGE_CHECK(idx1, owner->positions().size() - 1); - URANGE_CHECK(idx2, owner->positions().size() - 1); + URANGE_CHECK(idx1, owner->positions().size()); + URANGE_CHECK(idx2, owner->positions().size()); dp_forceField = owner; d_at1Idx = idx1; diff --git a/Code/ForceField/UFF/PositionConstraint.cpp b/Code/ForceField/UFF/PositionConstraint.cpp index 9a95e04d1..f0af48169 100644 --- a/Code/ForceField/UFF/PositionConstraint.cpp +++ b/Code/ForceField/UFF/PositionConstraint.cpp @@ -23,7 +23,7 @@ PositionConstraintContrib::PositionConstraintContrib(ForceField *owner, double forceConst) { PRECONDITION(owner, "bad owner"); const RDGeom::PointPtrVect &pos = owner->positions(); - URANGE_CHECK(idx, pos.size() - 1); + URANGE_CHECK(idx, pos.size()); dp_forceField = owner; d_atIdx = idx; diff --git a/Code/ForceField/UFF/TorsionAngle.cpp b/Code/ForceField/UFF/TorsionAngle.cpp index 0a6ae494c..e6dd3e20d 100644 --- a/Code/ForceField/UFF/TorsionAngle.cpp +++ b/Code/ForceField/UFF/TorsionAngle.cpp @@ -94,10 +94,10 @@ TorsionAngleContrib::TorsionAngleContrib( PRECONDITION((idx1 != idx2 && idx1 != idx3 && idx1 != idx4 && idx2 != idx3 && idx2 != idx4 && idx3 != idx4), "degenerate points"); - URANGE_CHECK(idx1, owner->positions().size() - 1); - URANGE_CHECK(idx2, owner->positions().size() - 1); - URANGE_CHECK(idx3, owner->positions().size() - 1); - URANGE_CHECK(idx4, owner->positions().size() - 1); + URANGE_CHECK(idx1, owner->positions().size()); + URANGE_CHECK(idx2, owner->positions().size()); + URANGE_CHECK(idx3, owner->positions().size()); + URANGE_CHECK(idx4, owner->positions().size()); dp_forceField = owner; d_at1Idx = idx1; diff --git a/Code/ForceField/UFF/TorsionConstraint.cpp b/Code/ForceField/UFF/TorsionConstraint.cpp index cc04f3557..df7363220 100644 --- a/Code/ForceField/UFF/TorsionConstraint.cpp +++ b/Code/ForceField/UFF/TorsionConstraint.cpp @@ -37,10 +37,10 @@ TorsionConstraintContrib::TorsionConstraintContrib( unsigned int idx4, double minDihedralDeg, double maxDihedralDeg, double forceConst) { PRECONDITION(owner, "bad owner"); - URANGE_CHECK(idx1, owner->positions().size() - 1); - URANGE_CHECK(idx2, owner->positions().size() - 1); - URANGE_CHECK(idx3, owner->positions().size() - 1); - URANGE_CHECK(idx4, owner->positions().size() - 1); + URANGE_CHECK(idx1, owner->positions().size()); + URANGE_CHECK(idx2, owner->positions().size()); + URANGE_CHECK(idx3, owner->positions().size()); + URANGE_CHECK(idx4, owner->positions().size()); PRECONDITION((!(maxDihedralDeg < minDihedralDeg)) && ((maxDihedralDeg - minDihedralDeg) < 360.0), "bad bounds"); @@ -62,10 +62,10 @@ TorsionConstraintContrib::TorsionConstraintContrib( double maxDihedralDeg, double forceConst) { PRECONDITION(owner, "bad owner"); const RDGeom::PointPtrVect &pos = owner->positions(); - URANGE_CHECK(idx1, pos.size() - 1); - URANGE_CHECK(idx2, pos.size() - 1); - URANGE_CHECK(idx3, pos.size() - 1); - URANGE_CHECK(idx4, pos.size() - 1); + URANGE_CHECK(idx1, pos.size()); + URANGE_CHECK(idx2, pos.size()); + URANGE_CHECK(idx3, pos.size()); + URANGE_CHECK(idx4, pos.size()); PRECONDITION((!(maxDihedralDeg < minDihedralDeg)) && ((maxDihedralDeg - minDihedralDeg) < 360.0), "bad bounds"); diff --git a/Code/GraphMol/Bond.cpp b/Code/GraphMol/Bond.cpp index edfe95924..6c598cc67 100644 --- a/Code/GraphMol/Bond.cpp +++ b/Code/GraphMol/Bond.cpp @@ -82,12 +82,12 @@ unsigned int Bond::getOtherAtomIdx(const unsigned int thisIdx) const { } void Bond::setBeginAtomIdx(unsigned int what) { - if (dp_mol) URANGE_CHECK(what, getOwningMol().getNumAtoms() - 1); + if (dp_mol) URANGE_CHECK(what, getOwningMol().getNumAtoms()); d_beginAtomIdx = what; }; void Bond::setEndAtomIdx(unsigned int what) { - if (dp_mol) URANGE_CHECK(what, getOwningMol().getNumAtoms() - 1); + if (dp_mol) URANGE_CHECK(what, getOwningMol().getNumAtoms()); d_endAtomIdx = what; }; diff --git a/Code/GraphMol/ChemReactions/ReactionRunner.cpp b/Code/GraphMol/ChemReactions/ReactionRunner.cpp index 727ff6c59..097ff3e75 100644 --- a/Code/GraphMol/ChemReactions/ReactionRunner.cpp +++ b/Code/GraphMol/ChemReactions/ReactionRunner.cpp @@ -131,7 +131,7 @@ void recurseOverReactantCombinations( VectVectMatchVectType &matchesPerProduct, unsigned int level, VectMatchVectType combination) { unsigned int nReactants = matchesByReactant.size(); - URANGE_CHECK(level, nReactants - 1); + URANGE_CHECK(level, nReactants); PRECONDITION(combination.size() == nReactants, "bad combination size"); for (VectMatchVectType::const_iterator reactIt = matchesByReactant[level].begin(); diff --git a/Code/GraphMol/Conformer.cpp b/Code/GraphMol/Conformer.cpp index 4d1c0f8f1..489e32d68 100644 --- a/Code/GraphMol/Conformer.cpp +++ b/Code/GraphMol/Conformer.cpp @@ -50,7 +50,7 @@ const RDGeom::Point3D &Conformer::getAtomPos(unsigned int atomId) const { if (dp_mol) { PRECONDITION(dp_mol->getNumAtoms() == d_positions.size(), ""); } - URANGE_CHECK(atomId, d_positions.size() - 1); + URANGE_CHECK(atomId, d_positions.size()); return d_positions[atomId]; } @@ -58,7 +58,7 @@ RDGeom::Point3D &Conformer::getAtomPos(unsigned int atomId) { if (dp_mol) { PRECONDITION(dp_mol->getNumAtoms() == d_positions.size(), ""); } - URANGE_CHECK(atomId, d_positions.size() - 1); + URANGE_CHECK(atomId, d_positions.size()); return d_positions[atomId]; } } diff --git a/Code/GraphMol/Depictor/DepictUtils.cpp b/Code/GraphMol/Depictor/DepictUtils.cpp index 0b77cf1a9..3f01383ec 100644 --- a/Code/GraphMol/Depictor/DepictUtils.cpp +++ b/Code/GraphMol/Depictor/DepictUtils.cpp @@ -366,7 +366,7 @@ void getNbrAtomAndBondIds(unsigned int aid, const RDKit::ROMol *mol, RDKit::INT_VECT &aids, RDKit::INT_VECT &bids) { CHECK_INVARIANT(mol, ""); unsigned int na = mol->getNumAtoms(); - URANGE_CHECK(aid, na - 1); + URANGE_CHECK(aid, na); RDKit::ROMol::ADJ_ITER nbrIdx, endNbrs; boost::tie(nbrIdx, endNbrs) = mol->getAtomNeighbors(mol->getAtomWithIdx(aid)); diff --git a/Code/GraphMol/FileParsers/MolFileParser.cpp b/Code/GraphMol/FileParsers/MolFileParser.cpp index f558bac97..057fb92d5 100644 --- a/Code/GraphMol/FileParsers/MolFileParser.cpp +++ b/Code/GraphMol/FileParsers/MolFileParser.cpp @@ -168,7 +168,7 @@ void ParseOldAtomList(RWMol *mol, const std::string &text, unsigned int line) { throw FileParseException(errout.str()); } - URANGE_CHECK(idx, mol->getNumAtoms() - 1); + URANGE_CHECK(idx, mol->getNumAtoms()); QueryAtom a(*(mol->getAtomWithIdx(idx))); ATOM_OR_QUERY *q = new ATOM_OR_QUERY; @@ -785,7 +785,7 @@ void ParseNewAtomList(RWMol *mol, const std::string &text, unsigned int line) { << line; throw FileParseException(errout.str()); } - URANGE_CHECK(idx, mol->getNumAtoms() - 1); + URANGE_CHECK(idx, mol->getNumAtoms()); QueryAtom *a = 0; int nQueries; @@ -972,7 +972,7 @@ void ParseAtomAlias(RWMol *mol, std::string text, const std::string &nextLine, << line; throw FileParseException(errout.str()); } - URANGE_CHECK(idx, mol->getNumAtoms() - 1); + URANGE_CHECK(idx, mol->getNumAtoms()); Atom *at = mol->getAtomWithIdx(idx); at->setProp(common_properties::molFileAlias, nextLine); }; @@ -991,7 +991,7 @@ void ParseAtomValue(RWMol *mol, std::string text, unsigned int line) { << line; throw FileParseException(errout.str()); } - URANGE_CHECK(idx, mol->getNumAtoms() - 1); + URANGE_CHECK(idx, mol->getNumAtoms()); Atom *at = mol->getAtomWithIdx(idx); at->setProp(common_properties::molFileValue, text.substr(7, text.length() - 7)); diff --git a/Code/GraphMol/ForceFieldHelpers/CrystalFF/TorsionAngleM6.cpp b/Code/GraphMol/ForceFieldHelpers/CrystalFF/TorsionAngleM6.cpp index 46b9f8635..996ebeb5f 100644 --- a/Code/GraphMol/ForceFieldHelpers/CrystalFF/TorsionAngleM6.cpp +++ b/Code/GraphMol/ForceFieldHelpers/CrystalFF/TorsionAngleM6.cpp @@ -57,10 +57,10 @@ TorsionAngleContribM6::TorsionAngleContribM6( PRECONDITION((idx1 != idx2) && (idx1 != idx3) && (idx1 != idx4) && (idx2 != idx3) && (idx2 != idx4) && (idx3 != idx4), "degenerate points"); - URANGE_CHECK(idx1, owner->positions().size() - 1); - URANGE_CHECK(idx2, owner->positions().size() - 1); - URANGE_CHECK(idx3, owner->positions().size() - 1); - URANGE_CHECK(idx4, owner->positions().size() - 1); + URANGE_CHECK(idx1, owner->positions().size()); + URANGE_CHECK(idx2, owner->positions().size()); + URANGE_CHECK(idx3, owner->positions().size()); + URANGE_CHECK(idx4, owner->positions().size()); }; double TorsionAngleContribM6::getEnergy(double *pos) const { diff --git a/Code/GraphMol/ForceFieldHelpers/MMFF/AtomTyper.h b/Code/GraphMol/ForceFieldHelpers/MMFF/AtomTyper.h index 1a3ac9094..cd9bd57af 100644 --- a/Code/GraphMol/ForceFieldHelpers/MMFF/AtomTyper.h +++ b/Code/GraphMol/ForceFieldHelpers/MMFF/AtomTyper.h @@ -63,17 +63,17 @@ class MMFFMolProperties { const ForceFields::MMFF::MMFFBond *getMMFFBondStretchEmpiricalRuleParams( const ROMol &mol, const Bond *bond); boost::uint8_t getMMFFAtomType(const unsigned int idx) { - URANGE_CHECK(idx, this->d_MMFFAtomPropertiesPtrVect.size() - 1); + URANGE_CHECK(idx, this->d_MMFFAtomPropertiesPtrVect.size()); return this->d_MMFFAtomPropertiesPtrVect[idx]->mmffAtomType; }; double getMMFFFormalCharge(const unsigned int idx) { - URANGE_CHECK(idx, this->d_MMFFAtomPropertiesPtrVect.size() - 1); + URANGE_CHECK(idx, this->d_MMFFAtomPropertiesPtrVect.size()); return this->d_MMFFAtomPropertiesPtrVect[idx]->mmffFormalCharge; }; double getMMFFPartialCharge(const unsigned int idx) { - URANGE_CHECK(idx, this->d_MMFFAtomPropertiesPtrVect.size() - 1); + URANGE_CHECK(idx, this->d_MMFFAtomPropertiesPtrVect.size()); return this->d_MMFFAtomPropertiesPtrVect[idx]->mmffPartialCharge; }; @@ -148,12 +148,12 @@ class MMFFMolProperties { void setMMFFHeavyAtomType(const RingMembershipSize &rmSize, const Atom *atom); void setMMFFHydrogenType(const Atom *atom); void setMMFFFormalCharge(const unsigned int idx, const double fChg) { - URANGE_CHECK(idx, this->d_MMFFAtomPropertiesPtrVect.size() - 1); + URANGE_CHECK(idx, this->d_MMFFAtomPropertiesPtrVect.size()); this->d_MMFFAtomPropertiesPtrVect[idx]->mmffFormalCharge = fChg; }; void setMMFFPartialCharge(const unsigned int idx, const double pChg) { - URANGE_CHECK(idx, this->d_MMFFAtomPropertiesPtrVect.size() - 1); + URANGE_CHECK(idx, this->d_MMFFAtomPropertiesPtrVect.size()); this->d_MMFFAtomPropertiesPtrVect[idx]->mmffPartialCharge = pChg; }; diff --git a/Code/GraphMol/ForceFieldHelpers/MMFF/testMMFFHelpers.cpp b/Code/GraphMol/ForceFieldHelpers/MMFF/testMMFFHelpers.cpp index 702435291..8ffa3c40f 100644 --- a/Code/GraphMol/ForceFieldHelpers/MMFF/testMMFFHelpers.cpp +++ b/Code/GraphMol/ForceFieldHelpers/MMFF/testMMFFHelpers.cpp @@ -162,6 +162,11 @@ void testMMFFBuilder1() { TEST_ASSERT(mmffMolProperties); TEST_ASSERT(mmffMolProperties->isValid()); field = new ForceFields::ForceField(); + // add the atomic positions: + for (unsigned int i = 0; i < mol->getNumAtoms(); ++i) { + field->positions().push_back(&(conf->getAtomPos(i))); + } + MMFF::Tools::addBonds(*mol, mmffMolProperties, field); TEST_ASSERT(field->contribs().size() == 3); @@ -207,6 +212,11 @@ void testMMFFBuilder1() { TEST_ASSERT(mmffMolProperties); TEST_ASSERT(mmffMolProperties->isValid()); field = new ForceFields::ForceField(); + // add the atomic positions: + for (unsigned int i = 0; i < mol->getNumAtoms(); ++i) { + field->positions().push_back(&(conf2->getAtomPos(i))); + } + MMFF::Tools::addBonds(*mol, mmffMolProperties, field); TEST_ASSERT(field->contribs().size() == 3); @@ -240,6 +250,11 @@ void testMMFFBuilder1() { TEST_ASSERT(mmffMolProperties->isValid()); field = new ForceFields::ForceField(); + // add the atomic positions: + for (unsigned int i = 0; i < mol->getNumAtoms(); ++i) { + field->positions().push_back(&(conf3->getAtomPos(i))); + } + MMFF::Tools::addBonds(*mol, mmffMolProperties, field); TEST_ASSERT(field->contribs().size() == 1); @@ -259,6 +274,9 @@ void testMMFFBuilder1() { mol2 = MolOps::addHs(*mol); TEST_ASSERT(mol2->getNumAtoms() == 6); + Conformer *conf4 = new Conformer(mol2->getNumAtoms()); + cid = static_cast(mol2->addConformer(conf4, true)); + delete field; delete mmffMolProperties; @@ -267,6 +285,11 @@ void testMMFFBuilder1() { TEST_ASSERT(mmffMolProperties->isValid()); field = new ForceFields::ForceField(); + // add the atomic positions: + for (unsigned int i = 0; i < mol2->getNumAtoms(); ++i) { + field->positions().push_back(&(conf4->getAtomPos(i))); + } + MMFF::Tools::addBonds(*mol2, mmffMolProperties, field); TEST_ASSERT(field->contribs().size() == 5); @@ -535,9 +558,14 @@ void testSFIssue1653802() { MMFF::MMFFMolProperties *mmffMolProperties = new MMFF::MMFFMolProperties(*mol); TEST_ASSERT(mmffMolProperties); - + boost::shared_array nbrMat; field = new ForceFields::ForceField(); + // add the atomic positions: + for (unsigned int i = 0; i < mol->getNumAtoms(); ++i) { + field->positions().push_back(&((mol->getConformer().getAtomPos(i)))); + } + MMFF::Tools::addBonds(*mol, mmffMolProperties, field); TEST_ASSERT(field->contribs().size() == 8); diff --git a/Code/GraphMol/ForceFieldHelpers/UFF/testUFFHelpers.cpp b/Code/GraphMol/ForceFieldHelpers/UFF/testUFFHelpers.cpp index 2ac0f24c2..2cd6e5866 100644 --- a/Code/GraphMol/ForceFieldHelpers/UFF/testUFFHelpers.cpp +++ b/Code/GraphMol/ForceFieldHelpers/UFF/testUFFHelpers.cpp @@ -220,6 +220,11 @@ void testUFFBuilder1() { TEST_ASSERT(foundAll); TEST_ASSERT(types.size() == mol->getNumAtoms()); field = new ForceFields::ForceField(); + // add the atomic positions: + for (unsigned int i = 0; i < mol->getNumAtoms(); ++i) { + field->positions().push_back(&((conf->getAtomPos(i)))); + } + UFF::Tools::addBonds(*mol, types, field); TEST_ASSERT(field->contribs().size() == 3); @@ -260,6 +265,11 @@ void testUFFBuilder1() { TEST_ASSERT(foundAll); TEST_ASSERT(types.size() == mol->getNumAtoms()); field = new ForceFields::ForceField(); + // add the atomic positions: + for (unsigned int i = 0; i < mol->getNumAtoms(); ++i) { + field->positions().push_back(&(conf2->getAtomPos(i))); + } + UFF::Tools::addBonds(*mol, types, field); TEST_ASSERT(field->contribs().size() == 3); @@ -288,6 +298,11 @@ void testUFFBuilder1() { TEST_ASSERT(types.size() == mol->getNumAtoms()); field = new ForceFields::ForceField(); + // add the atomic positions: + for (unsigned int i = 0; i < mol->getNumAtoms(); ++i) { + field->positions().push_back(&(conf3->getAtomPos(i))); + } + UFF::Tools::addBonds(*mol, types, field); TEST_ASSERT(field->contribs().size() == 1); @@ -310,8 +325,15 @@ void testUFFBuilder1() { boost::tie(types, foundAll) = UFF::getAtomTypes(*mol2); TEST_ASSERT(foundAll); TEST_ASSERT(types.size() == mol2->getNumAtoms()); + Conformer *conf4 = new Conformer(mol2->getNumAtoms()); + cid = static_cast(mol2->addConformer(conf4, true)); field = new ForceFields::ForceField(); + // add the atomic positions: + for (unsigned int i = 0; i < mol2->getNumAtoms(); ++i) { + field->positions().push_back(&(conf4->getAtomPos(i))); + } + UFF::Tools::addBonds(*mol2, types, field); TEST_ASSERT(field->contribs().size() == 5); @@ -448,10 +470,36 @@ void testUFFBuilder2() { RWMol *mol = MolFileToMol(pathName + "/small1.mol", false); TEST_ASSERT(mol); MolOps::sanitizeMol(*mol); + + UFF::AtomicParamVect types; + bool foundAll; + boost::shared_array nbrMat; + boost::tie(types, foundAll) = UFF::getAtomTypes(*mol); + + ForceFields::ForceField *field; + field = new ForceFields::ForceField(); + + // add the atomic positions: + for (unsigned int i = 0; i < mol->getNumAtoms(); ++i) { + field->positions().push_back(&((mol->getConformer().getAtomPos(i)))); + } + + UFF::Tools::addBonds(*mol, types, field); + nbrMat = UFF::Tools::buildNeighborMatrix(*mol); + UFF::Tools::addAngles(*mol, types, field); + UFF::Tools::addTorsions(*mol, types, field); + // std::cout << field->contribs().size() << std::endl; + UFF::Tools::addNonbonded(*mol, 0, types, field, nbrMat); + delete field; + + field = UFF::constructForceField(*mol); + field->initialize(); + field->minimize(); + delete field; + RWMol *mol2 = new RWMol(*mol); - ForceFields::ForceField *field; - field = UFF::constructForceField(*mol); + field = UFF::constructForceField(*mol2); TEST_ASSERT(field); field->initialize(); int needMore = field->minimize(); @@ -788,6 +836,11 @@ void testSFIssue1653802() { TEST_ASSERT(foundAll); TEST_ASSERT(types.size() == mol->getNumAtoms()); field = new ForceFields::ForceField(); + // add the atomic positions: + for (unsigned int i = 0; i < mol->getNumAtoms(); ++i) { + field->positions().push_back(&((mol->getConformer().getAtomPos(i)))); + } + UFF::Tools::addBonds(*mol, types, field); TEST_ASSERT(field->contribs().size() == 8); diff --git a/Code/GraphMol/MolTransforms/MolTransforms.cpp b/Code/GraphMol/MolTransforms/MolTransforms.cpp index f1f6ed3d5..34f2fa896 100644 --- a/Code/GraphMol/MolTransforms/MolTransforms.cpp +++ b/Code/GraphMol/MolTransforms/MolTransforms.cpp @@ -402,8 +402,8 @@ void _toBeMovedIdxList(const ROMol &mol, unsigned int iAtomId, double getBondLength(const Conformer &conf, unsigned int iAtomId, unsigned int jAtomId) { const RDGeom::POINT3D_VECT &pos = conf.getPositions(); - URANGE_CHECK(iAtomId, pos.size() - 1); - URANGE_CHECK(jAtomId, pos.size() - 1); + URANGE_CHECK(iAtomId, pos.size()); + URANGE_CHECK(jAtomId, pos.size()); return (pos[iAtomId] - pos[jAtomId]).length(); } @@ -411,8 +411,8 @@ double getBondLength(const Conformer &conf, unsigned int iAtomId, void setBondLength(Conformer &conf, unsigned int iAtomId, unsigned int jAtomId, double value) { RDGeom::POINT3D_VECT &pos = conf.getPositions(); - URANGE_CHECK(iAtomId, pos.size() - 1); - URANGE_CHECK(jAtomId, pos.size() - 1); + URANGE_CHECK(iAtomId, pos.size()); + URANGE_CHECK(jAtomId, pos.size()); ROMol &mol = conf.getOwningMol(); Bond *bond = mol.getBondBetweenAtoms(iAtomId, jAtomId); if (!bond) throw ValueErrorException("atoms i and j must be bonded"); @@ -436,9 +436,9 @@ void setBondLength(Conformer &conf, unsigned int iAtomId, unsigned int jAtomId, double getAngleRad(const Conformer &conf, unsigned int iAtomId, unsigned int jAtomId, unsigned int kAtomId) { const RDGeom::POINT3D_VECT &pos = conf.getPositions(); - URANGE_CHECK(iAtomId, pos.size() - 1); - URANGE_CHECK(jAtomId, pos.size() - 1); - URANGE_CHECK(kAtomId, pos.size() - 1); + URANGE_CHECK(iAtomId, pos.size()); + URANGE_CHECK(jAtomId, pos.size()); + URANGE_CHECK(kAtomId, pos.size()); RDGeom::Point3D rJI = pos[iAtomId] - pos[jAtomId]; double rJISqLength = rJI.lengthSq(); if (rJISqLength <= 1.e-16) @@ -453,9 +453,9 @@ double getAngleRad(const Conformer &conf, unsigned int iAtomId, void setAngleRad(Conformer &conf, unsigned int iAtomId, unsigned int jAtomId, unsigned int kAtomId, double value) { RDGeom::POINT3D_VECT &pos = conf.getPositions(); - URANGE_CHECK(iAtomId, pos.size() - 1); - URANGE_CHECK(jAtomId, pos.size() - 1); - URANGE_CHECK(kAtomId, pos.size() - 1); + URANGE_CHECK(iAtomId, pos.size()); + URANGE_CHECK(jAtomId, pos.size()); + URANGE_CHECK(kAtomId, pos.size()); ROMol &mol = conf.getOwningMol(); Bond *bondJI = mol.getBondBetweenAtoms(jAtomId, iAtomId); if (!bondJI) throw ValueErrorException("atoms i and j must be bonded"); @@ -501,10 +501,10 @@ double getDihedralRad(const Conformer &conf, unsigned int iAtomId, unsigned int jAtomId, unsigned int kAtomId, unsigned int lAtomId) { const RDGeom::POINT3D_VECT &pos = conf.getPositions(); - URANGE_CHECK(iAtomId, pos.size() - 1); - URANGE_CHECK(jAtomId, pos.size() - 1); - URANGE_CHECK(kAtomId, pos.size() - 1); - URANGE_CHECK(lAtomId, pos.size() - 1); + URANGE_CHECK(iAtomId, pos.size()); + URANGE_CHECK(jAtomId, pos.size()); + URANGE_CHECK(kAtomId, pos.size()); + URANGE_CHECK(lAtomId, pos.size()); RDGeom::Point3D rIJ = pos[jAtomId] - pos[iAtomId]; double rIJSqLength = rIJ.lengthSq(); if (rIJSqLength <= 1.e-16) @@ -531,10 +531,10 @@ double getDihedralRad(const Conformer &conf, unsigned int iAtomId, void setDihedralRad(Conformer &conf, unsigned int iAtomId, unsigned int jAtomId, unsigned int kAtomId, unsigned int lAtomId, double value) { RDGeom::POINT3D_VECT &pos = conf.getPositions(); - URANGE_CHECK(iAtomId, pos.size() - 1); - URANGE_CHECK(jAtomId, pos.size() - 1); - URANGE_CHECK(kAtomId, pos.size() - 1); - URANGE_CHECK(lAtomId, pos.size() - 1); + URANGE_CHECK(iAtomId, pos.size()); + URANGE_CHECK(jAtomId, pos.size()); + URANGE_CHECK(kAtomId, pos.size()); + URANGE_CHECK(lAtomId, pos.size()); ROMol &mol = conf.getOwningMol(); Bond *bondIJ = mol.getBondBetweenAtoms(iAtomId, jAtomId); if (!bondIJ) throw ValueErrorException("atoms i and j must be bonded"); diff --git a/Code/GraphMol/ROMol.cpp b/Code/GraphMol/ROMol.cpp index 31092e285..d8e302f50 100644 --- a/Code/GraphMol/ROMol.cpp +++ b/Code/GraphMol/ROMol.cpp @@ -146,7 +146,7 @@ unsigned int ROMol::getNumHeavyAtoms() const { Atom *ROMol::getAtomWithIdx(unsigned int idx) { PRECONDITION(getNumAtoms() > 0, "no atoms"); - URANGE_CHECK(idx, getNumAtoms() - 1); + URANGE_CHECK(idx, getNumAtoms()); MolGraph::vertex_descriptor vd = boost::vertex(idx, d_graph); Atom *res = d_graph[vd].get(); @@ -156,7 +156,7 @@ Atom *ROMol::getAtomWithIdx(unsigned int idx) { const Atom *ROMol::getAtomWithIdx(unsigned int idx) const { PRECONDITION(getNumAtoms() > 0, "no atoms"); - URANGE_CHECK(idx, getNumAtoms() - 1); + URANGE_CHECK(idx, getNumAtoms()); MolGraph::vertex_descriptor vd = boost::vertex(idx, d_graph); const Atom *res = d_graph[vd].get(); @@ -244,7 +244,7 @@ unsigned int ROMol::getNumBonds(bool onlyHeavy) const { Bond *ROMol::getBondWithIdx(unsigned int idx) { PRECONDITION(getNumBonds() > 0, "no bonds"); - URANGE_CHECK(idx, getNumBonds() - 1); + URANGE_CHECK(idx, getNumBonds()); BOND_ITER_PAIR bIter = getEdges(); for (unsigned int i = 0; i < idx; i++) ++bIter.first; @@ -256,7 +256,7 @@ Bond *ROMol::getBondWithIdx(unsigned int idx) { const Bond *ROMol::getBondWithIdx(unsigned int idx) const { PRECONDITION(getNumBonds() > 0, "no bonds"); - URANGE_CHECK(idx, getNumBonds() - 1); + URANGE_CHECK(idx, getNumBonds()); BOND_ITER_PAIR bIter = getEdges(); for (unsigned int i = 0; i < idx; i++) ++bIter.first; @@ -267,8 +267,8 @@ const Bond *ROMol::getBondWithIdx(unsigned int idx) const { } Bond *ROMol::getBondBetweenAtoms(unsigned int idx1, unsigned int idx2) { - URANGE_CHECK(idx1, getNumAtoms() - 1); - URANGE_CHECK(idx2, getNumAtoms() - 1); + URANGE_CHECK(idx1, getNumAtoms()); + URANGE_CHECK(idx2, getNumAtoms()); Bond *res = 0; MolGraph::edge_descriptor edge; @@ -283,8 +283,8 @@ Bond *ROMol::getBondBetweenAtoms(unsigned int idx1, unsigned int idx2) { const Bond *ROMol::getBondBetweenAtoms(unsigned int idx1, unsigned int idx2) const { - URANGE_CHECK(idx1, getNumAtoms() - 1); - URANGE_CHECK(idx2, getNumAtoms() - 1); + URANGE_CHECK(idx1, getNumAtoms()); + URANGE_CHECK(idx2, getNumAtoms()); const Bond *res = 0; MolGraph::edge_descriptor edge; @@ -341,8 +341,8 @@ unsigned int ROMol::addAtom(Atom::ATOM_SPTR atom_sp, bool updateLabel) { } unsigned int ROMol::addBond(Bond *bond_pin, bool takeOwnership) { PRECONDITION(bond_pin, "null bond passed in"); - URANGE_CHECK(bond_pin->getBeginAtomIdx(), getNumAtoms() - 1); - URANGE_CHECK(bond_pin->getEndAtomIdx(), getNumAtoms() - 1); + URANGE_CHECK(bond_pin->getBeginAtomIdx(), getNumAtoms()); + URANGE_CHECK(bond_pin->getEndAtomIdx(), getNumAtoms()); PRECONDITION(bond_pin->getBeginAtomIdx() != bond_pin->getEndAtomIdx(), "attempt to add self-bond"); PRECONDITION(!(boost::edge(bond_pin->getBeginAtomIdx(), diff --git a/Code/GraphMol/RWMol.cpp b/Code/GraphMol/RWMol.cpp index e89f0c057..2fd22cabc 100644 --- a/Code/GraphMol/RWMol.cpp +++ b/Code/GraphMol/RWMol.cpp @@ -131,7 +131,7 @@ void RWMol::replaceAtom(unsigned int idx, Atom *atom_pin, bool updateLabel, bool preserveProps) { RDUNUSED_PARAM(updateLabel); PRECONDITION(atom_pin, "bad atom passed to replaceAtom"); - URANGE_CHECK(idx, getNumAtoms() - 1); + URANGE_CHECK(idx, getNumAtoms()); Atom *atom_p = atom_pin->copy(); atom_p->setOwningMol(this); atom_p->setIdx(idx); @@ -146,7 +146,7 @@ void RWMol::replaceAtom(unsigned int idx, Atom *atom_pin, bool updateLabel, void RWMol::replaceBond(unsigned int idx, Bond *bond_pin, bool preserveProps) { PRECONDITION(bond_pin, "bad bond passed to replaceBond"); - URANGE_CHECK(idx, getNumBonds() - 1); + URANGE_CHECK(idx, getNumBonds()); BOND_ITER_PAIR bIter = getEdges(); for (unsigned int i = 0; i < idx; i++) ++bIter.first; BOND_SPTR obond = d_graph[*(bIter.first)]; @@ -271,8 +271,8 @@ void RWMol::removeAtom(Atom *atom) { unsigned int RWMol::addBond(unsigned int atomIdx1, unsigned int atomIdx2, Bond::BondType bondType) { - URANGE_CHECK(atomIdx1, getNumAtoms() - 1); - URANGE_CHECK(atomIdx2, getNumAtoms() - 1); + URANGE_CHECK(atomIdx1, getNumAtoms()); + URANGE_CHECK(atomIdx2, getNumAtoms()); PRECONDITION(atomIdx1 != atomIdx2, "attempt to add self-bond"); PRECONDITION(!(boost::edge(atomIdx1, atomIdx2, d_graph).second), "bond already exists"); @@ -322,8 +322,8 @@ unsigned int RWMol::addBond(Atom::ATOM_SPTR atom1, Atom::ATOM_SPTR atom2, } void RWMol::removeBond(unsigned int aid1, unsigned int aid2) { - URANGE_CHECK(aid1, getNumAtoms() - 1); - URANGE_CHECK(aid2, getNumAtoms() - 1); + URANGE_CHECK(aid1, getNumAtoms()); + URANGE_CHECK(aid2, getNumAtoms()); Bond *bnd = getBondBetweenAtoms(aid1, aid2); if (!bnd) return; unsigned int idx = bnd->getIdx(); @@ -388,7 +388,7 @@ void RWMol::removeBond(unsigned int aid1, unsigned int aid2) { } Bond *RWMol::createPartialBond(unsigned int atomIdx1, Bond::BondType bondType) { - URANGE_CHECK(atomIdx1, getNumAtoms() - 1); + URANGE_CHECK(atomIdx1, getNumAtoms()); Bond *b = new Bond(bondType); b->setOwningMol(this); @@ -399,7 +399,7 @@ Bond *RWMol::createPartialBond(unsigned int atomIdx1, Bond::BondType bondType) { unsigned int RWMol::finishPartialBond(unsigned int atomIdx2, int bondBookmark, Bond::BondType bondType) { PRECONDITION(hasBondBookmark(bondBookmark), "no such partial bond"); - URANGE_CHECK(atomIdx2, getNumAtoms() - 1); + URANGE_CHECK(atomIdx2, getNumAtoms()); Bond *bsp = getBondWithBookmark(bondBookmark); if (bondType == Bond::UNSPECIFIED) { diff --git a/Code/GraphMol/Trajectory/Trajectory.cpp b/Code/GraphMol/Trajectory/Trajectory.cpp index 179a8dd99..831ee5635 100644 --- a/Code/GraphMol/Trajectory/Trajectory.cpp +++ b/Code/GraphMol/Trajectory/Trajectory.cpp @@ -24,7 +24,7 @@ RDGeom::Point2D Snapshot::getPoint2D(unsigned int pointNum) const { PRECONDITION(d_trajectory, "d_trajectory must not be NULL"); PRECONDITION(d_trajectory->dimension() == 2, "d_dimension must be == 2"); PRECONDITION(d_trajectory->numPoints(), "d_numPoints must be > 0"); - URANGE_CHECK(pointNum, d_trajectory->numPoints() - 1); + URANGE_CHECK(pointNum, d_trajectory->numPoints()); unsigned int i = pointNum * d_trajectory->dimension(); return RDGeom::Point2D(d_pos[i], d_pos[i + 1]); } @@ -34,7 +34,7 @@ RDGeom::Point3D Snapshot::getPoint3D(unsigned int pointNum) const { PRECONDITION(d_trajectory, "d_trajectory must not be NULL"); PRECONDITION(d_trajectory->dimension() >= 2, "d_dimension must be >= 2"); PRECONDITION(d_trajectory->numPoints(), "d_numPoints must be > 0"); - URANGE_CHECK(pointNum, d_trajectory->numPoints() - 1); + URANGE_CHECK(pointNum, d_trajectory->numPoints()); unsigned int i = pointNum * d_trajectory->dimension(); return (RDGeom::Point3D(d_pos[i], d_pos[i + 1], (d_trajectory->dimension() == 3) ? d_pos[i + 2] : 0.0)); @@ -65,19 +65,19 @@ unsigned int Trajectory::addSnapshot(const Snapshot &s) { } const Snapshot &Trajectory::getSnapshot(unsigned int snapshotNum) const { - URANGE_CHECK(snapshotNum + 1, d_snapshotVect->size()); + URANGE_CHECK(snapshotNum, d_snapshotVect->size()); return (*d_snapshotVect)[snapshotNum]; } unsigned int Trajectory::insertSnapshot(unsigned int snapshotNum, Snapshot s) { - URANGE_CHECK(snapshotNum, d_snapshotVect->size()); + URANGE_CHECK(snapshotNum, d_snapshotVect->size()+1); s.d_trajectory = this; return (d_snapshotVect->insert(d_snapshotVect->begin() + snapshotNum, s) - d_snapshotVect->begin()); } unsigned int Trajectory::removeSnapshot(unsigned int snapshotNum) { - URANGE_CHECK(snapshotNum + 1, d_snapshotVect->size()); + URANGE_CHECK(snapshotNum, d_snapshotVect->size()); return (d_snapshotVect->erase(d_snapshotVect->begin() + snapshotNum) - d_snapshotVect->begin()); } diff --git a/Code/GraphMol/Wrap/rough_test.py b/Code/GraphMol/Wrap/rough_test.py index f7d19653c..ad4ae6705 100644 --- a/Code/GraphMol/Wrap/rough_test.py +++ b/Code/GraphMol/Wrap/rough_test.py @@ -3996,7 +3996,7 @@ CAS<~> if platform.system() == 'Windows': details = details.replace('\\', '/') self.assertTrue("Code/GraphMol/ROMol.cpp" in details) - self.assertTrue("Failed Expression: 3 <= 0" in details) + self.assertTrue("Failed Expression: 3 < 1" in details) self.assertTrue("RDKIT:" in details) self.assertTrue(__version__ in details) @@ -4360,6 +4360,15 @@ M END "CN[C@@H](C)C(=O)N[C@H](C(=O)N1C[C@@H](Oc2ccccc2)C[C@H]1C(=O)N[C@@H]1CCCc2ccccc21)C1CCCCC1"), True)) + def testGithub1461(self): + # this is simple, it should throw a precondition and not seg fault + m = Chem.RWMol() + try: + m.AddBond(0,1,Chem.BondType.SINGLE) + self.assertFalse(True) # shouldn't get here + except RuntimeError: + pass + if __name__ == '__main__': if "RDTESTCASE" in os.environ: suite = unittest.TestSuite() diff --git a/Code/ML/InfoTheory/InfoBitRanker.cpp b/Code/ML/InfoTheory/InfoBitRanker.cpp index 40df27e25..7f933bc65 100644 --- a/Code/ML/InfoTheory/InfoBitRanker.cpp +++ b/Code/ML/InfoTheory/InfoBitRanker.cpp @@ -42,7 +42,7 @@ void InfoBitRanker::setBiasList(RDKit::INT_VECT &classList) { // finally make sure all the class ID in d_biasList are within range for (bi = d_biasList.begin(); bi != d_biasList.end(); bi++) { - URANGE_CHECK(static_cast(*bi), d_classes - 1); + URANGE_CHECK(static_cast(*bi), d_classes); } } @@ -115,7 +115,7 @@ double InfoBitRanker::BiasInfoEntropyGain(RDKit::USHORT *resMat) const { void InfoBitRanker::accumulateVotes(const ExplicitBitVect &bv, unsigned int label) { - URANGE_CHECK(label, d_classes - 1); + URANGE_CHECK(label, d_classes); CHECK_INVARIANT(bv.getNumBits() == d_dims, "Incorrect bit vector size"); d_nInst += 1; @@ -129,7 +129,7 @@ void InfoBitRanker::accumulateVotes(const ExplicitBitVect &bv, void InfoBitRanker::accumulateVotes(const SparseBitVect &bv, unsigned int label) { - URANGE_CHECK(label, d_classes - 1); + URANGE_CHECK(label, d_classes); CHECK_INVARIANT(bv.getNumBits() == d_dims, "Incorrect bit vector size"); d_nInst += 1; diff --git a/Code/Numerics/SymmMatrix.h b/Code/Numerics/SymmMatrix.h index 2c0165217..92e3d95ca 100644 --- a/Code/Numerics/SymmMatrix.h +++ b/Code/Numerics/SymmMatrix.h @@ -80,8 +80,8 @@ class SymmMatrix { } TYPE getVal(unsigned int i, unsigned int j) const { - URANGE_CHECK(i, d_size - 1); - URANGE_CHECK(j, d_size - 1); + URANGE_CHECK(i, d_size); + URANGE_CHECK(j, d_size); unsigned int id; if (i >= j) { id = i * (i + 1) / 2 + j; @@ -92,8 +92,8 @@ class SymmMatrix { } void setVal(unsigned int i, unsigned int j, TYPE val) { - URANGE_CHECK(i, d_size - 1); - URANGE_CHECK(j, d_size - 1); + URANGE_CHECK(i, d_size); + URANGE_CHECK(j, d_size); unsigned int id; if (i >= j) { id = i * (i + 1) / 2 + j; diff --git a/Code/RDGeneral/Invariant.h b/Code/RDGeneral/Invariant.h index be9f1a683..5862d5f12 100644 --- a/Code/RDGeneral/Invariant.h +++ b/Code/RDGeneral/Invariant.h @@ -138,9 +138,9 @@ std::ostream& operator<<(std::ostream& s, const Invariant& inv); } #define URANGE_CHECK(x, hi) \ - if ((x) > (hi)) { \ + if (x >= (hi)) { \ std::stringstream errstr; \ - errstr << x << " <= " << hi; \ + errstr << x << " < " << hi; \ Invar::Invariant inv("Range Error", #x, errstr.str().c_str(), __FILE__, \ __LINE__); \ BOOST_LOG(rdErrorLog) << "\n\n****\n" << inv << "****\n\n"; \ @@ -163,7 +163,7 @@ std::ostream& operator<<(std::ostream& s, const Invariant& inv); #define UNDER_CONSTRUCTION(fn) assert(0); #define RANGE_CHECK(lo, x, hi) \ assert((lo) <= (hi) && (x) >= (lo) && (x) <= (hi)); -#define URANGE_CHECK(lo, x, hi) assert((x) <= (hi)); +#define URANGE_CHECK(lo, x, hi) assert((hi>0) && (x < hi)); #define TEST_ASSERT(expr) assert(expr); #elif INVARIANT_SILENT_METHOD From 58ede0f81b96d12ba7186967814edd03864b2d03 Mon Sep 17 00:00:00 2001 From: Brian Kelley Date: Tue, 12 Sep 2017 11:41:21 -0400 Subject: [PATCH 13/44] Dev/rgroup decomp freefunction (#1557) * Adds RGroupDecomp free function and python wrapper * Fixes subtle bug, adds new RGroupDecomp API * Updates results for the subtle bug fix. Verified results were correct. * Removes smilesCaching. * Changes RGroupDecompose ordering, adds docstrings and more tests --- .../RGroupDecomposition/RGroupDecomp.cpp | 158 ++++++++++++++---- .../RGroupDecomposition/RGroupDecomp.h | 13 ++ .../Wrap/rdRGroupComposition.cpp | 115 ++++++++++++- .../RGroupDecomposition/Wrap/test_rgroups.py | 29 +++- .../RGroupDecomposition/testRGroupDecomp.cpp | 8 +- Code/RDGeneral/types.cpp | 2 +- Code/RDGeneral/types.h | 1 + 7 files changed, 273 insertions(+), 53 deletions(-) diff --git a/Code/GraphMol/RGroupDecomposition/RGroupDecomp.cpp b/Code/GraphMol/RGroupDecomposition/RGroupDecomp.cpp index 78b0b1be1..4d2fb6450 100644 --- a/Code/GraphMol/RGroupDecomposition/RGroupDecomp.cpp +++ b/Code/GraphMol/RGroupDecomposition/RGroupDecomp.cpp @@ -52,6 +52,7 @@ namespace RDKit { namespace { const std::string RLABEL = "tempRlabel"; const std::string SIDECHAIN_RLABELS = "sideChainRlabels"; +const std::string done = "RLABEL_PROCESSED"; bool setLabel(Atom *atom, int label, std::set &labels, int &maxLabel, bool relabel, const std::string &type) { @@ -181,6 +182,7 @@ bool RGroupDecompositionParameters::prepareCore(RWMol &core, namespace { // RGroup Class to hold the attached bits + struct RGroupData { boost::shared_ptr combinedMol; std::vector > mols; // All the mols in the rgroup @@ -188,7 +190,15 @@ struct RGroupData { std::string smiles; // smiles for all the mols in the rgroup (with attachments) std::set attachments; // attachment points + bool labelled; + private: + RGroupData(const RGroupData &rhs); + + public: + RGroupData() : combinedMol(), mols(), smilesSet(), smiles(), attachments(), labelled(false) { + } + void add(boost::shared_ptr newMol, const std::vector &rlabel_attachments) { // some fragments can be add multiple times if they are cyclic @@ -196,6 +206,7 @@ struct RGroupData { if (newMol.get() == mols[i].get()) return; } + labelled = false; std::copy(rlabel_attachments.begin(), rlabel_attachments.end(), std::inserter(attachments, attachments.end())); @@ -206,10 +217,12 @@ struct RGroupData { combinedMol = boost::shared_ptr(new RWMol(*mols[0].get())); } else { ROMol *m = combineMols(*combinedMol.get(), *newMol.get()); + m->updateProps(*combinedMol.get()); combinedMol.reset(new RWMol(*m)); delete m; } smiles = getSmiles(); + combinedMol->setProp(common_properties::internalRgroupSmiles, smiles); } std::map getNumBondsToRlabels() const { @@ -249,13 +262,24 @@ struct RGroupData { } namespace { +typedef boost::shared_ptr RData; + +typedef std::map R_DECOMP; struct RGroupMatch { - size_t core_idx; - std::map rgroups; - RGroupMatch(size_t core_index, const std::map &input_rgroups) + // RGroupMatch is the decomposition for a single molecule + size_t core_idx; // index of the matching core + R_DECOMP rgroups; // rlabel->RGroupData mapping + + RGroupMatch(size_t core_index, const R_DECOMP &input_rgroups) : core_idx(core_index), rgroups(input_rgroups) {} + }; +void ADD_MATCH(R_DECOMP &match, int rlabel) { + if(match.find(rlabel) == match.end()) + match[rlabel] = boost::make_shared(); +} + struct CartesianProduct { std::vector permutation; std::vector sizes; @@ -314,23 +338,23 @@ double score(const std::vector &permutation, std::map, int> linkerMatchSet; // std::map, int > attachMatch; for (size_t m = 0; m < permutation.size(); ++m) { // for each molecule - std::map::const_iterator rg = + R_DECOMP::const_iterator rg = matches[m][permutation[m]].rgroups.find(l); if (rg != matches[m][permutation[m]].rgroups.end()) { #ifdef DEBUG - std::cerr << " RGroup: " << rg->second.smiles; + std::cerr << " RGroup: " << rg->second->smiles; #endif - matchSet[rg->second.smiles]++; + matchSet[rg->second->smiles]++; #ifdef DEBUG - std::cerr << " score: " << matchSet[rg->second.smiles] << std::endl; + std::cerr << " score: " << matchSet[rg->second->smiles] << std::endl; #endif // XXX Use fragment counts to see if we are linking cycles? - if (rg->second.smiles.find(".") == std::string::npos && - rg->second.attachments.size() > 1) { - linkerMatchSet[rg->second.attachments]++; + if (rg->second->smiles.find(".") == std::string::npos && + rg->second->attachments.size() > 1) { + linkerMatchSet[rg->second->attachments]++; #ifdef DEBUG std::cerr << " Linker Score: " - << linkerMatchSet[rg->second.attachments]++ << std::endl; + << linkerMatchSet[rg->second->attachments]++ << std::endl; #endif } } @@ -486,10 +510,10 @@ struct RGroupDecompData { lit != labels.end(); ++lit) { bool allH = true; for (size_t i = 0; i < result.size(); ++i) { - std::map::const_iterator rgroup = + R_DECOMP::const_iterator rgroup = result[i].rgroups.find(*lit); if (rgroup == result[i].rgroups.end() || - !rgroup->second.isHydrogen()) { + !rgroup->second->isHydrogen()) { allH = false; break; } @@ -605,12 +629,15 @@ struct RGroupDecompData { void relabelRGroup(RGroupData &rgroup, const std::map &mappings) { PRECONDITION(rgroup.combinedMol.get(), "Unprocessed rgroup"); - const std::string done = "RLABEL_PROCESSED"; - if (rgroup.combinedMol->hasProp(done)) return; - - rgroup.combinedMol->setProp(done, true); RWMol &mol = *rgroup.combinedMol.get(); + if (rgroup.combinedMol->hasProp(done)) { + rgroup.labelled = true; + return; + } + + mol.setProp(done, true); + //std::cerr << "==> relabelling: " << mol.getProp("idx") << " <++idx" << std::endl; std::vector > atomsToAdd; // adds -R if necessary @@ -643,13 +670,16 @@ struct RGroupDecompData { mol.addAtom(atomsToAdd[i].second, false, true); mol.addBond(atomsToAdd[i].first, atomsToAdd[i].second, Bond::SINGLE); } + if (params.removeHydrogensPostMatch) { bool implicitOnly = false; bool updateExplicitCount = false; bool sanitize = false; MolOps::removeHs(mol, implicitOnly, updateExplicitCount, sanitize); } + mol.updatePropertyCache(false); // this was github #1550 + rgroup.labelled = true; } // relabel the core and sidechains using the specified user labels @@ -672,15 +702,13 @@ struct RGroupDecompData { for (std::vector::iterator it = best.begin(); it != best.end(); ++it) { - for (std::map::iterator rit = it->rgroups.begin(); + for (R_DECOMP::iterator rit = it->rgroups.begin(); rit != it->rgroups.end(); ++rit) { if (rit->first >= 0) userLabels.insert(rit->first); if (rit->first < 0) indexLabels.insert(rit->first); - std::map rlabelsUsedInRGroup = - rit->second.getNumBondsToRlabels(); - for (std::map::iterator numBondsUsed = - rlabelsUsedInRGroup.begin(); + std::map rlabelsUsedInRGroup = rit->second->getNumBondsToRlabels(); + for (std::map::iterator numBondsUsed = rlabelsUsedInRGroup.begin(); numBondsUsed != rlabelsUsedInRGroup.end(); ++numBondsUsed) { // Make space for the extra labels if (numBondsUsed->second > 1) { // multiple @@ -701,12 +729,11 @@ struct RGroupDecompData { indexLabels, extraAtomRLabels); } - const std::string done = "RLABEL_PROCESSED"; for (std::vector::iterator it = best.begin(); it != best.end(); ++it) { - for (std::map::iterator rit = it->rgroups.begin(); + for (R_DECOMP::iterator rit = it->rgroups.begin(); rit != it->rgroups.end(); ++rit) { - relabelRGroup(rit->second, finalRlabelMapping); + relabelRGroup(*rit->second, finalRlabelMapping); } } } @@ -825,6 +852,8 @@ int RGroupDecomposition::add(const ROMol &inmol) { // Should probably scan all mols first to find match with // smallest number of matches... + size_t size = data->matches.size(); + std::vector potentialMatches; @@ -839,12 +868,16 @@ int RGroupDecomposition::add(const ROMol &inmol) { } if (tMol) { - std::map match; + R_DECOMP match; // rlabel rgroups MOL_SPTR_VECT fragments = MolOps::getMolFrags(*tMol, false); for (size_t i = 0; i < fragments.size(); ++i) { std::vector attachments; boost::shared_ptr &newMol = fragments[i]; + newMol->setProp("core", core_idx); + newMol->setProp("idx", size); + newMol->setProp("frag_idx", i); + for (ROMol::AtomIterator atIt = newMol->beginAtoms(); atIt != newMol->endAtoms(); ++atIt) { Atom *tmp = *atIt; @@ -874,7 +907,8 @@ int RGroupDecomposition::add(const ROMol &inmol) { for (size_t attach_idx = 0; attach_idx < attachments.size(); ++attach_idx) { int rlabel = attachments[attach_idx]; - match[rlabel].add(newMol, attachments); + ADD_MATCH(match, rlabel); + match[rlabel]->add(newMol, attachments); } } else { // special case, only one fragment @@ -940,8 +974,6 @@ int RGroupDecomposition::add(const ROMol &inmol) { data->matches.push_back(potentialMatches); data->permutation = std::vector(data->matches.size(), 0); - size_t size = data->matches.size(); - if (size) { if (data->params.matchingStrategy & Greedy || (data->params.matchingStrategy & GreedyChunks && size > 1 && @@ -974,9 +1006,9 @@ RGroupRows RGroupDecomposition::getRGroupsAsRows() const { RGroupRow &out_rgroups = groups.back(); out_rgroups["Core"] = data->labelledCores[it->core_idx]; - std::map &in_rgroups = it->rgroups; + R_DECOMP &in_rgroups = it->rgroups; - for (std::map::const_iterator rgroup = in_rgroups.begin(); + for (R_DECOMP::const_iterator rgroup = in_rgroups.begin(); rgroup != in_rgroups.end(); ++rgroup) { std::map::const_iterator realLabel = data->finalRlabelMapping.find(rgroup->first); @@ -984,7 +1016,7 @@ RGroupRows RGroupDecomposition::getRGroupsAsRows() const { "unprocessed rlabel, please call process() first."); out_rgroups[std::string("R") + boost::lexical_cast(realLabel->second)] = - rgroup->second.combinedMol; + rgroup->second->combinedMol; } } return groups; @@ -998,27 +1030,79 @@ RGroupColumns RGroupDecomposition::getRGroupsAsColumns() const { unsigned int molidx = 0; for (std::vector::iterator it = permutation.begin(); it != permutation.end(); ++it, ++molidx) { - std::map &in_rgroups = it->rgroups; + R_DECOMP &in_rgroups = it->rgroups; groups["Core"].push_back(data->labelledCores[it->core_idx]); - for (std::map::const_iterator rgroup = in_rgroups.begin(); + for (R_DECOMP::const_iterator rgroup = in_rgroups.begin(); rgroup != in_rgroups.end(); ++rgroup) { std::map::const_iterator realLabel = data->finalRlabelMapping.find(rgroup->first); PRECONDITION(realLabel != data->finalRlabelMapping.end(), "unprocessed rlabel, please call process() first."); + PRECONDITION(rgroup->second->combinedMol->hasProp(done), + "Not done! Call process()"); + std::string r = std::string("R") + boost::lexical_cast(realLabel->second); RGroupColumn &col = groups[r]; if (molidx && col.size() < (size_t)(molidx - 1)) col.resize(molidx - 1); - col.push_back(rgroup->second.combinedMol); + col.push_back(rgroup->second->combinedMol); } } - // Now make all columns equal + // Now make all columns equal - this adds empty mols... for (std::map::iterator it = groups.begin(); it != groups.end(); ++it) { - if (it->second.size() != molidx) it->second.resize(molidx); + if (it->second.size() != molidx) { + it->second.resize(molidx); + } + + for(size_t idx=0;idxsecond.size();++idx) { + if(!it->second[idx].get()) { + it->second[idx] = boost::make_shared(); + } + } } return groups; } + +namespace { +std::vector Decomp(RGroupDecomposition &decomp, + const std::vector &mols) { + std::vector unmatched; + for(size_t i=0; i &cores, + const std::vector &mols, + RGroupRows &rows, + std::vector *unmatchedIndices, + const RGroupDecompositionParameters &options) { + RGroupDecomposition decomp(cores, options); + std::vector unmatched = Decomp(decomp, mols); + if(unmatchedIndices) + *unmatchedIndices = unmatched; + rows = decomp.getRGroupsAsRows(); + return mols.size() - unmatched.size(); +} + +unsigned int RGroupDecompose(const std::vector &cores, + const std::vector &mols, + RGroupColumns &columns, + std::vector *unmatchedIndices, + const RGroupDecompositionParameters &options) +{ + RGroupDecomposition decomp(cores, options); + std::vector unmatched = Decomp(decomp, mols); + if(unmatchedIndices) + *unmatchedIndices = unmatched; + columns = decomp.getRGroupsAsColumns(); + return mols.size() - unmatched.size(); +} + } diff --git a/Code/GraphMol/RGroupDecomposition/RGroupDecomp.h b/Code/GraphMol/RGroupDecomposition/RGroupDecomp.h index 4e8ee07a8..b6c8e055e 100644 --- a/Code/GraphMol/RGroupDecomposition/RGroupDecomp.h +++ b/Code/GraphMol/RGroupDecomposition/RGroupDecomp.h @@ -143,6 +143,19 @@ class RGroupDecomposition { //! return rgroups in column order group[attachment_point][row] = ROMol RGroupColumns getRGroupsAsColumns() const; }; + +unsigned int RGroupDecompose(const std::vector &cores, + const std::vector &mols, + RGroupRows &rows, + std::vector *unmatched = 0, + const RGroupDecompositionParameters &options = RGroupDecompositionParameters()); + +unsigned int RGroupDecompose(const std::vector &cores, + const std::vector &mols, + RGroupColumns &columns, + std::vector *unmatched = 0, + const RGroupDecompositionParameters &options = RGroupDecompositionParameters()); + } #endif diff --git a/Code/GraphMol/RGroupDecomposition/Wrap/rdRGroupComposition.cpp b/Code/GraphMol/RGroupDecomposition/Wrap/rdRGroupComposition.cpp index 8231728f5..07aea9458 100644 --- a/Code/GraphMol/RGroupDecomposition/Wrap/rdRGroupComposition.cpp +++ b/Code/GraphMol/RGroupDecomposition/Wrap/rdRGroupComposition.cpp @@ -39,7 +39,7 @@ #include #include -#include +#include #include #include #include @@ -77,7 +77,7 @@ class RGroupDecompositionHelper { int Add(const ROMol &mol) { return decomp->add(mol); } bool Process() { return decomp->process(); } - python::list GetRGroupsAsRows() { + python::list GetRGroupsAsRows(bool asSmiles=false) { const RGroupRows &groups = decomp->getRGroupsAsRows(); python::list result; @@ -87,14 +87,18 @@ class RGroupDecompositionHelper { const RGroupRow &side_chains = *(it); for (RGroupRow::const_iterator sit = side_chains.begin(); sit != side_chains.end(); ++sit) { - dict[sit->first] = sit->second; + if (asSmiles) { + dict[sit->first] = MolToSmiles(*sit->second, true); + } else { + dict[sit->first] = sit->second; + } } result.append(dict); } return result; } - python::dict GetRGroupsAsColumn() { + python::dict GetRGroupsAsColumn(bool asSmiles=false) { python::dict result; RGroupColumns groups = decomp->getRGroupsAsColumns(); @@ -105,14 +109,49 @@ class RGroupDecompositionHelper { for (RGroupColumn::const_iterator cit = it->second.begin(); cit != it->second.end(); ++cit) { - col.append(*cit); + if (asSmiles) { + col.append(MolToSmiles(**cit,true)); + } else { + col.append(*cit); + } } result[it->first] = col; } return result; } + + }; +python::object RGroupDecomp(python::object cores, + python::object mols, + bool asSmiles = false, + bool asRows = true, + const RGroupDecompositionParameters &options = RGroupDecompositionParameters() + ) { + RGroupDecompositionHelper decomp(cores, options); + python::list unmatched; + + python::stl_input_iterator iter(mols), end; + unsigned int idx=0; + while (iter != end) { + if (!*iter) throw_value_error("reaction called with None reactants"); + if(decomp.Add(*(*iter)) == -1) { + unmatched.append(idx); + } + ++iter; + ++idx; + } + + decomp.Process(); + if ( asRows ) { + return make_tuple(decomp.GetRGroupsAsRows(asSmiles), unmatched); + } else { + return make_tuple(decomp.GetRGroupsAsColumn(asSmiles), unmatched); + } +} + + struct rgroupdecomp_wrapper { static void wrap() { python::class_("MOL_SPTR_VECT") @@ -144,6 +183,27 @@ struct rgroupdecomp_wrapper { .value("MCS", RDKit::MCS) .export_values(); + docString = "RGroupDecompositionParameters controls how the RGroupDecomposition sets labelling and matches structures\n" + " OPTIONS:\n" + " - RGroupCoreAlignment: can be one of RGroupCoreAlignment.None or RGroupCoreAlignment.MCS\n" + " If set to MCS, cores labels are mapped to each other using their\n" + " Maximum common substructure overlap.\n" + " - RGroupLabels: optionally set where the rgroup labels to use are encoded.\n" + " RroupLabels.IsotopeLabels - labels are stored on isotopes\n" + " RroupLabels.AtomMapLabels - labels are stored on atommaps\n" + " RroupLabels.AtomIndexLabels - use the atom index as the label\n" + " RGroupLabels.RelabelDuplicateLabels - fix any duplicate labels\n" + " RGroupLabels.AutoDetect - auto detect the label [default]\n" + " Note: in all cases, any rgroups found on unlabelled atoms will be automatically\n" + " labelled.\n" + " - RGroupLabelling: choose where the rlabels are stored on the decomposition\n" + " RGroupLabels.AtomMap - store rgroups as atom maps (for smiles)\n" + " RGroupLabels.Isotope - stroe rgroups on the isotope\n" + " RGroupLabels.MDLRGroup - store rgroups as mdl rgroups (for molblocks)\n" + " default: AtomMap | MDLRGroup\n" + " - matchOnlyAtRGroups: only allow rgroup decomposition at the specified rgroups\n" + " - setRemoveRGroupsThatAreAllHydrogen: remove all rgroups that only have hydrogens\n" + " - removeHydrogensPostMatch: remove all hydrogens from the output molecules\n"; python::class_( "RGroupDecompositionParameters", docString.c_str(), python::init<>("Constructor, takes no arguments")) @@ -199,10 +259,49 @@ struct rgroupdecomp_wrapper { .def("Process", &RGroupDecompositionHelper::Process, "Process the rgroups (must be done prior to " "GetRGroupsAsRows/Columns)") - .def("GetRGroupsAsRows", &RGroupDecompositionHelper::GetRGroupsAsRows) + .def("GetRGroupsAsRows", &RGroupDecompositionHelper::GetRGroupsAsRows, + python::arg("asSmiles")=false, + "Return the rgroups as rows (note: can be fed directrly into a pandas datatable)\n" + " ARGUMENTS:\n" + " - asSmiles: if True return smiles strings, otherwise return molecules [default: False]\n" + " Row structure:\n" + " rows[idx] = {rgroup_label: molecule_or_smiles}\n" + ) .def("GetRGroupsAsColumns", - &RGroupDecompositionHelper::GetRGroupsAsColumn); - }; + &RGroupDecompositionHelper::GetRGroupsAsColumn, + python::arg("asSmiles")=false, + "Return the rgroups as columns (note: can be fed directrly into a pandas datatable)\n" + " ARGUMENTS:\n" + " - asSmiles: if True return smiles strings, otherwise return molecules [default: False]\n" + " Column structure:\n" + " columns[rgroup_label] = [ mols_or_smiles ]\n" + ); + + docString = "Decompose a collecion of molecules into their Rgroups\n" + " ARGUMENTS:\n" + " - cores: a set of cores from most to least specific.\n" + " See RGroupDecompositionParameters for more details\n" + " on how the cores can be labelled\n" + " - mols: the molecules to be decomposed\n" + " - asSmiles: if True return smiles strings, otherwise return molecules [default: False]\n" + " - asRows: return the results as rows (default) otherwise return columns\n" + "\n" + " RETURNS: row_or_column_results, unmatched\n" + "\n" + " Row structure:\n" + " rows[idx] = {rgroup_label: molecule_or_smiles}\n" + " Column structure:\n" + " columns[rgroup_label] = [ mols_or_smiles ]\n" + "\n" + " unmatched is a vector of indices in the input mols that were not matched.\n"; + python::def( + "RGroupDecompose", RDKit::RGroupDecomp, + (python::arg("cores"), python::arg("mols"), + python::arg("asSmiles") = false, + python::arg("asRows") = true, + python::arg("options") = RGroupDecompositionParameters()), + docString.c_str()); + }; }; } diff --git a/Code/GraphMol/RGroupDecomposition/Wrap/test_rgroups.py b/Code/GraphMol/RGroupDecomposition/Wrap/test_rgroups.py index 5a4869724..1e059fe52 100644 --- a/Code/GraphMol/RGroupDecomposition/Wrap/test_rgroups.py +++ b/Code/GraphMol/RGroupDecomposition/Wrap/test_rgroups.py @@ -37,7 +37,7 @@ from rdkit.six.moves import cPickle from rdkit import rdBase from rdkit import Chem -from rdkit.Chem.rdRGroupDecomposition import RGroupDecomposition, RGroupDecompositionParameters +from rdkit.Chem.rdRGroupDecomposition import RGroupDecompose, RGroupDecomposition, RGroupDecompositionParameters from collections import OrderedDict class TestCase(unittest.TestCase) : @@ -112,12 +112,23 @@ C1CCO[C@@](S)(P)1 core = Chem.MolFromSmarts("C1CCOC1") rgroups = RGroupDecomposition(core) for m in mols: - print (m, Chem.MolToSmiles(m)) rgroups.Add(m) rgroups.Process() columns = rgroups.GetRGroupsAsColumns() + data = {} for k,v in columns.items(): - print("%s:%s"%(k, " ".join([Chem.MolToSmiles(m,True) for m in v]))) + data[k] = [Chem.MolToSmiles(m,True) for m in v] + + rgroups2,unmatched = RGroupDecompose([core], mols) + columns2,unmatched = RGroupDecompose([core], mols, asRows=False) + data2 = {} + for k,v in columns2.items(): + data2[k] = [Chem.MolToSmiles(m,True) for m in v] + + self.assertEqual(data, data2) + columns3, unmatched = RGroupDecompose([core], mols, asRows=False, asSmiles=True) + self.assertEqual(data, columns3) + def test_h_options(self): core = Chem.MolFromSmiles("O=c1oc2ccccc2cc1") @@ -142,6 +153,18 @@ C1CCO[C@@](S)(P)1 columns = rgd.GetRGroupsAsColumns() self.assertEqual(columns['R2'][0].GetNumAtoms(),7) + def test_unmatched(self): + cores = [Chem.MolFromSmiles("N")] + mols = [Chem.MolFromSmiles("CC"), + Chem.MolFromSmiles("CC"), + Chem.MolFromSmiles("CC"), + Chem.MolFromSmiles("N"), + Chem.MolFromSmiles("CC")] + + res, unmatched = RGroupDecompose(cores, mols) + self.assertEquals(len(res), 1) + self.assertEquals(unmatched, [0,1,2,4]) + if __name__ == '__main__': unittest.main() diff --git a/Code/GraphMol/RGroupDecomposition/testRGroupDecomp.cpp b/Code/GraphMol/RGroupDecomposition/testRGroupDecomp.cpp index 515bb754e..c6021e4e8 100644 --- a/Code/GraphMol/RGroupDecomposition/testRGroupDecomp.cpp +++ b/Code/GraphMol/RGroupDecomposition/testRGroupDecomp.cpp @@ -269,10 +269,10 @@ const char *coreSmi[] = { "C1CCOC(Cl)CC1", "C1CC(Cl)OCCC1", "C1CCOC(I)CC1", "C1CC(I)OCCC1"}; const char *coreSmiRes[] = { - "Core:C1CCC([*:1])N([*:2])CC1 R1:Cl[*:1].[H][*:1] R2:[H][*:2]", - "Core:C1CCC([*:1])N([*:2])CC1 R1:Cl[*:1].[H][*:1] R2:[H][*:2]", - "Core:C1CCC([*:1])N([*:2])CC1 R1:I[*:1].[H][*:1] R2:[H][*:2]", - "Core:C1CCC([*:1])N([*:2])CC1 R1:I[*:1].[H][*:1] R2:[H][*:2]", + "Core:C1CCC([*:2])N([*:1])CC1 R1:Cl[*:1].[H][*:1]", + "Core:C1CCC([*:2])N([*:1])CC1 R1:Cl[*:1].[H][*:1]", + "Core:C1CCC([*:2])N([*:1])CC1 R1:I[*:1].[H][*:1]", + "Core:C1CCC([*:2])N([*:1])CC1 R1:I[*:1].[H][*:1]", "Core:C1CCSC([*:1])CC1 R1:Cl[*:1].[H][*:1]", "Core:C1CCSC([*:1])CC1 R1:Cl[*:1].[H][*:1]", "Core:C1CCSC([*:1])CC1 R1:I[*:1].[H][*:1]", diff --git a/Code/RDGeneral/types.cpp b/Code/RDGeneral/types.cpp index b2e77a4e6..7c6ebc50b 100644 --- a/Code/RDGeneral/types.cpp +++ b/Code/RDGeneral/types.cpp @@ -97,7 +97,7 @@ const std::string origNoImplicit = "origNoImplicit"; const std::string ringMembership = "ringMembership"; const std::string smilesSymbol = "smilesSymbol"; const std::string atomLabel = "atomLabel"; - +const std::string internalRgroupSmiles = "internalRgroupSmiles"; } // end common_properties const double MAX_DOUBLE = std::numeric_limits::max(); diff --git a/Code/RDGeneral/types.h b/Code/RDGeneral/types.h index 03db63434..6dd196036 100644 --- a/Code/RDGeneral/types.h +++ b/Code/RDGeneral/types.h @@ -163,6 +163,7 @@ extern const std::string Discrims; // FragCatalog Entry extern const std::string DistanceMatrix_Paths; // boost::shared_array // - note, confusing creation of names in // - getDistanceMat +extern const std::string internalRgroupSmiles; } // end common_properties #ifndef WIN32 From 25ac7904e8af5a3eeae4ee1c4e33686462e4cfa8 Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Tue, 12 Sep 2017 17:44:37 +0200 Subject: [PATCH 14/44] remove setters and getters for RGroupDecompositionParameters data members (#1554) --- .../RGroupDecomposition/RGroupDecomp.h | 29 ---------- .../Wrap/rdRGroupComposition.cpp | 54 +++++++------------ .../RGroupDecomposition/Wrap/test_rgroups.py | 2 +- 3 files changed, 19 insertions(+), 66 deletions(-) diff --git a/Code/GraphMol/RGroupDecomposition/RGroupDecomp.h b/Code/GraphMol/RGroupDecomposition/RGroupDecomp.h index b6c8e055e..3a6212aba 100644 --- a/Code/GraphMol/RGroupDecomposition/RGroupDecomp.h +++ b/Code/GraphMol/RGroupDecomposition/RGroupDecomp.h @@ -78,35 +78,6 @@ struct RGroupDecompositionParameters { removeHydrogensPostMatch(removeHydrogensPostMatch), indexOffset(-1) {} bool prepareCore(RWMol &, const RWMol *alignCore); - void SetRGroupLabels(unsigned int rgroupLabels) { labels = rgroupLabels; } - void SetRGroupLabelling(unsigned int labelling) { - rgroupLabelling = labelling; - } - void SetRGroupMatching(unsigned int matching) { matchingStrategy = matching; } - void SetRGroupCoreAlignment(unsigned int coreAlignment) { - alignment = coreAlignment; - } - void SetChunkSize(unsigned int size) { chunkSize = size; } - void SetOnlyMatchAtRGroups(bool matchAtRGroups) { - onlyMatchAtRGroups = matchAtRGroups; - } - void SetRemoveRGroupsThatAreAllHydrogen(bool remove) { - removeAllHydrogenRGroups = remove; - } - void SetRemoveHydrogensPostMatch(bool remove) { - removeHydrogensPostMatch = remove; - } - - unsigned int GetRGroupLabels() const { return labels; } - unsigned int GetRGroupLabelling() const { return matchingStrategy; } - unsigned int GetRGroupMatching() const { return rgroupLabelling; } - unsigned int GetRGroupCoreAlignment() const { return alignment; } - unsigned int GetChunkSize() const { return chunkSize; } - bool GetOnlyMatchAtRGroups() const { return onlyMatchAtRGroups; } - bool GetRemoveRGroupsThatAreAllHydrogen() const { - return removeAllHydrogenRGroups; - } - bool GetRemoveHydrogensPostMatch() const { return removeHydrogensPostMatch; } private: int indexOffset; diff --git a/Code/GraphMol/RGroupDecomposition/Wrap/rdRGroupComposition.cpp b/Code/GraphMol/RGroupDecomposition/Wrap/rdRGroupComposition.cpp index 07aea9458..8508bd2f5 100644 --- a/Code/GraphMol/RGroupDecomposition/Wrap/rdRGroupComposition.cpp +++ b/Code/GraphMol/RGroupDecomposition/Wrap/rdRGroupComposition.cpp @@ -210,42 +210,24 @@ struct rgroupdecomp_wrapper { .def(python::init()) - .def("SetRGroupLabels", - &RDKit::RGroupDecompositionParameters::SetRGroupLabels) - .def("GetRGroupLabels", - &RDKit::RGroupDecompositionParameters::GetRGroupLabels) - .def("SetRGroupLabelling", - &RDKit::RGroupDecompositionParameters::SetRGroupLabelling) - .def("GetRGroupLabelling", - &RDKit::RGroupDecompositionParameters::GetRGroupLabelling) - .def("SetRGroupMatching", - &RDKit::RGroupDecompositionParameters::SetRGroupMatching) - .def("GetRGroupMatching", - &RDKit::RGroupDecompositionParameters::GetRGroupMatching) - .def("SetRGroupCoreAlignment", - &RDKit::RGroupDecompositionParameters::SetRGroupCoreAlignment) - .def("GetRGroupCoreAlignment", - &RDKit::RGroupDecompositionParameters::GetRGroupCoreAlignment) - .def("SetChunkSize", - &RDKit::RGroupDecompositionParameters::SetChunkSize) - .def("GetChunkSize", - &RDKit::RGroupDecompositionParameters::GetChunkSize) - .def("SetOnlyMatchAtRGroups", - &RDKit::RGroupDecompositionParameters::SetOnlyMatchAtRGroups) - .def("GetOnlyMatchAtRGroups", - &RDKit::RGroupDecompositionParameters::GetOnlyMatchAtRGroups) - .def("SetRemoveRGroupsThatAreAllHydrogen", - &RDKit::RGroupDecompositionParameters:: - SetRemoveRGroupsThatAreAllHydrogen) - .def("GetRemoveRGroupsThatAreAllHydrogen", - &RDKit::RGroupDecompositionParameters:: - GetRemoveRGroupsThatAreAllHydrogen) - .def("SetRemoveHydrogensPostMatch", - &RDKit::RGroupDecompositionParameters::SetRemoveHydrogensPostMatch) - .def("GetRemoveHydrogensPostMatch", - &RDKit::RGroupDecompositionParameters::GetRemoveHydrogensPostMatch) - - ; + .def_readwrite("labels", &RDKit::RGroupDecompositionParameters::labels) + .def_readwrite("matchingStrategy", + &RDKit::RGroupDecompositionParameters::matchingStrategy) + .def_readwrite("rgroupLabelling", + &RDKit::RGroupDecompositionParameters::rgroupLabelling) + .def_readwrite("alignment", + &RDKit::RGroupDecompositionParameters::alignment) + .def_readwrite("chunkSize", + &RDKit::RGroupDecompositionParameters::chunkSize) + .def_readwrite( + "onlyMatchAtRGroups", + &RDKit::RGroupDecompositionParameters::onlyMatchAtRGroups) + .def_readwrite( + "removeAllHydrogenRGroups", + &RDKit::RGroupDecompositionParameters::removeAllHydrogenRGroups) + .def_readwrite( + "removeHydrogensPostMatch", + &RDKit::RGroupDecompositionParameters::removeHydrogensPostMatch); python::class_( "RGroupDecomposition", docString.c_str(), diff --git a/Code/GraphMol/RGroupDecomposition/Wrap/test_rgroups.py b/Code/GraphMol/RGroupDecomposition/Wrap/test_rgroups.py index 1e059fe52..4003ab978 100644 --- a/Code/GraphMol/RGroupDecomposition/Wrap/test_rgroups.py +++ b/Code/GraphMol/RGroupDecomposition/Wrap/test_rgroups.py @@ -144,7 +144,7 @@ C1CCO[C@@](S)(P)1 columns = rgd.GetRGroupsAsColumns() self.assertEqual(columns['R2'][0].GetNumAtoms(),12) - params.SetRemoveHydrogensPostMatch(True) + params.removeHydrogensPostMatch = True rgd = RGroupDecomposition(core,params) for smi in smiles: m = Chem.MolFromSmiles(smi) From 870fc26a9b7cb5b04fdcd2f85acd9e2847dca608 Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Tue, 12 Sep 2017 22:07:36 +0200 Subject: [PATCH 15/44] Implement stereoisomer enumeration (#1531) * python implementation of stereisomer enumeration * add another doctest * support a maximum number of chiral centers * Changes from review: - add maxNumCenters argument - switch to using a generator - allow centers to be explored in random order * fix a py27 problem * python 2.7 and 3.5+ have different RNG behavior, so skip that doctest * switch to using an option class * remove random option; rename function --- rdkit/Chem/AllChem.py | 126 ++++++++++++++++++++++++++++++++++++++++- rdkit/Chem/__init__.py | 11 ++-- 2 files changed, 128 insertions(+), 9 deletions(-) diff --git a/rdkit/Chem/AllChem.py b/rdkit/Chem/AllChem.py index 13520fcf5..c648431bd 100644 --- a/rdkit/Chem/AllChem.py +++ b/rdkit/Chem/AllChem.py @@ -1,6 +1,5 @@ -# $Id$ # -# Copyright (C) 2006-2011 greg Landrum and Rational Discovery LLC +# Copyright (C) 2006-2017 greg Landrum and Rational Discovery LLC # # @@ All Rights Reserved @@ # This file is part of the RDKit. @@ -451,6 +450,129 @@ def AssignBondOrdersFromTemplate(refmol, mol): raise ValueError("No matching found") return mol2 +class StereoEnumerationOptions(object): + """ + - tryEmbedding: if set the process attempts to generate a standard RDKit distance geometry + conformation for the stereisomer. If this fails, we assume that the stereoisomer is + non-physical and don't return it. NOTE that this is computationally expensive and is + just a heuristic that could result in stereoisomers being lost. + + - onlyUnassigned: if set (the default), stereocenters which have specified stereochemistry + will not be perturbed + + - maxNumCenters: the maximum number of stereocenters that can/will be handled. + Since every additional stereocenter doubles the number of results + (and execution time) it's important to keep an eye on this. + + """ + __slots__=('tryEmbedding', 'onlyUnassigned', 'maxNumCenters') + def __init__(self, tryEmbedding = False, onlyUnassigned = True, + maxNumCenters = 10): + self.tryEmbedding = tryEmbedding + self.onlyUnassigned = onlyUnassigned + self.maxNumCenters = maxNumCenters + +def GenerateStereoisomers(m,options=StereoEnumerationOptions(),verbose=False): + """ returns a generator that yields possible stereoisomers for a molecule + + Arguments: + - m: the molecule to work with + + + - verbose: toggles how verbose the output is + + + A small example with 3 chiral centers (8 theoretical stereoisomers): + >>> from rdkit.Chem import AllChem + >>> m = AllChem.MolFromSmiles('OC1OC(C2)(F)C2(Cl)C1') + >>> isomers = tuple(AllChem.GenerateStereoisomers(m)) + >>> len(isomers) + 8 + >>> for smi in sorted(AllChem.MolToSmiles(x,isomericSmiles=True) for x in isomers): + ... print(smi) + O[C@@H]1C[C@@]2(Cl)C[C@@]2(F)O1 + O[C@@H]1C[C@@]2(Cl)C[C@]2(F)O1 + O[C@@H]1C[C@]2(Cl)C[C@@]2(F)O1 + O[C@@H]1C[C@]2(Cl)C[C@]2(F)O1 + O[C@H]1C[C@@]2(Cl)C[C@@]2(F)O1 + O[C@H]1C[C@@]2(Cl)C[C@]2(F)O1 + O[C@H]1C[C@]2(Cl)C[C@@]2(F)O1 + O[C@H]1C[C@]2(Cl)C[C@]2(F)O1 + + Because the molecule is constrained, not all of those isomers can + actually exist. We can check that: + >>> opts = StereoEnumerationOptions(tryEmbedding=True) + >>> isomers = tuple(AllChem.GenerateStereoisomers(m, options=opts)) + >>> len(isomers) + 4 + >>> for smi in sorted(AllChem.MolToSmiles(x,isomericSmiles=True) for x in isomers): + ... print(smi) + O[C@@H]1C[C@@]2(Cl)C[C@@]2(F)O1 + O[C@@H]1C[C@]2(Cl)C[C@]2(F)O1 + O[C@H]1C[C@@]2(Cl)C[C@@]2(F)O1 + O[C@H]1C[C@]2(Cl)C[C@]2(F)O1 + + By default the code only expands unspecified stereocenters: + >>> m = AllChem.MolFromSmiles('O[C@H]1OC(C2)(F)C2(Cl)C1') + >>> isomers = tuple(AllChem.GenerateStereoisomers(m)) + >>> len(isomers) + 4 + >>> for smi in sorted(AllChem.MolToSmiles(x,isomericSmiles=True) for x in isomers): + ... print(smi) + O[C@@H]1C[C@@]2(Cl)C[C@@]2(F)O1 + O[C@@H]1C[C@@]2(Cl)C[C@]2(F)O1 + O[C@@H]1C[C@]2(Cl)C[C@@]2(F)O1 + O[C@@H]1C[C@]2(Cl)C[C@]2(F)O1 + + but we can change that behavior: + >>> opts = StereoEnumerationOptions(onlyUnassigned=False) + >>> isomers = tuple(AllChem.GenerateStereoisomers(m, options=opts)) + >>> len(isomers) + 8 + + since the result is a generator, we can allow exploring at least parts of very + large result sets: + >>> m = MolFromSmiles('Br'+'[CH](Cl)'*20+'F') + >>> opts = StereoEnumerationOptions(maxNumCenters=50) + >>> isomers = AllChem.GenerateStereoisomers(m, options=opts) + >>> for x in range(5): + ... print(MolToSmiles(next(isomers),isomericSmiles=True)) + F[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)Br + F[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@H](Cl)Br + F[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@H](Cl)[C@@H](Cl)Br + F[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@H](Cl)[C@H](Cl)Br + F[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@H](Cl)[C@@H](Cl)[C@@H](Cl)Br + + """ + tm = Mol(m) + if options.onlyUnassigned: + possibleCenters = [x for x,y in FindMolChiralCenters(tm, force=True, includeUnassigned=True) if y=='?'] + else: + possibleCenters = [x for x,y in FindMolChiralCenters(tm, force=True, includeUnassigned=True)] + nCenters = len(possibleCenters) + if not nCenters: + yield tm + return + if nCenters>options.maxNumCenters: + raise ValueError("nCenters (%d) larger than maxNumCenters (%d)"%(nCenters,options.maxNumCenters)) + bitflag = (1<=0: + tm = Mol(m) + for i in range(nCenters): + if bitflag & 1<= 0: + yield tm + elif verbose: + print("%s failed to embed"%(MolToSmiles(tm,isomericSmiles=True))) + bitflag -= 1 # ------------------------------------ # diff --git a/rdkit/Chem/__init__.py b/rdkit/Chem/__init__.py index 2ddf7b78e..be512a125 100755 --- a/rdkit/Chem/__init__.py +++ b/rdkit/Chem/__init__.py @@ -1,8 +1,5 @@ -## Automatically adapted for numpy.oldnumeric Jun 27, 2008 by -c - -# $Id$ # -# Copyright (C) 2000-2008 greg Landrum and Rational Discovery LLC +# Copyright (C) 2000-2017 greg Landrum and Rational Discovery LLC # # @@ All Rights Reserved @@ # This file is part of the RDKit. @@ -13,7 +10,7 @@ """ A module for molecules and stuff see Chem/index.html in the doc tree for documentation - + """ from rdkit import rdBase from rdkit import RDConfig @@ -72,7 +69,7 @@ def FindMolChiralCenters(mol, force=True, includeUnassigned=False): >>> mol = Chem.MolFromSmiles('[C@@H](Cl)(F)Br') >>> FindMolChiralCenters(mol) [(0, 'S')] - + >>> FindMolChiralCenters(Chem.MolFromSmiles('CCC')) [] @@ -90,7 +87,7 @@ def FindMolChiralCenters(mol, force=True, includeUnassigned=False): [(2, '?'), (6, '?')] >>> Chem.FindMolChiralCenters(Chem.MolFromSmiles('C1C[C@H](C)C(C)[C@H](C)C1'),includeUnassigned=True) [(2, 'S'), (4, '?'), (6, 'R')] - + """ AssignStereochemistry(mol, force=force, flagPossibleStereoCenters=includeUnassigned) centers = [] From db89172bf852789648e2c3a1a04be870d03ba63a Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Tue, 12 Sep 2017 22:10:15 +0200 Subject: [PATCH 16/44] handle the heavy-atom degree queries differently (#1560) * handle the heavy-atom degree queries differently * Fixes #1563 * add a test for the heavy atom degree option * Support (and test) adjustHeavyDegree in the cartridge too. * test results --- Code/GraphMol/AdjustQuery.cpp | 46 ++++--- Code/GraphMol/MolOps.h | 17 ++- Code/GraphMol/MolPickler.cpp | 20 +-- Code/GraphMol/QueryOps.cpp | 119 ++++++++++-------- Code/GraphMol/QueryOps.h | 8 ++ .../RGroupDecomposition/RGroupDecomp.cpp | 12 +- .../RGroupDecomposition/testRGroupDecomp.cpp | 1 + Code/GraphMol/Wrap/MolOps.cpp | 10 +- Code/GraphMol/molopstest.cpp | 44 ++++++- Code/GraphMol/testPickler.cpp | 54 +++++--- Code/PgSQL/rdkit/adapter.cpp | 4 + Code/PgSQL/rdkit/expected/rdkit-91.out | 18 +++ Code/PgSQL/rdkit/sql/rdkit-91.sql | 3 + 13 files changed, 238 insertions(+), 118 deletions(-) diff --git a/Code/GraphMol/AdjustQuery.cpp b/Code/GraphMol/AdjustQuery.cpp index 8f21a9eca..52855e4ee 100644 --- a/Code/GraphMol/AdjustQuery.cpp +++ b/Code/GraphMol/AdjustQuery.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2015 Greg Landrum +// Copyright (c) 2015-2017 Greg Landrum // // @@ All Rights Reserved @@ // This file is part of the RDKit. @@ -78,7 +78,7 @@ void adjustQueryProperties(RWMol &mol, const AdjustQueryParameters *inParams) { ringInfo->numBondRings(i))) { QueryBond *qb = new QueryBond(); qb->setQuery(makeBondNullQuery()); - const bool preserveProps = true; + const bool preserveProps = true; mol.replaceBond(i, qb, preserveProps); delete qb; } @@ -109,7 +109,7 @@ void adjustQueryProperties(RWMol &mol, const AdjustQueryParameters *inParams) { QueryAtom *qa; if (!at->hasQuery()) { qa = new QueryAtom(*at); - const bool updateLabel = false; + const bool updateLabel = false; const bool preserveProps = true; mol.replaceAtom(i, qa, updateLabel, preserveProps); delete qa; @@ -118,24 +118,40 @@ void adjustQueryProperties(RWMol &mol, const AdjustQueryParameters *inParams) { } else { qa = static_cast(at); } - if (params.adjustDegree == 2) { - ATOM_EQUALS_QUERY *tmp = new ATOM_EQUALS_QUERY; - tmp->setVal(qa->getTotalDegree() - qa->getTotalNumHs(true)); - tmp->setDataFunc(queryAtomHeavyAtomDegree); - tmp->setDescription("queryAtomHeavyDegree"); - qa->expandQuery(tmp); - } else { - qa->expandQuery(makeAtomExplicitDegreeQuery(qa->getDegree())); - } + qa->expandQuery(makeAtomExplicitDegreeQuery(qa->getDegree())); } // end of adjust degree + if (params.adjustHeavyDegree && + !((params.adjustHeavyDegreeFlags & ADJUST_IGNORECHAINS) && !nRings) && + !((params.adjustHeavyDegreeFlags & ADJUST_IGNORERINGS) && nRings) && + !((params.adjustHeavyDegreeFlags & ADJUST_IGNOREDUMMIES) && + !atomicNum) && + !((params.adjustHeavyDegreeFlags & ADJUST_IGNORENONDUMMIES) && + atomicNum) && + !((params.adjustHeavyDegreeFlags & ADJUST_IGNOREMAPPED) && + isMapped(at))) { + QueryAtom *qa; + if (!at->hasQuery()) { + qa = new QueryAtom(*at); + const bool updateLabel = false; + const bool preserveProps = true; + mol.replaceAtom(i, qa, updateLabel, preserveProps); + delete qa; + qa = static_cast(mol.getAtomWithIdx(i)); + at = static_cast(qa); + } else { + qa = static_cast(at); + } + qa->expandQuery(makeAtomHeavyAtomDegreeQuery(qa->getTotalDegree() - + qa->getTotalNumHs(true))); + } // end of adjust heavy degree if (params.adjustRingCount && !((params.adjustRingCountFlags & ADJUST_IGNORECHAINS) && !nRings) && !((params.adjustRingCountFlags & ADJUST_IGNORERINGS) && nRings) && !((params.adjustRingCountFlags & ADJUST_IGNOREDUMMIES) && !atomicNum) && !((params.adjustRingCountFlags & ADJUST_IGNORENONDUMMIES) && - !((params.adjustRingCountFlags & ADJUST_IGNOREMAPPED) && - isMapped(at)) && - atomicNum)) { + atomicNum) && + !((params.adjustRingCountFlags & ADJUST_IGNOREMAPPED) && + isMapped(at))) { QueryAtom *qa; if (!at->hasQuery()) { qa = new QueryAtom(*at); diff --git a/Code/GraphMol/MolOps.h b/Code/GraphMol/MolOps.h index 980dbbaf2..22915abe4 100644 --- a/Code/GraphMol/MolOps.h +++ b/Code/GraphMol/MolOps.h @@ -253,14 +253,8 @@ typedef enum { ADJUST_IGNOREALL = 0xFFFFFFF } AdjustQueryWhichFlags; -namespace AdjustDegree { -const unsigned int NoAdjust = 0; -const unsigned int TotalDegree = 1; -const unsigned int HeavyDegree = 2; -} - struct AdjustQueryParameters { - int adjustDegree; /**< add degree queries 1/true == all 2 == heavy*/ + bool adjustDegree; /**< add degree queries */ boost::uint32_t adjustDegreeFlags; bool adjustRingCount; /**< add ring-count queries */ boost::uint32_t adjustRingCountFlags; @@ -272,9 +266,12 @@ struct AdjustQueryParameters { boost::uint32_t makeBondsGenericFlags; bool makeAtomsGeneric; /**< convert atoms to generic queries (any atoms) */ boost::uint32_t makeAtomsGenericFlags; + bool adjustHeavyDegree; /**< adjust the heavy-atom degree instead of overall + degree */ + boost::uint32_t adjustHeavyDegreeFlags; AdjustQueryParameters() - : adjustDegree(AdjustDegree::TotalDegree), + : adjustDegree(true), adjustDegreeFlags(ADJUST_IGNOREDUMMIES | ADJUST_IGNORECHAINS), adjustRingCount(false), adjustRingCountFlags(ADJUST_IGNOREDUMMIES | ADJUST_IGNORECHAINS), @@ -283,7 +280,9 @@ struct AdjustQueryParameters { makeBondsGeneric(false), makeBondsGenericFlags(ADJUST_IGNORENONE), makeAtomsGeneric(false), - makeAtomsGenericFlags(ADJUST_IGNORENONE) {} + makeAtomsGenericFlags(ADJUST_IGNORENONE), + adjustHeavyDegree(false), + adjustHeavyDegreeFlags(ADJUST_IGNOREDUMMIES | ADJUST_IGNORECHAINS) {} }; //! returns a copy of a molecule with query properties adjusted /*! diff --git a/Code/GraphMol/MolPickler.cpp b/Code/GraphMol/MolPickler.cpp index 05e33f574..f0ae04561 100644 --- a/Code/GraphMol/MolPickler.cpp +++ b/Code/GraphMol/MolPickler.cpp @@ -1,6 +1,5 @@ -// $Id$ // -// Copyright (C) 2001-2013 Greg Landrum and Rational Discovery LLC +// Copyright (C) 2001-2017 Greg Landrum and Rational Discovery LLC // // @@ All Rights Reserved @@ // This file is part of the RDKit. @@ -70,7 +69,7 @@ void propmutex_create() { boost::mutex::scoped_lock test_lock(mutex); } -boost::mutex& GetPropMutex() { +boost::mutex &GetPropMutex() { #ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11 static boost::once_flag flag; #else @@ -91,13 +90,12 @@ unsigned int MolPickler::getDefaultPickleProperties() { } void MolPickler::setDefaultPickleProperties(unsigned int props) { -#ifdef RDK_THREADSAFE_SSS +#ifdef RDK_THREADSAFE_SSS boost::mutex::scoped_lock lock(GetPropMutex()); #endif defaultProperties = props; } - namespace { using namespace Queries; template @@ -246,6 +244,8 @@ void finalizeQueryFromDescription(Query *query, query->setDataFunc(queryAtomExplicitDegree); } else if (descr == "AtomTotalDegree") { query->setDataFunc(queryAtomTotalDegree); + } else if (descr == "AtomHeavyAtomDegree") { + query->setDataFunc(queryAtomHeavyAtomDegree); } else if (descr == "AtomHCount") { query->setDataFunc(queryAtomHCount); } else if (descr == "AtomImplicitHCount") { @@ -753,11 +753,11 @@ void MolPickler::molFromPickle(std::istream &ss, ROMol *mol) { streamRead(ss, patchVersion); if (majorVersion > versionMajor || (majorVersion == versionMajor && minorVersion > versionMinor)) { - BOOST_LOG(rdWarningLog) << "Depickling from a version number (" - << majorVersion << "." << minorVersion << ")" - << "that is higher than our version (" - << versionMajor << "." << versionMinor - << ").\nThis probably won't work." << std::endl; + BOOST_LOG(rdWarningLog) + << "Depickling from a version number (" << majorVersion << "." + << minorVersion << ")" + << "that is higher than our version (" << versionMajor << "." + << versionMinor << ").\nThis probably won't work." << std::endl; } majorVersion = 1000 * majorVersion + minorVersion * 10 + patchVersion; if (majorVersion == 1) { diff --git a/Code/GraphMol/QueryOps.cpp b/Code/GraphMol/QueryOps.cpp index 786632041..e5f63e773 100644 --- a/Code/GraphMol/QueryOps.cpp +++ b/Code/GraphMol/QueryOps.cpp @@ -234,6 +234,13 @@ ATOM_EQUALS_QUERY *makeAtomTotalDegreeQuery(int what) { return res; } +ATOM_EQUALS_QUERY *makeAtomHeavyAtomDegreeQuery(int what) { + ATOM_EQUALS_QUERY *res = + makeAtomSimpleQuery(what, queryAtomHeavyAtomDegree); + res->setDescription("AtomHeavyAtomDegree"); + return res; +} + ATOM_EQUALS_QUERY *makeAtomHCountQuery(int what) { ATOM_EQUALS_QUERY *res = makeAtomSimpleQuery(what, queryAtomHCount); @@ -332,12 +339,14 @@ ATOM_EQUALS_QUERY *makeAtomInRingQuery() { ATOM_OR_QUERY *makeQAtomQuery() { ATOM_OR_QUERY *res = new ATOM_OR_QUERY; - res->setDescription("AtomOr"); // FIX: we really should label this more descriptively so that it can be output more cleanly + res->setDescription("AtomOr"); // FIX: we really should label this more + // descriptively so that it can be output more + // cleanly res->setNegation(true); res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(6))); + Queries::Query::CHILD_TYPE(makeAtomNumQuery(6))); res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(1))); + Queries::Query::CHILD_TYPE(makeAtomNumQuery(1))); return res; } ATOM_EQUALS_QUERY *makeQHAtomQuery() { @@ -359,86 +368,87 @@ ATOM_OR_QUERY *makeXAtomQuery() { ATOM_OR_QUERY *res = new ATOM_OR_QUERY; res->setDescription("AtomOr"); res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(9))); - res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(17))); - res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(35))); - res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(53))); - res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(85))); + Queries::Query::CHILD_TYPE(makeAtomNumQuery(9))); + res->addChild(Queries::Query::CHILD_TYPE( + makeAtomNumQuery(17))); + res->addChild(Queries::Query::CHILD_TYPE( + makeAtomNumQuery(35))); + res->addChild(Queries::Query::CHILD_TYPE( + makeAtomNumQuery(53))); + res->addChild(Queries::Query::CHILD_TYPE( + makeAtomNumQuery(85))); return res; } ATOM_OR_QUERY *makeXHAtomQuery() { ATOM_OR_QUERY *res = makeXAtomQuery(); res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(1))); + Queries::Query::CHILD_TYPE(makeAtomNumQuery(1))); return res; } ATOM_OR_QUERY *makeMAtomQuery() { - // using the definition from Marvin Sketch, which produces the following SMARTS: + // using the definition from Marvin Sketch, which produces the following + // SMARTS: // !#1!#2!#5!#6!#7!#8!#9!#10!#14!#15!#16!#17!#18!#33!#34!#35!#36!#52!#53!#54!#85!#86 // it's easier to define what isn't a metal than what is. :-) ATOM_OR_QUERY *res = makeMHAtomQuery(); res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(1))); + Queries::Query::CHILD_TYPE(makeAtomNumQuery(1))); return res; } ATOM_OR_QUERY *makeMHAtomQuery() { - // using the definition from Marvin Sketch, which produces the following SMARTS: + // using the definition from Marvin Sketch, which produces the following + // SMARTS: // !#2!#5!#6!#7!#8!#9!#10!#14!#15!#16!#17!#18!#33!#34!#35!#36!#52!#53!#54!#85!#86 // it's easier to define what isn't a metal than what is. :-) ATOM_OR_QUERY *res = new ATOM_OR_QUERY; res->setDescription("AtomOr"); res->setNegation(true); res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(2))); + Queries::Query::CHILD_TYPE(makeAtomNumQuery(2))); res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(5))); + Queries::Query::CHILD_TYPE(makeAtomNumQuery(5))); res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(6))); + Queries::Query::CHILD_TYPE(makeAtomNumQuery(6))); res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(7))); + Queries::Query::CHILD_TYPE(makeAtomNumQuery(7))); res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(8))); + Queries::Query::CHILD_TYPE(makeAtomNumQuery(8))); res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(9))); - res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(10))); - res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(14))); - res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(15))); - res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(16))); - res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(17))); - res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(18))); - res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(33))); - res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(34))); - res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(35))); - res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(36))); - res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(52))); - res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(53))); - res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(54))); - res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(85))); - res->addChild( - Queries::Query::CHILD_TYPE(makeAtomNumQuery(86))); + Queries::Query::CHILD_TYPE(makeAtomNumQuery(9))); + res->addChild(Queries::Query::CHILD_TYPE( + makeAtomNumQuery(10))); + res->addChild(Queries::Query::CHILD_TYPE( + makeAtomNumQuery(14))); + res->addChild(Queries::Query::CHILD_TYPE( + makeAtomNumQuery(15))); + res->addChild(Queries::Query::CHILD_TYPE( + makeAtomNumQuery(16))); + res->addChild(Queries::Query::CHILD_TYPE( + makeAtomNumQuery(17))); + res->addChild(Queries::Query::CHILD_TYPE( + makeAtomNumQuery(18))); + res->addChild(Queries::Query::CHILD_TYPE( + makeAtomNumQuery(33))); + res->addChild(Queries::Query::CHILD_TYPE( + makeAtomNumQuery(34))); + res->addChild(Queries::Query::CHILD_TYPE( + makeAtomNumQuery(35))); + res->addChild(Queries::Query::CHILD_TYPE( + makeAtomNumQuery(36))); + res->addChild(Queries::Query::CHILD_TYPE( + makeAtomNumQuery(52))); + res->addChild(Queries::Query::CHILD_TYPE( + makeAtomNumQuery(53))); + res->addChild(Queries::Query::CHILD_TYPE( + makeAtomNumQuery(54))); + res->addChild(Queries::Query::CHILD_TYPE( + makeAtomNumQuery(85))); + res->addChild(Queries::Query::CHILD_TYPE( + makeAtomNumQuery(86))); return res; } - ATOM_EQUALS_QUERY *makeAtomInNRingsQuery(int what) { ATOM_EQUALS_QUERY *res; res = makeAtomSimpleQuery(what, queryIsAtomInNRings); @@ -448,12 +458,11 @@ ATOM_EQUALS_QUERY *makeAtomInNRingsQuery(int what) { ATOM_EQUALS_QUERY *makeAtomHasRingBondQuery() { ATOM_EQUALS_QUERY *res = - makeAtomSimpleQuery(true, queryAtomHasRingBond); + makeAtomSimpleQuery(true, queryAtomHasRingBond); res->setDescription("AtomHasRingBond"); return res; } - BOND_EQUALS_QUERY *makeBondOrderEqualsQuery(Bond::BondType what) { BOND_EQUALS_QUERY *res = new BOND_EQUALS_QUERY; res->setVal(what); diff --git a/Code/GraphMol/QueryOps.h b/Code/GraphMol/QueryOps.h index afba81bb5..00f036915 100644 --- a/Code/GraphMol/QueryOps.h +++ b/Code/GraphMol/QueryOps.h @@ -269,6 +269,14 @@ T *makeAtomTotalDegreeQuery(int what, const std::string &descr) { //! \overload ATOM_EQUALS_QUERY *makeAtomTotalDegreeQuery(int what); +//! returns a Query for matching heavy atom degree +template +T *makeAtomHeavyAtomDegreeQuery(int what, const std::string &descr) { + return makeAtomSimpleQuery(what, queryAtomHeavyAtomDegree, descr); +} +//! \overload +ATOM_EQUALS_QUERY *makeAtomHeavyAtomDegreeQuery(int what); + //! returns a Query for matching hydrogen count template T *makeAtomHCountQuery(int what, const std::string &descr) { diff --git a/Code/GraphMol/RGroupDecomposition/RGroupDecomp.cpp b/Code/GraphMol/RGroupDecomposition/RGroupDecomp.cpp index 4d2fb6450..80f980709 100644 --- a/Code/GraphMol/RGroupDecomposition/RGroupDecomp.cpp +++ b/Code/GraphMol/RGroupDecomposition/RGroupDecomp.cpp @@ -168,15 +168,15 @@ bool RGroupDecompositionParameters::prepareCore(RWMol &core, MolOps::AdjustQueryParameters adjustParams; adjustParams.makeDummiesQueries = true; - adjustParams.adjustDegree = onlyMatchAtRGroups - ? MolOps::AdjustDegree::HeavyDegree - : MolOps::AdjustDegree::NoAdjust; + adjustParams.adjustDegree = false; + adjustParams.adjustHeavyDegree = onlyMatchAtRGroups; + // if (onlyMatchAtRGroups) + // adjustParams.adjustDegreeFlags |= MolOps::ADJUST_IGNOREHS; adjustQueryProperties(core, &adjustParams); for (std::map::iterator it = atomToLabel.begin(); it != atomToLabel.end(); ++it) core.getAtomWithIdx(it->first)->setProp(RLABEL, it->second); - return true; } @@ -954,8 +954,8 @@ int RGroupDecomposition::add(const ROMol &inmol) { } } if (potentialMatches.size() == 0) { - BOOST_LOG(rdWarningLog) << "No attachment points in side chains" - << std::endl; + BOOST_LOG(rdWarningLog) + << "No attachment points in side chains" << std::endl; return -1; } diff --git a/Code/GraphMol/RGroupDecomposition/testRGroupDecomp.cpp b/Code/GraphMol/RGroupDecomposition/testRGroupDecomp.cpp index c6021e4e8..cd8092a34 100644 --- a/Code/GraphMol/RGroupDecomposition/testRGroupDecomp.cpp +++ b/Code/GraphMol/RGroupDecomposition/testRGroupDecomp.cpp @@ -128,6 +128,7 @@ void testRGroupOnlyMatching() { ROMol *mol = SmilesToMol(matchRGroupOnlyData[i]); int res = decomp.add(*mol); if (i < 4) { + std::cerr << i << " " << res << std::endl; TEST_ASSERT(res == i); } else { TEST_ASSERT(res == -1); diff --git a/Code/GraphMol/Wrap/MolOps.cpp b/Code/GraphMol/Wrap/MolOps.cpp index f978e05db..72ad178f6 100644 --- a/Code/GraphMol/Wrap/MolOps.cpp +++ b/Code/GraphMol/Wrap/MolOps.cpp @@ -950,7 +950,7 @@ struct molops_wrapper { - The original molecule is *not* modified.\n\ \n"; python::def("RemoveHs", - (ROMol * (*)(const ROMol &, bool, bool, bool))MolOps::removeHs, + (ROMol * (*)(const ROMol &, bool, bool, bool)) MolOps::removeHs, (python::arg("mol"), python::arg("implicitOnly") = false, python::arg("updateExplicitCount") = false, python::arg("sanitize") = true), @@ -1962,7 +1962,7 @@ EXAMPLES:\n\ \n\ \n"; python::def("ReplaceCore", (ROMol * (*)(const ROMol &, const ROMol &, bool, - bool, bool, bool))replaceCore, + bool, bool, bool)) replaceCore, (python::arg("mol"), python::arg("coreQuery"), python::arg("replaceDummies") = true, python::arg("labelByIndex") = false, @@ -2081,6 +2081,8 @@ EXAMPLES:\n\ Attributes:\n\ - adjustDegree: \n\ modified atoms have an explicit-degree query added based on their degree in the query \n\ + - adjustHeavyDegree: \n\ + modified atoms have a heavy-atom-degree query added based on their degree in the query \n\ - adjustDegreeFlags: \n\ controls which atoms have a degree query added \n\ - adjustRingCount: \n\ @@ -2113,6 +2115,10 @@ A note on the flags controlling which atoms/bonds are modified: \n\ &MolOps::AdjustQueryParameters::adjustDegree) .def_readwrite("adjustDegreeFlags", &MolOps::AdjustQueryParameters::adjustDegreeFlags) + .def_readwrite("adjustHeavyDegree", + &MolOps::AdjustQueryParameters::adjustHeavyDegree) + .def_readwrite("adjustHeavyDegreeFlags", + &MolOps::AdjustQueryParameters::adjustHeavyDegreeFlags) .def_readwrite("adjustRingCount", &MolOps::AdjustQueryParameters::adjustRingCount) .def_readwrite("adjustRingCountFlags", diff --git a/Code/GraphMol/molopstest.cpp b/Code/GraphMol/molopstest.cpp index fe3e19bd6..6dcf549a7 100644 --- a/Code/GraphMol/molopstest.cpp +++ b/Code/GraphMol/molopstest.cpp @@ -5785,6 +5785,38 @@ void testAdjustQueryProperties() { delete qm; } + { // heavy atom degree + std::string smiles = "C1CC(*)C1*"; + ROMol *qm = SmartsToMol(smiles); + TEST_ASSERT(qm); + TEST_ASSERT(qm->getNumAtoms() == 6); + MolOps::AdjustQueryParameters params; + params.adjustDegree = false; + params.adjustHeavyDegree = true; + ROMol *aqm = MolOps::adjustQueryProperties(*qm, ¶ms); + TEST_ASSERT(aqm); + TEST_ASSERT(aqm->getNumAtoms() == 6); + { + smiles = "C1CC(C)C1(C)"; + ROMol *m = SmilesToMol(smiles); + TEST_ASSERT(m); + MatchVectType match; + TEST_ASSERT(SubstructMatch(*m, *qm, match)); + TEST_ASSERT(SubstructMatch(*m, *aqm, match)); + delete m; + } + { + smiles = "C1CC([2H])C1(C)"; + ROMol *m = SmilesToMol(smiles); + TEST_ASSERT(m); + MatchVectType match; + TEST_ASSERT(SubstructMatch(*m, *qm, match)); + TEST_ASSERT(!SubstructMatch(*m, *aqm, match)); + delete m; + } + delete qm; + delete aqm; + } BOOST_LOG(rdInfoLog) << "Finished" << std::endl; } @@ -6618,11 +6650,15 @@ void testGithubIssue908() { << std::endl; { std::string mb = - "\n RDKit 2D\n\n 4 3 0 0 0 0 0 0 0 0999 V2000\n " + "\n RDKit 2D\n\n 4 3 0 0 0 0 0 0 0 0999 " + "V2000\n " " -0.0000 -1.5000 0.0000 Br 0 0 0 0 0 0 0 0 0 0 0 " - "0\n -0.0000 -0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 " - " 0\n 1.2990 0.7500 0.0000 F 0 0 0 0 0 0 0 0 0 0 " - "0 0\n -1.2990 0.7500 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 " + "0\n -0.0000 -0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 " + "0 " + " 0\n 1.2990 0.7500 0.0000 F 0 0 0 0 0 0 0 0 0 0 " + " " + "0 0\n -1.2990 0.7500 0.0000 Cl 0 0 0 0 0 0 0 0 0 " + "0 " " 0 0\n 2 1 1 1\n 2 3 1 0\n 2 4 1 0\nM END\n"; RWMol *m = MolBlockToMol(mb); TEST_ASSERT(m); diff --git a/Code/GraphMol/testPickler.cpp b/Code/GraphMol/testPickler.cpp index 35b8e163c..95d072c3b 100644 --- a/Code/GraphMol/testPickler.cpp +++ b/Code/GraphMol/testPickler.cpp @@ -1,6 +1,5 @@ -// $Id$ // -// Copyright (C) 2004-2011 Greg Landrum and Rational Discovery LLC +// Copyright (C) 2004-2017 Greg Landrum and Rational Discovery LLC // // @@ All Rights Reserved @@ // This file is part of the RDKit. @@ -833,7 +832,7 @@ void testIssue3496759() { if (inl[0] == '#' || inl.size() < 2) continue; std::vector tokens; boost::split(tokens, inl, boost::is_any_of(" \t")); - // std::cerr<<"smarts: "<addAtom(new Atom(6)); m->addBond(2, 3, Bond::SINGLE); - m->getAtomWithIdx(0) - ->setMonomerInfo(new AtomMonomerInfo(AtomMonomerInfo::OTHER, "m1")); + m->getAtomWithIdx(0)->setMonomerInfo( + new AtomMonomerInfo(AtomMonomerInfo::OTHER, "m1")); m->getAtomWithIdx(1)->setMonomerInfo(new AtomPDBResidueInfo("Ca", 3)); MolOps::sanitizeMol(*m); @@ -1017,14 +1016,13 @@ void testGithub713() { void testPickleProps() { BOOST_LOG(rdInfoLog) << "-----------------------\n"; - BOOST_LOG(rdInfoLog) << "Testing pickling of properties" - << std::endl; + BOOST_LOG(rdInfoLog) << "Testing pickling of properties" << std::endl; std::vector v; v.push_back(1234.); v.push_back(444.); v.push_back(1123.); - + ROMol *m = SmilesToMol("CC"); m->setProp("double", 1.0); m->setProp("int", 100); @@ -1039,7 +1037,7 @@ void testPickleProps() { a->setProp("boolfalse", false); a->setProp("dvec", v); a->setProp("_private", true); - + Bond *b = m->getBondWithIdx(0); b->setProp("double", 1.0); b->setProp("int", 100); @@ -1047,7 +1045,7 @@ void testPickleProps() { b->setProp("boolfalse", false); b->setProp("dvec", v); b->setProp("_private", true); - + std::string pkl; { MolPickler::pickleMol(*m, pkl, PicklerOps::AllProps); @@ -1126,7 +1124,8 @@ void testPickleProps() { } { - MolPickler::pickleMol(*m, pkl, PicklerOps::AtomProps | PicklerOps::PrivateProps); + MolPickler::pickleMol(*m, pkl, + PicklerOps::AtomProps | PicklerOps::PrivateProps); RWMol *m2 = new RWMol(pkl); TEST_ASSERT(m2); TEST_ASSERT(!m2->hasProp("double")); @@ -1150,7 +1149,7 @@ void testPickleProps() { delete m2; } - + { MolPickler::pickleMol(*m, pkl, PicklerOps::BondProps); RWMol *m2 = new RWMol(pkl); @@ -1166,7 +1165,7 @@ void testPickleProps() { TEST_ASSERT(!a->hasProp("bool")); TEST_ASSERT(!a->hasProp("boolfalse")); TEST_ASSERT(!a->hasProp("_private")); - + b = m2->getBondWithIdx(0); TEST_ASSERT(b->getProp("double") == 1.0); TEST_ASSERT(b->getProp("int") == 100); @@ -1177,7 +1176,8 @@ void testPickleProps() { } { - MolPickler::pickleMol(*m, pkl, PicklerOps::BondProps | PicklerOps::PrivateProps); + MolPickler::pickleMol(*m, pkl, + PicklerOps::BondProps | PicklerOps::PrivateProps); RWMol *m2 = new RWMol(pkl); TEST_ASSERT(m2); TEST_ASSERT(!m2->hasProp("double")); @@ -1200,12 +1200,32 @@ void testPickleProps() { TEST_ASSERT(b->getProp("_private") == true); delete m2; } - + delete m; - + BOOST_LOG(rdErrorLog) << "\tdone" << std::endl; } +void testGithub1563() { + BOOST_LOG(rdInfoLog) << "-----------------------\n"; + BOOST_LOG(rdInfoLog) + << "Testing Github 1563: Add a canned Atom query for heavy atom degree" + << std::endl; + + RWMol m; + QueryAtom *qa = new QueryAtom(); + qa->setQuery(makeAtomHeavyAtomDegreeQuery(3)); + m.addAtom(qa); + TEST_ASSERT(m.getAtomWithIdx(0)->hasQuery()); + TEST_ASSERT(m.getAtomWithIdx(0)->getQuery()->getDescription() == + "AtomHeavyAtomDegree"); + RWMol nm(m); + TEST_ASSERT(nm.getAtomWithIdx(0)->hasQuery()); + TEST_ASSERT(nm.getAtomWithIdx(0)->getQuery()->getDescription() == + "AtomHeavyAtomDegree"); + + BOOST_LOG(rdErrorLog) << "\tdone" << std::endl; +} int main(int argc, char *argv[]) { RDLog::InitLogs(); @@ -1239,5 +1259,5 @@ int main(int argc, char *argv[]) { testAtomResidues(); testGithub149(); testGithub713(); - + testGithub1563(); } diff --git a/Code/PgSQL/rdkit/adapter.cpp b/Code/PgSQL/rdkit/adapter.cpp index af8065d73..2e30ad683 100644 --- a/Code/PgSQL/rdkit/adapter.cpp +++ b/Code/PgSQL/rdkit/adapter.cpp @@ -646,6 +646,7 @@ void parseAdjustQueryParameters(MolOps::AdjustQueryParameters &p, boost::property_tree::ptree pt; boost::property_tree::read_json(ss, pt); p.adjustDegree = pt.get("adjustDegree", p.adjustDegree); + p.adjustHeavyDegree = pt.get("adjustHeavyDegree", p.adjustHeavyDegree); p.adjustRingCount = pt.get("adjustRingCount", p.adjustRingCount); p.makeDummiesQueries = pt.get("makeDummiesQueries", p.makeDummiesQueries); p.aromatizeIfPossible = pt.get("aromatizeIfPossible", p.aromatizeIfPossible); @@ -654,6 +655,9 @@ void parseAdjustQueryParameters(MolOps::AdjustQueryParameters &p, std::string which; which = boost::to_upper_copy(pt.get("adjustDegreeFlags", "")); if (which != "") p.adjustDegreeFlags = parseWhichString(which); + which = + boost::to_upper_copy(pt.get("adjustHeavyDegreeFlags", "")); + if (which != "") p.adjustHeavyDegreeFlags = parseWhichString(which); which = boost::to_upper_copy(pt.get("adjustRingCountFlags", "")); if (which != "") p.adjustRingCountFlags = parseWhichString(which); which = diff --git a/Code/PgSQL/rdkit/expected/rdkit-91.out b/Code/PgSQL/rdkit/expected/rdkit-91.out index 41d8db278..b82b17d5b 100644 --- a/Code/PgSQL/rdkit/expected/rdkit-91.out +++ b/Code/PgSQL/rdkit/expected/rdkit-91.out @@ -845,3 +845,21 @@ select 'C1C(C)C1CCCC'::mol @> mol_adjust_query_properties('C1CC1CC'::mol,'{"adju select 'C1C(C)C1CCCC'::mol @> mol_adjust_query_properties('C1CC1CC'::mol,'{"adjustDegreeFlags":"bogus"}'); ERROR: bad which string provided 'BOGUS' +select 'C1C([2H])C1CCCC'::mol @> mol_adjust_query_properties('C1CC1CC'::mol); + ?column? +---------- + f +(1 row) + +select 'C1C([2H])C1CCCC'::mol @> mol_adjust_query_properties('C1CC1CC'::mol,'{"adjustDegree":false}'); + ?column? +---------- + t +(1 row) + +select 'C1C([2H])C1CCCC'::mol @> mol_adjust_query_properties('C1CC1CC'::mol,'{"adjustDegree":false,"adjustHeavyDegree":true}'); + ?column? +---------- + t +(1 row) + diff --git a/Code/PgSQL/rdkit/sql/rdkit-91.sql b/Code/PgSQL/rdkit/sql/rdkit-91.sql index 233f7d8ec..98c86f6c4 100644 --- a/Code/PgSQL/rdkit/sql/rdkit-91.sql +++ b/Code/PgSQL/rdkit/sql/rdkit-91.sql @@ -322,3 +322,6 @@ select 'C1C(C)C1CCCC'::mol @> mol_adjust_query_properties('C1CC1CC'::mol,'{"adju select 'C1C(C)C1CCCC'::mol @> mol_adjust_query_properties('C1CC1CC'::mol,'{"adjustDegreeFlags":"IGNORERINGS"}'); select 'C1C(C)C1CCCC'::mol @> mol_adjust_query_properties('C1CC1CC'::mol,'{"adjustDegreeFlags":"IGNORERINGS|IGNORECHAINS"}'); select 'C1C(C)C1CCCC'::mol @> mol_adjust_query_properties('C1CC1CC'::mol,'{"adjustDegreeFlags":"bogus"}'); +select 'C1C([2H])C1CCCC'::mol @> mol_adjust_query_properties('C1CC1CC'::mol); +select 'C1C([2H])C1CCCC'::mol @> mol_adjust_query_properties('C1CC1CC'::mol,'{"adjustDegree":false}'); +select 'C1C([2H])C1CCCC'::mol @> mol_adjust_query_properties('C1CC1CC'::mol,'{"adjustDegree":false,"adjustHeavyDegree":true}'); From b344b56a4003187a390e83e1b1d26caaf598a62f Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Fri, 15 Sep 2017 08:07:17 +0200 Subject: [PATCH 17/44] remove the INCHI-API dir from .gitignore --- .gitignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index f36ef3d71..ed5e61c4a 100644 --- a/.gitignore +++ b/.gitignore @@ -74,7 +74,6 @@ __pycache__/ /Code/GraphMol/test_data/prop.pkl /Projects/DbCLI/testData/bzr/ -External/INCHI-API/* /rdkit/ML/Data/test_data/testgeneral.dat.pkl /rdkit/ML/Data/test_data/testquant.qdat.pkl -.DS_Store \ No newline at end of file +.DS_Store From 4160d20fdcebe985061fc0b873b1837792f4ef2e Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Fri, 15 Sep 2017 18:59:26 +0200 Subject: [PATCH 18/44] Fixes github #1572 (#1573) * Fixes #1572 initial pass * one more cleanup; adjust expected results for the python unit tets --- External/INCHI-API/inchi.cpp | 33 ++- External/INCHI-API/test.cpp | 505 ++++++++++++++++++++--------------- rdkit/Chem/UnitTestInchi.py | 4 +- 3 files changed, 318 insertions(+), 224 deletions(-) diff --git a/External/INCHI-API/inchi.cpp b/External/INCHI-API/inchi.cpp index 53102a7b0..527fbb8ad 100644 --- a/External/INCHI-API/inchi.cpp +++ b/External/INCHI-API/inchi.cpp @@ -1,4 +1,3 @@ -// $Id$ // // Copyright (c) 2011, Novartis Institutes for BioMedical Research Inc. // All rights reserved. @@ -78,6 +77,7 @@ #endif #include +//#define DEBUG 1 namespace RDKit { namespace { /* assignBondDirs @@ -426,11 +426,25 @@ bool _Valence5NCleanUp3(RWMol& mol, Atom* atom) { mol, atom, 7, 0, Bond::DOUBLE, Bond::DOUBLE, 0, 1, NULL, stack, _visited); if (target == NULL) return false; - target->setFormalCharge(-1); - target->calcExplicitValence(false); - stack.top()->setBondType(Bond::SINGLE); - atom->setFormalCharge(1); - atom->calcExplicitValence(false); + // we are double bonded to a neighboring N. Check to see if we are also + // double bonded to an O. If so, we don't want to mess with the other N + // this occurs because the InChI code produces this structure: + // CN(=O)=N(=O)C + // and we don't want to mess with that. + // this was github #1572 + + std::stack stack2; + std::set _visited2; + Atom* target2 = + findAlternatingBonds(mol, atom, 8, 0, Bond::DOUBLE, Bond::DOUBLE, 0, 1, + NULL, stack2, _visited2); + if (target2 == NULL) { + target->setFormalCharge(-1); + target->calcExplicitValence(false); + stack.top()->setBondType(Bond::SINGLE); + atom->setFormalCharge(1); + atom->calcExplicitValence(false); + } return true; } @@ -1233,9 +1247,10 @@ RWMol* InchiToMol(const std::string& inchi, ExtraInchiReturnValues& rv, unsigned int aid = m->addAtom(atom, false, true); indexToAtomIndexMapping.push_back(aid); #ifdef DEBUG - BOOST_LOG(rdWarningLog) << "adding " << aid << ":" - << atom->getAtomicNum() << ":" - << (int)inchiAtom->num_iso_H[0] << std::endl; + BOOST_LOG(rdWarningLog) + << "adding " << aid << ":" << atom->getAtomicNum() << ":" + << (int)inchiAtom->num_iso_H[0] + << " charge: " << (int)inchiAtom->charge << std::endl; #endif } diff --git a/External/INCHI-API/test.cpp b/External/INCHI-API/test.cpp index 780684a49..111c61769 100644 --- a/External/INCHI-API/test.cpp +++ b/External/INCHI-API/test.cpp @@ -20,461 +20,539 @@ #include #include - #include #include #include "inchi.h" using namespace RDKit; - #ifdef RDK_TEST_MULTITHREADED namespace { - void runblock(const std::vector &mols,unsigned int count, - unsigned int idx, - std::vector &inchis, - std::vector &keys - ){ - for(unsigned int j=0;j<50;j++){ - for(unsigned int i=0;i &mols, unsigned int count, + unsigned int idx, std::vector &inchis, + std::vector &keys) { + for (unsigned int j = 0; j < 50; j++) { + for (unsigned int i = 0; i < mols.size(); ++i) { + if (i % count != idx) continue; + ROMol *mol = mols[i]; + ExtraInchiReturnValues tmp; + std::string inchi = MolToInchi(*mol, tmp); + TEST_ASSERT(inchi == inchis[i]); + std::string key = InchiToInchiKey(inchi); + TEST_ASSERT(key == keys[i]); + ROMol *mol2 = InchiToMol(inchi, tmp); + TEST_ASSERT(mol2); + ExtraInchiReturnValues tmp2; + std::string inchi2 = MolToInchi(*mol2, tmp2); + TEST_ASSERT(inchi == inchi2); + delete mol2; } - }; + } +}; } -#include -void testMultiThread(){ +#include +void testMultiThread() { BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdErrorLog) << " Test multithreading" << std::endl; std::string fName = getenv("RDBASE"); fName += "/Data/NCI/first_200.props.sdf"; SDMolSupplier suppl(fName); - std::cerr<<"reading molecules"< mols; - while(!suppl.atEnd()&&mols.size()<100){ - ROMol *mol=0; - try{ - mol=suppl.next(); - } catch(...){ + while (!suppl.atEnd() && mols.size() < 100) { + ROMol *mol = 0; + try { + mol = suppl.next(); + } catch (...) { continue; } - if(!mol) continue; + if (!mol) continue; mols.push_back(mol); } - std::cerr<<"generating reference data"< inchis; std::vector keys; - BOOST_FOREACH(const ROMol *mol,mols){ + BOOST_FOREACH (const ROMol *mol, mols) { ExtraInchiReturnValues tmp; - std::string inchi=MolToInchi(*mol,tmp); - std::string key=InchiToInchiKey(inchi); + std::string inchi = MolToInchi(*mol, tmp); + std::string key = InchiToInchiKey(inchi); inchis.push_back(inchi); keys.push_back(key); } - + boost::thread_group tg; - std::cerr<<"processing"<(MolFileToMol(fName)); TEST_ASSERT(m); - std::string smi=MolToSmiles(*m,true); - TEST_ASSERT(smi=="CNC[C@H](O)[C@@H](O)[C@H](O)[C@H](O)CO"); + std::string smi = MolToSmiles(*m, true); + TEST_ASSERT(smi == "CNC[C@H](O)[C@@H](O)[C@H](O)[C@H](O)CO"); ExtraInchiReturnValues tmp; - std::string inchi=MolToInchi(*m,tmp); - TEST_ASSERT(inchi=="InChI=1S/C7H17NO5/c1-8-2-4(10)6(12)7(13)5(11)3-9/h4-13H,2-3H2,1H3/t4-,5+,6+,7+/m0/s1"); + std::string inchi = MolToInchi(*m, tmp); + TEST_ASSERT(inchi == + "InChI=1S/C7H17NO5/c1-8-2-4(10)6(12)7(13)5(11)3-9/" + "h4-13H,2-3H2,1H3/t4-,5+,6+,7+/m0/s1"); // blow out the stereo information with a copy: - RWMol *m2=new RWMol(*m); + RWMol *m2 = new RWMol(*m); m2->clearComputedProps(); MolOps::sanitizeMol(*m2); - inchi=MolToInchi(*m2,tmp); - TEST_ASSERT(inchi=="InChI=1S/C7H17NO5/c1-8-2-4(10)6(12)7(13)5(11)3-9/h4-13H,2-3H2,1H3/t4-,5+,6+,7+/m0/s1"); + inchi = MolToInchi(*m2, tmp); + TEST_ASSERT(inchi == + "InChI=1S/C7H17NO5/c1-8-2-4(10)6(12)7(13)5(11)3-9/" + "h4-13H,2-3H2,1H3/t4-,5+,6+,7+/m0/s1"); delete m; delete m2; - } - BOOST_LOG(rdInfoLog) <<"done" << std::endl; + BOOST_LOG(rdInfoLog) << "done" << std::endl; } -void testGithubIssue8(){ +void testGithubIssue8() { BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; - BOOST_LOG(rdInfoLog) <<"testing a consequence of the fix for github issue 8: bad mols from some inchis" << std::endl; + BOOST_LOG(rdInfoLog) << "testing a consequence of the fix for github issue " + "8: bad mols from some inchis" + << std::endl; { - std::string fName= getenv("RDBASE"); + std::string fName = getenv("RDBASE"); fName += "/External/INCHI-API/test_data/github8_extra.mol"; - ROMol *m = static_cast(MolFileToMol(fName,true,false)); + ROMol *m = static_cast(MolFileToMol(fName, true, false)); TEST_ASSERT(m); ExtraInchiReturnValues tmp; - std::string inchi=MolToInchi(*m,tmp); - TEST_ASSERT(inchi=="InChI=1S/C20H13IN2O3/c21-15-8-14-18(9-16(15)23)26-17-7-10(22)5-6-13(17)19(14)11-3-1-2-4-12(11)20(24)25/h1-9,23H,22H2,(H,24,25)/b23-16+/i21-2"); + std::string inchi = MolToInchi(*m, tmp); + TEST_ASSERT(inchi == + "InChI=1S/C20H13IN2O3/" + "c21-15-8-14-18(9-16(15)23)26-17-7-10(22)5-6-13(17)19(14)11-3-" + "1-2-4-12(11)20(24)25/h1-9,23H,22H2,(H,24,25)/b23-16+/i21-2"); ExtraInchiReturnValues tmp2; - ROMol *m2 = InchiToMol(inchi,tmp2); + ROMol *m2 = InchiToMol(inchi, tmp2); TEST_ASSERT(m2); - std::string smi=MolToSmiles(*m2,true); - TEST_ASSERT(smi=="N=c1cc2oc3cc(N)ccc3c(-c3ccccc3C(=O)O)c-2cc1[125I]"); + std::string smi = MolToSmiles(*m2, true); + TEST_ASSERT(smi == "N=c1cc2oc3cc(N)ccc3c(-c3ccccc3C(=O)O)c-2cc1[125I]"); - inchi=MolToInchi(*m2,tmp2); - TEST_ASSERT(inchi=="InChI=1S/C20H13IN2O3/c21-15-8-14-18(9-16(15)23)26-17-7-10(22)5-6-13(17)19(14)11-3-1-2-4-12(11)20(24)25/h1-9,23H,22H2,(H,24,25)/i21-2"); + inchi = MolToInchi(*m2, tmp2); + TEST_ASSERT(inchi == + "InChI=1S/C20H13IN2O3/" + "c21-15-8-14-18(9-16(15)23)26-17-7-10(22)5-6-13(17)19(14)11-3-" + "1-2-4-12(11)20(24)25/h1-9,23H,22H2,(H,24,25)/i21-2"); delete m; delete m2; - } - BOOST_LOG(rdInfoLog) <<"done" << std::endl; + BOOST_LOG(rdInfoLog) << "done" << std::endl; } -void testGithubIssue40(){ +void testGithubIssue40() { BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; - BOOST_LOG(rdInfoLog) <<"testing github issue 40: bad MWs from inchis" << std::endl; + BOOST_LOG(rdInfoLog) << "testing github issue 40: bad MWs from inchis" + << std::endl; { ExtraInchiReturnValues tmp; - std::string inchi="InChI=1S/C10H9N3O/c1-7-11-10(14)9(13-12-7)8-5-3-2-4-6-8/h2-6H,1H3,(H,11,12,14)"; - ROMol *m = InchiToMol(inchi,tmp); + std::string inchi = + "InChI=1S/C10H9N3O/c1-7-11-10(14)9(13-12-7)8-5-3-2-4-6-8/" + "h2-6H,1H3,(H,11,12,14)"; + ROMol *m = InchiToMol(inchi, tmp); TEST_ASSERT(m); - double mw=Descriptors::calcAMW(*m); - TEST_ASSERT(feq(mw,187.202)); - + double mw = Descriptors::calcAMW(*m); + TEST_ASSERT(feq(mw, 187.202)); + delete m; } - BOOST_LOG(rdInfoLog) <<"done" << std::endl; + BOOST_LOG(rdInfoLog) << "done" << std::endl; } -void testGithubIssue67(){ +void testGithubIssue67() { BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; - BOOST_LOG(rdInfoLog) <<"testing github issue 67: seg fault from inchi" << std::endl; + BOOST_LOG(rdInfoLog) << "testing github issue 67: seg fault from inchi" + << std::endl; { ExtraInchiReturnValues tmp; - std::string inchi="InChI=1S/C18H17N3/c19-18(20)21-14-17-12-10-16(11-13-17)9-5-4-8-15-6-2-1-3-7-15/h1-3,6-13H,14H2,(H4,19,20,21)/b9-8+"; - ROMol *m = InchiToMol(inchi,tmp); + std::string inchi = + "InChI=1S/C18H17N3/" + "c19-18(20)21-14-17-12-10-16(11-13-17)9-5-4-8-15-6-2-1-3-7-15/" + "h1-3,6-13H,14H2,(H4,19,20,21)/b9-8+"; + ROMol *m = InchiToMol(inchi, tmp); TEST_ASSERT(m); - TEST_ASSERT(m->getNumAtoms()==21); - + TEST_ASSERT(m->getNumAtoms() == 21); + delete m; } - BOOST_LOG(rdInfoLog) <<"done" << std::endl; + BOOST_LOG(rdInfoLog) << "done" << std::endl; } -void testGithubIssue68(){ +void testGithubIssue68() { BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; - BOOST_LOG(rdInfoLog) <<"testing github issue 68: hang while reading InChI" << std::endl; + BOOST_LOG(rdInfoLog) << "testing github issue 68: hang while reading InChI" + << std::endl; { ExtraInchiReturnValues tmp; - std::string inchi="InChI=1S/C11H20NSSi2.Li/c1-14(2)8-9-15(3,4)12(14)10-11-6-5-7-13-11;/h6-7H,8-10H2,1-4H3;/q-1;+1"; - BOOST_LOG(rdInfoLog) <<" parse 1:" << std::endl; - ROMol *m = InchiToMol(inchi,tmp); - BOOST_LOG(rdInfoLog) <<" done" << std::endl; + std::string inchi = + "InChI=1S/C11H20NSSi2.Li/c1-14(2)8-9-15(3,4)12(14)10-11-6-5-7-13-11;/" + "h6-7H,8-10H2,1-4H3;/q-1;+1"; + BOOST_LOG(rdInfoLog) << " parse 1:" << std::endl; + ROMol *m = InchiToMol(inchi, tmp); + BOOST_LOG(rdInfoLog) << " done" << std::endl; TEST_ASSERT(m); - TEST_ASSERT(m->getNumAtoms()==16); - + TEST_ASSERT(m->getNumAtoms() == 16); + delete m; } { ExtraInchiReturnValues tmp; - std::string inchi="InChI=1S/C12H22NSSi2.Li/c1-15(2)10-11-16(3,4)13(15)8-7-12-6-5-9-14-12;/h6,9H,7-8,10-11H2,1-4H3;/q-1;+1"; - BOOST_LOG(rdInfoLog) <<" parse 2:" << std::endl; - ROMol *m = InchiToMol(inchi,tmp); - BOOST_LOG(rdInfoLog) <<" done" << std::endl; + std::string inchi = + "InChI=1S/C12H22NSSi2.Li/" + "c1-15(2)10-11-16(3,4)13(15)8-7-12-6-5-9-14-12;/" + "h6,9H,7-8,10-11H2,1-4H3;/q-1;+1"; + BOOST_LOG(rdInfoLog) << " parse 2:" << std::endl; + ROMol *m = InchiToMol(inchi, tmp); + BOOST_LOG(rdInfoLog) << " done" << std::endl; TEST_ASSERT(m); - TEST_ASSERT(m->getNumAtoms()==17); - + TEST_ASSERT(m->getNumAtoms() == 17); + delete m; } - BOOST_LOG(rdInfoLog) <<"done" << std::endl; + BOOST_LOG(rdInfoLog) << "done" << std::endl; } -void testGithubIssue296(){ +void testGithubIssue296() { BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; - BOOST_LOG(rdInfoLog) <<"testing github issue 296: problems with chiral S and inchi" << std::endl; + BOOST_LOG(rdInfoLog) + << "testing github issue 296: problems with chiral S and inchi" + << std::endl; { - std::string smiles="C[S@@](=O)C(C)(C)C"; + std::string smiles = "C[S@@](=O)C(C)(C)C"; ROMol *m = SmilesToMol(smiles); TEST_ASSERT(m); ExtraInchiReturnValues tmp; - std::string inchi=MolToInchi(*m,tmp); - TEST_ASSERT(inchi=="InChI=1S/C5H12OS/c1-5(2,3)7(4)6/h1-4H3/t7-/m1/s1"); + std::string inchi = MolToInchi(*m, tmp); + TEST_ASSERT(inchi == "InChI=1S/C5H12OS/c1-5(2,3)7(4)6/h1-4H3/t7-/m1/s1"); delete m; } { - std::string fName= getenv("RDBASE"); + std::string fName = getenv("RDBASE"); fName += "/External/INCHI-API/test_data/github296.mol"; ROMol *m = static_cast(MolFileToMol(fName)); TEST_ASSERT(m); ExtraInchiReturnValues tmp; - std::string inchi=MolToInchi(*m,tmp); - TEST_ASSERT(inchi=="InChI=1S/C5H12OS/c1-5(2,3)7(4)6/h1-4H3/t7-/m1/s1"); + std::string inchi = MolToInchi(*m, tmp); + TEST_ASSERT(inchi == "InChI=1S/C5H12OS/c1-5(2,3)7(4)6/h1-4H3/t7-/m1/s1"); delete m; } - BOOST_LOG(rdInfoLog) <<"done" << std::endl; + BOOST_LOG(rdInfoLog) << "done" << std::endl; } -void testGithubIssue437(){ +void testGithubIssue437() { BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; - BOOST_LOG(rdInfoLog) <<"testing github issue 437: problems with InChI and ring stereochemistry" << std::endl; + BOOST_LOG(rdInfoLog) << "testing github issue 437: problems with InChI and " + "ring stereochemistry" + << std::endl; // start with some general chirality checks { - std::string smiles="C[C@@H](F)Cl"; + std::string smiles = "C[C@@H](F)Cl"; ROMol *m = SmilesToMol(smiles); TEST_ASSERT(m); - std::string smi1 = MolToSmiles(*m,true); + std::string smi1 = MolToSmiles(*m, true); ExtraInchiReturnValues tmp; - std::string inchi=MolToInchi(*m,tmp); - //std::cerr<<" result: "<getNumAtoms()==1); - TEST_ASSERT(m->getAtomWithIdx(0)->getNumRadicalElectrons()==1); - TEST_ASSERT(m->getAtomWithIdx(0)->getNumExplicitHs()==1); - TEST_ASSERT(m->getAtomWithIdx(0)->getNoImplicit()==true); + TEST_ASSERT(m->getNumAtoms() == 1); + TEST_ASSERT(m->getAtomWithIdx(0)->getNumRadicalElectrons() == 1); + TEST_ASSERT(m->getAtomWithIdx(0)->getNumExplicitHs() == 1); + TEST_ASSERT(m->getAtomWithIdx(0)->getNoImplicit() == true); - std::string oinchi=MolToInchi(*m,tmp); - - TEST_ASSERT(oinchi==inchi); + std::string oinchi = MolToInchi(*m, tmp); + + TEST_ASSERT(oinchi == inchi); delete m; } - BOOST_LOG(rdInfoLog) <<"done" << std::endl; + BOOST_LOG(rdInfoLog) << "done" << std::endl; } -void testGithubIssue614(){ +void testGithubIssue614() { BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; - BOOST_LOG(rdInfoLog) <<"testing github issue 614: segfault from MolToInchi when bad bond stereochem info is present" << std::endl; + BOOST_LOG(rdInfoLog) << "testing github issue 614: segfault from MolToInchi " + "when bad bond stereochem info is present" + << std::endl; { - std::string smiles="C/C=C/C"; + std::string smiles = "C/C=C/C"; RWMol *m = SmilesToMol(smiles); TEST_ASSERT(m); m->removeAtom(3); ExtraInchiReturnValues tmp; - std::string inchi=MolToInchi(*m,tmp); - TEST_ASSERT(inchi=="InChI=1S/C3H6/c1-3-2/h3H,1H2,2H3"); + std::string inchi = MolToInchi(*m, tmp); + TEST_ASSERT(inchi == "InChI=1S/C3H6/c1-3-2/h3H,1H2,2H3"); delete m; } - BOOST_LOG(rdInfoLog) <<"done" << std::endl; + BOOST_LOG(rdInfoLog) << "done" << std::endl; } +void testGithubIssue1572() { + BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; + BOOST_LOG(rdInfoLog) + << "testing github issue 1572: Incorrect conversion from InChI" + << std::endl; + + { + std::string inchi = + "InChI=1S/C16H10N6O2/" + "c23-21(15-9-17-11-5-1-3-7-13(11)19-15)22(24)16-10-18-12-6-2-4-8-14(12)" + "20-16/h1-10H"; + ExtraInchiReturnValues tmp; + RWMol *m = InchiToMol(inchi, tmp, false); + TEST_ASSERT(m); + TEST_ASSERT(m->getNumAtoms() == 24); + m->updatePropertyCache(false); + TEST_ASSERT(m->getAtomWithIdx(20)->getAtomicNum() == 7); + TEST_ASSERT(m->getAtomWithIdx(21)->getAtomicNum() == 7); + TEST_ASSERT(m->getAtomWithIdx(22)->getAtomicNum() == 8); + TEST_ASSERT(m->getAtomWithIdx(23)->getAtomicNum() == 8); + TEST_ASSERT(m->getAtomWithIdx(20)->getFormalCharge() == 0); + TEST_ASSERT(m->getAtomWithIdx(21)->getFormalCharge() == 0); + TEST_ASSERT(m->getAtomWithIdx(22)->getFormalCharge() == 0); + TEST_ASSERT(m->getAtomWithIdx(23)->getFormalCharge() == 0); + + // and the molecule should be sanitizable: + MolOps::sanitizeMol(*m); + TEST_ASSERT(m->getAtomWithIdx(20)->getFormalCharge() == 1); + TEST_ASSERT(m->getAtomWithIdx(21)->getFormalCharge() == 1); + TEST_ASSERT(m->getAtomWithIdx(22)->getFormalCharge() == -1); + TEST_ASSERT(m->getAtomWithIdx(23)->getFormalCharge() == -1); + delete m; + } + BOOST_LOG(rdInfoLog) << "done" << std::endl; +} //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* // //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* -int main(){ +int main() { RDLog::InitLogs(); #if 1 testGithubIssue3(); @@ -486,6 +564,7 @@ int main(){ testMultiThread(); testGithubIssue437(); testGithubIssue562(); -#endif testGithubIssue614(); +#endif + testGithubIssue1572(); } diff --git a/rdkit/Chem/UnitTestInchi.py b/rdkit/Chem/UnitTestInchi.py index b2698fbe9..0e1a65eee 100755 --- a/rdkit/Chem/UnitTestInchi.py +++ b/rdkit/Chem/UnitTestInchi.py @@ -248,9 +248,9 @@ class TestCase(unittest.TestCase): same += 1 fmt = "\n{0}InChI read Summary: {1} identical, {2} variance, {3} reasonable variance{4}" print(fmt.format(COLOR_GREEN, same, diff, reasonable, COLOR_RESET)) - self.assertEqual(same, 620) + self.assertEqual(same, 621) self.assertEqual(diff, 0) - self.assertEqual(reasonable, 561) + self.assertEqual(reasonable, 560) def test2InchiOptions(self): m = MolFromSmiles("CC=C(N)C") From f30dea195f95dd2f1c16647d5c39035912277ba6 Mon Sep 17 00:00:00 2001 From: Patrick Avery Date: Fri, 15 Sep 2017 22:44:06 -0400 Subject: [PATCH 19/44] Added C++ version of getBestRMS() (#1568) getBestRMS() was previously a Python-only function. This adds a C++ version of the function, and replaces the old version. --- Code/GraphMol/MolAlign/AlignMolecules.cpp | 46 ++++++++++++++++ Code/GraphMol/MolAlign/AlignMolecules.h | 30 +++++++++++ Code/GraphMol/MolAlign/Wrap/rdMolAlign.cpp | 59 +++++++++++++++++++++ Code/GraphMol/MolAlign/Wrap/testMolAlign.py | 12 +++++ Code/GraphMol/MolAlign/testMolAlign.cpp | 25 ++++++++- rdkit/Chem/AllChem.py | 46 ---------------- 6 files changed, 170 insertions(+), 48 deletions(-) diff --git a/Code/GraphMol/MolAlign/AlignMolecules.cpp b/Code/GraphMol/MolAlign/AlignMolecules.cpp index 2cf104855..c3517435a 100644 --- a/Code/GraphMol/MolAlign/AlignMolecules.cpp +++ b/Code/GraphMol/MolAlign/AlignMolecules.cpp @@ -69,6 +69,52 @@ double alignMol(ROMol &prbMol, const ROMol &refMol, int prbCid, int refCid, return res; } +double getBestRMS(ROMol& probeMol, ROMol& refMol, + int probeId, int refId, + const std::vector& map, + int maxMatches) +{ + std::vector matches = map; + if (matches.empty()) { + bool uniquify = false; + bool recursionPossible = true; + bool useChirality = false; + bool useQueryQueryMatches = false; + + SubstructMatch(refMol, probeMol, matches, uniquify, + recursionPossible, useChirality, + useQueryQueryMatches, maxMatches); + + if (matches.empty()) { + throw MolAlignException( + "No sub-structure match found between the reference and probe mol"); + } + + if (matches.size() > 1e6) { + std::string name; + probeMol.getPropIfPresent(common_properties::_Name, name); + std::cerr << "Warning in " << __FUNCTION__ << ": " << matches.size() + << " matches detected for molecule " << name << ", this may " + << "lead to a performance slowdown.\n"; + } + } + + double bestRMS = 1.e300; + MatchVectType& bestMatch = matches[0]; + for (size_t i = 0; i < matches.size(); ++i) { + double rms = alignMol(probeMol, refMol, probeId, refId, &matches[i]); + if (rms < bestRMS) { + bestRMS = rms; + bestMatch = matches[i]; + } + } + + // Perform a final alignment to the best alignment... + if (&bestMatch != &matches.back()) + alignMol(probeMol, refMol, probeId, refId, &bestMatch); + return bestRMS; +} + void _fillAtomPositions(RDGeom::Point3DConstPtrVect &pts, const Conformer &conf, const std::vector *atomIds = 0) { unsigned int na = conf.getNumAtoms(); diff --git a/Code/GraphMol/MolAlign/AlignMolecules.h b/Code/GraphMol/MolAlign/AlignMolecules.h index 747321b02..0d4efafd5 100644 --- a/Code/GraphMol/MolAlign/AlignMolecules.h +++ b/Code/GraphMol/MolAlign/AlignMolecules.h @@ -100,6 +100,36 @@ double alignMol(ROMol &prbMol, const ROMol &refMol, int prbCid = -1, const RDNumeric::DoubleVector *weights = 0, bool reflect = false, unsigned int maxIters = 50); +//! Returns the optimal RMS for aligning two molecules, taking +// symmetry into account. As a side-effect, the probe molecule is +// left in the aligned state. +/*! + This function will attempt to align all permutations of matching atom + orders in both molecules, for some molecules it will lead to 'combinatorial + explosion' especially if hydrogens are present. + Use 'RDKit::MolAlign::alignMol' to align molecules without changing the + atom order. + + \param probeMol the molecule to be aligned to the reference + \param refMol the reference molecule + \param probeId (optional) probe conformation to use + \param refId (optional) reference conformation to use + \param map (optional) a vector of vectors of pairs of atom IDs + (probe AtomId, ref AtomId) used to compute the alignments. + If not provided, these will be generated using a + substructure search. + \param maxMatches (optional) if map is empty, this will be the max number of + matches found in a SubstructMatch(). + + Returns + Best RMSD value found +*/ +double getBestRMS(ROMol& probeMol, ROMol& refMol, + int probeId = -1, int refId = -1, + const std::vector& map = + std::vector(), + int maxMatches = 1e6); + //! Align the conformations of a molecule using a common set of atoms. If // the molecules contains queries, then the queries must also match exactly. diff --git a/Code/GraphMol/MolAlign/Wrap/rdMolAlign.cpp b/Code/GraphMol/MolAlign/Wrap/rdMolAlign.cpp index c1d3b5c02..9c1596260 100644 --- a/Code/GraphMol/MolAlign/Wrap/rdMolAlign.cpp +++ b/Code/GraphMol/MolAlign/Wrap/rdMolAlign.cpp @@ -47,6 +47,17 @@ MatchVectType *_translateAtomMap(python::object atomMap) { return aMap; } +std::vector _translateAtomMapVector(python::object atomMapVec) { + std::vector aMapVec; + PySequenceHolder aMapVecSeq(atomMapVec); + for (size_t i = 0; i < aMapVecSeq.size(); ++i) { + MatchVectType* aMap = _translateAtomMap(aMapVecSeq[i]); + aMapVec.push_back(*aMap); + delete aMap; + } + return aMapVec; +} + RDNumeric::DoubleVector *_translateWeights(python::object weights) { PySequenceHolder wts(weights); unsigned int nwts = wts.size(); @@ -197,6 +208,21 @@ double AlignMolecule(ROMol &prbMol, const ROMol &refMol, int prbCid = -1, return rmsd; } +double GetBestRMS(ROMol &prbMol, ROMol &refMol, int prbId, + int refId, python::object map, int maxMatches) { + std::vector aMapVec; + if (map != python::object()) + aMapVec = _translateAtomMapVector(map); + + double rmsd; + { + NOGIL gil; + rmsd = MolAlign::getBestRMS(prbMol, refMol, prbId, refId, + aMapVec, maxMatches); + } + return rmsd; +} + namespace MolAlign { class PyO3A { public: @@ -636,6 +662,39 @@ BOOST_PYTHON_MODULE(rdMolAlign) { python::arg("maxIters") = 50), docString.c_str()); + docString = + "Returns the optimal RMS for aligning two molecules, taking\n\ + symmetry into account. As a side-effect, the probe molecule is\n\ + left in the aligned state.\n\ + \n\ + Note:\n\ + This function will attempt to align all permutations of matching atom\n\ + orders in both molecules, for some molecules it will lead to\n\ + 'combinatorial explosion' especially if hydrogens are present.\n\ + Use 'rdkit.Chem.AllChem.AlignMol' to align molecules without changing\n\ + the atom order.\n\ + \n\ + ARGUMENTS\n\ + - prbMol: the molecule to be aligned to the reference\n\ + - refMol: the reference molecule\n\ + - prbId: (optional) probe conformation to use\n\ + - refId: (optional) reference conformation to use\n\ + - map: (optional) a list of lists of (probeAtomId,refAtomId)\n\ + tuples with the atom-atom mappings of the two\n\ + molecules. If not provided, these will be generated\n\ + using a substructure search.\n\ + - maxMatches: (optional) if map isn't specified, this will be\n\ + the max number of matches found in a SubstructMatch()\n\ + \n\ + RETURNS\n\ + The best RMSD found\n\ + \n"; + python::def( + "GetBestRMS", RDKit::GetBestRMS, + (python::arg("prbMol"), python::arg("refMol"), python::arg("prbId") = -1, + python::arg("refId") = -1, python::arg("map") = python::object(), + python::arg("maxMatches") = 1000000), docString.c_str()); + docString = "Alignment conformations in a molecule to each other\n\ \n\ diff --git a/Code/GraphMol/MolAlign/Wrap/testMolAlign.py b/Code/GraphMol/MolAlign/Wrap/testMolAlign.py index 51834cb0f..1cfe816d7 100644 --- a/Code/GraphMol/MolAlign/Wrap/testMolAlign.py +++ b/Code/GraphMol/MolAlign/Wrap/testMolAlign.py @@ -466,6 +466,18 @@ class TestCase(unittest.TestCase): ) self.failUnlessEqual(len(algs), nConfs) + def test17GetBestRMS(self): + sdf = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'MolAlign', + 'test_data', 'probe_mol.sdf') + molS = Chem.SDMolSupplier(sdf, True, False) + mol1 = molS[1] + mol2 = molS[2] + + # AlignMol() would return this for the rms: 2.50561 + # But the best rms is: 2.43449 + rmsd = rdMolAlign.GetBestRMS(mol1, mol2); + + self.failUnlessAlmostEqual(rmsd, 2.43449209) if __name__ == '__main__': print("Testing MolAlign Wrappers") diff --git a/Code/GraphMol/MolAlign/testMolAlign.cpp b/Code/GraphMol/MolAlign/testMolAlign.cpp index b1aded6d9..4f8250b5f 100644 --- a/Code/GraphMol/MolAlign/testMolAlign.cpp +++ b/Code/GraphMol/MolAlign/testMolAlign.cpp @@ -66,6 +66,23 @@ void test1MolAlign() { delete m3; } +void test1GetBestRMS() { + std::string rdbase = getenv("RDBASE"); + std::string fname = + rdbase + "/Code/GraphMol/MolAlign/test_data/probe_mol.sdf"; + SDMolSupplier supplier(fname, true, false); + ROMol *m1 = supplier[1]; + ROMol *m2 = supplier[2]; + + // alignMol() would return this for the rms: 2.50561 + // But the best rms is: 2.43449 + double rmsd = MolAlign::getBestRMS(*m1, *m2); + + TEST_ASSERT(RDKit::feq(rmsd, 2.43449)); + delete m1; + delete m2; +} + void test1MolWithQueryAlign() { // identical to test1MolAlign except we replace one atom with a QueryAtom instead @@ -88,7 +105,7 @@ void test1MolWithQueryAlign() { std::string fname3 = rdbase + "/Code/GraphMol/MolAlign/test_data/1oir_trans.mol"; - + RWMol *m3 = new RWMol(*MolFileToMol(fname3)); m3->replaceAtom(0, new QueryAtom(5)); @@ -114,7 +131,7 @@ void test1MolWithQueryAlign() { // provide an atom mapping delete m1; delete m2; - delete m3; + delete m3; } @@ -884,6 +901,10 @@ int main() { std::cout << "\t test1MolAlign \n\n"; test1MolAlign(); + std::cout << "\t---------------------------------\n"; + std::cout << "\t test1GetBestRMS \n\n"; + test1GetBestRMS(); + std::cout << "\t---------------------------------\n"; std::cout << "\t test1MolWithQueryAlign \n\n"; test1MolWithQueryAlign(); diff --git a/rdkit/Chem/AllChem.py b/rdkit/Chem/AllChem.py index c648431bd..60c4f3961 100644 --- a/rdkit/Chem/AllChem.py +++ b/rdkit/Chem/AllChem.py @@ -89,52 +89,6 @@ def ComputeMolVolume(mol, confId=-1, gridSpacing=0.2, boxMargin=2.0): vol = voxelVol * len(voxels) return vol - -def GetBestRMS(ref, probe, refConfId=-1, probeConfId=-1, maps=None): - """ Returns the optimal RMS for aligning two molecules, taking - symmetry into account. As a side-effect, the probe molecule is - left in the aligned state. - - Arguments: - - ref: the reference molecule - - probe: the molecule to be aligned to the reference - - refConfId: (optional) reference conformation to use - - probeConfId: (optional) probe conformation to use - - maps: (optional) a list of lists of (probeAtomId,refAtomId) - tuples with the atom-atom mappings of the two molecules. - If not provided, these will be generated using a substructure - search. - - Note: - This function will attempt to align all permutations of matching atom - orders in both molecules, for some molecules it will lead to 'combinatorial - explosion' especially if hydrogens are present. - Use 'rdkit.Chem.AllChem.AlignMol' to align molecules without changing the - atom order. - - """ - if not maps: - matches = ref.GetSubstructMatches(probe, uniquify=False) - if not matches: - raise ValueError('mol %s does not match mol %s' % (ref.GetProp('_Name'), - probe.GetProp('_Name'))) - if len(matches) > 1e6: - warnings.warn("{} matches detected for molecule {}, this may lead to a performance slowdown.". - format(len(matches), probe.GetProp('_Name'))) - maps = [list(enumerate(match)) for match in matches] - bestRMS = 1000. - for amap in maps: - rms = AlignMol(probe, ref, probeConfId, refConfId, atomMap=amap) - if rms < bestRMS: - bestRMS = rms - bestMap = amap - - # finally repeate the best alignment : - if bestMap != amap: - AlignMol(probe, ref, probeConfId, refConfId, atomMap=bestMap) - return bestRMS - - def GetConformerRMS(mol, confId1, confId2, atomIds=None, prealigned=False): """ Returns the RMS between two conformations. By default, the conformers will be aligned to the first conformer From 2fbf74c06e0fda9702fde965902ce237eb5ad2b2 Mon Sep 17 00:00:00 2001 From: Brian Kelley Date: Fri, 15 Sep 2017 22:44:50 -0400 Subject: [PATCH 20/44] Fixes double free for Dict::update (#1571) * Fixes double free for Dict::udpate * fix a leak * Dict.update now behaves like python's update (i.e. replaces existing values) --- Code/RDGeneral/Dict.h | 89 +++++----- Code/RDGeneral/RDValue-taggedunion.h | 2 + Code/RDGeneral/testDict.cpp | 235 +++++++++++++-------------- 3 files changed, 164 insertions(+), 162 deletions(-) diff --git a/Code/RDGeneral/Dict.h b/Code/RDGeneral/Dict.h index f09b44b82..fa45b08a8 100644 --- a/Code/RDGeneral/Dict.h +++ b/Code/RDGeneral/Dict.h @@ -33,26 +33,26 @@ typedef std::vector STR_VECT; //! The actual storage is done using \c RDValue objects. //! class Dict { -public: + public: struct Pair { std::string key; RDValue val; - Pair() : key(), val() {} - Pair(const std::string &s, const RDValue &v) : key(s), val(v) { - } + Pair() : key(), val() {} + Pair(const std::string &s) : key(s), val() {} + Pair(const std::string &s, const RDValue &v) : key(s), val(v) {} }; typedef std::vector DataType; - Dict() : _data(), _hasNonPodData(false) { }; + Dict() : _data(), _hasNonPodData(false){}; Dict(const Dict &other) : _data(other._data) { _hasNonPodData = other._hasNonPodData; if (_hasNonPodData) { std::vector data(other._data.size()); _data.swap(data); - for (size_t i=0; i< _data.size(); ++i) { + for (size_t i = 0; i < _data.size(); ++i) { _data[i].key = other._data[i].key; copy_rdvalue(_data[i].val, other._data[i].val); } @@ -60,30 +60,42 @@ public: } ~Dict() { - reset(); // to clear pointers if necessary + reset(); // to clear pointers if necessary } - void update(const Dict &other, bool preserveExisting=false) { - if(!preserveExisting) { + void update(const Dict &other, bool preserveExisting = false) { + if (!preserveExisting) { *this = other; - } - else { - for (size_t i=0; i< other._data.size(); ++i) { - const Pair & pair = other._data[i]; - if(!hasVal(pair.key)) { - _data.push_back(pair); + } else { + if (other._hasNonPodData) _hasNonPodData = true; + for (size_t i = 0; i < other._data.size(); ++i) { + const Pair &pair = other._data[i]; + Pair *target = 0; + for (size_t i = 0; i < _data.size(); ++i) { + if (_data[i].key == pair.key) { + target = &_data[i]; + break; + } + } + + if (!target) { + // need to create blank entry and copy + _data.push_back(Pair(pair.key)); copy_rdvalue(_data.back().val, pair.val); + } else { + // just copy + copy_rdvalue(target->val, pair.val); } } } } - + Dict &operator=(const Dict &other) { _hasNonPodData = other._hasNonPodData; if (_hasNonPodData) { std::vector data(other._data.size()); _data.swap(data); - for (size_t i=0; i< _data.size(); ++i) { + for (size_t i = 0; i < _data.size(); ++i) { _data[i].key = other._data[i].key; copy_rdvalue(_data[i].val, other._data[i].val); } @@ -96,15 +108,15 @@ public: //---------------------------------------------------------- //! \brief Access to the underlying data. const DataType &getData() const { return _data; } - DataType &getData() { return _data; } - + DataType &getData() { return _data; } + //---------------------------------------------------------- //! \brief Returns whether or not the dictionary contains a particular //! key. bool hasVal(const std::string &what) const { - for(size_t i=0 ; i< _data.size(); ++i) { - if (_data[i].key == what ) return true; + for (size_t i = 0; i < _data.size(); ++i) { + if (_data[i].key == what) return true; } return false; }; @@ -143,7 +155,7 @@ public: //! \overload template T getVal(const std::string &what) const { - for(size_t i=0; i< _data.size(); ++i) { + for (size_t i = 0; i < _data.size(); ++i) { if (_data[i].key == what) { return from_rdvalue(_data[i].val); } @@ -171,7 +183,7 @@ public: template bool getValIfPresent(const std::string &what, T &res) const { - for(size_t i=0; i< _data.size(); ++i) { + for (size_t i = 0; i < _data.size(); ++i) { if (_data[i].key == what) { res = from_rdvalue(_data[i].val); return true; @@ -180,7 +192,6 @@ public: return false; }; - //! \overload bool getValIfPresent(const std::string &what, std::string &res) const; @@ -200,7 +211,7 @@ public: template void setVal(const std::string &what, T &val) { _hasNonPodData = true; - for(size_t i=0; i< _data.size(); ++i) { + for (size_t i = 0; i < _data.size(); ++i) { if (_data[i].key == what) { RDValue::cleanup_rdvalue(_data[i].val); _data[i].val = val; @@ -213,7 +224,7 @@ public: template void setPODVal(const std::string &what, T val) { // don't change the hasNonPodData status - for(size_t i=0; i< _data.size(); ++i) { + for (size_t i = 0; i < _data.size(); ++i) { if (_data[i].key == what) { RDValue::cleanup_rdvalue(_data[i].val); _data[i].val = val; @@ -223,21 +234,13 @@ public: _data.push_back(Pair(what, val)); }; - void setVal(const std::string &what, bool val) { - setPODVal(what, val); - } + void setVal(const std::string &what, bool val) { setPODVal(what, val); } - void setVal(const std::string &what, double val) { - setPODVal(what, val); - } + void setVal(const std::string &what, double val) { setPODVal(what, val); } - void setVal(const std::string &what, float val) { - setPODVal(what, val); - } + void setVal(const std::string &what, float val) { setPODVal(what, val); } - void setVal(const std::string &what, int val) { - setPODVal(what, val); - } + void setVal(const std::string &what, int val) { setPODVal(what, val); } void setVal(const std::string &what, unsigned int val) { setPODVal(what, val); @@ -261,7 +264,7 @@ public: a KeyErrorException will be thrown. */ void clearVal(const std::string &what) { - for(DataType::iterator it = _data.begin(); it < _data.end() ; ++it) { + for (DataType::iterator it = _data.begin(); it < _data.end(); ++it) { if (it->key == what) { if (_hasNonPodData) { RDValue::cleanup_rdvalue(it->val); @@ -278,7 +281,7 @@ public: //! void reset() { if (_hasNonPodData) { - for (size_t i=0; i< _data.size(); ++i) { + for (size_t i = 0; i < _data.size(); ++i) { RDValue::cleanup_rdvalue(_data[i].val); } } @@ -313,9 +316,9 @@ public: }; */ private: - DataType _data; //!< the actual dictionary - bool _hasNonPodData; // if true, need a deep copy - // (copy_rdvalue) + DataType _data; //!< the actual dictionary + bool _hasNonPodData; // if true, need a deep copy + // (copy_rdvalue) }; } #endif diff --git a/Code/RDGeneral/RDValue-taggedunion.h b/Code/RDGeneral/RDValue-taggedunion.h index 52889e822..2752283e3 100644 --- a/Code/RDGeneral/RDValue-taggedunion.h +++ b/Code/RDGeneral/RDValue-taggedunion.h @@ -303,6 +303,8 @@ struct RDValue { // copy act's like a move for better value semantics. // Containers may need to copy though. inline void copy_rdvalue(RDValue &dest, const RDValue &src) { + if (&dest == &src) // don't copy over yourself + return; dest.destroy(); dest.type = src.type; switch (src.type) { diff --git a/Code/RDGeneral/testDict.cpp b/Code/RDGeneral/testDict.cpp index 6d39e7f41..d29e0f7fb 100644 --- a/Code/RDGeneral/testDict.cpp +++ b/Code/RDGeneral/testDict.cpp @@ -56,19 +56,16 @@ void testGithub940() { void testRDAny() { std::cerr << "Testing RDValue" << std::endl; - { - RDAny v(-2147450880); - } - + { RDAny v(-2147450880); } + { int vi = 0; RDValue v(0); - for (int i=0; i<100; ++i) { - vi += i; - v = rdvalue_cast(v) + i; - TEST_ASSERT(vi == rdvalue_cast(v)); - } - + for (int i = 0; i < 100; ++i) { + vi += i; + v = rdvalue_cast(v) + i; + TEST_ASSERT(vi == rdvalue_cast(v)); + } } std::cerr << "Testing RDAny" << std::endl; { @@ -77,8 +74,7 @@ void testRDAny() { TEST_ASSERT(rdany_cast(a) == 1); TEST_ASSERT(rdany_cast(b) == 1); } - - + { RDAny a(1); RDAny b = a; @@ -96,18 +92,18 @@ void testRDAny() { bool a = true; RDValue v(a); TEST_ASSERT(rdvalue_cast(v) == true); - v = (int) 10; + v = (int)10; TEST_ASSERT(rdvalue_cast(v) == 10); } - + { Dict d; - bool a=true; + bool a = true; d.setVal("foo", a); d.getVal("foo"); } - { // tests computed props + { // tests computed props STR_VECT computed; Dict d; d.setVal(RDKit::detail::computedPropName, computed); @@ -119,13 +115,13 @@ void testRDAny() { computed2 = d2.getVal(RDKit::detail::computedPropName); TEST_ASSERT(computed2[0] == "foo"); } - + { Dict d; - //int v=1; - //d.setVal("foo", v); - //TEST_ASSERT(d.getVal("foo") == 1, "bad getval"); - + // int v=1; + // d.setVal("foo", v); + // TEST_ASSERT(d.getVal("foo") == 1, "bad getval"); + std::vector fooV; fooV.resize(3); fooV[0] = 1; @@ -139,7 +135,7 @@ void testRDAny() { fooV2 = rdany_cast >(a); TEST_ASSERT(fooV == fooV2); } - + { std::vector fooV2; std::cerr << "dict set int vect" << std::endl; @@ -149,38 +145,35 @@ void testRDAny() { TEST_ASSERT(fooV == fooV2); } } - + { std::vector v; - for(int i=0;i<4;++i) - v.push_back(i); + for (int i = 0; i < 4; ++i) v.push_back(i); RDAny foo(v); RDAny bar = foo; RDAny baz(foo); - - for(int i=0;i<4;++i) { + + for (int i = 0; i < 4; ++i) { TEST_ASSERT(rdany_cast >(foo)[i] == i); TEST_ASSERT(rdany_cast >(bar)[i] == i); TEST_ASSERT(rdany_cast >(baz)[i] == i); } - } - + { std::vector v; - for(double i=0;i<4;++i) - v.push_back(i); + for (double i = 0; i < 4; ++i) v.push_back(i); RDAny foo(v); - for(int i=0;i<4;++i) { + for (int i = 0; i < 4; ++i) { TEST_ASSERT(rdany_cast >(foo)[i] == i); } - + RDAny b = foo; - for(int i=0;i<4;++i) { + for (int i = 0; i < 4; ++i) { TEST_ASSERT(rdany_cast >(b)[i] == i); } } @@ -188,112 +181,120 @@ void testRDAny() { { std::clock_t clock1 = std::clock(); boost::any v; - for(int i=0;i(*v) + i: i); + boost::any *v = 0, *vv; + for (int i = 0; i < loops; ++i) { + vv = new boost::any(v ? boost::any_cast(*v) + i : i); delete v; v = vv; } delete vv; std::clock_t clock2 = std::clock(); - std::cout << "dynamic boost any:" << (double)(clock2-clock1)/CLOCKS_PER_SEC << " s" << std::endl; + std::cout << "dynamic boost any:" + << (double)(clock2 - clock1) / CLOCKS_PER_SEC << " s" + << std::endl; } { std::clock_t clock1 = std::clock(); RDAny v; - for(int i=0;i(*v) + i : i); + RDAny *v = 0, *vv; + for (int i = 0; i < loops; ++i) { + vv = new RDAny(v ? rdany_cast(*v) + i : i); delete v; v = vv; } delete vv; std::clock_t clock2 = std::clock(); - std::cout << "dynamic RDAny:" << (double)(clock2-clock1)/CLOCKS_PER_SEC << " s" << std::endl; + std::cout << "dynamic RDAny:" << (double)(clock2 - clock1) / CLOCKS_PER_SEC + << " s" << std::endl; } { std::clock_t clock1 = std::clock(); RDValue v; - for(int i=0;i(v) + i); } std::clock_t clock2 = std::clock(); - std::cout << "dynamic RDValue:" << (double)(clock2-clock1)/CLOCKS_PER_SEC << " s" << std::endl; + std::cout << "dynamic RDValue:" + << (double)(clock2 - clock1) / CLOCKS_PER_SEC << " s" + << std::endl; } - - { // checks replacement with vector + + { // checks replacement with vector RDAny vv(2.0); TEST_ASSERT(rdany_cast(vv) == 2.0); - - + std::vector vect; vect.push_back(1); vv = vect; TEST_ASSERT(rdany_cast >(vv)[0] == 1); - + // tests copy RDAny vvv(vv); - - TEST_ASSERT(rdany_cast >(vvv)[0] == 1); + + TEST_ASSERT(rdany_cast >(vvv)[0] == 1); } { // Checks fallback to Any - std::vector > pvect; - pvect.push_back(std::make_pair(2,2)); + std::vector > pvect; + pvect.push_back(std::make_pair(2, 2)); boost::any any1(pvect); - boost::any_cast > >(any1); - boost::any_cast > &>(any1); - boost::any_cast > &>(any1); - + boost::any_cast > >(any1); + boost::any_cast > &>(any1); + boost::any_cast > &>(any1); + RDAny vv(pvect); - boost::any &any = rdany_cast(vv); - boost::any_cast > >(any); - boost::any_cast > &>(any); - boost::any_cast > &>(any); - - const std::vector > &pv = rdany_cast > >(vv); + boost::any &any = rdany_cast(vv); + boost::any_cast > >(any); + boost::any_cast > &>(any); + boost::any_cast > &>(any); + + const std::vector > &pv = + rdany_cast > >(vv); TEST_ASSERT(pv[0].first == 2); RDAny vvv(vv); - TEST_ASSERT((rdany_cast > >(vvv)[0].first == - 2)); - + TEST_ASSERT( + (rdany_cast > >(vvv)[0].first == 2)); } { @@ -309,16 +310,16 @@ void testRDAny() { #endif } catch (boost::bad_any_cast &e) { } - + TEST_ASSERT((*rdany_cast *>(vv))[0] == 100); - TEST_ASSERT((*rdany_cast *>((const RDAny&)vv))[0] == 100); + TEST_ASSERT((*rdany_cast *>((const RDAny &)vv))[0] == 100); delete p; - std::map *m = new std::map(); + std::map *m = new std::map(); (*m)[0] = 1; RDAny mv(m); // leaks - std::map *anym = rdany_cast *>(mv); + std::map *anym = rdany_cast *>(mv); TEST_ASSERT(anym->find(0) != anym->end()); delete anym; } @@ -330,24 +331,23 @@ void testRDAny() { p->push_back(100); RDAny v(p); RDAny vv(v); - TEST_ASSERT((*rdany_cast(v))[0] == 100); + TEST_ASSERT((*rdany_cast(v))[0] == 100); TEST_ASSERT((*rdany_cast(vv))[0] == 100); - TEST_ASSERT((*rdany_cast((const RDAny&)vv))[0] == 100); + TEST_ASSERT((*rdany_cast((const RDAny &)vv))[0] == 100); - typedef boost::shared_ptr > mptr; - mptr m(new std::map()); + typedef boost::shared_ptr > mptr; + mptr m(new std::map()); (*m)[0] = 1; RDAny mv(m); // leaks mptr anym = rdany_cast(mv); TEST_ASSERT(anym->find(0) != anym->end()); - RDAny any3(boost::shared_ptr( new Foo )); + RDAny any3(boost::shared_ptr(new Foo)); TEST_ASSERT(any3.m_value.getTag() == RDTypeTag::AnyTag); } } - class DictCon { public: DictCon() { d.reset(); }; @@ -439,7 +439,7 @@ void testVectToString() { std::cerr << sv << std::endl; TEST_ASSERT(sv == "[10001,0,]"); } - + BOOST_LOG(rdErrorLog) << "\tdone" << std::endl; } @@ -472,19 +472,19 @@ void testConstReturns() { d.setVal("foo",v); double ls=0; - BOOST_LOG(rdErrorLog) << "copy" << std::endl; + BOOST_LOG(rdErrorLog) << "copy" << std::endl; for(int i=0;i<100000000;++i){ std::string nv=d.getVal("foo"); ls+= nv.size(); } BOOST_LOG(rdErrorLog) << "done: "<("foo"); ls+= nv.size(); } - BOOST_LOG(rdErrorLog) << "done: "<("foo"); } #else @@ -584,34 +584,16 @@ void testUpdate() { f.push_back(1); f.push_back(2); d.setVal("foo3", f); - + Dict d2; d2.update(d); TEST_ASSERT(d.getVal("foo") == d2.getVal("foo")); TEST_ASSERT(d.getVal("foo2") == d2.getVal("foo2")); - TEST_ASSERT(d.getVal >("foo3") == d2.getVal >("foo3")); - } - - { - Dict d; - std::string sv; - sv = "1.3"; - d.setVal("foo", sv); - double dv = 3.0; - d.setVal("foo2", dv); - std::vector f; - f.push_back(1); - f.push_back(2); - d.setVal("foo3", f); - - Dict d2; - d2.update(d, false); - TEST_ASSERT(d.getVal("foo") == d2.getVal("foo")); - TEST_ASSERT(d.getVal("foo2") == d2.getVal("foo2")); - TEST_ASSERT(d.getVal >("foo3") == d2.getVal >("foo3")); + TEST_ASSERT(d.getVal >("foo3") == + d2.getVal >("foo3")); } - { + { // a few tests to make sure copying/updating with nonPOD data is ok Dict d; std::string sv; sv = "1.3"; @@ -622,26 +604,41 @@ void testUpdate() { f.push_back(1); f.push_back(2); d.setVal("foo3", f); - - Dict d2; - d2.setVal("foo", 1); - d2.update(d, true); - TEST_ASSERT(1 == d2.getVal("foo")); - TEST_ASSERT(d.getVal("foo2") == d2.getVal("foo2")); - TEST_ASSERT(d.getVal >("foo3") == d2.getVal >("foo3")); + { + Dict d2; + d2.setVal("foo", 1); + d2.update(d, true); + TEST_ASSERT(d2.getVal("foo") == "1.3"); + TEST_ASSERT(d.getVal("foo2") == d2.getVal("foo2")); + TEST_ASSERT(d.getVal >("foo3") == + d2.getVal >("foo3")); + } + + { + Dict d2 = d; + d2.setVal("foo", 1); + TEST_ASSERT(1 == d2.getVal("foo")); + TEST_ASSERT(d.getVal("foo2") == d2.getVal("foo2")); + TEST_ASSERT(d.getVal >("foo3") == + d2.getVal >("foo3")); + } + + { + Dict d2(d); + TEST_ASSERT(d.getVal("foo2") == d2.getVal("foo2")); + TEST_ASSERT(d.getVal >("foo3") == + d2.getVal >("foo3")); + } } - BOOST_LOG(rdErrorLog) << "\tdone" << std::endl; - } int main() { RDLog::InitLogs(); testGithub940(); - testRDAny(); - testRDAny(); #if 1 + testRDAny(); Dict d; INT_VECT fooV; fooV.resize(3); From c21605dbea8f91ea82e38fda5de1c322b21efb2b Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Sun, 17 Sep 2017 15:12:53 +0200 Subject: [PATCH 21/44] SMILES lexer optimization/enhancement (#1575) * needs testing * add some tests, update periodic table * update isotope data from NIST --- .../SmilesParse/lex.yysmiles.cpp.cmake | 1242 ++++++++++++----- Code/GraphMol/SmilesParse/smiles.ll | 286 ++-- Code/GraphMol/SmilesParse/test.cpp | 109 +- Code/GraphMol/atomic_data.cpp | 125 +- 4 files changed, 1132 insertions(+), 630 deletions(-) diff --git a/Code/GraphMol/SmilesParse/lex.yysmiles.cpp.cmake b/Code/GraphMol/SmilesParse/lex.yysmiles.cpp.cmake index 648ae124f..17f41076f 100644 --- a/Code/GraphMol/SmilesParse/lex.yysmiles.cpp.cmake +++ b/Code/GraphMol/SmilesParse/lex.yysmiles.cpp.cmake @@ -362,8 +362,8 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); *yy_cp = '\0'; \ yyg->yy_c_buf_p = yy_cp; -#define YY_NUM_RULES 153 -#define YY_END_OF_BUFFER 154 +#define YY_NUM_RULES 181 +#define YY_END_OF_BUFFER 182 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -371,28 +371,35 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[190] = +static yyconst flex_int16_t yy_accept[246] = { 0, - 0, 0, 0, 0, 154, 152, 151, 135, 148, 143, - 144, 133, 142, 141, 147, 140, 149, 150, 152, 6, - 112, 113, 118, 122, 121, 114, 115, 116, 117, 145, - 139, 123, 124, 125, 126, 127, 128, 138, 134, 152, - 112, 113, 152, 152, 118, 152, 122, 121, 16, 152, - 152, 114, 115, 116, 152, 117, 152, 87, 20, 69, - 152, 35, 152, 146, 152, 128, 152, 136, 137, 0, - 0, 0, 0, 0, 0, 120, 119, 139, 84, 43, - 13, 90, 15, 30, 80, 74, 51, 9, 102, 78, - 92, 17, 44, 53, 93, 91, 107, 23, 21, 50, + 0, 0, 0, 0, 182, 180, 179, 162, 176, 171, + 172, 144, 170, 169, 175, 168, 177, 178, 163, 180, + 161, 6, 123, 124, 129, 133, 132, 125, 126, 127, + 128, 173, 167, 134, 135, 136, 137, 138, 139, 166, + 180, 145, 180, 123, 124, 180, 180, 129, 180, 133, + 132, 16, 180, 180, 125, 126, 127, 180, 128, 180, + 87, 20, 69, 180, 35, 180, 174, 180, 139, 180, + 164, 165, 0, 0, 0, 0, 0, 0, 131, 130, + 167, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 84, 43, 13, 90, 15, 30, 80, - 26, 100, 105, 61, 63, 94, 58, 24, 109, 95, - 82, 28, 59, 29, 7, 67, 75, 62, 103, 45, - 72, 32, 52, 8, 98, 66, 111, 96, 12, 22, - 38, 104, 11, 37, 55, 10, 25, 97, 88, 71, - 86, 77, 42, 56, 79, 54, 73, 89, 83, 33, - 70, 99, 106, 41, 81, 40, 47, 18, 31, 101, - 14, 57, 46, 34, 68, 60, 39, 48, 85, 19, - 76, 64, 0, 49, 65, 27, 36, 130, 131, 129, - 132, 2, 4, 5, 3, 1, 110, 108, 0 + 74, 51, 9, 102, 78, 92, 17, 44, 53, 93, + 91, 107, 24, 21, 50, 26, 100, 105, 61, 63, + 94, 58, 23, 109, 95, 82, 28, 59, 29, 7, + 67, 75, 62, 103, 45, 72, 32, 52, 8, 98, + 66, 111, 110, 96, 12, 22, 38, 104, 11, 37, + 55, 10, 108, 25, 97, 88, 113, 71, 86, 77, + 42, 56, 79, 54, 73, 89, 83, 33, 70, 99, + 106, 41, 81, 40, 47, 18, 31, 101, 14, 57, + 46, 34, 68, 60, 39, 48, 85, 19, 76, 64, + 112, 0, 49, 65, 27, 36, 141, 142, 140, 143, + + 2, 4, 5, 3, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 116, 120, 114, 122, 119, 118, 121, 117, 115, 149, + 154, 147, 152, 156, 150, 158, 157, 151, 155, 160, + 146, 153, 148, 159, 0 } ; static yyconst YY_CHAR yy_ec[256] = @@ -400,17 +407,17 @@ static yyconst YY_CHAR yy_ec[256] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 3, 1, 1, 4, 1, 5, 1, 3, 6, - 7, 8, 9, 1, 10, 11, 12, 13, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 15, 1, 16, - 4, 17, 1, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 1, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 1, 1, 1, 47, 48, 49, 50, + 1, 3, 1, 1, 4, 1, 5, 1, 6, 7, + 8, 9, 10, 1, 11, 12, 13, 14, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 16, 1, 17, + 18, 19, 1, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 1, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 1, 1, 1, 49, 50, 51, 52, - 51, 52, 53, 54, 55, 1, 56, 57, 58, 59, - 60, 61, 1, 62, 63, 64, 65, 66, 1, 1, - 67, 1, 1, 1, 1, 68, 1, 1, 1, 1, + 53, 54, 55, 56, 57, 1, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 1, 1, + 70, 1, 1, 1, 1, 71, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -427,7 +434,7 @@ static yyconst YY_CHAR yy_ec[256] = 1, 1, 1, 1, 1 } ; -static yyconst YY_CHAR yy_meta[69] = +static yyconst YY_CHAR yy_meta[72] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -435,98 +442,119 @@ static yyconst YY_CHAR yy_meta[69] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1 } ; -static yyconst flex_uint16_t yy_base[190] = +static yyconst flex_uint16_t yy_base[246] = { 0, - 0, 0, 54, 0, 184, 256, 256, 256, 256, 256, - 256, 256, 256, 162, 256, 256, 256, 256, 166, 95, - 113, 108, 256, 256, 256, 256, 256, 256, 256, 256, - 111, 256, 256, 256, 256, 256, 256, 256, 256, 71, - 57, 90, 40, 60, 48, 107, 108, 84, 89, 115, - 114, 135, 82, 141, 160, 169, 185, 79, 256, 256, - 88, 90, 104, 256, 58, 75, 65, 256, 256, 218, - 80, 69, 46, 37, 44, 256, 256, 256, 256, 256, - 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, - 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 0, 0, 66, 0, 242, 312, 312, 312, 312, 312, + 312, 312, 312, 222, 312, 312, 312, 312, 312, 228, + 312, 113, 172, 177, 312, 312, 312, 312, 312, 312, + 312, 312, 188, 312, 312, 312, 312, 312, 312, 312, + 131, 312, 62, 118, 135, 70, 8, 78, 26, 124, + 16, 169, 142, 153, 169, 57, 178, 198, 207, 220, + 165, 312, 312, 176, 174, 19, 312, 157, 88, 164, + 312, 312, 272, 185, 178, 184, 173, 178, 312, 312, + 312, 146, 137, 36, 134, 126, 116, 75, 126, 126, + 70, 125, 107, 312, 312, 312, 312, 312, 312, 312, - 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, - 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, - 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, - 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, - 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, - 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, - 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, - 256, 256, 108, 256, 256, 256, 256, 256, 256, 256, - 256, 256, 256, 256, 256, 256, 256, 256, 256 + 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, + 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, + 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, + 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, + 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, + 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, + 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, + 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, + 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, + 312, 234, 312, 312, 312, 312, 312, 312, 312, 312, + + 312, 312, 312, 312, 312, 166, 160, 155, 154, 152, + 150, 144, 143, 142, 140, 138, 133, 112, 79, 77, + 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, + 312, 312, 312, 312, 312, 312, 312, 312, 312, 312, + 312, 312, 312, 312, 312 } ; -static yyconst flex_int16_t yy_def[190] = +static yyconst flex_int16_t yy_def[246] = { 0, - 189, 1, 1, 3, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, + 245, 1, 1, 3, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 0 + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 0 } ; -static yyconst flex_uint16_t yy_nxt[325] = +static yyconst flex_uint16_t yy_nxt[384] = { 0, - 6, 7, 6, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 8, 19, 6, 20, 6, 21, - 22, 6, 6, 23, 6, 24, 25, 6, 6, 6, - 26, 27, 28, 6, 6, 29, 6, 6, 6, 6, - 6, 6, 6, 30, 31, 6, 6, 32, 33, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 34, 35, - 36, 6, 37, 6, 6, 6, 6, 38, 39, 186, - 185, 184, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 102, 55, 56, - 57, 58, 59, 60, 61, 62, 63, 70, 108, 64, + 6, 7, 6, 8, 9, 6, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 6, 22, + 6, 23, 24, 6, 6, 25, 6, 26, 27, 6, + 6, 6, 28, 29, 30, 6, 6, 31, 6, 6, + 6, 6, 6, 6, 6, 32, 33, 6, 6, 34, + 35, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 36, 37, 38, 6, 6, 39, 6, 6, 6, 6, + 40, 41, 120, 121, 127, 122, 135, 128, 129, 195, + 136, 42, 244, 196, 243, 208, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 65, 183, 103, 87, 109, 110, 104, 88, 182, 111, - 89, 90, 91, 71, 72, 181, 66, 67, 76, 79, - 178, 105, 106, 80, 107, 179, 73, 81, 82, 180, - 74, 75, 83, 84, 85, 86, 92, 175, 174, 93, - 94, 95, 120, 173, 140, 121, 77, 96, 97, 98, - 122, 99, 100, 112, 101, 78, 113, 114, 115, 116, - 117, 123, 176, 128, 77, 177, 129, 118, 187, 124, - 119, 188, 130, 131, 76, 69, 125, 132, 68, 126, - 127, 133, 134, 189, 135, 136, 189, 141, 142, 137, - 143, 189, 189, 189, 138, 139, 189, 189, 144, 189, + 57, 209, 58, 59, 60, 61, 62, 63, 64, 65, + 66, 157, 94, 67, 68, 73, 95, 242, 73, 117, + 96, 97, 158, 217, 218, 213, 98, 99, 100, 101, + 123, 69, 70, 74, 75, 118, 124, 125, 241, 119, + 198, 214, 126, 240, 199, 239, 76, 238, 237, 236, + 77, 78, 82, 83, 84, 235, 85, 234, 86, 233, + 232, 87, 88, 89, 90, 231, 102, 91, 92, 93, + 103, 230, 220, 104, 105, 106, 130, 131, 132, 219, + 216, 215, 79, 107, 212, 133, 108, 109, 110, 134, + 138, 211, 210, 80, 111, 112, 113, 207, 139, 114, - 145, 189, 146, 189, 147, 148, 149, 150, 189, 189, - 151, 152, 153, 154, 189, 189, 157, 158, 155, 159, - 70, 160, 189, 161, 156, 189, 162, 163, 189, 189, - 164, 165, 166, 167, 189, 168, 71, 72, 169, 170, - 189, 171, 172, 189, 189, 189, 189, 189, 189, 73, - 189, 189, 189, 74, 75, 5, 189, 189, 189, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, + 115, 206, 116, 143, 144, 205, 140, 145, 204, 141, + 142, 203, 202, 146, 147, 201, 200, 149, 150, 148, + 151, 152, 197, 194, 153, 154, 159, 160, 193, 161, + 155, 156, 192, 137, 81, 80, 79, 162, 72, 163, + 71, 245, 164, 245, 165, 166, 167, 168, 245, 245, + 169, 170, 171, 172, 245, 245, 175, 176, 173, 177, + 245, 178, 245, 179, 245, 174, 180, 181, 183, 184, + 185, 182, 186, 245, 73, 187, 188, 73, 189, 190, + 245, 245, 245, 221, 245, 191, 245, 245, 245, 222, + 245, 245, 74, 75, 223, 224, 225, 226, 245, 227, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 189 + 228, 229, 245, 245, 245, 76, 245, 245, 245, 77, + 78, 5, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245 } ; -static yyconst flex_int16_t yy_chk[325] = +static yyconst flex_int16_t yy_chk[384] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -534,36 +562,42 @@ static yyconst flex_int16_t yy_chk[325] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 3, 75, - 74, 73, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 43, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 20, 45, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 3, 47, 47, 49, 47, 51, 49, 49, 66, + 51, 3, 220, 66, 219, 84, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 72, 43, 41, 45, 45, 43, 41, 71, 45, - 41, 41, 41, 20, 20, 67, 3, 3, 41, 40, - 65, 44, 44, 40, 44, 66, 20, 40, 40, 66, - 20, 20, 40, 40, 40, 40, 42, 62, 61, 42, - 42, 42, 48, 58, 53, 48, 42, 42, 42, 42, - 49, 42, 42, 46, 42, 31, 46, 46, 47, 47, - 47, 50, 63, 51, 22, 63, 51, 47, 173, 50, - 47, 173, 51, 51, 21, 19, 50, 51, 14, 50, - 50, 52, 52, 5, 52, 52, 0, 54, 54, 52, - 54, 0, 0, 0, 52, 52, 0, 0, 54, 0, + 3, 84, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 56, 43, 3, 3, 22, 43, 218, 22, 46, + 43, 43, 56, 91, 91, 88, 43, 43, 43, 43, + 48, 3, 3, 22, 22, 46, 48, 48, 217, 46, + 69, 88, 48, 216, 69, 215, 22, 214, 213, 212, + 22, 22, 41, 41, 41, 211, 41, 210, 41, 209, + 208, 41, 41, 41, 41, 207, 44, 41, 41, 41, + 44, 206, 93, 44, 44, 44, 50, 50, 50, 92, + 90, 89, 44, 45, 87, 50, 45, 45, 45, 50, + 53, 86, 85, 45, 45, 45, 45, 83, 53, 45, - 54, 0, 54, 0, 54, 54, 55, 55, 0, 0, - 55, 55, 55, 55, 0, 0, 56, 56, 55, 56, - 70, 56, 0, 56, 55, 0, 56, 56, 0, 0, - 56, 57, 57, 57, 0, 57, 70, 70, 57, 57, - 0, 57, 57, 0, 0, 0, 0, 0, 0, 70, - 0, 0, 0, 70, 70, 189, 189, 189, 189, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, + 45, 82, 45, 54, 54, 78, 53, 54, 77, 53, + 53, 76, 75, 54, 54, 74, 70, 55, 55, 54, + 55, 55, 68, 65, 55, 55, 57, 57, 64, 57, + 55, 55, 61, 52, 33, 24, 23, 57, 20, 57, + 14, 5, 57, 0, 57, 57, 58, 58, 0, 0, + 58, 58, 58, 58, 0, 0, 59, 59, 58, 59, + 0, 59, 0, 59, 0, 58, 59, 59, 60, 60, + 60, 59, 60, 0, 73, 60, 60, 73, 60, 60, + 0, 0, 0, 192, 0, 60, 0, 0, 0, 192, + 0, 0, 73, 73, 192, 192, 192, 192, 0, 192, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, - 189, 189, 189, 189 + 192, 192, 0, 0, 0, 73, 0, 0, 0, 73, + 73, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245 } ; /* The intent behind this definition is that it'll catch @@ -653,7 +687,7 @@ size_t setup_smiles_string(const std::string &text,yyscan_t yyscanner){ } -#line 657 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/lex.yysmiles.cpp" +#line 691 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/lex.yysmiles.cpp" #define INITIAL 0 #define IN_ATOM_STATE 1 @@ -932,7 +966,7 @@ YY_DECL #line 86 "smiles.ll" -#line 936 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/lex.yysmiles.cpp" +#line 970 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/lex.yysmiles.cpp" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { @@ -959,13 +993,13 @@ yy_match: while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 190 ) + if ( yy_current_state >= 246 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } - while ( yy_base[yy_current_state] != 256 ); + while ( yy_base[yy_current_state] != 312 ); yy_find_action: yy_act = yy_accept[yy_current_state]; @@ -1008,360 +1042,725 @@ YY_RULE_SETUP { return AT_TOKEN; } YY_BREAK case 7: -#line 98 "smiles.ll" +YY_RULE_SETUP +#line 97 "smiles.ll" +{ yylval->atom = new Atom(2); return ATOM_TOKEN; } + YY_BREAK case 8: -#line 99 "smiles.ll" +YY_RULE_SETUP +#line 98 "smiles.ll" +{ yylval->atom = new Atom(3); return ATOM_TOKEN; } + YY_BREAK case 9: -#line 100 "smiles.ll" +YY_RULE_SETUP +#line 99 "smiles.ll" +{ yylval->atom = new Atom(4); return ATOM_TOKEN; } + YY_BREAK case 10: -#line 101 "smiles.ll" +YY_RULE_SETUP +#line 100 "smiles.ll" +{ yylval->atom = new Atom(10); return ATOM_TOKEN; } + YY_BREAK case 11: -#line 102 "smiles.ll" +YY_RULE_SETUP +#line 101 "smiles.ll" +{ yylval->atom = new Atom(11); return ATOM_TOKEN; } + YY_BREAK case 12: -#line 103 "smiles.ll" +YY_RULE_SETUP +#line 102 "smiles.ll" +{ yylval->atom = new Atom(12); return ATOM_TOKEN; } + YY_BREAK case 13: -#line 104 "smiles.ll" +YY_RULE_SETUP +#line 103 "smiles.ll" +{ yylval->atom = new Atom(13); return ATOM_TOKEN; } + YY_BREAK case 14: -#line 105 "smiles.ll" +YY_RULE_SETUP +#line 104 "smiles.ll" +{ yylval->atom = new Atom(14); return ATOM_TOKEN; } + YY_BREAK case 15: -#line 106 "smiles.ll" +YY_RULE_SETUP +#line 105 "smiles.ll" +{ yylval->atom = new Atom(18); return ATOM_TOKEN; } + YY_BREAK case 16: -#line 107 "smiles.ll" +YY_RULE_SETUP +#line 106 "smiles.ll" +{ yylval->atom = new Atom(19); return ATOM_TOKEN; } + YY_BREAK case 17: -#line 108 "smiles.ll" +YY_RULE_SETUP +#line 107 "smiles.ll" +{ yylval->atom = new Atom(20); return ATOM_TOKEN; } + YY_BREAK case 18: -#line 109 "smiles.ll" +YY_RULE_SETUP +#line 108 "smiles.ll" +{ yylval->atom = new Atom(21); return ATOM_TOKEN; } + YY_BREAK case 19: -#line 110 "smiles.ll" +YY_RULE_SETUP +#line 109 "smiles.ll" +{ yylval->atom = new Atom(22); return ATOM_TOKEN; } + YY_BREAK case 20: -#line 111 "smiles.ll" +YY_RULE_SETUP +#line 110 "smiles.ll" +{ yylval->atom = new Atom(23); return ATOM_TOKEN; } + YY_BREAK case 21: -#line 112 "smiles.ll" +YY_RULE_SETUP +#line 111 "smiles.ll" +{ yylval->atom = new Atom(24); return ATOM_TOKEN; } + YY_BREAK case 22: -#line 113 "smiles.ll" +YY_RULE_SETUP +#line 112 "smiles.ll" +{ yylval->atom = new Atom(25); return ATOM_TOKEN; } + YY_BREAK case 23: -#line 114 "smiles.ll" +YY_RULE_SETUP +#line 113 "smiles.ll" +{ yylval->atom = new Atom(26); return ATOM_TOKEN; } + YY_BREAK case 24: -#line 115 "smiles.ll" +YY_RULE_SETUP +#line 114 "smiles.ll" +{ yylval->atom = new Atom(27); return ATOM_TOKEN; } + YY_BREAK case 25: -#line 116 "smiles.ll" +YY_RULE_SETUP +#line 115 "smiles.ll" +{ yylval->atom = new Atom(28); return ATOM_TOKEN; } + YY_BREAK case 26: -#line 117 "smiles.ll" +YY_RULE_SETUP +#line 116 "smiles.ll" +{ yylval->atom = new Atom(29); return ATOM_TOKEN; } + YY_BREAK case 27: -#line 118 "smiles.ll" +YY_RULE_SETUP +#line 117 "smiles.ll" +{ yylval->atom = new Atom(30); return ATOM_TOKEN; } + YY_BREAK case 28: -#line 119 "smiles.ll" +YY_RULE_SETUP +#line 118 "smiles.ll" +{ yylval->atom = new Atom(31); return ATOM_TOKEN; } + YY_BREAK case 29: -#line 120 "smiles.ll" +YY_RULE_SETUP +#line 119 "smiles.ll" +{ yylval->atom = new Atom(32); return ATOM_TOKEN; } + YY_BREAK case 30: -#line 121 "smiles.ll" +YY_RULE_SETUP +#line 120 "smiles.ll" +{ yylval->atom = new Atom(33); return ATOM_TOKEN; } + YY_BREAK case 31: -#line 122 "smiles.ll" +YY_RULE_SETUP +#line 121 "smiles.ll" +{ yylval->atom = new Atom(34); return ATOM_TOKEN; } + YY_BREAK case 32: -#line 123 "smiles.ll" +YY_RULE_SETUP +#line 122 "smiles.ll" +{ yylval->atom = new Atom(36); return ATOM_TOKEN; } + YY_BREAK case 33: -#line 124 "smiles.ll" +YY_RULE_SETUP +#line 123 "smiles.ll" +{ yylval->atom = new Atom(37); return ATOM_TOKEN; } + YY_BREAK case 34: -#line 125 "smiles.ll" +YY_RULE_SETUP +#line 124 "smiles.ll" +{ yylval->atom = new Atom(38); return ATOM_TOKEN; } + YY_BREAK case 35: -#line 126 "smiles.ll" +YY_RULE_SETUP +#line 125 "smiles.ll" +{ yylval->atom = new Atom(39); return ATOM_TOKEN; } + YY_BREAK case 36: -#line 127 "smiles.ll" +YY_RULE_SETUP +#line 126 "smiles.ll" +{ yylval->atom = new Atom(40); return ATOM_TOKEN; } + YY_BREAK case 37: -#line 128 "smiles.ll" +YY_RULE_SETUP +#line 127 "smiles.ll" +{ yylval->atom = new Atom(41); return ATOM_TOKEN; } + YY_BREAK case 38: -#line 129 "smiles.ll" +YY_RULE_SETUP +#line 128 "smiles.ll" +{ yylval->atom = new Atom(42); return ATOM_TOKEN; } + YY_BREAK case 39: -#line 130 "smiles.ll" +YY_RULE_SETUP +#line 129 "smiles.ll" +{ yylval->atom = new Atom(43); return ATOM_TOKEN; } + YY_BREAK case 40: -#line 131 "smiles.ll" +YY_RULE_SETUP +#line 130 "smiles.ll" +{ yylval->atom = new Atom(44); return ATOM_TOKEN; } + YY_BREAK case 41: -#line 132 "smiles.ll" +YY_RULE_SETUP +#line 131 "smiles.ll" +{ yylval->atom = new Atom(45); return ATOM_TOKEN; } + YY_BREAK case 42: -#line 133 "smiles.ll" +YY_RULE_SETUP +#line 132 "smiles.ll" +{ yylval->atom = new Atom(46); return ATOM_TOKEN; } + YY_BREAK case 43: -#line 134 "smiles.ll" +YY_RULE_SETUP +#line 133 "smiles.ll" +{ yylval->atom = new Atom(47); return ATOM_TOKEN; } + YY_BREAK case 44: -#line 135 "smiles.ll" +YY_RULE_SETUP +#line 134 "smiles.ll" +{ yylval->atom = new Atom(48); return ATOM_TOKEN; } + YY_BREAK case 45: -#line 136 "smiles.ll" +YY_RULE_SETUP +#line 135 "smiles.ll" +{ yylval->atom = new Atom(49); return ATOM_TOKEN; } + YY_BREAK case 46: -#line 137 "smiles.ll" +YY_RULE_SETUP +#line 136 "smiles.ll" +{ yylval->atom = new Atom(50); return ATOM_TOKEN; } + YY_BREAK case 47: -#line 138 "smiles.ll" +YY_RULE_SETUP +#line 137 "smiles.ll" +{ yylval->atom = new Atom(51); return ATOM_TOKEN; } + YY_BREAK case 48: -#line 139 "smiles.ll" +YY_RULE_SETUP +#line 138 "smiles.ll" +{ yylval->atom = new Atom(52); return ATOM_TOKEN; } + YY_BREAK case 49: -#line 140 "smiles.ll" +YY_RULE_SETUP +#line 139 "smiles.ll" +{ yylval->atom = new Atom(54); return ATOM_TOKEN; } + YY_BREAK case 50: -#line 141 "smiles.ll" +YY_RULE_SETUP +#line 140 "smiles.ll" +{ yylval->atom = new Atom(55); return ATOM_TOKEN; } + YY_BREAK case 51: -#line 142 "smiles.ll" +YY_RULE_SETUP +#line 141 "smiles.ll" +{ yylval->atom = new Atom(56); return ATOM_TOKEN; } + YY_BREAK case 52: -#line 143 "smiles.ll" +YY_RULE_SETUP +#line 142 "smiles.ll" +{ yylval->atom = new Atom(57); return ATOM_TOKEN; } + YY_BREAK case 53: -#line 144 "smiles.ll" +YY_RULE_SETUP +#line 143 "smiles.ll" +{ yylval->atom = new Atom(58); return ATOM_TOKEN; } + YY_BREAK case 54: -#line 145 "smiles.ll" +YY_RULE_SETUP +#line 144 "smiles.ll" +{ yylval->atom = new Atom(59); return ATOM_TOKEN; } + YY_BREAK case 55: -#line 146 "smiles.ll" +YY_RULE_SETUP +#line 145 "smiles.ll" +{ yylval->atom = new Atom(60); return ATOM_TOKEN; } + YY_BREAK case 56: -#line 147 "smiles.ll" +YY_RULE_SETUP +#line 146 "smiles.ll" +{ yylval->atom = new Atom(61); return ATOM_TOKEN; } + YY_BREAK case 57: -#line 148 "smiles.ll" +YY_RULE_SETUP +#line 147 "smiles.ll" +{ yylval->atom = new Atom(62); return ATOM_TOKEN; } + YY_BREAK case 58: -#line 149 "smiles.ll" +YY_RULE_SETUP +#line 148 "smiles.ll" +{ yylval->atom = new Atom(63); return ATOM_TOKEN; } + YY_BREAK case 59: -#line 150 "smiles.ll" +YY_RULE_SETUP +#line 149 "smiles.ll" +{ yylval->atom = new Atom(64); return ATOM_TOKEN; } + YY_BREAK case 60: -#line 151 "smiles.ll" +YY_RULE_SETUP +#line 150 "smiles.ll" +{ yylval->atom = new Atom(65); return ATOM_TOKEN; } + YY_BREAK case 61: -#line 152 "smiles.ll" +YY_RULE_SETUP +#line 151 "smiles.ll" +{ yylval->atom = new Atom(66); return ATOM_TOKEN; } + YY_BREAK case 62: -#line 153 "smiles.ll" +YY_RULE_SETUP +#line 152 "smiles.ll" +{ yylval->atom = new Atom(67); return ATOM_TOKEN; } + YY_BREAK case 63: -#line 154 "smiles.ll" +YY_RULE_SETUP +#line 153 "smiles.ll" +{ yylval->atom = new Atom(68); return ATOM_TOKEN; } + YY_BREAK case 64: -#line 155 "smiles.ll" +YY_RULE_SETUP +#line 154 "smiles.ll" +{ yylval->atom = new Atom(69); return ATOM_TOKEN; } + YY_BREAK case 65: -#line 156 "smiles.ll" +YY_RULE_SETUP +#line 155 "smiles.ll" +{ yylval->atom = new Atom(70); return ATOM_TOKEN; } + YY_BREAK case 66: -#line 157 "smiles.ll" +YY_RULE_SETUP +#line 156 "smiles.ll" +{ yylval->atom = new Atom(71); return ATOM_TOKEN; } + YY_BREAK case 67: -#line 158 "smiles.ll" +YY_RULE_SETUP +#line 157 "smiles.ll" +{ yylval->atom = new Atom(72); return ATOM_TOKEN; } + YY_BREAK case 68: -#line 159 "smiles.ll" +YY_RULE_SETUP +#line 158 "smiles.ll" +{ yylval->atom = new Atom(73); return ATOM_TOKEN; } + YY_BREAK case 69: -#line 160 "smiles.ll" +YY_RULE_SETUP +#line 159 "smiles.ll" +{ yylval->atom = new Atom(74); return ATOM_TOKEN; } + YY_BREAK case 70: -#line 161 "smiles.ll" +YY_RULE_SETUP +#line 160 "smiles.ll" +{ yylval->atom = new Atom(75); return ATOM_TOKEN; } + YY_BREAK case 71: -#line 162 "smiles.ll" +YY_RULE_SETUP +#line 161 "smiles.ll" +{ yylval->atom = new Atom(76); return ATOM_TOKEN; } + YY_BREAK case 72: -#line 163 "smiles.ll" +YY_RULE_SETUP +#line 162 "smiles.ll" +{ yylval->atom = new Atom(77); return ATOM_TOKEN; } + YY_BREAK case 73: -#line 164 "smiles.ll" +YY_RULE_SETUP +#line 163 "smiles.ll" +{ yylval->atom = new Atom(78); return ATOM_TOKEN; } + YY_BREAK case 74: -#line 165 "smiles.ll" +YY_RULE_SETUP +#line 164 "smiles.ll" +{ yylval->atom = new Atom(79); return ATOM_TOKEN; } + YY_BREAK case 75: -#line 166 "smiles.ll" +YY_RULE_SETUP +#line 165 "smiles.ll" +{ yylval->atom = new Atom(80); return ATOM_TOKEN; } + YY_BREAK case 76: -#line 167 "smiles.ll" +YY_RULE_SETUP +#line 166 "smiles.ll" +{ yylval->atom = new Atom(81); return ATOM_TOKEN; } + YY_BREAK case 77: -#line 168 "smiles.ll" +YY_RULE_SETUP +#line 167 "smiles.ll" +{ yylval->atom = new Atom(82); return ATOM_TOKEN; } + YY_BREAK case 78: -#line 169 "smiles.ll" +YY_RULE_SETUP +#line 168 "smiles.ll" +{ yylval->atom = new Atom(83); return ATOM_TOKEN; } + YY_BREAK case 79: -#line 170 "smiles.ll" +YY_RULE_SETUP +#line 169 "smiles.ll" +{ yylval->atom = new Atom(84); return ATOM_TOKEN; } + YY_BREAK case 80: -#line 171 "smiles.ll" +YY_RULE_SETUP +#line 170 "smiles.ll" +{ yylval->atom = new Atom(85); return ATOM_TOKEN; } + YY_BREAK case 81: -#line 172 "smiles.ll" +YY_RULE_SETUP +#line 171 "smiles.ll" +{ yylval->atom = new Atom(86); return ATOM_TOKEN; } + YY_BREAK case 82: -#line 173 "smiles.ll" +YY_RULE_SETUP +#line 172 "smiles.ll" +{ yylval->atom = new Atom(87); return ATOM_TOKEN; } + YY_BREAK case 83: -#line 174 "smiles.ll" +YY_RULE_SETUP +#line 173 "smiles.ll" +{ yylval->atom = new Atom(88); return ATOM_TOKEN; } + YY_BREAK case 84: -#line 175 "smiles.ll" +YY_RULE_SETUP +#line 174 "smiles.ll" +{ yylval->atom = new Atom(89); return ATOM_TOKEN; } + YY_BREAK case 85: -#line 176 "smiles.ll" +YY_RULE_SETUP +#line 175 "smiles.ll" +{ yylval->atom = new Atom(90); return ATOM_TOKEN; } + YY_BREAK case 86: -#line 177 "smiles.ll" +YY_RULE_SETUP +#line 176 "smiles.ll" +{ yylval->atom = new Atom(91); return ATOM_TOKEN; } + YY_BREAK case 87: -#line 178 "smiles.ll" +YY_RULE_SETUP +#line 177 "smiles.ll" +{ yylval->atom = new Atom(92); return ATOM_TOKEN; } + YY_BREAK case 88: -#line 179 "smiles.ll" +YY_RULE_SETUP +#line 178 "smiles.ll" +{ yylval->atom = new Atom(93); return ATOM_TOKEN; } + YY_BREAK case 89: -#line 180 "smiles.ll" +YY_RULE_SETUP +#line 179 "smiles.ll" +{ yylval->atom = new Atom(94); return ATOM_TOKEN; } + YY_BREAK case 90: -#line 181 "smiles.ll" +YY_RULE_SETUP +#line 180 "smiles.ll" +{ yylval->atom = new Atom(95); return ATOM_TOKEN; } + YY_BREAK case 91: -#line 182 "smiles.ll" +YY_RULE_SETUP +#line 181 "smiles.ll" +{ yylval->atom = new Atom(96); return ATOM_TOKEN; } + YY_BREAK case 92: -#line 183 "smiles.ll" +YY_RULE_SETUP +#line 182 "smiles.ll" +{ yylval->atom = new Atom(97); return ATOM_TOKEN; } + YY_BREAK case 93: -#line 184 "smiles.ll" +YY_RULE_SETUP +#line 183 "smiles.ll" +{ yylval->atom = new Atom(98); return ATOM_TOKEN; } + YY_BREAK case 94: -#line 185 "smiles.ll" +YY_RULE_SETUP +#line 184 "smiles.ll" +{ yylval->atom = new Atom(99); return ATOM_TOKEN; } + YY_BREAK case 95: -#line 186 "smiles.ll" +YY_RULE_SETUP +#line 185 "smiles.ll" +{ yylval->atom = new Atom(100); return ATOM_TOKEN; } + YY_BREAK case 96: -#line 187 "smiles.ll" +YY_RULE_SETUP +#line 186 "smiles.ll" +{ yylval->atom = new Atom(101); return ATOM_TOKEN; } + YY_BREAK case 97: -#line 188 "smiles.ll" +YY_RULE_SETUP +#line 187 "smiles.ll" +{ yylval->atom = new Atom(102); return ATOM_TOKEN; } + YY_BREAK case 98: -#line 189 "smiles.ll" +YY_RULE_SETUP +#line 188 "smiles.ll" +{ yylval->atom = new Atom(103); return ATOM_TOKEN; } + YY_BREAK case 99: -#line 190 "smiles.ll" +YY_RULE_SETUP +#line 189 "smiles.ll" +{ yylval->atom = new Atom(104); return ATOM_TOKEN; } + YY_BREAK case 100: -#line 191 "smiles.ll" +YY_RULE_SETUP +#line 190 "smiles.ll" +{ yylval->atom = new Atom(105); return ATOM_TOKEN; } + YY_BREAK case 101: -#line 192 "smiles.ll" +YY_RULE_SETUP +#line 191 "smiles.ll" +{ yylval->atom = new Atom(106); return ATOM_TOKEN; } + YY_BREAK case 102: -#line 193 "smiles.ll" +YY_RULE_SETUP +#line 192 "smiles.ll" +{ yylval->atom = new Atom(107); return ATOM_TOKEN; } + YY_BREAK case 103: -#line 194 "smiles.ll" +YY_RULE_SETUP +#line 193 "smiles.ll" +{ yylval->atom = new Atom(108); return ATOM_TOKEN; } + YY_BREAK case 104: -#line 195 "smiles.ll" +YY_RULE_SETUP +#line 194 "smiles.ll" +{ yylval->atom = new Atom(109); return ATOM_TOKEN; } + YY_BREAK case 105: -#line 196 "smiles.ll" +YY_RULE_SETUP +#line 195 "smiles.ll" +{ yylval->atom = new Atom(110); return ATOM_TOKEN; } + YY_BREAK case 106: -#line 197 "smiles.ll" +YY_RULE_SETUP +#line 196 "smiles.ll" +{ yylval->atom = new Atom(111); return ATOM_TOKEN; } + YY_BREAK case 107: -#line 198 "smiles.ll" +YY_RULE_SETUP +#line 197 "smiles.ll" +{ yylval->atom = new Atom(112); return ATOM_TOKEN; } + YY_BREAK case 108: -#line 199 "smiles.ll" +YY_RULE_SETUP +#line 198 "smiles.ll" +{ yylval->atom = new Atom(113); return ATOM_TOKEN; } + YY_BREAK case 109: -#line 200 "smiles.ll" +YY_RULE_SETUP +#line 199 "smiles.ll" +{ yylval->atom = new Atom(114); return ATOM_TOKEN; } + YY_BREAK case 110: -#line 201 "smiles.ll" +YY_RULE_SETUP +#line 200 "smiles.ll" +{ yylval->atom = new Atom(115); return ATOM_TOKEN; } + YY_BREAK case 111: YY_RULE_SETUP #line 201 "smiles.ll" -{ yylval->atom = new Atom( PeriodicTable::getTable()->getAtomicNumber( yytext ) ); - return ATOM_TOKEN; - } +{ yylval->atom = new Atom(116); return ATOM_TOKEN; } YY_BREAK case 112: YY_RULE_SETUP -#line 204 "smiles.ll" -{ yylval->atom = new Atom(5);return ORGANIC_ATOM_TOKEN; } +#line 202 "smiles.ll" +{ yylval->atom = new Atom(117); return ATOM_TOKEN; } YY_BREAK case 113: YY_RULE_SETUP -#line 205 "smiles.ll" -{ yylval->atom = new Atom(6);return ORGANIC_ATOM_TOKEN; } +#line 203 "smiles.ll" +{ yylval->atom = new Atom(118); return ATOM_TOKEN; } YY_BREAK case 114: YY_RULE_SETUP -#line 206 "smiles.ll" -{ yylval->atom = new Atom(7);return ORGANIC_ATOM_TOKEN; } +#line 205 "smiles.ll" +{ yylval->atom = new Atom(110); return ATOM_TOKEN; } YY_BREAK case 115: YY_RULE_SETUP -#line 207 "smiles.ll" -{ yylval->atom = new Atom(8);return ORGANIC_ATOM_TOKEN; } +#line 206 "smiles.ll" +{ yylval->atom = new Atom(111); return ATOM_TOKEN; } YY_BREAK case 116: YY_RULE_SETUP -#line 208 "smiles.ll" -{ yylval->atom = new Atom(15);return ORGANIC_ATOM_TOKEN; } +#line 207 "smiles.ll" +{ yylval->atom = new Atom(112); return ATOM_TOKEN; } YY_BREAK case 117: YY_RULE_SETUP -#line 209 "smiles.ll" -{ yylval->atom = new Atom(16);return ORGANIC_ATOM_TOKEN; } +#line 208 "smiles.ll" +{ yylval->atom = new Atom(113); return ATOM_TOKEN; } YY_BREAK case 118: YY_RULE_SETUP -#line 210 "smiles.ll" -{ yylval->atom = new Atom(9);return ORGANIC_ATOM_TOKEN; } +#line 209 "smiles.ll" +{ yylval->atom = new Atom(114); return ATOM_TOKEN; } YY_BREAK case 119: YY_RULE_SETUP -#line 211 "smiles.ll" -{ yylval->atom = new Atom(17);return ORGANIC_ATOM_TOKEN; } +#line 210 "smiles.ll" +{ yylval->atom = new Atom(115); return ATOM_TOKEN; } YY_BREAK case 120: YY_RULE_SETUP -#line 212 "smiles.ll" -{ yylval->atom = new Atom(35);return ORGANIC_ATOM_TOKEN; } +#line 211 "smiles.ll" +{ yylval->atom = new Atom(116); return ATOM_TOKEN; } YY_BREAK case 121: YY_RULE_SETUP -#line 213 "smiles.ll" -{ yylval->atom = new Atom(53);return ORGANIC_ATOM_TOKEN; } +#line 212 "smiles.ll" +{ yylval->atom = new Atom(117); return ATOM_TOKEN; } YY_BREAK case 122: YY_RULE_SETUP +#line 213 "smiles.ll" +{ yylval->atom = new Atom(118); return ATOM_TOKEN; } + YY_BREAK +case 123: +YY_RULE_SETUP #line 215 "smiles.ll" +{ yylval->atom = new Atom(5);return ORGANIC_ATOM_TOKEN; } + YY_BREAK +case 124: +YY_RULE_SETUP +#line 216 "smiles.ll" +{ yylval->atom = new Atom(6);return ORGANIC_ATOM_TOKEN; } + YY_BREAK +case 125: +YY_RULE_SETUP +#line 217 "smiles.ll" +{ yylval->atom = new Atom(7);return ORGANIC_ATOM_TOKEN; } + YY_BREAK +case 126: +YY_RULE_SETUP +#line 218 "smiles.ll" +{ yylval->atom = new Atom(8);return ORGANIC_ATOM_TOKEN; } + YY_BREAK +case 127: +YY_RULE_SETUP +#line 219 "smiles.ll" +{ yylval->atom = new Atom(15);return ORGANIC_ATOM_TOKEN; } + YY_BREAK +case 128: +YY_RULE_SETUP +#line 220 "smiles.ll" +{ yylval->atom = new Atom(16);return ORGANIC_ATOM_TOKEN; } + YY_BREAK +case 129: +YY_RULE_SETUP +#line 221 "smiles.ll" +{ yylval->atom = new Atom(9);return ORGANIC_ATOM_TOKEN; } + YY_BREAK +case 130: +YY_RULE_SETUP +#line 222 "smiles.ll" +{ yylval->atom = new Atom(17);return ORGANIC_ATOM_TOKEN; } + YY_BREAK +case 131: +YY_RULE_SETUP +#line 223 "smiles.ll" +{ yylval->atom = new Atom(35);return ORGANIC_ATOM_TOKEN; } + YY_BREAK +case 132: +YY_RULE_SETUP +#line 224 "smiles.ll" +{ yylval->atom = new Atom(53);return ORGANIC_ATOM_TOKEN; } + YY_BREAK +case 133: +YY_RULE_SETUP +#line 226 "smiles.ll" { return H_TOKEN; } YY_BREAK -case 123: +case 134: YY_RULE_SETUP -#line 219 "smiles.ll" +#line 230 "smiles.ll" { yylval->atom = new Atom ( 5 ); yylval->atom->setIsAromatic(true); return AROMATIC_ATOM_TOKEN; } YY_BREAK -case 124: +case 135: YY_RULE_SETUP -#line 223 "smiles.ll" +#line 234 "smiles.ll" { yylval->atom = new Atom ( 6 ); yylval->atom->setIsAromatic(true); return AROMATIC_ATOM_TOKEN; } YY_BREAK -case 125: +case 136: YY_RULE_SETUP -#line 227 "smiles.ll" +#line 238 "smiles.ll" { yylval->atom = new Atom( 7 ); yylval->atom->setIsAromatic(true); return AROMATIC_ATOM_TOKEN; } YY_BREAK -case 126: +case 137: YY_RULE_SETUP -#line 231 "smiles.ll" +#line 242 "smiles.ll" { yylval->atom = new Atom( 8 ); yylval->atom->setIsAromatic(true); return AROMATIC_ATOM_TOKEN; } YY_BREAK -case 127: +case 138: YY_RULE_SETUP -#line 235 "smiles.ll" +#line 246 "smiles.ll" { yylval->atom = new Atom( 15 ); yylval->atom->setIsAromatic(true); return AROMATIC_ATOM_TOKEN; } YY_BREAK -case 128: +case 139: YY_RULE_SETUP -#line 239 "smiles.ll" +#line 250 "smiles.ll" { yylval->atom = new Atom( 16 ); yylval->atom->setIsAromatic(true); return AROMATIC_ATOM_TOKEN; } YY_BREAK -case 129: +case 140: YY_RULE_SETUP -#line 244 "smiles.ll" +#line 255 "smiles.ll" { yylval->atom = new Atom( 14 ); yylval->atom->setIsAromatic(true); return AROMATIC_ATOM_TOKEN; } YY_BREAK -case 130: +case 141: YY_RULE_SETUP -#line 248 "smiles.ll" +#line 259 "smiles.ll" { yylval->atom = new Atom( 33 ); yylval->atom->setIsAromatic(true); return AROMATIC_ATOM_TOKEN; } YY_BREAK -case 131: +case 142: YY_RULE_SETUP -#line 252 "smiles.ll" +#line 263 "smiles.ll" { yylval->atom = new Atom( 34 ); yylval->atom->setIsAromatic(true); return AROMATIC_ATOM_TOKEN; } YY_BREAK -case 132: +case 143: YY_RULE_SETUP -#line 256 "smiles.ll" +#line 267 "smiles.ll" { yylval->atom = new Atom( 52 ); yylval->atom->setIsAromatic(true); return AROMATIC_ATOM_TOKEN; } YY_BREAK -case 133: +case 144: YY_RULE_SETUP -#line 261 "smiles.ll" +#line 272 "smiles.ll" { yylval->atom = new Atom( 0 ); yylval->atom->setProp(common_properties::dummyLabel, std::string("*")); @@ -1370,143 +1769,214 @@ YY_RULE_SETUP return ORGANIC_ATOM_TOKEN; } YY_BREAK -case 134: +case 145: YY_RULE_SETUP -#line 269 "smiles.ll" +#line 280 "smiles.ll" { return COLON_TOKEN; } YY_BREAK -case 135: + + // The next block is a workaround for a pathlogy in the SMILES produced + // by some Biovia tools + +case 146: YY_RULE_SETUP -#line 271 "smiles.ll" -{ - yylval->bond = new Bond(); - Bond::BondType bt=Bond::UNSPECIFIED; - switch(yytext[0]){ - case '=': - bt = Bond::DOUBLE; - break; - case '#': - bt = Bond::TRIPLE; - break; - case ':': - bt = Bond::AROMATIC; - yylval->bond->setIsAromatic(true); - break; - default: - CHECK_INVARIANT(0,"cannot get here"); - } - yylval->bond->setBondType(bt); - return BOND_TOKEN; } +#line 286 "smiles.ll" +{ yylval->atom = new Atom(104); return ATOM_TOKEN; } YY_BREAK -case 136: +case 147: +YY_RULE_SETUP +#line 287 "smiles.ll" +{ yylval->atom = new Atom(105); return ATOM_TOKEN; } + YY_BREAK +case 148: +YY_RULE_SETUP +#line 288 "smiles.ll" +{ yylval->atom = new Atom(106); return ATOM_TOKEN; } + YY_BREAK +case 149: +YY_RULE_SETUP +#line 289 "smiles.ll" +{ yylval->atom = new Atom(107); return ATOM_TOKEN; } + YY_BREAK +case 150: YY_RULE_SETUP #line 290 "smiles.ll" -{ - yylval->bond = new Bond(Bond::DATIVER); - return BOND_TOKEN; -} +{ yylval->atom = new Atom(108); return ATOM_TOKEN; } YY_BREAK -case 137: +case 151: +YY_RULE_SETUP +#line 291 "smiles.ll" +{ yylval->atom = new Atom(109); return ATOM_TOKEN; } + YY_BREAK +case 152: +YY_RULE_SETUP +#line 292 "smiles.ll" +{ yylval->atom = new Atom(110); return ATOM_TOKEN; } + YY_BREAK +case 153: +YY_RULE_SETUP +#line 293 "smiles.ll" +{ yylval->atom = new Atom(111); return ATOM_TOKEN; } + YY_BREAK +case 154: YY_RULE_SETUP #line 294 "smiles.ll" -{ - yylval->bond = new Bond(Bond::DATIVEL); - return BOND_TOKEN; -} +{ yylval->atom = new Atom(112); return ATOM_TOKEN; } YY_BREAK -case 138: +case 155: +YY_RULE_SETUP +#line 295 "smiles.ll" +{ yylval->atom = new Atom(113); return ATOM_TOKEN; } + YY_BREAK +case 156: +YY_RULE_SETUP +#line 296 "smiles.ll" +{ yylval->atom = new Atom(114); return ATOM_TOKEN; } + YY_BREAK +case 157: +YY_RULE_SETUP +#line 297 "smiles.ll" +{ yylval->atom = new Atom(115); return ATOM_TOKEN; } + YY_BREAK +case 158: +YY_RULE_SETUP +#line 298 "smiles.ll" +{ yylval->atom = new Atom(116); return ATOM_TOKEN; } + YY_BREAK +case 159: YY_RULE_SETUP #line 299 "smiles.ll" -{ yylval->bond = new QueryBond(); - yylval->bond->setQuery(makeBondNullQuery()); - return BOND_TOKEN; } +{ yylval->atom = new Atom(117); return ATOM_TOKEN; } YY_BREAK -case 139: +case 160: YY_RULE_SETUP -#line 303 "smiles.ll" +#line 300 "smiles.ll" +{ yylval->atom = new Atom(118); return ATOM_TOKEN; } + YY_BREAK +case 161: +YY_RULE_SETUP +#line 302 "smiles.ll" +{ yylval->bond = new Bond(Bond::DOUBLE); + return BOND_TOKEN; } + YY_BREAK +case 162: +YY_RULE_SETUP +#line 304 "smiles.ll" +{ yylval->bond = new Bond(Bond::TRIPLE); + return BOND_TOKEN; } + YY_BREAK +case 163: +YY_RULE_SETUP +#line 306 "smiles.ll" +{ yylval->bond = new Bond(Bond::AROMATIC); + yylval->bond->setIsAromatic(true); + return BOND_TOKEN; } + YY_BREAK +case 164: +YY_RULE_SETUP +#line 309 "smiles.ll" +{ yylval->bond = new Bond(Bond::DATIVER); + return BOND_TOKEN; } + YY_BREAK +case 165: +YY_RULE_SETUP +#line 311 "smiles.ll" +{ yylval->bond = new Bond(Bond::DATIVEL); + return BOND_TOKEN; } + YY_BREAK +case 166: +YY_RULE_SETUP +#line 313 "smiles.ll" +{ yylval->bond = new QueryBond(); + yylval->bond->setQuery(makeBondNullQuery()); + return BOND_TOKEN; } + YY_BREAK +case 167: +YY_RULE_SETUP +#line 317 "smiles.ll" { yylval->bond = new Bond(Bond::SINGLE); yylval->bond->setBondDir(Bond::ENDDOWNRIGHT); return BOND_TOKEN; } YY_BREAK -case 140: +case 168: YY_RULE_SETUP -#line 307 "smiles.ll" +#line 321 "smiles.ll" { yylval->bond = new Bond(Bond::SINGLE); yylval->bond->setBondDir(Bond::ENDUPRIGHT); return BOND_TOKEN; } YY_BREAK -case 141: +case 169: YY_RULE_SETUP -#line 311 "smiles.ll" +#line 325 "smiles.ll" { return MINUS_TOKEN; } YY_BREAK -case 142: -YY_RULE_SETUP -#line 313 "smiles.ll" -{ return PLUS_TOKEN; } - YY_BREAK -case 143: -YY_RULE_SETUP -#line 315 "smiles.ll" -{ return GROUP_OPEN_TOKEN; } - YY_BREAK -case 144: -YY_RULE_SETUP -#line 316 "smiles.ll" -{ return GROUP_CLOSE_TOKEN; } - YY_BREAK -case 145: -YY_RULE_SETUP -#line 319 "smiles.ll" -{ BEGIN IN_ATOM_STATE; return ATOM_OPEN_TOKEN; } - YY_BREAK -case 146: -YY_RULE_SETUP -#line 320 "smiles.ll" -{ BEGIN INITIAL; return ATOM_CLOSE_TOKEN; } - YY_BREAK -case 147: -YY_RULE_SETUP -#line 322 "smiles.ll" -{ return SEPARATOR_TOKEN; } - YY_BREAK -case 148: -YY_RULE_SETUP -#line 324 "smiles.ll" -{ return PERCENT_TOKEN; } - YY_BREAK -case 149: -YY_RULE_SETUP -#line 326 "smiles.ll" -{ yylval->ival = 0; return ZERO_TOKEN; } - YY_BREAK -case 150: +case 170: YY_RULE_SETUP #line 327 "smiles.ll" +{ return PLUS_TOKEN; } + YY_BREAK +case 171: +YY_RULE_SETUP +#line 329 "smiles.ll" +{ return GROUP_OPEN_TOKEN; } + YY_BREAK +case 172: +YY_RULE_SETUP +#line 330 "smiles.ll" +{ return GROUP_CLOSE_TOKEN; } + YY_BREAK +case 173: +YY_RULE_SETUP +#line 333 "smiles.ll" +{ BEGIN IN_ATOM_STATE; return ATOM_OPEN_TOKEN; } + YY_BREAK +case 174: +YY_RULE_SETUP +#line 334 "smiles.ll" +{ BEGIN INITIAL; return ATOM_CLOSE_TOKEN; } + YY_BREAK +case 175: +YY_RULE_SETUP +#line 336 "smiles.ll" +{ return SEPARATOR_TOKEN; } + YY_BREAK +case 176: +YY_RULE_SETUP +#line 338 "smiles.ll" +{ return PERCENT_TOKEN; } + YY_BREAK +case 177: +YY_RULE_SETUP +#line 340 "smiles.ll" +{ yylval->ival = 0; return ZERO_TOKEN; } + YY_BREAK +case 178: +YY_RULE_SETUP +#line 341 "smiles.ll" { yylval->ival = atoi( yytext ); return NONZERO_DIGIT_TOKEN; } YY_BREAK -case 151: -/* rule 151 can match eol */ +case 179: +/* rule 179 can match eol */ YY_RULE_SETUP -#line 331 "smiles.ll" +#line 345 "smiles.ll" return 0; YY_BREAK case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(IN_ATOM_STATE): -#line 333 "smiles.ll" +#line 347 "smiles.ll" { return EOS_TOKEN; } YY_BREAK -case 152: +case 180: YY_RULE_SETUP -#line 334 "smiles.ll" +#line 348 "smiles.ll" return yytext[0]; YY_BREAK -case 153: +case 181: YY_RULE_SETUP -#line 336 "smiles.ll" +#line 350 "smiles.ll" ECHO; YY_BREAK -#line 1510 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/lex.yysmiles.cpp" +#line 1980 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/lex.yysmiles.cpp" case YY_END_OF_BUFFER: { @@ -1799,7 +2269,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 190 ) + if ( yy_current_state >= 246 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -1828,11 +2298,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 190 ) + if ( yy_current_state >= 246 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 189); + yy_is_jam = (yy_current_state == 245); (void)yyg; return yy_is_jam ? 0 : yy_current_state; @@ -2685,7 +3155,7 @@ void yysmiles_free (void * ptr , yyscan_t yyscanner) #define YYTABLES_NAME "yytables" -#line 336 "smiles.ll" +#line 350 "smiles.ll" diff --git a/Code/GraphMol/SmilesParse/smiles.ll b/Code/GraphMol/SmilesParse/smiles.ll index 486870c13..c809a90e1 100644 --- a/Code/GraphMol/SmilesParse/smiles.ll +++ b/Code/GraphMol/SmilesParse/smiles.ll @@ -94,113 +94,124 @@ size_t setup_smiles_string(const std::string &text,yyscan_t yyscanner){ @ { return AT_TOKEN; } -He | -Li | -Be | -Ne | -Na | -Mg | -Al | -Si | -Ar | -K | -Ca | -Sc | -Ti | -V | -Cr | -Mn | -Co | -Fe | -Ni | -Cu | -Zn | -Ga | -Ge | -As | -Se | -Kr | -Rb | -Sr | -Y | -Zr | -Nb | -Mo | -Tc | -Ru | -Rh | -Pd | -Ag | -Cd | -In | -Sn | -Sb | -Te | -Xe | -Cs | -Ba | -La | -Ce | -Pr | -Nd | -Pm | -Sm | -Eu | -Gd | -Tb | -Dy | -Ho | -Er | -Tm | -Yb | -Lu | -Hf | -Ta | -W | -Re | -Os | -Ir | -Pt | -Au | -Hg | -Tl | -Pb | -Bi | -Po | -At | -Rn | -Fr | -Ra | -Ac | -Th | -Pa | -U | -Np | -Pu | -Am | -Cm | -Bk | -Cf | -Es | -Fm | -Md | -No | -Lr | -Rf | -Db | -Sg | -Bh | -Hs | -Mt | -Ds | -Rg | -Cn | -Uut | -Fl | -Uup | -Lv { yylval->atom = new Atom( PeriodicTable::getTable()->getAtomicNumber( yytext ) ); - return ATOM_TOKEN; - } +He { yylval->atom = new Atom(2); return ATOM_TOKEN; } +Li { yylval->atom = new Atom(3); return ATOM_TOKEN; } +Be { yylval->atom = new Atom(4); return ATOM_TOKEN; } +Ne { yylval->atom = new Atom(10); return ATOM_TOKEN; } +Na { yylval->atom = new Atom(11); return ATOM_TOKEN; } +Mg { yylval->atom = new Atom(12); return ATOM_TOKEN; } +Al { yylval->atom = new Atom(13); return ATOM_TOKEN; } +Si { yylval->atom = new Atom(14); return ATOM_TOKEN; } +Ar { yylval->atom = new Atom(18); return ATOM_TOKEN; } +K { yylval->atom = new Atom(19); return ATOM_TOKEN; } +Ca { yylval->atom = new Atom(20); return ATOM_TOKEN; } +Sc { yylval->atom = new Atom(21); return ATOM_TOKEN; } +Ti { yylval->atom = new Atom(22); return ATOM_TOKEN; } +V { yylval->atom = new Atom(23); return ATOM_TOKEN; } +Cr { yylval->atom = new Atom(24); return ATOM_TOKEN; } +Mn { yylval->atom = new Atom(25); return ATOM_TOKEN; } +Fe { yylval->atom = new Atom(26); return ATOM_TOKEN; } +Co { yylval->atom = new Atom(27); return ATOM_TOKEN; } +Ni { yylval->atom = new Atom(28); return ATOM_TOKEN; } +Cu { yylval->atom = new Atom(29); return ATOM_TOKEN; } +Zn { yylval->atom = new Atom(30); return ATOM_TOKEN; } +Ga { yylval->atom = new Atom(31); return ATOM_TOKEN; } +Ge { yylval->atom = new Atom(32); return ATOM_TOKEN; } +As { yylval->atom = new Atom(33); return ATOM_TOKEN; } +Se { yylval->atom = new Atom(34); return ATOM_TOKEN; } +Kr { yylval->atom = new Atom(36); return ATOM_TOKEN; } +Rb { yylval->atom = new Atom(37); return ATOM_TOKEN; } +Sr { yylval->atom = new Atom(38); return ATOM_TOKEN; } +Y { yylval->atom = new Atom(39); return ATOM_TOKEN; } +Zr { yylval->atom = new Atom(40); return ATOM_TOKEN; } +Nb { yylval->atom = new Atom(41); return ATOM_TOKEN; } +Mo { yylval->atom = new Atom(42); return ATOM_TOKEN; } +Tc { yylval->atom = new Atom(43); return ATOM_TOKEN; } +Ru { yylval->atom = new Atom(44); return ATOM_TOKEN; } +Rh { yylval->atom = new Atom(45); return ATOM_TOKEN; } +Pd { yylval->atom = new Atom(46); return ATOM_TOKEN; } +Ag { yylval->atom = new Atom(47); return ATOM_TOKEN; } +Cd { yylval->atom = new Atom(48); return ATOM_TOKEN; } +In { yylval->atom = new Atom(49); return ATOM_TOKEN; } +Sn { yylval->atom = new Atom(50); return ATOM_TOKEN; } +Sb { yylval->atom = new Atom(51); return ATOM_TOKEN; } +Te { yylval->atom = new Atom(52); return ATOM_TOKEN; } +Xe { yylval->atom = new Atom(54); return ATOM_TOKEN; } +Cs { yylval->atom = new Atom(55); return ATOM_TOKEN; } +Ba { yylval->atom = new Atom(56); return ATOM_TOKEN; } +La { yylval->atom = new Atom(57); return ATOM_TOKEN; } +Ce { yylval->atom = new Atom(58); return ATOM_TOKEN; } +Pr { yylval->atom = new Atom(59); return ATOM_TOKEN; } +Nd { yylval->atom = new Atom(60); return ATOM_TOKEN; } +Pm { yylval->atom = new Atom(61); return ATOM_TOKEN; } +Sm { yylval->atom = new Atom(62); return ATOM_TOKEN; } +Eu { yylval->atom = new Atom(63); return ATOM_TOKEN; } +Gd { yylval->atom = new Atom(64); return ATOM_TOKEN; } +Tb { yylval->atom = new Atom(65); return ATOM_TOKEN; } +Dy { yylval->atom = new Atom(66); return ATOM_TOKEN; } +Ho { yylval->atom = new Atom(67); return ATOM_TOKEN; } +Er { yylval->atom = new Atom(68); return ATOM_TOKEN; } +Tm { yylval->atom = new Atom(69); return ATOM_TOKEN; } +Yb { yylval->atom = new Atom(70); return ATOM_TOKEN; } +Lu { yylval->atom = new Atom(71); return ATOM_TOKEN; } +Hf { yylval->atom = new Atom(72); return ATOM_TOKEN; } +Ta { yylval->atom = new Atom(73); return ATOM_TOKEN; } +W { yylval->atom = new Atom(74); return ATOM_TOKEN; } +Re { yylval->atom = new Atom(75); return ATOM_TOKEN; } +Os { yylval->atom = new Atom(76); return ATOM_TOKEN; } +Ir { yylval->atom = new Atom(77); return ATOM_TOKEN; } +Pt { yylval->atom = new Atom(78); return ATOM_TOKEN; } +Au { yylval->atom = new Atom(79); return ATOM_TOKEN; } +Hg { yylval->atom = new Atom(80); return ATOM_TOKEN; } +Tl { yylval->atom = new Atom(81); return ATOM_TOKEN; } +Pb { yylval->atom = new Atom(82); return ATOM_TOKEN; } +Bi { yylval->atom = new Atom(83); return ATOM_TOKEN; } +Po { yylval->atom = new Atom(84); return ATOM_TOKEN; } +At { yylval->atom = new Atom(85); return ATOM_TOKEN; } +Rn { yylval->atom = new Atom(86); return ATOM_TOKEN; } +Fr { yylval->atom = new Atom(87); return ATOM_TOKEN; } +Ra { yylval->atom = new Atom(88); return ATOM_TOKEN; } +Ac { yylval->atom = new Atom(89); return ATOM_TOKEN; } +Th { yylval->atom = new Atom(90); return ATOM_TOKEN; } +Pa { yylval->atom = new Atom(91); return ATOM_TOKEN; } +U { yylval->atom = new Atom(92); return ATOM_TOKEN; } +Np { yylval->atom = new Atom(93); return ATOM_TOKEN; } +Pu { yylval->atom = new Atom(94); return ATOM_TOKEN; } +Am { yylval->atom = new Atom(95); return ATOM_TOKEN; } +Cm { yylval->atom = new Atom(96); return ATOM_TOKEN; } +Bk { yylval->atom = new Atom(97); return ATOM_TOKEN; } +Cf { yylval->atom = new Atom(98); return ATOM_TOKEN; } +Es { yylval->atom = new Atom(99); return ATOM_TOKEN; } +Fm { yylval->atom = new Atom(100); return ATOM_TOKEN; } +Md { yylval->atom = new Atom(101); return ATOM_TOKEN; } +No { yylval->atom = new Atom(102); return ATOM_TOKEN; } +Lr { yylval->atom = new Atom(103); return ATOM_TOKEN; } +Rf { yylval->atom = new Atom(104); return ATOM_TOKEN; } +Db { yylval->atom = new Atom(105); return ATOM_TOKEN; } +Sg { yylval->atom = new Atom(106); return ATOM_TOKEN; } +Bh { yylval->atom = new Atom(107); return ATOM_TOKEN; } +Hs { yylval->atom = new Atom(108); return ATOM_TOKEN; } +Mt { yylval->atom = new Atom(109); return ATOM_TOKEN; } +Ds { yylval->atom = new Atom(110); return ATOM_TOKEN; } +Rg { yylval->atom = new Atom(111); return ATOM_TOKEN; } +Cn { yylval->atom = new Atom(112); return ATOM_TOKEN; } +Nh { yylval->atom = new Atom(113); return ATOM_TOKEN; } +Fl { yylval->atom = new Atom(114); return ATOM_TOKEN; } +Mc { yylval->atom = new Atom(115); return ATOM_TOKEN; } +Lv { yylval->atom = new Atom(116); return ATOM_TOKEN; } +Ts { yylval->atom = new Atom(117); return ATOM_TOKEN; } +Og { yylval->atom = new Atom(118); return ATOM_TOKEN; } + +Uun { yylval->atom = new Atom(110); return ATOM_TOKEN; } +Uuu { yylval->atom = new Atom(111); return ATOM_TOKEN; } +Uub { yylval->atom = new Atom(112); return ATOM_TOKEN; } +Uut { yylval->atom = new Atom(113); return ATOM_TOKEN; } +Uuq { yylval->atom = new Atom(114); return ATOM_TOKEN; } +Uup { yylval->atom = new Atom(115); return ATOM_TOKEN; } +Uuh { yylval->atom = new Atom(116); return ATOM_TOKEN; } +Uus { yylval->atom = new Atom(117); return ATOM_TOKEN; } +Uuo { yylval->atom = new Atom(118); return ATOM_TOKEN; } + B { yylval->atom = new Atom(5);return ORGANIC_ATOM_TOKEN; } C { yylval->atom = new Atom(6);return ORGANIC_ATOM_TOKEN; } N { yylval->atom = new Atom(7);return ORGANIC_ATOM_TOKEN; } @@ -268,37 +279,40 @@ s { yylval->atom = new Atom( 16 ); \: { return COLON_TOKEN; } -[\=\#\:] { - yylval->bond = new Bond(); - Bond::BondType bt=Bond::UNSPECIFIED; - switch(yytext[0]){ - case '=': - bt = Bond::DOUBLE; - break; - case '#': - bt = Bond::TRIPLE; - break; - case ':': - bt = Bond::AROMATIC; - yylval->bond->setIsAromatic(true); - break; - default: - CHECK_INVARIANT(0,"cannot get here"); - } - yylval->bond->setBondType(bt); - return BOND_TOKEN; } -\-\> { - yylval->bond = new Bond(Bond::DATIVER); - return BOND_TOKEN; -} -\<\- { - yylval->bond = new Bond(Bond::DATIVEL); - return BOND_TOKEN; -} +%{ + // The next block is a workaround for a pathlogy in the SMILES produced + // by some Biovia tools +%} +\'Rf\' { yylval->atom = new Atom(104); return ATOM_TOKEN; } +\'Db\' { yylval->atom = new Atom(105); return ATOM_TOKEN; } +\'Sg\' { yylval->atom = new Atom(106); return ATOM_TOKEN; } +\'Bh\' { yylval->atom = new Atom(107); return ATOM_TOKEN; } +\'Hs\' { yylval->atom = new Atom(108); return ATOM_TOKEN; } +\'Mt\' { yylval->atom = new Atom(109); return ATOM_TOKEN; } +\'Ds\' { yylval->atom = new Atom(110); return ATOM_TOKEN; } +\'Rg\' { yylval->atom = new Atom(111); return ATOM_TOKEN; } +\'Cn\' { yylval->atom = new Atom(112); return ATOM_TOKEN; } +\'Nh\' { yylval->atom = new Atom(113); return ATOM_TOKEN; } +\'Fl\' { yylval->atom = new Atom(114); return ATOM_TOKEN; } +\'Mc\' { yylval->atom = new Atom(115); return ATOM_TOKEN; } +\'Lv\' { yylval->atom = new Atom(116); return ATOM_TOKEN; } +\'Ts\' { yylval->atom = new Atom(117); return ATOM_TOKEN; } +\'Og\' { yylval->atom = new Atom(118); return ATOM_TOKEN; } +\= { yylval->bond = new Bond(Bond::DOUBLE); + return BOND_TOKEN; } +\# { yylval->bond = new Bond(Bond::TRIPLE); + return BOND_TOKEN; } +\: { yylval->bond = new Bond(Bond::AROMATIC); + yylval->bond->setIsAromatic(true); + return BOND_TOKEN; } +\-\> { yylval->bond = new Bond(Bond::DATIVER); + return BOND_TOKEN; } +\<\- { yylval->bond = new Bond(Bond::DATIVEL); + return BOND_TOKEN; } \~ { yylval->bond = new QueryBond(); - yylval->bond->setQuery(makeBondNullQuery()); - return BOND_TOKEN; } + yylval->bond->setQuery(makeBondNullQuery()); + return BOND_TOKEN; } [\\]{1,2} { yylval->bond = new Bond(Bond::SINGLE); yylval->bond->setBondDir(Bond::ENDDOWNRIGHT); diff --git a/Code/GraphMol/SmilesParse/test.cpp b/Code/GraphMol/SmilesParse/test.cpp index 950da7328..1b2d5a9eb 100644 --- a/Code/GraphMol/SmilesParse/test.cpp +++ b/Code/GraphMol/SmilesParse/test.cpp @@ -103,12 +103,16 @@ void testPass() { "[C:0]", // issue 3525776 "[si]1cccc[si]1", // aromatic Si (github issue #5) "[asH]1cccc1", // aromatic As (github issue #682) - "[Db][Sg][Bh][Hs][Mt][Ds][Rg][Cn][Uut][Fl][Uup][Lv]", // new elements + "[Db][Sg][Bh][Hs][Mt][Ds][Rg][Cn][Nh][Fl][Mc][Lv][Ts][Og]", // new elements + "[Uun][Uuu][Uub][Uut][Uuq][Uup][Uuh][Uus][Uuo]", // old names for new + // elements + "['Db']['Sg']['Bh']['Hs']['Mt']['Ds']['Rg']['Cn']['Nh']['Fl']['Mc']['Lv']['" + "Ts']['Og']", // a biovia pathology "EOS" }; while (smis[i] != "EOS") { string smi = smis[i]; - // BOOST_LOG(rdInfoLog)<< "***: " << smi << std::endl; + BOOST_LOG(rdInfoLog) << "***: " << smi << std::endl; mol = SmilesToMol(smi); CHECK_INVARIANT(mol, smi); if (mol) { @@ -3845,35 +3849,33 @@ void testGithub1219() { } void testSmilesParseParams() { - BOOST_LOG(rdInfoLog) - << "Testing the SmilesParseParams class" - << std::endl; - { - std::string smiles = "C1=CC=CC=C1[H]"; - ROMol *m = SmilesToMol(smiles); - TEST_ASSERT(m); - TEST_ASSERT(m->getNumAtoms() == 6); - TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic()); - delete m; + BOOST_LOG(rdInfoLog) << "Testing the SmilesParseParams class" << std::endl; + { + std::string smiles = "C1=CC=CC=C1[H]"; + ROMol *m = SmilesToMol(smiles); + TEST_ASSERT(m); + TEST_ASSERT(m->getNumAtoms() == 6); + TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic()); + delete m; - { - SmilesParserParams params; - m = SmilesToMol(smiles,params); - TEST_ASSERT(m); - TEST_ASSERT(m->getNumAtoms() == 6); - TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic()); - delete m; - } - { // no removeHs, with sanitization - SmilesParserParams params; + { + SmilesParserParams params; + m = SmilesToMol(smiles, params); + TEST_ASSERT(m); + TEST_ASSERT(m->getNumAtoms() == 6); + TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic()); + delete m; + } + { // no removeHs, with sanitization + SmilesParserParams params; params.removeHs = false; - m = SmilesToMol(smiles,params); - TEST_ASSERT(m); - TEST_ASSERT(m->getNumAtoms() == 7); - TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic()); - delete m; - } - { // removeHs, no sanitization + m = SmilesToMol(smiles, params); + TEST_ASSERT(m); + TEST_ASSERT(m->getNumAtoms() == 7); + TEST_ASSERT(m->getBondWithIdx(0)->getIsAromatic()); + delete m; + } + { // removeHs, no sanitization SmilesParserParams params; params.sanitize = false; m = SmilesToMol(smiles, params); @@ -3882,7 +3884,7 @@ void testSmilesParseParams() { TEST_ASSERT(!m->getBondWithIdx(0)->getIsAromatic()); delete m; } - { // no removeHs, no sanitization + { // no removeHs, no sanitization SmilesParserParams params; params.removeHs = false; params.sanitize = false; @@ -3894,49 +3896,52 @@ void testSmilesParseParams() { } } - { // basic name parsing + { // basic name parsing std::string smiles = "CCCC the_name"; ROMol *m = SmilesToMol(smiles); TEST_ASSERT(!m); - { // no removeHs, no sanitization + { // no removeHs, no sanitization SmilesParserParams params; m = SmilesToMol(smiles, params); TEST_ASSERT(!m); } - { // no removeHs, no sanitization - SmilesParserParams params; - params.parseName = true; - m = SmilesToMol(smiles, params); - TEST_ASSERT(m); - TEST_ASSERT(m->getNumAtoms() == 4); - TEST_ASSERT(m->hasProp(common_properties::_Name)); - TEST_ASSERT(m->getProp(common_properties::_Name)=="the_name"); - delete m; - } - } - { // name parsing2 - std::string smiles = "CCCC\tthe_name"; - { // no removeHs, no sanitization + { // no removeHs, no sanitization SmilesParserParams params; params.parseName = true; - RWMol *m = SmilesToMol(smiles, params); + m = SmilesToMol(smiles, params); TEST_ASSERT(m); TEST_ASSERT(m->getNumAtoms() == 4); TEST_ASSERT(m->hasProp(common_properties::_Name)); - TEST_ASSERT(m->getProp(common_properties::_Name) == "the_name"); + TEST_ASSERT(m->getProp(common_properties::_Name) == + "the_name"); delete m; } } - { // name parsing3 - std::string smiles = "CCCC\t the_name "; - { // no removeHs, no sanitization + { // name parsing2 + std::string smiles = "CCCC\tthe_name"; + { // no removeHs, no sanitization SmilesParserParams params; params.parseName = true; RWMol *m = SmilesToMol(smiles, params); TEST_ASSERT(m); TEST_ASSERT(m->getNumAtoms() == 4); TEST_ASSERT(m->hasProp(common_properties::_Name)); - TEST_ASSERT(m->getProp(common_properties::_Name) == "the_name"); + TEST_ASSERT(m->getProp(common_properties::_Name) == + "the_name"); + delete m; + } + } + { // name parsing3 + std::string smiles = "CCCC\t the_name "; + { // no removeHs, no sanitization + SmilesParserParams params; + params.parseName = true; + RWMol *m = SmilesToMol(smiles, params); + TEST_ASSERT(m); + TEST_ASSERT(m->getNumAtoms() == 4); + TEST_ASSERT(m->hasProp(common_properties::_Name)); + TEST_ASSERT(m->getProp(common_properties::_Name) == + "the_name"); delete m; } } diff --git a/Code/GraphMol/atomic_data.cpp b/Code/GraphMol/atomic_data.cpp index db5448a5d..115f41402 100644 --- a/Code/GraphMol/atomic_data.cpp +++ b/Code/GraphMol/atomic_data.cpp @@ -138,10 +138,18 @@ const std::string periodicTableAtomData = 111 Rg 1.21 0 1.7 281 2 281 281.16537 -1 \n \ 112 Cn 1.22 0 1.7 285 2 285 285.17411 -1 \n" // added from BODR 30.10.2016 - "113 Uut 1.36 0 1.7 285 2 285 284.17808 -1 \n \ -114 Fl 1.43 0 1.7 289 2 289 289.18728 -1 \n \ -115 Uup 1.62 0 1.7 289 2 289 288.19249 -1 \n \ -116 Lv 1.75 0 1.7 290 2 290 292.19979 -1 \n"; + // atomic mass data from NIST + // we leave Uut and Uup in here for backwards + // compatibility + "113 Nh 1.36 0 1.7 284 2 284 284.17873 -1 \n \ +113 Uut 1.36 0 1.7 284 2 284 284.17873 -1 \n \ +114 Fl 1.43 0 1.7 289 2 289 289.19042 -1 \n \ +115 Mc 1.62 0 1.7 288 2 288 288.19274 -1 \n \ +115 Uup 1.62 0 1.7 288 2 288 288.19274 -1 \n \ +116 Lv 1.75 0 1.7 293 2 293 293.20449 -1 \n \ +117 Ts 1.65 0 1.7 292 2 292 292.20746 -1 \n \ +118 Og 1.57 0 1.7 294 2 294 294.21392 -1 \n \ +"; atomicData::atomicData(const std::string &dataLine) { boost::char_separator spaceSep(" \t"); @@ -3278,57 +3286,62 @@ const std::string isotopesAtomData[] = { 110 Ds 279 279.15886 0 \n \ 110 Ds 280 280.1598 0 \n \ 110 Ds 281 281.16206 0 \n", - // from BODR 30.10.2016 - "111 Rg 272 272.15362 0 \n \ -111 Rg 273 273.15368 0 \n \ -111 Rg 274 274.15571 0 \n \ -111 Rg 275 275.15614 0 \n \ -111 Rg 276 276.15849 0 \n \ -111 Rg 277 277.15952 0 \n \ -111 Rg 278 278.1616 0 \n \ -111 Rg 279 279.16247 0 \n \ -111 Rg 280 280.16447 0 \n \ -111 Rg 281 281.16537 0 \n \ -111 Rg 282 282.16749 0 \n \ -111 Rg 283 283.16842 0 \n \ -112 Cn 277 277.16394 0 \n \ -112 Cn 278 278.16431 0 \n \ -112 Cn 279 279.16655 0 \n \ -112 Cn 280 280.16704 0 \n \ -112 Cn 281 281.16929 0 \n \ -112 Cn 282 282.16977 0 \n \ -112 Cn 283 283.17179 0 \n \ -112 Cn 284 284.17238 0 \n \ -112 Cn 285 285.17411 0 \n \ -113 Uut 283 283.17645 0 \n \ -113 Uut 284 284.17808 0 \n \ -113 Uut 285 285.17873 0 \n \ -113 Uut 286 286.18048 0 \n \ -113 Uut 287 287.18105 0 \n \ -113 Uut 283 283.17645 0 \n \ -113 Uut 284 284.17808 0 \n \ -113 Uut 285 285.17873 0 \n \ -113 Uut 286 286.18048 0 \n \ -113 Uut 287 287.18105 0 \n \ -114 Fl 285 285.1837 0 \n \ -114 Fl 286 286.18386 0 \n \ -114 Fl 287 287.1856 0 \n \ -114 Fl 288 288.18569 0 \n \ -114 Fl 289 289.18728 0 \n \ -115 Uup 287 287.19119 0 \n \ -115 Uup 288 288.19249 0 \n \ -115 Uup 289 289.19272 0 \n \ -115 Uup 290 290.19414 0 \n \ -115 Uup 291 291.19438 0 \n \ -115 Uup 287 287.19119 0 \n \ -115 Uup 288 288.19249 0 \n \ -115 Uup 289 289.19272 0 \n \ -115 Uup 290 290.19414 0 \n \ -115 Uup 291 291.19438 0 \n", - // from wikipedia 30.10.2016 - "116 Lv 290 290.19864 0 \n \ -116 Lv 291 291.20108 0 \n\ -116 Lv 292 292.20174 0 \n\ -116 Lv 293 293.20449 0 \n", + // from NIST + // https://www.nist.gov/pml/atomic-weights-and-isotopic-compositions-relative-atomic-masses + // 17.09.2017 + "111 Rg 272 272.15327 0 \n \ +111 Rg 273 273.15313 0 \n \ +111 Rg 274 274.15525 0 \n \ +111 Rg 275 275.15594 0 \n \ +111 Rg 276 276.15833 0 \n \ +111 Rg 277 277.15907 0 \n \ +111 Rg 278 278.16149 0 \n \ +111 Rg 279 279.16272 0 \n \ +111 Rg 280 280.16514 0 \n \ +111 Rg 281 281.16636 0 \n \ +111 Rg 282 282.16912 0 \n \ +111 Rg 283 283.17054 0 \n \ +112 Cn 276 276.16141 0 \n \ +112 Cn 277 277.16364 0 \n \ +112 Cn 278 278.16416 0 \n \ +112 Cn 279 279.16654 0 \n \ +112 Cn 280 280.16715 0 \n \ +112 Cn 281 281.16975 0 \n \ +112 Cn 282 282.17050 0 \n \ +112 Cn 283 283.17327 0 \n \ +112 Cn 284 284.17416 0 \n \ +112 Cn 285 285.17712 0 \n \ +113 Nh 278 278.17058 0 \n \ +113 Nh 279 279.17095 0 \n \ +113 Nh 280 280.17293 0 \n \ +113 Nh 281 281.17348 0 \n \ +113 Nh 282 282.17567 0 \n \ +113 Nh 283 283.17657 0 \n \ +113 Nh 284 284.17873 0 \n \ +113 Nh 285 285.17973 0 \n \ +113 Nh 286 286.18221 0 \n \ +113 Nh 287 287.18339 0 \n \ +114 Fl 285 285.18364 0 \n \ +114 Fl 286 286.18423 0 \n \ +114 Fl 287 287.18678 0 \n \ +114 Fl 288 288.18757 0 \n \ +114 Fl 289 289.19042 0 \n \ +115 Mc 287 287.19070 0 \n \ +115 Mc 288 288.19274 0 \n \ +115 Mc 289 289.19363 0 \n \ +115 Mc 290 290.19598 0 \n \ +115 Mc 291 291.19707 0 \n \ +116 Lv 289 289.19816 0 \n \ +116 Lv 290 290.19864 0 \n \ +116 Lv 291 291.20108 0 \n \ +116 Lv 292 292.20174 0 \n \ +116 Lv 293 293.20449 0 \n \ +117 Ts 291 291.20553 0 \n \ +117 Ts 292 292.20746 0 \n \ +117 Ts 293 293.20824 0 \n \ +117 Ts 294 294.21046 0 \n \ +118 Og 293 293.21356 0 \n \ +118 Og 294 294.21392 0 \n \ +118 Og 295 295.21624 0 \n", "EOS"}; } From fd3524f77ce05af3969ff3f53b85080bf1c7cf32 Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Sun, 17 Sep 2017 15:13:14 +0200 Subject: [PATCH 22/44] Optimization of the MaxMin diversity picker (#1574) * initial submission; needs review * minor * line endings * remove cache functionality since it's now redundant * add test data * add a test * changes from review --- Code/SimDivPickers/MaxMinPicker.h | 143 ++- Code/SimDivPickers/Wrap/MaxMinPicker.cpp | 94 +- Code/SimDivPickers/Wrap/testPickers.py | 19 + .../Wrap/test_data/chembl_cyps.head.fps | 1000 +++++++++++++++++ 4 files changed, 1153 insertions(+), 103 deletions(-) create mode 100644 Code/SimDivPickers/Wrap/test_data/chembl_cyps.head.fps diff --git a/Code/SimDivPickers/MaxMinPicker.h b/Code/SimDivPickers/MaxMinPicker.h index 7fcf2d6bd..d8f4ab6ee 100644 --- a/Code/SimDivPickers/MaxMinPicker.h +++ b/Code/SimDivPickers/MaxMinPicker.h @@ -1,5 +1,6 @@ // // Copyright (C) 2003-2007 Greg Landrum and Rational Discovery LLC +// Copyright (C) 2017 Greg Landrum and NextMove Software // // @@ All Rights Reserved @@ // This file is part of the RDKit. @@ -7,8 +8,8 @@ // which is included in the file license.txt, found at the root // of the RDKit source tree. // -#ifndef __RD_MAXMINPICKER_H__ -#define __RD_MAXMINPICKER_H__ +#ifndef RD_MAXMINPICKER_H +#define RD_MAXMINPICKER_H #include #include @@ -110,6 +111,7 @@ class MaxMinPicker : public DistPicker { unsigned int pickSize, RDKit::INT_VECT firstPicks, int seed = -1) const { CHECK_INVARIANT(distMat, "Invalid Distance Matrix"); + if (!poolSize) throw ValueErrorException("empty pool to pick from"); if (poolSize < pickSize) throw ValueErrorException("pickSize cannot be larger than the poolSize"); distmatFunctor functor(distMat); @@ -123,6 +125,13 @@ class MaxMinPicker : public DistPicker { return pick(distMat, poolSize, pickSize, iv); } }; + +struct MaxMinPickInfo { + double dist_bound; // distance to closest reference + unsigned int picks; // number of references considered + unsigned int next; // singly linked list of candidates +}; + // we implement this here in order to allow arbitrary functors without link // errors template @@ -130,74 +139,120 @@ RDKit::INT_VECT MaxMinPicker::lazyPick(T &func, unsigned int poolSize, unsigned int pickSize, RDKit::INT_VECT firstPicks, int seed) const { + if (!poolSize) throw ValueErrorException("empty pool to pick from"); + if (poolSize < pickSize) throw ValueErrorException("pickSize cannot be larger than the poolSize"); - RDKit::INT_LIST pool; - RDKit::INT_VECT picks; + + unsigned int memsize = (unsigned int)(poolSize * sizeof(MaxMinPickInfo)); + MaxMinPickInfo *pinfo = new MaxMinPickInfo[memsize]; + if (!pinfo) return picks; + memset(pinfo, 0, memsize); + picks.reserve(pickSize); - unsigned int pick = 0; - - // enter the pool into a list so that we can pick out of it easily - for (unsigned int i = 0; i < poolSize; i++) { - pool.push_back(i); - } - - // get a seeded random number generator: - typedef boost::mt19937 rng_type; - typedef boost::uniform_int<> distrib_type; - typedef boost::variate_generator source_type; - rng_type generator(42u); - distrib_type dist(0, poolSize-1); - source_type randomSource(generator, dist); - if (seed > 0) generator.seed(static_cast(seed)); + unsigned int picked = 0; // picks.size() + unsigned int pick; // pick the first entry - if (!firstPicks.size()) { + if (firstPicks.empty()) { + // get a seeded random number generator: + typedef boost::mt19937 rng_type; + typedef boost::uniform_int<> distrib_type; + typedef boost::variate_generator source_type; + rng_type generator(42u); + distrib_type dist(0, poolSize - 1); + source_type randomSource(generator, dist); + if (seed > 0) generator.seed(static_cast(seed)); + pick = randomSource(); // add the pick to the picks picks.push_back(pick); // and remove it from the pool - pool.remove(pick); + pinfo[pick].picks = 1; + picked = 1; + } else { for (RDKit::INT_VECT::const_iterator pIdx = firstPicks.begin(); pIdx != firstPicks.end(); ++pIdx) { pick = static_cast(*pIdx); - if (pick >= poolSize) + if (pick >= poolSize) { + delete[] pinfo; throw ValueErrorException("pick index was larger than the poolSize"); + } picks.push_back(pick); - pool.remove(pick); + pinfo[pick].picks = 1; + picked++; } } + + if (picked >= pickSize) { + delete[] pinfo; + return picks; + } + + unsigned int pool_list = 0; + unsigned int *prev = &pool_list; + // enter the pool into a list so that we can pick out of it easily + for (unsigned int i = 0; i < poolSize; i++) + if (pinfo[i].picks == 0) { + *prev = i; + prev = &pinfo[i].next; + } + *prev = 0; + + unsigned int poolIdx; + unsigned int pickIdx; + + // First pass initialize dist_bound + prev = &pool_list; + pickIdx = picks[0]; + do { + poolIdx = *prev; + pinfo[poolIdx].dist_bound = func(poolIdx, pickIdx); + pinfo[poolIdx].picks = 1; + prev = &pinfo[poolIdx].next; + } while (*prev != 0); + // now pick 1 compound at a time - while (picks.size() < pickSize) { + while (picked < pickSize) { + unsigned int *pick_prev = 0; double maxOFmin = -1.0; - RDKit::INT_LIST_I plri = pool.end(); - for (RDKit::INT_LIST_I pli = pool.begin(); pli != pool.end(); ++pli) { - unsigned int poolIdx = (*pli); - double minTOi = RDKit::MAX_DOUBLE; - for (RDKit::INT_VECT_CI pi = picks.begin(); pi != picks.end(); ++pi) { - unsigned int pickIdx = (*pi); - CHECK_INVARIANT(poolIdx != pickIdx, ""); - double dist = func(poolIdx, pickIdx); - if (dist <= minTOi) { - minTOi = dist; + prev = &pool_list; + do { + poolIdx = *prev; + double minTOi = pinfo[poolIdx].dist_bound; + if (minTOi > maxOFmin) { + unsigned int pi = pinfo[poolIdx].picks; + while (pi < picked) { + unsigned int picki = picks[pi]; + CHECK_INVARIANT(poolIdx != picki, "pool index != pick index"); + double dist = func(poolIdx, picki); + pi++; + if (dist <= minTOi) { + minTOi = dist; + if (minTOi <= maxOFmin) break; + } + } + pinfo[poolIdx].dist_bound = minTOi; + pinfo[poolIdx].picks = pi; + if (minTOi > maxOFmin) { + maxOFmin = minTOi; + pick_prev = prev; + pick = poolIdx; } } - if (minTOi > maxOFmin || - (RDKit::feq(minTOi, maxOFmin) && poolIdx < pick)) { - maxOFmin = minTOi; - pick = poolIdx; - plri = pli; - } - } + prev = &pinfo[poolIdx].next; + } while (*prev != 0); - // now add the new pick to picks and remove it from the pool + // now add the new pick to picks and remove it from the pool + *pick_prev = pinfo[pick].next; picks.push_back(pick); - CHECK_INVARIANT(plri != pool.end(), ""); - pool.erase(plri); + picked++; } + + delete[] pinfo; return picks; } }; diff --git a/Code/SimDivPickers/Wrap/MaxMinPicker.cpp b/Code/SimDivPickers/Wrap/MaxMinPicker.cpp index ff3514a61..50df5e201 100644 --- a/Code/SimDivPickers/Wrap/MaxMinPicker.cpp +++ b/Code/SimDivPickers/Wrap/MaxMinPicker.cpp @@ -1,6 +1,5 @@ -// $Id$ // -// Copyright (C) 2003-2008 Greg Landrum and Rational Discovery LLC +// Copyright (C) 2003-2017 Greg Landrum and Rational Discovery LLC // @@ All Rights Reserved @@ // This file is part of the RDKit. // The contents are covered by the terms of the BSD license @@ -57,79 +56,57 @@ RDKit::INT_VECT MaxMinPicks(MaxMinPicker *picker, python::object distMat, class pyobjFunctor { public: - pyobjFunctor(python::object obj, bool useCache) - : dp_obj(obj), dp_cache(NULL) { - if (useCache) - dp_cache = new std::map, double>(); - } - ~pyobjFunctor() { delete dp_cache; } + pyobjFunctor(python::object obj) : dp_obj(obj) {} + ~pyobjFunctor() {} double operator()(unsigned int i, unsigned int j) { - double res; - std::pair idxPair(i, j); - if (dp_cache && dp_cache->count(idxPair) > 0) { - res = (*dp_cache)[idxPair]; - } else { - res = python::extract(dp_obj(i, j)); - if (dp_cache) (*dp_cache)[idxPair] = res; - } - return res; + return python::extract(dp_obj(i, j)); } private: python::object dp_obj; - std::map, double> *dp_cache; }; RDKit::INT_VECT LazyMaxMinPicks(MaxMinPicker *picker, python::object distFunc, int poolSize, int pickSize, python::object firstPicks, int seed, - bool useCache) { + python::object useCache) { + if (useCache != python::object()) { + BOOST_LOG(rdWarningLog) << "the useCache argument is deprecated and ignored" + << std::endl; + } RDKit::INT_VECT firstPickVect; for (unsigned int i = 0; i < python::extract(firstPicks.attr("__len__")()); ++i) { firstPickVect.push_back(python::extract(firstPicks[i])); } RDKit::INT_VECT res; - pyobjFunctor functor(distFunc, useCache); + pyobjFunctor functor(distFunc); res = picker->lazyPick(functor, poolSize, pickSize, firstPickVect, seed); return res; } // NOTE: TANIMOTO and DICE provably return the same results for the diversity -// picking -// this is still here just in case we ever later want to support other +// picking this is still here just in case we ever later want to support other // methods. typedef enum { TANIMOTO = 1, DICE } DistanceMethod; template class pyBVFunctor { public: - pyBVFunctor(const std::vector &obj, DistanceMethod method, - bool useCache) - : d_obj(obj), d_method(method), dp_cache(NULL) { - if (useCache) - dp_cache = new std::map, double>(); - } - ~pyBVFunctor() { delete dp_cache; } + pyBVFunctor(const std::vector &obj, DistanceMethod method) + : d_obj(obj), d_method(method) {} + ~pyBVFunctor() {} double operator()(unsigned int i, unsigned int j) { double res = 0.0; - std::pair idxPair(i, j); - if (dp_cache && dp_cache->count(idxPair) > 0) { - res = (*dp_cache)[idxPair]; - } else { - switch (d_method) { - case TANIMOTO: - res = 1. - TanimotoSimilarity(*d_obj[i], *d_obj[j]); - break; - case DICE: - res = 1. - DiceSimilarity(*d_obj[i], *d_obj[j]); - break; - default: - throw_value_error("unsupported similarity value"); - } - if (dp_cache) { - (*dp_cache)[idxPair] = res; - } + switch (d_method) { + case TANIMOTO: + res = 1. - TanimotoSimilarity(*d_obj[i], *d_obj[j]); + break; + case DICE: + res = 1. - DiceSimilarity(*d_obj[i], *d_obj[j]); + break; + default: + throw_value_error("unsupported similarity value"); } return res; } @@ -137,18 +114,21 @@ class pyBVFunctor { private: const std::vector &d_obj; DistanceMethod d_method; - std::map, double> *dp_cache; }; RDKit::INT_VECT LazyVectorMaxMinPicks(MaxMinPicker *picker, python::object objs, int poolSize, int pickSize, python::object firstPicks, int seed, - bool useCache) { + python::object useCache) { + if (useCache != python::object()) { + BOOST_LOG(rdWarningLog) << "the useCache argument is deprecated and ignored" + << std::endl; + } std::vector bvs(poolSize); for (int i = 0; i < poolSize; ++i) { bvs[i] = python::extract(objs[i]); } - pyBVFunctor functor(bvs, TANIMOTO, useCache); + pyBVFunctor functor(bvs, TANIMOTO); RDKit::INT_VECT firstPickVect; for (unsigned int i = 0; i < python::extract(firstPicks.attr("__len__")()); ++i) { @@ -187,7 +167,8 @@ struct MaxMin_wrap { (python::arg("self"), python::arg("distFunc"), python::arg("poolSize"), python::arg("pickSize"), python::arg("firstPicks") = python::tuple(), - python::arg("seed") = -1, python::arg("useCache") = true), + python::arg("seed") = -1, + python::arg("useCache") = python::object()), "Pick a subset of items from a pool of items using the MaxMin " "Algorithm\n" "Ashton, M. et. al., Quant. Struct.-Act. Relat., 21 (2002), " @@ -205,14 +186,13 @@ struct MaxMin_wrap { " - firstPicks: (optional) the first items to be picked (seeds " "the list)\n" " - seed: (optional) seed for the random number generator\n" - " - useCache: (optional) toggles use of a cache for the distance " - "calculation\n" - " This trades memory usage for speed.\n") + " - useCache: IGNORED\n") .def("LazyBitVectorPick", RDPickers::LazyVectorMaxMinPicks, (python::arg("self"), python::arg("objects"), python::arg("poolSize"), python::arg("pickSize"), python::arg("firstPicks") = python::tuple(), - python::arg("seed") = -1, python::arg("useCache") = true), + python::arg("seed") = -1, + python::arg("useCache") = python::object()), "Pick a subset of items from a pool of bit vectors using the " "MaxMin Algorithm\n" "Ashton, M. et. al., Quant. Struct.-Act. Relat., 21 (2002), " @@ -225,11 +205,7 @@ struct MaxMin_wrap { " - firstPicks: (optional) the first items to be picked (seeds " "the list)\n" " - seed: (optional) seed for the random number generator\n" - " - useCache: (optional) toggles use of a cache for the distance " - "calculation\n" - " This trades memory usage for speed.\n" - - ); + " - useCache: IGNORED.\n"); }; }; diff --git a/Code/SimDivPickers/Wrap/testPickers.py b/Code/SimDivPickers/Wrap/testPickers.py index 57608b65c..5b5a6939a 100755 --- a/Code/SimDivPickers/Wrap/testPickers.py +++ b/Code/SimDivPickers/Wrap/testPickers.py @@ -222,6 +222,25 @@ class TestCase(unittest.TestCase): self.assertEqual(len(mm2), N) self.assertEqual(list(mm1), list(mm2)) + def testBitVectorMaxMin3(self): + fname = os.path.join(RDConfig.RDBaseDir, 'Code', 'SimDivPickers', 'Wrap', 'test_data', + 'chembl_cyps.head.fps') + fps = [] + with open(fname) as infil: + for line in infil: + fp = DataStructs.CreateFromFPSText(line.strip()) + fps.append(fp) + mmp =rdSimDivPickers.MaxMinPicker() + ids=list(mmp.LazyBitVectorPick(fps,len(fps),20)) + self.assertEqual(ids,[374,720,690,339,875,842,404,725,120,385,115,868,630,\ + 881,516,497,412,718,869,407]) + + ids=list(mmp.LazyBitVectorPick(fps,len(fps),20,firstPicks=[374,720,690,339,875])) + self.assertEqual(ids,[374,720,690,339,875,842,404,725,120,385,115,868,630,\ + 881,516,497,412,718,869,407]) + + + if __name__ == '__main__': unittest.main() diff --git a/Code/SimDivPickers/Wrap/test_data/chembl_cyps.head.fps b/Code/SimDivPickers/Wrap/test_data/chembl_cyps.head.fps new file mode 100644 index 000000000..12bb5fade --- /dev/null +++ b/Code/SimDivPickers/Wrap/test_data/chembl_cyps.head.fps @@ -0,0 +1,1000 @@ +00000000000000000000010000000000000000000000000000000000400000000000000020000000000000000000000020000000000000000000000000040200000000000000000000000000000400000004000000000008000000000080000000000100800000000000000000080000000000408040000000000000000000000080000010040000010000000000000000040000008000004000000000000000010000000000000000000000100200000000000000000000008100000100000000000000000000000000000000000000400008000000000000004204200800800000000000000000000002000000002000010000000000000200000200000000 +000000000000000000000004000000000000000000000080000000000000000000000000000000000000000000000004000000000000000000000000000a0000000000000000000000080000000020000004000000000008100400000000000000002204800000000008000000080201010000000000000002000000000000000000000022000000000200000000000021090000000000002004000000000000000000000000000000208000100200000400000000100000000000000000100000000000000000000000000000002000400000000200000000004000000000000000040000000000000002000000002000010000001000000000000000000000 +00000000000000000000010000000000000000400000000000000000002000000000000040004000000000000000480408000000000000000000000240000000004000000010000000800000000000000004000000208004000000000000000000000004800000000000000000080000000000408000200000000000000001581800000002000000010200000000000201000000008000000000500002000000000800000020000000200000100200000000000020100000000000000000000000000000000000000002000000000080000000000210000020044000000000000000000000000000000002040000802000000000100000000000010001000000 +00200000000000000000010000000000000000400000000020000000002002800002000040004000000000000000400400000000000000020000000040000000004000000000000000000000000000000004010000008004000000000400000000000000802000000002000000080000000000408000000000000000002001008008000002000000000200000000000201000000000000000000400000000000000800000000000020200000100200000000000000100000000000000004000000000000200000000002000000800080000000000200000020004004000008000001000000000000800002000000022000000000100000000000000000000000 +0000000001020000000001140000100000000000000000804000200000000000000000000000400004002000400200040000000000000000000000000000000000000000000010000001000000000000000400000400800000400000000000000020400080000080000a000000000000200000400000000000000000000000001000000002002000400000000000010001000000000000000000000000000200000000000000000000000000108100000000000000800000000000000400000001000000000000000000000000000000000000000000000400044000000000000000000100000080000102000000002000000000800000000000000000000000 +00000000000000000400010000000000000000000000000022000020000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000024010800000200000000000040000000000000800000000000000000000000000000408000400000000000000000080000000000000000010000000000000201000000008000000000000000000000000000000000000000000050100000200000000002000000000700000000000000000000000000000010000000800000000000000000000000004000000000800004000000800002000012100000822008000000000000000000000000000000 +04000000000000000000000002000000000000000000000000000000000000000000000100000000000000000000000000000000000400000000000000000000000000001010000020004000000000000000000004000000004020000000000010000000004000000000000000080000000000408000000100010000000000001080000010000040010000000000000000040000800000000000000000080000000000000000000000000400100000000000000000000000000100000000000000000000000000000000000040000000000000000000000000004000000000000000000000000040000082000000000000000400000000000040000000000000 +00000000000002000000010200000000000000000000000000000000000000000000000000000202000000000000000420000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000400000000000000000000000000000000080040000010000040000000000000000008000000000000000000000000000000000000000000000100000000000400000000000000010000000000800000000000000000000000000000000000000000000000100004004000000000000000000000000100402000001000000000000000000000000000000000000 +10000000000000000004010000000400000000000000000000200040000000000000000000000000000000000000000000200000000000000000000200000000000000000000000000100000000000000020000008000000000000000001000000000000900200000000000000080000000020408000200000000000000000000000000000000000012000000000000200800000008000000200000004100000008000000000000000000000100000000002000000200040000500000000040000000000000002000000000000800000020000000000000000004000000000800000000000000000000002000000800000010000000000000000000000000010 +000000020000800000000110000000000000000000040100000000000200000000000000000000000400000080000004200000000088000400000000000000000010001000080800000000000400000000000100000080000040200000000000002000008000008000020000000800000000004080000000000000001000000a1000000002000008030000000804050200000000008000000000000000000080008000010000000000000800108011000000404000000000000100000000000001000010000400000000000000000080000000000000000c00044000000010000000000000000090000002000000000002000010000000001000000000010000 +004000000000000000000000000080000000000000000000000000000000020004000000020000000000800000000084a0000000000000000000100040000000000080000000000000000800000000000004000008004000020000002000000000000000800000000000000000000000000000008400000000000000000000000000000000000000010200840000000001000000008000000000010000000000000000000000020000000000100200000000000000000000100000000000000000000080001000000000000000000000020000000000000000004600000080000000000000000080000002000000002000000000080000000200000000000000 +00000000000000100000010000008000000000000000008000000000000000000000000000000000040100400010000400000002000000000000001000000000000010000000000000000000000000200004000800009080004000000101000000200800400000000002000000080000000000000000000000000000000000000080000002000000010800040000000081010000000000000000002800004000000000000000000020200000100200100001000000100000100000000000000001000000400000100018000000000000000000000000000000004001000000000000000000000080000482000000000000000a00400010100000000100000000 +00000000000000000000010000001400000000010000008100000000000000000000000000010000000020000000000400000000000000000080000040008000000000002000000000040000000000000004000000000000000000000000000400000000800200000008010000180000000000008000000000000000000000000080000003040000010002000000000201010000000000000400000000100002000000010100000000000001108000000002000000200001000000000000040000000000000000000000000000000000000000080000000400004004040000000000000100000000000002000000002000010000100000040000000002000000 +00200000000000100000010000008000000000000000000000000000000000000000000040000000040100000010000000000000000000000000001000000000000000000000000000800000000000000000000000008000004000000000000000000004400000000000000000080000000000000000000000002000000000000004000002000000000000040000800000000900000000000000000802000000000000000000000020300000100000000000000010100000000000200000000000000000000000000000000000000000000000000000000000004001000000000000000000000100000082000000800000000a00000000000000000000000000 +02000000000000000080010000008000000000000000000000000000000000000000000800000000000100000010002000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000002000000000400c000000000000000000c0000000000000000000000000000008000000000000002000000000000040000000000000800000000000000000000000000000000000200000020200000100000000800000000000000000000000000000000000000000000000400000000000000000000000000000000004001000000000000000000000000000082000000000000000a00000004000000000000000000 +00000000082000000000004000000000001000000000000000000000000000020000000002000002000000002000000420000000001000000000000000000000000000000000100000000000000020000000000004008000008000000000000000004000880000000002000000080000000000008000000400000000000000000000000002000000010200000000000280000000008000000000002000000000200000000000000000004000100300000000000000000000000000000000000001000000000000000000000000000000000000000200008000004000000000000000000000000088000002000002000000000000000004200000000000000000 +00000400000000000000000000000000000000000000000000000001000000000000000000000080000004400000400420008000040000000110000000040000000000080000008000020004000000200004000000000000000000000000200000000000050000000000000000000000000000408000000000000000000000001000000010020000010000000000000000040000008000000000000000010000000000000000000000000000100000000000000000100000100100000000000000000000000000000100000000000000000000000000000000004200000000000000000000000002000402000000000000000000000000000000000000000000 +02000000000000000000010000004000000000000002000000000000080000000000000800000000000000000000000000000000004000000000000000000000000000000000000000000040000000000000040000008000000000000000000000400000800000000000000000000000000000000000000000000000000000001080000002000080010001010000000001000000008000000000000000000000000000000000000000220000100000000400000000100000000000000000000000000000600000000000000000000000000000000000000000004000000000000000000000000080000002000000040000000000000004000000000000404000 +00000000000000000800010000001000000000000000000060000000000000000000040000000000000000022000000400000000000000000000000000000000000000200000000000000000000000000800000804000000000020810400220000004000800000000000000000000000000000000000000200000000000000080000000002000000000000000000000001010040000000000000000000000000000000000400000000000090100100000010400000000000000000000800000000000000000000000000000000000000000000000000000400000000400000000000000000000000000002000004000000000020000000021000000000000002 +00000000000000000000000000800000001000000000000000000000000800000800000000000040000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000400010000020000000000000000400800000000000000000480000040000c00000000000400000000020080000010002000000000001000000000001000800000000000000000000000000000000000020000000000000108000000000000000080000000000000000000000000000000000000000000000000000000000080000100400004000000000000000008000000000000002000000000000000000004000008000000000000000 +00000000000000000000011000000000000000000000000000000001002280000000000040000000080000000000000400000200008000000000000000000000000000000000020000000000000000000000000000008000000000000000000000000010000001000000000000000000000000048000000000000000000000000000000002400000000000000000000000100000000000000000400000000000000000100000000000000000100000000000400001100000000000000000000000000000000000000000000001000000000008000000001400004000400000000000000402000010000002000000000000000080100000000100000000000000 +00000000000000000000011400000000000000400400000020000000000000820001000000004000000000000000200400000000080000000000000040000000000400000000000000000000000000000004000008008008000000000020000000000000802000000002000000080000000000008000000000000000000000000000000102000000010000000900000001000000008000400000000000000000000000000000000820200000100000000400000000000000000000000000000001000000000200200000000000000020400008000000000400004004200000000010000040000000000002000000002000110000100004000000000000000000 +00000000000000000000010040000000000000000000000000000040000000000000000000000000040000800000000020000000000000000000000000000000000000000000000000000000000000000014000040008000004000010800000000000000840000000000000000000000002000408000000000000000000002081000000000000000010000000000000060000000008000000000000000000080000000000020000000000000100000000000000000100000000100000000000000000000000000000000008000000280000000000000000000004000000000000001000000000000000002800000002000000000000000000000110200000000 +00000000000000000000000000000000000000000000000000000008000000000200000000000000000000000000000400100000000020000000000000000000008000000000000000000000000000000000000000000000000000000100000000000800000000000208000000000000000000009000000000000000800000000000080000000000012000000000000080010000000000000000000000000000000000000000000000000000100200002000000000100000000000000000008000000000000004000808000000004000000000000000000000004000000000008000000000000080000403000000000010000000000000000000000000000000 +00000400000000000000000000000000000000000000000000000001000000000000000000000000000000000000008420008000000000000000000000040200000000000000000000000004000000000004000000000000000000000080000000000000800000000000000000000000000000408040000000000000000000000000000210000000010000000000000000040000008000010000000000000000000000000000000000000000100200201000000000000000000100008100000000000000000000000800000000000000000000000000000000004200000000000000000002000000000402000000002000000000000000000000000200000000 +0000000200000000000001400000000000000000000000040000040000280000000000004000008000008050000000000000000000020001000000000000000000000000000000000000000000000000000400000000c000000820000008000000000000800000000000000001080000000000000000000080000000000000000000000002010000000000000000000008000000000000000000400000000000000000000000000000000000100000000000000000100000100000000000000000000000000000000000000000000000000000000000100400004000004000000000008010000000000002000000000801000000000004000000000000000200 +0000000000200000800003000000008000000000000000000000000000000000000000004200000000000000210000040000000000000000000000000000000000000080000000000080000000000000000000000000000000000000000000100000000c000000000000000000001000000000008020000000000001000000000100000012000000010200040000002000000000008000000000000000000004200000000000000000000000100000000000000000000040000000000000000000000000000000000000000000000000000000202000000400004000000000000000000000000090000002002000800000000000000000400000000000000000 +002000000000000000000100000000000800000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000002200000000000000000000000000000240000020080000000000008000000000000408000000000000000200000100000004080000000000000000000000a0008000002010000000000004000000200000000080000000000400000200000000000200020000000000000000000000000000000000000000110000000000004000000000000000000000000000000000000000000000000000000000002800000000000000000080000000000002000000000000000000001000000000000 +000000000000000000000000000000020000000020000000000000010000000100000000000000000000000001400004000000000000000000000004000010000000000000000a0000000000002000000004010008010000000000020000000000000800800001000000800000080000000000408040000000000000000000000000000000041000010000000000000000000000000000020000020000000000000000000000000000000000100000000000200000000000000100000100000040000000000020000000004001000000000008000000000000004004000000000000000000000000000002000000002040000000000000080000000200000000 +000000000002000000000100000000000000000000000000200000010000000100000000000000a0000000400002000020000000000004000000000000004000000000000000060000002000000000000004010800008000000800000000000000000000840021100400000000000a00000000400000400000000400000000081000200000440000010000000000000001000000408000000000400800000000000000000020000000000000108000000000002001000010100000020800000002000000000000000000000400000000000008000000000000044004000000000000000000000000000002000000002000000000000000000080000000000000 +02010000000000000000000400002000000000000000008501080000000020000000000900000000040000000000020020000000008000000000000000000000000000000000002000004000000000000004000080008008004000000000000000000000800000000008000000080000000000400000000000000000000000080000000012020080010000000000000001000000008000400000000080000004000000000480000000002000100000000400000040000000000000000000000000000000002000000000000000000000410008000000000002004040008000000000000100000080000002000000002000010000000000002000000000000000 +02000000000000000000010400008000000000000000000000000040002000000000000000000000000100000010000000000000000000000000001004000000000000000080000000000000000000000000000000800000000000000800000000000000c00000000000000000000000000000008000000000000000000000000000000000000000010000040001000000000000008020000000000800000000000000000000100020200000100000000000000000000000000000000000000000000000200000008000000000400000000000000000000000004000000080000000000000000000000082000000000000000200000000000000000000000000 +00600000000000000000010000000000000001000000000010000000200002000000000000000000000000000000008018001000000000000000000040000000000000000000000000000000000000000000010008008000000420002000000000000000800000020002000000000000000000408000000000000000002000081000000082000000410000000000000001000000000000000000000000010001001000000020000000000000100000020000000000000000002000000000040000000080000000000000000014000000000000000000000010004100200000000000000000000000000002000000c00008000000000000000002100000000002 +10000000000000000010010000000000000000000000008000000000000000000000000000004084000000400040000020000000000000000000010000004000000000000000028000000000000000000004000400000000000000008001000000000000000000000008000000080800000000208000c00000000000000000000000000000000000010000000000200001000000008000000000000000004000000000000000100000000000100000040000000000800000900000000000000000000400000000000000000000000000000008000000000000004004200000800000000000000000000002000000000000000000000000000000000000000000 +000000000000000000000100000004000000000000000080000000000000000000000000c00000000000000000000004000100000000208000000000000000000000000000000008000000000000800100000000040008c0010020000000000000004000800000000000000000000000000000000000200000000000010000000000080002010000010000000000000001010000000000040000000000000000000000000000000000000000100100000000000000000000000000000000008000000000000004000800000000000000000000000000000000004000000000000000001100000000000402100000000000000000000000000000000000000000 +002000000000000000000100080004000000000000000000000000000000000000000000000000c000000000000002042001000000000000010000000000000000000000000000800000000000000000001400400000a000000000000000000000000000880000000000000000000200000000000000000000000000000000000000000002000000010000000000000008080000008000000000000000010000800004000000000000000000100000000002000000100000000000000000000000000010000000000000000000000000000000000000000800024000000000000000000000000000000402000000002000000080000000000000000002000400 +00000000000000000000010000000000000008000000000000000000000000000000000040000080000000400000000020000000000000000000000000000008000400000000008000000000000000000006000000008000000000000000000000000100800000000200000000000000000001408000000000000000000080000000000012040000010000000040000000040000008000000000400000000000010000000000000000000000100000000000000000000000100900000000000000000000000000000000000000000000000008000000002400004004200800800000000000000000000002000000002000000000000000000000000000000000 +00000000040000000000014000000000000000000000000020000000000800020010000040000080000000400000000000400000000000400000000040000000000000000000000000000000000000000004000000008000000800000000000000000000800000000202000000080000000000408000000000000000040000081000000002000000000000000000000001000800002000000000000000000000000000002020000000008000100000000000000000000000100100000000000001000100100000009000000000000000000000001000040000004000040000000000000000000000000002000000002100000000000004008000000040000000 +0000000000000000000000400000000000100000000000800000000000028002080008020000020000000000000000040000000000000000000000044000000000000000000000000000000000200000000401000000800000000000000000000000080080000000002a000000080000010000008000000000000000000010000000020002042000010000000000000001010080000000000000022000000000000000000000000000000000100000000000000001000000000000000000008001000000000000000000000000000000000000100000000000004004000080000010000102000010000002000000002040000000000004040000000000000000 +00000000000200000000010000000000000000000000008000000000000000000000000000000000000000000000000020000020000000000100000000000000000000004000000000000000000000000004000004000080000000000000000000000000800000000000000000000000200008000000000000400000000000000000000000002000010000000000000001000000008000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000012000000000000000000000000000000000000400000004000000000000000000100000000000002000000802000000000000800000000000000000000 +00000000000200000000010000008000000000000000000020000000000000000000000040000000000000000000000020000000000000000000000000000000000800000000000000802000000000000004000800000000000000000000000000000004800000100000400000000000000000000000000000000000000000000000000082040000010000040000000001000000008000000000000800000000000009000000000000200000100000000000401000000000000000000000000000000010200020000000000000000000000000000000400000004204000082000000000000000000000002000000802000000000000500000000001000000400 +00000000000400000000110000000000000001000000000000004000a00000000000002040000000000000010002000000000000000000000000000840000000000000000001000000800000000000000004000008000080000420000002000000000004800000000008000000000000000020400040000000000000200000080000000002000000000000000000001001000000000000000000000000000000000004200020000000000000100000000000000000000000002400000000800000000080000000000000000000000000000000000000000010040100000000000000000002000000000002000000802000000000000000008000100000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000220000000000000020000000000000000000000000000000000000000000000000004010000004000001820000400020000000000000000004000000001080100000000400000001002000000000800000000000000000040010000000000000000000000008800000000000000000000000000000000000060000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000004000000000000001000001000040800002002000020000000000000800000000000000000000 +00000000002000000004010400008000000000000000000000000000000000000000000000000004000000000000000000000800004000000000000000000000000000000000000000000000000000000004000000000008000000000000400000000000800000000000000000001000000000408000000000000008000000080000000004000008010004040000000200000000008000000000000000001000200000000020010000000000100200000400000000080000000100400000000000000010000008000000040000000000400000200200000000004200000080000000000000000100000002000000802000010000000008000004000000140120 +000000000100000000000000000000020000000020000000001000014000000000000000000000000000000000000004200000100001000000000004000000040000000000000200000000000000000000000100000000000000000000000000000008000000010000000000000800000000000080000000120000000000000000000000000000000102000000000000020008000000000000000a0000000000000000000000000000200000100200000000000000000200000000000000000000000000000000000000000000002000000008000100000000004000000002000020000000000080000002000000000840000000100000000000000000000000 +00020000000000000000010000000000000000000000000000900000000000002000000000000000000000000000000400000000000000000000010000000000000000000000000000000000000000000004001000000002000800000000020002000000000000004000000000080000010000009000000000001000000000000000000002000000000000000000000000010000000800000000000000000004000000000000000000000020108000100000000000100000000000000000000000000000000000000000000000000000000000000000000400004000200000000000428000000001000002000000000000000000020808000000000000000400 +02400000000200000008010000000000000000000400000000000000000000080008000000008000000000000000000422000000000000000000000000000000000000000000000000000000000000000004000008008000000000000002000000000000808000000002000000000000000000000000000000000000002000000000000003000000010000000000000001100000008000000000000000000000000400000000000000002000100000000000000000000000000000000000000000800001002400000000000000000004000000000008000000004080000000000000000100000000000002000000002000000000000000000000000000000000 +02000000000000000000004000002000000000000000000000000001800200000000000800000004000000000040000000000000000000000000020000000000040000000000020000000000000000000004000000000208000000000800000000000040800000000000000000080000080000408000000100400000000000081000000002000000000000000000020001000000000000000000000000000000000000008000000000000000100000100000000000000200000001000000000000000000000000400000000000040000000008000000000000004000000000000000000002000100000002000000002000010000000010000000000000000000 +0000000004200000000001000000800040000000000000000000000000000000000000004000000400000000004000000000000000000000000000000000000000000000000002008000200000000000800400000000000000000000000040000000000004000000000004000008000000000000800000000000000800000000000000000204000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000040000000000000000000000000000000a000000000000000200000000000000000000000000000002000000000000000000000000000000000000000000 +80880000002000000000100000000004000000004000400000000000000000000000000002000000000000002000000400000041000000020000010000000021800002000008000000000000004000000000000804000000000000000000000000004010800000000000000000000000000000408010000000000000000000080000000012000000810a00100800000004040000008000000800100000000004200000000020000000000000101100000000001001000000000000020000000800000000000000000000000000000000000001000000000000044000002000000000000000000080000002500000000000000000200002000000000000000000 +000000000000000000000500000000000000000000080000000000000002000000000000000006040c8000000000000420008000000000000000800000000001000000000080040000000000000000000004000000008000000000000101000000200000140000000002000000080000000000408000000000000000000000000081020002040000010200040000000000010000008000000000000000010000000000500000000000000000100000000000000000100000000100000010008001000000000000000000000000000000100000040100000004004004200010000000000000000080000002000000000000000000000010000000000010000000 +00000000000000000000010040000000000000000000000000000000000000820000000000400200000000000100000400000000000000000000000000020000000400000000000000000000000000000000000004008000100000000100000000004000000004040002000000080000000000002000000000000000000000000080000002000000010000000000010001010000008000000000000000000000000080000000000028008000100100000401000000100000000200000000008001000000000000200800000000000020000000000000000040004000000800000000000000000000000002000000000000000000000084000000000000200000 +01000000000000000000010000081000000000400000000400000000000004000200000002000004000020000000000420000000000000000000000000000001000000000000000000200000000000008004000000000000000000000008000000000008800000000000000000000000000000008000000000000000000000000000000200000000010200000000000100100000108000000000000000000000000000000000000080200000100000000000000001000000000000000200000000000000200000000000000000008000000000000000000000004000000080000000000002000010000002000000000080000000000000000000000000000000 +10000000000020000000010000001000000000000000000000020000000000000000000002000000000000000000000000240000000000000000000040000000000000001000040000100000000000000000000008000000800000000001000000000000000800000100000000080004000020408000200000000000000000081000000002000000012000000000000200800000008000000000000080000000008000000020000008008000100000000000000000000000000100000002000000000100000002000000000000800000000000000000000800004000000000000000000000000000000002000000000000000000000000000040000000000010 +000000020000000000000100000000000000000000000000000000002000000000000000400000400001000400000004000000000000000200000000000008000000000000000000000000000000020000000100000040000000200004000000000000000800000000000000010800800000004080000000000000000000000000080000020000000000000002000000081000000000000000000000008000000002000000000000200000001000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000040000000200080c1000000000000900002000000020000000000000000000000000000000200 +02000000200000000000011000001000000000000000000000000000000000400000000040000004000000000002000420000000000020000000000000000000000200000000002000000000000000000004000004000000000000008008000000084000840000000000040000090000000000008000000800020000000000000000200042040000010000000000090201000800008200000001000800000000200000000000000000000200100100000000000000000200000000000800000000010000400000000000000000000000000000000100000000004004000000004000000100000080600002000000002000000000000000000000000000000000 +02000000000004000000010000000000000000000000000000000000400080000000000820000000000000000000000000000000000000000000000000040200000000000000000000000004000400200004400000000008000000000080000000000000840000000000000000080000000000408040000000000000000000001080000012000000010000000000000000040000000000000000000000000000400000000000000000000000100200000040000000000000008100000100000008000000000000000000000000000000400000000000000000004200000000800000000000008000000002000000002004010000000000000200000200000000 +00000000000200000080010000000002000000000000000020000000000000030000000000000000040000000000000400000000400000000000000000000000000000000000000010002000000000080004010808008000004010000000000000200000800000900002000002180000010000400000000000000000000000000000000002000000000000000000000001010000000000000000000800000000000000000000000020000000180000000000000000000000000000000000000041000010000020000000000000000000000000000000400000204000000000000000000000000000000002100000802000000000000014000000000100000000 +00002000000000000000010000004000000000000000000000000000000000000000000000000000000000000100000000000200000000000000000000000000000000000800000000000000000000000010000000006000000000000000000004100001000000000000000000000200000000000000000000000001002000000000000002000000010000000100000000080000008000000000000000000000000000000000000000000080100000000000000000010000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000002800000000001000080000000000000000000000000 +00100000000000000000010000000000000000000000000000000000000000820000000000000000000000000100000400000000000020000000000000000000000000000000000000000000000000002000000000008000400000000000000000000800000000000002000000000000000000000000000000000001000000000000080002040000010800000000000001000000008000000000000000000000000000000000000000000000100200100401000000100000000000000000008001000000400004100808000000000000000000200000000000004004000000000000800000000080000402000000000000010000000004000000100000000000 +00000000000000040000010400000000000000000000000000000000000000000000000002000000040000000000000420000000000000000000080000000000000800001000040000000000000000000000010800008000100400000100000000200000000000000002000000080000000000408000400000000000000000000080000002000000010200000000000201010000008000000000002000000000000040000000000000200000100200200001008002000000000500000000000001000000200000000000000000000000000000000000100000004000000002800000000000000082000002000000000000000000000010000000000000000000 +00200000000200000000010000000400000000000000000020000000000000004000000000000000040000000000000000000000080000000000000000000000000000000000040000000000040000000004000000008000000000000000000000020000800200000000000000080000000008000000000000000000000020000084008002000000010000000000000001000000008000000001000000000000000000000000000000000000500000000000000000300000000000200000000000000010000000200000000000000000000000000100400400004000000000000000008100000000000002000000802000010010000000000000000000000000 +00010000000200000000010000000000000000000000000020000000000000820002000400004000002000000008000000000000001200020000000040000000000000000000000000000000000000000004010800008000000000000400000000000000800000000002000000080000000000400000000000000000000000000008000002000000000000000000000001000000000000000000000000000000000000000000000020000000100200000000000000000000000000000004000001000018200020800000000000800000000000000000000000004004000008000001000000000000800002001000022000000000000004000000000000000000 +00000000000000000000014200000c0000000000000000000000004000200080000000004000400000000000000000000001000800020000000000400000000000000000000000000000000000008000000000000080c00000000000000800000000000080000000000000000008000000000000081000000000000000000000080000000200000000000000000002000100010000000000000040000000000000000000000000000000400010000000000000000010000000000000000000000c00000000000000000000000020000000000000000000000000400400000c000000000000000000000002000000000000000000080004000000000000000000 +00000000000000000000000800000000000200000000000000080000000000000000000000000000400090000800000000000000000000000200000000000000000000000000000000000000000000000820000000000000000020010000000000000000800000001280000000080000000000000000000000000000000000020000000002000000010000000000000000000000008000000000000000000000000000000000000000200000100200000000000000000000000000000000000000000000200000000000008000000000000000000200000000004008000000000000000000000080000002000000000000000000000000000000000000000000 +00000000000000000000010000000000000000000000008000000000000000000000000000000000000000000008008400000000000000000000000040000000004000000001000000000000000000000014000000002000000000000000000000000000800000000008000000080200010000000000040000000000000000000000000002002000000100000000000001090000000000010000000800000000000000000000000020000000100200000000000000000000080000000000800002000000000000008c00000000000000000000000200000000024000000000000800000100000000000402000000802000000080001000040000000000000000 +000000000000000000000100000000000000000000000000410000000000000000000000008000a0000000400040000000000000000000000000000000004000000000000000020000000100000000000004000800000000000800100000000000000000000000001000000000080000000000000000000000402000000000000080000000000084010000000000000001000800000000000000000000000000000000000000400000200000100000000000000000000000100000000020000000000000000000000000000400000000000008000000000020004000000000000000000000000180000002400000800000000000000000000000000000000000 +00100000000000000000010000000000000000000000000000000000000000820000000000000000040000000140000400000000000000000000000000020000000400000000020000000000000000080000000000018000004000000000000000200000000000000002000000180000000000000000000000401001000000000000000002000000010801000000000001000000008000000010000000000000000000001000000020100000100000000001000000100000000200000000000001000000000000000000000000400000000008080000000000204000000000000000040000000000000002000000000000000000000014000000000000000000 +00000000000000040000010400000000000000000001000000000000000000000000000002000000000000000000000420000000000000000000080000000000000800001000000000000000000000000000010800000000100400000200000000000000000000000000000000000200010000408000400001000000000000000000000002000000010300000000000201090000008000000000000000000000000040000000000000200000180200200001008002000000000500000000000000000000200000000000000000000000000000001000100000004000000000800000000000000082000002000000000000000000000000000000000000000000 +0200000000000000000001000000400000000000000200000000000008000000000000080000000000000000000000000000000000400000000000000000000000000000000000000000004000800000000004000000c000000000000000000000400000800000000000000000000000000000000010000000000000000000001000000002000000010000000000000001000000008000000000000002000000000000000000000020024000100000000400000000180000000000000000000000000000400000200000000000210000000000000000000000004000000000000000000000000000000002000004000000000000000004000000000000404000 +00400000000000000000010400000000000000000000008010000000000002800000000002000000000000400000008420000002000000000000080000000000000000001000000000000000000000000004010008001080100000000101000040000000000000000000000000080000000000002000000000000000000000000080000002000000010200000000000001010000008000000000002000014000000040000000000000200000100200000001000000000000100000000000000000000080200000800010000000000000000000000000100000004000000000000000000000000080000002000000000000000000400000100000000000000000 +0000000000000000000001000000000000000000000100000000000000000000080000000200000000000000000000042000000000000000000004040000000800000000000000020008000000000000000401000000000000000000000000000000280080000000000000000000020001000000000000000000000000000000000000002200000001220000000000000009000000800000200002000000000000004000000000000020000010060000000000000000800400000000004000000000000020000000000000000000200000000000020010000000400000000000000000000000008000000a000002002040400000000000000000000000000000 +00000000000000040000010000000000000000000000000000000000000200000000000000000000100000000000000100000000000000000000000000000004000000000000000000000000000000000004040000004000000800000000020002000000800000004000000000480a00000000008010000000000500000000000000000002000000000000100000000000000000000800000000800000000004000000000000020000014000100000000000000000000000000000000100000000000000000000000000000000200008000000000000000400004000400000000000420002000004000002000000002000000000000800008002000000000000 +00000020000000000000010000000000000000000000000000004000800000010000000000008004800000000000040020000000000000000000000000000000000000000000000080000000000000000006010000040000000000000040000000000000c00000000000000000000002001000408000000000000000000000080080000010000000000001200000000004044000000000020000100000000000004900000020000000000000100000000000000000000000080100040000000000000000001000008400000000000001800000000000000000044000030000000000010000000000000002000000000000000000000000100000000040000000 +00400000000004080000010000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000040000000000000005000000000004000000204004400008000000000000000080000000000000840000000000800000000000000000408040000000000000000000001000000010800004000000002000000000040000000000000000400000000000000000000000000000000000100000000040000000100000000100000100008000000080000404000800004000010000000000000000000000000200200000800100000000000000000402000000002000020000000000000000040200000000 +00000000000010000000010000000000000000000000008000000000000000000000000140000000000080000000000020000000000000000080800001000000004000000000000000000000000000000000010000004080000000000000000000000800000000000800000000000000000100000000000000008000000000000000000002000000010000000001000001000000808000000000000000000000000000000000000000000000100100000000010000000000000000000000000000000000000000001000802000000000008000000000000000004000000101000400010000000000000002000000000000000000000000000000000000000000 +00020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000401100000000000000010000000020000000000000000000000000000000020000000010000000000100400000000000000000a00000000000000000000080000010000400000000002000000004000080001000000000000000200000000800021010000000000000004000000000000000000000020000000208000100000000000000000100000000000000000040000000000000020000000000004000000000000000000000000004000020000000000040000000000000002000000000000000000800008000000000000000000 +00000000000000000000010000000000000000000000000000000000000000000000000000004080000200400000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000800000000000000000000000000000000000000000000000000000002000000002000000000000000200000000000000200000000000000000900000000000000000800000000000000000000000000000000100008000000000000000000100000000000000000000000000000000000000000000000000000000000000000004004000000000000000000000100000002000000000000010000000000000000000040000000 +00000000000000100000010000008000000000000000000000000040000000000000000000400000040100000110000400000000000000000000001000020000000000000000000000000000000000200000000800008000104000000200000000200000400000040002000000080200010000000000000001000000000000000000000002000000000100040000000001090000000000000000000800000000000080000000000020208000180000000001008000100000000000000000008001000000000000000800000000000000000000001000000000004001000800000000000000000000000082000000000000000a00000010000000000100200000 +0220000000000000000001000000000000000000000000000000000000200000000000000000001000000100000000002000000000000000000000000000000000000000000000002000000000000000001000000000a000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000002000000010000000000000000080000008000000000000000000000000004000040000000002000108000000040000000000000000000000000000000000000002000000000000000000020000000000000008400004000000000000000000000000800000002000000000000100080000000000080000000000000 +02400000000000000000000000002000000000000000000000800000400002000000008820001000800000100000008000000000000000000108000040000000004000800000000000000000000000000004000008000008000000000000000000000080800000000000000000080000000000408000000000000000000000000080000002000000014000000000000201000000000000000000100000000200000000000000000000000000100200000000000000000000008100000000000000000080000000000000000880001000400000000000000000004000000000000000000000000000000002000000002000010000000000000200000000000000 +00000000000000000000010000000000000000040000000000000000000000020000000000000000000000400000000000000000000000000000000000040000000400000000000000020000000000000004000000009000000000000000000000000100000000000002000000000000000000408000000040000000000010000000000012000000010000000000000000040000008000004000000000000000010000000000000020000000100000000400000000000000100100000000000001000000000000200000000000000020000000000000000000004200200000800100000000000000000002000000000000000000000004000002000000000000 +020000000000800000000110000040000000000000000100000000000a00000000000000000000000000000080000004000000000088000000000004000000000000a0000000000000000000000000000000010000008000000020000002000000000800800000000000000040080000400000408000000000000000000000021000000002000000030000000804040200000000000004000000020000000000008000010000000000000800108001000000404000000004000100000040000000000010000400000000020000000000000000000000000c00044000000000000000000000000090000002000000000040404010000000000001000000004000 +0420000000000000000001000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000024000000008000000000000002000000000000800000000000000000000000000000408000000000000000000000001000000000000000000000000000000200000000000000000000000000000000000000000200000000000000100200000040000000000000000500000000040000000000000000010400000000000000000000000200010040004000000004800000000000000000000002000000802000000000000000000040000000000000 +00000000000000000000010400000000000000000001000000000000000000000000000000004004048000000000000400000000000000000000000000000000000000000000000000000000000000000004000000000008000000000000000000000000040000000000000000000200000000008000000000000000000000000001000002000080000200000000200000080000000000000000000000000000000000604000000000000000100000000440000000100000000000000010008000000000000060000000000000000000400008001102000000004004200000000000000000000080000002000000000000010000000000000000000000000000 +00000000000000000000010000000000000000000000000000000002000000820000000001400000040000000100000400000000000000000000000000020000000400000000000000000000000000080000000000008000504000000000000000200000000000040002000000180000000000002000000000000001000000000000000002000000010000000000000001000000008000000000000000000000000080000000000020008000100000000401000000100000000200000000008001000000000000000800000000000000000000000000000000204000000000000000000000000000000002000000000000000000000014000000000000200000 +02000008400000000000010000008000000000000000000000000001800000000000020000000000000104000012000000000000000000000000001000000000000000000000020000080200000000000004008000000000020000000000000000800000c00001000000000000000200000040408000000000000000000000080000000002400000010000040000000200000000808000002000000800000000000000000220000020200000100200000000000000000000000000000000000044000000200000008000000000000000000008000200000000004000004080001000000000000000000082000000402000000280000008000000000000000000 +04000020000200000400010400000400000000000000000000800000000200000000000000000000000000000002000400000000000000000000200010000000000000000000000000000000000000000004000000000008002040000200000000000000800000000100000000000004000000408000000000000000000000081000000000000000000000000000000011000100000000000000001000000000000000000020100000000400500000000400042001000000000000000000000000000010000200000000000000000000400000000000000000004000000000000000000102000010000002004001002000010010100000000000000000000000 +000000000000000000000100000000000000000000800100000000000000000000000000400000000000000080000004000400000080000420000000000000000000000008000000000000000000000000040000000880000000200000000000000000008000000000020000000a0000000000408000000000000000000000020000000002080000000000000000000200000000000000000000100000000000080000000000000020000800100000000040000000000000000100000000420000000010000000000000000000000000002000000000000000040000000000a08000000000000080000002000002000000000014000000000000000020000000 +00000000000000000000000002400080000000000000008100000000000000000000000000000000000000000000000020000000000000020000000040000000000000000000000000000000000000000004010000000000000000000400000000000000800000000008000000080000000000400400000000000000000000000008000000000000010000800000000001000000008000000000000000000000000000000000000020000000100200000000001000000000000000000000000040000000000000000000000000800000020000000000000000004000000000000001000100000000800202000000022000000000000100000200000000000000 +00000020000000000000010000000000000000000000000000000000000000800000000080000000000000000040000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000800000000000000000000000000000400000000000400000001000080000000000000000010000000000000001000000008000000000000000000000000000000020000020000000100000000000000000000000000000000000000000000000000000201000000000000000801008000000800000004000000000000000000000000000000002400000000000000000000000004000000000000000 +00000000000000100000010000008000000000000000000000000000000000000200000000000000040100000010200400000000000020000000001000020000000000000000000000000000000020200000000800008000104400000100000000200200400000000002000000080000010000000000000002000000000000000000080002000000010200040000000021010000000000000004800800000000000000000000000020208000100000000001008000100000000000000000008001000000000004000800000000000000000000000000000000004001000000000000040000000000000482000000000000000a00000010000000000100000000 +00000000080000000000010000000000000000000000000022000010800000800000000000000000040000000000000420000000000000000000000000000008000000000000040001000000000000400004010000008200000000000100000001200000800000000002000000080000000000400000000000000080000000080080000002040000010000000000000001010000008000000000000000000000000000000000000000000000101000000000000100000000000000000000000001000000200000000000000000000000000000000000000000004004000002000000000000000000000002100000002000000000000090000000000000004000 +00100000000000000000010040000000000000000000000000000000000000800000000000000200000000000000000400000000000000000000000000020000000000000000000000000000000000000000000004010000000000000100000000004000400004000800000000080000000000000000000000001000000020000080008002040000010800000000010001010000000000000010000000000000000000001000000000000000100100000001000000100000000000000000000000000000000000000000000000000020000000080000000440004004000008000000048000000000000002000000000000000000000080000000100000000000 +00000000000000000000000400000000000000000000008000000000000000000000000002000000000000400000000420000002000000000000080000080000000000000000000000000000000000000004000000001088100000000101000000000000000000000008000000080001000000000000000000000000000000000080000002000000010200000000000001010000008000000000002000004000000040000000000000200000100200000400000000000000100000000000100000000000200000000010000000000000400000000000100000004000000000000000000000000080000002000000000000010000400000100000000000000000 +02800400000000000000000000000000000000000000000000000000000000000000000000000080000000400000400020000000000000000020000000040000000000080000008000020004000000600004000000000000000000000000200000200000050000000000000000000000000000408000000000000000000000001000000010028000010000000000000000040000008000000000000000000200000000000002000000002000100000000000000000000000100100000000000000000000002000000100000000000000000000000000000000004200000000000000000000000000000002000000000000000000000000000000000000000000 +00000000000000000000000000000100000000000000008000000000000000000000000000000084000000400400000000000004000000000000000000080000000000000000000000080000000000000004000000400008001800000000020800000000808008004008000000000200000000000000000000000000000000000000000002000000000000000000000001080000000800000001000000000000000000000000000010000000100000000000000000000080180000000000100000000000000000008400000000000800000000000000000000004800000000400000000000000000010002000000000000000004000800000000000000000000 +00000000000004000000010000000000000000000000000000000000000000020000000000000200000000000000000000000000000000000000000000000000000400000000000000000004000000200000400000008000000000000000000000000000040000000002000000000000000000408000000000000000000000001000000012000004010000040000000000040000008000400000000000000000000000100000000020000000100000000440000000000000000101000010000001000000000000200000000000000020000000000000000000004200200000800100000000000000000002000000000000000000000004000000000000000000 +00000400040004000000010040000000000000000000100000000000400000000000000020004200000000000000020000000000000000000000000000040200000000000000000000000004000400200004000004000008000000000000000000004000840000000000000000080000000000408000000000000000000000001080000010000004010000000000010000040000000000000000000000000000010000000000000000000000100300000000000000000000008100000100000000000000000000000000000000000000400008002000000000004204200800800000000000000000000002000000002000010000040000000200000200000000 +10000000000000000000010000000400000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000100000000000000010000008002000000000000001000000000000000200000000000000080200000020008000240800000000000000000000000002000000012000000000000200880000008000000000000004100000008000000000000000000000100000000002000000200040000000000000040000000000000002000000000000800000020000000000000000004000000000000000000000000000000002000000800000010080000000000000000000000010 +02010000000000000000010000002000000008000000008000000000000020000000000900000000000000020000020020000000008000000000000000000000000000000000002000000000000000000004000080008000000000000002000000000000800000000000000000000000000200400000000000000000000000080000000012060000010000000100000001000000008000000000000080400004000000000480000000002000100000000000400000000000000000000000000000000000002000000000000000000000000008000000000000004044000000000000000000000000000002000000002400000000000000002000000000000004 +00000000000000000000012000000000000000000000000020001020000040000000004002004000000000020000000400008000000000400000000000000000000000000000000000000000002000000004010800010200000002000800000800000000890000100000000000000000000000408000000200480000000000081000000000000000010200000201000801000000008000000000000800000800800000000020000000000000100000000000000000000000000100000000000000000000000000001000000000000000000000000000000000044000000020000000018000000080000002000000002000000000000000000000000000002000 +00000000000000000000000000000400040000000000000000000008000000004000000002000000000000000100000420100000080000000000000000000000000000000000000000000000008000000000000080000000000000000000000000002000000200000008000000000000000008009000000000000001000000000000000000000000012200000000000000000000008000000000000000000000000000200000000000200000100200000000000200200000000000000000000000000000200100000800000000004000004000000000100000004000000000000000000000000080000403000000000000010000000000000000000000000000 +02000000000000000080014000000000001000000000000000000000002000000000000040004000000000000000000000000000000200000000000000000008000000000000000000000000000200000014000000008000000000000000000000000000880000000080000000080200000000000000000000000000000000000000000002000000000000000000000000090800000000100000400000000000000000000000000020000000100000000000000000100000000000000000004000000000000000000000000000000000000000000000000000004004100000000000000000000000000002000004002000000000000004004000000000000008 +0000000000020008000001400000000000000000200000000000000100000000000000001000100000000000004000040000000000000000000000000002000000000000000002000000000000000000001001080400a000000000000002000000004000008001000000000000080200000020000000004020000080000000200000000002000000000040000000010001080000000000020084000000000000000400000000000000000000100100000001004000100000000000000000000000000000000000001000000000000000000008000000000000004000000000000000000000000080000002000000000000000080000004000000000000000000 +00200000000000000000010000000000000000000000000000000000000000000000000000000000000000000100000400000000000000000000000040020008000000000000000000040000000020000010000800008000100400000000000000000000000000000002000000080200010000000000000002000001002000000000000002000000010200000000000021090000008040000004800001000000000000000000000028208000100000000001008000100000000000000000000000000000000000200000000000000000000002000000000000004000100000000000040000000000000002000000000000000000000000000000000000000008 +00200000000000000000010800000400000000000000000000000000000000000000800000000000000000000400000000000000000000000000000000040000000000400000000000000000000000000004000800008000001800000000020000000000000200004000000000080000080000000000100000000000000000000000000002000000010000000000000001000000008840000001000000100000000000000000000000000000108000000403000000300000000000000040040000000000000000000000000000000000020000000000000400004000000000000000000000000000010002000000000000010000000804000080001000000000 +00000000080000000000010400000400000000000000000000000000000000804000000002000000000000000100000420000000080000000000080400000000000000001000000000000000000000000000000000000200100010000000000000002000000200000000040000000000000008402000000000040001000000000000000002000000010200000000000001000000008000000000000000000000000000200000000000200000100200000001000200300000000000000000008000000000200000000000000000000000000000000000100408004000000000000000000000000080000002000000000000010000000000000000000000000800 +00000000000000000000000000040000000000000400000002000000000000008000000002000000040000000000000420000000000000000021000000000000000000000020000000000000000000000004000008008000004000000010000000000000800000000000000000002000000000000000000000001000000000000000000000020000010200000000040000000000008000000000000000000000000000000000000000000000100200000000000000000000000000000000000000000000000000000000020000000000000000000200002000004400000000000000000000000080000002000000002000000000000000000000000000000000 +00000000010000200000000000000000000000000000000000000000000000000000002000000000008000000000000400008000000000000000000000000000008000000000020000000000000000000000000000000000000000000000000000000000000000000000000000800000000000408000000000000000000000080080002000000000010000400000000000008800000000000000000000000000100000000020000000000000100000000000000000000000000100000000000000000000000000000000000000000000000008000000000000004040000000000000000000010080000002000000000000000000000000000004000000000000 +0000000001000000000001000000100020000000000002000000000000000000000000004000100000002800000001040000000400000000000000000000000000000000001000000000000000040400000401000000000000000000000000100000000080000000400000000000080000000040800000000000000000000200100000000200000001000000000104000000000000c000800000100000000000008000000000000000200000100800000000000000000000000100000000000000000000200000001000000000a00000000000000010001000044000000000808000050000000080000102000040002000000000800000000000000000000000 +02000004000000000000010000000000000000000000040000000000080000000000000000000000040002400000000000000000000001000084000000000000000001000000000000000000000000000000100000000000000040000000000000000000800000000000000000080000000000000000002000000000000000000000000002000080010000000000000000000000008000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000400004000000000000000000000000080000002000000000000400000000000000000000000004000 +0001000000000000000001000000000000000040000000002000000000280000000200004000400000000000000040040000000000000000000000004000000000400000000000000000000000000000000400080000800400000000000000000000000480001010000000000008000000000000800000000000000000000100000020000200000000020000000000020100000000000000000040080000000000080000000000000020000010020000000000000010000000000000080000000000000000000000000200000000008000000000020000042000400400000000000000800000000000000a000000002001000000100000000000000000000000 +04000000000000040000010000000000080000000400000000000040000000000000000000000004000000000010000000000000000000000020000000000000002000000000000000000000000000000004000828000000040400000000000000000000800000002000800000002000080020448000000000000000000000001000000000000000010000000000000201000000008000000001000000000000000000000000000020200000100000000041000000000000000500000000000000000000200000000000000000000000000000000000000080204100000000800000000000000000010002000000000000000000000000000140000000000000 +00400000000000020000000000000000000000000000000000800000000000000000000000000004000000000100001000000000000000001000000000000000000000000004000000000000000000000004000008000000000000000080000000000000000000000000000000000400000000408000000000021001000000000000100002000000010000000000000200000000008000000200100000000000000000000040000000000000100000000000000000000000000100040000000000000090400000040000000000000000000000000010000000044000000000000108000000000000400002000000000000000000000000000000000000000000 +000000000000000400000100000000000000080000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000002802000001000000000000400000000040100000080000000200000000000000000008000000000400000000000000000000000000010000000000000000a0008000002000000000000004000010000000002080000000004000000000000000000000408000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000001010000000000000000000400000000000002002000040000000020000000000000000 +02000000000000000000000012402400000000002080008000000001002000000000000000000000000000000000000020000000000000000000000040000000004000000040020000000100000000000004000000000080000000000000000000000000880000000000000000080000000000000000000000000000000000000080000000002000014000000000000001000000008000000000000000000000000000100000000000000000100200001000001000000000000000000000000000000000000000000000002000000000000008000000000000004000000000000000000100000000040002000000002000000000000100000200000000000000 +02000000000000000000010000004000000000000002000000000008080000000000000800000000000000000000000001000010004000000000000000000000000000000000200000000040000000000000040000008000000000000000000000400000800000000000000000000000000000008000000000000000000000001000000002000000012000000000000001000000008000000000000000000000008000000000000000020000100000000400000000100000000000000000000000000000400000000000000000800000000000000000001000004000000000000000000000004000000002000000000000000000000004000000000000404000 +00000400000004000000010000000000000000100000000000000000000000020000000000000000040000000000020020000000000000000000000000040000000410000000040000000004000000200004000000008000000000000000000000000000840000000002000000000000080000408000000000000000000000001000000012020004010000000000000000040000008000000000000000000000010000000000000020000000100000000400000040000000000100000000000001000000000000200000000000000020000000002000000002004200200000800100000000000000000002000000002000000000000004000000000200000000 +00000000000000000000014000012000001000000000000000000000000000020200000000004000000000000000000402000000000020000000000000000000000000000001000000000000000000200004000808008040000000000100000000000000000000000002000000080000000000000000000000001000000000000800080002000000010000400000000001010000000000000000002800000500000000000000000000000000100000000001000000000000020000000800008001000080000004000800000000000000000000000000000000004004000000000000000000000080000402000000000000000000000004000000000000000000 +0200000000000000200000000000002000000220000000030000000000000000000000080000000400000000000000000000000000000000000000010000000000000000000000000002000000000000000400000c008000000000000000000000004040800000000000000800400000000000408000000000000000000000000000000002000000000000800000010000000800200000000000000000000000200000000000000080000000100100000000000000000200000000000000000000000010008004040000001000000000000040000000000000000000000002000000000000000000000000004000002000000100000000040000000000000000 +0000000000000000000001000000000000100b000000000000000000000000000000000040000000040000800000000000000000000000000000000000000000000000000000000000000040000000000004000000008000004020000000800000000000800000000000000000000000000004000000000000000400000020000040000002000000000000000000800000000800000000000000400000000800000000000000000000000000100680000000000040000000000000000000040000000010000000000000000000000000000000000200000402004100000000000000000000000000000002000000802040000000000000000000100000000000 +00000000000000000000000000040000000000000000000200040000000000000000000000000080000000400000000400000000000000000000000000000000000000000000000000000000000000000004000000000000000820000000000002000000800000000200000000080000000000000800000000000100000000000000000000000000000000000000000000000800002000000000000000000020000000000000000000000000100004000000000000100000100002000000008000000000008000008400000000000000000001000000000000004000000000000000000000000040000002000000000000000001000000000000000000000000 +0000800000000000000001000000000000000000000000000000000000000000000000008000000000010004004000040000000000000002000000000008000000000000000002000000100000000000000002000000c00000002000000200200000000008000000000000000108080000002100800000000240000000000002000000000300000001002000000000000010000000800000000400000040000000000000000000002000280010000000040000000010000000000000004000000000000000000020000000000000000000000a00000000040c004000000000000000000000000010000002000400000000000000100004000000000000000000 +00000000000000100000010040008000000000000000000000000000000000000000000000000200040100000010000400000000000000000000001000020000000000000000000000000000000020200000000804008000104400000100000000204200400004000002000000080000010000000000000002000000000000000080000002000000010200040000010021010000000000000004800800000000000000000000000020208000100100000001008000100000000000000000000001000000000000000000000000000000000000000000000040004001000000000000040000000000000082000000000000000a00000090000000000100000000 +00000000000000100000010000008000000000000000000000000002000000020000000001400000040100000110000400000000000000000000001000020000000000000000000000000000000000200000000800008000504000000000000000200000400000040002000000080000000000000000000000000001000000000000000002000000010000040000000001000000008000000000000800000000000080000000000020208000100000000401008000100000000000000000008001000000000000000800000000000000000000000000000000004001000000000000000000000000000082000000000000000a00000014000000000100200000 +00000000400002000000010000000000000000000000000000000001000010000000000000000004000000000100000000000000000000000000000000000000000000000000020000180000000001000404000000000000000800002000020002800000800001004000000000800220000000008000000001000001000000000000000000400000010100000000000200000000008800002000000000000004000000000000000000000000100200000000000000000040000000000000000000000000000000000000000000000000200008000200000000004000000000000000420000000000000002000000802001000080000800000000000000000000 +00200000000000000000010000000000000000000000000000000000000000000008000000000000000000000100040000001000000000000000000040000000000000000000000000000000008000000000000000008000000000000000000000020000002000000003000000000000000000408000800000000001002000000000000002000000030000000000000200000000008000000000100000000000000200000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000080010010000004000000000000000000000000000000002000000800000000004000000000000000000000000 +00000000000000000000011000080200000000400000400000000000080000000000000000000000000000000040002400000000000000000000008040000000004000000000020010000000000000000004000000008008000000000002000000000000800000000000000000080100000000008000000000400080000000000080000002040010010000000000000001000000008000001004000000000000000000000000000000000000100200000400020020100000000000000000000000000000000200000000000000000000000108000000000400004004600000000800000100000000000002000000002000010000100004000200000000000400 +00000000000000000000001000008000000000000000000000000080000000000000000000000000000000400000002400000000000000000000000000000000000000000000000000000000000000000000000000000000010000000002000000004800800000000000000000080000000000000000000000000000000000000000000002000000000000040000000000000000000000000000000000000000000000000200000000200000100000000000000000100000000000000000000404000000000000000480000000000200000000000000000420004200000000000000000000020000000402000000000000000000001000000000000100000010 +00000000000000000000010000000000000000000000008000000000000000800000000000000000000000400000000400000002000000000000000000020000000000000000000000000000000020000004000000001080100400000101000000000200000000000800000000080000010000002000000002000000000020000080008002040000010200000000000021010000000000000004800000004000000000000000000000208000100000000001000000100000100000000000000000000000000000000010000000000000000000000000000400004004000008000000048000000000000002000000000000000000400000100000100000000000 +00100000000000000000010000000000000000000000000000000000000000800200000000000000000000000000000400000000000020000000000000000000000000000000000000000000000000002000000000000000000000000100000000000800000000000200000000000000000000000000000000000000000000000000080000040000010800000000000081010000000000000000000000000000000000000000000000000000100200100001000000100000000000000000008000000000400004100808000000000000000000000000000000004004000000000000800000000080000402000000000000000000000000000000100000000000 +0000000000000000000001000000a000000000000000100000000000000000000000000042000000000080000000000400000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000010000000000000200000000001000000000000000000000000000000002000000010200040000000000000000008000000000000000000000000000000000000000000000100000000000000000001000000000000000082004000000000000000000000000000000000080000000000000004200000080000000000000000080000002000000000000000000000000000000000000000000 +00000400000000000000000000000000000000000000100000000001000000000000000000000000040004000000020400008000040000000110000000040200000000000000000000000004000000200004000000008000004000000000000000200000840000800002000000000000000000408000000000000000000000001000000012000000010000000000000000040000000000000000000000010000000000000000000000000000100200000000000000100000000100008100000001000000000000000000000000000000000000002200000000004200000000000000000000000002000402000000002000000000000000000000000200000000 +00000000000000100000010000008000000000000000000000000000000000020000000000000000040100000110000400000000000000000000001000020000000010000000000000000000000000200000000800018000404000000000000000200000400000000002000000080000000000000000000000001001000000000000000002000000010800040000000001000000008000000010000800000000000000001000000020200000100000000401000000100000000000000000000001000010000000000000000000400000000000080000000000004001000000000000040000000000000082000000000000000a00000014000000000100000000 +00000400000000000000000040000400000000000000008100000004000000000000000000000280000000000000000000000000000000040000000000040200000000000000000000000004000000000004000004000080000000000080000000004000800200000000000000080000800000408040000000000000000000000080000010000000010000000000010041040000000000000000000080100000000000000000000000000000300380000002000000200000000100000100008000000000000000000000000000000000000000002000000040004200000000000000000100000000000002000000002000010000000080000000000200000000 +00002000000000000000010000004000000000000000000000000000000000000000000000000000000000000100000000000200000000000000000000000000000000000800000000000000000000000010000000006000000000000000000004100001000000000000000000000200000000000000000000000001002000000000000002000000010000000100000000080000008000000000000000000000000000000000000000000080100000000000000000010000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000002800000000001000080000000000000000000000000 +00000400000000000000000000000000100000000000000000000001000000000000000000000000000000000000000400008000000000000100000000040020008004000000000001000004000000000004000000008000000000000080000000000000800000000002000000800000000000408000000000000000000000000000000012020000010000000000000009040000008000000001000000000000000000000000000000000004100000000000000000100000000100000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000402000000002000000000000000000000000200000000 +00000400000004000000010000000000000000000000000000000000000000000000000000000200000000000000008400000000000000000000000000200000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000408000000000000000000000000000000010000000000000040000000000040000000000410000000000000000000000100000000000000000100000000000000000000000000001000010000000000000000000000800000000000000000008000000000000004204200800800000000000000000000402040000000000000000000000000000000000000000 +0000000000000000000001000000000000000000000000000000000000000000080000000200000004000000000000042000000000000000000004040000000800000000000004020000000000000000000001000000800000000000010000000020080000000000000200000008020000000000000000000000000000000000008000000200000001220000000000000009000000800000000002200000000000004000000000000020000010060000000000000000800400000000004000000100000020000000000000000000000000000000000010000000400000000200000000000000008000000a000002000040400000000010000000000000000000 +00000000000000000004010000000000000000000000000000000000000000000000000000004000000000000000000020000000000000020000000000000000000000000000000000000000000000000000010000000000000000000401000000000100000000000000000000080000000000408000400000000000000000000008000000040000010000000000000000000000008000000000000000000000000000000000000000000000100000000000000000000000000100000004000200000000000000000000000000800000000008000000000000004004200800800000000000000000100002000000020000000000000000000000000000000000 +0000000000000000000800000201000000000440000000000000000000000000000000000000000480000000014000002000000000400000000000000000000100000000000000000000000000000000000400000800000000000000000000000000000000080000000000000080000001000000802008000000000900000000000000020200000001000000000000020000000000800000000008000000000000800004000003000000000010000000000000000000008000000000000000000008000000000004000000000080000000004000000020040000400040000000000000000a000000000002000000014000000000000000000000000000000010 +020000000000000000002100000000080000000000000000000000008000000000000000040000040000804000000000200000000040000000000000100000000000014000000000000001000000000000040000000000000000200000000010000000008000000000000000000000000000004080002000000000000004000800000000122000000102080000000002000400000080000000000000000400840000000001a0000000000000120000000000000000000000300000000000040010000000000000000000000000000080000000200000000001004000000000000000000000000080000002000000000000000000000000000000000000000000 +000000000020000000000100000000020000004000000000000000c0000000040000000004000000080000000000000420000000000000000000000000000000000010000000000000000000000000000000010000000000000000000000000000000000800000002000040000400000000000008000000000000000000000000000000000040100010000000100000000000000008000000000000000000000200000000000000000200000100000000000000000000000000000000000000000000000200000001000000000000001000008000000000000004004200000000100000000000000000002100000000000400200100000000000000000000000 +02010000000000000000000000000000000000000000008501080000000000000000000800000000060000200000000020000000000000000000000000002000000000000000002000004000000000000004000080000000000000000000000000000400800000000008000000080000000000400000000000000000000000080000000012020080010000000000000001000800008000000000000080000004000000000480000000002000100000000000000000000000000000000000000000000000002000000000000000000000010000000000000000004000000000000000000101000080000002000000002000000000000000002000000000000000 +1000000000020000000001000000000000000a008000000040000000000000030000000000000080000000400008000400000000000000000000200000004000000000000000008000000000000000000004010000008000000000000000000000000000800000000102000000080000000000000000000000000000000000000080000002020000010800000000000001000000018000000001000000004000000000400000000000000000100240000400000000000000100000080000040141000000000000000000000000000000000000000100000400404000000000400000000100000000000002000000002000000000000004000220100000400000 +0000000000000000000001004000000000000000000000000000000000000000080000000200020000000000000000042000000000000000000004040000000800000000000000020000000000000000000001000400000000000000010000000000480000000400000000000008020000000000000000000000000000000000008000000200000001220000000001000009000000800000000002200000000000004000000000000020000010070000000000000000800400000000004000000000000020000000000000000000000000000000000010004000400000000000000000000000008000000a000002000040400000000080000000000000000000 +00000000000200000000010000000000000000000000008101000000000000000000000040000000000000000000000400000000000000000000000000000000000000000000000000000000000000000004010000000080000000000100000000000000800000000000000000080000240000000000000000000000000000000080800002000000010000000000200001110000000000000000000000000000000000000000000000000000100100000000000000000000000000000000000000000000000000001010000000000000000000000000000000004000000000001000000100080000000002000000002000000000000000000000000000000002 +0040000000000010000401000000000000000000200000800080000100000000000000000000000004020000000000242000000000000000000000080008000000000000000002000000000000000000000000000000800000400000000000000020010080000100000a000000080000000000408000000002400000040000000100000102000000000204000000000201000000000000000000100000000000000010000000000020200000100000000000000000000000080500000400000003000000000000008400000000000000000008000000000020004000200000800100000000000080000002000000000000000000000010000000000000000000 +02200000000020000000010000004000000000000000000000000000000000800000000800000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000420000000800000802000000080000000000000000000000000000002020000080008002040000010000000000000001000000000000000000000000000000000000000000000000000000100000000000000000000000010000000000000000000000000000000000000000000000000000000000000400004004000008000000008000000000000002000000000000000000000000000000000004000000 +00000000040000000000010000000000000000000000000000000000000000000000000242000000480000000102000420080002000000020001000000000000000000000000000000040000000000000004000000004000000000000000000000000000810000000000000002080000000000408000088800000000000020000080008002000000010200000000000000000000008000000000000000000000000000000000000000220000500000000000100000000000000000000000000000000000200000000000000000000000020000000000000404004000000000800000008080000080000002000000002000000004000000000000000000000200 +00000000000000000000010000001000000000200000008000000000000000000000000000004002000020000000000400000000000000000080000041000000000000000000000000000000008000000004004008000000000000010000000400002000800000000008000000000200002000400000000000000000000000000000000000002000000000000000000021000000000000000000000000000000000000000000000000000000100200000000000000000000000000000000000000000000000000000000008000000200020000000200200000004004000000000840000100000000000002000200002000000000001000040000000000000000 +00000000000200000004110000000080000000000000008100000000000000000000210000000000000000000040000000000000000000020000000000000000000000000000020000000000000000000004010000000000000000000400000000000000800000000008000000080000200000408000400000400000000000000008000000000000010000000000000001000000008000000001000000000000100000000100000000000000100000000000000000000000000100000000000200000000000000000000000000800000000008000100000000004000000000800000000100000000100002000000022001000010000000000000000000000000 +00000000010200002000011400001000000000000000008140002000002000000000000040004000040020004002000400000000000000000000000000000000000000000000140000010000000000000004000004008080000000000000000000004000800000000000000000080000200000400000000000000000000000001080000002000000410000000000010001000000000000000000400000000200000000000000000000000000108100000400000000900000000000200400000000000000000000000000000000000000000000000000000400044000000000000000000100000080000102000000002000000000800000000000000000000000 +00000000000004000000010000000000000000000000000000000000400000000000000020000000000000000000000020000000000000000000000000040200000000000000000000000004000400200004400000000008000000000080000000000000840000000000000000080000000000408040000000000000000000001080000010040004010000000000000000040000008000000000000000000000000000000000000000000000100200000040000000000000008100000100000000000000000000000000000000000000400008000000000000004204200800800000000000000000000002000000002000010000000000000200000200000000 +00000000000000000000010000000400000000000000000000000000c00000020000000042400000000000000402000400000000000000000000000000000000000000000000000000000000000000000100010000008000000000000040000000000000000000000002000000000000000080400000000000000000000010080080000002000000010200000000000000400000000000000000000000000000000000000000000000000000108000000400000000600002000000000000000001000001000000000000000000000000000000000000000000004000000000008000000000000080000002000000000000000040000004000100000100000400 +00000000000000000004010000008000040020000000000000000080040000000000000000004000040000800000000400008000000000020000000000020000000000000000000000000000000000000000010000008000004000000401000000200100000000000002000000080000000000408000000000000000000000000008000002000000000000040000000000000000000020000000004000000000000000000000000020200000100000000000000000100000010100001004000401000000000000000000000000800200000000000000001020004204200800800081060000000000800002000000020000000000000010000000000000000000 +06000000000000000000000000000000000000000000000000000000000000000000000800004002000000000000000420000000000000000000000000000020000000000000000000000000000004000000000000800400000000000008000000020000000000000000000000000220000001400000000000000000000000001000000002000000010000000000000001000000008020000000000000000000000000000000000400002000100000000000000000000000000000000000000000000000002000000000000800000000000000800000000000044000000000000000000000000000000002000000000000000000000000000000000000000000 +00000000000000000000010000000000000000000000000000000000000000820000000000000000040000000000000401100000000000000010000000020000000400000000000000000000000020080000010000008000104400000000000000200a00000000000002000000180000010000002000000002000000004000000000000002000000000200000000000021010000000000000004800000000000000000000000000020208000100000000001000000100000000200000000040001000000000000000000000000000000000000000000000000204000020000000000040000000000000002000000000000000000800014000000000000000000 +22000000000000000000114000008000000060000000000000040000c00000800000000800000004000000010000080020000100000000408004000040000000200000008000000010000000000000040004010000108200000000000800000000000000c00010000010000000000000000000408000000000400800000000081880020012040400014002440000000205002000008000000000100000000000023000000020000080000000120000000000000000000100000100008000000000000000000000000000000000000000000000020000000044004004010080002000000000000002000082000000002000000200000000000108000000000000 +00200000000000000000010000200000000000004000000000800000008000000000400000000004002000000000000020004000000000000000000000000000000000000000000000000000000000000004010000008000000000000000000000000800000000000000100000080000000000000000000000000400000000000000200000040000010000000000000000000000018000000000020802000000000000000000000000210000100000000000000002100000000000000000000000000000000000001000000140000000000000000000000020004004000000000000010008000000000002000000800000000000000000000000000000000002 +0200000000000000200001500040008000000200000000810000000000000003000000080000000000000000000000040000000800100002002020000000000000000008000000200000000000000000000401000000800000000000040200000000000080000000080a000000080000000000400000000000000000000000000008000002000000000000200000000101000000000200000004002000002000000000000000000020000000100200000000000000100000000000000000000041000000000000000000000020800000094000000200000400004000000000000001000100002000800002000000022000000000000004000000000000000400 +0000004000000000001001000000000000000000000000000000000000000000000010004000000400000000000000000000000000000000000000000000000000000000000100000080000000000000100400000000800000000000000000000000000480000000020200000000400200000040000000000000000400000008000000011200000000000004c00000000100000001000000000000080000000400100020000000000000000010002000000400001000000000000000000000000000000000000000000000000000000000000020000000044000000000000000000000040000000000000200000080a000000000000020000000002000000000 +00000000000000000000012000001400000000000000000000000000000000000000000000000000000020000000000020010000000000000000000000000000000040000000000000010000008000000000000000000000000000000000000400000000000000000000000000000000000000002000000000002000000000000000000002040000010000000000000000000800008000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000040000000000000000004004000000000000000000000000000002000000000000000000000000000000000000040000 +000000000020000000000100000010000000000004000000000000000000020000000000000000000400200000000004010000000800000000000000000000000001000000001000000000000080000080040000080080200040000100080000002200008000000000020000000a0040000000008001000400000000000000000000000002000000000200000000000200000000000000000000000000000000000000000000000100000000100004000000000000000800000000000000000011000000000000000000808000000000000000200000000000004000000000000000000000000080000002000000002000000000800010000000000020000000 +02000000000000000000010000000000000000000000080000000001880000000000000000000000000000000000002020000000001000000000000000000000800000000000040010000020000000000004800000004000000000000003000000000000800002000000000000480004000000408010000000000000000000081000000010000000000000100000000000040000000000000000100000000000000000100220000000004000100000000800000000000000000100800000000000000000001000000400000040200000000000020002000008004040000000000000001000001000000002000000002000000000000000100000000040000000 +00000000010000000000010000001000000000000000000000000000000000000000000040000000000020400001800400010000000000000000000000000000000000000000000000000080000000000004000000000000000000000000000000000004000000000000000000080000000000000000000000000000014000200000000002000000010000000800000000000040008000010000000000000000000000000000000000000000108000000000000000000000100004000000012000000000480000000000000000040000000000000000000408004000000000000000000000000080000002000000000000008000000000000080000000000000 +00000000000400000000080000008000000000000000000000000000000000000800000000000000008000000002000000000000000000000000000000001000000040000000000000020000004000000004000000008000000002001800000000000000800000200002020000000000000000408000400000000400000000080000000002000040010000040000000001000000009000000000000000020000001008000120000020200000100000000000000000000000000100100000000000000000200000000000000000000000000000002000000000044200000080000000800000000040000002000000002000000004000000100000000000000080 +00000000000001000000010002008000000000000000000000000000000000020000000040000004000000000000000000000000000000000000000800000001000000000020000000000000000000000004000000008000000000000000800000000000040000000002000000080004000000408000000000000000000000081002000002000000000000040000000200000000000000000000002000000000000000000020000000208000100000000000000000400000000100000000000001000100000000800000000000000300000000000100244000000200000000000002000000000000020002000000000000000000000004000040002044000000 +02000000000000000080010000002000000000000000008000000000000000000000000000000000000000000000000020000000000000000000000440000002000000000000002000000000002200000004010000000000000000000100000000000800800000000008000280000000000000000000000000000000000000020000000002842000010000000000000001000080008000000000020000000000000000000000000000000000100200000000000800000000000000000000000000000000000000000000010000000000010000000200000000004004000000000000001100000000000002000000002040000000000000000000400000000000 +00000000000000000004004000000000001000000000000000000000000000030000000000000000000000000100000400000000000000000000000000000000000000000000000000000000000000000000000040008008000000000000000000000000c00000000022000000080000018000000000000000001000000000000000000002000000000000040000000000010000000000000000002000000000000000000410000000000000100000000400000000000040088000000000000001000000000000008400000000000000402000000000000000004000000000000000000000000000000002000008000000010000000004000000100000000000 +00000000000000000000001000000108000000000000000000000000000280000000000000000010080000000000000400000000008000000000010020000000000000000000000000000000000000000000000000000000000000010100004000000000000000000000000000080000002800008000000000000000000000000080000003000000010000000800000020110000000000000000000000000000000400000000000000200000100000000000000000800000000000200000000000000000000000000000008000000200000000000000001400004000000000000000000002000000000002000000000000000080100000000000004000000000 +00000000002000000000010000000080000000000000000000000000000000000000000002000000000080002100000421000000001000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000200000000000000000000008000000000041001000000080000000100040000010240000000000008000000008000000000000000001000208000000000000000000000100000000000000000900000000000000000000000000000000000000000000000800000000008000000000400004004208080000000000000000080000402000000000000000000040000000000000400000000 +00000000000200000000010000000000000000080000008100000000000000000000000042000004000000000000000420000000000000000000000000000000000000000000000000000000000000000004010000000080800000000100000000000000800000000000000000080000240000000002000000000000000000000080800002000000010200050000200001010000008000000000000000000000000000000000000000200000100000000000000000000010000000000000000000000000200000001010000000000000000000000000000000004000000000001000000100080080000002000000002000000000000000000000000000000000 +000000000002000000000100000004000000000000000000000000010000000000400000000000000000000000000000200000010000000000000000100000000000000000100200000000000000000000040000000000000000000000000000000000008000010000000000000002000000044080000000000000000000000000000000124000000100000000040002140c0000008000000000000000000000010000100000000000000000100000000002000000000000000500000000000000000000000000000000000400002002000008000000200000004000000000800000000000000000000002000000002000000000000000020000000002000042 +02000000000000000000010000000400000000000000000000000000000000000000000000000000040000000000008020000000000000000000000000000000000000040000000000000000000000000000000900108000004000000800000000000000000200000000000000008000000000000000000000010000000000000000000002000000010000000000000001000000008000000000000000100000000000000000000000002000100000000002400000200000000000000000000000000000002000000000000000000000020000800000000000404000020000000000000000000000000002000000000000010000000000000008000000004000 +00400000000000000000010000000000800000000000008010000000400002000000000000000004000000000000008420000000208000000000000000080000000000000000000000100000000200000004010008000080000000100000000000000040000000000000000000000200000000408000000000000000200000000000000000000000010000000000000001000000008000008000000000010000000000000000000000000001100000020000000000000000000000000000100004000080000000000000000000000000000000000000000000004000200000000000000000000000000002000000000000000000000000000000000000000000 +00400000000000000000010000000000000000000000000010000002000002800000000000400000000000000100008400000000000000000000000000020008000000000000000000000000000000000010010008000000100000000000000040000000000000040000000000000200000000002000000000000001000000000000000002000000010000000000000001080000008000000000000001010000000080000000000020008000100000000001000000100000000000000000008000000080000000a00800000000000000000000000000000000004080100000000000000000000000000002000000000000000000000000000000000000200008 +00400000000000000000011000000000000000000008000010000000000202000000000000000004000000000000008400000002000000000000000000000001040000000000000000000000000000000004010088008000000000000000000200000000040000000002000000000000000000008000000000000000000000000001000002000000010200000000000000000000000000000000000000010000000000400000000000000000100008028000000000100000000000040000008001000080000000000000000000000000000000000100000400004000200000000000000000000280000002000000000000000000000000000000001000000000 +02000000000000000080010000000000000000000000000000000000080000000000000000004000040000000000000000000000000000000002000000000000000800000000000000000000000010000000010000008000004000000000000000200000800000800002000200000000000000408000400000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000100000200000000002000000000102000000000001000000000000000000000800000000000000000000000000004004000000800000000000000002000002000000000004000000000000000000000000004000 +04000000000200000000010000001000000010002000000000900001000000000002000000000000000020000140000409000000000000000000200000000000000000000000020000000000000000000004000000010000000000000008000000000000800009000000000000080004000000498000000000000000000040081000000000000000000040000040800001100000000000020000000000001000000000000020000000000400100000020000000000020000000000001400000000000000000000000000000045000000000008000000000400004000000000000000000000000000200002000000402000000000800000000002000000000040 +00000000000000000000010000000400000008800000000000000000000004020000000000020000008000000400000420018000000000000000000000000000000008000000000000000008000000000004000000008200000000000802000000100000800000000002000000080000000000608200000000000000000000080000000002060000010204000000000001000800008800000000102000210000000000000000000000200000100000000000000000000a00000120001000000001000000000000000000000000000150000004000000000400004004000000000000000000000080000002000000002c00000000000404000000000000000004 +00000000000000000004010000000000000002000000000000000000800040000000200000008000000000000400000020008000000000000000200000000000000000000000000000000800000000000004000000008000001800000100020000000000800000004002000000080000010400408000000000000000000000000000100002000000010000000000000001010000008800000000000000000000008000000100000000000000100200000000000000000000000100001000000000000000000001000000040000000000000000200200080000004000000000800000000000000000000002000000002800000000001800000000000000000000 +00000000000000000000010000000000000000000000000000400000000200000000000040000004080004000000000400000000000000000000000000000001000000000100000000000000000000000004000000000008000000000000008000000000000000000000000000080000000000608000000000000000000000080005000002000000000200000000000001010000000000000000000000001200000000040020000000400000100000000001000000100000000000000000008010000000004000000000000000000000400000040100004004000000000000000000000000000080000002000000400000410000000000000100004000000040 +00200000001000000000010000000000000000001000000000000000000000000000000000000000000004000400000020000000000000400000000000000000000000000000000000000000000000000024000000008000001800000000020000000000800000004000000000000020000000408000020000200000000000080000000002000000010000000000001200000000008800000000000002202000000000200020000000000000100000000400000000100000000500000040000000000000000000000000000000000000000000000000000000004000000000800000000000000000000002000000802000000000000804000000000000000000 +00000400000000000000000000000000000000000000100000000001000000000000000000000000000004000000020020008000000000000000000400041000000000000000000000000004002000200004010000000000000000000000000000000800840000000000000000000000000000408000000000000000000000001000000210040000010000000000000000040000008000000000020000000000000000000000000000000000100000200000200000000000000100000100000000000000000000000000000000000000000000002000000000004204000000000000000002000000000002000000002042000000000000000000000200000000 +00000000000000000000010000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000080000000000000000000000000000000000000000000080000000000000000000000000000000020000080008002000000010000000000000001000000000020000000000000000000000000000000000000000000100000000001000000000000000000000020000000000000000000000000000000000000000000000000000400004001000000000000008000000000000002000000000000010000000000000000000000000000 +00004000000000000000010000000000000004000000000000080000000000040000000000000000400000000040000000200000040000000000000000000000000000000000020000100000000000000010000008002000000000000000000000000400000000000200000000000200000000008000240800400000000000000080000002000080010001000000000200080000008000000000000000000000008000000000000000200000100000000004000000000040000000000000000000000000200000000000000000000000000008000000000000004000000000000000000000000080000002000000800800000180000004000000000000000010 +00000000000000000000010200001000000000000000000000000000000000000000000000004202000020000040000400000000000000000080000000000000000000000000020000000000000000000000000400000000000000000000000400000000000000080000000000080200000000400000400000000000000000000000000000000000000000040008000000000000000000000000000002000000000000000000000000000000100000040000000000000000000000000000000000000400000000000000000000000000000008000100000000004204040000000000000000000000100402000000000000000000000000000000000000000000 +00000000000004000000010000000000000000000000000000000000000000020000000000000000040000000000000000000000000000000000000000040200000400000000000000000004000000200004400000008000004000000080000000200000840000800002000000000000000000408040000000000000000000001000000012000004010000000000000000040000008000000000000000000000000000000000000020000000100200000440000000000000000100008100000001000000000000200000000000000020000000000200000000004200200000800100000000000000000002000000002000000000000004000000000200000000 +00010000000000400000010000001000000000000400000000000000000000000000000000000000080020000004000420000000000000000000800000000000000000000002100040000000100000000000000008004000000000000108000000000000000000000000000000490000000000008010000000000002000000000000000202000000010002000800000200110000008000000000000000000000000000000000000000204000180000000000000000020000000000001000000000000000000001000000000000200008000000000000000400004000000000000080000000000000000002000100000000000000100000001000000000000000 +00000000000000000000010000010080000000000008000002000000800000000000004000004008040000000000020020000000000000000000010000010000000000000000000000230000000000000004000000008000004400000800000000200000844000800202001000080000000000408040000000000000000000081800000012000010010000004000000201000020008000000000800800000000200000000000000000000000100200000040000000000000080100008100000001000800000000008400000000000000000000000000000040004005004000004000000000000800000002000000022002000000000000000240000220000000 +00010000000000000004010000000000000000000000000020080000800000020002000000000000040000000000000000008000000000000000000040000000004000000000000000004100000000000024000800008000000000000000000000000000800000000002000000080020000000408000000000000000000000000000000002000080010000000000000201000000008000000000000000000000008000000000000000000000100200000400000000000000000500001000000001000000000000000000000000800000000000000200000000004000000000800010000000000080000012000000802000000840000004000000000000000000 +00000000000200000000000000000000000000080000000000000001000000000000000000000000000000000000000400000000000000000000000000000000000000000000020000000000000000000000010004000000000001000000000000004000000001200000000000000000010000000000000020000000000000000000800002400000000000000400010001010000000000000000000000000000000400000000000000000000100100000000484000000000000000040000000000000000000000001000000000000000000008000000000000004000000000000000000000000080020002000000000000000000000000000000000000000000 +00000000002000000000010000000000000000000000000000000020000000000000000000004000008000000040000000000000000040000000000000000000000000000000020000000000000000000004000400000000000020000001000000000000840000000000000001080000000000008000400000000800000000000000000000000000010000000000000000000000008000000000800000000000200000000000000000200010100000040000000000000000020000000000000000000404200000000400000000000000020008000000000000004004200000000000000000000000100002000000000000000000000000000000000000000000 +0000000400000000000001080000000000000000000008000000000000000000000000000000000000009000000000002000000004000000008000000000000000000000000000800000000400000000000000000000020000002000000000000000000080000000000000000000000000000000000000000000000000080002000000004204000001000000000000000000000000840000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400c000000000000000080000000000002000000000000000000000000008000040000000000 +0000000040000000000001000000000000000a000000000100000000000008000100000040000004000000000000400020000000000000000000200000000000000000000000000000000000000000000004000000008000000000000000800000000000800000000000000000800000000000408001000000000000000000000000000002440000030000000000000000000000008000000000400000000000000000000000000000000000102000000000000000000000000000000000000000000000000000000400000000000000000008000000000400004004200000000000000000000000000002000000002000000004000000000000000000000000 +00000000000000000000010000040000000000000000000040002000000000000000000040004000000000004002000400000000000000000000000000000000000000000000000000800000000000000000000004000000000000000000000000004004800000000000000000000000000000410000000000800000000000001000000002000000000000000000010080000000000000000000000800000000000000000000000000000000108100000000000000000000000000800000000000000000000000000c00000000000000000000000000000000040000000002000000000000000080000000000002800000000000000000000000000004000000 +000000000006000000000100000000000000000004000000000000000008200000000000000040a0000000400000000403000000000000000000000002000000000000000000000000000000000000000004000008000000000800000000000000000000800000000000000000000008000000400000000000000400000000001000000002000000000000000000000001004000000000000000020000000000000000010000000000000000500000810000000000000000100000000000000000800010000000000000000000000000000000000000000400044080000000000000008300000080000002000000002001000010000000000000000000000000 +200000000000000000000100000000000000000000000000000000000000200000000002400000048400000000010000080000000000000000000000000000000000000000000000001000000008000000040000000080000040000000000000002000048000100000020000000800000000000080000000000000000000000a080000000200000000000000000000020100004000000000000000000000000000800000000000000000000010000000000000000000000000000000000000000100000000000000080000000000000000000000000000004c004000000000000000000000000000000002000000402800000000000010000000000000000000 +02000000000000000000000000000000000000000000000000080000082200000200000000000200200000000000000420000000000000000000000000000020000000000000000000010000000000000000000000000000000000000100000000000000800000000000000000080004000010400000000000001000000000081000000000000080010001040000000000010000008000000800000000000100000000000020000000200000100000000000000000000000000000000800000000000000200000000000200400000000001000000000001020004000000000400000010000000080000002000000000100000000000008000000000000000000 +0000000000000004000001000000000000000000000000000000004000020000000000004010000400000000000000042008000000000000000000000000080100000000010000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000120020204000001020000000000000100000000800000000000080000000000000014000000000040000010000000000100000010000000000000000000800000000000400000000000000100000000000000010000400000400c000000000000000002000080000002000002000000400000000000000002004000000000 +00080000002000200000010000000000000002000000000002000020000004000040000000000000000000000000000000000000000000000000010000000000000000000000000010000000000004000004000000008000000000400000000000000000800000000002000000000004000400408001000000000000000002081000000002000000010000000000000001000100008000000000000000002000200000200120000000200000100000000000000000800000000100800000000000000000220000000000000000000000000000000000000000004000000000000000000000000000000002000000002000000000000000008040000000000000 +00000000000000000004010000000000000000000000000000000000000000000000000000004000000000000000000400008000000000020110000000000000000000000000000000000000000000000000010000000000000000000401000000000100000000000000000000080000000000408000000000000000000000000008000000000000010000000000000000000000000000000000000000010000000000000000000020000000100000000000000000100000000100001004000000000000000000000000000000800000100000000000000000004004200800800001000000000002800402000000020000000000000000000000000000000000 +00000000000000000000010400000000000000000000000000000000000000800000000002002000000000000100000420000000000020000000080000000000000000001000000000000000000000002000000000000000100000000000000000000000000000000000000000000000000000002000000000000001000000000000080002040000010200000000000001000000008000000000000000000000000000200000000000200000108200000001000000000000000000000000008400000000200004000800000000000000000000000000100400004004000000000000800000000080000402000000000000000000000000000080100000000000 +0040000000000000000001044000000000000000000000001000000000000280000000000200020000000000000000842000000000000000000008000000000000000000100000000000000000000000000001000c000000100000000100000040004000000004000000000000080000000000002000000000000000000000000080000000000000010200000000010001010000008000000000002000010000000040000000000000200000100300000001000000000000000000000000000000000080200000800000000000000000000000000000100040004000000000000000000000000080000002000000000000000000000080000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000400008000000000000100000000040020008004000000000001000000000000000004000000008000000000000080000000000000800000000002000000800000000000408000000000000000000000000000000012020000010000000000000009048000008000004001000000000000000000000000000000000004100000000000000000100000000100000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000402000000002000000000000000000000000200000000 +000000000002000000000100000004000000000000000000000000010000000000400000000000000000000000000000200000010000000000000000100000000000000000100200000000000000000000040000000000000000000000000000000000008000010000000000000002000000044080000000000000000000000000000000124000000100000000040002140c0000008000000000000000000000010000100000000000000000100000000002000000000000000500000000000000000000000000000000000400002002000008000000200000004000000000800000000000000000000002000000002000000000000000020000000002000042 +00000000000000100000010000008000000000000100000000000000000000000000000000000000040100000010000400000000000000020000001000020000000000000000000000000000000020200000010800008000104400000400000000200200400000000002000000080000010000400000000002000000000000000008000002000000000200040000000021010000000000000004800800000000000000000000000020208000100000000001008000100000000000000000000001000000000000000000000000800000000000000000000000004001000000000001040000000000800082000000020000000a00000010000000000100000000 +002000000000000000000100000000000000000000000000000000010002020000000000000004040800000000000004000000000000000000008000400000010000000000000200000000000000000000040000000080000000000000000000000000000400010000020000000002000100000080000000000000000020000000010000024000800002000000020002000900000000000000000000000000000000006000000000000000001000000000400000001000000000000000000080000000000000200000000000000000000000080411020000040040000000000000000000000000c0000002000000000000000000000000000000000000000000 +00000000000000000000000000000400000000000000000000000001000000000000000000000020044000000000000020010000000000000000000000000000000000001000020000000000000000000004000000008000004000000000000004000000800001000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000080000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000008000000000000004000000000000000000020000000000002000000002000000000000000020000000000000000 +02800000000000000000000000000000000000040000000000000000000000000000000000000000000000400000000020000000000000000020000000040000000000000000000000020000000000000004000000001000000000000000000000200000000000000000000000000000000000408000000040000000000010000000000012000000010000000000000000040000008000004000000000000200000000000002000000003000100000000000000000000000100100000000000000000000002000000000000000000000000000000000000000004200000000000000000000000000000002000000000000000000000000000002000000000000 +0000000000000000080001800000000000000a000000000000000000000000800000000040000000080000000000000420000000000000000000800000200000000000000000000008000001000000000004000000008000000000000100800000000000800000080000002000000000000000008000000000000000000000000000000002000000012000000000000000010000008000000000400000000000000000000000000000000000108200000000000000000000000000000000000000000000000000000000000000000000000000000100000400004000000020000000000000000080000002000000002000000000000002000080000000000000 +06000000000000000000010040004000000000000000000000000000080000000000000000000000040000000000000000000000000000000000000000000000000000000000000000002000000000000000040000008000004000000000000000000000800000000000000000000000000000408000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000040000020100000000102000000000004000000000000000000000800000000000000000000000000004000000000800000000000000000000002000000000004000000000000000040000000004000 +00000000000000000000000000000000000000002000000000000001000000000000010000000000000000000140000000000000000000000000000040000000000000000000020000000000000000000004000000000000000800000000020000000000800001004080000000080001000000000000080000000000000000000000000000000000000000000000002001000000000800080001000000000004000000000000000000000000100000000000000000000000080000000020000000000000000000008400000000000000000008000000000000004000000000000000420100000000010002000000002000001000000800008000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000040004000000008400008000000000000000000000040200000000000000000000000000000000000004000000808000004000000080000000200000800000800002000000000000000000408040000000000000000000000000000012000000000000000000000000040000000000014000000000000000000000000000000000000000100200200000000000000000000100008100000001000000000008000800000000000000000000000200000000004200000000000000000002000000000402000000002000000000000000000000000200000000 +00000000000000000000010000440000000000080000000000000000000000000000000000000000040000000000000420000000008000000000000000000008000000000008000000000000000000000004000000008000004000000000000000200000800000000802000000080200000000000000020002000400000000020000200002040000010200000000000000000000008000000000000800000000000000000000000020000000100000000000000000000000000000000000000001000000000010000400000000800000000000000000000000004004000000000080000000100080040002000000002000000080400010000000000000000000 +02000000000000000000010400008000000000000000000000000001080000000000000000000004000000000000000020000000000000000000000000000001200000000000000000000020000800000004000000000008000000000000400000000000840000000000000000000000000000408000000000400008000000080000000000040000010000040000000220000000008000000000000000200000000008000020000000200000100300000c00000002000000000500000000000000000000200000800000000000000000400000000300000000004200000088800000000000201000000002000000202000010000000000000000000000000000 +00000000000000000000010000000000010000000000000000000000000000000000002000000004000000000000040020000000000000800000000000000000000000000000000000000000000000000004000000000000000000000000000000000000800000000100000000000000000000600010000000000000000000080000000012000000010000040000000000100000008000000000000000000004000000000000000000000000100200000000000000082000000000000000000000000010000000000000040000000000000000201000100000004000000000000000000000040000020002000000002000200000000000000208000000000000 +00000000002000000000010000000000000000002000000000000021000000000000000000000000008000000000000000000000000040000000000000000000000000000000020000000100000000000004000000000000000020000001000000000000840000000000000001080000000000008000000000000800000000000080000000040000010000000000000000000000008000000000800000000000200000000000000000200010100000000000000000000000020000000000000000000004200000000400000000000000020008000000000000004004200000000000000000000000100002000000000000000000000000000000000000000000 +00000000000000000000008000000000000100000000000000000001000000000000200000000000000000000000008400008000000000000000000000050000000000000000000000000004000000200004400000010000000000000080000000000000840000000100000000000000000000408040000000000000000000001000400012000000012000000000000200040000000000010000000000000000000000000000000000000000100000200200000000000000000100000100000000000000000008000800000000000000000000000000000000004200000000000000000002000000000402000000002002000000000000000000000200000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000400040001400010000000000000000000000000000000000000000020000000000000000000004000000008000000000000000000040000000008000000002002000000200000000000000000000400000010800000000800002000000010400000000000000080000008000000000000000000000400010200000000000000000100000000040100000000000100000000000000000000000000000000000000000000000000008001000000000004000000000000000000000000080000002000020000000000000000000000000000000000000 +00000000000000000000010000000000000000000000000000000000000000800000000000000000000000000000000401100000000000000010000000020000000000000000000000000000000020000000010000000000100400000000000000000a00000000000800000000080000010000002000000002000000004020000080008002040000010200000000000021010000000000000004800000000000000000000000000000208000100000000001000000100000000000000000040000000000000000000000000000000000000000000000000400004004020008000000048000000000000002000000000000000000800000000000100000000000 +02000002000600000000011000000000000000000000000000000000020800000040000c0000000000000000000000040000000000000000000000000040000000004800000000000000000000000000000400000000c000000022000000000000000008800000000002000001080000000000408000000000000000040000081000000003000800020000000804040001008000000000000000000000000080108200310020000000000000108200000000400000000000000100008100000000000000000400000000000000000100000000000200000c00044000000000000008108002000090080002000000002005020010008000100000000000000200 +00200000000000008000010000008000000000000400000000000000000000080000000040000000040000000000000400000000000000000000000000200004000000000020000000000000001000000000000008008000004000000000000000000000000000000000000000082200000000001000000012000000000000000004000002000000000200000000000000080000001000000000000000000000000000000000000000000000100000000000000000100000000000200000000004000000000000000000000000000000200000001000000000004000000100000000000000800080000002000000000000000080000000200000000000000000 +06000000000000000000000000000000000000002000000000000001002000000000000000000000000000000040002000000000000000000000000000000000000000000000022000000800008000000004000000000000000000000000000000000000a000010000000000000804008000004082000000000000000000000010800008020010000140000000000000010000000000000200000000000002000000000000000000000000001080000000000000000000000021000000000000000000000000000000000000000000000000080000000004000040000000000000000001000000000000020000000020000000200000000000c0000000000000 +20000000000200000000010000000000000000000000020021000000000000000000000000000004000000000000000000000000000000000000000000000000000000000010000000142000000000000004000800000000000000000000000200000000800000000000010000000000000010408000000000000000000000081000000000000008030000000800040201000000008000000000100000000000009000000000000000000000102000000000004000000200000100000000200000000010000020100000000000800000000000000010000000044000040000000000000080000000000002000000002000000008000000040000000000000000 +00000000800000000000010000000000000000000000000000000000000200000000000042000000080000800000000400000000000000000000800000000000000000000000000000000000000000000000000000001000000000000002000000000004800000000000000000000000010000008000000000000000000000000000000002000000000000000000000000010000000000000000000800800000000000000200000000000000100000000000002001000000000000000000000000000000000000000400000000002000008000000000004000004000000004000000000002000010000002000000000000000000100000000000000000000400 +0240000200200000000001004000400000000000000000000000000000000000000000080000000004000000001000002000004000000000000000000000000000000000000000000001000000001000000000000000c000004000000000000000000000000000000800000000400000000000000000000000000000000000000000000002000000010000000000000000000000008000000000000000000000000000000000000000020000100000000000000020100000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000002000000000000000000000000000040000000000200 +00000000000000000000010000000000000000000000000000000000000000000000000001000000000000000000000020000000000000000000000000000000000000000000000000000020000000000004000000000000000000000000000800000000800000000000000000000200000000000000000000000000000000000000000000002000010100000000000000008000408000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000080000000000000024000000000000000000000000000000002000000002000000000000000000000000000000000 +05000000002000000000010000000000000000000000000000000004000000000000000004000040000000008000000400000000000000000000000000000000080000000000100000000000000000000004000000000000000800000000020000000000000000004000000000080000000000408000000400000000000000001000000002000000000200000000000200000000000800000000000800000004000000000000000000000000100004000040000000000000000500000000000000000000000000000400000000000000000000000000000000004000000000800000420000000080000002000000000000001000000800000040000020000000 +00000000000000000000010000000000001000000000000020000000000000000000000000000000000000000000000020000000000000000000000000000000001000000000000000000000008000000000000800000000000000000000000000000000800000100000000000000000000000020000000000000000000000000000200000040000010001800000000001000800008000000000000800000000000000000000000000000000100000000000000000080000000000000800000000000000000000000000000000000000000000040000000000004004000000000000000000000000000002000000000000000000000000000000000014000000 +00000400000004000000010000000000000000000000100000000000000000020000000000000000000000000000020000000000000000000000000400041000000400000000000000000004002000200004010000008000000000000000000000000800840000000002000000000000000000408000000000000000000000001000000012040004010000000000000000040000008000000000020000000000010000000000000020000000100000000400200000000000000100000100000001000000000000200000000000000020000000002000000000004204200000800100000000000000000002000000002040000000000004000000000200000000 +00000000000200000000014008000000000000202000000000000001000000020000000000000004000000000000000000000000000000000000000000000000000010000000020000100000000000000004000008008000000000000000000000000040800001000002000800080400000000408000000000000000000000000000000006000000000000200000000001000000000000000001000000000000300000000100000000000000100000000000010000000000000000000000000001000000000000000080000000000000000008080000000000004000000000000000000100000000000002000000002000000010000004000000000000400000 +02000000000000000000010000001000000000000000000000000001000000020000000000004000000000000040000400000000000000000010000000400000000000000000020000000000000000000000000800000000000000000800000000080000000001000008000000000000000000009000000100400000000000000080200000400000012000000000000000000000000000000000000800000000000000000000000000000020100000000000000000008000000000000800000000000000000000200c00000000004000000008000000100000004004000000000000000000000002000402000000000004000080000000000000000000000000 +00000000000000000000010400000000000000000000000000000000000000820000000002000000000000008100000420000000000000000000080000000008000400001000000000000000000000000010000000008000100000000000000000000000000000000002000000000200000000002000000000000001000000000000000002000000010200000000000001080000008000000000000001000000000000200000000020200000100200000401000000000000000200000000000001000000200000200000000000000020000000000000100000004000100000000000000000000080000002000000000000000000000004000000000000000008 +0200000000000000000001000000000000000000000000000000000000000080000000000800000004000000000000000000000000000000000000040000000000000000000000000000000000000000000001000400c000004000000000000000600800000000800002000000000000000000000010000000000000000000000000000002000000010000000000000021800000000100000000020000000800000000000000000000006000100000000000000000000016000000000040000001000000000000000000000000200000000000000000000000004000000040000000000000000020000002000000000040400000000000000000000000000000 +00000000000000000000010000000000000000000000000000000040000000000000000000080000000000000000000020000000000000000000000000040000000000000000000000000000000000000004000000008000000000000080000100000100800000000002400000000000000000408000000000000000002002000000000012040000010000000000000000040000008000004000000000000000010000000000000000000000100000000000000000000000000100000000000000000000000000000000000000000000000008000000000000004204200800800000000000000000000002000000002000000000000000000000100200000000 +00000400000004000000018000000400000100000000100000000000000000000000200000000000000000000000020000000000000000000000000000050000000000000000000000000004000000200004000000000000000000000000000000000000840200000104000000080000800000408000000000000000000000001000400012000004012000000000000240040000000000000000000000100000010000000000000000000001100000000202000000200000000100000100000000000000000000000000000000000000000000002000000000004204200800800000000000000000000002000000002002010000000000000000000200000000 +00000000040000000000000000000000000000000000008000000000000800000000000000000080000000400000000020000000000000000000000000004000000000000000000000000000000000800004000000000080000800000000000000000000000000000000002000000800000000000000000020000000000000000000000002100000010000000000000001000000008100000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000000000000000000000000000000000000000000400004000000000000000008000000000000002000000000001000000000000000000000000000000 +00000000000000000000010040000000000000000000000000000000000000800000000000400200000000000100000400000000000000000000000000020000000000000000000000000000000000000000000004000000100000000100000000004000000004040800000000080000000000002000000000000000000020000080008002040000010000000000010001010000000000000000000000000000000080000000000008008000100100000001000000100000000000000000008000000000000000000800000000000000000000000000000440004004000808000000008000000000000002000000000000000000000080000000100000200000 +0000000040000000000001000000002000000a20000000030000000000000000000000004000000400000000000000000000000000000000000000010000000000000000000000000000000000000000000400000c008000000000000000800000004040800000000000000800000000000000408000000000000000000000000000000002000000000000800000010000000800200000000000400000000000200000000000000000000000100100000000000000000200000000000000000000000010008004040000001000000000000040000000000400000000000002000000000000000000000000004000002000000100000000000000000000000000 +0020000200000000000011400002000000100000000000000000000000000202000000020001000400000000000000040000000800000000000000000000000000000000000100000000000000800000000401001000c000000000000000000000000080000000001003000000080000200000808000000000000000000000040000000402000000010000000100000000000000008000000000002002000000000000000200000000000000500000000400000000100000000000080040000001000000000000000000200000000000000000080000000400004020000000000000000010000000000002000000000000000000004004000000000000000200 +02000000040000000000010000000000000000000000000000000000080000000000000000000000040000000010000428000000000000000000000000000000000000000000000000000000000020000000000000008000004000000080000000200000800000800002000000000000000000008000040000000000000008000000000002040000012000000000000000000000008000000000000000000000000000000000000000802000100000000000000000900000800000000000000001000000000000000000000000000000000008000000000200004004200000000000000000000020000402000000000000000000000000000000000000000000 +0000000000000000000000040000000000000000000000800000000a000000000000000000000000000000000000000400100000000400000000000040000000008000000000000000000000000000080004000000000008000000000000000000000000800000000008000000000000000000009000000000000000000000000000000000002000002000000000000001000000000000000000000000000000000000000080000000000000100200000400000000100000000000000000008000000000000000000800000000004000400000000200000000004000000100008800000100000000000403000000002000010000000000040000000000000000 +00200000000000000000010000000000000000000000000000000000200000000000000000000000040000000000000400000000000000000300000000008000000000000000000000000000000000000000000000008000004000000080000000000000000000000000000000080000000000000000000000000000000000000084080002000080010000000000000000000000000000000000000000000002000000000000000000000000108000000400000000100000000000200040000000000000000000000000000000000000000000080000001400004002000000000000000000000080000402000000800000000800000004000000000000000800 +00000000000000000000010400000082000000000008000000000000800000000000004000004000000040000000000020000000200000000000000000010000000000000000000000030010000000000004000000408008002400000800000000200000844004000202001000080200000000408000000000000000000000080800000032000010010000004000000001080020008000002000800000000000000000000000000020000000108200000440000020000000080000008100000000000800000000000000000000002000400000080000000440204004204000000000000000000800000002000000022000010000000000000200000020000000 +00000000002000800000010000000080000000000000000000200001000000000000000000004000000000002000000420000000000000000000000000040000000000004000020000000000400000000004000000008000000840000182020000000000001001004000000000080000000000008000000002000000000000000000000000400000010200000000000000010000008800000000000000000004000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000800008000000000400004004000000000000420000000080000002000000000000001000000800000000000000000004 +00000000000000000100000000000004000000000000000000000000000000120000000400000000002008000000000400000000000000000000000000000000000000000000020000000000200000000000000008008000000020000000000000000000000000000802000000080000040100000000000000000000000000000000000002000000000000000000800000000000000000000002000000000002000000020000000000000000100000000004000000000000020000000000000001000000000000800000000000000000000008000000000000000000000000000000000000000040000002001000000000000000000004000000000000000000 +0200000000000000000001000000000000000200000000000000000000000000000000184000008000000040000000002000020000000000000000800000400040000000000000000000004080200000000400000000c000000800000100000000000004800000000002000200000800110400000000000000000000000000000000000002000000010000000000000001010000008000000000000000000000000000000000000000202000100200000000000000000000100000000000000000000010000000000000000000000000010000000200080000004000000000000000000000000420000002000000102000002000001000000000000000000000 +00000000000000000000014000000000001000000000000000000000000000020000000000004000000000000000000400000000002000000000000000000000000000000000000000000000000000000000000000008000000004000000000000000800000400001002000000080000000000000000010000000000000000000800000002000000000000000000400000000000000000000000002000000000000000000000000000200000100000000000400000100000000000000000000001000000000000000000000000000100000000000000000200004004000000000000000000000080000402000002000000400000000004000000000000000000 +0200000000000004000001100000000000000800000400000000000002000000000000080000000000000000100000040000000000000000000000000040000000020000000000000000000004000000000401000000c0000000200000000000000000008000000000400000000a00000800004080000000000000001000000a100800000300000c020000004804850000000002000000000000000000000000118200110020000000000000108000000004400000000000000100008000000100000000000400000000000000000000000000000000000c00040000800010000000000000000090000002000000002006000010000000000000000000800000 +0200000000000000000001000000240100000000000000000000000000000000000008004000000004000000000000002000020000000000000000000000000000000000000804000180000000000000000400000020c000000000000000000080000004800200000000000000082000000000000000000000000000000000000080000002000000010000000000000001000000008000400000000000100000000000000000000000102000100000080002000000200000000000000000040000000000002010000000000100000000000000000000000002004040008000000000000000000000000002000000802000010000000000008000000002000000 +00000000000000000000010000000000000000000000000000000002000000820000000001400000000000000100000400000000000000000000000000020000000400000000000000000000000000000000000000008000500000000000000000000000000000040002000000000000000000002000000000000001000000000000000002000000010000000000000001000000008000000000000000000000000080000000000020008000100000000401000000100000000200000000008001000000000000200800000000000020000000000000000000004000000000000000000000000000000002000000000000000000000004000000000000200000 +0a000000000000200000010000000000000000000000000000000100000020000000000800000204000000000000012000000000000000000000000000000000000000000001000000000040000000000004010000000000000000000000000000000000800000000000020000000000000000000100000000000000000000020000000042000000010000000001008001000000008000000000000000000000000000000000000000200000100000000001000000000010000000000000000000000000200000001000000000000000000020000000000000004000000000000000010100008000000002000000002000000000000000000000000000000000 +00000000000200000000010000081000000004000000000020000000000000800000000002000004002022000000000421000000000000000000000400000001040000000000000000000000000000000004010000000000000010000008000000000800800000000000000000000000000000008000000000000200000000000080000002000000010200000000000001800000008000000000020000000000000000000000002000200000108000000000000000000004000000000440000010000000200000000400000000000000000000000000000400004000000000000000000000008080000002000000002040400000800000000082000000000000 +02000000000000000000000000082000000000040000000000000004000004000000000800000000000000400000000000000000000000000000000000040000000000000000000000020000000000000004000000001000000000000080000000000000800000000000000000000000000000408000000040000000000010001000000012000000000000000000000001040000000000004000000000000000000000000000000000000000000000100000000000000010100100000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000002000000000000000000002000200000000 +00000000000000000000010000000400000000000000020000000001000000820000000000000000000000008000000000000000002000000000000000000000000400000000020000000000000000000000000000008000000000000000000000000000800001000002000000000000000000000000000000000000001002000000000002400000010000000000000001000000008000000000000000000000000000004000000020000000100000000402000000000000000000000000000001000000000000200000000000000020021008000000000000004000000000000000000000000000000002000000100000000020000004000000000000000000 +00000000000000000000000400000000000000008000000000000000000000000000000002000000000000000140000420000000000000000000080000000000000000000000020000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000400001000000000000000002000000010200000000000001000000008000000000000000000000000000200000100000300000100200000000400000000000000000040000000000000000200000000000000000000000000008000000100000004000000000000000000000000080001002000000000000000000000000000000000000000000 +00100000000000000000018000000000000000000000000000000000000000800000000000000000000000000100000400000000000000000000000000020000000000000000000000000000000000000000000000010000000000000000000000000000000000000800000000080000000000000000000000001001000020000080008002040000010800000000000001000000008000000010000000000000000000001000000000000000108000000001000000100000000000000000000400000000000000000000000000400000000000080000000400004004000008000000048000000000000002000000000000000000000000000080100000000000 +00000000000000000000000000000000000000000000000000000000004000000000000000000000000004000000008420008000000000000000000000040300000000000000000000000000000000000004000000800000000000000180000000000200800000000000000000080000000000408040000000000000000000000080000210000000010000000000000000050000008000014000000000000000000000000000000000000000100200000000000000000000000100008100000000000000000000000800000000000000000000000000000000004200000000000000000002000000000402000000002000000000001000000000000200000000 +02000000000200000000010000001000000000200000000420000000000000800200000800004000002022000000000401000000000000020000000000000000000000000000000000000000000000008004010000000000000000000408000040000000800000000000000000080000000000408000000000000000000000000008000002000000000000000000000001100000000000000000000080000080000000000000000020000000100000000000000000000000000000000404000000000000200000000000000000800000000000000200000000004004000088000001000000000000800002000000022000000000800000000000000000200000 +00000000000000000000010000000000000000000000000020000001000000000000000000004000000000020000000000000010200000000000000000000000000000000000020000000000000000000004000800000000000000000000000000000000800001100000000000000000000000000000000000000000000000000000200002400000000000000000000001000000000000040000000800000000000000000000000000000000100000000000c00000000000000000000800000000000000000000000000000000000000000008000000000000004004000400000000000000000000000002000000002000000000000000000000000000000000 +00000000000000000804000000000000000000000000000000000000000000000000000000000100000000000100008400000000000000000000000040000200000000040000000000000000000000000004000010000000000000080002000000000000800000000000000000000000000000400010000000000001000000000000000012100000010000000000000001000000008080010000100000000004000000000000000000000000100200000000000000000000010000000000000000000200000000000800000000000000020000000010000000004000008000000000000000000000008402000000002000000000000100000000000000000000 +00100000000000000000010000000000000000000001000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000800000000000800000000080200010000000000000001000000000020000080008002040000010900000000000081090000000000000000000000000000000000000000000000000000180200100001000000100000000000000000000000000000400000100008000000000000000000001000000400004004000008000000008000000080000402000000000000000000000000000000100000000000 +00000000000000100000010000008000000000000000000000000002000000000000000000400000040100000110000400000000000000000000001000020000000000000000000000000000000000200000000800008000104000000000000000200000400000040002000000080000000000000000000000000001000000000000000002000000010000040000000001000000008000000000000800000000000080000000000020208000108000000001008000100000000000000000008401000000000000000800000000000000000000000000000400004001000000000000000000000000000082000020000000000a00000010000080000100200000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000100000000000000000000000000000000000000000000100000040000000000000000000000000000000000100008000000810000000000000000000000002000000010000000000000200010800208000000000000000000000000000000000000000000000100000000000000040100200000000000000008000000000000000000000000000000000000000100000000000004000000000000000000400000000000002000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000001000000000000000000000a00000002000000000000000000000420000000000020000000040000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000200000000000200000000000000000000000000000000000000080002000000010200000000000000090000008000200000000000000000000040000000000000200000100600000000000000000000000000000000008000000000200004000800000000000000000000001000100000004000000000000000000000000080000402000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000001000000000000000000000800000002000000040000000000000420000000000000000000040000000000000000000000040000000000000000000000000000008000000000000100000000200000000000000002000000080200000000000000000000000000000000000080000002000000010200000000000000090000008000200000002000000000000040000000000000200000100600000000000000000000000000000000000001000000200000000000000000000000000000001000100000004000000002000000000000000080000002000000000000000000000010000000000000000000 +00000000000000000000010000000000000000000040000000000000000000002000000000000204000000400000000000000000000000000080000000000000000000000000000000000000000000000004010000000000000010000000000000100000802000000040000000080001004000000002000000008000000000000000000002000080010000000001000000000000008000000000000000000000000000000000000000000000300000000000000010000010000000000000000000000000000000001000000000000000000000200000000400004000000000000000018000000080000002000000002100000000000000008000000000800000 +0a000000000200000000010000000008000000000000000020408000200800000000000800004000000000000102000400000000000000000800020000000000000400000010000000002004000000000004000800000008000000000800000000800000800000000000000000000200000000408000000000000001000000001081800002000000010000000000000001110000408000000000500000000000000000000100000000000400108200000000000000c00000000000000000000002000000000000000000000000000000000000000010000000044000000080000000000000008100100002020000042000010000110000000000000004000000 +0040000000000000000000000000000000000080000008000000000000000200000000000000000000000000000000a08200000000000000000000000000000000000000000000000000080000000000000400000c044000020000000000000000004000880000000000000000000000000000008000020000000000000000000080000002009000010000000000000001000000000000040000000000000000000000000000000000000000108100000000000000000000002000000000000000000080000000000000000000000000000000000000000400004400000000000000000100000000000002000000002000000000000000000080000000000000 +0000000000000010000001100000800000000000000000000000000000000001000000000000000004010000001000040000000000000000002000100002000000000000000000000000000000002020000001080000800010440000000000000020000040000000080200000008000001000000000000000200000000000000000000000200000000020004000000002101000000000000000480080000000000000000002000002020c000100000000001008000100000000000000000000041000000000000000000000020000000000000400000000400004801000000000000040000000000000082000000000000000a00000010000000000120000000 +00000000000000000000008000000000000000000000000000000000000000000000000000004000000020000000000420000000000000000000000000000000000000000000100000000000000000000004000000004000000820000000020000000000000000004000000001000000000000008000100080000000000000000000000210004000012800000000000001000000008800000000000000100004000000000000080000000000100000000000000008900000000000200000008000008000000000000000000008010000000000000000000000004000000008000000420002000000000802000000000000000000000800000000000000000000 +02000000000000000000100000000000000000000000000000000000000000000000000000000004000000000100000000000000000000000000000000000000000000000000000000000000000000000004000000000000080000000008000000000000000000000000000800000000000000000008000000000001000000000000000002000000010000000000000000000000008000400000000000000000000000000000000000000000100000000200000000000000100000000000000000000000000000000000000000000000000000000000000400004000000100000000000000000000000002000000000000000000000000000000000000000000 +00100000000000000000010000000000000000000000000000000000000000800000000000000000000000000000000401100000000000000010000000020000000000000000000000000000000000000000010000010000000000000000000000000800000000000800000000080000000000000000000000001000004020000080008002040000010800000000000001010000000000000010000000000000000200001000000000000000100000000001000000100000000000000000000000000000000000000000000000000020000000080000000400004004020008000000048000000000000002000000000000000000800000000000100000000000 +0000000000000000000000000000000004002000000000000000000800000002000000000140000008000000010000040010000000000000000000000002000000000000000000000000000000000000000000008000800040000000000000000000000000000000000a000000000000000000009000000000000001000000000000000002000000012000000000000004000000008000000000000000000000000080000000000000000000100000000400000000100000000000000000008001000000000000000800000000004000000000000000000000004000000000000000000000000000000403000000000000000000000004000000000000200000 +00000000000000000000011000080000000000000008000000000000000200000000000000000004048000000000000420000002000000000000000000000001000000000080040000000000000000000004000080008000000000000003000000200000040000000002000000080800000000008000000000000000000000000081000002040000010200000000000000000000008000000000000000000000000000400000000000002000100008008000000000100000000000040000008001000000000000000000000000000000000000000100000400004004200000000000000000000280000002000000000000000000000010000000000000000004 +00010000020200000000010000000400000000000000000020000000000000800002000000000000002000000008000000010000000200000000000440000000000000000000000000000000000000000004010800000000000000000000000000000800800000000000000000000000000000000000000000000200000000000000000002000000010000000000000001800000000000000000020000000000000000000000000800000000100200000002000000000004000000000040000000001010000020000000000000000000020000000200000000004000000000000000000000000000000002000000002040400000000000000000000000000000 +00000000000000000000010000000400000000000040000000000000000040000000800000000004000000000440000000000000000000000000010000000001000000000080020000000800000400000004000000000000001800000000020000000000000200004000000000080000000000008000000000400000000000000080000000000000010000000000000000000000000800000000000000100000000000000000000000000000100000000002000000a00000000000000000000000000000000000000000000000000000000008000000000000004000200000000020000000000000000002000000000000010000000800000000004000000400 +00000000000000000000010000001400000000000000000000000000000000000000000042000000000000000002000600040000000000000000000000000000000800000000000000000000020000000000010000040000000100000000000000000000000000000008000000000010000000400000000000000000000000080280000002000000010200000000000000000000000000000000000000000000000000000000000000000000100000000000000040000002000000000000001000000001000000000000000000000000000000000000000800004000000000008000000000000080000002000000000000000010000100020100000000000400 +02000000000000100000010000000000000000002000000000000001000000080000020840000000040000000000002420000000000000200000000000000000000000000000020000000000801000000000000000808400004000000800000000200000000081000002000000080200000000001000000002400000000000000000000102000000000204000000000001000000000000000000000000000000000010000000000000200000100000000000000000000000000000000400000001000000002000000000000000000000000008000000000020004000000000000000000000000080000002000000800000000080000010200000000004000000 +00000000000000000000000000000000000000002001000000000000000000000000000000000002000000000000000400000000000020000000000000000040000002000000000000000000200000000000000000000000000000000220000000000000800000090000000400000200010000c08010000001000080000000080000080012000000010100000000000100090000004200000000000000000084000020000000020000000000180200002000080000000000008000000000808000000000004004000c01000000000080000000001000000000004000000000000000000400000080000402000000000000000000100000000000000000000000 +00000000000000000200010000000000000000000000000000800000000000000000000040000000000000000000002000000000000000000000000000000000000000000010000000000004000000000000000000000000000000000002000010000000800000000400000000080000000000408000000000000000000000001080000012000000010001000000000200040000000000000000000000000000000000000000000080000000100000000800000000000000000100000003000000000000000000000400000040000088000000000000000000004000000000000000000000000402000002000000000000000000000000000040000000000000 +00400000000000000000000000000000040020000000000000800040000000000000000000400000000000000100000400008000000000000000000000020000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000200010000408000000001000000000000000000000002000000000100000000010200090000000000000000100000000000000080000000000000000000180000000000000000100000010100001000008200000000000000000800000000000000000000001000000000004000000000000000000000000000000002000000000000000000000000000000000000200000 +00000000000000000000000000000000000002000000000400000000200004000200200000000000000000000000000400000000000000000000200000000800000000000000000000000000000000000004000000008000000000000000000000000000800000000002000000080000000400108000000000000000000000000080000202000000010000000000000001100000000000000000000000000000200000000000000000000000100200001000000000000000000000000000000000000000000000000000000000000000000000000000080000004000000080000080000002000010000002000000002000000000000000000200000000000080 +00000000000000000000010200000000000000000000000000000000000200010000000000000404080000000002000420000000000000000000800000000001000000000000000000000020000000000004010000000000000000000100000000000000040020000000000000000200001000408000400000000000000000081001000002000080010200000000000000090000008000000000000000000000000000600020000000000000108000000040000000100010000000000000008000000000000020000000000000000000000000041102000004004000000000000000000000000080000002000000004000000000000000000000000000000000 +00000000000000000000010000000000000000000001000000000200000000000000000080400004040000000040000400000000000000000000200000020000000000000000020000000000000000000004000000000000000000000000000000000000040004000000000000000000000000008000000000400000000000000000000000000000010200000000200000000000008000000000000000000000000000004000000020000000100000000000000000100000000000000010008000000000000040200800000000000000000008000100000000004000200000000000000000000000000002000000000000000000000000404000000000200000 +00000000000000000000000000000000000000000000000000008008000000000200000000000000000000000000000400100000000020000000000000020000018000000000000000000000000000000004000000000000000000000100000000000000000000000008000000080000000000049000000000001000000000000000080000000000012000000000000000010000000000000000000000000000000000001000000000000000100000000000000000100000000000000000008000000000000004000800000000004020000000000000000000004000000000008000040000000000000403000000000000000000000000000000000000000000 +00000000000002000000010200000000000000000000000000000000000000000000000000000202000000000000081400000000000000000000000000000000000000000000000000000000000000000800000000008000000000000002000000000000000000000000000000000200000000400000000000000000000000080800000000000000010000040000000000000000008000000004000000000000000000000022000000000000100000000400000000110000000000000000200000000000000000000000000000000000000000000000000100004000000000000000020000000000100402000001000000000000000004000000010000000000 +00000000000000000000010000000000000000000000000000000400000000000000000000000204000000000000400000000000000000000000000000000000000000000000000000000000010000000004000000000008000000000000000000000000000000000000000000000000000000408000000000000000000000000001000000100000030000040000004000000000008000000000000000000000000000000000000060000000100000001000000000000000000100000000000000000000000000200000000000000000000000000000000000004000200000000000000800000100000402000000000000010000000000000000000000000000 +00000000002800000000000000000000000000000000000080000000000000000000000000000000000000000400000400000000000000000000000000000000000000004000000000008000000000000004000000000000001800000000020000000000100000004000000000080000000000008010000000000000000000000000000002000100010000000000000000000000008800000000200000000004008000000000000000200000109000000000000200000000000000000000008000000000000000000000000000800000000000000000000400004000000000000000020000000c10000002000000000000000000000800000080000000000000 +00000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000020000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000800000400000000000000000000000000000000002000000010000000000000000000000008000000000000000000000000000000000000010000000108204000000000000000000001000000000000000000000000000800000000000000000000000000000000000044200000000000000800000000000000002000001000000000100000000000200000000000000 +000000040000000000000100000010000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000020000000000000002000000400000100000000000000000008c0008000000000000800000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004204000008000000000000000100000002000000000000000000000000000000000000000000 +00000000000400000000080000008000000000000000000000000000000000000800000000000000008000000002000000000000000000000000000000001000000040000000000000020000004000000004000000008000000002001800000000000000800000200002020000000000000000408000400000000400000000080000000002000040010000040000000001000000009000000000000000020000001008000120000020200000100000000000000000000000000100100000000000000000200000000000000000000000000000002000000000044200000080000000800000000040000002000000002000000004000000100000000000000080 +12000000000000000000004000000100000000002001008100000001000000000000000802000080000000400000000600000000000000000000000000004000000000000000022000000000000000000204000100008000000800000000000000000000800001000008000000080800000000000800001000000000000000004000000002002000010a00000000000101000000008000000000000000006000004000000000000000000000108000000000000800100000100000000000008000000000000000000000000000000000010808000000001400004000000000000000000100000080000002000000002000000000000004000000000000000000 +00000000000000000000010000000000000000000000000000000001000000010200000000004000000000000000000400000000000020000000000000000000000000000000020000000000000000000000010000000000000000000100000000000080000001000200000000000000000020000000000000000000000000000000080080400000010000000000000000010000000000000000000000000000000000000000000020000000100200000000400000000000000000000000008040000000000004000800000400000000000008000000000000004004000000000000000000000080000402000000400000000800000000000000002000000000 +0000000000000000000001800000000000000000000000000000000000000000000000000000000000000000010000040000020000000000000000040002000800000000000000020000000000000000000001000000000000000000000000000000080000000000000000010008020000000000000000000000100100000000000000000200000001200000000000000008000010800000000002000000000000000000100000000000000010800000000000000010000400000000004000040000000080000000000000000040000000000000000000040000400000000000000004000000000000000a000000004040400000000000000080000000000000 +000000000000000000000000000020000010000000000080000000000000000000000000000000000402000000000004020000000000000000000000000800000000000000010400000000000000000000000000080080c0000000000002000000200000800000000002000000080000010000000000000000001000000000000080008002000000010000000000000001010000000000000000000000000500000000000200000000000000100000000400000000000000000000000000000001000080000000000400000000000000000000000000000000004000000004000000000000000080000002000000000000000000000018000000000000000000 +00020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000401100000000000000010000004000000000000000000000000000000000000000000018000000000000000000000000000000800000000000000000000000000000000400000000000000000004000080000000000000000000800000000800081010000000000000000000000000000000000000020000000000000100200100000000000100000000000000000000000000000000020100008000004000000000000000000000004004000020000000000000000000080000402000000000000000000800000000000000000000000 +00400000000200000080010002400000000000000000008000000000000002000000000040000100000000000000008000000000080000000000000040000000000000000000000000000000000000000004000008000000200000000002000000000004800000000008000000000000280008000040000000000000000000000040000002002000010000800000000001000000000000000000000000000000000000000000001000200000500200000000001000000000000000000000000040000090000000000000000000000000020020000200000000004000000000000000000100000000000002000000002000000000000000000000000000000000 +0000000000020000000401100000000000000000200000002000000100000000000000000000000000000000000000040000801000000000000000000000010000000000000002000000210000000000002400080080000000000000000000000000000080000000000000000008000000000040c000000800000000000000000080000202000000010001004800000201000000000200000000000800000000000000000000000000000040100000400100000000000000000500001080000004000010000020000000000000000000000008000000000600004000400000800000000002000080008012000004802000000000100000000000000000000400 +04000000000200000000010000000000000000000400000000000004000000080000000040000000000000000000000402000000000000000000000000000000000000000000000000000000000000000004000008000000000000000000000000000004800000000000000000000000080000408000000000800000000000001000000003000000000000000000000201100000000000000000000800000000000000000000000000200000500000000040000000000000000500000000000000000011000400000000400000000000000000000008000000000080000000800000000100000000000000000000002000000000000000000040000000000000 +00000000000000000000000000000000000000000000008000000800000000000000000000000000000000000000000420000002000000000000000000080000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000080000040000000000000000000000000000000000000002000000010800000000000001000800008000000000010100000000000000040000000000000000100000000000000000000200000000000020110000000000000000000000000000000000000000000000000408004000000000000000000000000080000002000000000000000000000000000000000000000000 +00000000000000200000010000000000000008000000000000000001000200000000000040000000000000000000000400000000000000000000010000010000000000000000020000800000000000000004000020008000010010000002000000000004800001000000000004000000000000408000000000000000000000000000000002400000000000000000000000100000000000000000000000000010000000000000000000000000100480000000001000800000000000000000000000000010000000000000000000000000000008000000000000004000002080000000000002000000000002000000802000000000000000000000004000000000 +00000000000000000000010000000000000000000000000000000000000210000000000040100004000000000000000420000020100000000000000000000801000000000100000000000000000000000004000004000000000000000000000000004000040000080000000000000000000000008000000000000000000000000001200002040000030200000002000201000000008008000000000800000000000000540000000000400000100100000001000000100000000000000000008000000000004000000000000001000000000000000100004000004004000000000000000000000080000002000002000000400000000000000000004000000000 +02040000000000000000010000000000200000000000000000000000000000080000000800000004000000000002000000000000000000000000000002000008000000000000000000000000000000000004010000002000000000000000000000000000800000000000000000200210000000410000000000000000000000001000000002000000000000000000000000000000200000000000010000000000000400000000000000200040108000000000000010000010080002000000000000000000000000009400000000000000000000000000000020044000000000000200000000008000100002000000000000000000000000000000000000000400 +02000000000000200004010000000000000000002000000080000001080000000000000000000000000000000000000020008000000000000000000000000100000000000000020000000100000000000004000000800000000000000000000000000000800000000000000000080001000000408000000000000000000000000080000200400000010000000000000000000000008000000000000000000000000000000000000000002000100000000000000000000000000102021000000000000000002000000000000000000000000008000000000000004000000000800000000002000000000002000000000004000000000000000000000000000100 +00400000000000000000012000000004000000000000000030000000000002800000000002000004000000400040008400010000000000000000000000000000000000000000000000120000000000000004010008000200000080000000000000000000810000000000000000000000000000408000000000400000010000080080000000000000010200000000000001000000000000000000000000010008000000000020000000110000100000000000000000000000100100008000000000002080000000800000000000010000000000000010001000004000000000000000000000200000000002000080002000000000000080000000000000000000 +02000000000000000000012000000000000000000000000020000020000000000000000840000000000000400000000020000000000000400000000202000008000080080000000000021000040000000004000800000240000000000800000000000004810000000020000000000200000000408000000000400000000000081000000002040000010000000200000801000000008000000000000000000040000000000020000000000000100000000000000000000000100100000000000000000000040000000000000000000000000100000000000000004004000000008000000000000000000012000000802000000080000008000000000000020000 +0000000000000000000001000000000000000000002000000000000000000000000000000000000000000000010000040000020000000000000000040002000800000000000000020000000000000000001001000000000000000000000000000000080000000000000000010008020000000000000000000000100100000000000000000200000001200000000000000008000010800000000002000100000000000000100000002000000010000000000000000010000400000000004000000000000080000020000000000040000000000000000000000000400010000000000004000000000000000a000000004040400000000000000000000000000008 +00000000000000000000000400000000000000000000008000000000000000000000000002000000000000000000000421100000000000000010080000080000000000000000000000000000000000000000010000000080100000000000000000000800000000000000000000000001000000000000000000000000004000000000000000000000010200000000000001010000008000000000000000000000000040000000000000200000100200000000000000000000000000000000100000000000200000000000000000000000400000000000100004004000020000000000000000000080000002000000000000000000800000000000000000000000 +02000000000000400000000400000000000000000400000102000000000000000000000000008080000000400000400420000000000000000000000000000000000000000000000000000000000000000004000008000008000800000100000000000000010000000000000000000000000000008000000000001000000000000000000000000000012000000000000000010000008000001000000000000000000000000000000000004000100000000c0000100010000010000000000000c000000000000000000000000000000000400000000000000004004004000000000000000000000010000002000000000000410000100008000000000000000000 +02000000000000000008010000000000000000000000000000000001000000000000000000000000000000000000000420000000000000000100000000002000000002000000820000000000000000000010000000002000000000000c00000000000000000001000020000000000200000000000000000000000000000000000000000002400000010000040000000008080000008000040000000000000000000000000000000000002000100000000000000000100000000000000000000000000000000000000000000000000000000008000000000000004000000000000000000000000020000402000000000000000080000000000000000000000000 +00000000040004000000010040000000000000040000000000000000000000000000000000004200000000400000000000000000000000000000000000040000000000000000000000020004000000200004400004001000000000000000000000004000040000000000000000000000000000408000000040000000000010001000000012000004000000000000010000040000000000000000000000000000000000000000000000000000100100000040000000000000100100000000000000000000000000000000000000000000000008000000000000004204200800800000000000000000000002000000000000000000040000000002000000000000 +0000000000000000000001000000000000000000000000000000000001000002000000000000000000800000000000002000000000000000000000000000000000000000001000000008004000000000000000000000c000000020000000000010000000000000000002000001080000000000402000000002000000000010001000000412000000010000000000000000040000008010001000002000000000000000000000000000000000100000000800000000000000000000000000000005000000000000000000000040000008000000000000000000204000000000000000000000000000000002000000000000000000000004000000000000080000 +00010000000000000000010000000000000000400000000020000000002000000002000040004000000000000000400420000000000000000000000040000000004000000000000000800100000000000004000800008004000000000000000000000004800000000000000000080000000000008000000000000400000001000000200002040000010200000000000201000000018000000000400800000000000800000000000000200000100200000000000000100000000000000000000000000000000000000002000000000080000000000200000020004004000000000000000000000000000012040000802000000000100000000000000001000000 +00000000000000000000010200001000000000000000000000000000000000000000000000000202000020000000000420000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000800000080000002000000240000000400000000000000000000000000000000000000000010000040008000000000000008000000000000002000000000000000000000000000000100200000000000000000000000000000000000000000000000000000000040000000000000100200100000000004000000000000000000000000000100402000000002000000000800000000200000000000000 +00000400000000000000000000000000000000000000008100000004400000000000000000000080000000400000400020000000000000000000000000040000000000080000008000020004000000200004000000000088400000000080200000000000850000000000000000080000000000408000000000000000000000001080000010020000010000000000008001040000008000000000000000000000000000000000000000000000300080000000000000000000108100000000000000000000000000000100000000000000400000002000000000004200000000000000000100000000000002000000002000010000000000000000000200000000 +00000000000000000000000040000000000000000001000000000000000000000800000002000200000000000000000420000000000000000000040000000000000000000000000000000000000000000000000004000000000000000100000000004000000004000000000000080200000000000000000000000000000000000080000002000000010200000000010000090000008000200000002000000000000040000000000000200000100700000000000000000000000000000000000000000000200000000000000000000000000000001000100040004000000000000000000000000080000002000000000000000000000080000000000000000000 +00010010000000000000010400001000000000000000000020000000000000810000000000000000000020000000000420000020000040000000000040040000000800000000000000040000000000400024010800000018000000000000000400000000802800000000200000000000000000408000400000000000000000000000000000040000010000000000000201000000008000000008000080000010000000000000000008000040100000200400000002000000000504000000000040000000200000000000004000000000400000000000000000004004000000800000000000000002000012000002802000010000000000000000000000000000 +00000000400000000000010000000000000000008000000000060000800000000000000040000000000000000100000000000000000000000000000000000000000000000000020000000000800200000000000000000000000000000002000000000004800010000000000000080000000000408000000100000000000000080008000002000000000000000000000200000000000000000000100000000000000000000100000000000000100000000000000000000000080100000000000000000000000000008400200000000110000000000000000000044800000200400008000000000000000002000100000080000000000000100000000040000000 +0040000000000000000000400000000000040000000000810080004080000003000000000000000000000000010000040000800000000000000000004000001000000000000000100000000000000000002401000001800000000000000000000000000080000010000a000000080000110000408000000000000000000400000000000002000000000000000000000201010000000000000000102000000000018000000000000000000000108200000000000000000000000100001000000041000000000000000000000000000000020000000200000400004000000000000800000100000080000012000000402000000800000004040000002000000000 +02800000000000000004010400000000000000000000000000000000000000000000000000000000000000000000000020000000000000000020000000000000000000000000000000000000000000000000000000004008000000000000000000000000000000000800000000500000000000408000000000000000000000000000000000000000030000000000000000000000008000000000000000000200000000000002000000123000100000000400400000000000000100800000000000000000000000000000000800000000400000000000000000004000000000800000000000000020000002000000000000010000000000000000000000010200 +02000000000000000000000000000080000000000000008100000000000000000000000800000000000000000000000400000000000000120000000000000000000000000000002000000000000000000004010000000000100800010400020000000000800000004008000000080000000000408000000000000000001000000008000002000000000000000000000001000000000800000000000080000000008000000000000020000000100000000800000000000400000000000000000000000000000000000000008000800000010000000000000410004000c00000000001000100000000800002000000022000000000100800000404000000000000 +00400000000000000000014800001000000000000000000010000000000802020000000000000040040220000000008421000000000000000000000000000000000000000000400000000000000000000004010008008000004000000008000000200800840000000002000000080040000000008000000000000000000000000000200002040000010000000200000200100000008000000000000800010000200000000000000000000000100000000000400000020000000000000000000001000080000000000000000000000000000000200000000000006004000000004000000000000020000002000000002000000400800014008000000800000000 +004000000000000000040120080000000000000004000004208000200000000000000000000000000400000000000004000080000000004000000000002000000000000000200000000000000000000000240008080182000040000008000000002000008100000000020000000820000000004080000000024800000000000810000000020000000002000002000002010000000000000000001000000000000000000000200000000000c0100000000000000000000000000500000000000001000000000000000200000000000000200000400000000000004000000000800000000000000080000012000000802000000000000010000000000000000000 +02800000000000000000001000000000000000000000000000000000000000010000000000000000000000000000800420000000000000000020000000040000000000000000000000040004000000600004410000000000000000000080000000000000840000000a00000000000000800000408040000000000000000000001000000012008000010000000000000000040080008000000000000000000200000000001002000000002000100000000000000000000000000100000100000040000000002000000000000020000000000000000000000400004200000000000000000000000000000002000000002000000000000000000000000200000000 +02000000000400000000020000002000000000000000040000000200000000000000000000000200200000000004000020000000000000000002000000000000000040000000000000000000000000000004020000008200000000000000000000000000800000000002004004000004000800400000000000000000000040081000000002000000010000040000000001000402008000000000000000000000001000000020000000002000100000000000000000000000000000000800000000000400002000000000000000000000000000000000000000014000000000000000000000000000000002000000002100000000000000400000000000000000 +02000000000000000000010000000000001000000000000000000000000000020000000000000000000000000000000020000000000000000000000000000000000000040000000000000000000000000000000900008000000000000800000000000000000000000002000000008000000000000000200000000000000000000000000002000000010000000000000001000000008000000000000000000000000000000000000000002010100000000400400000000000000000000000000001000000002000000000000000000000000000800000000000404000020000000000000000000000000002000000000000000000000004000008000000004000 +00000000000200000000010400001000000000000000008400000000000000000200000000000000000020000000000401000000000000000000000000000000000000000000000000000000000000008004000000000008000000000008200000000000800000000008000000000004200000408000000000000000000000081000000000002000000000000000000001100000000000001000000000000000000000000020000000000000100000000400000000800000004000000400000000000000000000000001000000000000400000000000000000004000000080000000000100004000000002000000402000010000800000000002000000000000 +00010000000000000000000000000000000000000480000000800000000000000080000000000000000000000100002402000000000000002000600040000080000000000000000000000000000001000004000008000000000802000000000000000000c00000000000000000000000000000008000000000000049000000000000000002000000010000000000008201000000008000200000000000000000000000000000000000000000100000000000100000100000000000000000088000000000000000000000000000000000000000000000000400004000000040000000000100000000000102000000102000000010000000000000000000100100 +00000000000000000000010000000000000000000000024000000000000000020000010000000020000000000040000028000000000000000000000040000000000000000000020400000000000000000004000000008000000000000000000000000000800000000802000000080001000000408000000000000000000000080000000002040000030000000000000001000000008000000001000040000000000000200020010000000000100000080000400000002000800100048000000001000000000000000000000000000000002008000000000000004004240000000000000000000000000002000000002000000000000004008080000040000000 +02000000000000000000010000004000000000000000000000000000000000000000000800000000002000000000000000000000000000000000000000000000040000000000800000000000000000008000000000008000000000000200000000000400000000000000000000000000000000000000000000000000000000000080000002000000010000000000000000000800000000000000000000000000000000000000000000000000108000000000000000100000000000000000000000000020000000000000000000000000000000000000000400004000000000000000000000000000000002000000000000000000010000000080000000000000 +0020008200000000000001000000000000000800000001000000000000000000000000000000080800000000000000002000000000000000000000000000000000000000000000000020000000000000000400000000c000000000000000000000000000800000000800000000080000000000000000000000000000000000000000200000040200010000000000000000000000008000000000000800000000000000100000000000000000100000000000000000000000080000000000000000000000000010008400000000000000000000000000000080004004000000000000000000000000000002000000002000000000000000000000010080000202 +02000000000000000000010000000000000002000000000001000004000000000000001840000000000000000000000020000200000000000000008040000008400000000000000000800000800000000004000000004000000000000000008000000004800000000008000000000200100000000000000000000000000000000000000002000000010000000000000001000000008000000000000000000000000000000000000000202000100000000000000000000000000000000000000000000010002000000000200000000000000000000000000000004000000000000000000000000400000002000000100000000000000008000000000000000000 +00000000000000000000010000020000000000000008000000000000000000000000000040000004000000000000028400000002000000008000010000000001000000000000000000000000000000000004000000000000000000000000000000000004040010000000000000080000000000008000000000000000000000000800000002000000000000000000000200000800000000000000000000000000000000000000000000000000108000800000000000000200000000000000000000000000200000000000000000000000000000000000000400000000000000002000000000000082000002000001000000000000100000000000000000000000 +0000000000060000000001000000000000000040040000800000000000080000000000004080000400000000000200040000000800000000000000020000008100000000000000000000000002000000000401000800000000800000000000000000000c800000000009000000000000a00000448010000000000000200000020000000012002002000000000000000001100800000000000000000000000004100000000100000080000000100000000000000000000000000000000000000001000000000000000000000000000000000000000000082400004000000080000000008500000000000002000000002001000000000000000100000000000000 +00000000000800000000010080000400000008002000000000000001000000000000000000000004000004000040000400010001000000000000000000000001000000000000020000000000000000000004000000000000000000000000000000000000100001000000000000080000000000009000000020000000000000000000000002000000000000000000000000000000000008020000000000000000000000000000000020200080120000000000000000900000000000000000008000000000000000000000000000000000400008000100000000204000200000000000000000000000000003000000000000000000000000004000001000000000 +00000000000000000000002000000400000000000000000000000000000000000000000000000000000000000040810420000000084000000000020000000000000000000000020000000000000000002000000000000000000000000000000000000000000000000008000000000000000008009000000000400000000000000001400000000000012000000000000000000000008000000000000000000000000000000000000000000000100000000002000000000000000000000000000000000000000000000800000000004008000008000000000000004000000000000000000000000000000402000000000000000000000000000000000002000000 +00000000000000000000010000000000000000000000000000000000000000800000000000000000040000000000000420000000000000000000000000020000000000000000040000000000000020400000000000008000100400000100000000200200000000000002000000080000010000002000000002000000000000000080000002040000010200000000000021010000008000000004800000000000000000000000000000208000100000000001000000100000000000000000000001000000000000000000000000000000000000000000000000004004000002000000040000000000000002000000000000000000000010000000100000000000 +02000000041000000000010040000000000000400000000400000000000000000200000000000200000000000000000420000000000000000020000000000000000000000000000000000000000000000000000104000000000000000000000000004000000800000000000000000000800000408000000000000000000000001000000000040000010000000100010000100008008000000000000000000200000000000002000000803000100100000000000000000000000100000000000004000000000000000000000000000000000408000000000000004004200080000000000000000020000002000000000000000000040000000040000000000000 +004000000000000000000100000000000000000000080000100000000002020000000000000004040c0000000000008400000000000000000000800000000001040000000000000000000000000000000004010008008000004000000000000200200000040000800002000000000000010000008000000000000000000000000001000002000000010200000000000000010000000000000000000000010000000000400000000000000000100008028000000000100000000000040000008001000080000000000000000000000000000000040100000004004000200000000000000000000080000002000000000000000000000000000000001000000000 +00000000000000000000010000000000000000000000000000000040000000000000000000080000000004000000008400008000000000000000000000040000000000000000000000000000000000000004000000808000000000000080000100000000800000000002400000000000000000408000000000000000002002000000000012000000000000000000000000040000000000014000000000000000000000000000000000000000100000200000000000000000000100000000000000000000000008000800000000000000000000000000000000004200000000000000000002000000000402000000002000000000000000000000100200000000 +00000000000004000000010000000000000000000000000000000000000000000000000000000000040000000000000020000000000000000000000000040200000000000000000000000004000000200004400000008000004000000080000000200000840000800002000000000000000000408040000000000000000000001000000012040004010000000000000000040000008000000000000000000000000000000000000000000000100200000040000000000000000100008100000001000000000000000000000000000000000008000200000000004204200800800000000000000000000002000000002000000000000000000000000200000000 +00000000002000000000010000000080000000002000000000000001000000000000000002000000000008002140000400000000000000000100000000000000000000000000020000000000000000000000000000000000000000000000000000000000044005000000000000080000000000008000000020000001000000000000080080000000010200000000000002000000008000020000000000000000200000000000000020000000100000000000000000100000000000800000000000000000000000000000000000000000000008000000000400204000200000000000000000000080000402000000800100000000000000004000000000000000 +00400000000000080000010000000400000000000000000000000000000000000000000000000080000000000000000400000000000000040000000000040200000000000004000000000000000000004004000008000000000000000080000000000100800200000000000000080000800000408040000000000000000000000000000010000000000000000000000040040000000000004000400000100000010000000000000000000000100200000002000000300000000100000100000000000080000400000000000000010000000000000000000000000200200000800000000000000000000402000000002000030000000000000000000200000000 +00000000000000000000000000000020001000000000000000040004000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000004004000000000000000000000004000880000000040000000080000000000000000000000000000000000000000000000000000000000000100100000000800000000000000010000000000000000000000000000004000100300000000000000000000000000000000800000000000000000008400000000000000000000000000000000000000080000000000000000000108000002000008000000000000000040000000000000000000 +00000000000000000000100000000010000000000000008000000000000000008000000002000004040000400040000400010000000000000000000000000000000000000000000000120000000000000004010000048200000000000000000000200200810000000002000000180000000000408000000000400000010000088080000002000000010200000000000001000000000000000400400000000008000000000020000000000000100000000400000000000000100100000000000041000000000000000000000000000000000000000000001000004000000000000000000100200000000002004080002000000000000000000000000000800000 +020000000000000000000900000080000000000000000080020000000000000040004008020000000000800000000004000010000000000000000000000000000000800080000200000040000000000010040000000000000000000000000000000000008002000000080000000002040000004000000000000000000000000810000000820020000102010400200000010000000080000000000008000000000000000000200000000020001000080000000800000000000000000000000000000000000000000000000000000000000000000000004000000042000000800000100001000000a0000002000000002000000080000000000000000000000000 +00000000000000000010010000000008040000000000000020000000008000010000000000004004000000000102080000000000000000020000000000000000000000000000000000000000000000000004010000000200000000000401000000000000840020000800000000880000000000408000400000000001002000081808000000000000010000000000000001000000008000000000000002000000c00000000020000020000000108000000000000000000010000000000004000000000000000000001000000000800000000000800000000000004004208080000001000000000000800002000000022000000000000000000000000000000000 +00000000000000000000010000000000000000000000000020000000000000820002000000000000002000080040000000000000001000000000000040000000000000000000020000000000000000000006000000008000000000000000000000000000802000000002004000080000000002000000000000000000000000000080000102000080010001000000000001000000008000000000000000000000000000000000000020200000100200000000000000000000000000000000000001000008200000a00000000000000000000008000000000000004000000000000000000000000080000002001000002000000000000004000000000000000020 +0000000000020000000001000000008000000000008400810400000000000002000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000401000000800000000000040000000000000080000000000a000000080000200000408000000000000000000000000008000002000000000000000000000001000000000000000000102000000000100000000180000020000000100000000000000000000000000100000000400001000000000000000000000000800000000200000000000000044000000000800001000100000000800002000100022001000004000004000000000000000000 +02800400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000420880000000000000020000000040000000000000001000000000004000000000004000008000000000000000081000000000000800010000000800000000000000000408040000000000000020000000000000010028000010000000000000000140000008000000000000000000200000000000002000000002000100000000000000000000000080100000140000000000000002000000000004000000000000000000000000000004200000000000000000000000000000002000000002000000000000000000000000200000000 +00000000000000000000010000000000000000000000008000000000000000820000000000000000000000400000000400000002000000000000000000020000000400000000000000000000000020000004000000009080100400000101000000000200000000000002000000080000010000002000000002000000000000000080000002000000010200000000000021010000008000000004800000004000000000000000000020208000100000000401000000100000100200000000000001000000000000200010000000000020000000000000000000004000000000000000040000000000000002000000000000000000400004100000000000000000 +00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000100000400000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000800000000000002000000000000000000000000000000000001000000000000000002000000010800000000000001000000008000000000000000000000004000000000000000000000100200100400400000100000000000040000000001000000000000100008000000000000000000200000000000004000000000000000000000000080000402000000000000010000000004000000000000000400 +200000000000000400000100000020000000080000000000010000108000000000000000000040040000000000000000000000000000002280000008000000000002002000001000001000000400000000040100000080000000200004010000000000008000000000404600008800000000004080000010000000000100400a0008000022000400000000004000010000000002080000000400000000020000000000800428000020000000100000000000000000010200008000002104000000000000000000000000000000800000000000000000000000004004200000000001000000000004c00002000000022002000040000000020000000000000001 +0200000000000000008001000000000000000000001000002000000000000080000000080000000000002000000000042000000000000000010000000000000000000000000000200000000000000000000400000800000000001000000000000000000080000020000000020000000000000000000000000000000000000000000000000204000001000000000000000b00000000800000000000000000000000000000000000000000000010000000000000000030000000000000004000000000000000000000000000000000000000000000000000000000400401000000000000000000000000040a000000002000000000000000000000000000000000 +0000000200010000000000400000000000000000000000000040000000000002000000040000204400000000000000002000000000000000800040000000000000000000000000000000000000000000000400000000c200000020000000000000000000c00000000002000001080000000000500000000000000000000000080004000012000800010000040000000009000000008000000000000000000080000001000000000000000000100800000000000000000000000400000000000001000000000000108400000000000080000000000000000080004000000000000000000000000000000c02000000002004000000000004000000000000000200 +00000000000000000000010000008000000000000000000000000000000000820000000000000000002100000010000000000000000000000000001000000000000000000000000000001000200000000000000800008008000000000002000000000000400000000002000000000000000000000000000000000400001000000081000002100000010008040010000001000200008000000000000800000000000000000000000020200000100000000400000000100000000000000000000005000000200000208000000000000000001000000000000000004000000080000000000000000100000082000000000000010200000004004000000100000000 +00000000000a0000000001000000000000000000000000002000000000080080000000000000400000200000000000040000000000000000000000000002000000000000100000000000000000400040000c000000000000000000000008000000000000800000000000000000000000000000009020000000000000000000000100000002000000000000000000000001000000000000000000000000000000000000000100000000000000100000000000001000000000000000000000000000000000200000000800000000000000000000002000000400004004000000000000008000000000000002000000002001000000000000000000000000000000 +020000000000000000000000000000000000002000000000000000000000800000000008000000040000000008000000000000000000000000000000000000000000000000000c0000000000000000000004000000000000000000000000000000000040800000000000000000000000000000408200000000000000000000020000000002000000010000000000000000000000008000000000000000000000008010000000000000000000500800020000000000000000000100000000000000000000000000000000000000800000000000000000000000044000000000000000000000000000000002000000002000008000000001000000800000000000 +0000000000000000000001000000000000000000000000000000000000000000080000000040000000000000010000040110000000000000001000050002000800000000000000020000000000000000000001000000000000000000000000000000180000000000000000000000020000000000000000000000000000400000000000000200000001200000000000000009000000000000000002000000000000008000000000002000000010000000000000000010800400000000004000800000000000000000080000000000000000000000010000000000400002000000000000000000000000000a000000000040400000800000000000000000200000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000400008000000000000100000400041000008004000000000000000000002000000004010000000000000000000080000000000800800000000000000000800000000000408040000000000000000000000000000010040000010000000000000008048000008000004000020000000000000000000000000000000004100000000000200000100000000100000100000000000000000000000000000000000000000000000000000000004204000000000000000000000000000402000000002040000000000000000000000200000000 +000000000001000200000000000000000000000001000000000000200002000000010000804008040000000001000000000000000000000200000000400000000000000000000000000000000000000000040100000080000000000004400000000000000000000000020000000800000000404180020000000008000000000808000000020000000100000000000002000000000000000000000000000000000000000000000000200000001000000000000000000002000001000000000020000008000000000000000000100000400000000000000000000400400000100000010000000000008000020000000a0000000000000000100000000000000000 +00000000000200000000010000001000000000000000000000000000000000000000000000004000008020000000002421000000000000020000000000040000000000000000000000000000000000000004010000000000000000000509000000000000840000000000000000080000000000408000000000000000000000000088000002001000010000000000008001110000008000000000000000000000000000000000000020000000108000000000000000820000002000001404000000000000000000000000000000800000000000000000000408004004200000080001000100000020800002000000022000000000800000000080000000000000 +00000400000004000000010000000000000000000000000000000000000000020000000000000000000000000000008400000000000000000000000000040200000400000000000000000004000000000004000000008000000000000080000000000000800000000002000000000000000000408040000000000000000000000000000012000000010000000000000000040000008000010000000000000000000000000000000020000000100200000400000000000000000100008100000001000000000000200800000000000020000000000000000000004200200000800100000000000000000402040000002000000000000004000000000200000000 +00000000000000000000014000000000000000000000000000000002000000020000000001400000000000000100000400000000000000000000000000020000000000000000000000000000000000200000000800008000500200000000000000000000400000040002000000000010000000000000000000200001000000000000000002000000010000040000000001000000008000000000000800000000000080000000000000008000100000000401008000100000000000000000008001000000000000000800000000000000000000200000000000004000000000000000000000000001000002000800000000004000000004000000000000200000 +02000000000000000400010000004000000000000080000000000000080004000000000000000000000000000000000000000000000000020000000000000000000000000000000000002000000000000000010000008000000000000040000000000000800000000000000040000000000000408000000000000000000000080000000000000000010000001000010000000000008000000000100000000000000000000000000000000000108080000000000000000000000300000000c0000400000000000000001000080080004200000000001000000004400000000080000000000000000000000a00010002000c000004000008000001000000004000 +2000000400000000000001000000000000000000800000000000000000000000000000004000000400000000000000000000000000000000000000040000000000000000000000000080000000000000000401000000000000000001084000000000000c000000000100000000000000002000408020000000400000000000080010000002000000000000000000000020008000000000000000000000000080000000200120000000000000108000000000000000000000000000000000000000000000000000000000008000000200000000000000000000006000000000000108000002000000080002000000800008000000000010100008000000000000 +00000000000000100000010000000000000400800000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000040000800000000000000000000000000000008000000000000000000000010000000400000000000000000000000088800000012000000010000000000000001040000008000000000000000000000000000000020000000000008100000800000400000001000000000000000000004000080000000002000000000000000000000000000000000404000000000000000000000000000000002000001800000000000000000100008000000000000 +00800000000000000000010000010000000000000000000000000000000000000000000000004000000000000040000000000000000000000000000000000000000000000000020000000000000000000000000420000000000000000000000000000000000000000000000000080200000000408000400000000000000000001000000002000000000000000000000200080000000008000000100800000000000000000000040000000000100000040040000000000000000500000000000000000400000000000000000000000000000008000000000000004004000000800000000000100000000002000000000000000080000000000040000000000000 +0000040000000040000801000000000000000800000000000000000000000010000000004000000000000000000000002000000000000000000000000004000000000000000000000000000000000000000400000800c200000020000000000000000000800000000000000000000000000000000000001000000000000000000080000002000000010000000000000000000000000000000000400000000000000000000000000000000000148000000000000000000008000000000000004080000000000000000042000040000000000000000000000400004000000000000000080000000000000002000000002000000000000000001080000002000000 +00000000000000000000001000000000000000000000008000000004000000010000000000000000040000000000820400000000000000000020000000040000000000000000000000040004000000200004410000008000404000000080000000200000840000800a0a000000000000000000408040000000000000000000001000000012002000000000000000000001040080000000000000000000000000000000001000000000000000300080000000000000000000000100000100000041000000000000000000000020000000000000002000000400004200000000000000000100000000000002000000002000000000000000000000000200000000 +00000000000000000000010000000000000000000000000000000000000000820000000000000000040000000000000400000000000000000000000000020000000400000000000000080000000020080004000000008000104400000000000000202200800000000002000000180200010000002000000002000000000000000000000022000000000200000000000021090000000000002004800000000000000000000000000020208000100200000001000000100000000200000000000001000000000000000000000000002000000000000200000000204000000000000000040000000000000002000000002000000000001014000000000000000000 +00000000000000000000000200000000000000000000000000000000000000000000000000000202000000000040002400000000000000000000000000080000000000000000020000000000000000000000000000000000000000000000000000000000010000000000000000000200000000400000000000400000000000000080000000000008010000040000000001000000000000000000000000000000010001000000000000000000100000800000000000020000000000000000000000000000000800000000000000000000000008000000000000004000000000000000000000000000100402000000000000000000000000000000000000000000 +00000000000000000000010000001000020000000000000401000000000000020000000400000000002020000000000400000000000000000000000010000000000000000010000000000000000000000000010000008001000000010000000000010000000000000022000000080008002000400000400000000800000000020000800012000000000000001000000020310000000000000000000000000000000000000000000000000000100100000080000000000080000000000000000001000000000000801000008000000202000000000000000000004000000000000000000000000000000002101000040000000000000004000000000000000000 +02000000000000000000010000000400000000000000000000000001482000080000200040000000000000120040000001000000000000000000000000000000000000000000020000800000000000000000000000000000000000000800000000040004800200000008000000080200000000000000020000000000000000200002000002000000000000000000000000001000000000020000000000100000000000000000000000200400100000000002000000200000000000000000040004000000002000000000000000000000020008000000000020004808000000000000000000000000000002000000810000010080000000000000000000000000 +00400000000000000000000000000000040020000000000000800000000000000000000000400000000000000100000400008000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000408000000000000001000000000000000002000000010000000000010204000000008000000000100000000000000080000000000000000000108000000000000000100000010100001000008400000000000000000800000000000000000000000000000400004000000000000000000000000000000002000020000000000000000000000080000000200000 +0000000000000000000000000000000000000000000000040000000000020400020000000000000000000000000000040000000000000002000000000000000000080000000000000000000000000000000401000000400000000001040000000000000080010000080000000008000010200040800000000000000000000002000000000200000000000000010000002110000000000000000100000000000000000200000000002000000090010000000000000100000000000000000000000000000000000000000000a000000200000000000000000000004000000180000001005002000010800002002000022000000000000000048000000080040000 +02400000000000000080000000100000000000000000000000000000000002000000000000000000000000000000008020000000080000000000000000000000000000000000000000000000000000000004000008000000000000008000200000000000800000000000000000000000000008408040000400000000000000000000000000000000010000000000000004000000008000000000000000000000000000000000000000002000100000000000000080000000000100000100000000000080002020000000000000000000020000000000002000004000000000000000000000000000000002000000002000000000000000000000000200000000 +00000000020000001000010000000000001000000000000000000000000400100000000042000000000000000000002420000000000000000000000004000000000000000000000000000000000000000000000800000008000000000000000000000204004000000000000000000000000000000000000000000000000000000000000002000000010600000000000001000000018000000000000000000000400000000000000000200000100000000001000020000000000000000000000000000000200000000000402000000000000000000000001400004000000000000000000000000080000002000000000000010000000000000100000000000000 +00100000000000000000010000000000000000000000000000000000000000820000000000000000000000000140000400000000000000000000000000020000000400000000020000000000000000000000000000018000000000000000000000000000000000000002000000080000000000000000000000401001000000000000000002000000010801000000000001000000008000000010000000000000000000001000000020100000100000000401000000100000000200000000000001000000000000200000000000400020000008080000000000004000000000000000040000000000000002000000000000000000000004000000000000000000 +00200000000000002000010000000000000000000000000000000000002000000000000040000000040000000000000000001000000000000000000040040000000000000000040000000000000000000000000800008000000000000000000008000000000000000002000000080000000000000000000000000000003000008084000002000000010000000000000001000000000000000000400000000000000000000004000000000000100000000000000000100000000000200000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000002000000800000000000000000000000000000000000 +02000000000200000000010020000400000000000000008000000000000000000000000800000000000000000000008400000000000000000000000000000008000000000000008000000000800002000004000800000000000210100800000040400000800200000008000000000000200000000800000000000000000000200000000002002000000000040000000201000000000000000000000800100800080000000000000000000000500000000002000000300000000000000000000000000010000000000000000000000000020000000000400000004040000000000000000100000000000082000000802000010000000000000000000004000000 +00000000000000000000000000008020000000000000000000000000000000008000000000000000000000400000000000000000000000000080000000000000000000000000000000010000000000000000000002005800000000100000000000000800000000000800000000400000000000000000000000000000000800000000000002000000010000040000000000000200008000000000000000000000000008000000000000200000100000000000000000000000000000000000000000000000200000000000000000000000000000000000000400004200000080000000000004000100000002000000000020000000000000000000000000000200 +04000000000000000000000000000000040001000000000000000000000002000000000040000000000000000000020400000000000000000000000000040000000200000000000000000000000000000004010000000000000000000400000000000000800000000000000000000000000000408040000000000000000000001000000002000000000004000000000000100800000000000000400000000000000000000000000000000000100000000000000004000a00000100000100000040000008000000000000000000000000100000000000000400000000400080000000000000000010000000004000002000000000000000000040000200000000 +00000000000000000000000000000000001000000000000000000000008000000800000000000040000000400040000000000000000002000000000000000000000000000000020000000000008000000000000000004000000020000000000000000000800000000000000001000000000000100000000000400000000000000080000000000000010001000000000001000800000000000000000000000000000000000000000000040000100000000000000000080000000000000000000000000000000000000000000000000000000008000000000000004000000000000000000000000000000802400000000000000000000000000000000000000000 +00208000000000000000010000000000000008000000000000000000000000080000000050000000000000000000000000008000000000000000000010000000000000000010000000000000001000000004000000008000000800000000020002000000800000004200000000000200000000401000001000000000000000001000000012000000000000000000000000040000001800000000000000000004000000000000000000000000100000000000000000001010000000000000000000000000000000000000000040000000100000000000000000004000000000000000420000000000000002000000002000000080000800200000000000000000 +0040000000020400000001000000100000000000000000000000000000000000000000000000000000002000000200040900000000000000000000000000000400000000000400000000000000000000000400020c000000000000000008000000004000800000000000000000000000000000008080000000000000000000000000000002000000002000000000010201000000000000000000000000000000000000000000000000000000100140000200000000900000010000000400000000000080000000000000000000000000001000000000000000004040000000000020000100000000400402000000002000000000800000000000000000000000 +00000000000000000000000000000000040020000000000000000040000000000000000000400200000000000100000400008000000000000000000000020000000000000000000000080000000000000004000000000000000000000000000000002000900000000000000000000200010000408000000000000000000000000000000022000000000000040000010000090000000000002000000000000000000080100000000000000000100200000000000000100000010100000010008200000000000000000800000000002000000000000200000000004000000000000000000000000000000002000000002000000000000000000000000010200000 +00000021002000000000010000000000000008000000000020000000800000000000000000000000000000000000080020000000001100008000010040000080000000000000000010000000000000000004000000008020000010000802000000000000800000000000000000000080000000408000000000000000000000080880000002040000010000000000008201002000008000000000100000400000201000000000000000000000100000000210000000000000080000000000000000000000000000001000000000000000000000020000000040004044000000002000000000000000000002000000002400000000000000000100000010000004 +00000000000000000000000200000000000000000000000000080000000000000000000002000202000200000000000410000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000200000000400000000000001000000000000200000000000080010200040000400000000000008000000000080000000000000000000000000000000000100000000000001000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000080100402000010000000000080000000000000000000000000 +00400000000000000000010000000000000000000000008010000000000002800000000000000000000000400000008400000002000000000000000000020000000000000000000000000000000020000004010008001080100400000101000040000200000000000000000000080000010000002000000002000000000000000080000002000000010200000000000021010000000000000004800000014000000000000000000000208000100000000001000000100000100000000000000000000080000000800010000000000000000000000000000000004000000000000000040000000000000002000000000000000000400000100000000000000000 +02000008000000000000020000001000000000000000000000000000000000000000040801000002000000400100000220000000000000000000000000000000000000000001002000000000020000000004000000021000000000000000000000080000800800000000000000000200000000000000000000000000000000000200000002000000110100000000000001000000008000000001000000010000000000000000000000000000100000000000000000000000100000000000000000000000004000000000000000000000000000000180000000004000000000000004000100000000200002000000002000000000000000000000000000000000 +00000000000000000000080000008000000000000000000000000000000000000800000000000000008000000002000020000000001000000000000000001000000000000000000000020000004000000004000000000000000002001800000000004000800000200000020000000000000000408000400000000400000000080000000000000040010000040000000000000000009000000000000000020000001008000120000020200000100000000000800000000000000100000000000000000000200000000000000000000000000000000000000000044200000080000000800000000040000002000000002000000004000001100000000000000080 +0000000004000001000001000000000000000a000000008000000002000000000000000040000004000000000100000000000000000000000000000000000000000000000000002000100040000004000404000000008000000000000000800000000000800000000008000000800000000000008000000000000001000000000080000002002000010000000000000001000000000000000001400000000000008000000000000000200020100a00000000000081000000000000000000040000000000600000000000000000000000000000000200000400004000000000000000000100000000010002000000002800000000000000006100000000000000 +0000000000000000000001000000000000000000000000000000000000040000000010000000400400000000010000020000000000000000000000000000000000000000000000000000000000000000000400080000000000020000000200000000000080000000000000000000000000000040000000000000000100100008084020000000000001000000020000000100020000800000000010080000000000000000022000000000000010000000000000000000000000000000080000000000000000000000140800000000000000000000001000000004400400000c000000000000000000000002000000000000000008000000000000000000000000 +04000000000200000000010000000000000000400000000020000000000000000000000000000004000000000000000420000000000000000000000000000000000000000000000000002000000000000024000801000000000000000100000000000000800000000000000000000000000000608000000000001000004000001200000000000000010000000000200201050000008000000000001000000000000000000000000000000040100000000040000000000000000500000000000000000010000020000000000000000000000000000000000000004000000000800000000000000000000012080000802000000000100008040040000000000000 +00200000000000000000010040000000000000000000000000000000000000080000000040004000040000000000000020000000000000000000000000000000000000000000000000000000001000000000000000008000004000000000000000000000000000000000000000000200000000001000000000000000000000000004000082040000010000000000000000000000009000000000000000000000000000000000000000000000100000000000400000100000000000000000000000000000000000000000000000000000000000000000000000004004000000000000000000800800000002000000000000000080000000200000000000000000 +000400000020000080000180000000000010000000010000800000000020000000000000400020000400000000000804000000000002000000000000000000000000000000000000000000000000000000040000000080000040000000000000002000008000018000020000000000000120000080000000000000000000000808000000120000000100000c0000000000010800008000000000400000000000000000000000000000000000100200000400080000110001000000000000800001000000000000000001000000000800000000000000000400004000000000001000000400000080000002000000002000000000100004000000000000000000 +04000000000200000000010000000000000000000000008000000000000800000000000000004080000000400000000000000000001000000000000000004000000000000000000000000000000000000004000000000000000800000000000000000000800000000008000000000804208000400000000000000000000000081000200002002000040000000000000001000000000000000000000800000000000800000020000000000000500000000000000000000000100000000000000000000010000000000000004004000000000000000000000600004004000000000000008100000000000002000000002001000000000000000000000020000000 +02010000000000000000000000000000000000000000008501080000000020000000000900000080040000400000000020000000008000000000000000004000000000000000002000004000000000000004000080000000000800000100000000000000800000000008000000080800010000400000000000000000002000080000000012020080010000000000000001010000008000000000000080000004020000000480000000002000100000000000000000000000100000000000000000000000002000000000000000000000010000000000000000004000000000000000000100000080000002000000002000002000001000002000000000000000 +00000000000000000000010000000000000000400000000000000001800000000000000040000000800000000002000000000000000000000000000100000000000000000000000000000020000000000000000000000008000000000000000000000004c00200000000000000000200000000400000000000000000000000080010000002000000000000000000000000000000000000000000000000000000000000080060000000000000100000000000000000000000080400000000000000000000000000008400000000000000000000000000000000044000020000000000000000200120000002000000000000010080000000000000000000000000 +00000080000080000000000000000000000000000020000000000000000000000800000000000000000000000000000020000000000001100000000000000000000000000000000000000000000400000004000000004000000000000000000000000000800000000800000000000000000000400000000200000100000000021000000012000000000000000100000000040000000000000000000000000004000100008000000020000000100000000000000000000000000000100001100000000000000100000000000400000000040000000000000400440000000000000000000008000000000000000000002000000000300000000000000000000000 +00600000000000000000010000000000000001000000000010000000200002000000000000000000000000000000008018000000000000000000000040000000008000000000000000000000000000000000010008008000000420002000000080000000800000020002000000000000000000408000000000000000002000081000000082000000410000000000000001000000000000000000000000010000001000000020000000000000100000020000000000000000002000000000040000000080000000000000000014000000000000000000000010004100200000000000000000000000000002000000400008000000000000000002000000000002 +02000000000000000000010000002400008000000000000000000000000000000040080040000000000000000000000020010200000000000000000000000000000000000000000001800000000000000004000000004000000000000000000080000004800000000000000000002000000000000004000000000000000000000000000002000000010000000000400001000000008000000000000000000000000000000000000001102000100000080000000000000000000000000000000000000000002010000000000100000000000000000000000000004000000000000000000000000000000002000000802000000000000000008000000000000000 +00000000000000000000010000001000000000000000000020000001000000800000000000004000000800000200000400000000000000000000000000000000000000000000028000000000008002400000000000000000000210000000000040000000800001000000000000000000000000000800000000000000004000000000000000400000000001040000000201000140000000000000000800000000000000000000000000000000100000000000000000100000004000000000000000000000200000000000000000000000000008000000000000004044000000000000000000000000000082100000800000000000000000000000000080000000 +20000020000000002000010000000000200000000000000000000000000000000000004040000000000000000100000000000000000400000000000000008000000000000000000000000000000000000000000080002000000000000000001000000800000000000000000000000050000000400000000000000000000000089000000012000000000000000000000000000000000000000000000000000004000000000020000000000000100000000000000000400000000100000040000020000000000008800000000000000000000000000000000000040200000000000008000008000000000000000000000000000000000000000000000000000000 +0000000000000000000001000000008000000000000800000000000080000000000000400000000400000000000002002000000000000000000001000001000000000000000000000003800000000000001400000000800000040000080000000000004084400000020200100008000000000040804000000008000002000008180000001204001003000004400000020100002000800000000080000000000000000010000000000000000010020000004000000000000008010000810000000010080000000080000000000000000000000000000000004000400500400000000800000000080000000200000002a002000000000800000240000220000000 +000000008400000000000100000000000000000000000020000000a0000800000000000040000000080000000000400420000000004000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000088000001000409000000002000000000020091000000002000000000200000000000000000000000000000000000000000000000000000020000000208480100000000000000000900000000100000000000000000100000000000400000000000000000000001000040404004000000000000000008000000080020002000000000000000000000000008000000040000000 +02000002000000000080010000000000200000000000000000000040080000000000000800004000000000000000000000000000000000000000000000000000100000000000000000000040000000010004000000004000000000000000000000400002800000000000000200080000000000001000280008000000001000000000000082000000000000000000000001000000000000000001000000000000000000000000000000002400100000000001000401000000080000000000000000000000000000008400000000000000000000000100000001004004000000000000000000000020000002000000000000000000001000400000000004000200 +00000000000000000000000000000000000000001000000000000020000000040000100000000004001000000100000000200000001000000000000000000000000000000000000820000000000000000004010000000000000000000000000000000000800000000000000000080000000000000000000000000000000000080000000002000000010000008000000000000000000000000000000000020000000200000000000000000000100000000000000000000010000000000000000000000000000000001000000010000100000000000000000500400000000000000000000000000000000002000000010002000000000000000000000000000000 +04000000000000000000012000000000000000000000000020000020000000000000000800000000000000000000020020000000000000400000000000000000000000000000000000000000000000000004000800000200000000000800000000000000810000100000000000000200000000408000000000400000000000081000200002040000010000000200000001080000008000000000000802000000000000000020000000000000100000000000000000000000000100000c00000000000000000000000000000000002000000000000000000000004004200000000000000000000000000002000000002000000000000000000000000200000000 +00000000000000000000080000008000000000080000000000000000000000000000000000000002000000000002002400000000000000000000400000000000000000000000000000000000000000000000000000000000090000000002000000004000800000000000000000080200000000400000000000000400000000000000000002000000000000040000000000000000000000000000020000000000000000000220000800200000100000000000000000000000000000000000000004000000200000000400000000000200000000000000000420044200000000000000000000000000000002000000000000000000000000000020000000000000 +0204000000000000008001000000002000000000000010000800004000080000000000080000008000000040000180262000000000000000000001000440600000000000800000000000028000000000000400000000c00000082000000000000000000080000000000200020000080000800000c000000000000000000000000000000002040080010800080000000001102040008000000000000000000000000000100000000000100000100400000000000000000000100000000000000000000000002000008000000100000000010080000000000c00004004a00080000000008000000000000002000000002001002000000000000000000000020000 +00000000000000000000010000008000000000000000000000000000000000000000000000000000000100000010000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000010000040000000000000900008000000000000800000000000000000000000020300000100000000000000000000000000000000000000000000000200000008000000000000000000000000000000000004000000080000000000000000100000082000000000000000200000000000000000000000000 +2000000000020000000001000000000000000000000000000100000000000000000000000000000400000000000008000a000000000000000000000200000000000000000010000000100000000000000004000000200000000000000000000000000000800000000000010000000010000000408000200000000000000000181800000000000008010000000000000001000000008000000000100000000000001000000120000000000000102000000000000020000200000000000000200000000000000000000080000000000000000000000010000000044000040000000000000080000000000002400000002000000000000000000000010000000000 +00000000000000000000000000000000000000000000000000000000000000000000010010000000000000000040080000000000000000000000000000000000000000018000020000000000000000000040000400000000000000000000000000000000000000000000000000080000000000400000000000000000000000080800000002000000010000800000000001000000008000000000000000000080001000080000000000000000100000040000400000000000000000000000100000000400000000000200000000000000000008000000000000004000000000000008000000000000000002000000040000000000000000000000010000000000 +00000000000000000000000000000000000000100000000000000001000000000000000000000000040000000000000420008000000000000100000000040000008004000000040001000004000000200004400000018000000000000080000000000000840000000000000000800000080000408000000000000000000000201000000010020000010000000000000008040000008000000000000000000000000000000000000000000004100000000000000040100000000100000000000000000000000000000000000000000000000000000000000002004200000000000000000000000000000402000000002000000000000000000000000200000000 +04000000040000000000010000000000000000000000000000000000000000000000000040000004000000000100000400008000000000000000000000000000000000000000000000100000000000000004000008010000000000000000000000000080000800020000000000800000000000c08000080000000401000000001000000002000000010000000000000000000000008000000000000000000001008000000000000000000020100000000008000000000000000100000000000200000000400000040000000000800000000000000001000000004000000000000000000000000000000003000000004000000000000000008040000000000010 +00000000000000000000010408000000000000000000000000000000000000800000000000004000000000000040000000000000000000000000000000000000000000000000020000000000000000000000000c00000008000000000000000000000000000000000000000000080000000000000000400000000000001000000000200000000000000000000000000001000200000000000000000800000000000000000000000000000000100000040400000000000000000000000800000004000400000000000000000000000000400008000000000000004004000008000000000000000000000002000000000000010000000000004000000000000000 +00400020000000000000000000000000040020000100000000800000000000000000000000000000000000000000000400008000000000020000000000020000000000000000000000000000000020000000010000000000000400000400000000000200000000000000000000080000010000408000000002000000000000000008000002000000000200000000000200010000000000000004100000000000000000000000000020200000100000000000000000100000010100001000000000000000000000000000000000800000000000000000000000004000000000000001040100000000800002000000020000000000000000000000000000000000 +0000000000000000000001000800040000000000000000000000000000000000480000000040000000000000010000040000000008000000000000040002000800000000000000020000000000000000000001000000000000000000000000000000380000020200000000000000020000000800000000000000000100000000000000000200000001200000000000000008000000800000000002000000000000008000000000002000000010000000000000000030800400000000004000800000000000000000080000000000000000000000000000000000400000000000000000000000000000000a000000000040410000000000000000000000200000 +02400000000000000000010050004000000000000000000000000000000000400000000800000000040000000000000000000000000400000000000010000000000000000010000000000000000000000000000004008000004000000000000000104000000000000000000000000000000000400000000000000000000000000000000012000000000080000000008000040000000000000000000000000001000000000000000010000000100104000000000021110000000000000000000000000000000000800000000000000000000000000000000000004200000000000400000000008000000002000000000000000000000000000000000000000000 +00000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000400000000000000000800000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000200000040000010000000000000001000800008000000000000800000000000000000000000000000000100000000000000000000000000000000800000000000000000800000000000000000000000000002000000000004004000000000000000000000000000002000000000000000000000000000000000000000000 +00400000000004080000010000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000040000000000000004002000000004000000204004400008000000000000000080000000000000840000000000000000000000000000408000000000000002000000021000000012000004000000000000000000040000000000000000400000000000000010000000000000000000100000000040000000100000000100000000000000000080000400000000000000010000000000000000000000000200200000800000000000000000000402000000002000020000000000000000000200000000 +00000002000000040000100000040000000000000000000000000000000200000000000000000000000000000000000120000000000000000001000000000000000000000000000000000000000000000004000000004000004000000000000000000000800000000000000000080000000100400000000200000000000000020000000012040000000000000000040000040000000000000000000000000004000000000000000000000000120200000000000000000000000000000000000000000000000008000000000000100000000000000200000000004400000000010000000000000000000002000000002000000000000000100000000000000200 +0040010000020000001009008000100000000800000000000000000100900000000000000000080000002000000000042200000000000000000000000000200000000000000402000000880000000000000400000c08c000000000000000000000004000800001000000000000000000000000800810000000000000000800080000000002400000000000000000010201000800000000000040000000000084000000000000000000004000100100000000000000900000000000000400000000000080000000000000000000200000000008000000000400004080000000000008000100000000080402000000002000022000880000040000000000000400 +00000000000000000000010002008000000000000000000000000000000000000000000000000004000000000000000020008000000000020000000000000001004000000020000000000000000000000004010000800000000000000400800100000000840000000000000000080000000000408000000000000000100002000002000200000000010000040000000200000000008080000000000000000000000000000000000020200000100000200000000000000000000100001000000000000010000020000000100000000200000000000100200000004200000000000003000002000000820002000000822000000000000000000000000220000020 +00000000000000000000000400000000000000000000000004100000000000000000000002000000480004000000000400000000000000000000800000000000040000000000000002400000000000000000000000008008000000000000000000002800c40000000002000000000000010000409000000000001000000000080000000002000020000000000000000000010000000000000000000000020000000000000020000000000000100000008400000000100000000000000000000001000000000000000000000000000004400000000000010000004000000000000000000000000080020402000000400000010000000010000000001000000000 +04000000000000000000010000001000000004002040000000080000000000000000000040000000000020000000000000000000000000000000000000000000000000000000000000000040000000000000001004000000000000000000000000004000000000000000800000000000000000400080000000000000000000001000000012000000000000040000010000040800000000000000000000010000000000000000000000000000110100000000000000000200000000000000000000000002000008000000800040000000000000010000000000000000000000000000000000000000002000000000000000000000000000000000000000000000 +00000000000000000000010400000400000000800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000100000010000000000000000000000024000000000008000000000000000010000000800200000000000000080000000000408000000000000000000000000080000014000000010000000000000214040000000000000000000000100000010000000000000000000000100200000402000000280000000500000000040000000010000000000000040000000000400000200200000000004000000000800000000000000000000002000000802000010000000000020000000002000020 +00000000000000000000010400000000000000000000008020000000000020000000000002000000000000400000000420000002000000000000080000000000000000001000000000000000000000000004000800001080100000080101000000000000800000000000000000080000000000000000000000000000000000020080000002000000010200000000000001010000008000000000003000014000000040000000000000200000100200000001008000000000100000000020000000000000200000000010000000000000000000000000100000004000000000000000000000000080000002000000002000000000400000100000000000000000 +02000400000004000000010000000000000000000000000000000000000000000000000800000000000000000000000400880000000000000000000000040000000000000001000000000004000000000004000008000000000000000081000000000000800010000000800000000000000008408040000000000000000000000000000012020000000000000000000000140000000000000000000000000000400000000000000000000000100000000000000000000000080100000140000008000000000000000000004000000000000000000000000000000200000000800000000000008000000002000000002004000000000000000000000200000000 +0000000000000000000000000000000000000000000000400000000000000000000000000000000000001000000400002000000000000200000040000000000000000000000a000000000000000000000004000000000000000000000000000000000000800000000000000000000000000000400000000000400000000000080000000000000000000000040000000000000000000000000000000004000000001000000000000000000000000000000000840000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000 +00400000000000000000011000000000000000000008000012000000000202000000000000000004040000000000008400000002000000000000000000000001000000000000000000000000000000000004010088008000004000008000000200200000040000800002000000000000000000008000000000000000000000000001000002000000010200000000000000000000000000000000000000010000000000400000000000000000100008028000000000100000000000040000008001000080000000000000020000002000000000000100000400004000200000000000000000000280000002000000000000000000000000000000000000000000 +002000000000000000000100400000000000000000000080000000000002020000000000000006040800000000000004200000000000000000040000400800010000000001000000000000000000000000040000040080800000000001000000000040000400040000020000000800000000000080000000000000000020000000810000030000000102000000020102010100000080000000000000000000000000004000000000000000001001000000000000001000000000000000001080000000000040040000000000000000000000000401000000440040000000000000000000000000c0000002000000000000400000000080000000000000000000 +00000000000000002000010040000000000000000000000000000000802000000000000040000000040000000000000000008000000000000000000040000000000000000000000000000000000000000004000000018000004000000000000000000000800000000000000000000000000000408000080000000000000000001000000002000000010000000000000001000000008000000001400000000000008000000000000000000000100200000000000000100200000100000000000000000000000000000000000000800000020000000300000000004000000004000800000100000000000002000000002000000000000000000040000000000000 +0200000040020004002001400000100000000a000000008020000008000000800000000000000000002000000000000000000000000000000000000400080000000000000000000000000000000000000004010000008000000000000000000000000800800808000008000000000000000000000000000000000200000000000000000400000000010000000000000001800000008000000001020080000000000000000000000000000000100000000000000080000004000000080840100000000000000000000000000000200000000200000108000000004000000000000000000000000000000002000000002040410000000000008020100000000000 +00010000000000000000018000080000000000000000000020000000000000000000000002000004000000000000000420002000000000000000000240000009000000800000000000000001000000004004000800000000000000000000000000000000800000000000000000000200000000008000000000000000000000000000000002040000012200000000000801080000008000000000100000000000000000002000000000200000100000000000000080000000000000000000000400000000200000000000010000000000000402000100000000004004000000000000000000000080040012000000802000000080000002008000000000000000 +00100000000000000000011000000000000000000000000000000000000000810000000000000000000000000000000420000000000000000020000000000000000000000000000000000000000000400000010000000000000000000000000000000800000000000800000000000000000000000000000000000000000000000000000002040000010800000000000001000000008000000000000000000000000000000020000000004000100200100001000000100000000000000200000040000000400000100008000020000000000000000000000400004804000000000000000000000080000402000000000000000000800000000000100000000000 +2000000000000000000401000000000000000000001000000000000580020000000000000000000400000000000000040000000000000000010000000000000000000000000002000000000000000000000400000000001000001000000000000000004000000100000000000000000000000040800000000000000000002008000000000040000001020000000000020a000001008000080000000800000000000000000100000001000000100080000000000000100000000500000000000000000000000000000000000000000000000048000000000800014000000000800000000002000040000402200000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000020840000000000020000000004000000408000000000000000000000081000020000000000010000000000000040000000008000000000000000020080000000000020000000000000101000000000000000000000000100000000000000100000000000002000000000000080000000020000000000004000000000000000000000000040000002000000000000000000000000000000010000000000 +00000000000000000000050000000000000000000008000000000000000200000000000000100204048000000000000420008000000000000000000000000801000000000080040000000000000000000004000000008000000000000001000000200000140000000002000000080000000000408000000000000000000000000081220002040000010200040000000000000000008008000000000800010000000000500000000000000000100000000000000000100000000100000010008001000000000000000000000001000000100000000100000000004004200010000000000000000080000002000002000000000000000010000000000010000000 +0000000000200000000009000800000000000000000000000000000000c000000000000040000004000000000002000000004000000000000000000000000000000000000100000000000020000000000004000000000000000000400000000000000040040000000000000000020000000000408010000004000000000000081000000012000040010000000000000000040000008000000000000000000000210000000000000080600000100000000020000000000000000100000000100000000020200000000000000000000000000000000000000000044000000000000001000000000040000002000000000100000000000000000002000000000000 +00000000040004000000010040000000000000000000000000000000000000000000000000004200000000000000000000000000000000000000000000040020000000000000000001000004000000200004400004008000000000000080000000004000840000000002000000000000000000408000000000000000000000001000000012020004000000000000010001040000000000000001000000000000000000000000000000000000100100000040000000000000000100000000000000000000000000000000000000000000000008000000000000004204200800800000000000000000000002000000002000000000040000000000000200000000 +00000000000000000000010000008000000000000000000002000000000004000000000000004000220000000040000001000000000000000000000000000000000000000000020000000000000000000004000400000000000000000000000000000000800000000000000000080004001000408000400000000000000002081000000000000000000000000000000000000000000000000000000000000000000000500020000000008000100000040040000000000000000100000000000000000500000004000000000000000000000008000000000000004004000000800000004000000000000002000000002000000000000000000040000000000000 +00000400000004000000010000000400000000000000000000000040000000000000000000080000000000000000020000000000000000000000000000040000000000000000000000000014000000200004000000008000000000000000000000000000840200000006400000080000800000408000000000000000002002001000000012000004000000000000000040040000000000000000000000100000010000000000000000000001100000000002000000200000000100000000000000000000000000000000000000000000000000002000000000000204200800800000000000000000000002000000002000010000000000000000100200000000 +00000010000000000000000000000000000000000000000000000020010800100000100000004000080000000002000400000010000000000000a00000000000000000000000000000000000000000000000100000000000000000000000000000000000800000000000000000000000010000408000000000000000000000001000000002010000000000000000000000010000000000000000000000000000000000010000000000800000108000000000000000000000000000000000000000000000000000000400000000000000000080000100000400044000000000000000008000000080000002000004000001000010100000000000000000000000 +00000000000200000000010000001000000000000000008000000000000020000000000000004000008020000000000421000000000000020000000000040000000004000000000000000000000000000004010000000000000000000509000000000000840000000008020000080000200000408000000000000000000000020008000002002000010000000000008001110000008000000000000000000000000000000000000020000000100000000000000000820000000000001404000000000000000000000000000000800000000000000000000400004004200000080001000100000020800002000000022000000000800000000000000000000000 +08000002000000000000010002400000000000000000100020000000000000800040000040002040000000000000000020000000000000000000000000000000000000000000000000000000000000400000000000004004000020000000000000000000800000000000000001000200000000101000000001000000000000000000000002042000010100000000000001000000008000000000000000000000000000000000000000000000100000000000001000000000000000000000000000000000200000000000000000000000000080000000000000004004040000000000000000000000000802000000000000000000000000000000000000000280 +00000000000000000000012000000000000000000000000020000020000800000000000000000080000000400000400000000000000000400000000000000000000000080000000000020000000000000004000800000200000800400800200000000000810000000000000000000004000000408000000000400000000000081000000002000000000000000200000201000000000000000000000000000000000000200020000000000040100000000000000000000000100100000000000000000000020000000000000000000000000000000000040400806000000000000000008000000000000012000000802001000000000100000040000040028000 +00400000000000000000010400000000000000000000000010000000000002820000000002000000000000000100008420000000000000000000080000000000000000001000000000000000000000000000010008008000500000000000000040000000000000000002000000000000000000002000000000000001000000000000000002000000010200000000000001000000008000000000000000010000000000200000000000200000100200000401000000000000000000000000000001000080200000800000000000000000000000000000100000004000000000000000000000000080000002000000000000010000000004000000000000000000 +00010000000000000000010000000000000000000000000020080000000000000002000000000000040000000000000000000000000000000000000040000000004800000000000000044000000000000004010800000000000400000000000000000000800000000000000000080000000000408000400000000000000000000000000000000080010000000000000201000000008000000000000000000000000000000000000000000000100200200000000002000000000500000000000000000000000000000000000000000000000000000200000000004000000000800000000000000082000002000000002000000040000000000000000000000000 +0000000200000000000001000008100000040840000000000000000000000000000002024000000404002000000000040000000000000000000000000000000000000000090000000000000000000000000400000800c00000400000000000000000008080000000000000000000000000000080000000000000000000000002080800000200000000000020000000000000000010000000000040000000000000000000000000002000000010040000000000004000000000000000000000000000000000000000000000000000000000000000000000040200400000a000000000000000000000000002000000002000000000800000000000000000000210 +00000000000000000000010000000000000000000000000000000000000000800000000000004000000000000000000000000000000000020002000000000002000000000000000000000000000000000000010800000000000000010402000000000000800000000200000000080000000000400000000000000000001000000000200000000000000000000000000001000200000000000000000800000000000000000200001020000000100000000000000000000000000000000800000000000000000000000400008000000000001000000000000000004004000004000001000000000000800002000000020000000000000000004000000000000020 +02800400000000000000010000000000000000000000000000000040000000000000000000080000000000000000000020000000000000000020000000040000000000000000000000000004000000000004000000008000000000000080000100000000800000000002400000000000000000408000000000000000022002000000000012008000010000000000000000040000008000000000000000000200000000000002000000002000100000000000000000000000000100000000000000000000002000000000000000000000000000000000000000004200000000000000000000000000000002000000002000000000000000000000100200000000 +00400000000000000000000000000000001002002000000000000001000000000000000000000000000000000000000400000000008000000000200000020000000000000004020000000100400000000004000008008000000020000000000000080000800000000000000000080000000000000000000000000000000000020080000002000000010000000000000000000000000000000000000000000000000000000000000000000000100200000000000000120000000000000000000000000080000000000000000000000000000008000002000000004018000000000000000000000000040402200000002000020000000000000200000000020000 +02000000000000000000010000000000000000000000020000000008000000000000000800000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000001000010000004000000400000000000000000000080000002000408000000000000000000000000000000002000000020000000000000020000800000000000000100000000000008000000000000000000000100000000000000000000000000100000000000000000000000000000000008000000000001000000000000000044000000000000000040000000000000002000100002004000000000200100000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000200000000400400200400010000000000200000400000000000000000000000000000000000000000008006000000000000000020400000000000000000010000000000000000000000000000408000000000000000010000080080000002000080010000040000000000000000000000010000000000000002000000300000000000200010100000000000000000000000100100000000008000000000000004000800000000000000000040000000000000004020000000000000000000000080000402000000000000000800000000000000000010000010 +00000400000000000000000000000000100000000000000000000001400000000000000020000000000000000000000400008000000000000100000000040200008004000000000000000004000400000004000000000008000000000080000000000000800000000000000000880000000000408040000000000000000000000080000010000000010000000000000008040000008000000000000000000000000000000000000000000004100200000000000000100000008100000100000000000000000000000000000000000000400000000000000000004200000000000000000000000000000402000000002000010000000000000200000200000000 +0200000000000000000001000000800000000800000000000000000080000000000000004002000000000000000600000000000000000000000000000000000000004000020000000000000000000000000400003000800000000000000000000000000080000000000000000000000000000040000000000000040000000008000000000200000001000004000000000000000000800000000040000000000000000800000000000020000010000000000000000000000000000000080000000400000020000000100000000000000000008000000100040000420000008000000000000000000000000200000000a000000000000000040000000000000000 +00000000000000000000000000000400040000000000000000000000000000000000000000000000000000000000000400018000000000000000000000000000000000000000000000000008000000000008000000010020000000000000000000000000000000000000000000000000000000408000000000000000000000001000000002400000000000000000000001000000000000000000000000010000000000000000000000000000100000000000000000000000000100000000000000000000006000000000000000000000100000000000000000000000000000000000000000000080000000000001000800000000000000000040000000000000 +00000000000000000000010000008080000000000008000000000000800000000000004000004000040140000010002020000000000000000000001000010000000000000000000000030000000000000004000000008000004400000802000000200000c44000800202001000080200000000408000000000000000000000080800000032000010010000044000000201080020008000002000800800000000200000000208000020200000100200000840000000000000080000008100000001000800000000000400000000002000000000000000000040004005004000000000000000000800000082000000022000000a00000000000200000020000000 +00000000000000000000010000020004000000000000000000000000000000000000000000000004060000000000000000000001800000008002000000000000800000040800040000100100004000000004000800008000004200000000000000200000000080000002000000080020000000408000000000000000000000480880000012000200000000000000c00201040000000000000000100000040004000000000220000000000000100000000000010000000040300000000200000001000000020000000000000000000010000000000000000000044000000000000000000000000000000002000000800000008080000010000000000000000000 +00000000000000000000000002000000000800000000000000000002000000000000000000200000000000000000000020000000000000040000000000000000000000000000000000000000000000000000000008000000000000000000002000000000000400000000000000000000000000000000000040000000000000080000000000000000010000040000000000011000008000200000000000000080000000000000000000000000100000000000000808000000000000000000000000000000000000000000000000000080000000000000200000004000000000000000000000000000040002000000000000000200000000000000000000000000 +0000000000020000000011000000000000000a008000008000000000800000000000000000000000040000000000000400000010000000000000000000080000000000000000000000000000000000000004000080008000000000000000000000200000800000000002000000080800200000008000000800200000000000008000000002000000000000000800000001000000000000000400000000000000000000000000000000000002100000000400000000000000000000080000010021000000000000000000000000000000000000000000000408000000000000000001000100000081000002000000002000000000100000000020100000000000 +00000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000008400888000000000000000000000040000000000000001000000000004000000200004400008010000000000000081000000000000840010000000800000000000000000408040000000000000000000001000000010020000000000000000000000140000000000010000000000000000000000000000000000000000100000200000000000000000080100000140000000000000000008000800004000000000000000000000000000004200000000000000000002000000000402000000002002000000000000000000000200000000 +00000000000000000000010000008000000008000000000000000000000000000000000040000000000100000010000000000000000000000000001000000000000000000000000000000000000000000004000020008000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000002000000010000040000000000000000008000000000400800000000000000000000000020200000100480000000000000000000000000000000800000000010200000008000000000000000000000000000000400204000000080000000000000000000000082000000802000000200000000000000000000000200 +22000000000000000000090000000000040000000000008100000000000000028000000842001004048000000000000008000100000000008000008000000000000000000000040010000000000000000004010002008280000000000000000000200800800000000002000000082004000000408000000000000000000000081080000016400008010000000000000001000020000000000000000000000000000000200020000000000000100000080400000000000800050200000000000001010000000080000040000000000000000000001000000000004000000000000000040300000000080002040000002000000000000010000000020000001000 +00400000000000000000000000000000040000000000000000800000000000000000000002000000040000000000000420008000000000000000000000000000000000000000040000000000000000000000000000008000000000000100000000200000000000000002000000080000000000408000000000000000000000000080000002000000010200000000040200010000008000000000102000000000000040000000000000200000100200000000000000000000010100001000000001000000200100000000000000000000004000000000100000004000000002000000000000000080000002000000000000000000000010000000000000000000 +00000000000000000000000000000000000000100000000000000001000000000000000000000000040000000000008420008000000000000000000000040000000000000000040001000004000000200004400000018000000000000080000000000000840000000000000000000000080000408000000000000000000000001000000010020000010000000000000000040000008000010000000000000000000000000000000000000000100000200000000040000000000100000000000000000000000008000800000000000000000000000000000002004200000000000000000002000000000402000000002002000000000000000000000200000000 +00000000000000000000010440000000000000000000000000000000000000800000000002000200000000000000000420000000000000000000080000000000000000001000000000000000000000400000000004000000100000000100000000004000000004000000000000080000000000002000000000000000000000000080000000040000010200000000010001010000008000000000002000000000000040000000000000200000100300000001000000000000000000000000000000000000200000000000000000000000000000000000100040004004000000000000000000000080000002000000000000000000000080000000100000000000 +02000000000000000000010000004000000000000002000000000000080000000000000800000000000000000000000000000000004000000000000000000000000000000000000000000040000000000000040000008000000000000000000000400000800000000000000000000000000000000000000000000000000000001080000002000080010001010000000001000000008000000000000000000000000000000000000000220000100000000400000000100000000000000000000000000000600000000000000000000000000000000000000000004000000000000000000000000080000002000000040000000000000004000000000000404000 +04000000000000000000010000008000001000200000000000000080000000100000000400000000000000400000002020000000000000000080000000000010000000000000000000000000000000000004000000000000000080000082000000000000802000000000000000080000004000408000000000000000000800021000000002000000008000040000000200004000000000000000000000000000040008000200000020200000100000000840000000000000000500000000000400000000000000000400000000000000000000000000000400006200000000800000000000000000000002800000002000000800800000000140000000400000 +00000000000000000000010000000000000000000000000000004000000000000000000000000002000000000000000420000000000401000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000002000000000200000000400800000000200000000000009000200002040000010000000000000000000000008000000000800800000000002040000000008000000000100000040000000000000000000000000000000000000000000000800000000000000000000000000000000400004004000000000000000000000000000002000000000000000000000000000000000000000000 +02800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008420000000000000000020000000040200000000000000000000000004000000600004400000000000000000000080000000000000840000000000000000000000800000408040000000000000000000001000000010008000010000000000000000040000008000010000000000000200000000000002000000002000100200000000000000000000000100008100000000000000002000000800000000000000000000000000000000004200000000000000000000000000000402000000002000000000000000000000000200000000 +02010000000000000080010000002000000008000000000000000040000020000002000900000000000000000000020020000000008000000000000004000000000000008000002000000000000000000004000080009000000000000002000000000000800000000000000200000000008200400000000040000000000000080000000012060000010000000000000001000000008000000000000080400004000000000480000000002000100000002000000000000000000000000000000000000000002000000000000000000000000008000000000000004044000000000000000000000000000002000000002400000000000000002000000000000004 +02000000000000000000010000001000000000000000000000000010080000000000000840000800000000100000000000000000000000002000000000000000000000000000000000800100000000000000000800000000000000000000000000400004880800000000000000004000000000000000000000000000000000000000000002000000000000000000800001000000000000000000000080000000000000000000000000002000100020000000000010000000000000000800000000000200000000000000000000000008000000000008000000004000000000000000000000000020000022000000800000000000000000000000000000000000 +2200000000000000000000000000000000004000000000000000000000200000000000000000000004000000000010040000000000000002010000000000000000000000000000000000000000000000000001000000840000400000040000000020000080000080000204000008000000000040000000000000000000000000000000000200000001000000000000000100000000010000000000000000000000000000000000002000200010400000000000000010000000000000000000000100000000400000840000000000000000000100000000000000400080000000000100080000002080040a000000020000000000000000000000000000000000 +00000000000000100000010000008000000000000000000000000000000000000000000000000000040100000010000400000000000000000000001000020000000000000000000000080000000020200004000800008000104400000000000000202200c00000000002000000080200010000000000000002000000000000000000000022000000000200040000000021090000000000002004800800000000000000000000000020208000100200000001008000100000000000000000000001000000000000000000000000002000000000000200000000004001000000000000040000000000000082000000002000000a00001010000000000100000000 +00400080000000000000000000008000000000000000000000000000000002000000000000000080800000400000008080000000000000000000000000000000000000000000000000000800000000000004040008004000000800000008000000000000800000000a00000000080000000000008000000000000000000080000000000002000000010000000000000001000820002000000001000000000000000000000000000000000000108000000000000008000000100000000000000000000080100000008000000002000020000000080000000400004000000000000000000100000000000002000000002000000000000000000000000000000000 +02000000000000000000100400008000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000008008000000000000000000000000000000004000000000000000400000408000000000000000000000080000000402000000000000000000000200000000000000000000000000000000001000000020000000002000100000000400000000000000000000000200000000000000000000000000000000000000400000000000020000004000000000000000000000000820000002000000401000110000000000000000000000000000 +00000000000000000000000000008000000000000000108000000000000000000000000002000000000080000000000400000000000000020000000040000000004080000000000000000000000000000004010000000000000000000400000000000000800000000008000000080000010000400000000000000000000000000008000000002000010200040000000001010000008000000000000000000000000000000000000020000000100200000000000000400000000000000000000000000000000000000002000000800000000000000600000000004200000080000801100100000080800002000000022002000000000000040000000000000000 +0000000000000000000001000000040000008040000000002000000000001000000000004000000400000001000000040001100000000000000000004004020100080000000000000000100000000000000401800000010000000000000000000000000480001000000000000000000002000040800040000000000000000200000000000200008001000000000000020100000000800000000000000000000000000000000000000020800010000020000000000200000000010000000400000000000020040000000000000000000000000000000000000000400000000000000000000000000000000a000000002080000000100000000000000000000000 +00000000000000000000000000000000000000000000000000000008000000000000000000000000000000000140000400100000000000000000000000000000008000000000020000000000000000000000000000000000000000000000000000000800000000000008000000000000000000009000000000400001800000000000000000000000012000000000000000000000008000000000000000000000000000000000100000100000100200002000000000100000000000000000000000000000000000000808000000004000000008200000000000004000000000008000000000000080000403000000000010000000000000000000000000000000 +14000001000000000000010000000000000000002000000000000001000000000000000000000000000000000000000000200010000000000000000000008000000000000000020000100000000000000000000008000000000000000001000000000000140001000000000100080000000020408000200000000000000000001000000010000000052000000000000200840000008000000000000000000000008000000000000000000000100000000000080000000040000100000000000002000000000002000000000040800000000008000000000000004000000000000000000010000000000002000000800000000000000000000000000000000010 +000000020000000000000140000000000000000000000004000004000020000000000000400020c000000050000000002000000000020001000000004400000000400000000000800000000000000000000400000000c000000820000008020000000000800000004000000001080000000000100000000080000000000000000080000002000000010000000000000009000000008800000000400000000004000000000000000000000000100200000400000000100000100000000000000000000000000000000004000000000000000000000000100000004000000000000000020010000000000802000000002000001000000804000201000000000200 +000000000000000000000004000000000000000000000080000008000000000000000000000000000000000000000006000000000000000000000000000a0000000000000000000000000000000000000000000000000008000000000200000000000000000000000008000000080200010000000000000001001000000000000000000002000000000900000000000001090000000000000010000000000000000000001000000000000000180000000400000000100000000000000000100000000000000000000000000000000020400000081000000000004000000000000000040000000000000002000000000000010000000008000000000000000000 +0000000000000000000001000000000000000000000000000000000040000000080000000000000000000000010200060000000000000000000000040002000800000000000000020000000000002000000001000400000000040000000000000000580000000000000000000008020001000000000000000200000100000000000000004200000001228000000001000009000000800000000402000000000000000000000000000820000010010000000000000010800400000000004000000000000000000000000000000000000000000000000000000000420000000000000004000000000040000a000000000040400000000000000000000000000000 +00000400000004000000010000000000000000000000000000000000000000000000000000000000000000000000022020000000000000000000000000040000000000000000002000000004000000200004000000000000000000000000000000000000840000000000000000000000000000408000000000000000000000021000000012040004010000000000000000040000008000000000000000000000010010000000000000000000100000000000000000000000000100000000000000000000000000000000000000000000000008002000000000004204200800800000000000000000000002000000002000000000000000000000000200000000 +00000400000004000000010000000000000000000000100000000000000000000000000000000000000000000000028400000000000000000000000000240200000000000000000000000004000000200004000000000000000000000000000000000000840000000000000000000000000000408000000000000000000000001000000010000004000000000000000000040000000000010000000000000000010000000000000000000000100200000000000000000000000100008100000000000000000000000800000000000000000008002000000000004204200800800000000000000000000402000000002000000000000000000000000200000000 +00000080000000000000000000008000000000000000000000000000000800000000000000000000000100000000000000000000000000000000000100000000000000000000000000000000000000000004000000004000000000000000000000000000c00000000800001000000000000000000000000002000100000000000000000002000000010000040000000000000002008000040000000000000000000000000000000000200000100200000000000000000000000000000000000000000000200000000000000000000000080000000200020400004000000080000000008200000000000082000000002001000200000000000000000000000000 +00000000000000000000000000008000000002000000000000000000000410000000000000000000040000000000002000000000000000020000000840000000004000800000000010000000000000000004010000008000004000000400000000200000800000000002000000080000000400400000000000001000000000000008000002000000000000040000000001000000000020000000000000000000040000000000000020200000100200000000000000000000000000000000000001000000000000000000000000800200000000000200000020004200000000000801000100000000800002000000022002000000000010000000000000000000 +02000000000000000080010040000000000000002000000000000041080000000000000800004000040000000000000020000000000000000000000000000000100000000000020000000140000000010004000000108000004000000000000000400000800000000000000200080000000000000000200000000000000000000080000002000000010000000000000001000000000000000000000000000000000000000000000000002400100000000000000401100000000000000000000000000000002000000000000000000000000008000000000001024004000000000000000000000000000002800000002000000000001000000000100004000000 +04000000000000000000000002400000000000001000008000000000000800000000000000004000000000000000000000000000000000010000000000000000000000000040000000000000000000000000000000000000000000000000000000000000800000000008000000000004000000408000000000000000000000081000000002002000000000000000000001000000020000000000000000000000000000000020000000000000100000000000000000000000000100000000000000000000000020000000000000000000080000000000000400014000000000000000008100000040000002000000400001000000000000000002000200000000 +00000000004000000000010000000000040000400008000000000008000000000000000008020000000000000001000401000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000008004000000000000000000000080000000000008000000000000000000000000000000002000000032000000000000000000000000000000000000000000000000000000000000100000000108100000000000008000000001000000400010000000000000000000000000000000000000000000104000408000000000000010000000000004080000002000000000000000000100000000100000000000000 +02000020000000000000010000000000010000000000000000000011080000000000000800000000000000000000000020000000000000000004000000000000010000000000002000000020000000000004000000000000000000000402000000000000810000000000000000014000000000408000000000000000000000080000000002040000010000000000000000000000008000000000000000000200000000000220000040002000100000000800000000000100000100000000000000000000000000000400000000000000000000000000000000004004000004000000000000001020000002000000202000000000000000000000000000000000 +00000000002000000000000000000000000000000000000000000000000000100000002000000000000000000800000000000000000000000000000040000000004000100000100000000000000000000004000000000000000000000000000000000000800000000000100000080000000000008000080000000000000000000080000002000080010001000000000201000000008000000001000000000000000000000000000000200000100a00080000000000000000000000000000000000000000200000000000000000000000000000000300004400004000400000000800000100000080000002000000002000000000000000000002000020000000 +00000400000000000000000000000000000000000000100000000001000000000000000000000000000004000000028400008000000000000000000400041000000000000000000000000004002000200004010000000000000000000000000000000800840000000000000000000000000000408000000000000000000000001000000010040000010000000000000000040000000000010000020000000000000000000000000000000000100000200000200000000000000100000100000000000000000008000800000000000000000000002000000000004204000000000000000002000000000402000000002042000000000000000000000200000000 +00000000100000000000000000000000000000000000000000000000002000000000000000000000040000020000000000000000000000000000000040000000000000000008000000000000000000000004000000008000005000004000000000000000800000000000000000480000000000408010008000000000000000080000000012000000000000000000000201040000000000400000000000000004028000000000000000000000100000001000400000000000000100000000000000000000040000000000000000000000000000000000000002004040000000000000000000000000040002100201002800000000000000100000000000000000 +06000000000000000000000000000000000000000000000000000000002000000000000800000000000000000040000000000000000000000000000000000000000000000000020020000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000400000000048000080000002000000010000000000000000000800000000000000000000002000000000000000000000000000100000000000000000000000000000020020000000000000000000000000000000000000000008000000000000004000000000000000000000000000000002000000000000000000000000000000000000000000 +00000000000000000000000000080000000000000000000000000000800000000000000000000000000000000000080400000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000400000000000000000000000080800000012000000010000040000000000000000008000000000100000200004000000100002000000000000100002000000000000001000000000000000000000000000040000000000000000000000000000000210000000004000000001000000000000000000000002000000000000000000000000100000000000000000 +00000000000000000000001000000000000000000000000000000008000000010000000000000000000000000000000400100000000000000020000000000000008000000000000000000000000000000000010000000000000000000000000000000800000000000808000000000000000000009000000000000000800000000000000002000000002000000000000000000000000000000000000000000000000000000020000000004000100200002000000000100000000000000200000040000000000000000808000020004000000000000000000400004800000000008000000000000080000403000000000010000000800000000000000000000000 +00000000000000000000000000008000040020000000000000000080041804000000000000000000000000800000000400008000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000080000000000408000000000000000000020000000000002000000010000040800000000002000008000000000100000000000000008000000000000200400100000000000000000100000000100000000800400000000000000000000000000000000000000000010001400044200000000000080068000000000000002000100000000000804000000000000000000000000 +00000000000000000000010000008020020000000000000000000000000000000000000000000000000000000000002000000000000000001000000000000000000000000000000000000000000000000000000000001000000000000002000000000000800000000000000000080000000000000000000000002000000000000000000002000000000000040000000000000900000000000000000800000000000008000200000000200000100000000800000000000000000000000000000000000000000000000400000000000000000000000000000400004200000000000000000000000100200002000000000000000800000200000000000000000400 +0221000002000000000001000000200000000800000000002000000000002000000000090000000000000000000002002000000000800000000000004000000000000000000000200000000000000000000400088000800000000002000200000000000080000000000200000000000000020040000000000000000000200008000000001206000001000000000000000100000000800000000000008040000400000000048000000000200010000000000000000000000000000000000000000000000000200000000000000000000000000a000000000000004044000000400000000000000000000002000000002400000000000000002000000000000004 +00000000000010000008010021000400000000000000100005000200000000000800000040000000000000000000000400000000000000004000000040020000000000000000000002000000040000000004010000008000000000010000000000001000800000000000008000000200000000009000000000001000000000180000000002000000800840000000010000000001040000000000000020020000000000000000000000000000100000100000000000100000008000000000000080000000000000000000000000000000000080000100101010000000010000000000040000401000000042020004000002000000000000000080000000000000 +00000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000400008000000000000100000000040000008004000001000000000004000000200004400000010000000000000080000000000000840000000000800000800000000000408040000000000000000000201000000010800000010000002000000008040000008000000000000000000000000000000000000000000004100000000000000000100000000100000100008000000000000004000800004000000000000000000000000000004200000000000100000000000000000402000000002000000000000000000000040200000000 +00000000000000000000000000008000004000080000000000000000000000000000000000000004000000000102000000000000000000000000000000000000000000000000000000000000000000008004000000000000000000010000004000000000000000000000000000080000002400400000000000000001000000000000000010000000010000040000000020000000008000000000000000000000000008000000000010200000100000000000000000000040000000000000000000000010a00000000000008000400000002000000000010004004200000040000000000000000000000002000000000000000800000000400000000000000000 +00000000000000100000010000008400000000000000000000000002000000004000000000400000040100000110000400000000080000000000001000020000000000000000000000000000000000200000000800008000104000000000000000202000400202040002000000080000000008000000000000000001000000000000000002000000010000040000000001000000008000000000000800000000000080000000000020208000100000000001008000300000000000000000008001000000000000000800000000000000000000000000000000004001000000000000000000000000000082000000000000010a00000010000000000100200000 +0000000000000000000000000000040000000000000000000004000000000002000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000001000000c000000060000000000000000000800200000402000401080100080000000000001000000000000800000000000002000000000001000000000000000100000000000000000000100000000000000000000000000000100000000002000000208000000000000000000001000000000000001400000000000000020000000000000000004000000000000000000000000040000002000000000000410000000004000000000000000000 +0200040000000000000000000000000220000000000000000000000000200000000200080000000000000000000000000000000000000002000000000000000000000000000000000000400000000000000000400000400000002000000000000000000080000000000000000108000000000000000000100200000000000000000000000200000001000000000000000000000000800000000000000000000000000000000000004000001010800000000000000000000000000000000000000001000000000000840000000000000000000000000000040000400000000000020000008000000000000a400000400000000000000000000000000000000000 +00000000000000000000010000000000000000000000000000000000000000000000000000000000000004000000000420400000000000000000000000000010000000000000000000000000000001000000000000000000000000000100000000000000000000000000000400000800000000000000000000000000000000000000000080040000010000000000000000010800008000200000000000000000000000000000000000000000100000000000400000000a00000000000000000000000000000000000000000800000000000000000000000000004804000000000000000000000080000002000002000000404000000000000000000000000000 +0000000209000400000000400000100400100000000000000000200000000002000000000000200000000000400000040004000000000000000000000000200004000000000000000000000000000000000000000c00c000000020000000000000004000000000000002000001080000000000000000000000000000000000000000000102000000000000000000010009000000000000000000002000000000000000000000000000000200100100000000000000800000000000000000000001000000000000000000000000000000000000000000000800004000000008000000000010000800800802000000000000000000000004000000020000000200 +02000000000000000080010000040000000000000000000010000000000000010000000000000000000000000000000420000000000000000000000000000000080000000000020000002000000000000004010000000000000000000000000000000400800000000000000000000000000000000000000000000000000008000000000000000800000000000000000000000800000000002000000000000000000000000000000000000000100000000000080000000000000000000000000040000000000000000400000000000800000008000000000000000000000000000000000800001002000000000000002000000000000000008000000000000000 +00000000000200000000010000003000000000000000000020000000000000820000000000000000002022000000000400000010000000000000000000080000000400000000008000000000000000000404000000008000000000000000000000000000800000000002000000080800000000008000000800200000000000000000000102000040010000000800000001000000008000000000000000000000000000000000000020000002100000000400000000000000000000000400010001000000000000200000000000000020000000000000000408004000000000000001000000000080000002000000002000000000900004000000020000000000 +00000000000000000000000000000400000000008000000000000002000000004000000000400000000000000100000400000000080000000000000000020000000000000000000000000000000000000000000000000000100000000000000000002000000202000000000000000000000008000000000000000001000000000000000002000080010000000000000001000000008000000000000000000000000080000000000000008000100000000000400000300000000000040000008000000000000000000800000000000000000000000000000000004000000000000000000000000000000002000000000000010000000000000000000000200000 +0000000000060000000001000000000000000040040000000000000000000000000000004080000400000000000200040000000800000000000000020000008100000010000000000000000002000000000401000800000000800000000000000000000c800000000001000000000000800000448010000000000000200000020080000012000082010001000000000001100800008000000001000000000004100000000100000080200000100800000000000000000000000000000000000001000000200000000000000000000000000000000100082000004000000080000000000500000080000002000000002000000010000000000100000000000000 +00000000000000000000010000000000000010000400000000800000000010000002002000000000000000000000000020001000000000000020200001000008100000000000020000000000000000000004000008000000000000000000000000200000800200000000000000002200000000400000000400000000000008080000000000040000010000000000000800000000008000002000000000000000000000000020100000200400100000000000000000020000000000000000000000000000200000000000000040000000000048000000000000004106000000000000000000000000200002000000002000000000000000000000000000001000 +00000000002000000000010000000000000000001000000000000001000000000000000002004040008000002000000400000000000000000000000000000000080000000000020000000000000000000000000000000000000000000000000000800100040001000000000000000000000000408000000000000000000000001000000000400100010200000000000000000000008000000000000000000000200000000000000000000000100000000040000000000000000100000000000000000000000000000000000000000000000008000000000000004004200000800000000000000080000002000000000100000000000000000040000000000000 +00000000000000000000010000000400000000000000000020000000000000800200000002004000048000000000000400002000000000000000000440000000000000000000000000040000000000000204010000008000004000000000000000200800842000800002000000000000002000008000000000000200000000000000000002000000010200000000000001800800018000000000020000000000000000000000000000000000100000000000000000000204000004020040000001000000000000000000000000000000000008000100001000084004200000000000000000000080000002000000002040400000000000000000000000000000 +04000000000000000000000000000000040400000000000000002000800000000000000000000000000000004002000420008000000000001000000000000000000000000000000000000000000000000000010004010000000000000040000000004000000000200000010000000000000000408000000020000020000010181000000000000000010000000000010000000800008020000020000000000080000000000000000000000000100100000000000000200a00010100000000000000000000000000020000000000000080000000000000000000004000000000000000000000000080000002000000040000000000000200000140000000000800 +00400000000000000000000400000000000000000000000000800000000000000000000000000080000000000000000000000000000000000000000040000000100000000000000000000000000000000004000000000008000000000000000000000000800000000000000000000010000000408000000000000000000000000000000002000000000000000000000201000000000000000040100000000000000000000000000000000000100200000400000000000000000100000000000000000000000000000000000000000000420000000200000000004000000000001000000000000000000002000000002000010000000000000000400000000000 +10000001000000000000000000000000000000002000000000000005000020000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000004010000000000000000000002000000000000800001000000000000080000000000408000000000000000000010020008000002000000010000000000000001000000008000000000100000000001008000000000000000000000100800000000200000000000000200000000000000000001000000000000000200000000000008000010000000004000000280000000040000000000000002000000122000000404800000000000000000000000 +00000000000000000000000000040000000000200000000000000000000000000000000000000000000000000000000420008000000000000000000000000000000000000000000000000000000000000000000008000000000000000800800000002000000000000000000008000000000000408000000000000000000000080000000000000000010000000000800000000000008000200000000004000080000000000000000000000000100000004008000000000000000100000000000000000000000000000000000000000080010000000000000000004000000000000000000000000000000006000000000400000000000000000000800000000000 +0000002000000000000000040000000000000000000000000080000800080000008000000000008000000040000040000000000000000000800000000000000000000000000000000000000000000000000400000000000800080000080000000000000001000000000000000008000000000040800000200000000002002008080000000200000000000000000000020000000000000000000000000000000000c000000420000000000000100000000400000000000000100100000000000004000000100000000000000100000000410000020000000400004000000000000000008000000000040002000400000800010000000000000000000000000000 +00000000000000000000010000000002000000002000000000000041400000000002000000000000000000000000010020400000000000000000000e00000000000400000000020000000000000040000000010000000002000000000100000000000000800001000000000002080000008000000000000000000000000000000000000000000000010000200000000000010000008000000000000000000000000000000000000000200000100000000000000000000000000000400000000000000000000000001000000000000000000008000000800000004000000000000008050000000000000002000080000000010000000000008000000000000000 +00000000040000000000010000000000000000000080000000080000000000000000000240000000000000000000000200200000000000000080000000000000000000000000000000100000000000000000000008004000000000000000000000000800000000000000000000000810000020008000200000000000000000000080100002000080010000000000000000800000008000000000000000000000008000000000000000000000108000000000000000000000000000000000001000000000400000008000000000800000008010000000000400004000000001000400000000000080000002000008000008004040000000000080000000040010 +000000000002000000000100000000000000000000000000200000000008008000000000000000a0002000400000000020000000000200000000000000004000000000000000000000000000000000400004000800000000000800100000000000000000800000000000000000000800000000000000000000000000000000000000000002040000010000000000000001000000008000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000010200020000000000400000000000000000000000400004004000000000000008000004000000002000000002001000000000000000000000000000000 +00000000000200000000010040000000008000008000008001000000000000000000000040000004040000000001000400000000000000008000000000000001000000020000000000000000000200000004000001008000004000000000000008080004840010000008001000000000210000008000000000000000000000020000000002802000000000040000000201010000000000000000000000000000000000000000000000000000100200000000000000500000000000000000000000000000000000000002000000000000000000000600001000004200000000004000001100200080000002800000002400000000000000000000100000000000 +02000400000004000000010000000000000000000000100000000000000080000000000800000000000000000000020400000000000000000000000000040000000000000001000000000004000000200004000000000000000000000000000000000000840000000000800000000000000000408000000000000000000000001000000012800000000000002000000000040000000000000000000000000000410000000000000000000000100000000000000000100000000100000100008008000000000004000800004000000000000000002000000000000200000000800100000000008000000402000000002004000000000000000000040200000000 +00000000000000000000010000000000000000000000000000000000000000800000000000000000000000000100000400000000000000000000000000020008000000000000000000040000000020000010000000000000100400000000000000000000000000000800000000080200010000002000000002000001000020000080008002040000010200000000000021090000008000000004800001000000000000000000000028208000100000000001000000100000000000000000000000000000000000200000000000000000000000000000000400004004100008000000048000000000000002000000000000000000000000000000100000000008 +04000000000200000000014000000000000000000000000061000008000000000000800000004080040000400040000000000000001000000000000000004000000000000000020000002000000000000004000800008000004800000000000000200000800000900002000000080004008000400000000000000080000000081000200002000000000040000000000001000000080000000000000800000000000800000020000000000000100000000000000000100000100000000800000001000000000000000000004004000000000008000000000000004004000000000000000000000000000002000000002000000000000004000000100020000000 +00000000040000000000000000000000000800000000000000080000800000040004000000000080040000400002000000000000000000400000000000004000000000000000000000400000000000000004010000008200004800000042000000200000800000800002000000000800000000400000000020000000000000080008000002000080010001000000000001000000008000000000000000000000000000000000000000200010100000000000000000000000100000000000000001000000200000000000000000000000000000400000000004004000000000000000000000000080000002100000022000000000000000000000000000000000 +00000400000000000000000000000000000000000000000000000001004000000000000000000200000000000000000020008000000000000000000000000100000000000000000000000004000000000000000000000000000000000100000000000200000000000000000000080000000000408000000000000000000000000080000210000000010000040000000000050000008000400000000000000000000000100000000000000000100000001000000000000000000001000010000000000000000000000000000000000000000000000000000000004200000000000000000002000000000002000000000000000000001000000000000000000000 +02000000000000000000010000004000000000000002000000000000080000000000000800000000000000000000000000000000004000000000000000000000000000000000000000000040000000000000040000008000000000000000000000400000800000000000000000000000000000000000000000000000000000001080000002000080010001010000000001000000008000000000000000000000000000000000000000220000100000000400000000100000000000000000000000000000600000000000000000000000000000000000000000004000000000000000000000000080000002000000040000000000000004000000000000404000 +00000000000000000000010000000000000000000000000000000000000000800000000000400000040000000100000420000000000000000000000000020000000000000000040000000000000000400000000000008000100000000100000000200000000000040002000000080000000000002000000000000000000000000080000002040000010000000000000001010000008000000000000000000000000080000000000008008000100000000001000000100000000000000000008001000000000000000800000000000000000000000000000000004004000802000000000000000000000002000000000000000000000010000000100000200000 +002000000000000000000100000000000000000000000000000000010002020000000000000004040800000000000004000000000000000000008000400000010400000000000200000000000000000000040000000080000000000000000000000000000400010000020000000000000100000080000000000000000020000000010000024000000002000000020002000100000000000000000000000000000000004000000000000000001000080080000000001000000000000400000080010000000000000000000000000000000000080401000000040040000000000000000000000000c0000002000000000000000000000000000000001000000000 +02000000000000000008010002400002000000000000008020000001000000000000000000000000000000000000000020000000000000000000000000000000000000000000020000000000000000000000000800000000000000040800000000000000800001000008000000000004000000000000000040000000000000000000000000402000010000000000000001000000008000000000000000000000000000000000000000002000100000000000001000000000000000000000000000000000002000000000000000000000000008000000000000004000000000000000000100000000000002000000000000000000010100000000000000000000 +00000000000000002004010440000000000000000000000000000000002000000010200040000080040000400040400000000000000000000000000000000000000000000000000000020000000000000004000000008008004800000000200000000000810000000000000000000000000000408000000000000000000000000000100002000000000000000000000000000000000000000000400000000000000000000100000000000000100200000400000000100000100100000000000000000000000001000000040000000000400000200200000000004000000000800000000000000000000002000000002000010000000000000000000000000000 +00000000000000000000010000000000000000000000000000000000200000000000000001000000000000400000000400010000000000000000000000004000000000000000000000000000000000008004000800000000000000100000000000000000000000000000000000000000000000000000000000002000010000000080000000000080010000000000000041000800000000010000000000000000000000000000000000200010100000000000000000000000100000000000008000000000000004000800000400000000000000000000000000004020010000000000000000000180000402000000000000000000000000000000000000000010 +00000000000000000000010000000000000000000000000000002000200800100000000000000000008000004000000020000000000000000000000040010000080000000000000000000000000000000004000004000000000000000000000000004800840000000000000000000000000000008000000000000000000000000000000002040000010000000000010001000000008000000000000000000000000000000000002000000000100300000000000000000000000000000000000000000000000000000000000000000000020008000200000400004004600000000800008100000000000002004000002001000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000090002000000000000000001000420000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000080000000000000000000800000000000000000000000002000000010200000000000000000800008000000000000000000008000000000000000000220000108000000000000000000200000000000000010000000000200000000000000000000000000000000004000408004000000000000000000000000080000002000000000000400000000000000100000000200000 +02040002000000000000000000000002000000000000000000000000000000000000000800800008020100040000000000000000000000000000000400000000000000200001000000200000000000000000010008004000000020000000000000000800880000200000000001080000000000008000000000000020000000000000100002000000010000000000000008000000000000000000020000000000000000800000000000000000100000000000000000000000080000000000000000000080000000008400000000400080000000100000000080004000000002000060000000000000000002004000000040000000000000000000000000000200 +00010000000000000000010000000000000000000000000220000000000000000002000000000000000080000000000420000008000400000000000240000008000000000000000000000000000000004004000820004000000020000000000000000000800000000000000001000200000000000000000000000000000000000000000002050000010000000000000801080000008000000000100000000000000000000000000000000000100200000000000000100000000000000000008440000000000000000000000000100000000400000200000000004024000100000000000000000000000012000000802800000080000000000000020000000000 +00000000000000000100010000000000000000000000000000000000000000000000200000000000040000000000000040200000000080000020000000000000000000000000000100000000000000000004000008000000000000000000000000000000800000000000000000080000000020408000220000200000000002090000000002000080010000000000001000000000008000000000000000200000008000220120000000000000100000000000000000000040000100000000000000000000000002000000000000800000000000000000000000004000000000800000000000000180000002000000002000000000000000000000000000000010 +00000000000000000000000000000000000000000000000000000001000000000000000000000200020004000000000020008000000000800000000000040000000000000000000000000004400000200000000000000000000000000000000800000000000000000000000000000000000000408000000000000000000000001000000210000001010000040000000000040000008000000000000000000000000000100000000000000000100000200000000000000000000100000000000000000000000000000000000000000000000000000000000000004200000000000000000002010000000002000000000002000000000000000000000000000000 +00000020000000000000000000000000040020000000000000000000000000000000000000000000000000000000000400008000000000000000000000020000000800000000000000080000000020000004010000000000000400000000000000002200800000000000000000080200010000408000400002000000000040000000000022000000000200000000000000090000000000002004000000000000000000000000000000200000100200200000000002100000010100000000000000000000000000000000000000002000000000000200000000004000000000000000040100000000000002000000002000000000001000000000000000000000 +02000000000000400000014008000000001000000000004000000000000000820000000800004000040000000000000000000000000000002000000000000000000000000008000000000000000000000080000900008000004000000800000000000000010000000002000000080000000000000000000000010000001000000800000002000000000000000000000001000000800000000000002000000000000000000000000000002000100200000000000000000000000000000000000001000000000000000000000000000000000000000000000000004004002008000000000000000020000002000000000000000000000004044000000000000000 +04000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000080008000000000000000010000200000000000200080010000000020000000000000004000000200200000000000000000000000000800000000000000000000000000000408000200000400000000000181800000000000000010000000000000009000000008000000000100000000008000000000020000000000000100000000000000020000000100100000000000000000000000000000000000000000000001000000010000000044000000000000000000000200000000002000080002000000002000000000040010000000000 +00100000000000000000010000000000000000000000000000000000000000820200000000000000000000000000000400000000000020000000000000000000000400000000000000000000000000000000000000008000000000000100000000000800000000000202000000000000000000000000000000000000000000000000080002000000010800000000000081010000008000000000000000000000000000000000000020000000100200100401000000100000000200000000008001000000400004300808000000000020000000000000000000004000000000000000000000000080000402000000000000000000000004000000000000000000 +00000000000000040000010000000000000000000000000000000000000000000000000000000000000000000000000401100000000000000010000000020000000800000000000000000000000020000000010800000000100400000000000000000a00000000000000000000080000010000408000400002000000004000000000000000000000000200000000000221010000000000000004800000000000000000000000000000208000100000200001008002100000000500000000040000000000000000000000000000000000000000000000000000004000020000800000040000000002000002000000000000000000800000000000000000000000 +00000000000000000000010000000000000000000000000000000020000000000000000040100000000000000000000420000000000000000020000000000000040000000000000000800000008000000000000004000000000000000000000000004004000000000000000010000000000000009000000000000001008000000000000202000000030000000040000200000000008008000000000000000000000000000000000000000080100108000000000001900000000000000000000000000000000000000000000000000000000000080100000000004004000000000000000002000050000002040002800000000000100000000110000000000000 +00000082000200000000010000001000000000000000008000000000000000000000000040000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004000000004000000000000000000000000004800800000808000000400000280000000000000000000000000000000000000002002000000000000000000001000002000000000000000080000000000000100000000000200000500200000000000000000000000000000002000000000010000000000000000100000000080000000200020800004000000000000000000300000000000002000000002000000000000000000000000000000200 +0000000000000000000001000000000000000000000000000000000000000000080000000200000000000000810000042000000000000000000004040000000800000000000000020000000000000000001001000000000000000000000000000000080000000000000000000000020000000000000000000000000100000000000000000200000001220000000000000008000000800000000002000100000000000020000000002020000010060000000000000000800400000000004000000000000020000020000000000000000000000000000010000000400010000000000000000000008000000a000002000040400000000000000000000000000008 +02000000000000000000000000000001000000000000000000000000000000000000000200000004000000000000000020000000004000000000000000000000000000000100000000000000000000000004000000004000000000000000000040000000000000000000000000000000000000408000000000000000000000080010000002000000010000000000000200000000008000100000000000000000000000000120000000020000100000000000000000000000100000000000000000004000000000000000000000000000000000000000000000004000002000000000000000000000000002000000000000000000000000000000000000000200 +00000008c00000000000004000000000000000000000000000080000000000020000000800000000003000400100000000000000000000020080000000000000000000000004000000000000200000000000010000008008000000000400000000000000000000001002000000080000000000410000000000000000000000000000400002000000000000000010000000000000000000000000110000000000000000000000000020200000100000000000000000000000040000000000000001000000000000800000000000000000000000000000000000044000100000000001800000000080800002000000020008000000000004000000000000000000 +0000000000000000000001200000000000000a000000000000000000000000000000000000000000000000080040000400000000000020000000000000000000000000000000020000000000000000000004000480008000000000000000000000000000800000000000000000080000000000000000000000000000000000000000080000000000010000000000000000000000000000000000000000000000000000000000000000001000100200040000000000000000000000000000048000000400000004000800000000000000000008200200000000004000000000000000000000000000000402000000022000000000000400000220100000000000 +00000000000000000000010000000080000008000000008100000000000000000800000040000000000000000000000000000000000000020000000000000000000000000000000000000000000000000004010000008000000000000400000000000000800000000008000000080000000000400000000000000000000000000008000002000000000000000000000001000000000000000000400000000000000000000040000020000000100000000000000000000000000000000000000000000000000000000000000000800000000000000000000400004040000000000001000100000000800002000000022000000000000000000010000000000000 +0000000200000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000c000000000000002000000000000800000000800000000480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000100000000000000000000000100000000000000000000000000000000400000000000000000000000000000000004000000004000000000000000000000002000000000000000000000000800000000000000200 +00000000000000040000001000000000000000000000000002000000000200000000000000000004040000000000000420080002000000000000000000000001000000000000000000000000000000000004000080008000004000008000000000200000000000800002000000000000000000008000000000000000000000000001000202000000010200000000000000000000008000000000000000000000000000000000000000000000100008008000000000100000000000040000008001000000000000000000020000002000000000000100000400004008000000000000000002000080000002000000000000000000000000000002200000000000 +10000000000000000010010000000000000000000000008000000000000800000000000000004084000000400040000000000000000000000000010000004000000000000000020000000000000000000004000400000000000800008001000000000000000000000008000000080800000000208000c00000000000000000000000000002000000000000000000200001000000000000000000000000004000000000000000100000000000100000040000000000800000900000000000000000000400000000000000000000000000000008000000000400004004200000800000008000000000000002000000000001000000000000000000000000000000 +02000000000200000000030000002000000000008000000000000001040000000000000050000000240000000000000020000000000000000000000000000000000000000000020000800000000000000004000000000000000000040000000000000004800001000100000004000000080802400000000000000000000000180000000002440000010000000000000001000000008000000000100000000000001000000400000000002000100000000000000000000000000000000000000000000400000000000000000000000000000008000000000000004004000000000000000000000020000002000000802000000000000000000000000000000000 +00000000000200000000010000000000000000000000008100000000000000000000000000000004000000000100000000000000000000000000000000000000000000000000000000100000000001000404000000000080000020000000000000000000800000000000000000880000200000008000000000000001008020000080008002000080010000000000000201000000000000000000000000000000000000000000000000000000500000000000000001000040000000000000000000000010000000000000000000000000000000000000400400004001000000000000008100000080000002000000802000000000000000000100000000000020 +00000000000000000000000200000000040000000000000000000000000000000000000000000202000000000000080400000000000000000000000200000000000000080010000000000000000008000040000000000000000000000000000000000000000000000000000000000200000000400000000000000000000000081800000000000000010000040000000000000000008000000000100000000000000000040020000000000000100000000000000020000000000000000002800000000000000000000000000000000000000000000010000000044200000000000000000000000000100402000000000000000000000000000000000000000000 +00000000000200000004010000001000000000000000008100000000000000000000000000000100000020800000008400000000000800000000000000000000000000000001000000000000000000000404000000000080000000000000000000000000800000000000000000080000200000000000000000000000000020000080008002000040010000040000000001010000000000010000000000000000000000000000000000000000100000000000000000800000000000000408000000000000000000000802000000000000000000000400000400004001000000000000008100000080000402000000002000004000800000000000100000000000 +00000000000000000000000000000000000200100000000000080000000000000000000000000000000000400000000000000000004000020080000000000000000000000000000000002000000000000000010082800000800000000400000000000000000000001000000000080000000000400000000000000000400000000008000082000000000000000000000000000000000000004000000000000000004000000000000020200000100100000000000000000000000000000000008000000000000000000000000000000000000000000000000020004000000000000001000000000080800002000000020000000000000000000000000020040000 +00000000000000000000010400000000000000000000000000000000000000800000000002000000000000000000000421100000000000000010080000000000000000001000000000000000000000400000010000000000100000000000000000000800000000000000000000000000000000002000000000000000004000000000000000040000010200000000000001010000008000000000000000000000000040000000000000200000100200000001000000000000000000000000000000000000200000000000000000000000000000000000100004004004020000000000000000000080000002000000000000000000800000000000100000000000 +00000000000000000000016000010000001000082020000020000021000000020000000000004000000000000000000400000000000000400000000000000000000000000000020000000100000010000004010800008200000000000900000000000000810000100802000000080000000000408000000000400000000000081880800002000000010000000200000001010000000020000000002800000000000000000020000000000000100000000040000008000000000100000800000001000000000000001000000000000000000008000000000400004024200000800002000000080080000002000002006000000000000004000000000000000020 +04000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000001000000000000000000000000000000000000000000000004000000000000000000000001000000000100800000000000000000080100000000408000000000000000000000001080000000040000010000000000040000000000000000000000000002000000000000000000000000000000100200000040000000000000000100000000000000000000000000000000000000000000000000000000000000004004200800800000000000000000000002000000002000000000000000000240000000000000 +00000000000002000200010200000000000000000000000000000000000800000000000001000202000000400000002400000000000000000000000000000008000000000000000000000100000000000004000000001000000000000102000000000000800000000000000000080200000000400000000001000000000000000080000002000000010100140000000001000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000040000000000400000000200080000040000000000500004000000000000000008000000000100402000001000001000010000000000000000000000000 +02000000000000000000000000001000000200000000010000000000000000000000004000000004000000000900000400000800000000000000000000000080000000000001020000000000000000000044000000000000000000000000000000020000000000000000000001000000000002000000000000000001000000000000000000000040010000000000000000100000008000000000000000000000000000000000000000200000100000000000000410000400100000000000000000000000201000000000000000000000000008000000001000004000000040000000000000000080000002000000000000000000000000000000000000000000 +00000000000000000000010000000000000000000000000000000002000000800000000000400000000000000100000400000000000020000000000000020000000000000000000000000000000000002000000000000000100000000000000000000000000000040000000000000000000000002000000000000001000000000000080002040000010000000000000001000000008000000000000000000000000080000000000000008000108000000001000000100000000000000000008400000000000004000800000000000000000000000000000400004004000000000000800000000000000402000020000000000000000000000080100000200000 +04000000000000000000010000001000000000010408000000000000000000000000000002000000000020000000000400000000000000000020000000000000000000000020000000000000000000000000000008000000000000000000020000000000000200000000000000002204000000400000000000001000800000081000000080000000010200000000000000000000008000000000000000000000000000000024000000000000100000000000000000000000000000000000000050000000000000000000000000000000000000000000000000084000000000000000000000000080010002000000000800000000000000000000000000000000 +00200000000000000000010000000400000000000000000000000000000000000000000000000000000000000000008000001000008800000000000040000000000000000000000000000000000000000000000000008000000020400080000010000000800200000002000000000000000000000000000000002000002000000000000002000000000000002000000000000800000000000000000202100800000000000000000000000000108200000002000000200000000000000000000000000010000000000000000001000000020000000200000000044000000000000000000000000100000002000000800000010000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000008000000000000000000040000000000800000000000000000000000000000004010000000000000800000000020002000000800000004000000000000000000000408000480000000000000040000000000000000000010000000000000001000000008800000001000000000004008000000000000000000000100200200000000002000200000100000000000000000000000000000000000000800000020000000300000000004000000004000800420100000000000002000000002000000000000800000000000000000000 +02000000000004000000010000000000000000100000000000000000000080000000000800000000040000000000000020000000000000000000000000040000000000000000040001000004000000200004400000008000000000000080000000000000840000000000000000000000080000408000000000000000000000001000000012020000010000000000000000040000008000000000000000000000400000000000000000000000100000000040000040000000000100000000000008000000000000000000000000000000000000000000000002004200000000800000000000008000000002000000002004000000000000000000000200000000 +04020000000200000000010000000000000000000000000000000000000000000000200000000000000010000040000000000000000000000000000000000000000000000000020000000000000000000004000000000000000000010002004000000000800000000000020000080000002000408000200000400000000000001000000000000000010000000000000021000000008000000001000000000000100000000100000000000000100000000040000080000000000100000000000000000000000000000000008000000000400008000000000000004000000000800000010100000000010002000000002001000010000000008040000000000000 +0020000000000400000001000200000000000800040000802082000000000000000000000000000108000000000000002000000000020000000000000000011000000000000010000000000000000000000400080a008080000000000000000000000000800000000000000000000000000000008000000000000000000000000000000002002000010000000000000201000000008000000000000000000000000000000040000000000000100000000000000000000000000400000000000000000000000000000008000000000000000000000000200400004040400000400000000100000000000002000000002000000000000000006000000000800000 +00000400000000000000000000000000000000000000000000000001000000000000000000000000000004000000020400008000000000000100000000040020008014000000000000000004000000200004000000008000000000000000000000000000840000000002000000800000000000408000000000000000000000201000000012020000010000000000000009040000008000000001000000000000000000000000000000000004100000000000000000100000000100000000000000000000000000000000000000000000000000002000000000004200000000000000000000000000000402000000002000000000000000000000000200000000 +00000082000000000000010000000000000000000000000000000000000000000000000000004000000000000000000420000000000000000000000000400000000000000000000000000000000000000004000000004040000000000000000000000000800000000808000000400000000000009000000000040100000000000000000000000000002000000000000000000000000000000000000000000000000000100000000000000020100000000000020000008000000000000000001000000000000000000800000000004000000008000000000000004004200000000000000000000000000402000000002000000000000000000000000000000200 +00000000000000000020010400000400000002000100008000000000804000000000000040000000000000000000000400010000000000000000010040840000000000000000000001000000000000000014000000008008000000000000000000000100840000000008200000080000000000408000000000000000000000080882000202062000010000000000000001000000000000000000000000000008000000000022000000000001100000000400000000800000000100200000000000000000400000000000000000000000400000000000000000004004010000008000000102000000080002000000002000010000100000040000010200000000 +020000002000000000000100000011000000000000000000200000400000018000000008000040040000000001000004200000000000000200000000000000c10000000000010020000000000000000000040100080040000000000005080000000000008400000000000000000800000000004080100000000000000000a00000080000020000000100000000200800010520000080000000000000000000000000000000000000200040001000020000000000000000000000008008c4000000000080200000000000000000a00000000000201000000000004004000008000001001000000080800002000000022000000000000000000100000000000000 +00000000000000000000010000000400000000000000000000000000000000000000000000000000000000000000000000212000000000000000000000000000000100000000000000180000000000000010000008200000000000000000000000000000000000000000000000000200040020008000200000000000000000000000000002000000010000000000000000880010008000000000000000000000008000000000000000000000100000000000000000000000000000000000000000000000000002000000000000800000000000000000000000004000000020000000080000000000000002000000000000000000000000000000000000000010 +02000002000200000000010000000000000000400000000000000000001000000000000000002040000000000000000420000000000000020000000000002000000000000000000000000000000000000104010000004000000020000400000000000000800000000000000001080000000000548000000000000000000000000008000400000000000000000000000009000000400800000000000000000000000200000100000020000000100000200000000000000000000000000000000000000000000000000000000000800000000000000000000000004000000010000001000000004000c00812000000022000010000100000000000000000000200 +02800400000000000000000000000000000000000000000000000000000000000000000000000000000000000000022020000000000000000020000000040000000000000000002000000004000000600004000000000000000000000000000000200000840000000000000000000000000000408000000000000000000000021000000012008000010000000000000000040000008000000000000000000200000010000002000000002000100000000000000000000000000100000000000000000000002000000000000000000000000000002000000000004200000000000000000000000000000002000000002000000000000000000000000200000000 +00000000000000000000000000008000000000002000000000000001000000000040000000000000100000000010000400000000000000040000000000000000000080000000020000000000000000000000050000004000000020000000000000004000000001000000000001080000000000000000000000000000000000000000000002000000000200040000000001000000000000000000000000000000100000000000000000000000100000000000000010800000000000000400000000000000000000001000000000004000000008000000000400404200000008000400000400000080000802000000000000000800000000000040000000000800 +0000000000000000040001000000000000000000000000000000000000000000000000100000000400000000080000002000000000000002000000000000000002000000000000000000000000000000001401000000040080020000004000000000000000400000000002000000000000100040800000000000000000000008000000021000200001000004000000000004000000800000000000000000000001000000000000000000008010808000000000000200000000430000000000000000000000000400001000000080000000000000000000000000400000000080000000000200000000040a000000020008000000000000000000000000000000 +00200000000800000004011400080000000000080000000002000000000000000000800000000000042000000100000420000000000000000000010000000000000000000000000000000010000000000040000000018008004000100002000000100000800000000000000000081000000000008000000000000000000000000000000202000000010000040000000000000000108000000000000000000000000000000400000000000100100000000400000000900000020000200000008000000000000100008400020000040000400000000000000400004004000000000000000002000000000002000000000000010000000000000000104000000000 +00000000000000000000010000000400000000000000000000000000000000000008200000000004008000000000000020000000000000000000000000000001000800000000100000040000000000000004010000000000000000000000000008000000840000000000000000000000000200408000400000000000000000000000100002040000010000000000000200000800008000400000000000040000000000000100000000000000100000200000000002001200000100000000000000000000000000000000000000000000000008200000000000084004200000800000000000000002000002000000002000000000000010000000000000000000 +00000000002000000000000000000000200000080000000000400000000000000000000000000004000000000000000420000000000000000000000000000001800000000000100000000000000000000004010000000000000001000100000000000000000000000000000000000000000000808000000000000000000000000000800002000000010000000000000200010000008000000000000000000000200000000100000000200000100000000000000000000000000000000000000000000000200000041000000000000000000000000000005000004000010000000000000000000080000002000000000001000000000000000000000000000000 +00000000000000040000010400000000000000000000000000000000000000000000000002000000000000000140000420000000000000000000080000000000000800001000020000000000000000000000010800000000100400000000000000000000000000000000000000000000000000408000400000400001000000000000000000000000010200000000000201000000008000000000000000000000000000200000100000300000100200200001008002000000000500000000000000000000200000000000000000000000000008000000100000004000000000800000000000000082000002000000000000000000000000000000000000000000 +00000000000200000000010000001000000000000400008000000000000000000000000000000000000020000000010400000000000000000000000040000000000000000000000000000000000000000004100008000000000000000200020000200000800000000008000000000200200000000000000001000000808000000000000002002000000100000000000001080800000000000000000000000000000000000000000000000000180000000000000000800a00000000000400000000000000000000000000000000000000100000001000000000014000000000000000000100000081000002000000002000000000800000040000000000000000 +00000000000000000000010000000000000000000000200000000000000000000000000000000000000000000000000440040000000020000000008000000000000000000000000000000000000000000010000000004000000000010000000000000000820000000000000000000200002000000000000002000000000000000000080002000000010000000000000020080000000000000000000000000000000000000000020000000000100200000000000000000000000000000000008100000000000004000800008000000200000000000200000000004000000000000000000000000000000402000000000008000000000400000200000000000000 +020000000042000000000100000034000000000001000000000000000000000000000008000000800000200000000004a0002000000000020400000000000000000000000001000000000000000000000004010000000000000000000400000000000000c00200000000004000080080010010400000000000001000000000000008000002000040010000000000008001010040008000000000000000000000000040000000000020002000100000000000000400200000000000000000000000000010002000000000000800800000000000800000000000004000000000000001000000000080800002000000022000030000000000000000000000000008 +02000000000000000000000000000800000000000000008000000000082000000000000002000000000000000000000400000000000000000000000000000000000000000000000000030a00000020000000000000004000000000000800000000000800800000000000000000000000000000408010000000000000000000480000000000000000010200004001000000000000008000000000400080000000001000000020000000204000100000004000020000100000000110000000000000000000200000000000000020200000000000000000000000004000200000000000000000000040000412000000000000000000000000000000000000000000 +000000000000000000000000000000000400020000000000000000000000200000000002000000000020000000000004000080000000000000000000000000000008000000000000000000000000000000050100001080080000000100000000000000048000000000020000000000000004004080014000000000050000400000000000020000000100000000000000010000080080000000000000000000000000000000000000000000001000002004000000a2000000010100000000000000000000000000000000020000000000000000000000000000004000000000000000000000000080000002000000002000010000002004008000000000000000 +000000000000000000000100000010000000000004000000000000000000000000000000020000000000200000000004000000000000000000200000000000000000000000200000000000000000000000000008080000000000000000000200000000000000000000000000000020000000000000000000000010008000000000000000000000000102000000000000000000000080000000000000000000000000000000040000000000001000000000000000000000000004000000000000c0000000000000000000000000000000000000000000000000004000000000000000000000000080000002000000000000000000000000000000000000000000 +04000000000200000000010000001400000000000000000000000000000000000000001000004040000020000400000401010000000000020000000000000000000000000000000000000008000000000004010000000000000000000c08000000000000800008000000000000080804000000408000010000000000000000081008000002000000000000000200000001100000000000000000000000001000000000000020000020000000100000000000400000020000000000000404000000008000000000000000000000800000100004000000000000004004000000000001000000000000800002000000422000000000800000000002000000000040 +02000000000000000000014400000000000000000000000020000000000000020402000000000004000000400040000000010000000000000000000040000000004800080060000400020040000000000004010000008008000000000000000000000000810000000002000000080000000000408000400000000000000000001000000002000000000000000002000001000000000000000000000000000200000000000000000000002000100200200400000002000000100100000000000001000000000000000000000000000000440000000200000000004000400000000000000000000030000002000000002000010000000004000040004000010000 +00100000000000000000010000000000000000000000008000000000000000820000000000000000000000400000000400000002000000000000000000000000000400000000000000000000000000000004000000009080000000000101000000000800000000000002000000080000000000000000000000000000000000000080000002000000010800000000000081010000008000000000002000004000000000000000000020000000100200100401000000100000100200000000000001000000400000300018000000000020000000000000000000004000000000000000000000000080000402000000000000000000400004100000000000000000 +0200000000000004000001100000000000000800000400000000000002000000000000080000400000000000100000040000000000000000000000000040000000020000000000000000000004000000000401000000c0000000200000000000000000008000000000400000000a00000800004080000000000000001000000a100800000300000c020000004804810000000002000000000000000000000000118200110020000000000000108000000004400000000000000100008000000100000000000400000000000000000000000000000000000c00040000800010000000000000000090000002000000002006000010000000000040000000800000 +00400000000000000000010000000000000000000000000010000000000002800000000000000000000000000000008400000000000000000000000000020000000000000000000000080000000020000004010008000000100400000000000040002200800000000000000000080200010000002000000002000000000000000000000022000000010200000000000021090000000000002004800000010000000000000000000000208000100200000001000000100000000000000000000000000080000000800000000000002000000000000200000000004000000000000000040000000000000002000000002000000000001000000000000000000000 +02000000002000040000000000000000000000000000008000000001000200000000000802000000028000002000000400000000080000000000000000080000000004000000020000000000008000000000000000000000000020000200000000000000000009000008008000080000000000008000000000001000000000001000100002400000010200000000400001000000008000000001000000000000200000800000000000000000100000000000000000000000000000002000100000000000000000000000000000000000000008100000000000004000000000000000000002000080000002000000001000000000000000000002000000080000 +240000000000000400000100000020000000080000000000000000008000000000000000000000040000000000000000000000000000002080000000000000000002002000001000000000000400000000040100000480000000200000000000000000008000000000404600000000040000004080000010000000000100400a1008000022000400001000004000010000000002080000000400000000020000000000800428000008000000100000000000000000010200008000002100000000000000000000000000000000000000000000000000000000000000000000000000000000000004400000000000402006000040000000020002000000000001 +000020200000000000000106000000000000000000000000000000000000108000000000000040a0004000400000000000000020000000000000000000004000000000000000000000080000000000400004000004000008000800000000000000004000800000000000000000000a00000000000000000000000000000000000000000002000001020000000000000001080000000000002000000000000000000000000000000000000000100300000400000000000000100000000000000000000000000000000000000400000000400080000200000000004004000000000000000000000020000002000000002000010080000000000000000000000000 +00400000000000000000051000000000000000000008000010000000000202000000000000000004000000000000008400008002000000000000000000000001000800000000000000000000000000000004010088000000000000000000000200000000040000000000000000000000000000408000400000000000000040000001020002000000010200000000000000000000000000000000000000010000000000400000000000000000100000220000000002100000000100000000008000000080000000000000000000000000100000000100000400004000200010000000000000000280000002000000000000000000000000000000000000000000 +00000000000000000000000000008000001000080100000000000000000000000000000000012000080000000000000400000000000001020100000000000000000000000000000000000000000000000004010000000000000000000400000000000040800000000000000000080000010000400000000000001000000000000008000000000000010000040000000008010800008000000400000000000000000000000000000020000000100200000000000000500000000000000000000000000000000000000002000800800000000000000600008000004200040000000001000000000088800402000000022000000000000000000200000000000000 +04000000004000000000000000000000000002000000000000000002008000000000100000000000000000000000000000000000000000000000000000000000000000000000000000028000000000000004010004008000000000000000000000004000800000000002000000000004000400400800000000000000000000081000000002000000000001000000010001800800000000000000000000000000000040400020000000000000100100000000000000200200000000000000000000000000000000000000000000000000000000000000800400000000000000000000040000000000000000001000002000000000000000000000000000000000 +00000000000000000000010000000000000010000000008000000000040000000000000000000000000000000000000000200000000000000000000000000200000000000000000000120000000000000000000008000000000000020800000000000000000000000000000000000000001020408000200000000000000000080000000000000000010000000000000000800000008000000000000000000010008000000020000000000000100000000200000000000000020100000000000000000000200002000000000000800000000000000000000000004000000000000000000000000000000002000000002000000000000000000000000000000010 +00000000000400000000010000000000000000000400000000000010000000800000000000000000000000010002000400000000000800000000000400000080040000200000000000000000000080000000010008000000100000000000000000000800000000000000000000000010000000402000000200000000200000001000000002000000010000004000000001800000000000000000020000000000000000000000000000000000108000000001400800000004000000000040000000000000000000000000000000000000000000000000000400044000000000000000000200000080000002000000000040400000000000000100000000000000 +00000000002000000000000000000000000000000000000400000000000800400200000002000000000000002000000400000410000080000000000040000000000000000000000000000000000000000004000000000000100000000000000000000000800000000000000000000000000000008000000000000000000000000000000002000000010200000000000001100000008000000000000000000000200000000000000000002000100200000000000000000000000000000000000000000000000000000000000000000000020000000300000400014000000080000800008108000080000002000000002003000000004000000000000000000000 +000000000000000000000100000000000000000000000000400000010000000000000000000000a0000000400000000000000000000000000000000000004000000800000000000000000000000000000024010800000008000800100000000000000000000000000000000000080000000000408000400000000000000000000000000002000000000000000000000201000000000000000000000000000000000001000000000000000040108000200000000002000000100500400000000000000000000000040000000400000000000000000000000400004000000000800000000000000102000002400000800000010000000000000000000000000000 +00000000000000000000000400000000000000000000008000000000000000000000000002000000000000000000008421100000000000000010080000080000000000000000000000000000000000000000010000000000100000000000000000000800000000000000000000000001000000000000000000000000004000000000000000000000010200000000000401010000008000010000000000000000000040000000000000200000100200000000000000000000000000000000100000000000200000000800000000000000400000000000100004004000020000000000000000000080000402000000000000000000800000000000000000000000 +00000004000000000000010000010000000000000000000002000000000000080000000040004008000000000000000000000000000000000000000000000000000000000000000000200000000000000000000004000000000000000000000000000004800000000000000000080200000000000000000000000000000000000000000002000000000000000000000000001000000000000000000800000000000000000000000000000000100000000000000000000000080000000000000000000000000000008400000000000000000000000000000000004004020000000000000000100000000002000000000000000080000000000000000000000000 +00000000000004000000010000000000000000000000000000000000400000000000000020000000000000000000008400000000000000000000000000240200000000000000000000000004000400200004400000000008000000000080000000000000840000000000000000080000000000408040000000000000000000001080000010000004010000000000000000040000000000010000000000000000000000000000000000000000100200000040000000000000008100000100000000000000000000000800000000000000400008000000000000004204200800800000000000000000000402000000002000010000000000000200000200000000 +00000000000000000000000000000100040000000001000000000000000000000000000002000000000000000000008420000000000000000000000000000000000000000001000000000000000000040000000000100000000000400000000000000000000000000000000000000004000000408000000000000000000000081000000002000000010200000000000000010000008000010000000000000000000040200020000000200000100200000004000000000000000100000000000000000000220100000800001000000000004000000000100000004000000000000000000000000080000402000000000000000000000000000040000000000000 +2200000004000000000001100000200000000000000000000100000082000000000000084000000400000000000000040000000000000020800200000040000000000000000000000010000000000000000400001000800000002000000000000000000080000000000046000088000000000040800000000000000000004008100000002300040002000000080404000000000001000000040000000002000000820081002000000000000010800000000040000001020000810000a000000000000000400400000000000000000000000000000000000c00040000000000000000000000000090000002000000002004000010000000000000000000000001 +00000000080000000000010000000000000000000000000000000000000000800000000000000000000000000100000400000000000000000000000400020008000000000000000000040000000020000010000000000200100410000000000000000000000000000000040000080200010000402000000002040001000000000000000002000000010200000000000021090000008000000004800001000000000000000000000028208000100000000001000000100000000000000000008000000000000000200000000000000000000000000000000408004000100000000000040000000000000002000000000000000000000000000000000000000808 +02000000000400000000010020001000000000000400000000000050000000000000000800000000000020000002000420000000000800000084000004000080000000000000000000000000008080000000000008000400100000000000000400000000800000000000004000000010000000400000000000000000200000001000000002040040010000000000000001000000008000000000000000000000000000000000000000000000108000000000400000000000000000000000000000200000000000000004040000000000000000000000000000044004000000000000000200000080000002000000000000000000002000000100000004000100 +0000000000000000000001000000000000000000000000002000022080020000000000004000000404000000000000000000000000000000000000000000000000000000000000000080000008000000000400080000820000400000000000000020004c800000800002000000000080200000408000000000000000000000080000000002000000000000000000000001000000000000000004000000000080000000000000000000000000100000000050000000000000000000000000000001000000000000000000002000000000000000000000000000004000000000000008000002000000000012000000802004000000100000100000000000000000 +00000000000000000000030000001000001080002000000000040001000000000000000000000000000000000040000000000000000000000000000000000000000000000000020000000000008000000024000000000000000800000000020400000000800001004000000000080000000001000000000020000000000008000000000800000000000001000000000000000900000800020000000000000000000000000000000020000400100000000000000000000000000000000000000000000000000000000400000000000000000008000000000000204000000000004000000000000008000002000000004000000000004800000000020000102000 +0000000000000000000001000000000000000000000000800000000001000000000000004000000420020000000000040000000000000000000000000008000000000080000000000080000000000000008404000000008000020000000000000000000c000000000000000000080000000000800000000000000000000020000080008012000000010000040000000001000000000000000000000000000000010000000000000000000000100000000000000000000000080000000000000000080000000000000000400000000000000000000000000400004001200000000000008000000000010002000000800010000000000000000000000000000000 +00200008000000000000010000001000000000000000000000000000000000000000000000000000000020000000008420000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000200000040000010000800000000000000040008000010008000800000000000000000000000000000000100000000000000000000000000000000000000000000000000000000800000000000000000000000000000000004004000000000000000000000000000402000000000000000000000000000000000000000000 +02000000000000000008010400000000000000000000000000000000000000000000001000000004000000000000000020000000000000000000000000000000020000001000000000000000000000000034000000000408800200000800000000000000004000000000020000000004000000408000000000000000000000000000000210000000010000040000000200040000008000000000000100000000010000000000000000002080100000000400000002000000004500000000000000000000000000000000000000000000400000000000000000004000000000800000000002000020000402000000800000010000000000000000000000000000 +00000800000000000000000000000400000000000000000000000000100200804000000000000004000000000400000000000000080080000000000000020000000000000000000000000000000000000004000000000000001800000000020000000800000200004000000000081000000000008000000000000000000200000000000012000000000000040000000000000000000800000000000000000004000000000000000010000000100000000000000000200000000000000000000000000000000000000000000000000000000040000000000000004080000000000000000002000000000002000000000000010000080800020000000008000000 +00000000000000100000010000008000000000080000000020000000000020000000000020000000040000000000000020000000000000000000000000000000000800000000000000000000000000000004200800008000004000080100000000200000800000100002000000080000000000000000000000000000000000020000000002000000010000040000000001010000008000000000001800000000000008000000000000200000100000000000000000000000000000000000000001000000200000000000000000000000000000000000000000004200000000000000000000000000000002000000022000000800000210000000000000000400 +00000000000000000000000400000000000000000000008000000000000000020000000002000000000000000100008420000000000000000000080000080000000000000000000000000000000000000000000000008000500000000000000000000000000000000002000000000001000000000000000000000001000000000000000002000000010200000000000401000000008000010000000000000000000000200000000000200000100200000400000000000000000000000000100001000000200000000800000000000000400000000000100000004000000000000000000000000080000402000000000000010000000004000000000000000000 +00000000000000000000010000000400000000000000000000000000000000000000000000000000000000000000000400880000000000000000000000040000000000000001000000000000000000000004000008000000000000000081000000000100800210000004800000080000800000408040000000000000000000000000000010020000000000000000000040140000000000004000000000100000010000000000000000000001100000000002000000200000080100000140000000000000000000000000004000000000000000000000000000000204200800800000000000000000000002000000002000010000000000000000000200000000 +02000000000000000000010400000000000000000000000020000000000000800000000000004000000400000000008400880000080000000000000000000000000000000001002000000000000400400004000008000008000000000201000000000000800210000000800000000200000000400000000000000000000000080000000000020000000000000000000005100200000000012000000000000000000000000020000000002000100000000400000001000000080000000040020000000000200000000800000000000000402000100000000000004004000000000000000000000000200402000000002000010000000000000000000000000000 +00000000000200000000014000000000000000000000000020000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000002000000000000004000800000000000200000000000000000000c00000100000000000000010000000000000000000202000000000000000000000000000010000040000000001000800000000000000000800000000002000000000000000000000100000000000000000000000000000000000008000000010000020000800000000000000000000200000000000000000000000000000000000000101000002000800002000004000000000000000000000000000 +00000000000000000000010000000000000000000000008000000000000000800000000000000000000000400000000400000002000020000000000000020000000000000000000000000000000020002004000000001080100400000101000000000200000000000000000000080000010000002000000002000000000000000080080002040000010200000000000021010000000000000004800000004000000000000000000000208000100000000001000000100000100000000000008000000000000004000810000000000000000000000000000000004004000000000000840000000000000402000000000000000000400000100000100000000000 +00100000000000000000010000000000000200000000000000000001000000000000000000004000000000000000000000000000000000004000000000000000000000000000020400000000000000000200000000000000000000000000000000000000000001001200000000080000000000408000000000000000000000081800000000400088010000000000000004000000008000000000000000000000000000000000000000200000100000000000400000000000000100000000000000000000200000000000000000000000000008000000040040004004200000000000000000000080000002000000000000000000000000000000000040000000 +02000000000000000000010000000000000000000000000020000000000000000000000040040000000000000000000020000010000000000000000000000000001000000000000000000000008000000004000800000000100000000800000000000404804000000000000000000000000000000000000000000000000000000000000002000000000001000020000001000800000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000001002000010000000802000000000000000000000000004000000 +00000000000000000000000200000000000000000000000000000000000000000000000000000202000000000000000400000000000000020000000000000000000000000000000000000000000000000000010000008000080000000000000000000000000000000002000000000200000000400000000001000002020000010000000013000000010000040000000000800000008010000001000000000000040000000010000000000000100000000000000000000000000200000000000000000000000000100000000000800000000000000000000080004000000000000000000000000000100602000000020000000000000000000000000000000000 +00000000000000000000010000001000000000000400000000000000000000000000000002000000000020000000000400000000000000000020000000000000000000000020000000000000000000000000000008000000000000000000020000000000000000000000000000082000000000000000000000003000800000000000000000000000010200000000000000000840008000000000000000000000000000000004000000000000100000000000000000000000000000000000000040000000000000000000000000000000000000000000000000004200100000000000000000000180000002000000000000000000000000000000000000000000 +00000000000200002000010000009000000008000000000000000000002000000800000040000000040020000000000400000000000000000000000000000000000080000000000000000080000000000004000000008000004000000000000000000100800000000000000000080000000000000000000000000000000000200000000002000000000200840000000001000000000000000000400400000000100400400000000100000000100000000000000000100000000000200400000000000000000000000000000000000000000000000000000400004240000000000000000000000080000002000000002000000800800080040000000000000000 +00000400000004000000010000000000000000000000000000000000000000020000000000000000000000400000000000000000000000000000000000040000000400080080000000020004000000200004000000009000000000000000000000000000040000000002000000000000000000408000000040000000000000001000000012020004010000000000000000040000008000000000000000000000010000000000000020000000100000000400000000000000100100000000000001000000000000200000000000000020000000000000000000004200200000800100000000000000000002000000000000000000000004000002000000000000 +02000000003000000000010010000000000000000000000000000040080002000000000200000000040000400000000020000000010020400000000200000000000000000000000000000040000000000404000800008000004008000000000000200000840000800002000000080000010000008000000000000000001000000000000002000080010000000000000001010000008000000000000000000000200000000000000000000000100000000000000040000000000200000000000001000000000000000000000000000000000000100800000000004000000000000000000000000080000002000000006004000000000000000000000000004000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000800000000010000000000000000000000000000000000000000100000000000000000008200000000000000000000000000000000000800000000000000000000000000000000004000000000000010000000000000000402000000000000000000000000000000000000000000 +00000000000000000000010000000000200200000000000000000000000000000000000000000004000000400000000000000000000000000100000000000000000800000000000000000000000000000004010000000000800000000000000000000100800000000000000000000000000000418000400000000000000008000000000000000000010000000000000000000000008000000000010000000000000000000000000000200000100000200000000002000010080100000000000020000000200000009400000000000000000000000000000020004000200000800200000000000002000002000000000000000000000000000000000000000400 +02800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000020000000040000000000000000002000000004000000600004400000000000000000000080000000000000840000000000000000000000800000408000000000000002000000021000000012008000010000000000000000040000008000000000000000000200000010000002000000002000100000000000000000000000000100000000000000000000002000000000000000000000000000000000000000004200000000000000000000000000000002000000002000000000000000000000000200000000 +00000000000000000000010400000480000000000008000000000000800000000000004000004000000040000040000820000000000000000000000000010000000000000000020000030000000000000004000800008008000400000800000000200000844200000202001000080201080000408000000000000000000000080800000032000010010000004000000201080020008000002001800000100000000000000200000000000040100200000443000000200000080000008100040000000800000000000000100000002000420008000000000040004005004000000000000000000800010002000000822000010000000010000200000020000000 +02010000000000000000000000002000000100000000008501080000000020000000000900000000040000000000000420000000008000000000000040010000000000000000002000004000000000000004000080000000000000000000000000000000800000000008000000080000000000409000000000000000000000080000000012020080010002000000000201000000008000000000000080000004000000000480004000002800100000000000000000000000000000000000000000000000002000000000000000002000010008000000000408004000000000000000000108000080000002000000002000000000180000002000000000000000 +0200000000000000000000000000000400100000000000000000000001000000000008080000200000000000000000040a000000001000020800000008040000040000000000002000000000040000000004010008000200000020000400000000280000800000000000000000080204000000400000400001000000000000081008000002000000000100000000000001000800000000002000000000000000000004000020000000000002100000000000000000000200000000000000000200002020000000000000008004808000000000000000000000004000000000000000000000000000100002000000022000000000000000000200000000000000 +00000000000000002004030000000080000000000000000000000000002000020000000040000000040000000100000000000000000000000000000000000000000000000000000000000000000000041000000000008000004000000000000000000020000000000000000000081000000000000000000000000000000000000000000012000000000000040000000000080000020000000000400000000004000000000000000000000000100000000000000000100000000000200000000000000000000000000000000000000000000000000000000400004000000100000000000000000000000002000000000000000000000000400000000002000000 +2200000000000000000000000000000000000000000000000000000000200000000000080000000004000000400000000000000000000002000000000000000000000000000000000000000000000000000001000000800000400000040000008220000080000080000200000008000000000040000000000000000002000000000000000200000000000000000000000000000000000000000000000000000000000000000000002000200010000000000000000000000000000000000000000100000000000000840000000000000000000000000000000000400080000000000100000000002080000a000000020000000000000000000000000000000000 +0000000080000000000000000000000000000010000000000002000000000402000000000000000400200000000000002000000000000000000000000000000080000000080000000000000000000080000c000080008000000000000000000008000800800000000002000000080000000000408000000080000000000000080080000012000000010000000000000000000000008000100020100000000000000000000100000200000000110200000000000000000000000100008100000001000000000000800000000000000100000200000000000000044000000000000008000000000000000002001100002000000000000004000200000028000000 +004000000002000000000100000000000000000000000000300000000008028000000000000000a0002000400000008000000000000004000000000400004008000000000000040000000000000000000006010008000000000800000000000000000800800000000000000000000a00000000000000000000000600000000000000000002000000010000000000000001800000400000000000420000010000000000000000000000000000100000000080000001000004100000020040000002002080000000000000000400000000000000000000000400004000000000000000008000000000000002000000002041400000000000000080000000000000 +00000000000000000000010000000000000008000400000000000000000000000000000040000000040080000000000000040000000000000080000000000000000000000000000000000000000000000004000008008000004000000000000000300000810000000002000000082000004000000000000000000000000000000000000002100000000000000400000000000020000400000000400000000000000000000000000004000000100400000000000000000000000000000200000001000000000000000000000000000800009000000000000400004000000000000000000000000000000002000000002000000000000010000000000000000200 +00000004000000000000010000000400000000000001000000000000000000090000000040000000000000000000000420000000000000000000000000000000000000100000000000000000001000000004010000000000000000000100100000000000800000000000000000000300000020001000000000000000000000000000000022000000010000000000020000010000008000000000000800000000008000000000000020000000100200000000000000000000000000000000000040000000000000000000000400000000000000000000000000024000020000000000000000000080000012000000502000000080000000220000002000000000 +02000000000000000000010000000000000000000000000000000000080000008000000000000008000000000000000420000000000000000100000000000000000000100000000000000040000000010000000000000000000000000000000000000000800000000000000000000000020000000000000000000000020000000000000000000000010800000000000009000000008000000000000000000000000000000080000000002400100000000001000000100000000000000000000000000000002000000000000000000000000000000000000000004000000000000000000000000000000402000000000000000000000000000000000000000000 +00000000000200000000014000010000001000000000000020000000000800020000000000004004000000000000000000000020400000020000000000000000000000000000000000102000020000000004010800008000000000010000000000000040800000100002000000080000000000408000000000000000000020000808000002000000000000000000000201000000000000000000002800000002008100000000000000000000100000000000000000000000000000000800000001000010000020100000000000000000000000000010000400004004000000000000008000004000000002000000022000000000000004040000000000000000 +02000000000000000000010000000000000000200000008000000000000000000000000840000020000000080002000400000000000000000100000000084000000000000000000000000000000000000000000004000000100000000000000000004000000000000008000000000001000000000000000000000000000000000000080042000000010000000000090001000000000000000000000000000000000100800000000000002000100100000000000000100000000000000000100000010000000000000000000000000000000000000000000000004000000000000000000000000020400402000000000000000000000000000000000000000000 +00200000000000000000010000000400000000000000000000000000000000004000000000000000000000000100000400000000080000000000000040020000000000000000000000000000000020000000000800008000100400000000000000002000000200000002000000080000010008000000000002000001002000000000000002000000010200000000000021010000008040000004800000000000000000000000000008208000100000000001008000300000000000000001000000000000000000000000000000000000000002000000000000004000000000000000040000000000000002000000000000010000000000000000000000000000 +00000000010200000000010000001000000000000000000000080200000000000000000200000000240020000002000420000000000000010000000000200000000000000000000000004000000000000004000004008000004000040002000000204000800000000002000000080000000002000000000000000000000000000000000002040000010300000000010001000000008000000000000000000000000000000000000100000000100100000000000000000000000000000480000001000000000000000010000000000000000000000000000008004004000000000000000000000080400102000000002000000000800010000000000000000000 +000000000000000000000080000000000000000000000001000000002000000200000000000004000000000000400000000000000000000000000080000000000000000000000201000000000002000000040000000080000004200000000000000000008004000000020000000800000000000000000000000000000000000a0080002006000040010040000000000001000000000000000001000000000000000000000000000000000000100200000000000000000000002000000000000001000000000000000020000000000000000008000000000000004000000000000000021100000040000002000000002000000000000004000200000000080000 +000000000000000000000100000094000000000000000000000020000000001000000000020000000000a0000000000400000000002000000000000080000000000080000000000000000000000000000000000020008010000000000000000400000800000200000000000000000000000000000000000000001001000000000000000002000000010200040200000000000000008000000000000400000000000000400000000000000000100000000000000000300000000000000000000010000000000000000000000000000000800000000000000400004200000080000000000000000080000402000002000000010000000484040000000000000000 +00000000000000000000000000080080000000001000000000000000000000000000000202020004000000000400000420080000000000020000000000000001000000000000000000000000000000000004000000004000001800000000020000000000008000004000000000000000000000408000000002000000000000000000000000000000010200000000000000000000008800000000000000000010000000000000000000220000100000000200000000000000000100010000000000000000200000000000000000000000000000000080000400044000000000000000000000000080000002000000000000002000008800000000000000000000 +00000000000000000000010000000000000000000000000000000000800000000000000000008004800000000000040020000000000000000000000000000000000000000000000080000000000000000006010000044000000000000040000000000000c00002000000000000000000000000408010000000000000000000080080000010000000000001200000000004044000000000020000100000000000004900000000000000004000100000000000000000000000080100840000000000000000001000008400000000200001000000000000000000044000030000040000011000000000000002000000000000000000000000100000000040000000 +0000000000000000000000000000000000000000000000800000000400000000000000000000000004000000000000000000000000000000000000000004002000000000000000000100000000000000000400000000800000400000008000000020000080000080000a000000000000000000408000000000000000000000000000000012022000000000000000000001040000000000004001000000000000000000000000000000000000300080000000000000000010000100000000000001000000000000000000000000000000000000000000000000004200000000000000000100000000000002000000002000000000000000000000000200000000 +02000002040000000000010042000000000000000000000000000000000000000000000a00000204000000000000000400400000400000000000000000400000000000000000000000108000000000000004000884004000000000000000000000004000000000000008000000800000000000009000000000000000000000000000000112000000002000040000010000000000000000000000000000000000000000000000000000000420100100000000000000008000000000000000000000000000000000050800000000004000000000000000200000084000002000000000002000000000200402000000000084000000040000000000000000000200 +02800400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000020000400041000000000000000000000000004002000000004010000000000000000000080000000000800800000000000000000000000000000408040000000000000020000000000000010048000010000000000000000040000008000000000020000000200000000000002000000002000100000000000200000000000000100000100000000000000002000000000000000000000000000000000000000004204000000000000000000000000000002000000002040000000000000000000000200000000 +00200000000000000000010000000400000200400000000020000000000002800002000000004000000000000000400400040000000000000000000040000000004000000000000000000000000000000004000000008004000000000000000000000000802200000002000000080000800000008000000000000000002000008000004002000000000200000000000241000000000000000000000000100000000800000000000000200001100200000002000000200000000000000000000001000000200000000002000000000080000000000200000020004004000000000000000000000000000002000000002000010000100000000000000000000000 +00000000040000100000011400008000000000000000000000000000000000010000000002000000040100000010000420000000000000000020081000000000000000001000000000000000000000200000010800008000104000000000000000200000400000000802000000080000000000000000000000000000000000000000000002000000010200040000000001000000008000000000000800000000000000000020000020204000100200000001008000000000000000000000000041000000200000000000000020000000000000000000100400004801000000000000000000000080000082000000000000000a00800010000000000100000000 +0000008200000000000001400000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000100000000000000000000000000000000000000401000000c000000000010400004000000000800000000802000000080000002000600000000000000000002004000008004002000000000000000000000020000000000000000000000200000000000200100000000020000000100000000000000000100000010000000000000000000000000000000000008000800000080000000000000000004000000000000001010200000000800002000000022000000000100004008000000000000202 +0000000006220000000001400000100000100000000000810000000000020002020000004000000000002000000000040100000000000000000000000000000000000000000000000000000002080000000400000000800000000000000800000000000084000000002a040000080000210000048000000000000000000000000010008002000000010000000000000001110800008000000000802000000000200000000000080000200000100000000000000000820000000000001400000001000000200000000000000000000000000000000000000400004000000000000000000100000000000002000000002000000000800006000000000020000000 +00010000000400000000010000000000000000000400000020000000000000000000000000000000000000000000000004000000080000000000000040000000000800000000000100000000000000000024010808000000008000000000000000000000800000000000000800080000000080408000400002000000000000000000000000000000000000000000000201800000000000400000120000000000000000000000000800000040180000200000000002000000000500000000000000000000000000000000000000000000000000000000000000000000000000800000000000000002000012000000802000000000000000000000000000000000 +00000000002200000000010000001000000000000000000000000000000004000000000002000000000020002000000409000004001000000000000000000000004000000000000000000000000000000004000000000000000000000008000000000000840000000000000008000014000000408000000000000000000002081000000000000000010240000000000001000000008000000000100000000000200000000120000040000000100000000000000000000000000100000000800010000000010000000000000004008000000000000010000000044000000000000000000200800080000002000100002100000004800000000000000200000000 +00000000000000000000000000000000000000000000000000000000000800000000000000000000000020000000000400000000000000000000000000000000000000000000000000000000018000000000040000000000000020000000000000000000800000000000200000080000000000000000000000000000000020000000000002000000000001000000000001000100000000000001000080000000000000000000000000000000108000000000000000000000000000000000010000000000004040000000000002000000000000080000000408004000000000000000008100000080000002000000000000000000000000000000000004000000 +04000000000000000000010002400000000000000400000000000040000000000000000000000000001000000000000000001000000000000020000241000000000000200000020000000000000000000004000008000000000000000000000000200000800200000000000000002204000000400000000400000000000008081000000080000000030001800004000001000000008000000000000000000000100400000020000000200000100000000000000000020000000000000000000000000000200000000000000000000000200008040000000004004100000000000000000000000000000002800000802000000080000000000000000000000000 +00000000000000000000000000000000000000000000000000000001004000000000000000000000000000000000000020008000000000000000000400041100000000000000000000000004002000200004410000010000000000000180000000000a00840000000000000000080000000000408040000000000000000000001080000210040000010000000000000000050000008000000000020000000000000000000000000000000000100000000000200000000000000100000100000000000000000000000000000000000000000000000000000000004204000000000000000002000000000002000000002042000000001000000000000200000000 +06000000040000000000010000002000000000400000000000000000002000000000000840000000000000000000400400000000000000000000000040000000004000400000000000000200000000000004000000008004000000000000000000000000800000000000000000080004000000408000000000000000000021081000000002000000004240000000000001000000040000000000400000000000000800000020000000200000100200000000000000100020000000000000000000000000000000000002000004000080000000000200000020004000000000000000000000000000000002000000002000000000100000040000000000000000 +10000000000000000000010000000000000000000000000100000000000000000000000000000000000000000000000000200000000020000000000000000000000000000000000000100000000200000014000008002000000000000001000000000000800000000000000000080200000020008000240800000000000000020000000002000000012000000000000200880000008000000000000000000000008000000000000000000000100200000000000000000040000000000000000000000000000002000000000000800000000000000200000000004000000000000000001000000000000002000000802000000080000000000000000000000010 +00400000000000000000010000000000000000000000000010000000000002000000000000000080000000000000008400000040000000000100000000800008000000000000000000000010000010000002010008000000000000000000000000000000000000000000000000000200000002000000000000000000000000000000000002000000010000000000000008000000008000000000000000110000000000000000000000000100100000000000000000100000000000000000004000000080000000000000000000000000000080000000000000004080000001000000000000000000000402000000004000000080080000000000000000000000 +00000000000000000000014000000080001000000008000000000000800000020000004000004000008000000000020020000000000000000000010000010000000000000000000000030000000000000004000000008000002400000801000000000000844000000202001000080000000000408040000000000000000000081800000012040010010000004000000001000020008000000000802000000000000000000000000000000000100200000040000000000000080100008100000001000800000000000000000000000000000000000000000040004004204000000000000000000800000002000000022002000000000004000240000220000000 +00000000080000000000010000000000000000000000000000000000000000800000000000000000000000000140000400000000000000000000000400020000000000000000020000000000000020000000000000000200100410000000000000000000000000000000040000080000010000402000000002440001000000000000000002000000010200000000000021010000008000000004800000000000000000000000000008308000100000000001000000100000000000000000008000000000000000800000000000000000000008000000000408004000000000000000040000000000000002000000000000000000000000000000000000000800 +00500000000000000000010000000000000000000000000010000000000002800000000000000000040000000000008400000000000000000000000000000000000000000000040000000000000000000000010008008000000000000100000040200800000000000002000000080000000000000000000000000000000000000080000002000000010800000000000081010000000000000000002000010000000000000000000000000000100200100001000000100000000000000000000001000080400000900008000000000000000000000000000000004000000002000000000000000080000402000000000000000000000010000000000000000000 +00000000000000000000000000000000000000000000000000000001000000100000000000000000000000000000000400000000000000000000000000000000000000000000020000000000000000000000000000008000000000000000000000000000000001000000000000000000010000000000000000000000000000000080000002400000010000400000000000010000000000000000000000000000000000000000000000000000108008008400000000300000008004000000008000000000000000000040020000000000000008000000000400004000000000000000004000000000000002000000000000000000001004000080000020000000 +02000000000000000000010000008000000008000000000000000000000000000000000000000000000000000000100020000000000000000000000000000000000000000000000000000000000000000004000000008000000000100000200000000000800000000000000000000000000000408000008400000000000000080000000000020000010020004000000200000000008000000000000000200000000000000020000000002000100000000400000000000100000500000000000000000000002000000000000000000000000008000400000000004000000000800000000000000000000002000000002000000000800000000000000000000000 +00000000000000000000014000000000000000000000008000080000000000000000000002000000040200000000000420000000000000000001000000080000000000000000040000000000000000000044000000008080000010000002000000000000800008000000000000080000000000000000000000000000000000000080800000000080010200000000000001000000008000000001000002000000000000000000000000000040100000000400000080100010000000200000000000000000000000000000000000000000000000000100000000004000000000000000000000000080000002000010042000000080000040008000000000000000 +0000000000000000000001000000100000000000000000000000000000000010000000000000000000002000000000042000000000000000000000000008000000000000000002000000000000000000040400000000000000000000000000000000000080000000041000400008000000800000000000000000000000000000008000000200004001080000000000000100000000000000000101040020000000000000000000000000000010a000000010000000000000000000000000000000000000000000000040000000000000000008000100000400024040000000000000000000000080020012000000002000000000800000000080000000000000 +0000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000008002800000000000000000000020000000000020000041000000000000000000000000401000020020000000000000000000000000080000000000000000000000000000040000020000000000000080018180000000000000c010000000000000001000000008000000000100000000000000000000020000000100000100000000000820020000000000000000000000000000000000000000000000000000000000000000010000000044000000000000000000000000000000002000000002002000000000001000000030000000000 +00000400000000000000000000000000100000000000000000000001000000000000000000000000000000000000000400008000000000000100000400041000008004000000000000000004002000000004010000000000000000000080000000000800800000000000000000800000000000408040000000000000000000000000000010040000010000000000000008040000008000000000020000000000000000000000000000000004100000000000200000100000000100000100000000000000000000000000000000000000000000000000000000004204000000000000000000000000000402000000002040000000000000000000000200000000 +0000000a00000000020001000000000000000a000000000000000000000000000000000000200004000000000000000020000000000000000000000000000000000000000000000000100000010000000004000000008000000800000002020002000000800000004000000000000020800000408000000000000000000000080000100002040000010040040000800200000000008800000000000000000884800000000002000000000000100000000000000000000040000000000000000000000010000000000000000000040000000000000000000400024004000000000008420000000000000012000000822400000000000800000000000000000004 +0000000000000004000001100000000000000000000000000000000000000001000000000000000000000000000000040000000000000000002000000002000000080000000000000000000000002000000001080000000010040000000000000000000000000000080000000008000001000040800040000200000000000000000000000200000000020000000000022101000000000000000480000000000000000000002000000020c000100000200001008002100000000500000000000040000000000000000000000020000000000000400000000400004800000000800000040000000002000002000000000000000000000000000000000020000000 +00000000000000000000012000000000000000000080000020000020000004000000000000000000000000400000000000000000000000000010000000000000000000080000000000020000000000000024000800000200000000000000000000000000800000000000000000000000000000408000000000400000000000081000000000000000010000000000000201000000008000000000100000000008000000000020000000000040100000000000000000000000100100000000c00000000000000000000000000000000000001000000010000000044000000000800000000000200000000012000180802000000006000000000040000020000000 +00000000000000000004010000001000000008080000000000000000000000840000000042000100000020000000000420000000000a00000000000000000000000000000000000000000000000000000404000000008000000000100000000000000004800000000000000000000000000000000000000000000000000000000000000002000040010200040000000001000000008000000000400000000000000000000000000000200000100600000000000100000000000000000008000000000000200000004000000000000000000000000000100400004000000000000000800000000080000002000800002000000000800000000000100000000200 +02000000000000000000010000001000000000000000000000000100000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000800000000400000000000000000000000000000000000000000000000000000000000100000002000000200000000000000000000800000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000100008000000000000000000000000000000000000000000100000000 +00000000000000000000000000000000000000000000000002002001000000000000000000000000040000004000008400000200000000000000000000000000000000000000020000000000000000000000000004008000004000000000000000004800000001000000000000000200000000000000000000000000000000000000000002400000000000040000010008080000010000000000000000000000000000000000000000000000100100000000000000100000000000000000000000000000000000000000020000000000000008001000000000004000000000000000000000002000000402000800000000000000000000000000000004000004 +00200000000000002004000000000000000000000000000000000000000000800000000002000000000000000000000400000000000000000000000000000000000000000000000000800000000000000200000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000001000010200040000000001000800018000000000000000000000000000000000000000000000100000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000004000000000000000000000000080000002000000000000000000000000000000100000000000 +80000000020000000000000000020000000000000000000000000000000200000000000000000000000000000040000000008000000000000000000000000100000000000000420000000000000000000000000404800000000000000000000000004000880000000000000000080200080000408000000000000000000000000002000002000000000000000000000000080000000000000000000000000000000001000000000000000000108100040000000000000000000100001000000000000400000020000000000000002000000008000000000000004000000000000000000002000000000002000000000000000000000000000000000200000000 +02000000000000000000010040004000000000000000000000000010080000000008000800000000040000100000000020000000000000000000000000000000000000000000040000000000000000000000000000008000000000000002000000400000880000000000000000004000000000000000000000000800000000000000000002000000010000000000080001000000008000000000000000000000000000000200000000002000100000000000000020100000000002000000000000000000000000000400000000000000000000000000000000004000000004000000000000000020000002000000000000000000000000000000000004000000 +00000000000004000000010000000000000000000000000000000040000000000000000000080000000000000000008400000000000000000000000000240000000000000000000000000004000000200004400000008000000000000080000100000000840000000002400000000000000000408000000000000000002002001000000012000004000000000000000000040000000000010000000000000000000000000000000000000000100000000040000000000000000100000000000000000000000000000800000000000000000008000000000000004204200800800000000000000000000402000000002000000000000000000000100200000000 +00000000000000000000010000000000000000000000000000000000000000000000000044004040000000000000020000000000000000000004000040000000000000000000044000000040000000000004010000000000000020010000000000000004800010000000000000000000000000408000000010000000000000000000000002400000000000000000000201000000000000000000000000000000000040000000000000000000100000000000000000000001000500000000400000100000000000001000008000000000000800000000000000044004000000800000000000000000000002000000002000000000000000000000000000000000 +00000000000000002000010042400000000000000000008000000000002000000000000040004000040000000000000000000000000000000000000400000008000000000000000200080000000000000000010000008000004000000200000002000800800000000008000000000200000000000000000001000400800000000000000002002000010100000000000801080000000000000000420000000200000000000000000000000000180000000000000000100004000000000040000000000000000000000000000000000000000000041000000000004004000000000000000100000000000002000000000040400000000000000000000000010000 +02000000000000000000010000000400001000000000000000000000000000000000000800000000000000000000000020000040000000000000000000000000000000000000000000000000000012000004000000000000000000000000000000000000800000000000000000000000000006100000000100010000000000000000000002000000010000000000400000000800008000000000000000000000000000100000000000000000100000000002000000004000000000800000000000000000000000000004000000000002000000000000000000004000000000000010000000000000000002000000002000000000000000000000000002000000 +00000000000000000000010006000000000000000000000000000000000002800020000000000004000200200000000420080000001200000100000800000000000000000000000000100000000000000004000008000008000200000800000000000000000000000000000000000000000000408000000000001000000000080000000012040000030040040000000308000000008000000008000000000000000000000000000000000000108000000000000000101040000000000000000000000000000000000000000500100000004008000000200000004004200000000100000000000000000402000000010000000040000000500000000000000004 +00000000000000000000010000001000000020000010000000000000000800000000000000004210000020000000000400000000000000000080000000000000000000000000000080000000008000000000110000000000000000004000000400000000000000000001000000000008000000400000000000000800000000081000000002000000000000040000004000100000000000000000000000000000000000000020000000000000100000000000000000000000000000000800000004000080000000001000000000000000000000000000000400004404000000000000008000000000000002100000000101000000000000000000000000000000 +00000000000000000000010000000000000000000000000000000041000000000000000000080000000000000000000400008000040000000110000000040000000000000000000000000004000000200004400000018000000000000080000100000000840000000002400000000000000000408000000000000000002002001000000012000000010000000000000000040000000000000000000000010000000000000000000000000000100000000000000000100000000100000000000000000000000000000000000000000000000000000000000000000200000000000000000000000002000402000000002000000000000000000000100200000000 +0020000000000000081001000000000000000a000000000000000000000000080000000040000000000000000000000000000000000000000000000000000000000000000000000000000000001000008004000000008000004000000000000000000004800000000000000040080201000000001000002000000001000000000000000002000000000000000000000000000900001000000000000000000000000000000000000000000000100000000000000000100200000000000040000000000000000000010000000000000000100200000000000000004000000000000000000000000000000002000000002000000080000004208000000000000000 +00400000000000000000010000000000000000000000000010000002000002800000000000400000000000000100008400000000000000000000000000020000000000000000000000000000000000000000010008000000100000000000000040000000000000040000000000000000000000002000000000000001000000000000000002000000010000000000000001000000008000000000000000010000000080000000000000008000108000000001000000100000000000000000008400000080000000800800000000000000000000000000000400004000000000000000000000000000000002000020000000000000000000000080000000200000 +00000000000000000000010000000000000000400000000000000000800000000000000040000000800000000002000020000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000004800200000000000000000200000000400000000000000000000010080490200002040000010000002000000000000000008000000000100800000000000000000060000000000000100000000000000000000000000400000000000000000000000000008400000000000000000000000010000000044004020000000000000080100020000002000002000000000080000000000000000000000000 +0000000000000000000001000004000000000d002000000000000001400000000000000040000000000040000000000420008040008000000000000000000000000000000200020001000000000001000004000000008000000000000100000000000000800001000000000000080010000000408000000002000000000000000000000002020000010200000000000000010000008000000000400000000000000000000000000000200000100000000000000000000000000100001000000000000000000020000400000000000000000008000000000400004800010000000000000000000080000002000000002000000000000000000000000200000000 +0000000000000000000001000000000000000000001000000000000000000000000000000000000000000000000000040000000000002000010000000000080000000000000000000000000000000000200000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000008000004000001000000000000000a000000008000000000000800000000000000000000000001000000100000000000000000100000000000000000008000000000000004000800000000002000000000000000000000104004000000000000000000000000000402000000000000000000000000000000000000000000 +00000400000004000000018000000000000100000000100000000000000000000000200000000000000000000000020020000000000000000000000000050000000000000000000000000004000000200004000000000000000000000000000000000000840000000100000000000000000000408000000000000000000000001000400012040004012000000000000200040000008000000000000000000000010000000000000000000000100000000200000000000000000100000100000000000000000000000000000000000000000008002000000000004204200800800000000000000000000002000000002002000000000000000000000200000000 +00000000002200100000010000000000000000000000000020000000000000000008000042000000040000000100000000000000000000000000000000000000000800000000000000002000000000000004000880008000004000000000000000200004800000100002000400080000080000408000000000000001000000000000000002000000010000000000000001000000008000000000100800000000000000000000000000200000100000000000008000000000000000010004000001000010000020000000000000040000400000000010000000004008000000000000000000000000000002000000002000000004000010000000000020000400 +00000000000000000004010000000000000002000000000000000000000000040000000000000000080000000000000000000000000000040000000000000000000000000000000000000080000000000000010000000000010000400800000000000000000000000020000000004000000000408000000000000000000000080000000002000020000000000000000000000000000020000000000000000000000000200000000000000000104000000000000000000000000100000000000000000000000000001000000000004000000000000000000400404000200000800000000000000000000002000000000000400000000000000000000040000000 +00000000000000000000010000008000000000000000000000000001000000000000000000000000000100000010000000000001000000000000000010000000000000000010060000000000000000000000000000000000000000000000000000000100c00001000000000000000000000000408000000000000000000000000000000010400000010000040000000014040000008000000000000000000000010000000000000020200000100000000000000000000000000100000000000000000000200000008000000000000000000008000000200000004000200080800100000000000000000082000000000000000200000000020000000000000000 +04000000000000000000010000001000000100000000000000000000000200000000000000000004008020000000000420008000000000000000000000000101000000000000000000000000000000000004000004810000000000020008000000004000040000000000000000080000001000408000000002000000000080001000000000040000030200000000000000000000008000000000000000000000000000000000000000200000100100000000000000000000000100000000000010000000100000000000000000008000000008000100000000004004200000000800000002000080000002000000000000000000000000200040000000000000 +02800000000000004000010000000400000008000000000000000000804000000040000800000000000000000020000000000000010000000040000000000000000100000000000000000200000200000004000000008000000000000002000080000000800000000002020010000100000000408000000000000000000000080000000002000000000000000000000000000001000000000000000000020000000000000120202080000000100000000000000000000000000100000000000000000000000000000000000000000000001000000000000080000000000020000000000000000040000002000000102000000000000000100000200000000000 +00000400040004000000010040000000000000000000100000000000000000000000000000004200000000000000020400000000000000000000000000040000000000000001000000000004000000200004000004000000000000000000000000004000840000000000800000000000000000408000000000000000000000001000000010800004000000002000010000040000000000000000000000000000010000000000000000000000100100000000000000100000000100000100008000000000000004000800004000000000000008002000000000004204200800800100000000000000000402000000002000000000040000000000040200000000 +000000000000000000000000000004000000000000000000000000000000000000000000000000000000000001000804000000000000200000000000000000000000000000000000004000000000000000000000000000000000201000080000000000008000000000000000000000000000004080000000000000010000000a080008000200000001000000000000000000000000c000000000000008000000000002000000000200000000100200000000080000000000000100000000008800000000000004000800000000000000000000000000000000014008100000000000000000000040000402000000000000000000000400000200000000000000 +000000020002000000000104000000000000000000000000000001000000000000400004000020c0000000400000000020000000000000020000000000000008000000000000000000000000000000000004010000004008000820000400000000000200808000000080000001090200100000500000400000000000000000800008000000040000010000000000000801000000408000000000000000000000000000000000010000000000100000000400000000000000100000000000000200000000000000000000000000800000400000000000000000004004000000000000000000000000100812000000022000010000000000000000000000000200 +00000000000000000000000000008000040020080000000000000080440000020000000200000000000000800000000400008000000000000000000000020000000000000000000000000000000000000100000000008000000000000800000000000000000000000002000000000000000000408000000000000000000000082080000002000000010000040000001000000000000000000000000000000000001000200000000000000000100000000410000000100000000000000000000401000000000000000000000000000000000000000000001000004200000080000000060000000000000002000000000000000010000204000100000000000000 +00000000000000000000010000008000000000002000000000000001000000000000000000000000000000000000000400000000000000000000000000000000000080000000020000000000000000000000000800000000000000000000000000004000000001000000000000080000000000000000000000000000000000000000000000000000000220040000000001000000000000000000000000000000100000000000000000020000100000000001000000000100000000000400000004000000000000000000000000008000000008200000000000004200000000000100000000000080000002000000000000000800000000000040000000000800 +04000010000000000000010000000000040000000000000000000040000000000000000000000020000000000000000400008000000000000000000200000000000000000000000000000000000000000000000000010000000000000000000000000000800000000000000000000200000000408000000000000000000000011000000000000000000000000000000000000000000000000000000000000000400000200000004000000000100002000000000000000000010100000000000000000000000000000000000000000000000080000000001000008000080000000000000000000080000000000000000000000080000000000040000000000000 +02400020000000000000000000100000000000000000000000000000000002000000001000000000000000400000008020008000000000000000000000004000000000000000000000000000000010000004000008800000000000000000000000000000800000000000000200000000000000408000000000000000000000000000000200000000010000002000000001000000008000000000000000000000000000000000000000002000100000200000000000000000100100001000020000000080002020000000000000000000020000000000000000004000000000000000000002002400000203000000002000002000000000000000000200000000 +04000000000000000000000002040000000000200000000000000008000000000000000000002000000000000000000000000000000000010000400000000000000000000000000000000000000000000000000008100000000000000000000000000000000000000000000000000004000000408000000000200000000000081000000000000000000000000000000000000000000000000000000000000000000000000020000000000000100000000000000000000800800000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000040000000000000410000001000000000000002000000000001 +0208000000000000040001000000400000000000000000000000000008000000000000000000000000000000000000000000000000000042000000000000000000000000000000000000200000000000000001000000800000000000084000000000000080000000000000004000000400000040800000000000000000000008100000000200000001000000100021100000000000800000000000000000000000000020002000000000000010808000004000000000000000430000000000000400000000000000001000080080004000000000000000000000400000000080000000000000000000000a00000002000c000000000008000001000000004000 +00400000040000000000001000000000040000000000000000800000000000010000000002000000000000000000000420008000000000000020000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000800000000000000000000408000000000000000000000000000000002000000010200000000040200000000008000000000100000000000000000000020000000204000100200000000000000000000010100001000000040000000200100000000000020000000004000000000100400004800000000000000000000000080000002000000000000000000800000000000000000000000 +00000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000400888000040000000110000000040000000000000001000000000004000000200004400008010000000000000081000000000000840010000000800000000000000000408040000000000000000000001000000010020000010000000000000000140000000000000000000000010000000000000000000000000000100000000000000000100000080100000140000000000000000000000000004000000000000000000000000000000200000000000000000000000002000402000000002000000000000000000000000200000000 +00000002000000000000000000008000000000000000008000000000800040000000000002000000000080000400000400008000000000002000100000000000000080000000000000000800000000000004000004014000001800000000020000004000c80000005000000000080000000000408000000000000000000000001000000000000000010200040000000000000000008800000000010000000000008000000000020000000000100100000000000000004000000100000000080000000000000400000000000000000000000000000000000000004600000080000000000000000080000002000000000800000000000800000040000000000200 +00000000000000000000010000000000000000000000000000000000000000000000000040000000000000000002000000000000000000000000000000000000000000000000000000800000008000000000000000000000000000000000000000020004440000000000000000000030000000408000000000000000000000001000000002000000000000000000900200000000000000000000000000000000000000000000000000000000108000000040800014000000000000000000004010000000000000000000100000000000000000080000000000040000000000000000000000000000000000000000800000000000000000000000000000000000 +0020000200000000000001004000100000000000000000000000000008000000000000004000000804000000000000002000004008000000000000000000000000000000000000000001000000000000000000000000c000004000000000000000000008000000000800000000400000000002000000000000000000000000000004000002000000010000000000000000000000008000000000000000000000000000000000000000020000100000000000000000100000000000000000200000000000000000000000000000000000000000000000000000004000000000000000000000000000000002000000000000000000000000000000000000000200 +00000400000000000000000000000000000000100000000000000001000000000000000000000000040004000000020420008000000000000100000000040000008014000000040000000004000000200004000000008000000000000000000000000000840000000000000000800000080000408000000000000000000000201000000010020000010000000000000008040000008000000000000000000000000000000000000000000004100000000000000040100000000100000000000000000000000000000000000000000000000000002000000002004200000000000000000000000000000402000000002000000000000000000000000200000000 +00000000000200000000011000001000000000000000000020000001000000100000000000004000000022000000000400000000000000000000000000000010000000000000020000002000000000000404000800000000000000000000000000000000800001100000004000000000000000000800000000000400000000000000200002400040000000000000000001000000000000000000000800000000000000000000000000000000100000000000000000000000000000000c00000000000000000000000000000000000000000008000000000400004004000000000000000000000080000002000000002000000000800000000000000000000000 +00400000000200000080010000000000000008008000000080000000000002000001000000000080000000400040008000000000080000000000000000000000000800000000000000020000000000000004050028008800000800000000200000000000810000000000000000080000000008408000400000000000000000000000000002000000010000000000000001000000000000000001001000000000000000002000000000000000108400200080000002000000100100080000000000000090000000000000000002000020000000280000000402004000000000000000000100000000000002000000002000000010000000000000100000000000 +00000000000000000000010000001000000002000000008020000080000000800000000040004020000000000000000000000000000000000080000400000000200000000000000000000000800000000004010004000000000000000000000400024800880000000008000000000000000000000000400000000240000000000004000002002000010000000000000001800100008000040000020000000001040000000000000020000000108100000000000000000004000000000040000000000000000000200000000000000000000000000000000401004004000000008000000100000008000002000000002040400000000000000080000000000000 +00000000002000000000014000000000001000200000000000000000000000820000000002004000008000002000000420000000000000000000000000000000000000000000000000000000000000400000000000008000000000000000000000001000040000000002000000080000000000008000000000000000000000000800000002040000010200000000000001000000008000000020002000000000200000000000000000000000100000000001000000000000000000000000000001000000000000000008000000000000000008000000000000004004200008000000000000000080000002000000000100000000000004000000100000000000 +00000000000000000000010000000000000000000020000020000000000000810000000000000000000008000000000420000000000000000000000240000000000000000000000000000000000000400004010000000000000000000000000000000000802000000000800000080000000000000000000000000000000000000000000002040000010000000000000001000000018000000000000000000000000000000000000000000000100040000000000000000000000000000000000040000000200000000000000000000000000000000000000400404004000000000000000000000000000002000000002000000000000000000000000000000000 +00000004000000000000010000000400000000000000000000000000000000000000000040000000000000000000000020010200000000000000000000000000000000000000000000800000000000200004000000004000000000000000000080000004800000001000000000000000000000000000000000000000000000000000000002000000000040000000800000000000000000000000000000000000800000000000000000101000000000000000000011000000000000000000000000000010000000000000000000200000000000000000000000020000000000000000000000000000000000000000802000000000000004000000000000000000 +00000000000000000000011000000000000000000000000000000000000000000000000040000000000000000000000420000002000000000000000000000000000000000000020000000000000000000000000000000000000000010000004000000000000000000000000000080000002000000000000002000000000008000000000002000000000200000000000021000000000200000000000000000000000000000000000000200000100000002000000000000002000000000000000000000000000000000000008000000000000008000000000404004000000000008000000000000080000002000000000000020000000000000000000000000400 +00000000000004000000010000000000000000000000000000000000000000000000000000000200000000000000000020000000000000000000000000000000000000000000000000000004000000200000400000000000000000000000000000000000040000000000000000000000000000408000000000000000000000001000000010040004010000040000000000040000008000400000000000000000000000100000000000000000100000000040000000000000000101000010000000000000000000000000000000000000000008000000000000004204200800800000000000000000000002000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000400008000000000000100000000040020008004000000000001000004000000200004400000018000000000000080000000000000840000000002000000800000000000408000000000000000000000201000000012020000010000000000000009040000008000000001000000000000000000000000000000000004100000000000000000100000000100000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000402000000002000000000000000000000000200000000 +00001000000000400004001000000000000000000400000000000000000000000000000000000040000000400000000420000000000002000000000040000000008000000000020000000000000000000004000008004000040020000000000000000000902000000000800001080000040000108000000000000000000000000000000202000000010000040000000041000000008100000000000000000040000000000010000000000000100000000000000001000000000000000000000000000000000000000000000000400000000008000000000401004000400000000000000002000010000802000008002080000080100030000005100000000000 +00000400000004000000010000000000000000000000000000000000400000020000000020000000000000000000000000000000000000000000000000040200000400000000000000000004000400000004000000008008000000000080000000000000800000000002000000080000000000408040000000000000000000000080000012000000010000000000000000040000008000000000000000000000000000000000000020000000100200000400000000000000008100000100000001000000000000200000000000000020400000000000000000004200200000800100000000000000000002040000002000010000000004000200000200000000 +00000000000000000000010002400000000000000000000020000000000000000000000000000000040000000000000020000000000000000000000040000000000000000000000000000000000000000004000800008000000000000000000000208000800000100002000000080000000000000400000040000000000000008000200002040000010000800000000001000000008000000400000800000000000000000000000000000000100300000000001000000000000000000800000041000008000000000000000000000000000000000000000000004004000000000000000000000000000002000000002000000000000000000000000000000000 +00400001000000000000100000000000000000002000000000800001008000000000000000000000000000000100000000008000000000000000000000000000000000000000420000000000000000000000010000000000000000000000000000000000000001000008000000080000000000408000000000000000000000000008000002000000010000000000040200000000008000000000100000000000001000000000000000000000100000000000000000010000000300001000000000000000000000000000000000000000000008010000000000004000000080000000040000000000000002100000020001000000000000000000000000000000 +0000000000000400000000000000040008000080040200000000600000000000000000001000000400000000400001000000000000000000000000000004000000200000000000000000020000000000000401080c000000000000000000000000004000800000000000000040000000000000000000000004000008000000000000000000000000010000000001010001000000008100000000000000000000000000000000000001200000100100000000080000200000000000000000010000000000200000001000000000000000000000028000400000004000000000000000010100000000000202000000002000030000000000000100000000000000 +00000000000200000000010400001400000000008000000000040000000000000000001000000000000000000400000000010000000000000000000000000000000000000000000000000008000000000004000014000048000020200000000000004000800000000000000000000002000000000000200000000000000000000000000002000000000000000000000001200100000000040000000000000000000000010000000000000000100100000400000000000000000000000000000000008000000000000020000000000000400004000000000000004000000000000000000000000040000002000020002000010000800000000000000000000000 +00000000000000000000010040000000000000000000000000000000400000000800000000000200000000000000000600000000000000000000000400020008000000000000000200000000000020000000010004000000000400000100000000005a0000000400000000000008020001000000000000000200000000000000008000000200000001220000000001000009000000000000000402000000000000000000000000000020000010010000000000000010800400000000004000000000000000000000000000000000000000000000000000004000400000000000000004000000000000000a000000000040400000000080000000000000000000 +00000000000000000000010008080000000000000000000000000000002000800000000040004080002000400040000020000000000200000000000000000000000000000000020000000000000000000004000800008000000800000002000000000000000000000200000000080000000000000000400000000000001000000800204002040000010000008010000001000a0000a000000000400800000000000000000000000000000000100000000000000000100000100002000800000004000000000000008000000000000000000008000000000000004004000000000000000000000000001002000000000000000000000004004000000000000024 +00000000040000000000010000000000000040002000008000000001000000000000000040000000000200000000000400000000000000000000000000080000000000000000020000000100000000000000000000000080100000000000000000000000000000000000000000080005000000409000000000000000000080081080000002000000810000000001000001000800000000000000000004000100000080040020000000004080100000080000000000b00000000000080000000000000000004020000000000000002000800008000100001000004000000000000000000000010080000002000000000000500000000000000000000000001000 +02000000000000000000010000001000000000200000000400000000000000000200000800000000000020000000000401000000000000020000000000000000000000000000000000000000000000008004010080000000000000000408000040000000800000000000002000080040000000408000400000000000000000000008000002000000000000000000000000100000000000000000000080000080000000000000000000000000100200000000000000000000000000000000000200000000000000000000000000800000000000200200000000004000000080000000000000000000100002000000022002000000800000000000000000200000 +02000000000000000000010000000000000000000000000000000000000000000000000800000000000000000000000000200000000000000000000000000000000000000000000002100000000000000000000008000000000000000000000000000000000000000000000000000200000020008008200000000000000000000000000002000000010000000000000000880000008000000000000000000002008000004000000000000000100000000000000000000000000000000008000000000000000002000000000000800000000000000000000000004000000000000000000000000000000002000000000004000000000000010000000000000010 +10000001000000000000010000000000000000002000000000000001000000000020000040000000000004400000000000200000000000000000000000000000000000000000020000500100000002000004000008000000000000000001000000000040900001020001000000080000000020408000200000000000000000080000000002000000412200000000002200800000008000000000000000020000009000000020000000000000100000000000000000000040100000000000000000000000000002000000000000800000000008000000000000004000000000000000000000000000000002000000c00000000000000000000000000000000010 +00000000000000000000000000000000001000000000000000000000000000800040000000000040000000000010000000000000000000000000000000000000000000000000000000000000000000000004010000004000000820000000020000000000800000004000000001000000000000100000000000000000000000000008000001000000000000000000000001000800000800000100001000000000000000000000000000000000100000000000000000000000000000000000400000000000000000001000000000008000000000000000000000004000000000000400000400000000000802000000002000000000000800000000000100000000 +00000000002200000000010000000000020000000000008100000000800000000000000000000004000000000000000000000000000000000000000000000000000000000000000200000000000000000004010000000080000000000000000000000000840000000001000000080000200000008000000000000000000020000080008002000000010000400001000001000000008010000000000000000000300000000100000000000000100000000000000000000000000000000000000000000000000000001000000000000000000000000000000400004001000000000000018300000000000002000000002000000000000000000000000000000000 +08400000000000400000000000000000000000000000000000000008000002000000000000000000000000000000008401000000020000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000080000000000008000000000001000000000200000000003000000012000000000000000000000000000000000000000010000000000000000004000000000100000000000000000000000000000000000010000000080000400000000000000000000000000000000000408004004000000000000010000004080000022000000000000000000000000000000000000000000 +02010000000000000000000000002000000000000000008501080000000020000000000900000000040000000000000020000000008000000000000040000000000000000000002000004000000000000004000080000000000000000000000000000000800000000008000000080000000000400000000000000000000000080000000012020080014000000000000001000000008000000000000080000004000000000480000000002000100200000000000000000000000000000000000000000000002000000000000000000000030008000000000000004000000000000000000100000080000002000000002000000000080000002200000000000000 +02000000000000000000010440004000001000000000000000000000080000000000000000012000040000000000000000000000000001000000000000000000000000000000000000002000000000200004040000008008004000000000000000000000800000000000000000000000010000408000000000100000000000000000000000000000000000000000000000010800000000000000000000000000000000000000200000000000100200000400000020100000000100000000400010020000000000000000000800000000400000000200008000044000000020800000008000000000000002000000002004010000000000000000000000004000 +00000000000000000000010008000000000000000000000000080000200000800000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000408000000000000000000000000000000000000000000200000000000000000000000000000000000400000000001000000000000000040080010001000000000001000000008000000000000002000000000000000000000000200000100000080000000000000000000000000000000000002000200000000000000000000000000000000000000000004004000000000080000000000080010002000000000000000000000000000000000000000400 +0010008200000000000000000000100000000000000000000000000000000000000000000000000004000000000000000004000000000000000000000000000000000000000004000000000000000000000400000000c000000000000000000000200000800800000802000000480000000000000000000000000000000000000080000002000000010000000000000000000000000000000000000080000000000000100000000000000000100300000000000000000000000000000002000001000000000000000000000100000000080000000000020800004000000000000000000200000000000002000000002000000000000010000200000000000200 +00000000000000000000010000000000000000000000000000000000000200000000000000100004000000000000000420000000000000000000000000000801000000000000000000000000000000000004000000000000000000000000000000000000040000000000000000000200000000008000000000000000000000000001200002040080010200000002000200080000008008000000000800000000200000700000000000000000100000000040000000100000000000000000008000000000000020000000000001000000000000001102000000004004000000004000000000000080000002000002000000000000000000000000000000000000 +00000400000000000000000000000000000000000000008100000004400000000000000000000000000000000000020000000000000000000000000000040020000010000000000000000004000000200004000000008088400000000080000000000000840000000002000000080000000000408000000000000000000000001080000012020000010000000000008001040000000000000001000000000000000000000000000000000000300080000000000000000000008100000000000000000000000000000000000000000000400000002000000000004200000000000000000100000000000002000000002000010000000000000000000200000000 +000000000000000000040100000080000000000000000010200000040000008000000000000000000000080000002204200000000000004000000000000000000000000000000000000000000000004000040000000000000000000008000000000000008000000000000200000800000000004080000000000000000000000c1000000002040000010200040000000001000000008000000080410000000002100000000020000000000000108000000000000000004000000100000000000000000000200000000000000000000000000000000000000400004204000000000000000000000080000002000000002000009000000000000000010200000000 +00000000000000000000000000001000000000000000000000000001000200000000000000000000000000002000100000048000000000000000000000000000000000000000020000000000000000000000000004800000000020800000000000004000800001000000000000000000000000408000000000000000000000000000000002402000000000000000000000000000000000000000000000000000000010000000000000000000100100200000000000000000000100001000000000000000000020000100000000000002000008000000000000004000400000000000000002000000200002000000000000000000000000000000000200000000 +0000000000000000000001000000100000100000040008000004000000000002000020000200000000002000000000040000000000000000002000000000000000000800002000000000000000000000000400000c00c000000000000000020400004000880000000002020000082000000000000200000000001000a00000000000000002008000010200000000000000000800008000000000000000000000000000000004000020000000100100000000000000000000000000200000000041000080001000000400000000000000000000000000000000004400000000000000000010000080000002000000002000000000000044000000000020010200 +00c00000000000000000000000008000000000000000000000000000000000000000000000000000000000400000000404000000000000000000000000000000000000000104000000080000000000000000000008104000000020000000000000000000800000000000010001000000000000000000101000000000000000000000000000000000010000040000000000000000008000000000000000000000000008000000000000200000100000000000000000100000000000000000000000000080200000000400000000000000000000000000000000004200000080080000000100000000000402000000000030020000000000000000000000000000 +00400000000000400000000000000000000000000000000000020000000002000000000000000000000000000000008420000000000000000000000000000000000000000000000000010000000000000000010008004000000000000000000010000000000000000800000000400004000000000000100000000000000000000000800000000000010000000000000000104000008000000000000000000000000000000000004000028000100100000000000000000000000000000000000000000080000400001000000000000000000000000000000000004000000000000000000000000000000002000000000000000000000000000000000000000200 +00000000000200000000010000000000000000002000000000000001000040000000000080000004000000000040000000008000000000000000000000000100000008000000020000000100000000000004000000808000000000000000000000000040800000000000000000080000000000408000000000400000000100080080000200000000010000000000000000000000008000000000000000000000000000000020000020000000100000000000000000000000000100801000008008000000000020200000000000000000000008000000000000044000208000000010000002000000000002000000002000000000000200004000000200000000 +00400000000000000000010008000000000000000000000010000000002002800000000040000000002000000000008000000000000200000000000000000000000000000000000000000000000000000000010008008000000000010000000000000000000000000202000000080000000000000000000000000000001000000800004002000000010000000000000001000000000000000000600004010000000000000000000000000000100000000080000000100000020000000000000005002080000000800000008000000000000000000000000000004004000000000000000000000000001002000000000000000000000004000000000000000000 +00000000000000000000000200000000000000000400000000000000000000000000000000002002080000000000000422000104000020000000800000000000020000000000000000000000000000000000000008004000000020000100000000000000008000000000000001000000000000000000000000000000000000000000080002000000010000000000000001010000008000000000000001000000000000000000000000020000100000000000000000800000000000000000008000000000800004000800000800000000000000000000000400004000000008000000000000000080000c02000000000000000000000000000000000000000200 +00000000000800000028000400000000000000000000000000000002000000020000000000000000000000000000000400000000000400000000000040000000008000100020000000000000000000080004000000008000000010000000000000000000800000000002000000000000000000008000080000000000000000000000000002000000012000000000000001000000008000000001000000000000000000000000000000000000100200000400000000900000000000000000008041000000000000000000000000000000000000000300000000004000000100000800000100000000000402000000002000000000000004000000000000400000 +00000020000000000000012000000000000000000000000020100000000100800000000000004000000000400000800000000000000000020000000000004000000000000000000000000000000000000004010000000200000000000400000000000000800000000000000000080000040000400000080000400000000000280008000002000000000000000000000001000000000000000000000000000008000000000020000820000000108020000000000000000000100000000004000000000000200000001000000400800000800000000000800400004004000008000001008000000000800002000000022000000000020080000000000000000000 +00000000000000000000000000008000001000000000040000000080000000100000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000002000000010000040000000000004000008000010000000000000000040008000000000000200000100000000000000000000000000000000000008400000000200004000800000000000000000000000000000400006200000080000000000000000000000402000000000000000000000000000500000000400010 +00000000000200000000010000000000000000400000000020000000000000000000000000000004000000000000000420000000000010000000000000000000000000000000000000042000004000000024000801000000000000400100000000000000800000000000000000000000000002648000000000001000004000081200000082000000410000000000200201010020008000000000000000000000000000200120000000000000100000000000000000000000000000000000000000000000020000000000000000000000000000000000000000004000000000000000000000000000000002080000002000000000100008000000000000000000 +00100000000000000000000000008000000002080002000000000020000000000000000000000000002100000000000000000000800000000000000200000000000000000000000000000000000000000004000000008000000000000000000000000000c00000000000000000000000000000400000000000000000000000080000000002800000010000044000000000000000008000000000000000000000001040000020000000200000100000000080000000000000000000000000000000000000200000800000000000000000000000000000000000004200000080040000000000000000000082000000002000000200000000008000000400000000 +02010000000000000000010000002000000008000000000020000000000020800000000900000000000000000000020020000000008000000000000000000000000000000000002000000000000000400004000080008000000000020002000000000000800000000000000000000000000200400000000000000000000000080000000012060000010000000000000001000000008000000000000080400004000000000480000000002000100000000000000000000000000000000040000000000000202000000000000000000000000008000000000000004044000000000000000000000000000002000000002400000000000000002000000000000004 +00000000000000000004010000001000000000000000000002000000000000040000000000000000040020000000000420000000000000000080000000000800000000000080040000000000000000000000000000008000000000000400000400000000000000000000000000080000000000000000000000000000000000000080000002040000010000044000000000000000008000000000000010000000000000400000000000000004100000000000000000000000000000000000000000000000001000000000020000000000000000000000000400004004040000000000000000000080000002000200000000000000000400000000100000000000 +00000000000000000000010000011000001000000000000000000000000000100000000000000000000000000000000000000000000040000000000000000000000000000000000000000000008000000020000000000000000000000000000400000000800000000000000040000000000000000000000000000000000000000000000002000000010001000000000000000900008000000000000000000000000000000000000000200000100000000000000000000000000000000000000000000000200000000000000000000000000000000000000400004000000000004000000000800000000002000000000000000000004000000000000000400400 +00000000000000000000014000000000000000000000000000000040000000000000000000400000000000000100000400000000000000000000000000020000000000000000000000000000000000200000000800000000100200000200000000000000400000040000000000000210010000000000000001200000000000000000000002000000000100040000000001090000000000000000000800000000000080000000000000008000180000000001008000100000000000000000008000000000000000000800000000000000000000201000000000004000000800000000000000000001000002000800000000004000000000000000000000200000 +00400400000004080000010000000000000000000000000000000000000000000000000000000000000000400000000400000000000000000000000000040000000000080084000000020004000000204004000008001000000000000000000000000000040000000000000000000000000000408000000040000000000000001000000012020004000000000000000000040000000000000000400000000000010000000000000000000000100000000000000000100000100100000000000000000080000400000000000000010000000000000000000000000200200000800000000000000000000402000000000000020000000000000002000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000008400008000000000000100000000040200008004000000000000000000000000000004000000000000000000000080000000000000800000000000000000800000000000408040000000000000000000000000000010000000010000000000000008048000008000014000000000000000000000000000000000000004100200000000000000100000000100008100000000000000000000000800000000000000000000000000000000004200000000000000000000000000000402000000002000000000000000000000000200000000 +00000400000000000000000000000000000000000000000000000001004000000000000000000000000000000000008420008000000000000000000000040300000000000000000000000004000000000004000000000000000000000180000000000200800000000000000000080000000000408040000000000000000000000080000210000000010000000000000000050000008000010000000000000000000000000000000000000000100200001000000000000000000100008100000000000000000000000800000000000000000000000000000000004200000000000000000002000000000402000000002000000000001000000000000200000000 +00000400000000000000010000000000000000000000000000000041000000000000000000080000000000000000008400008000000000000000000000040000000000000000000000000004000000000004000000008000000000000080000100000000800000000002400000000000000000408000000000000000002002000000000012000000000000000000000000040000000000010000000000000000000000000000000000000000100000201000000000000000000100000000000000000000000008000800000000000000000000000000000000004200000000000000000002000000000402000000002000000000000000000000100200000000 +00000000000000000000010000080000000400000000000000000000000000000000000000040000000000000000000420000202000000000000000000000000000000000000000000000000000000000000000000008100000200000002000000000000400000000600000000000000000000000000000000000000000000000000000000040000010000040000000001000800008000000000000100004000000000000000000000000000100000000000000000100200000000000000000000000000000000000000000000000020000000000000001000004004000000000000000000000080000002000000000000000000400000000000800000000004 +000100000000000100000100000010000000000000000000200000000000000000020400000000800000004000000000200000000000000000000000400000000000000000000080000000000000000000040048000000000000000000000a0400001000808000000800000000080200000000000000000201000000000020000080008002040000010100000000000001080040008000000000000000000000000000000000000000000000100200000000000000000000100000000000000000000000008000000000800000000000020000000200000400004004040000000000008000000000000002000000002000000004000000000000000000000000 +00400000000000000000010000000080000000000008000000000000800000000000004000000000000000000000020020000000000000000000010000010000000000000004000000030000000000000004000008008000002400010800000000000000844004000202001000080000000000408040000000000000000000081800000012040010010000004000000001000020008000000000800000000000000000000000000020000000900200000040000000000000080100008100000000000880000000000000008000000000000000000000000040004004204000000080000000000800000002000000022802000000000000000240000a20000000 +00002000000000000000000000000000000000000000000000000008000200000000000000000004010000000000000400100000000000000000000000000000000000000000000000000000000000000004000000000000000000010000000040000000000000000008000000000000810000409000000000000090000000000000000000000000002000040000000000010000000000000000000000000000000000000000000000000000100000000020000000000000000000000000000010000000820000000800000000004000000000000000000000044000000000004000000002000000000403100000000000000000000000000000000000000000 +020000000000000000000110000000000000000000000000000000000a0000080000000040004000000000000000000400000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000800000000000000000080200000000409000000040000000000000001000000002000000020000000804000100000000000000000000000000000000008000010000000000000000108000000000400000000000000100000000000000000000000400000000000000000000000000000000000e00040000000000000000000000000090100002000000002004000010000000200040000000004000 +00000000000000000000004000000008000000080000000010000000000001020000000000000800040000000000000400000000000000030000000000000800000000000000000000000000020000000000010000008000004000000400000000200000800000000002000000080100000000c00000000000001080000000080804000002000000000000000000000000000800000000800000000000000000004000000000000020000000100000000000000000000000000000000000000001000010004000000400000000000000000000000000000040004000000000000001000000000000801002000000020800000000000014000000000000000000 +000000000000000000000104000000000000000000080000000002000002000000000000004004040c8000000000000400000000000000000000a00000020001000000000080040000000000000000000004000000008008000000000001000000200000040000000002000000080000010000008000000000000000000000000080000002040000010200000000000000010000000000000000000000000000000000000000000000000000100000000400000000100000000000000000008001000000000000000800000000000000400000040100000004004004200000000000000000000080000002000000000000010000000010400000000000200000 +02c00000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000020000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000408000000000000000000000000000000002000000010000000000000200000000008000000000100000000200000000000002000000003000100000000000000000000000000100000000000000000000002000000000000800000000000000000000000000004000000000000000000000000000000002000000000000000000000000000000000000000000 +00000000000000000000000400008000000000080000000000000000000000000000000000000000080000000004008400000000000000000000804000000000000000000001000000000000002000000100200000000008000800000000000000000040000000000000000000000000010000000000000000000000000000000000000012000000000000040000000000010000000000010400000000000000020000000000000000000000100000000404000000400000010000000000000000000000000000000802000000000000400000000400000000004200000000000000000000000080000402000000000000010000002000000000000000000000 +00000000004000000004000000200400000002000000000000000002008000000000000000000000040000040000000400018000000000000000000400000000000000000004000000008000002000000004010084008000004000000000000000004800800000000000000004000000000000000000000000000000000000080000080002040000010000040000010000000800000000000000020000000080000000000000000800000000100100000000000040200200010000000000000000000800000000000000000000010100000000000100000002004004000000000008040000000000000002000000002050000000000000000000100000000400 +02000000000000000000010000000000000004000001000000000000000000000000000000000004000000000000000020000000000000000001000000000000000010000080000000000000000000000004000000000000000000000000000008000400840004000000000000000000800000008000000000000000000400000000800000000000012000000000200000000800008000000000000002000000000000000000000020000000100000000000080080800000000000000000000000000000000000200000000000000000008010200000000000004000200000000000000000001002000002000000002004000000000000008000000000000000 +00002000000000000000000000000000000000000000000000800000000000000000000000000000000000000100001000000000000000000080000000000000000000000800000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000408000000000020001000000000000000002000000010000000000000200000000008000000000100000000000000000000000000000000000100000000000000000010000000100000000000000000000000000040000000000000000000000000000000000044000000000000108000000000000400002000000000001000000000000000000000000000000 +00000000000000100000010000008000000000000100000000000000000000000000000000000000040100000010000400000000000000020000001000000000000010000000000000000000000000200000010800008000004000000400000000200800400000000002000000080000010000400000000000000000000000000008000002000000000800040000000081010000000000000000002800000000000000000000000020200000100200100001000000100000000000000000000001000000400000100008000000800000000000000000000000004001000000000001000000000080800482000000020000000a00000010000000000100000000 +000000000002000000040100000004000000000000000081000000000000000000100000000000800400004000404000000000000000000000000000000000000000000800000000000200000000000000040000000080800048000000002000002000008102008000020000000a0000200000408000000000000040000000001080000002000008010000000000000201000000000000000000000000100000000000000000000000000000500000000042000000200000100500000000040001000010000000000000000000000000000000000000000000004000000000800000000100000000000002000000002000010000000000040000000002000000 +00000800000200000000010000001000000000000000000000000000000800000000000000004000000000000000000200040000000000000000000000000000000000000000000000000000008000000004004000040000000000000000000400000000800000000000000000000000000000000000000200000000000000000200000002000000010000000000000001000000008000000001000000000000000000000000000000000000100400000000000000800000000000000000000000000000000000000000000000000000000000000180000c00004004000000000000008100000000000002000000002001000010800000000000000000000000 +0000000000020000040001000000000000000000000000000000000000000002000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000401000000800000001000004000000000000080000000000200000000000000000040000000000000000000100008000000000200000001000000000000002100000000800000000100000000000000000000000000000000000010808000040000000000000000020000000000000100000000000000001000000080000000000000010000000000400000000000000000010000000000000a000000022008080010000004000000000000400004 +00000000000000004000010000000000000000400000000000000000800004000000000040000200800000000000002000020000000000000000000000000000000000000000020000000000000000000000200000004000000200000002000000000004800200000000000000080200000000400000000000000000000000080400000002000000000000000000000000000000000000000000100000040000000000000a60020000100000100000000000000000000000000000000000000000000000000000000400004000000000000000000000000000044000020000000000000000000020000002000000002000000080000000100000000000000000 +02000000000004000000011200000000000000001000000001000000020020000000200800000000040000000100000400000000010000000002000000400000000000000000040000000000000000000000010000008000004020000040000000200000800000000002040400080000000008408000000000000000000000081088000003000000030000000804040000000000020000000000000000020080008200010000000000000000108000000000400000000000020100008000000001000000000400000000000000000080008000000000000c00044000000000000000000000000090000002000000022004000010000010000000000000000000 +00000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000100000000000000000000000000000000000010000000000000000000000800000000000000000000000000000009000000000000000000000000000000022000000010000000000000000000000008000000000000000000000008000080000000000000000100004000000000000100000000000000000000000000000000000008400000080800000000000000000000400004000400000000000000080000000000002000000000000000000000000000000000000000800 +04400000000000000000010000000000000000000000100000000000000000000000000040000004000000000040000000004000000000000000000000000000000000000000020000000000000000000004010000000000000000000000000000000000000000000000100000080200000200001000000001000000000000200000000002000000000100000000000000000000000000000000000000000000000000000000000000200000100000000000000000000000000000000000000000000000000000001000000000000000000088000000000020004000000000020000010008000000000002000000000000010000000000000000000000000080 +200000000000000400001100000020000000080010000000000000208000000000000000000000040000000000000000000000000000002080000000000000000002002000001000000000000400000000040100000080080000200000000400000000008000000000404600000800000000004080000010000000000100400a0008000022000400000000004000010000000002280000000400000000020000008000800428000000000400100000000400000000010200008000002100000000000000000000000000000000000000400040000000000000004000000000000000000000000104400002000000002802010040000000020000000000000001 +00000000000000000000010000000000000000000000000000000000000000820000000000000000000000000000000401100000000000000010000000020000000400000000000000000000000020000000010000008000100400000000000000000a00000000000002000000080000010000002000000002000000004000000000000002000000010200000000000021010000008000000004800000000000000000000000000020208000100000000401000000100000000200000000040001000000000000200000000000000020000000000000000000004000020000000000040000000000000002000000000000000000800004000000000000000000 +00000000000200000004010000000000000000000000008100000001400200000000200000000000000000000000000000008000000000000000000000000000000000000000020000000000000000000004000000800088000000000000000000000000800001000000000000080000200000408000000000000000000000000080000000400000010000000000008001000000000000000000000000000000100000000100000000000000100000200000000000000000008100001000000000000000000000000000000000000000400008000000000000004000000000800000000102000000000002000000002001010000000000000000000000000000 +8040000000000000020001000000002000000a00040002000000000000000200000000024000000400000000000000a42000008000000000000000000000000100000000000000000000000000000000000600002800c000000000000102800000000000800000000010000000080000000000808000000000000000000000080080000002000000010000400040000000010010048000000000400000003000000000000002000000020000500000000000080000000000000000000001000000000080000000000400000000000000000000000000000404004000000000001200000000000000000002000000002000000000000000000040000040000200 +00000000000000000000010000000000000000000000000000000000400000000800000000000000000000000000000601100000000000000010000400020008000000000000000200000000000020000000010000000000000400000000000000001a0000000000000000000008020001000000000000000200000000400000000000000200000001220000000000000009000000000000000402000000000000000000000000000020000010000000000000000010800400000000004004000000000000000000000000000000000000000000000000000000400002000000000004000000000000000a000000000040400000800000000000000000000000 +02010000000000000000010000002002000008000000000020000000000020800000000900000000000000000000020020000000208000000000000000000000000000000000002000000010000000000004000080408008000000020002000000000000800000000000000000000000000200400000000000000000000000080000000112060000010000000000000001000000008000000000000080400004000000000480000020002000108000000000000020000000000000000040000000000000002000000000000000000000000008080000000400204044000000000000000000000000000002000000002400010000000000002000000000000004 +00000000000000000000010000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400041000000000000000000000000000002000000004010000000000000000000080000000000900800200000004000000080000800000408040000000000000000000000000000010040000010000000000000040040000000000004000020000100000010000000000000000000001100000000002200000200000000100000100000000000000000000000000000000000000000000000000000000004204200800800000000000000000000002000000002040010000000000000000000200000000 +00000000040000000000000000000000000000000000008000000000000800000000000000000080000000400000000000000000000000000000000000004000000000000000000000000000000000800004000000000000000800000000000000000000000000000008002000000800000000000000000020000000000000000000000002100000000000000000000001000000000100000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000000000000000000000000000000000000000000400004000000000000000008000000000000002000000000001000000000000000000000000000000 +000000000002000000000104000000000000000000000080000000000000000000000000000000000000000000000000000000000004000000000004000010000080000000000000000000000020000400040100000000080000000000000000000008008000000000080000000000002000004080c0000000000000000000000000000202042000010000000000000001000000000000000000020000000000000000000000000000400000100000000400200000000000000100000100000000000000000000800000000000000000400000000100000000004204000000000000000100000000000402000000002040010000200000000000000200000000 +00000000000000100000010000008000000000000000000000000000000000000000000000400000040100000110000400000000000000000000001000020000000000000000040000000000000000200000000800008000104000000100000000200000400000040002000000080000000000000000000000000000000000000080000002000000010000040000000001010000000000000000000800000000000080000000000028208000100000000001008000100000000000000000008001000000000000000800000000000000000000000000000000004001000802000000000000000000000082000000000000000a00000010000000000100200000 +00400000000000000000010000040800000000400000000010000000000002000000000080000000200000000040008400000000000000020040000000000000000000000000020000000008000000000014010008000000000000000000000100000008840000000000000000000000008000408000000000400000000102080000000000000000010000000000000000100000008000000000000000010000010000000020008020000000100008000000000000000000000100010000000000000080000000200400000000000004000008000100001020004000200080000000000000000080000002000000002100000000000000004000018200000000 +00400000000000000000010000000000000000000000000000000000000006000000000000000000000000400000008000000000000000000000000000004000004000000000000000000000020010000004000808000000000000100000000000000000800000000000000008000000000000408000000000000000100002000000000000000000010000002000000001000000008000000000100000000000000000000000000000000000100000000000000000000000100100800000820000000090000000000000000400000000000000000010000000044000000000000000000000804000000202000100002000000004000000000000000200000000 +00020000000200000000001000000000000000000000000000000000000000010000000000000000000000000000000400000000000000000020000000020000000000000000000000000000000000000000018000000000000000000000000000000000000000000800000000080000000000400000000000001000000000080000000002000000000800000000800001000000000000000010000000000000000000001020000000004000100000000000000000100000000000000000000040000000000020000000000024000000000000080000000400000800000000000000040000000000000002000000000000000000000080800000000000000000 +00500000000000000000010000000000000000000000000010000000000002820000000000000000000000000100008400000000000000000000000000020000000000000000000000000000000000000000010008018000400000000000000040000000000000000002000000080000000000000000000000001001000000000000000002000000010800000000000001000000008000000010000000010000000000001000000000000000100000000401000000100000000000000000000001000090000000800000000000400000000000080000000000004000000000000000040000000000000002000000000000000000000004000000000000000000 +00000080040000000000010400004000000000000000000000000000000001000000000000000000000000000000000020000000000100000000000000000000000000000000000000000000000000000004000000004008000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000010000000000000001000002008000000000000000000000000000000000000000000000100200000400000001000000000000000000000000000000000000000000040000000000480000200200020000004000000100000000000000000000000002000010002000010000000000000200000010000000 +02000000000000000000010000000100000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000040000000000000000000000000000000900008000000000000800000000000000000000000000000000008000000000000000100000000000000000000000000002000000010000000000000001000000008000000000000000000000000000000000000000002010108000000400400000000000000000000000000000000000002000000000000000000000000000800000000400404000020000000000000000000000000002000000000000000000000004000088000000004000 +0000000000200000a00009000800000000000a00000000000000000000c000000000000040000000000000000002000000000000000000000000000000000000000000000100000000000000000000001004000000008000200000400008800000000000840000000000000000020000000000408000000000000000000000081000000012000040010000810000000000040000008000000000400000000000200000000000000080200000100000000000000800000000000100000000100000000020200000000000000000000800000000000000000400046000000000000000000000000040000002000000002000000000000000002002000000000000 +00500000000000000000010000000000000000000000000010000000000002820000000000000000000000000100008400000000000000000000000000000000000000000000000000000000000000000000010008008000400000000000000040000800000000000002000000000000000000000000000000000001000000000000000002000000010800000000000001000000008000000000000000010000000000000000000000000000100200100401000000100000000000000000000001000080400000900008000000000000000000200000000000004000000000000000000000000080000402000000000000010000000004000000000000000000 +02000000000000000004010000000400000008000000000400004000002000020200000000000000000000000000008400010001000000000020000000200000000000000000000020000000000000008000000000008000000000000400000000000100000000000002000000000000000000408000000000000000000000000000000002000000010000000000000000100008008000010000000000000200000000008000000000801000120000000400000000000000000100000000000001000020000000000800000800000000000008000000000000004004200880800000000000000000000402000000000000000000000004000000000000000000 +00000400000004000000010000000000000000000000100000000000400000020000000020000000000000000000020000000000000000000000000000040200000400000000000000000004000400200004000000008008000000000000000000000000840000000002000000080000000000408000000000000000000000001080000012000004010000000000000000040000008000000000000000000000010000000000000020000000100200000400000000000000008100000100000001000000000000200000000000000020400000002000000000004200200000800100000000000000000002000000002000010000000004000200000200000000 +04000000000000000000000000000000000000000000000000000000000000000000000000000080040000400040400000000000000000010000000000000000000000000040000000020000000000000004000000008000004800000000200000200000010000800082000000000000000000408000000000000000000000081000000002000000000000000000000000000000000000000000000000000000000000000020000000000000100000000000000000000000100100000000100001000000000000000000000000000000000000000000000000004000000000000000000000000040000002000080400000000000000000000040000000000000 +00100000000000000000010000000000000000000000008000000000000000800000000000000000000000400000000420000002000000000000000000000000000000000000000000000000000000400004000000001080000000000101000000000800000000000000000000080000000000000000000000000000000000000080000002040000010800000000000081010000008000000000002000004000000000000000000000000000100200100001000000100000100000000000000000000000400000100018000000000000000000000000000000004004000000000000000000000080000402000000000000000000400000100000100000000000 +0000000000020000000001000002240000100000000000800002000001000042000000000000004024020000000000040200000000000000000000000008000000000000000100000000000000000008000400000800c080004030000000000000200000800200000002000001080000000000120000000002000040000000000080008002000000010200000000000001000000000000000000000000100000000000000000000000000000100000000002000000200000000000000000040001000080000000000000000000000000000004000000000000004000000000004000000000000080000812000400002000010000000014000000000002000000 +0000000000000000000001000000000000100a000000000020000000000000000000000040000000040000400000000000000000000000000000000000000000000000000000000000000140008000000004000800009000004000000000800000000000800000000000000000000040000000000000000000008000000020000040000002000000000001000000800001000800000000000000400000000800000000000000000000000000100680000000000040080000100000000000040000000010000000000000000000000000000000000200000402004000000000000000000000000000000012000000802000000000000000000000000000000000 +04000000000000000000004000000000000000000000000000800000000004020000000000000000000000000000040000080000000000200000800000000000000000000000000000000000000200000000010000008000040000000040000000000800800000000002000000000000000000408000000010000000000008080080000012000008080000000000000200040000000000000000100000060000005000000000000000000000900000000400000000000000000900000000100001000000000000000000000000000000000000000000400000004000000000000000000000000000000002000000000000000004000004100000000040000000 +10000000000000000000010000000400000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000100000000000000010000008002000000000000001000000000000000200000000000000080200000020008000240800000000000000000000000002000000012000000000000200880000008000000000000004100000008000000000000000000000100000000002000000200040000000000000040000000000000002000000000000800000020000000000000000004000000000000000000000000000000002000000800000010080000000000000000000000010 +00000002000000000000000400000000000000000000008000001000000000000000000002000000010000000000000400000000000000000000000040000000000000000000000000010000000000000004010000004008000080000000000000000000880000000808000000400000000000000000100000000000000000000000000000002000010200000001000001004000008000000000000000000000000000000000000000000000100200000400000000000000000000000000000000000000000000001000000800000000420000000200000000004000000000000800010100000080000002000000002000010000000000040000000000000200 +00000000000000000000010200000000000000000000000000000000000000000000000000000202000000000040002400000000000000000000000000080008000000000000020000000000000000004000000000000000000000000000000000000000010000000000000000080200000000400000400000000000000000001000000006000008000020040000000001080000000000000000100000000000010001000000000000000000100000000000000000020100000000000000000000200000000800000000000000000000000408000000000000000004000000000000000000000000100402000000000400000080000000000000000000000000 +0000008000000000000000000000000000000000000000800200000000000000000000000000000084000000000000002000000010000000000000040000000000000000000004000000000000000000000401000000c000004000000000080000000800800000000808000000000000000000000002000000000000000080000000000000002000010000000000040001000020008000000000020010000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000020000000000000000000000000000004000000000000400000100000000000002000000002040000000000000000000000080000000 +00002000000000000000000000000000000000000000000000800000000000000000000000000000000000000100001000000000000000000080000000000000000000000800000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000408000000000020001000000000000000002000000010000000000000200000000008000000000100000000000000000000000000000000000100000000000000000010000000100000000000000000000000000040000000000000000000000000000000000044000000000000108000000000000400002000000000001000000000000000000000000000000 +00000000000000000000000400000000000000008001000000000000000000000000000002000000000000000000000420000000000000000000080000000000000000000000000000000000000000000000000000000000100000000200000000000000000000000000000000000200010000000000000001000000000000000000000002000000010300000000000001090000008000000000000000000000000040000000000000200000180200000000400000000000000000040000000000000000200000000000000000000000000000001000100000004000000000000000000000000080001002000000000000000000000000000000000000000000 +00000080000000000000000000000000000000000000000000000000000000000140000200000000100000000000000000000000000000040001000000000000000000000000000000000000000000000104010010004000000000000800000000000000800000000800002000000000000000408002000000000000000000080000000002000000000000000000001000000000000000000000000000000000001000200000000000000000100000000000000000000000000000000000000000000000000000001000000000004000000000000000000400404000000000000400000001000000000002000000002100000000000000000000000200000000 +00400000000200000000010000000000000000000400000000000000000000080000000000000004000000000100000402000000000000000000000000000000000000000000000000100000000001000404000008008000000000000002000000000000800000000002000000800000000000008000000000000001002000000000000003000000010000000000000201100000008000000000000000000000000000000000000000000000500000000000000000000000000000000000000000800011000400100000000000000004000000000008000000004080000000000000000100000000000002000000002001000000000000040000000000000000 +00000000000004000000018000000000000100000000000000000000000000020000200000000000000000000000000000000000000000000000000000050000000400000000000000000004000000200004400000008000000000000080000000000000840000000102000000000000000000408040000000000000000000001000400012000004012000000000000200040000008000000000000000000000000000000000000020000000100000000640000000000000000100000100000001000000000000200000000000000020000000000000000000004200200000800100000000000000000002000000002002000000000004000000000200000000 +00000000000004000000010000000000000000040000000000000000000000000000000000000000000000400000008400000000000000000000000000240000000000000000000000020004000000200004400000001000000000000000000000000000040000000000000000000000000000408000000040000000000010001000000012000004000000000000000000040000000000010000000000000000000000000000000000000000100000000040000000000000100100000000000000000000000000000800000000000000000008000000000000004204200800800000000000000000000402000000000000000000000000000002000000000000 +00000000400000000000000000000000000000000001000000040000010000000000000000000000000000000000000400000000000000010040000000000000000000000000000000000002000000000000000000000000000000000000000000000002800000000000000000000000000000000000010000000000000000000080000000080000010000000000000000000000008000000000000000000000000000000000000000200000100000040000000010000000000000000000000000000000202000000400000000000000000000000000000000004000000000000000000000000000000002000000000002000000000000000100000000000000 +00200008000000000000010000000080000000000048000000000001000000000000000040004000000000000000000020000000000040000000000000000000000000000000020000000000004000000004000000008000402000000800000000020004c400010002020000000a0000000000408000000000000000000000080800200012400000010000004000000201000020008000000080000800000004210800200000000000000000100200000000000000000000000000008100000000000000000000000000000014000800000008000000004000004004000000004000000000000000000002000000002000000000000000000200001000000000 +00000800000200000000010000001000000000000000000020000000000000800000000000004000002002000100000400000000000000020800000000000000000000000000000000000000000000000004010000000008000000000420000400000000800000000800000000080000000000400000000200000001000000000009800002000000010000000000000001000000008000000000000000000000000000000000000020000000100400000000000000000000000000000004000000000000200000001000000000800000000000000000000400004024000008000003000000800180800002000202026000010000800000000000200000000000 +02420000010000000880010000001000000400000000000000000400020002000000000800000000000020000000008c20000000080000100000000800002000000000200040000000004180400000000004000808000000000000000000000000000000800000000000000000000000000008000000000000000000000000000000000002000000010000000000800001000040000000000000000000000000000000000000000000000000100000000000400000000000000000000000000000000080000000000000000000100000000000000000000000424000000000000100000000000080010002000000802000000000000000008008020000000000 +0000000000000000000001000000000000000000001000002008000000000080000000000000000004000000000000040000000000000000010000004000000008000000000000000000000000020000000401000800800008401000000000000020000080200020000200000008000000000000000000000000000000000000400000000200002001030000000000000b000000008000000000000000000000000000000000000101000000300000000000000000100000000000000000000001000000000100001010000000000000000000000000000000004004100000000000000000000080000402000000002000000000000010000000000000000000 +00000000000000000000010000000000000000002400000000000041001000000000000041000200000080000000000020000000000000000080000000000000000000000000020000000000080000000000002408004000000800000000000000000000002001000800010000082200000000000000000000000000000000000000000002000000010100000000000000080020008000000000000000000000000000000000002004400000100000000000000000000000000000000000000000000000000002000000000000000000009008000200000040004000000001000400000000000000000002000000040000000000000000000000000000000000 +00000000000000000000010000000000000000000000000000000000010000800004004000000004000000000000008420000000000000000000000000200000000000000000000000000000000000000004000000000000000800000000000000000000000000000000000000000000000000008000000000000000000000000000000210000000010000000000000000000001008000010000000000000000008000000000000000000002100000800000000000001000000000000000000000000000000000000802000000800000000040000000000040004004000000000000000002000000000402000000000000000000000000100000000000000000 +00000000000004000000011000000000000000000000000000000000000000030000000000000000000000000000800400000000000000000020000000040000000400000000000000040004000000200004410000008000000000000080000000000000840000000a02000000000000000000408040000000000000000000001000000012000004010000000000000000040080008000000000000000000000000000001000000020000000100000000440000000000000000100000100000041000000000000200000000020000020000000000000000400004200200000800100000000000000000002000000002000000000000004000000000200000000 +00000010000000040000000000000000000000000000000000000000000000800040000000000204000100000010000000000000000000020000000000000000000000000000000000000000010000000004010000004000000820000000020000040000000000004000000001000000000000408000400000000000000000000008000001000000000000000000000000000800000800000100000000000000000002000000000000000400100000000000000000000000000100000000000000000000000000009000000000008000000000000000000000004000000000000400000000000000000002000000000000000000000800000000000000000000 +06000000000000000080010000000000000000000000000000000000000000000000000000000100000000000000000020000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000200000000800000408000000000000000000080001000000000040000010000000000000000000000008000000000000000000200000000000000000000002000100000000000000000000000000100000000000000000000002000000000000000000000040000000000000000004004000000000000000000000010000002000000000000000000000000000040000000000000 +02000000000000000000010000000000000000000000008100000000000000000000008040000000000000000000000000000000000000000000000000000000000000000000002000000000004000000004000000000000000000002000000000000000800000000008000000080000000000000040000000000000000000000000000002000000000000000000000001080000000000000000000000000000000000000000000000000000108000000000000000000000000000000000000000010000000000008400000000000000010000080000000400004000000000000000000100000000000022000000002000000100000000000000000000000000 +0000008200000000000000000000000000000000000000000000000000000000000000000000000004008000000000000110000000000000000000000000000000000000000000000001000000000000000401000000c000004000000000000000200800800000800802000000400000000000000000000000000000004000000000000002000000000000000000000000000000000000000000000000000000000000100000000000000000100200000000000000000000000000000000000001000000000008000000000000000000080000000000020000004000000000000000000200000000000002000000002000000000800000000000000000000200 +00100000000000000800010000081400000004200000000000000000000000000000000002000004000000000000000624000000000000000000000000000001000000000000000000000000000000000004004008000000000000000000000400000000000200000000000000080000000000408000000200000000000000080080000040040000010200000000000000000000008000000000000000101000000000000000000000200001100000000002000000200000000000000000040000000100200400000000000000000800000000000000000000004004040000000000000010000080000002000000000001010800000000000080000002000000 +004000000400004000000100000010000000000000000000000800000000020000000000400000000400200000000084010000000000000000000000000000000000000000000000000040000000000000040000880000000000000000080000400000008400000000000420000800400000000080000000000000000080000000000000020000800100000000000000001000000080000000000000000000000000000000000040000000001002000000000000000200000000000010000000000000800004000000000000000000000000002002000004000040000000000000000000000000a0000002000000002000000040800000000000000000000000 +00000000000000000010010000000400000000000000008100000000000000000000000000004004000000000000000000000000000000000000010040000000000000000000000000000000000000000004000000000080000000000000000000000000800200000000000000080000000000208000000000000000000020000080008002000000010000000000200001000000000000000000000000100000000000000000000000000000100200000002000000a00000800000000000000000000000000000000000000000000000020008000200000400004005200000800820008100000000000002000000002000010000000000040000000000000000 +00000000000000000000000400000002000000000000008000000000000280000000080200800000000000000000000400000800000000000000000440000000000000000000000000000000000000000004010000000008000000000000000000000800800000000008000000000000000000008000000000000000000010000000000000002000010000000000000001000000000000000000020000000000000000000000000000000000100200000400000001000000000000000000008000000000000000000000000000000000420000100200000000004000000082000830000102000010000002000000002040010000000000040000000000000000 +00000000000100000000010000008000000000000000000020000000000020020000000000000000000000000010000000000000040000000000001000000000000000000000800000000000400000000004000800008000000000080000000000000000c00000100002000000080000000000000000000000000000000000020000000002000000000000040000000001000000000000000000001800000000000000000000000020200000100000000000000000000000000000000000000001000000000000008400000000000100000000000000000000000001000000000000000000000000000082000000002000000200000004000000000100000000 +00000000000000000800000000080000000000000000000000000000000000000000000002000085000000100040000400000000100000000000000040000001000000200000020000000000000020000004000000000008000000000000000000000000800000000000000000080000000000009000000000000000000100000000000000001000010200000000000801000000008000000000000000400000000000000010000000200000100000000400000000100000008000000000000000000000200000000000000000000000400008000000000000004000000000000000000010000000000002000000002000010000000000008000000000000000 +0040000000000000000001000002000000000000000000000000000000000004000000000000480004000000000000040200000000000000000000004000a000000000000004040000000800000001000044010008008000004000000082000000000000800000000000000000080000000000000000000000000000000000000000020042000000000000000000000001000000000000000000000000000002000800000000000000000000108000000000000000100000000000200000000000000080000000001000000000000000000000080000000400004004000000000000000100000000000402000000002000420000000000000000000000000000 +020000000000000000000100000000000000000000000000000800000000000000000008000000000400000000000000200000000000000000000000000000080000000000000000000040000000000000040000800000400000000000000000000000008000002000200000000802000000000000000000000000000000000000000000020400800100000000000008000000000080000000100000000000000000000000000000000000001002000000000000000800001000000000000000000000100400000000000000000000000000002002000000000040040000000080000000000000800000020000000020000000c0000000000000000000000000 +0000000000000000000000400000000000000000000000000002000000000002000000000000004004000000000000000000000000000000002000004000000000000000000100000000000000000000000400000800c000004020000000000000200000800000000002000001082000000020100000000002000000000000000000000402000000010000000000000001000000008000000040080002000000000000000000000000200002100000000000000010000000000000000000000001000080200000000000000000020000000000000000000000004000000000000000000000000000000802000000002000000000000014008001000000000000 +0000000004000000000000004000000000000400040000000000000b00000000000000000000008000000040000100440100000000200000000000004400408000000000000002000000000000000000000400000800000000080000000a000000208000800001000000000000080800000000008000000020000000000000000000000002400000012000000000000001000000000000000000000000000000000000000000000000000000108000000000400000000020100000000000010000000000000000000000000000000000000008400004000408004000000000000000000000004080000002000000002000000000000000000100000000000000 +00000000000000100000010400008000000000000001000000000000000000000000000002000000040100000010000420000000000000000000081000000000000000001000000000000000000000200000000800008000104000000200000000200000400000000002000000080200010000000000000001000000000000000000000002000000010300040000000001090000008000000000000800000000000040000000000020200000180200000001008000000000000000000000000001000000200000000000000000000000000000001000100000004001000000000000000000000080000082000000000000000a00000010000000000100000000 +00000000000000000000000000000000001000002000008100000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000022000000100008000000000000000000080000000000000000000000000800000000000000000080000000000020000000000000000000000000080000000000000010001800001000001000800000000000000000000000000000000000000000000000000100001000000000000080000000000000000000000000000000000000000000000000000000008000000000000004000000000000000000100000000000002000000000000000000000000000000000014000000 +00000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000400000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000080000000000080010000000000000000000800000000010000000000000000000000000000000000200000100000000000000000000200000000000000008000000000000004000800000000000000000000000000000000004020000000000000000000000080000442000000000000000000000000000000000000000010 +0000000000000000000001000000000000000000040000000000000000080000000010000000000000000000004000000000000008888000000020000000000100000000000002000000000004810000000001000c008000000020000002000000004000800000040000000010000000000000000000000000400001000008020080000002000000030000000000000000000000000000000000000000002000000800000000000020000000100100000000000000000000000000000000000000000000000000200000000000000000000008000000000000004008000000000000800000000000000002000000000000000000000000000000400000000000 +000000000000000000000100000400000000004800040004000000000200000a020000000000004000000020000000040000000000800002000000040000000800000000000000000000000000000000000001010000c040000001000400000000000800800000000002000000080200000000408000400000000000000000000000000002000000010200000000000000100000008000000000020000000000000000000000000020000000100000000400000000000044040000000040008201000000000000200410000000800020000000000020000000004000200080000000000000000084140002000000020040400000400004000000000000000000 +20000000000000000000114000108000000020000000000000040000800000900000000000000004000000410000080020000100000002408004000040000000000000008000000010000100000000040004010000101200000000000800000000000000c0001000001000000000000000000040800000000040000000000008188002001204040001400244000000020500200000800000000010000000000402300000002000008000000012000000000000000000010010010000800000000000000000000000000000000000000000000002000000004400c004010080002000000000000000000082000000002000000200000000000108000000000000 +00000082000000000000000000000000000010000000000000040000000000000000000000000000008000000000000000000000000000020000000000000000000000000000000000000000000000000004010000004000000020010400004000000000800000080800000000080000002000602080000000000000000000000008000002000000000020000000000020000000000000000000000000000000000200100000000020000000100000000000000000000000000000000000000000000000000000020400008000800000080000000000000000004004000000000001010200000000800002000000022000000000000000008000000000000202 +02000400000004000000011000000000000000000000100000000000000080010000000800000000000000000000820400000000000000000020000000040000000000000000000000040004000000200004010000000000000000000000000000000000840000000a00000000000000000000408000000000000000000000001000000012000000000000000000000000040080000000000000000000000000410000001000000000000000100000000000000000000000000100000100000048000000000000000000000020000000000000002000000400000200000000800000000000008000000000000000002004000000000000000000000200000000 +00010000000000000000010000000000000000002000000020000001000000000000000000000000040000000100000000000000000000000000000040000000000800000000020000040000000000000004010800008000004400000002000000200000800001800002000000080000000000408000480000000000000000000000000002000000000000000000000201000000000000000001000000000000000000002000000000000000100200200100000002000000000500000000000001000000000000000000000000000000020008000200000000004000000000800800000100000002010002000000002000000000000000008000000000000000 +06008000000000000000010000004000000000000000000000000040080000000000000000000000000000000100020020000000000000000000000000000000000000000000000000000002008000000000040000008000000000000100000000000000800000000000000001000000000010408000000000000201000000081000000000000000010001000000000000010000008000000000000000000000000400000000000000020000100000000400000000100000000100000000000000000000000000000000000000000000000000000000000000004000000000000000000000200000000002000000000000000000000004000040000200004000 +00000000000000000000010400000000000000000000000000000000000000820000000002000000000000000100000420000000000000000000080000000000000400001000000000000000000000000000000000008000500000000000000000000000000000000002000000000000000000002000000000000001000000000000000002000000010200000000000001000000008000000000000000000000000000200000000020200000100200000401000000000000000200000000000001000000200000200000000000000020000000000000100000004000000000000000000000000080000002000000000000010000000004000000000000000000 +00000000000000000000090040008000000000000000000000000000000000000000400002000000040080000000000400000000000000000000000060000000000080000000000000000000000000000044000000008000004000000002000000000000800000000000000000000000000000000000000000000000000000000000000000000000010200040000000001000800008000000000000000000000000000000000000000000000104200000000000000100000000000000000000000000000000000000000000000000000020000002200400000004200000080000400000000000080000002000000002000000000000000000800000000000000 +00400000000000400000000400000002000000000000000000000000000002000000000000000000000000000000008400000000000000000000000104000000000000000000000000000000000000000000010008000008000000000000000010000000000000000000000002000000010000080000000000000000000040000000800000000000010000000000000000010000000000000000000000000000000000000000004000000000100000000400000000100000000000000000008000000080000400001000000000000000400000000000000000004000000080000000000000000000000002000000000000010000000000000000000000000000 +0000000000000020000011000000000000000000000040000000000000000008000000004000000400000000000000000000000000000400001000000000000180000000080000000000000000010000000400088000a000000000000010000100000800800000000000000004000000040000400000000080000000000000080000040012000000000020000000000002000000008400000000000000020004001000200020000000000000100400000000105000010000000000000000000000005000000000000000000108000000000008000000000000040000004000800000000010000004000002000000002000010000000080000020000020040000 +00100000000000000000010000000400000000000000000000000000000000804000000000000000000000000100000420000000080000000000000000000000000000000000000000000000000000400000000000000000000000000000000000002800000200000000000000000000000008000000000000000001000000000000000000040000010800000000000001000000008000000000000000000000000000000000000000000000100200100001000200300000000000000000000000000000400000100008000000000000000000200000000000004004000000000000000000000080000402000000000000010000000000000000100000000000 +00000000000000000000010000000000000000004800000000100000000800800000000000000004000000000000200820000000000000000000000000000000000000000000020000000000020000400004000000000000000000000000000000000000000000000000001001880000000000008000000000000000000020000000000002040000010000020000000001000000008000000000000000000000008000000000000000000000108000000001000000000000000000000000000000000000001000000000000000000000000048000000000400204004000000000000008000000000000002000000000800000000000000000000100000000000 +00000000100000000000000000000000000000000000000000000000002000000000000000000000040000020000000000000000000000000000000040000000000000000008000000000000000000000004000000008000005000004000000000000000800000000000000000480000000000408010008000000000000000080000000012000000000000000000000201040000000000400000000000000004028000000000000000000000100000001000400000000000000100000000000000000000040000000000000000000000000000000000000002004040000000000000000000000000040002100201002800000000000000100000000000000000 +02200000000000000000010000000000000000000000000000000040080000000000000020000000000000000000000020000000000000000000000000000000000000001000000000000140000000010000000800008800020000000000000008000000800000002000000000080000000000000000000000000400001000000000200000040000010000000000800001000000018000000000000802000000000000000020000020002400100000000000000400000000080000000000000002000000200000008400000000000000000000000800000000004004000000000000000000000020000002000000800000000000000000000001000000000000 +04000000000000000000100000000000000000000000004000000000000000008000000000000004000000000000000020000000000000000000000000000000000080040000000000000000000000000004000008004000200002000100000000000000000000000000000000000000000000408000000004000000010000001000000000000200010000000000000000010000008000000000000000000000000000000000000000000000100000000004000000000000000100000000000000000000000000000000000000002000000000000000000000004000000000000000000000000000000002000000000000000000080000000040000000000010 +00000000000000004000010000001800040000000000000000000000000000000000000000000020000000400000200008000000000000000000000000004000000000000000000000020100008000000004000000000000000100400000000000000000800000000000000000000000000000400000000000000000088000080080000000000000000001000000000001000000000000000000000000000000001000000020000000000000000000080080000040000000100000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000080 +00000000000200000000010000001402000000000000000000000000000000004000001040000800000020000400000401050000000000000000000400000000000000000000000000800008000000000004010000000000000000000008000000000804840000000000000000000000000000008000000000000000000000000000000002000000010000000000000201100000000000000000020000000000000000000000000000000000100000000000000000020000000000001400000000008000000000000000100000000000000004000000000400004000000002000020000000000020000002040000802040000000800000000000000000000000 +02000400000004000000010000000000000000000000000000000000000080000000000800000080000000400000400020000000000000000000000000040000000000080000008000020004000000200004000000000000000000000000200000000000050000000000000000000000000000408000000000000000000000001000000012020000010000000000000000040000008000000000000000000000410000000000000000000000100000000000000000000000100100000000000008000000000000000100000000000000000000000000000000004200000000800000000000008000000002000000000004000000000000000000000000000000 +00400020000200000000012000000000000000000000000020000000000000800000000000000084240001000000000020004000000000000000000000000000000000000000000000000000000000000004010000008020004000000000000000200000800000000002100000080000040000400000000000400000000000080000000002000000000000000000200001000000000000000000000004000000000000000020000020200000100000000000800000000000000000004000000001000000000000001000000000000000800000000000800120004000000000000008010008000000000002000000002000000000000010000000000000000000 +02000000000000000000010000000000000000000000000000200000000000000000000040000000000000000800000004000000000000000000000800000000000000000000000000800004000000000000000000000000000000000800000000000004000000000000000000000000000400408000000000000000000000000000000012000020000000000000000000000800000000000400000000000004000000000000010000000000000000000010000000000000800000000000000000010000000000000000000000000010000100000000000000000000000000800000000000000000000000000000800004000000000000000000000000000200 +00000000000200400000010000000000000000000000008000000000000800800040000000000040000000000010000000000000000000000000000004000000000000000000000000000000000000000014010000004000000820000000020000000000800000004008000001000000000000100000000000000000000000000008000003000000000000000000000001000000000800000100000000000000000000000000000000000000100000400001000001000000000000000000000000000000000000001000000000008000000000000000000400004000000000000400008400000000000812000000002001000000000800000000000000000000 +00200000000000000000000100000000000000000000000000000000006000000000000000000008000000000000000020000000000000000000000080000000000000000800000000000000000000000000000000000000000020001000000000000000800000000000000080000000000000400000000000000000000000420000000002000040010000000001000000000000008200000080100002000000000000000000000000004000100200000000000000030000000000000000000000000000000000000000400000000000000002000010000000004000000000000000008001400040000002000000000001000000000000000200000000000000 +0400000000000000000000000000000000000200000000800000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000004000000000000400000000800000042000000000000000000080000000000a000000000004000400400000000000100000000000081000000002002000000001000000000001000000000000000000000000000000000000000020000000000000100200000000000000000000002000000000000400004008000000000000000000000002000000000200080000004000000000000000000100000000000002000000002000000000000000000000000000000000 +00000000000002000000010200000400000000000000000000040000000000100000000000020202000000000000000400010000080000000000000000000000000000000010000000010000000020000000000000000000000000000000000000000000800000000000000000080200000000400000000000000000000000000000000002000000000000040000000000000000000000000000000000000000000000000000000800000000108000108000400000000000000000000000000800000000000000000400000000000000000000000000000500000000000100000000000000000000100402800001000000000000000000000000000000000400 +200000000000000400000100000020000000080000000000010000008000000100000000000000040000000000020000000000000000002080000000000000000002002000001000001000300400000000040100000080000000200000000000000000008400200000404600008000000010004080004010000000000100400a1008000022000400000001004000010000000002080000000400000000020000000000800428000000000000108000000000000000010210008000002100000000000000000000000000000000000000000000000000000000000000000000000000000000000004400000000000002002000040000000020000000000000001 +00000000000000000000000000000000000000000000000000080000000000000000000002000000000000000000008400000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000200000000000080010200000000400000010000008000010000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000800000000000000000000000000000000004000000000000000000000000080000402000010000000000080000008000000000000001000 +0200000000020000000001000000200000000200000000000000000000000000000000184000000024000080000000002000020000000000000000800000000040000000000000000000004080000000000400000000c000000000040000000000000004800000020002000000000000100402000000000000000000000000000000000002040000010000000000000001000000008000000000000000000000000000000000000000202000100200000000000000000000000000000000000000000010000000000000000000000000000000000200080000004004000000000000000000000420000002000000102000000000000000000000000000000000 +00400000000000400000010000000000000000000008000010000000000202000000000000000404080000000000008400000000000000000000000000000001040000000000000000000000000000000004010008008000000000000000000200000000040000000002000000000000000000008000000000000000000000000001000002000000010200000000000000000000000000000000000000010000000000600000004000000000100008028000000000100000000000040000008001000080000400000000000000000000000000000100000004004000200000000000000100000080000002000000000000000000000000000000001000000000 +02000000000000000000010000008000000000000000000001000004040000000000040800000000000000000000000020000000000000000000000040000008000000000000000000000000000000000004000000000000000000000000008000000000800000000008000000000200200000400000000000001000020000400000000812000000010000000000000001040000008000000000000000000000000000000000000000004000100200000000000000000000000000800000000000000000000000000000000000002000000000000800000000004008000000000000000000000000000002000000000000000000000008000200000000000000 +00000080000000000000000000008020000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000400040000000000000004000000005000000000000000000000000000800000000800000000400000000000000000000000000000001000000000000002000000010400040000000000000000008000000000000000000000000008100000000000220000100000000000000000000000000000000000000000000000200000000000000000000400080000000000000400004200000080000000000200000000000002000000002000000000000000000000000000000200 +00000000000000040000000400000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000004000000008008000000000002000000000000800000000002000000000000000400000001080000000000000000000000000002000000010000000000000001000000008000000001000000000000000000000000000000000000100200000400000080000000000000000000000000000000000000000000000000000000420000000300000000004000000000000800000100000000000002000000002000010000000000008000000000000000 +00000000000000000000010000000000000000000000000000000000000000020000000000000200000000000000000000000000000000000000000000040000000400000000000000000000000000000000000000008000000000000000000000000100000000000002000000000000000000408000000000000000000000000000000012000000010000040000000000040000008000404000000000000000010000100000000020000000100000000400000000000000000101000010000001000000000000200000000000000020000000000000000000004200200000800100000000000000000002000000000000000000000004000000000000000000 +00420000000200000000018400000000000000000000000030000000000002800000080000000000002000000000008020000000000000000000000000010000000000000000000000000000004000000004010008000000000080000000000000000000800000000100000000000000000000008000000000000000000000000000000000000000012000000000000001000000008000000000000000010000000000000100000000000000100200000000010000800000000000000000000000000080000000800000000000000000000000000000000000004000008000008000000000000000020002000000002000000000000000000200000000000000 +02000000002200000000010000002000000000000000000000000000000000000000000002000000000000000000000420000000000000000000000000000000000000000000000000000000000000000004200000000000000000000000000000000000800020000000000000000000000000009000000000000000000100000080000000000000010200000000000001000000008100000000200000000000200000000100000000002080104000000000010000900000000000000000000000000000002000000000000000000000000000040000000000004000000000000000000000000000000002000000002000000000000000000000000000000020 +00000000000000000000000000000000040020000000000000000048000000000000000000400000080000000100000400100000000000000000000000020000000000000000000000080000000000000004000080000000000000000000000000002000800000000008000000000200010000009000000000000000000000000000000022000000002000000000000000090000000000002000000000000000000080000000000000000000100200000000000000100000000000000000008200000000000000000800000000006000000000000200000000004000000000000000000000000000000403000000002000000000000000000000000000200000 +0000000000000000000001000000000000000000000000800000000000000000080000000040000000000040010000040000000200000000000000050002000800000000000000020000000000000000000401000000108000000000010100000000180000000000000000000008020000000000000000000000000000000000008000000200000001200000000000000109000000000000000002000000400000008000000000002800000010000000000000000010800410000000004000800000000000000000081000000000000000000000000000000000400000000000000000000000000000000a000000000040400000400000100000000000200000 +00000000000000000000010002400000000000000000000020000000200000000000000000000400000000000000000400000000000000000000000000400000000000000000000000000000000000000000000800000000000400000000000000000000800000000008000000000000000000009000000000000000000000000000000000000000002000000000000201000000000000000000000000000200000000000000400000000060200000000000000000008000000000000000000000000000000000000800000000004000000000000000000000000000000000000000002000000000000412000000800000000000000000000000000000000000 +02000000000000000000000000002400000000000080008004000000200000000000000000000080040000400000000000020080000000000000000040000000000000000000000000000000000000000004000000008000004c2000000000100020000088000080020a000400000000400000000000000000000000000000000000000002002000004001000000000001000800002000000000000000000000000000000000000000000000100200000000000000000000102002000000000001000000000000008000000000000000020008000201000000004000000000000000000100000000000002000000002000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000040000000000000100000000000000000000000000004000000000000000000000000000000000000800000000000000000000000000000000000080000000000000000000080000000000080010001000000000001000000008000000001000000000000000000000000000000200000100a00000000000000000000000000000000000000000000200000000000000000000000020000000100000000004000000000000800000100000080000002000000002000000000000000000200000000000000 +00000000000000000000010000000000000000000000000000400000000200000000000000100004000004000000000420000000000000000000000000000801000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000200000000408000000000000000000000080001200002040080010200000000000000080000008000000000000800001200000000300020000000000000100000000040000000100000000000000000008000000000000020000000000001000000040000001102000000004004000000000000000000000080000002000002400000000000000000000000000000000040 +0040000000040040000000000000000080000000040000000000401000000200000000000000400400000000000200c400000000002002000000000000000000000000000000000000000000000001000004000008000000000010000000000000000000000000000000000000000200000000400000000020000000000010001000000010000000010000040000000000000000000000000000000000000000000000000000004000000000108000000000100000000000000000000000000000000080800400000000000000000000000001000000000000044800000000000000000200000000000003000000000000000000000000000000000002000000 +02800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000420880000000000000020000000040000000000000001000000000000000000000004000008000000000000000081000000200000800010000000800000000000000000408040000000000000000000000000000010020000010000000000000000140000008000004000000000000200000000000002000000003000100000000000000000000000080100000140000000000000002000000000004000000000000000000000000000004200000000000000000000000000000002000000002000000000000000000000000200000000 +00400000002000000000010400000080000000000000008100000000000000000000000800004000008000000000000000000000000000021000000040010000000000000004000000000000000000000004010008000008000000000400020000000000840000000008000000082000000000428000400000000000000000000008000000000000000000000000000001000000000000000000000008000000000800000000000000000000100000000404000000000000000000000000000200000080000000000000000000800000400008000000080000004004200000000000000100000000100002000000022000010000000000040000000000000000 +00000000002000000000010000200004000000000500000000000000000000000000000002000040200000000000000401000010000000020000000000000000000000000000000000000000000000000000210008000000000000000400000000000000000000000200000000080000010000409000000000000000000900001008000000000000010200000200000000110000008000000000200000000000200000000000000020000080100000000000040000900000000000000200000800000000000000000000000000800000000000000000000000004000200000000001000000000000800002000000022000400000100000000000000000000000 +00000000000200000000010000000000000000000000020020000000000000800000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000004010000000000005000000000000200000810800000000000000000000000000000408000000000000200000000000000000010000000030000800000000001800000008000000000120000000000008000000100000800000000100000000000000000008004000100000040000000000000000000000000000000800000000000000010000000044000000000000000000000000000000002000100002042400000000000002000000000000000 +02000000000000000000010000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000400041000000000000000000000000000002000000004010000000000000000000080000000000800800000000000000000000000000000408040000000000000000000000000000012040000010000000000000000040000000000004000020000000000410000000000000000000000100000000000200000000000000102000100000008000000000000000000000000000000000000000000000000004204000000800000000000008000000002000000002044000000000000000000000200000000 +00000000000200000000014008000400000000000000000005000000000000820000000000004000000000000400000020010008000000000000000000000000000000000000000000000008000000000004000800008000000000000000000000000000800000000002000000080000000000000000000000000000001000000800200002040000010000000000000001000200088000000000002800000000000000000000000000000000100000000000000000100000000000000800000005008000000000000000000000000000000004000000000000004004000008000000000000000000000002000000002000000000000004004000100000000000 +02000004000000000000010000001000000000000000000400000000000000000000000800000000000020000000000420000000000000000000000000000000000000000000000000000000000000000000010000004000000000000000000020000400000000000800000000400008000000000000000000000800000000000000000002000400030000000000000000100800008000000000200000000000000000000000000000120000100000000000000000100000000000000000000004000000000001001000000000000000000000000100040000804000002000000000000000000000040002100000000000000000000000000000000000000200 +0000000000000008400000040000040000000000040000000000000000000000000000000000008000000040040000040200000000000000000000005000000000004000004810000000000000000000000400000800802800080000000002000200008080000000c002000000000000000000000000808000000000000020000000000002000000000000000000000001000000000800000000000000000004000000000000000000000000100200000400000000300000100000000000028000000000080000000000010000000000420000000200001000004000000040000000420000000000000002000400002000010000000800000040000000000000 +00000000000000000004010000000000000000000000000000000000000000000000000000000004000000000200000400008000000000000110000000000000000000000000000000100000000000200024000000000000000000000000000000000140000000000000000000000020000000408010000000000000000000001000000010000000010000000000200200040000000000000000000000010000000000000000000000000000100000000000000000100040000500001000000000000000000000000000000040000000100000000000000000000200000000800000000000000002000402000000800000000000000000000000000000000002 +002000000000000000000100000000000000000000000000000000000002020000000000000004040c00000000000004000000000000000000008000400000010400000000000000000000000000000000040000000080000040000000000000002000000400008000020000000000000100000080000000000000000020000000010000020000000002000000020002000100000000000000000000000000000000004000000000000000001000080080000000001000000000000400000080010000000000000000000000000000000000000401000000040040000000000000000000000000c0000002000000000000000000000000000000001000000000 +00000000000000000000010000000000000000000000000000040000000000000000000800000000000800000402000404000000000000000100000000000000000000000000000000000000000000000004000000000000001800000000020000000800800000004000000000080000000000000000000000000000000000000000080000000000010000000000000000000000000800000000000000000000000000000000000020200000100000000000400200100400000000000000000000000000200000000400000000000000000000000000001000004000000000000000000000000000000402000000000000000800000800000000000000000000 +00000000000000000000000000008000000000000000100000000000000000000000000002000000000080000000000400000000000000020000000040000000004080000000800080000000000000000004050000000000000000000400000000000000800000000000000000080000010000400000080000000000000000000008000002000000010200040000000001010000008000000001000000000000000000000000000020000000108200000000000000400000000000000000000000000000000000000002000002800000000000080200000400004200000080000801100100000080800002000000022002000000000000000000000000000000 +02000000000000000000010000800400000008000000000400200000000000000200000000000001000000000000000420010001000020000000000400000008000000000000000200000000000000008000010000000000000000000000000000000800000000000000000000000200000000008000000000000000000000000000080002040000010000000004000800500008008000000001020000000000000000008000000000802000120000000000000000000004000000000040008000000000042004000800000000000000000000000000000000004004000080008000000000000000000402000000000040400000000000000000000000000000 +00000000002000000000000000000000000000000000000000000800000000000000000002000000000000000000000400000000002000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000008000000000000000000000000010000000000000410200000000000000140800008000000000000000000000200000000000000000000000100000000000000000000000000000000000000000000000000000000000000000008000000000000000000000004000000080000000000000000000000002000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000008400008000040000000110000000040200000000000000000000000004000000200004400000010000000000000080000000000000840000000000000000000000000000408040000000000000000000001000000010000000010000000000000000040000000000010000000000010000000000000000000000000000100200000000000000100000000100008100000000000000000000000800000000000000000000000000000000004200000000000000000000000002000402000000002000000000000000000000000200000000 +02000000000000000000010000000000000000000000000000000000000000000000000800000000040000000000000400000000000000020100000800000000000000000000000000000000800000000000000000808400000000000800000000200000000000000802000000080010000000000000000000002000000000000000080002000080010000000000000001000800000000000401000000000000000000000000000000001000100000000000000000100000000000000020000001000000000000000000000000000000040000000000001000004000000000000000000000000180000402000000800000000800400000000000000004000000 +00010000000000000000010000000000000000000000000020000000000008010000000080000000000000000102000420001000000000000000000040040000000000000000000000000000001000000004010800000000000000000000000000000008800000100000000000000000000000400000000000000001000000000040200000040000010000000000000001000000008000000000100800000000000000000000000000000000100000000000000000000000000000000804000040000000000000000000000000000000020000000010000000844004000000000000000000000000000002000000002000004000000000000000000000100000 +10000000000000000010010000000000000000000000008000000001000000000000000000004084000000400040000000000000000000000000010000004000000000000000020000000000000000000004000400000000000800008001000000000000000001000008000000080800000000208000c00000000000000000000000000000400000000000000000200001000000000000000000000000004000000000000000100000000000100000040000000000800000900000000000000000000400000000000000000000000000000008000000000000004004200000800000000000000000000002000000000000000000000000000000000000000000 +02010000000000000000010000002000000008000000000020000000000020800000000900004080000000400000020020000000008000000000000000000000000000000000002000000000000000400004000080009000000800020002000000000000800000000000000000000000000200400000000000000000000000080000000012060000010000000000000001000000108000000000000080400014000000000480000000002000100000000000000000000000100000000040000000000000202000000000000000000000080008000000000000004044000000000000000000000000000002000000002400000000000000002000000000000004 +00000000000200000000030000000000000000000200008100000000000000000010000001000000040000400000000000000000000000000000000000000000000200000000040000000000000200000004000000009080000000000000000200200020800000000002000000080200200000000000000000000000000000020080000002000000010100000000000001000000400000000000000200000000000000000000000000000000100200000000000000000000100000002000000001000000000000000000000000000000000010000000000000004000000000000000001100000000000002000000002000000000000010000200000000000000 +000000000020000000000010000000000800000004000000000200000000000000000000000000400000000000000004000001000000000000000100c0000000000000000000000000000000000000000004040208004000000020800000000000200000800000000000000001000000000420108000000002000000000000020000000002000000010000000000000001000000408000000000000000000000200010000008000000200000100000000000000000000020100000000000000000000000200000000000000000000000200000000000000400004000000000000000000000000080000802000000002000000010000000000001000000000000 +00000000000200000000010000000000000000000000000000000000002000000000200040000000000000000000000028000000000200000000000040000000000000000000000000000000000000000004000800008000000010000000000000000000800000000000000000000000000000408000000000000000000000080000000002000000010000000000000001000100008000000001400002200000100000000120000000000000100200000400000000100000000100000000000000000000000000000000000004008000020000000100000000004000000000820000000100000000000002000000002001000010000004000200000000000000 +02000000000000000000010000000000000000000000000000000000002000000002000040000200000000000000000020008008000200000000400000000800000000000000000000000000000000000002010100008000000000000000000000000000041000000000000000000040000000400000600000000000000000080000000002000000010000040000000000000000008000000000400000000000000000100000000000002000100000400400000000100000000000000000000000000000002000000000000000000000000000800000000000004000000000000000080000000000000002000000000000000002004004000000000000000000 +0000000000000000000001000000000000000800000100000040800000000000000100000000000000000000000000042040000000000000000000000000000000140000200000000000000200000000000400000008c004800000000100000000000000800000000000000200000000200800008000000000000008000020000000000012000004010000000000000200110000008000000000100000000084008000000100000000000000100600000000000000001000000000000000000000000000000000000000000000800000000000000000000000004000000080000000000000000000000002020000002000000000180000100000100000000000 +00000000000000000000010000000000000002000000000000001000000000000000000040004000000000000000000400000000000000000080000000000000000000000000000000000000000000000004000004004000000004000000000000004000800000040000000000080200000000000000000000000000000000200000000002000000000000000000000000000000400000000000000080000000000000200000000000000000100300000000000000000000000020000000010000000000000000000000040000000000000000200200000408004004000000008000000000400080000002000000002000000000000000000000020000000000 +02000000002000000000010000004000000000000000000000000000080000000000000200000000000000000000000000000000000000000000000000000000000000000000000000002000020000000000040000008000000000000000000000000000840000000000000000020000000000008000100000000000000000000000000002000000010000000000000000000000008000000000800000000000200000000000000000220000108000000400000000100000000000000000000000000000200000000000000000000000000000000000000400004000000000000000000000000000000002000000000004000000000004000080001000004000 +02010000000000000000000000002000000000000000008501080000000020000000000900000040040000000000000420000000008000000000000040000000000000000001002000004000000000000004000080000000000000000000000000000000800000000008800000080000000000400000000000000000000000080000000012820480010000002000000001000000008000000000000080000004000000000480000000002000100000000000000000100000000000000000008000000000002004000800000000000000010008000000000000004000000000000100000100000080000402000000002000000000080000002000000000000000 +0001000000000000000001400000000008000000040000002000000000000002000000000000040000000000000000040000000000000000000000004040000000000000000102000001000000000000000400080800800000000000000000000020000080000000008a000000000000000000009000000000000000000008000000000002100000002000000000000201000000000010000000000010000000000400000000000000200060300000000000000000028000000000000000000001000000000000000800000000004000000008000000000020004000000000000000000000000000000412000000802000000000000004000000000000000000 +00000000000000000000010008000000000000000000000000000000000000800000000040000000000000000000000000000000000000000000000020000000000000000000000000800100000000000000000800000000000000010000004008000004000000000000000000080000002000000000000000000000001000000080000002040000010000000000000001000000000000000000080000000000000000000000000000000000100000000000000010000000000000000000000004000000000000000000008000000000000000000000000000004004000008000000000000000000000002000000800000000000000000004000000000000000 +000000000000800400000110000000000000080000000100000000000200000000000000000000000000000080000004000000000080000000000000000000000002802000001000000000000400000000040100000080000000200000000000000000008000000000402000000800000000004080000010000000000000000a1008000002000000020000004804050200000002080000000000000000000000008000010408000000000800108000000000404000000000000100000100000000000010000400000000000000000000000000000000000c00040000000000000000000000000090400002000000002002000050000000020000000000000000 +00000002000000000000010000000000000000000000100000000000000000000040000040002000000020000000000400000000000000000000000000000000000000000001000000000000000000400000000000004000000020040000000000000000800000000000000001080200000000001000000001000000000000000000000002002000000100000000000001000000000000000000000000000002000000000000000000000000100000000000000000800000000080000000010000000000004000000400000000000000000080000000000408004000000008000000000000000080000802000800000000000000000000000000000000000280 +00000000000000000000010000000000200000000000000000040000000000080000000040004004000000000042000000000000800000000000000002000008000000404000020000000000000000000004010000000000000000000000000000000000800000000000000000080300000000411000000000000000000000001000000002000000000000000000000000000000000000000000000000000000000400000000000000200040108000000000000000000010800002000000000000000000000000001400000000000000000008000000000000040000000000000200000000000000000002000000004000000000000000200000000000000400 +00000000000000000000000000000400000000000000000000000000000200000000000000004000000000000002000400000000000200000000000000000000000000002000000000084000000000000004000000000000000000000000000000002000800200000000000000000200000000408000000000000000000000001000100022400000000000000000000000080000000000002400000000000000000000000000000000000000108200000040000005200000000000000000000000000000000000000000000000002000000000000200000000044000000000000000000002000010000002000000002000010000100000000000010000000000 +00000000000240000000012000022000000000000000000020000000200000c00000000002004000242000000000000422000000000000000001080000080000000000000001000000000000000000400804000008008000104010000000000000200000800000800002000000000000000000004000000000000000000000000000008002000000010200000000000001000000008000000000000000000000000000000000000000200000100000000000000000000000000000004000000001000080200000000000000000000000400004000000000000004004000000004080000000000080000002000000002000000000000000000000000000000000 +00010000000000008000000000000000000000000000000000000000000000000000000200000000000000000000000400000000000000000000000000000000000000000000000000000000000000008000000000000000100000000000000000000000000000000002000080000000000000000000008000000000000000000000000000000080010000000000000001100800008000000000000000000000000000000000000000200000100000000000000000000000000000000000008000000000200000000000004000000000000000002000000000004000000000000000000000000480000002000000000000000000000000000000000000000000 +02000000000000000000010040004000000000000002008000000000080020000000000800000000040000000000000000000000004000000000000000000000000004000000000000000040000000000004040000008000004000000000000000400000800000000008020000000000000000000000000000000000000000021000000002002000000000000000000001000000000000000000000000000000000000000000000000000000100000000000000020100000000000000000000000000000400000000000000000000000000000000000000000004000000000000000000100000000000002000000002000000000000000000000000000404000 +00000000000200000000010000000100000000000000008100000000000000000010000000000000000000000040000020000000000000000000000400000008000000000000020200080000000000000004010400000000000000000000000000000800800000100008000000080200200000000000000000000400000000000000000000000000010000000000000001000000408000002000020000000000000000000000000000000000100200040000000000000004000000000040000000000400002000000000000000000000000008000000000000004000000000000000000100000000000002000000002040400000000000000280000000010000 +00000000000000200000010000000000410000000000004024000000000000000000000040004200000000000000000420000000000000004000000000000000000000400000000002000000000000200004010800000200000000000000000000000000800000000000000200000000000000009000000001000000000000080002200002000000840800000000000001000801000000000000000800020000800000000000000000000000100000000001000000100a00008000000800000080000010004000000000000100000000000000002100005000024004000040000000000000000082000002000000002002400000000200000000000000000000 +00000000000000000000000000001500000000000000008000000004000000004000000000000000040000000000000400040000080020000000000000000000000000000000000000000080000000000004000000040080000000000000000000000002800200000000000000080000000000408000000000002000000000000200080002010000010000000000000001000000000800000000100000000000008000000000000000000000100980020000000100200000000100000000008000000000000004000800000000000000000000000000000800044000000000000000000100000000000402100100002000010000000000000000000000000000 +00000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000400888000000000000100000000040000008004000001000000000004000000200004400008010000000000000081000000000000840010000000800000800000000000408040000000000000000000201000000010020000010000000000000008140000008000000000000000000000000000000000000000000004100000000000000000100000080100000140000000000000000000000000004000000000000000000000000000004200000000000000000000000000000402000000002000000000000000000000000200000000 +00000010000000000000010000000000000000000000000000000040040000080000100040000000000000020000000000000000000000000000000280000000000000000000000000020000004000000100000000000000000000000000000000000000800000000400000000000204000000401002000000000000000000081000000082000000000000000000000100100000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000004000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000080000000600000000000000000 +00100000000000000000010000000000000000000000000000000000000000820000000000000000040000000140000400000000000000000000000000000000000400000000020000000000000000080000000000008000004000000000000000200800000000000002000000180000000000000000000000400001000000000000000002000000010800000000000001000000008000000000000000000000000000000000100020100000100200100001000000100000000200000000000001000000400000100008000000000000000008200000000000204000000000000000000000000080000402000000000000000000000014000000000000000000 +00000000000000000000010000001000000008002000000000000001000000000000000040000040000020000000000421000000000000000000000000000000000000000800020000000100000000000004000000008000000000000008000000000000800000000000000000080800000000008000000000001000000000000080000282040000010000000200000000100000108000000000400000000000000000000000000000000000100400000000400020020000000000002000000000000000000000000000000000000000100008000000000400004004000000000000000002000000000002000000002000000000800000000002000000000200 +00000000000000000000010004008000000000000000000002020000800000000000000040000000000000000100000008000000000000000000000040000000000000004000000000000000000000000004000000000001001000004800000000000000c00000000000010000000200000040409000000000000401000001080080000002000000010000040000000201800000000000000010100000000000002000000100000000000000120000000000000000000000000000000000000080000000800000000000000000000000000000000200000000004000000080000000000000000000080082000000002000000200000000000108002000000000 +00000400000004000000010000000400000000000000100000000000000000020000000000000080000000000000020000000000000000040000000000040200000400000000000000000004000000200004000000008000000000000000000000000000840200000002000000080000800000408000000000000000000000001000000012000004010000000000000040040000008000000000000000100000010000000000000020000000100200000402000000200000000100000100000001000000000000200000000000000020000000002000000000004200200000800100000000000000000002000000002000010000000004000000000200000000 +000000000000000000000100000000000000000000200080000008000000000000000000000000000000000001000006200000000000000000000000000a0008000000000000000000000000000000000010000000000080000000000000000000000000000000000000000000080200000000000000000000001001000000000000000002000000010800000000000001080000008000000010000001000000000000001000000020000000100000000000000000100000000000000000100000000000000000200000000000400000000000080000000000004000100000000000040000000000000002000000000000000000000000000000000000000008 +0000000000000000000001000000000000000000000000000000000000000002000000000000000000000000010000040000020000000000000000040002000800000000000000020000000000000000000001000000800040000000000000000000080000000000000200010008020000000000000000000000100100000000000000000200000001200000000000000008000010800000000002000000000000000000100000000000000010000000040000000010000400000000004000000100001080000000000000000040000000000000000000000000400000000000000004000000000000000a000000004040400000000004000000000000000000 +0000010000000000000001000000100000040a000000000000000020000000000002000040000000000020000000000420002000000000000000000000000000000000000000000000000000000000000004000000008000000000000000800000000000800000000000000000000000000000000000000000000000000000000000200002040040010000800000000000000840008000000000400800000000000000000000000000000000100000000000000000100a00000000000000008000000000000000000000400000000000000200000000000400004004000000000000000000000080000002001000002000000000000000008000000000000000 +00000000000400000000080000008000000000000000000000000000000000000800000000000000008000000002000000000000000000000000000000001000000040000000000000020000004000000004000000008000000002001800000000000000800000200002020000000000000000408000400000000400000000080000000002000040010000040000000001000000009000000000000000020000001008000120000020200000100000000000000000000000000100100000000000000000200000000000000000000000000000002000000000044200000080000000800000000040000002000000002000000004000000100000000000000080 +00000000000000000000010000000000000080000000008000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000100000080000000000000000004000004000000000000000000000000000040000000000000000000000000000000408000000000000000000000001000000000000000020000000880040000000040000000000000000000000000000000000000000000000000100000000040000008000000000100000000000000000000000000000000000000000000000000000000000000040080000000800000000000001000000000000000000000000000000000000040000000000000 +00000002000000000004000000000000000000000000000040000000200800002400000000000000000000000000000500000000000000000000000040000000000200000000000000000000000000000004000000004004000000010000000000000000900000000000000000000000002000000400000000000000000000000000000002000000000000840000000021000000000000000000000000100000000000000000000000000000100200000000000000000000000000000000010000000000001000000000008000000200020000000200000400004408000000000080008000000080000002000000002001000001000000000000100000000200 +00000000000000000000010000080200000000000000000000000000000000000000000000000000040040000000000400000000000000000000000000000000000000000000040000000000000000000044000000008000000800000002820000000000008000004002000000080100000000808000000000000000000000000080000252040002010000000000000000000800000800000000000000000004000000000000400000000000100000000000000000100200000000200000000000020000000000000004000000000000000001000000000000004004000000000000020002000000008002001000000000001000000800000000000000040000 +00002000000000000000000000000000000000000000000000800000000000000000000000000000000000000100001000000000000000000080000000000000000000000800000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000408000000000020001000000000000000002000000010000000000000200000000008000000000100000000000000000000000000000000000100000000000000000010000000100000000000000000000000000040000000000000000000000000000000000044000000000000108000000000000400002000000000001000000000000000000000000000000 +00000000000000000000010000000000000000002000000000000201000200020000000000400404080000000000000400000000000000000000200000020001000000000000020010000100000000000004000000008000000000000100000000000000040000000002000000080000000000008000000000000000000000000080000003000000010200000002000200010000008000000000000800000000200000000008000020000000100000000400000008100000000000000000008001000000000000200800000000000020000008040100000004004000000000000000000000000080000002000000000000000000000004400000000000200000 +00000002000000000000000000000000000000000000008000000000000800000080000000000000000000000000000000000000000000020000000440000000000000000000000000000000002000000004010000004000000000000400000000000800800000000008000000080000000000400000000041000000000000000008000002042000018000c00000000001000080000000040000020000000000000200000000000020000000100000000000000000000000000000000000080000000000000000000000000000800000000000000000000400004404000000000001008100000000800002000000022041000000000000000000000040000200 +00000000000000040000001000000000000000002000000000000001000200000000000000000004040000000000000400080002000000000000000000000001000000000000060000000100000000000004000080008000004000008000000000200000000000800002000000080000000000008000000000000000000000000081000002000000010200000000000000000000000000000000000000200000000000000000000000000004100008008000000000100000000000040000008001000000000000000000020000002000000008000100000400004008000000000000000002000080000002000000000000000000000000000002200000000000 +00200000002000800000010040000000000000000400000000000000000000000000000000000004040000000000000020000000000000000020040000000000000000000000040000000000000000000004000008008000000000000000000000000000040000000000000000002000000000008000000000000000000040000004000000000000010000000000000200000000008000000000000000000000200000000000000000004000100000000000000000100000000000000000000000000000000000000000100000000000000000000000090000004000000000000000000000000000000002000000800000000000000000000000000000000100 +00000000000000000000000000000000000000000000000000000000000000000200000000000000000000000040000400000000000020020000000040000000000000000000020000000000000000000004000000000000000000004100000000000800800000000280000000000000000000000000000000400000000008000080080000400000010800000000000081010000000000000000000000002000000000000000000000000000100200100000000080100000000000000000008000000000000004100808000000000000000008000000000000004000000000000000000100000080000402000000002000020000000000008000000000000000 +06000000000000002040010000004020000008000000008000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000004000000008080000000000000000000000000800000000000000000000000002000408000000000000080000000001000000000002000010000000000000005000000008000000000000000000000000000000040000000000000180000000040000000000000000102000000000000000000000000000000000000000000000000000000000001004040000000800000000100000000000002000000002004000000000000000050000000000000 +02004000000000000000010000000000000000000000000000000000000000000000010800004000040000000000000000000000004000000000000000000000000000000000000000020000000000000000000000008000004000000800000000200000000000800002000000000000000000400000000000010000001000080000200002000000000000000000000001000000000000000000000800000010001000000000000000000000100000000000000040000000000000000000000001000000010000200040000000000000000000000000000000004004000000000000000000000000000002000000000000000000000000010000000204000000 +00000000000000000000000000001000000000000000000000000001000000000000000000000000000000000002000000000000000400000000000000000000000000000001020000000000000000008000000004000000000000000000000000004000000801000000000000080001000000000000000000000000000000000202000000400000100000000000010000000900000000000000000080000000000080000080000000000000100100000000000000000200000000000000000000000000000000000000000000000000000008000000000000004000000000000004000000000000400002000000000000000000000000000000000000000000 +00000000000000000000000000000000000080000000000000000004000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000800000100020000010000800000004000000000080002000000408000000000000000000000000080000010000000010000040000000000010000008801000000000000000004008000000000200000000000100000000000000000000200000000000000000008000000000100008404000000800020000000000000000000004000000028000000020080000000000002000000000000001000000800000000000000000800 +00000000000004000000010000000000000000000000000000000000000000000000000000000000000000000000008400000000000000000000000400241000000000000000000000000004002000200004410000000000000000000080000000000800840000000000000000000000000000408040000000000000000000001000000010040004010000000000000000040000000000010000020000000000000000000000000000000000100000000040200000000000000100000100000000000000000000000800000000000000000008000000000000004204200800800000000000000000000402000000002040000000000000000000000200000000 +02200000000000000004010000000000000000000000000000000000000000000000000000000010000000000000000020000000004000000000000000000000000020000000000000000000000000000020000000008000000000002000000000000000000000000000000000000000000000408000000000000400000000000000200000040000010000000000000200000000008000000000000800000000000000000040000000002000100000000000000000000000000500000000000000000000002000000000000000000000000000000000000000004004000000800000000000000800000002000000800000100000000000000000000000000000 +00000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000008400000000000000000000000040000200000000000000000000000000000000000004000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000800000000010000000000000000000000000000000000000000100200000000000000000000000000000000000000000000000000000800000000000000020000002000000000004000000000000400000000000000000402000000002000000000000000000800000000000000 +02000000010000000000000000001080000000000000088110000000000000000000000802000000000000000000000400000000000000020000000000020002000000000000002000000000000020000004010000000000000000000400000000000000800080000008000000080000000000400000000000000000000000000008000002000000010200000000000001042000008000000004000000000000000000000000000020200000100000000000000000100000000000000800000000000000200000000000000000800000010000000000000000004000000000000001040100000010800002000000022000000000000000000000000000000000 +00400000200000000004010000000000000000000000000000000000800000020000000000000004000000000000000400008000000000000000000000000000000000000000000000000000000000000024000008008000000010000000000000000100000000000002000000088000000000418000000000000000000000000000000002000000012000000000200000000000008000000000000000000000008000000000000000000000102000000400000000000000000180001000000001000080000000000000000000800000000000000000000000004000200000800010200000000080000002000000002000000800000006800000000002000000 +0200000000000000000001000000040020000000000000000108000080000000000000084000008004000040000000002000000000000000000000000000000000000000000000000000410000000400001400000000a040000900000400100000000000800000000000000000080201040000000000000000000000000000000000000002040080010000000000000000080000008000000000000000000000000000000000000000000000100400000002000000000000100100000000020100000000000000000000000000000000800000000000000000004004000000000000000000000080110002000000002000000200000000000000400102000000 +200000000000000400000100000020000000080000000000010000008000000100000000000000040000000000020000000000000000002080000000000000000002002000001000001000300400000000040100000080000000200000000000000000008400200000404600008000000010004080004010000000000100400a1008000022000400000001004000010000000002080000000400000000020000000000800428000000000000108000000000000000010210008000002100000000000000000000000000000000000000000000000000000000000000000000000000000000000004400000000000002002000040000000020000000000000001 +02000000000000000000010000001000000000000000000000000000000000000000000800004000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000004000040000020010000000400004000800000000000000000000000402000000000200100000000000000000000000002000000000000000000000021200100000000040001008000000000000000800000000001000000100100000000000000000000000000000000000000000000000000000000008000000200000000000000000000004004000000000000000000000000000002000020000000000000000100000000000000000000 +000000000000000000000100000000020000004000000000000000010000000300000000000040000000080001000004000000000000000000000000c0000000000000000000020000000000000000000004010008009000400000020000000000000000800001000202800000080800000000008000000000000001000000000000000002401000010800000900000001000000008000000000000000000000000000000000000000000000100000000400000000000000000000000000000041000010000000000000800000000000000008000000000400004004200000000000000100000000000002000000002000000000100004000000000000000000 +00000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000008420000000000000000000000000200008000000000000000000000000000000000000000000000000000000000000000020080000800000000000000000000200000000000000000001000000000000000040200000040000010000000000080800000000008000010000000800000000000000000000000000000000100000000000000000000000000000000000000000000000000000000800000000000000000000000000000000004004000000000000000000100000000402000000000000000080000000000000000000000000 +00100000000000000000010000000000000000000000000000000000000000800200000000000000000000000000000420000000000020000000000000000000000000000000000000000000000000400000000000000000000000000100000000000800000000000200000000000000000000000000000000000000000000000000080000040000010800000000000081010000008000000000000000000000000000000000000000000000100200100001000000100000000000000000008000000000400004100808000000000000000000000000000000004004000000000000000000000080000402000000000000000000000000000000100000000000 +200000000000000400000100000020080000080000000000010000008000000000000000400000040000000000000000000000000000002080000000000000000002002000001000001000000400000000040100200080000000200000000000000000008000000000404600008000000000004080000010000000000100400a0008000022000400000000004000010200000002080000000400400000020000000000800428000000000000100400000000000000010200008000002100000000000010000000100000000000000000000000000000000400000000000000000000000000000004400000000000002002000048000000020000000000000201 +00000000002402000000000000000000040020000400000000000010000000000000000002004000000000000002000400000000000800000000000000020080000001000000100000000000020000000000200008000000010000000000000000000000000000000000000000000000000000409000000000000000200100001000000000000000010200000000000400000000008000000000000000000000200000000000000000000000108000000000000000100000000000000001000000000000000000000000000000000000000000000000000000044000000000000000040200000000000002000000000000000000000000040100000000000000 +02000000000000000000000000008000000000000000000000000000000000000000000802000000000000000000000400000800000000000000000000000000000000000000000400004000000000010040000000000000000020000000000000000000000000000000000080000000000000000000000000000000000000000080000002000080010200040000000000000000000000000000000000000000000000000000004000000000100000000000000000000000000000000000000004000001000000000000000000000000000000000000000000004200000080000000000000000080000002000000000000000010000000000100000000000000 +00000000000000000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000000000000000000840000000000000000000020000000000000000000004000000000000000000000002000000000000800001000000000000000000000000000040000000000020000000000000000000400000010000000000000001000000008000080000000000000000000000000000000000000000100200000000000080000000000000000000000000000000000000008400000000000000020008000200000000004000000000000000000080000000000002000000002000000000000000008000000000000000 +00000000000000000004000000000000000000002000000000000001000000010000000000000000008000000140000400008002000000000000000000000000008000000000420200000000000000000000000000010000000000000000000000000000140001000000000000080000000000408000000000001200040000080000000000000000000000040000000000008840000000020000000180000000000000000030000000000000100000000000000000000200000100000000000000000002000000000000000001000000000008000000000000004042000000000000000000000080000012000008000000000000000000000000110000000000 +00010000000000100000010000000000008000000000000020000000000000000000000000000000000000000000000000000000000000010000000040000000200800000000000000000000040800000024010800000000000000000000000000000000c00000000000000000080000040000408000400000400000000000080000000000000000000000040000000201000000000000000000000000000000000000000020000000000040100300208000000002000000000500000000000000000000000000000000000000000000000000000000000000000000000000800000000000000002000092000000802000000080000000000000000000080000 +000000000000004000000100000010000000000020000000808000010000000000000000000000000000200100000000000000000000000000c02000000000000000000000000200000001000000000000040000000002000000200000000004000000000000000000000000010800000000000000000000000000000000000000800000100400000100000400000000000000000080000000000000000000000000000000000000000000001000000000001000000000400000000000000000000000000000000c0000000000000000000008000000000000004004040000000000000000000020000002000000000000000090000000400000000000000000 +00000000000000000000010000080200000000000000000000000000000000000000000000004000000000000040000400000000000000000100000000000000000000000000020000000000004004000000000400008000000000000002000000000000000000000000000000080000000000000000400000000000000000000000000000000000010000000000000008000000008000000000000000000000000000000000000000000000100000040000000000100000000000000000000000000400040000000000000000000000000008000000000000004004000000000000040000000000000402000000000000000400000000000000000000000000 +0040000000000040000401000000100000000000000002000000000000000208000000000000000000002080000000840000000400080000000000000000000000000000001000000000000000000400040400000800000000000000000000000000000080000000000000000000000000000040800000000000000000000200100000000000004001000004000004000000000000c000800000100000000000008000000000004000000000100800000000000000000000000100000008000000000080000400000002000000800000000000000010000000044000000000800000000000000080000002000000002000004000800000000000100000000000 +0000000004000000000000000000100200000000000000000004000000000002000000000004000400000000010200000000000000000100000000000080000200000000400000000000000000800000000401008080c0020000040000000000000000008000000000060000004000000000004000100000002000010000000a0080000012400000010000000000000004000800000010000000000004020000001000200000000200000000300000000400000000000000109000002000000001000000000000200400001000000100000000080000000220004800000000200000800000010000400002000000002002000000000004001000000000000000 +00000400000000000000000000000000000000000000000000000001400000000000000020000000000000000000000020008000000000000000000000040200000000000000000000000004000400000004000000000008000000000080000000000000800000000000000000080000000000408040000000000000000000000080000210000000010000000000000000040000008000000000000000000000000000000000000000000000100200201000000000000000008100000100000000000000000000000000000000000000400000000000000000004200000000000000000002000000000002000000002000010000000000000200000200000000 +02000000000000000400010000000000000010000000000000800000000010000002000800004000000000000000000000001000000000420000200000000008100000000000020000004000000000000004010000000000000000000140000000000000800200000000000000000200000000400000000000000000000000080000000002000000010000000000000800000000008000000000000000000000000000000020000010002410100000000000000000000000000200000000000000000000000000000010000040800000000040000000000000004006000000000014000000000020200002100000022008100000000000000000000000000000 +02000000000000000000010000000400000000000000000000000000000000000000000000000000040000000000008020000000000000000000000000000000000000040000000000000000000000000000000900108000004000000800000000000000000200000000000000008000000000000000000000010000000000000000000002000000010000000000000001000000008000000000000000100000000000000000000000002000100000000002400000200000000000000000000000000000002000000000000000000000020000800000000000404000020000000000000000000000000002000000000000010000000000000008000000004000 +00000000000000002000010040000008000000000000000000000000002000000000000040100004040000000100080020000000000000000000000000000000000800000000000000000000000000000004010000008000004000000000000000000008800000000800000000800000002000408000400080000001000000080800000012000000010000000000000200000000008000000000400000000080000000000000000000000000100000200000800002100000000500000024000000000000000000000000000000000000000000000000000000004000008000800008000000000002020002000000002000000000000000100000000000000000 +02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000020000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000400800000040000000000000000000000000000000000000000000000080000000000000000000000000000000000000800000000000000040000000000000000000000000000000000000080800000800000000000002000000000000000000000000000000000000000000000000000000000000000000000000800000000000000001000000000000000002000000000000001000000000000000000 +04000000000000000000010000000000000000000001000000000001000000010000000000000000000000000000000400000000000000000000000000000000000000000000020000000000000000000000010000000000000000000000000000000100000001000000000000000000010020408000000000000000000020001000000000400000000000000000000000010000000000000000000000000000000000000000000020000000100200000040000000000000000100000000000040000000000000000000010400000000000008000000000000004000200000800000000000000080000002000000400000000000000000000040002000000000 +00000000000000000000010000001000000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000300000000000000000000000000000008000000000000000000000000000000000000400000000000000000000000000000000000000000004000000000000000000000100000000000000000000000000000000000000000000010000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000800000000000000000000000000000000004004000000000000000000000000000402000000000000000000000000000000000000000000 +02000000100000000000010000000000000000000000000000000001080000000000000000004000200000000040000020000000000000000000000000000000000000000000030000000020000000000004000400200000000000000000000000100000800000000000000000082204000000408000400000000000000000081000000002000000000000000000000000080000000000000000400000000000000000000020000000000000101000040800000000000000008100000000100000000400000001000000000000000000000808020000000000004004000000000000004000001040000002000000002000000000000000000040000000000000 +0000000000000000000000400000000000100000000000808000000000000002000000000000008000000040004040000000000000100000000000004000000000480000000000000002000000000000000401000000800000080000000020000000000081000000000a000000080000000000408000400000000000000000000000000002002000000000000000000001000000000000000000002000000000000000000000000000000000100200200000000002000000100100000000000001000000000000000000000000000000000000000200000000004000000000000800000100000000000002000000002000000000000004040000000000000000 +00080000000000000000016000000000000000000000000020000021800200000000000000000004000000000040000000000000000000400000020000000000000000000000020000000000000000000024000800000208000000000800000000000040800000000000000020080000080000408000000100400000000000081000000002000000000000000000221201000000000000000000000000000000000000200020000000000040100000000040000000000200004101000000000000000000000000400000000000040000000008000000000000004000000000800000000002000100000012000000802000010000000010000000000000000000 +00000000000000000000010400000480000000000008000000004000800000000000004000004080008040000000000420000000000000000000000000010000000000000000000000030000000000000004000000008008002c00000800000000200000844200000202001000082200000000408000000000000000000000080800000032000010010000006000000001080020008000002000800000000000000000000000000000000000100210000440000400300000080000008100008000000800000000000000000000002000400000000000000040004004204000000000000000000800000002000000022000010000000000000200000020000000 +02000000000000000004010000004000000000000000000000000000880000020000000000000000000000000000000000008000000000000000000000000000000000000000000000002000000000000000040000008000000000000000000000000000800000000002000000000000000000408000000000000000000000000080000002000080010001010000000000000000008000000000000000000000008000000000000000220000100000000400000000100000000102001000000001000000200000000000000800800000000000000000000000004000000000800010000000000080000002000000040004000800000004000000000000004000 +0000000000000000000011040008000000000a000000000000000000000000000000000040000004000000000000000400000000000000000000000000000000000000000000000000000000000000000004000008008008000000000000800000000000800000000002000000000000040400808000000000000000000000080000000002000000000000000000000001000200000400000000400800040080000000000002000000000000100000000408080000000000008000000000000008000000002000000000000004000000400000000000000400004000000040000008000000000000000002000000002004010000000000000003200001000010 +00000000000000000000010000000000000000000000008001080000000000000000000000000000040000000000000000000000400000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000008000000080000000000000000000000000000000000000000000000000080010000000000000001000000008020000000000000000000000000000000000000000000100000000001000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000080000002000000000000000000000000000008000000100000 +00000000000000000000090000008000000000000000000000000000000800000000400000004000000000000000000400000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000080001000000000000000000000000000020000000000082000000000200040000002000000900000000000000000000000000100000000000000000000000100000000000400000000200000000000000000004000000000000000000000000000000000000200000400400004204000000000010008000000080000002000000000000000800000000000000000000000000 +02000000001000000100010000000000000000000000000000000000000000000000000800000000000000000000000820200000000000400020000000000000000000000001000000000040000000000004000008000000000000000000000000000000800000000000000000000000000020008000200000000000001002000000000002000000010000000000000001000000008000000000000000000000008000020000000000000000120000000000000001000000000000000000000000000000000002000000000000800000000000000000000000004000000000001000000000008000000002000000002000000000000000000000000000000090 From e8ac0a1c1fce53f64f3b2389eb3c1deaff7454cd Mon Sep 17 00:00:00 2001 From: Brian Kelley Date: Mon, 18 Sep 2017 02:09:35 -0400 Subject: [PATCH 23/44] Squashes warnings on cygwin (#1578) --- CMakeLists.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ac369b10c..886301106 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -316,8 +316,12 @@ if (RDK_TEST_COVERAGE) else(RDK_TEST_COVERAGE) if(CMAKE_COMPILER_IS_GNUCXX) # We don't on C_FLAGS warnings to keep Avalon compiling quiet - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated -Wno-unused-function -fno-strict-aliasing -fPIC") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated -Wno-unused-function -fno-strict-aliasing -fPIC -Wall -Wextra") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated -Wno-unused-function -fno-strict-aliasing") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated -Wno-unused-function -fno-strict-aliasing -Wall -Wextra") + if (NOT CYGWIN) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") + endif() endif() if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") # We don't on C_FLAGS warnings to keep Avalon compiling quiet From 4862c920a536fb015a99851355dbd16d4a5d4d3e Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Tue, 19 Sep 2017 14:04:18 +0200 Subject: [PATCH 24/44] Fixes github1567 (#1576) * Fixes #1567 * update expected results * some cleanup and documentation --- Code/GraphMol/SmilesParse/SmilesWrite.cpp | 6 +- Code/GraphMol/SmilesParse/test.cpp | 10 +-- Code/GraphMol/Wrap/rough_test.py | 18 ++--- Code/GraphMol/hanoitest.cpp | 34 +++++++- Code/GraphMol/new_canon.cpp | 96 ++++++++++++++++------- Code/GraphMol/new_canon.h | 2 + 6 files changed, 121 insertions(+), 45 deletions(-) diff --git a/Code/GraphMol/SmilesParse/SmilesWrite.cpp b/Code/GraphMol/SmilesParse/SmilesWrite.cpp index a2f62c9ae..43bd357b1 100644 --- a/Code/GraphMol/SmilesParse/SmilesWrite.cpp +++ b/Code/GraphMol/SmilesParse/SmilesWrite.cpp @@ -437,7 +437,7 @@ std::string MolToSmiles(const ROMol &mol, bool doIsomericSmiles, bool doKekule, #ifdef VERBOSE_CANON for (unsigned int tmpI = 0; tmpI < ranks.size(); tmpI++) { std::cout << tmpI << " " << ranks[tmpI] << " " - << *(tmol.getAtomWithIdx(tmpI)) << std::endl; + << *(tmol->getAtomWithIdx(tmpI)) << std::endl; } #endif @@ -627,6 +627,10 @@ std::string MolFragmentToSmiles(const ROMol &mol, if (canonical) { Canon::rankFragmentAtoms(tmol, ranks, atomsInPlay, bondsInPlay, atomSymbols, true, doIsomericSmiles, doIsomericSmiles); + // std::cerr << "RANKS: "; + // std::copy(ranks.begin(), ranks.end(), + // std::ostream_iterator(std::cerr, " ")); + // std::cerr << std::endl; // MolOps::rankAtomsInFragment(tmol,ranks,atomsInPlay,bondsInPlay,atomSymbols,bondSymbols); } else { for (unsigned int i = 0; i < tmol.getNumAtoms(); ++i) ranks[i] = i; diff --git a/Code/GraphMol/SmilesParse/test.cpp b/Code/GraphMol/SmilesParse/test.cpp index 1b2d5a9eb..41804351b 100644 --- a/Code/GraphMol/SmilesParse/test.cpp +++ b/Code/GraphMol/SmilesParse/test.cpp @@ -3113,7 +3113,7 @@ void testFragmentSmiles() { int as[] = {0, 1, 2, 3}; std::vector atomsToUse(as, as + sizeof(as) / sizeof(int)); std::string csmiles = MolFragmentToSmiles(*m, atomsToUse, 0, 0, 0); - TEST_ASSERT(csmiles == "CC(O)=O"); + TEST_ASSERT(csmiles == "CC(=O)O"); delete m; } { @@ -3127,7 +3127,7 @@ void testFragmentSmiles() { std::vector bondLabels(labels, labels + 5); std::string csmiles = MolFragmentToSmiles(*m, atomsToUse, 0, 0, &bondLabels); - TEST_ASSERT(csmiles == "C-C(-O)=O"); + TEST_ASSERT(csmiles == "C-C(=O)-O"); delete m; } { @@ -3141,7 +3141,7 @@ void testFragmentSmiles() { std::vector bondLabels(labels, labels + 5); std::string csmiles = MolFragmentToSmiles(*m, atomsToUse, 0, 0, &bondLabels); - TEST_ASSERT(csmiles == "CaC(aO)bO"); + TEST_ASSERT(csmiles == "CaC(bO)aO"); delete m; } { @@ -3182,7 +3182,7 @@ void testFragmentSmiles() { std::string csmiles = MolFragmentToSmiles(*m, atomsToUse, 0, 0, &bondLabels); std::cerr << csmiles << std::endl; - TEST_ASSERT(csmiles == "CaC(aC)bC"); + TEST_ASSERT(csmiles == "CaC(bC)aC" || csmiles == "CbC(ac)ac"); delete m; } { @@ -3197,7 +3197,7 @@ void testFragmentSmiles() { std::string csmiles = MolFragmentToSmiles(*m, atomsToUse, 0, 0, &bondLabels); std::cerr << csmiles << std::endl; - TEST_ASSERT(csmiles == "CaC(bC)bC" || csmiles == "CbC(aC)bC"); + TEST_ASSERT(csmiles == "CaC(bC)bC" || csmiles == "CbC(bC)aC"); delete m; } { diff --git a/Code/GraphMol/Wrap/rough_test.py b/Code/GraphMol/Wrap/rough_test.py index ad4ae6705..7752b97ac 100644 --- a/Code/GraphMol/Wrap/rough_test.py +++ b/Code/GraphMol/Wrap/rough_test.py @@ -2258,15 +2258,15 @@ CAS<~> for rwmol in [Chem.EditableMol(mol), Chem.RWMol(mol)]: rwmol.ReplaceBond(0, newBond) - self.assertTrue(Chem.MolToSmiles(rwmol.GetMol()) == 'C1CCC1') + self.assertTrue(Chem.MolToSmiles(rwmol.GetMol()) == 'C1CCC1') self.assertFalse(rwmol.GetMol().GetBondWithIdx(0).HasProp("foo")) for rwmol in [Chem.EditableMol(mol), Chem.RWMol(mol)]: rwmol.ReplaceBond(0, newBond, preserveProps=True) - self.assertTrue(Chem.MolToSmiles(rwmol.GetMol()) == 'C1CCC1') + self.assertTrue(Chem.MolToSmiles(rwmol.GetMol()) == 'C1CCC1') self.assertTrue(rwmol.GetMol().GetBondWithIdx(0).HasProp("foo")) self.assertEqual(rwmol.GetMol().GetBondWithIdx(0).GetProp("foo"), "bar") - + def test47SmartsPieces(self): """ test the GetAtomSmarts and GetBondSmarts functions @@ -3258,10 +3258,10 @@ CAS<~> mol = Chem.MolFromSmiles('C1NCN1.C1NCN1') self.assertEquals( list(Chem.CanonicalRankAtomsInFragment(mol, atomsToUse=range(0, 4), breakTies=False)), - [0, 6, 0, 6, -1, -1, -1, -1]) + [4, 6, 4, 6, -1, -1, -1, -1]) self.assertEquals( list(Chem.CanonicalRankAtomsInFragment(mol, atomsToUse=range(4, 8), breakTies=False)), - [-1, -1, -1, -1, 0, 6, 0, 6]) + [-1, -1, -1, -1, 4, 6, 4, 6]) def test93RWMolsAsROMol(self): """ test the RWMol class as a proper ROMol @@ -3543,7 +3543,7 @@ CAS<~> ap = Chem.AdjustQueryProperties(core) self.assertEqual(ap.GetAtomWithIdx(0).GetPropsAsDict()["foo"], "bar") self.assertEqual(ap.GetAtomWithIdx(1).GetPropsAsDict()["foo"], "bar") - + def testGithubIssue579(self): fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 'NCI_aids_few.sdf.gz') @@ -4341,7 +4341,7 @@ M END self.assertEqual( c1, c2 ) assert d1 == d2 - + self.assertEqual(Chem.MolToSmiles(mol, isomericSmiles=True), Chem.MolToSmiles(mol3,isomericSmiles=True)) @@ -4354,7 +4354,7 @@ M END self.assertEqual(m2.GetProp("foo"),"bar") for atom in m2.GetAtoms(): self.assertEqual(atom.GetProp("myidx"), str(atom.GetIdx())) - + self.assertEqual(Chem.MolToSmiles(m2, True), Chem.MolToSmiles(Chem.MolFromSmiles( "CN[C@@H](C)C(=O)N[C@H](C(=O)N1C[C@@H](Oc2ccccc2)C[C@H]1C(=O)N[C@@H]1CCCc2ccccc21)C1CCCCC1"), @@ -4368,7 +4368,7 @@ M END self.assertFalse(True) # shouldn't get here except RuntimeError: pass - + if __name__ == '__main__': if "RDTESTCASE" in os.environ: suite = unittest.TestSuite() diff --git a/Code/GraphMol/hanoitest.cpp b/Code/GraphMol/hanoitest.cpp index b19ab1c7b..1cdff7512 100644 --- a/Code/GraphMol/hanoitest.cpp +++ b/Code/GraphMol/hanoitest.cpp @@ -1087,8 +1087,8 @@ std::string smis[] = { "C12C3C4C5C6C7C8C1C1C9C5C5C%10C2C2C%11C%12C%13C3C3C7C%10C7C4C%11C1C3C(C5C8%" "12)C(C62)C7C9%13", // does not initially work // drawn examples first reviewer - "C12C3C4C1CC5C46C7C5C1C57C6C53C1C2", - "C1C2C3C4CC5C6C1C17C8C61C5C48C3C27", "EOS"}; + "C12C3C4C1CC5C46C7C5C1C57C6C53C1C2", "C1C2C3C4CC5C6C1C17C8C61C5C48C3C27", + "EOS"}; void test7() { BOOST_LOG(rdInfoLog) << "testing stability w.r.t. renumbering." << std::endl; @@ -1459,6 +1459,35 @@ void test12() { BOOST_LOG(rdInfoLog) << "Finished" << std::endl; } +void testGithub1567() { + BOOST_LOG(rdInfoLog) + << "testing github #1567: Non-canonical result from MolFragmentToSmiles()" + << std::endl; + { + ROMol *m1 = SmilesToMol("CC1CN(Cc2cccc(C)c2)C1"); + TEST_ASSERT(m1); + int m1Ats_a[6] = {1, 12, 3, 4, 5, 11}; + std::vector m1Ats(m1Ats_a, m1Ats_a + 6); + int m1Bnds_a[5] = {12, 11, 3, 4, 13}; + std::vector m1Bnds(m1Bnds_a, m1Bnds_a + 5); + std::string smi1 = MolFragmentToSmiles(*m1, m1Ats, &m1Bnds); + + ROMol *m2 = SmilesToMol("CN(CCC)Cc1cccc(C)c1"); + TEST_ASSERT(m2); + int m2Ats_a[6] = {3, 2, 1, 5, 6, 12}; + std::vector m2Ats(m2Ats_a, m2Ats_a + 6); + int m2Bnds_a[5] = {2, 1, 4, 5, 12}; + std::vector m2Bnds(m2Bnds_a, m2Bnds_a + 5); + std::string smi2 = MolFragmentToSmiles(*m2, m2Ats, &m2Bnds); + + TEST_ASSERT(smi1 == smi2); + + delete m1; + delete m2; + } + BOOST_LOG(rdInfoLog) << "Finished" << std::endl; +} + int main() { RDLog::InitLogs(); #if 1 @@ -1476,6 +1505,7 @@ int main() { test7(); test8(); #endif + testGithub1567(); return 0; } diff --git a/Code/GraphMol/new_canon.cpp b/Code/GraphMol/new_canon.cpp index 2279bd5d6..c04d4b052 100644 --- a/Code/GraphMol/new_canon.cpp +++ b/Code/GraphMol/new_canon.cpp @@ -317,6 +317,19 @@ void getNbrs(const ROMol &mol, const Atom *at, int *ids) { } } +bondholder makeBondHolder(const Bond *bond, unsigned int otherIdx, + bool includeChirality) { + Bond::BondStereo stereo = Bond::STEREONONE; + if (includeChirality) { + stereo = bond->getStereo(); + if (stereo == Bond::STEREOANY) { + stereo = Bond::STEREONONE; + } + } + Bond::BondType bt = + bond->getIsAromatic() ? Bond::AROMATIC : bond->getBondType(); + return bondholder(bt, stereo, otherIdx, 0); +} void getBonds(const ROMol &mol, const Atom *at, std::vector &nbrs, bool includeChirality) { ROMol::OEDGE_ITER beg, end; @@ -324,18 +337,8 @@ void getBonds(const ROMol &mol, const Atom *at, std::vector &nbrs, while (beg != end) { const BOND_SPTR bond = (mol)[*beg]; ++beg; - Bond::BondStereo stereo = Bond::STEREONONE; - if (includeChirality) { - stereo = bond->getStereo(); - if (stereo == Bond::STEREOANY) { - stereo = Bond::STEREONONE; - } - } - unsigned int idx = bond->getOtherAtomIdx(at->getIdx()); - Bond::BondType bt = - bond->getIsAromatic() ? Bond::AROMATIC : bond->getBondType(); - bondholder bh(bondholder(bt, stereo, idx, 0)); - nbrs.push_back(bh); + nbrs.push_back(makeBondHolder( + bond.get(), bond->getOtherAtomIdx(at->getIdx()), includeChirality)); } std::sort(nbrs.begin(), nbrs.end(), bondholder::greater); } @@ -439,18 +442,59 @@ void initCanonAtoms(const ROMol &mol, std::vector &atoms, void initFragmentCanonAtoms(const ROMol &mol, std::vector &atoms, bool includeChirality, - const std::vector *atomSymbols) { + const std::vector *atomSymbols, + const boost::dynamic_bitset<> &atomsInPlay, + const boost::dynamic_bitset<> &bondsInPlay) { + // start by initializing the atoms for (unsigned int i = 0; i < mol.getNumAtoms(); ++i) { - basicInitCanonAtom(mol, atoms[i], i); + atoms[i].atom = mol.getAtomWithIdx(i); + atoms[i].index = i; + // we don't care about overall degree, so we start that at zero, and + // then count the degree in the fragment itself below. atoms[i].degree = 0; - if (atomSymbols) { - atoms[i].p_symbol = &(*atomSymbols)[i]; - } else { - atoms[i].p_symbol = 0; + if (atomsInPlay[i]) { + atoms[i].nbrIds = (int *)calloc(atoms[i].atom->getDegree(), sizeof(int)); + if (atomSymbols) { + atoms[i].p_symbol = &(*atomSymbols)[i]; + } else { + atoms[i].p_symbol = 0; + } + advancedInitCanonAtom(mol, atoms[i], i); + atoms[i].bonds.reserve(atoms[i].atom->getDegree()); } - advancedInitCanonAtom(mol, atoms[i], i); - atoms[i].bonds.reserve(atoms[i].degree); - getBonds(mol, atoms[i].atom, atoms[i].bonds, includeChirality); + } + + // now deal with the bonds in the fragment. + // these set the atomic degrees and update the neighbor lists + for (ROMol::ConstBondIterator bI = mol.beginBonds(); bI != mol.endBonds(); + ++bI) { + if (!bondsInPlay[(*bI)->getIdx()] || + !atomsInPlay[(*bI)->getBeginAtomIdx()] || + !atomsInPlay[(*bI)->getEndAtomIdx()]) + continue; + Canon::canon_atom &begAt = atoms[(*bI)->getBeginAtomIdx()]; + Canon::canon_atom &endAt = atoms[(*bI)->getEndAtomIdx()]; + begAt.nbrIds[begAt.degree] = (*bI)->getEndAtomIdx(); + endAt.nbrIds[endAt.degree] = (*bI)->getBeginAtomIdx(); + begAt.degree++; + endAt.degree++; + begAt.bonds.push_back( + makeBondHolder(*bI, (*bI)->getEndAtomIdx(), includeChirality)); + endAt.bonds.push_back( + makeBondHolder(*bI, (*bI)->getBeginAtomIdx(), includeChirality)); + } + + // and now we can do the last bit for each atom + for (size_t i = 0; i < mol.getNumAtoms(); ++i) { + if (!atomsInPlay[i]) continue; + // this is the fix for github #1567: we let the atom's degree + // in the original molecule influence its degree in the fragment + atoms[i].totalNumHs += + (mol.getAtomWithIdx(i)->getDegree() - atoms[i].degree); + + // and sort our list of neighboring bonds + std::sort(atoms[i].bonds.begin(), atoms[i].bonds.end(), + bondholder::greater); } } @@ -553,13 +597,9 @@ void rankFragmentAtoms(const ROMol &mol, std::vector &res, "bad atomSymbols size"); std::vector atoms(mol.getNumAtoms()); - initFragmentCanonAtoms(mol, atoms, includeChirality, atomSymbols); - for (ROMol::ConstBondIterator bI = mol.beginBonds(); bI != mol.endBonds(); - ++bI) { - if (!bondsInPlay[(*bI)->getIdx()]) continue; - atoms[(*bI)->getBeginAtomIdx()].degree++; - atoms[(*bI)->getEndAtomIdx()].degree++; - } + initFragmentCanonAtoms(mol, atoms, includeChirality, atomSymbols, atomsInPlay, + bondsInPlay); + AtomCompareFunctor ftor(&atoms.front(), mol, &atomsInPlay, &bondsInPlay); ftor.df_useIsotopes = includeIsotopes; ftor.df_useChirality = includeChirality; diff --git a/Code/GraphMol/new_canon.h b/Code/GraphMol/new_canon.h index 5130c10df..b17844343 100644 --- a/Code/GraphMol/new_canon.h +++ b/Code/GraphMol/new_canon.h @@ -289,6 +289,7 @@ class AtomCompareFunctor { else return 0; } + // move onto atomic number ivi = dp_atoms[i].atom->getAtomicNum(); ivj = dp_atoms[j].atom->getAtomicNum(); @@ -350,6 +351,7 @@ class AtomCompareFunctor { else if (ivi > ivj) return 1; } + if (df_useChiralityRings) { // ring stereochemistry ivi = getAtomRingNbrCode(i); From 1027d4469545653180fff9a38dc8224bd50e8b0d Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Fri, 22 Sep 2017 07:22:50 +0200 Subject: [PATCH 25/44] Update IPythonConsole and PandasTools to use new drawing code (#1577) * backup * restructure rdkit.Chem.Draw a bit (need more work here); switch PandasTools over to use that code * typo * limit max number of molecules displayed by default (otherwise jupyter can freak out) * switch to using the new SVG drawing code * update the PNG version to the new code as well * get a bit more robust w.r.t. lengths of optional arguments (allow the molecule list to be shorter than the other properties) rearrange where the preparation for drawing is done for images * disable kekulization of structures with aromatic query bonds during drawing This just generates lots of warnings --- rdkit/Chem/Draw/IPythonConsole.py | 50 +++------- rdkit/Chem/Draw/__init__.py | 150 +++++++++++++++++++----------- rdkit/Chem/PandasTools.py | 13 ++- 3 files changed, 116 insertions(+), 97 deletions(-) diff --git a/rdkit/Chem/Draw/IPythonConsole.py b/rdkit/Chem/Draw/IPythonConsole.py index a3266b19c..c32bb600b 100644 --- a/rdkit/Chem/Draw/IPythonConsole.py +++ b/rdkit/Chem/Draw/IPythonConsole.py @@ -27,6 +27,7 @@ import copy import os import json import uuid +import warnings import numpy try: import Image @@ -99,28 +100,9 @@ def _toPNG(mol): highlightAtoms = mol.__sssAtoms else: highlightAtoms = [] - try: - mol.GetAtomWithIdx(0).GetExplicitValence() - except RuntimeError: - mol.UpdatePropertyCache(False) - - if not hasattr(rdMolDraw2D, 'MolDraw2DCairo'): - mc = copy.deepcopy(mol) - try: - img = Draw.MolToImage(mc, size=molSize, kekulize=kekulizeStructures, - highlightAtoms=highlightAtoms) - except ValueError: # <- can happen on a kekulization failure - mc = copy.deepcopy(mol) - img = Draw.MolToImage(mc, size=molSize, kekulize=False, highlightAtoms=highlightAtoms) - bio = BytesIO() - img.save(bio, format='PNG') - return bio.getvalue() - else: - nmol = rdMolDraw2D.PrepareMolForDrawing(mol, kekulize=kekulizeStructures) - d2d = rdMolDraw2D.MolDraw2DCairo(molSize[0], molSize[1]) - d2d.DrawMolecule(nmol, highlightAtoms=highlightAtoms) - d2d.FinishDrawing() - return d2d.GetDrawingText() + kekulize=kekulizeStructures + return Draw._moltoimg(mol,molSize,highlightAtoms,"",returnPNG=True, + kekulize=kekulize) def _toSVG(mol): @@ -130,20 +112,7 @@ def _toSVG(mol): highlightAtoms = mol.__sssAtoms else: highlightAtoms = [] - try: - mol.GetAtomWithIdx(0).GetExplicitValence() - except RuntimeError: - mol.UpdatePropertyCache(False) - - try: - mc = rdMolDraw2D.PrepareMolForDrawing(mol, kekulize=kekulizeStructures) - except ValueError: # <- can happen on a kekulization failure - mc = rdMolDraw2D.PrepareMolForDrawing(mol, kekulize=False) - d2d = rdMolDraw2D.MolDraw2DSVG(molSize[0], molSize[1]) - d2d.DrawMolecule(mc, highlightAtoms=highlightAtoms) - d2d.FinishDrawing() - svg = d2d.GetDrawingText() - return svg.replace("svg:", "") + return Draw._moltoSVG(mol,molSize,highlightAtoms,"",kekulize) def _toReactionPNG(rxn): @@ -190,7 +159,7 @@ def display_pil_image(img): _MolsToGridImageSaved = None -def ShowMols(mols, **kwargs): +def ShowMols(mols, maxMols=50, **kwargs): global _MolsToGridImageSaved if 'useSVG' not in kwargs: kwargs['useSVG'] = ipython_useSVG @@ -198,6 +167,13 @@ def ShowMols(mols, **kwargs): fn = _MolsToGridImageSaved else: fn = Draw.MolsToGridImage + if len(mols)>maxMols: + warnings.warn("Truncating the list of molecules to be displayed to %d. Change the maxMols value to display more."%(maxMols)) + mols = mols[:maxMols] + for prop in ('legends','highlightAtoms','highlightBonds'): + if prop in kwargs: + kwargs[prop] = kwargs[prop][:maxMols] + res = fn(mols, **kwargs) if kwargs['useSVG']: return SVG(res) diff --git a/rdkit/Chem/Draw/__init__.py b/rdkit/Chem/Draw/__init__.py index 3b7d027d4..80fc2a7e8 100644 --- a/rdkit/Chem/Draw/__init__.py +++ b/rdkit/Chem/Draw/__init__.py @@ -303,35 +303,75 @@ def MolsToImage(mols, subImgSize=(200, 200), legends=None, **kwargs): res.paste(MolToImage(mol, subImgSize, legend=legends[i], **kwargs), (i * subImgSize[0], 0)) return res +from io import BytesIO def _drawerToImage(d2d): try: import Image except ImportError: from PIL import Image - from io import BytesIO sio = BytesIO(d2d.GetDrawingText()) return Image.open(sio) -def _moltoimg(mol, sz, highlights, legend, **kwargs): +def _okToKekulizeMol(mol,kekulize): + if kekulize: + for bond in mol.GetBonds(): + if bond.GetIsAromatic() and bond.HasQuery(): + return False + return True + return kekulize + +def _moltoimg(mol, sz, highlights, legend, returnPNG=False, **kwargs): + try: + mol.GetAtomWithIdx(0).GetExplicitValence() + except RuntimeError: + mol.UpdatePropertyCache(False) + + kekulize=_okToKekulizeMol(mol,kwargs.get('kekulize', True)) + + try: + mc = rdMolDraw2D.PrepareMolForDrawing(mol,kekulize=kekulize) + except ValueError: # <- can happen on a kekulization failure + mc = rdMolDraw2D.PrepareMolForDrawing(mol, kekulize=False) if not hasattr(rdMolDraw2D, 'MolDraw2DCairo'): - img = MolToImage(mol, sz, legend=legend, highlightAtoms=highlights, **kwargs) + img = MolToImage(mc, sz, legend=legend, highlightAtoms=highlights, **kwargs) + if returnPNG: + bio = BytesIO() + img.save(bio, format='PNG') + img = bio.getvalue() else: - nmol = rdMolDraw2D.PrepareMolForDrawing(mol, kekulize=kwargs.get('kekulize', True)) d2d = rdMolDraw2D.MolDraw2DCairo(sz[0], sz[1]) - d2d.DrawMolecule(nmol, legend=legend, highlightAtoms=highlights) + d2d.DrawMolecule(mc, legend=legend, highlightAtoms=highlights) d2d.FinishDrawing() - img = _drawerToImage(d2d) + if returnPNG: + img = d2d.GetDrawingText() + else: + img = _drawerToImage(d2d) return img +def _moltoSVG(mol, sz, highlights, legend, kekulize, **kwargs): + try: + mol.GetAtomWithIdx(0).GetExplicitValence() + except RuntimeError: + mol.UpdatePropertyCache(False) + + kekulize=_okToKekulizeMol(mol,kekulize) + + try: + mc = rdMolDraw2D.PrepareMolForDrawing(mol, kekulize=kekulize) + except ValueError: # <- can happen on a kekulization failure + mc = rdMolDraw2D.PrepareMolForDrawing(mol, kekulize=False) + d2d = rdMolDraw2D.MolDraw2DSVG(sz[0], sz[1]) + d2d.DrawMolecule(mc, legend=legend, highlightAtoms=highlights) + d2d.FinishDrawing() + svg = d2d.GetDrawingText() + return svg.replace("svg:", "") + + def _MolsToGridImage(mols, molsPerRow=3, subImgSize=(200, 200), legends=None, - highlightAtomLists=None, **kwargs): + highlightAtomLists=None, highlightBondLists=None, **kwargs): """ returns a PIL Image of the grid """ - try: - import Image - except ImportError: - from PIL import Image if legends is None: legends = [''] * len(mols) @@ -339,29 +379,39 @@ def _MolsToGridImage(mols, molsPerRow=3, subImgSize=(200, 200), legends=None, if len(mols) % molsPerRow: nRows += 1 - res = Image.new("RGBA", (molsPerRow * subImgSize[0], nRows * subImgSize[1]), (255, 255, 255, 0)) - for i, mol in enumerate(mols): - row = i // molsPerRow - col = i % molsPerRow - highlights = None - if highlightAtomLists and highlightAtomLists[i]: - highlights = highlightAtomLists[i] - if mol is not None: - img = _moltoimg(mol, subImgSize, highlights, legends[i], **kwargs) - res.paste(img, (col * subImgSize[0], row * subImgSize[1])) + if not hasattr(rdMolDraw2D, 'MolDraw2DCairo'): + try: + import Image + except ImportError: + from PIL import Image + res = Image.new("RGBA", (molsPerRow * subImgSize[0], nRows * subImgSize[1]), (255, 255, 255, 0)) + for i, mol in enumerate(mols): + row = i // molsPerRow + col = i % molsPerRow + highlights = None + if highlightAtomLists and highlightAtomLists[i]: + highlights = highlightAtomLists[i] + if mol is not None: + img = _moltoimg(mol, subImgSize, highlights, legends[i], **kwargs) + res.paste(img, (col * subImgSize[0], row * subImgSize[1])) + else: + fullSize = (molsPerRow * subImgSize[0], nRows * subImgSize[1]) + d2d = rdMolDraw2D.MolDraw2DCairo(fullSize[0],fullSize[1],subImgSize[0], subImgSize[1]) + d2d.DrawMolecules(mols,legends=legends,highlightAtoms=highlightAtomLists, + highlightBonds=highlightBondLists,**kwargs) + d2d.FinishDrawing() + res = _drawerToImage(d2d) + return res -def _MolsToGridSVG(mols, molsPerRow=3, subImgSize=(200, 200), legends=None, highlightAtomLists=None, +def _MolsToGridSVG(mols, molsPerRow=3, subImgSize=(200, 200), legends=None, + highlightAtomLists=None, highlightBondLists=None, stripSVGNamespace=True, **kwargs): """ returns an SVG of the grid """ - matcher = re.compile(r'^(<.*>\n)(\n)(.*)', re.DOTALL) if legends is None: legends = [''] * len(mols) - hdr = '' - ftr = '' - rect = '' nRows = len(mols) // molsPerRow if len(mols) % molsPerRow: @@ -370,43 +420,37 @@ def _MolsToGridSVG(mols, molsPerRow=3, subImgSize=(200, 200), legends=None, high blocks = [''] * (nRows * molsPerRow) fullSize = (molsPerRow * subImgSize[0], nRows * subImgSize[1]) - for i, mol in enumerate(mols): - highlights = None - if highlightAtomLists and highlightAtomLists[i]: - highlights = highlightAtomLists[i] - if mol is not None: - nmol = rdMolDraw2D.PrepareMolForDrawing(mol, kekulize=kwargs.get('kekulize', True)) - d2d = rdMolDraw2D.MolDraw2DSVG(subImgSize[0], subImgSize[1]) - d2d.DrawMolecule(nmol, legend=legends[i], highlightAtoms=highlights) - d2d.FinishDrawing() - txt = d2d.GetDrawingText() - h, r, b = matcher.match(txt).groups() - if not hdr: - hdr = h.replace("width='%dpx' height='%dpx' >" % subImgSize, - "width='%dpx' height='%dpx' >" % fullSize) - if not rect: - rect = r - blocks[i] = b - for i, elem in enumerate(blocks): - row = i // molsPerRow - col = i % molsPerRow - elem = rect + elem - blocks[i] = '%s' % (col * subImgSize[0], - row * subImgSize[1], elem) - res = hdr + '\n'.join(blocks) + ftr + + d2d = rdMolDraw2D.MolDraw2DSVG(fullSize[0],fullSize[1],subImgSize[0], subImgSize[1]) + d2d.DrawMolecules(mols,legends=legends,highlightAtoms=highlightAtomLists, + highlightBonds=highlightBondLists,**kwargs) + d2d.FinishDrawing() + res = d2d.GetDrawingText() if stripSVGNamespace: res = res.replace('svg:', '') return res def MolsToGridImage(mols, molsPerRow=3, subImgSize=(200, 200), legends=None, - highlightAtomLists=None, useSVG=False, **kwargs): + highlightAtomLists=None, highlightBondLists=None, + useSVG=False, **kwargs): + if legends and len(legends)>len(mols): + legends = legends[:len(mols)] + if highlightAtomLists and len(highlightAtomLists)>len(mols): + highlightAtomLists = highlightAtomLists[:len(mols)] + if highlightBondLists and len(highlightBondLists)>len(mols): + highlightBondLists = highlightBondLists[:len(mols)] + if useSVG: return _MolsToGridSVG(mols, molsPerRow=molsPerRow, subImgSize=subImgSize, legends=legends, - highlightAtomLists=highlightAtomLists, **kwargs) + highlightAtomLists=highlightAtomLists, + highlightBondLists=highlightBondLists, + **kwargs) else: return _MolsToGridImage(mols, molsPerRow=molsPerRow, subImgSize=subImgSize, legends=legends, - highlightAtomLists=highlightAtomLists, **kwargs) + highlightAtomLists=highlightAtomLists, + highlightBondLists=highlightBondLists, + **kwargs) def _legacyReactionToImage(rxn, subImgSize=(200, 200), **kwargs): diff --git a/rdkit/Chem/PandasTools.py b/rdkit/Chem/PandasTools.py index 01a651d17..035243a05 100644 --- a/rdkit/Chem/PandasTools.py +++ b/rdkit/Chem/PandasTools.py @@ -103,6 +103,7 @@ from rdkit import Chem from rdkit import DataStructs from rdkit.Chem import AllChem from rdkit.Chem import Draw +from rdkit.Chem.Draw import rdMolDraw2D from rdkit.Chem import SDWriter from rdkit.Chem import rdchem from rdkit.Chem.Scaffolds import MurckoScaffold @@ -185,10 +186,8 @@ def patchPandasHeadMethod(self, n=5): def _get_image(x): - """displayhook function for PIL Images, rendered as PNG""" - bio = BytesIO() - x.save(bio, format='PNG') - s = b64encode(bio.getvalue()).decode('ascii') + """displayhook function for PNG data""" + s = b64encode(x).decode('ascii') pd.set_option('display.max_columns', len(s) + 1000) pd.set_option('display.max_rows', len(s) + 1000) if len(s) + 100 > pd.get_option("display.max_colwidth"): @@ -253,10 +252,10 @@ def PrintAsBase64PNGString(x, renderer=None): else: highlightAtoms = [] if molRepresentation.lower() == 'svg': - return _get_svg_image(x, highlightAtoms=highlightAtoms, size=molSize) + return _get_svg_image(x, highlightAtoms=highlightAtoms, size=molSize, kekulize=True) else: - return 'Mol' % _get_image( - Draw.MolToImage(x, highlightAtoms=highlightAtoms, size=molSize)) + data = Draw._moltoimg(x,molSize,highlightAtoms,"",returnPNG=True, kekulize=True) + return 'Mol' % _get_image(data) def PrintDefaultMolRep(x): From 56b472ef97fa7a2ec5b6ba4c54f4c4f0d4ba79dd Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Fri, 22 Sep 2017 07:25:17 +0200 Subject: [PATCH 26/44] Support continuous highlighting in drawMolecules(). (#1579) Add a fillHighlights option to DrawOptions --- Code/GraphMol/MolDraw2D/MolDraw2D.cpp | 15 ++++- Code/GraphMol/MolDraw2D/MolDraw2D.h | 3 + Code/GraphMol/MolDraw2D/Wrap/rdMolDraw2D.cpp | 1 + Code/GraphMol/MolDraw2D/test1.cpp | 60 +++++++++++++++++++- 4 files changed, 76 insertions(+), 3 deletions(-) diff --git a/Code/GraphMol/MolDraw2D/MolDraw2D.cpp b/Code/GraphMol/MolDraw2D/MolDraw2D.cpp index 004d47ef9..0464317db 100644 --- a/Code/GraphMol/MolDraw2D/MolDraw2D.cpp +++ b/Code/GraphMol/MolDraw2D/MolDraw2D.cpp @@ -244,7 +244,7 @@ void MolDraw2D::drawMolecule(const ROMol &mol, } else if (drawOptions().circleAtoms && highlight_atoms) { ROMol::VERTEX_ITER this_at, end_at; boost::tie(this_at, end_at) = mol.getVertices(); - setFillPolys(false); + setFillPolys(drawOptions().fillHighlights); while (this_at != end_at) { int this_idx = mol[*this_at]->getIdx(); if (std::find(highlight_atoms->begin(), highlight_atoms->end(), @@ -714,13 +714,24 @@ void MolDraw2D::drawMolecules( int col = 0; if (nCols > 1) col = i % nCols; setOffset(col * panelWidth(), row * panelHeight()); + + vector *lhighlight_bonds = NULL; + if (highlight_bonds) { + lhighlight_bonds = new std::vector((*highlight_bonds)[i]); + } else if (drawOptions().continuousHighlight && highlight_atoms) { + lhighlight_bonds = new vector(); + getBondHighlightsForAtoms(tmols[i], (*highlight_atoms)[i], + *lhighlight_bonds); + }; + drawMolecule(tmols[i], legends ? (*legends)[i] : "", highlight_atoms ? &(*highlight_atoms)[i] : NULL, - highlight_bonds ? &(*highlight_bonds)[i] : NULL, + lhighlight_bonds, highlight_atom_maps ? &(*highlight_atom_maps)[i] : NULL, highlight_bond_maps ? &(*highlight_bond_maps)[i] : NULL, highlight_radii ? &(*highlight_radii)[i] : NULL, confIds ? (*confIds)[i] : -1); + delete lhighlight_bonds; } }; diff --git a/Code/GraphMol/MolDraw2D/MolDraw2D.h b/Code/GraphMol/MolDraw2D/MolDraw2D.h index c0c781add..2a370be5e 100644 --- a/Code/GraphMol/MolDraw2D/MolDraw2D.h +++ b/Code/GraphMol/MolDraw2D/MolDraw2D.h @@ -66,6 +66,8 @@ struct MolDrawOptions { DrawColour highlightColour; // default highlight color bool continuousHighlight; // highlight by drawing an outline *underneath* the // molecule + bool fillHighlights; // fill the areas used to highlight atoms and atom + // regions int flagCloseContactsDist; // if positive, this will be used as a cutoff (in // pixels) for highlighting close contacts bool includeAtomTags; // toggles inclusion of atom tags in the output. does @@ -100,6 +102,7 @@ struct MolDrawOptions { circleAtoms(true), highlightColour(1, .5, .5), continuousHighlight(true), + fillHighlights(true), flagCloseContactsDist(3), includeAtomTags(false), clearBackground(true), diff --git a/Code/GraphMol/MolDraw2D/Wrap/rdMolDraw2D.cpp b/Code/GraphMol/MolDraw2D/Wrap/rdMolDraw2D.cpp index 13ab64307..4d3ec1087 100644 --- a/Code/GraphMol/MolDraw2D/Wrap/rdMolDraw2D.cpp +++ b/Code/GraphMol/MolDraw2D/Wrap/rdMolDraw2D.cpp @@ -336,6 +336,7 @@ BOOST_PYTHON_MODULE(rdMolDraw2D) { "labels deuterium as D and tritium as T") .def_readwrite("continuousHighlight", &RDKit::MolDrawOptions::continuousHighlight) + .def_readwrite("fillHighlights", &RDKit::MolDrawOptions::fillHighlights) .def_readwrite("flagCloseContactsDist", &RDKit::MolDrawOptions::flagCloseContactsDist) .def_readwrite("atomRegions", &RDKit::MolDrawOptions::atomRegions, diff --git a/Code/GraphMol/MolDraw2D/test1.cpp b/Code/GraphMol/MolDraw2D/test1.cpp index e6153884a..c074400ab 100644 --- a/Code/GraphMol/MolDraw2D/test1.cpp +++ b/Code/GraphMol/MolDraw2D/test1.cpp @@ -1,5 +1,5 @@ // -// Copyright (C) 2015 Greg Landrum +// Copyright (C) 2015-2017 Greg Landrum // // @@ All Rights Reserved @@ // This file is part of the RDKit. @@ -2051,6 +2051,63 @@ void test14BWPalette() { std::cerr << " Done" << std::endl; } +void test15ContinuousHighlightingWithGrid() { + std::cerr << " ----------------- Testing use of continuous highlighting with " + "drawMolecules" + << std::endl; + + { + std::string smiles = + "COc1cccc(NC(=O)[C@H](Cl)Sc2nc(ns2)c3ccccc3Cl)c1"; // made up + RWMol *m1 = SmilesToMol(smiles); + TEST_ASSERT(m1); + smiles = "NC(=O)[C@H](Cl)Sc1ncns1"; // made up + RWMol *m2 = SmilesToMol(smiles); + TEST_ASSERT(m2); + std::vector mols; + mols.push_back(m1); + mols.push_back(m2); + std::vector > atHighlights(2); + atHighlights[0].push_back(0); + atHighlights[0].push_back(1); + atHighlights[0].push_back(2); + atHighlights[0].push_back(6); + + atHighlights[1].push_back(0); + atHighlights[1].push_back(1); + atHighlights[1].push_back(2); + atHighlights[1].push_back(6); + + { + MolDraw2DSVG drawer(500, 200, 250, 200); + drawer.drawOptions().continuousHighlight = false; + drawer.drawMolecules(mols, NULL, &atHighlights); + drawer.finishDrawing(); + std::string text = drawer.getDrawingText(); + std::ofstream outs("test15_1.svg"); + outs << text; + outs.flush(); + TEST_ASSERT(text.find("stroke:#FF7F7F;stroke-width:8px;") == + std::string::npos); + } + + { + MolDraw2DSVG drawer(500, 200, 250, 200); + drawer.drawOptions().continuousHighlight = true; + drawer.drawMolecules(mols, NULL, &atHighlights); + drawer.finishDrawing(); + std::string text = drawer.getDrawingText(); + std::ofstream outs("test15_2.svg"); + outs << text; + outs.flush(); + TEST_ASSERT(text.find("stroke:#FF7F7F;stroke-width:8px;") != + std::string::npos); + } + } + + std::cerr << " Done" << std::endl; +} + int main() { RDLog::InitLogs(); #if 1 @@ -2085,4 +2142,5 @@ int main() { testGithub1322(); testGithub565(); test14BWPalette(); + test15ContinuousHighlightingWithGrid(); } From 213c3149e4a7d40512e8e9b48f6d8cced2ae3394 Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Fri, 22 Sep 2017 08:53:59 +0200 Subject: [PATCH 27/44] fix a dumb interbranch clash (#1586) --- rdkit/Chem/PandasTools.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rdkit/Chem/PandasTools.py b/rdkit/Chem/PandasTools.py index 035243a05..2a5c0ec64 100644 --- a/rdkit/Chem/PandasTools.py +++ b/rdkit/Chem/PandasTools.py @@ -194,10 +194,10 @@ def _get_image(x): pd.set_option("display.max_colwidth", len(s) + 1000) return s +from IPython.display import SVG def _get_svg_image(mol, size=(200, 200), highlightAtoms=[]): """ mol rendered as SVG """ - from IPython.display import SVG from rdkit.Chem import rdDepictor from rdkit.Chem.Draw import rdMolDraw2D try: @@ -252,7 +252,8 @@ def PrintAsBase64PNGString(x, renderer=None): else: highlightAtoms = [] if molRepresentation.lower() == 'svg': - return _get_svg_image(x, highlightAtoms=highlightAtoms, size=molSize, kekulize=True) + svg = Draw._moltoSVG(x, molSize, highlightAtoms, "", True) + return SVG(svg).data else: data = Draw._moltoimg(x,molSize,highlightAtoms,"",returnPNG=True, kekulize=True) return 'Mol' % _get_image(data) From de2e7c7a319119cd9f8eb913e9b1cca8fcbaa37f Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Sat, 23 Sep 2017 17:27:12 +0200 Subject: [PATCH 28/44] Fix/another pandastools mistake (#1592) * fix another PandasTools problem * fix another PandasTools problem --- rdkit/Chem/Draw/__init__.py | 2 +- rdkit/Chem/PandasTools.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/rdkit/Chem/Draw/__init__.py b/rdkit/Chem/Draw/__init__.py index 80fc2a7e8..b5f4889c4 100644 --- a/rdkit/Chem/Draw/__init__.py +++ b/rdkit/Chem/Draw/__init__.py @@ -397,7 +397,7 @@ def _MolsToGridImage(mols, molsPerRow=3, subImgSize=(200, 200), legends=None, else: fullSize = (molsPerRow * subImgSize[0], nRows * subImgSize[1]) d2d = rdMolDraw2D.MolDraw2DCairo(fullSize[0],fullSize[1],subImgSize[0], subImgSize[1]) - d2d.DrawMolecules(mols,legends=legends,highlightAtoms=highlightAtomLists, + d2d.DrawMolecules(list(mols),legends=legends,highlightAtoms=highlightAtomLists, highlightBonds=highlightBondLists,**kwargs) d2d.FinishDrawing() res = _drawerToImage(d2d) diff --git a/rdkit/Chem/PandasTools.py b/rdkit/Chem/PandasTools.py index 2a5c0ec64..d0830cb88 100644 --- a/rdkit/Chem/PandasTools.py +++ b/rdkit/Chem/PandasTools.py @@ -194,10 +194,10 @@ def _get_image(x): pd.set_option("display.max_colwidth", len(s) + 1000) return s -from IPython.display import SVG def _get_svg_image(mol, size=(200, 200), highlightAtoms=[]): """ mol rendered as SVG """ + from IPython.display import SVG from rdkit.Chem import rdDepictor from rdkit.Chem.Draw import rdMolDraw2D try: @@ -252,6 +252,7 @@ def PrintAsBase64PNGString(x, renderer=None): else: highlightAtoms = [] if molRepresentation.lower() == 'svg': + from IPython.display import SVG svg = Draw._moltoSVG(x, molSize, highlightAtoms, "", True) return SVG(svg).data else: From 210935a92c94712e4645262df5a7bd89bfe9c187 Mon Sep 17 00:00:00 2001 From: Brian Kelley Date: Mon, 25 Sep 2017 02:57:14 -0400 Subject: [PATCH 29/44] Adds FreeSASA adapter (#1565) * Adds FreeSASA adapter * Uses windows branch when necessary * Oops inverted windows and unix builds * Fixes windows source build * Adds downloading message * Updates FreeSASA to final API * Adds python API * Finished queryatom API * Changes d_alg to algorithm (and d_classifier) exposes to python adds docs/tests * Adds FATAL_ERROR to MSVC builds, removes from appveyor --- .travis.yml | 2 +- CMakeLists.txt | 1 + External/CMakeLists.txt | 1 + External/FreeSASA/CMakeLists.txt | 87 ++++++ External/FreeSASA/RDFreeSASA.cpp | 201 ++++++++++++ External/FreeSASA/RDFreeSASA.h | 115 +++++++ External/FreeSASA/Wrap/CMakeLists.txt | 8 + External/FreeSASA/Wrap/rdFreeSASA.cpp | 175 +++++++++++ External/FreeSASA/Wrap/testFreeSASA.py | 384 +++++++++++++++++++++++ External/FreeSASA/freesasa2.c | 259 ++++++++++++++++ External/FreeSASA/getline.c | 15 + External/FreeSASA/testFreeSASA.cpp | 414 +++++++++++++++++++++++++ 12 files changed, 1661 insertions(+), 1 deletion(-) create mode 100644 External/FreeSASA/CMakeLists.txt create mode 100644 External/FreeSASA/RDFreeSASA.cpp create mode 100644 External/FreeSASA/RDFreeSASA.h create mode 100644 External/FreeSASA/Wrap/CMakeLists.txt create mode 100644 External/FreeSASA/Wrap/rdFreeSASA.cpp create mode 100644 External/FreeSASA/Wrap/testFreeSASA.py create mode 100644 External/FreeSASA/freesasa2.c create mode 100644 External/FreeSASA/getline.c create mode 100644 External/FreeSASA/testFreeSASA.cpp diff --git a/.travis.yml b/.travis.yml index e0272fe17..715a4d72c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -62,7 +62,7 @@ script: - cd $RDBASE - mkdir build - cd build - - cmake -D Python_ADDITIONAL_VERSIONS=$TRAVIS_PYTHON_VERSION -D PYTHON_EXECUTABLE=$PYTHON -D PYTHON_LIBRARY=`find $PY_PREFIX -name "libpython$TRAVIS_PYTHON_VERSION*.so"` -D PYTHON_NUMPY_INCLUDE_PATH=$PY_SP_DIR/numpy/core/include -D BOOST_ROOT=$PY_PREFIX -D Boost_NO_SYSTEM_PATHS=ON -D RDK_BUILD_AVALON_SUPPORT=ON -D RDK_BUILD_INCHI_SUPPORT=ON -DRDK_BUILD_THREADSAFE_SSS=on -DRDK_TEST_MULTITHREADED=on -DRDK_INSTALL_STATIC_LIBS=OFF -DRDK_BUILD_SWIG_WRAPPERS=ON -DRDK_SWIG_STATIC=OFF .. + - cmake -D Python_ADDITIONAL_VERSIONS=$TRAVIS_PYTHON_VERSION -D PYTHON_EXECUTABLE=$PYTHON -D PYTHON_LIBRARY=`find $PY_PREFIX -name "libpython$TRAVIS_PYTHON_VERSION*.so"` -D PYTHON_NUMPY_INCLUDE_PATH=$PY_SP_DIR/numpy/core/include -D BOOST_ROOT=$PY_PREFIX -D Boost_NO_SYSTEM_PATHS=ON -D RDK_BUILD_AVALON_SUPPORT=ON -D RDK_BUILD_INCHI_SUPPORT=ON -DRDK_BUILD_THREADSAFE_SSS=on -DRDK_TEST_MULTITHREADED=on -DRDK_INSTALL_STATIC_LIBS=OFF -DRDK_BUILD_SWIG_WRAPPERS=ON -DRDK_SWIG_STATIC=OFF -DRDK_BUILD_FREESASA_SUPPORT=ON .. - make -j2 - make install diff --git a/CMakeLists.txt b/CMakeLists.txt index 886301106..da0eac6b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,6 +41,7 @@ option(RDK_BUILD_TEST_GZIP "Build the gzip'd stream test" OFF) option(RDK_OPTIMIZE_NATIVE "Use native features while compiling." ON) option(RDK_USE_STRICT_ROTOR_DEFINITION "Use the most strict rotatable bond definition" ON) option(RDK_BUILD_DESCRIPTORS3D "Build the 3D descriptors calculators, requires Eigen3 to be installed" ON) +option(RDK_BUILD_FREESASA_SUPPORT "build the rdkit freesasa wrapper" OFF ) if(NOT MSVC) if(RDK_OPTIMIZE_NATIVE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mpopcnt") diff --git a/External/CMakeLists.txt b/External/CMakeLists.txt index a987b806b..678e72604 100644 --- a/External/CMakeLists.txt +++ b/External/CMakeLists.txt @@ -1,3 +1,4 @@ add_subdirectory(INCHI-API) add_subdirectory(AvalonTools) +add_subdirectory(FreeSASA) diff --git a/External/FreeSASA/CMakeLists.txt b/External/FreeSASA/CMakeLists.txt new file mode 100644 index 000000000..523661589 --- /dev/null +++ b/External/FreeSASA/CMakeLists.txt @@ -0,0 +1,87 @@ +if(RDK_BUILD_FREESASA_SUPPORT) + +if(NOT DEFINED FREESASA_DIR) + set(FREESASA_DIR "${CMAKE_CURRENT_SOURCE_DIR}/freesasa") + set(needDownload "TRUE") + if(EXISTS "${FREESASA_DIR}/src/freesasa.h") + set(needDownload "FALSE") + endif() +endif() + +if(needDownload) + # don't actually use the md5 here + if(MSVC) + message(FATAL_ERROR "FreeSASA currently not working on windows. Come back soon!") + message("Downloading WINDOWS FREESASA source") + downloadAndCheckMD5("https://github.com/mittinatten/freesasa/archive/windows.tar.gz" + "${CMAKE_CURRENT_SOURCE_DIR}/master.tar.gz" + "") + execute_process(COMMAND ${CMAKE_COMMAND} -E tar zxf + ${CMAKE_CURRENT_SOURCE_DIR}/master.tar.gz + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + set(FREESASA_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/freesasa-windows") + set(FREESASA_GETLINE "getline.c") + else() + downloadAndCheckMD5("https://github.com/mittinatten/freesasa/archive/master.tar.gz" + "${CMAKE_CURRENT_SOURCE_DIR}/master.tar.gz" + "") + execute_process(COMMAND ${CMAKE_COMMAND} -E tar zxf + ${CMAKE_CURRENT_SOURCE_DIR}/master.tar.gz + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + set(FREESASA_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/freesasa-master") + set(FREESASA_GETLINE "") + endif() +endif() + +macro(use_c99) + if (CMAKE_VERSION VERSION_LESS "3.1") + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + set (CMAKE_C_FLAGS "--std=gnu99 ${CMAKE_C_FLAGS}") + endif () + else () + set (CMAKE_C_STANDARD 99) + endif () +endmacro(use_c99) + +use_c99() +message("Copying freesasa2.c to ${FREESASA_SRC_DIR}/src/freesasa2.c") +file(COPY freesasa2.c DESTINATION ${FREESASA_SRC_DIR}/src/) + +set (freesasa_clib_srcs + ${FREESASA_SRC_DIR}/src/classifier.c + ${FREESASA_SRC_DIR}/src/classifier_naccess.c + ${FREESASA_SRC_DIR}/src/classifier_oons.c + ${FREESASA_SRC_DIR}/src/classifier_protor.c + ${FREESASA_SRC_DIR}/src/coord.c + ${FREESASA_SRC_DIR}/src/freesasa2.c + ${FREESASA_SRC_DIR}/src/lexer.c + ${FREESASA_SRC_DIR}/src/log.c + ${FREESASA_SRC_DIR}/src/nb.c + ${FREESASA_SRC_DIR}/src/node.c + ${FREESASA_SRC_DIR}/src/parser.c + ${FREESASA_SRC_DIR}/src/pdb.c + ${FREESASA_SRC_DIR}/src/rsa.c + ${FREESASA_SRC_DIR}/src/sasa_lr.c + ${FREESASA_SRC_DIR}/src/sasa_sr.c + ${FREESASA_SRC_DIR}/src/selection.c + ${FREESASA_SRC_DIR}/src/structure.c + ${FREESASA_SRC_DIR}/src/util.c + ${FREESASA_GETLINE} + ) + +add_definitions(-DUSE_THREADS=0) +add_definitions(-DUSE_JSON=0) +add_definitions(-DUSE_XML=0) +rdkit_library(freesasa_clib ${freesasa_clib_srcs}) +include_directories("${FREESASA_SRC_DIR}/src") + +rdkit_library(FreeSASALib RDFreeSASA.cpp SHARED LINK_LIBRARIES freesasa_clib GraphMol DataStructs RDGeometryLib RDGeneral ) +rdkit_headers(RDFreeSASA.h DEST GraphMol) + +rdkit_test(testFreeSASALib testFreeSASA.cpp + LINK_LIBRARIES FreeSASALib freesasa_clib FileParsers SmilesParse + GraphMol DataStructs RDGeometryLib RDGeneral) + +add_subdirectory(Wrap) + +endif(RDK_BUILD_FREESASA_SUPPORT) diff --git a/External/FreeSASA/RDFreeSASA.cpp b/External/FreeSASA/RDFreeSASA.cpp new file mode 100644 index 000000000..b24d80dee --- /dev/null +++ b/External/FreeSASA/RDFreeSASA.cpp @@ -0,0 +1,201 @@ +// Copyright (c) 2016, Novartis Institutes for BioMedical Research Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Novartis Institutes for BioMedical Research Inc. +// nor the names of its contributors may be used to endorse or promote +// products derived from this software without specific prior written +// permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include +#include +#include +#include +#include +#include "RDFreeSASA.h" +#include "boost/format.hpp" + +extern "C" { +#include "freesasa.h" +} + +namespace RDKit { + namespace common_properties { + namespace Atom { + const std::string SASA = "SASA";; // Solvent Accessible Surface Area for atom- double + const std::string SASAClass = "SASAClass"; // Class type, 0,1,2... etc + const std::string SASAClassName = "SASAClassName"; // Class name, Polar, APolar etc... + } + namespace Molecule { + const std::string SASA = "SASA"; // Total Solvent Accessible Surface area for molecule; + } + } +} + +namespace FreeSASA { +using namespace RDKit; + +bool classifyAtoms(ROMol &mol, std::vector &radii, + const SASAOpts &opts) { + radii.clear(); + const freesasa_classifier *classifier = 0; + switch (opts.classifier) { + case SASAOpts::Protor: + classifier = &freesasa_protor_classifier; + break; + case SASAOpts::NACCESS: + classifier = &freesasa_naccess_classifier; + break; + case SASAOpts::OONS: + classifier = &freesasa_oons_classifier; + break; + default: + throw ValueErrorException("unknown FreeSASA classifier specified"); + return false; + } + + bool success = true; + for (ROMol::AtomIterator at = mol.beginAtoms(); at != mol.endAtoms(); ++at) { + Atom *atom = *at; + freesasa_atom_class cls = FREESASA_ATOM_UNKNOWN; + std::string classification = "Unclassified"; + double radius = 0.0; + + const AtomMonomerInfo *info = atom->getMonomerInfo(); + if (info) { + const char *atom_name = info->getName().c_str(); + const char *res_name = 0; + + if (info->getMonomerType() == AtomMonomerInfo::PDBRESIDUE) { + res_name = ((AtomPDBResidueInfo *)info)->getResidueName().c_str(); + radius = freesasa_classifier_radius(classifier, res_name, atom_name); + + if (radius == 0.0) { + BOOST_LOG(rdWarningLog) << "Atom " << atom->getIdx() + << " has zero radius" << std::endl; + } + + cls = freesasa_classifier_class(classifier, res_name, atom_name); + if (cls == FREESASA_ATOM_UNKNOWN) { + BOOST_LOG(rdWarningLog) << "Atom " << atom->getIdx() + << " could not be classified" << std::endl; + success = false; + } else { + classification = freesasa_classifier_class2str(cls); + } + } + } + + radii.push_back(radius); + atom->setProp(common_properties::Atom::SASAClass, (int)cls); + atom->setProp(common_properties::Atom::SASAClassName, classification); + } + + return success; +} + +namespace { +double internalCalcSASA(const ROMol &mol, + const std::vector &radii, + int confIdx, + const SASAOpts &opts) { + PRECONDITION(mol.getNumConformers(), "No conformers in molecule"); + PRECONDITION(confIdx < rdcast(mol.getNumConformers()), + "Conformer index out of range"); + PRECONDITION(mol.getNumAtoms(), "Empty molecule"); + + freesasa_parameters params = freesasa_default_parameters; + params.n_threads = 1; + switch (opts.algorithm) { + case SASAOpts::LeeRichards: + params.alg = FREESASA_LEE_RICHARDS; + break; + case SASAOpts::ShrakeRupley: + params.alg = FREESASA_SHRAKE_RUPLEY; + break; + default: + throw ValueErrorException("Unknown freesasa algorithm"); + } + + // sneaky, but legal :) + std::vector coords(mol.getNumAtoms() * 3); + const RDGeom::POINT3D_VECT &vec = mol.getConformer(confIdx).getPositions(); + for (size_t i = 0; i < mol.getNumAtoms(); ++i) { + coords[i * 3] = vec[i].x; + coords[i * 3 + 1] = vec[i].y; + coords[i * 3 + 2] = vec[i].z; + } + + freesasa_result *res = + freesasa_calc_coord(&coords[0], &radii[0], mol.getNumAtoms(), ¶ms); + if (!res) return 0.0; + CHECK_INVARIANT(res->n_atoms == rdcast(mol.getNumAtoms()), + "freesasa didn't return the correct number of atoms"); + + double sasa = res->total; + mol.setProp(common_properties::Molecule::SASA, sasa); + size_t i = 0; + for (ROMol::ConstAtomIterator at = mol.beginAtoms(); at != mol.endAtoms(); + ++at, ++i) { + (*at)->setProp(common_properties::Atom::SASA, res->sasa[i]); + } + + freesasa_result_free(res); + return sasa; +} +} + +double calcSASA(const RDKit::ROMol &mol, + const std::vector &radii, + int confIdx, + const RDKit::QueryAtom *query, + const SASAOpts &opts){ + double result = internalCalcSASA(mol, radii, confIdx, opts); + if(query) { + result = 0.0f; + for (ROMol::ConstQueryAtomIterator at = mol.beginQueryAtoms(query); + at != mol.endQueryAtoms(); ++at) { + const Atom *atom = *at; + result += atom->getProp("SASA"); + } + } + return result; +} + +const RDKit::QueryAtom * makeFreeSasaAPolarAtomQuery() { + QueryAtom *qa = new QueryAtom; + qa->setQuery(makePropQuery("SASAClassName", "Apolar")); + return qa; +} + +const RDKit::QueryAtom * makeFreeSasaPolarAtomQuery() { + QueryAtom *qa = new QueryAtom; + qa->setQuery(makePropQuery("SASAClassName", "Polar")); + return qa; +} +} + + + diff --git a/External/FreeSASA/RDFreeSASA.h b/External/FreeSASA/RDFreeSASA.h new file mode 100644 index 000000000..31555e3a5 --- /dev/null +++ b/External/FreeSASA/RDFreeSASA.h @@ -0,0 +1,115 @@ +// Copyright (c) 2016, Novartis Institutes for BioMedical Research Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Novartis Institutes for BioMedical Research Inc. +// nor the names of its contributors may be used to endorse or promote +// products derived from this software without specific prior written +// permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef RDKIT_FREESASA_H +#define RDKIT_FREESASA_H + +#include + +namespace RDKit { + namespace common_properties { + namespace Atom { + extern const std::string SASA; // Solvent Accessible Surface Area for atom- double + extern const std::string SASAClass; // Class type, 0,1,2... etc + extern const std::string SASAClassName; // Class name, Polar, APolar etc... + } + namespace Molecule { + extern const std::string SASA; // Total Solvent Accessible Surface area for molecule; + } + } +} + +namespace FreeSASA { +struct SASAOpts { + enum Algorithm { LeeRichards = 0, ShrakeRupley = 1 }; + enum Classifier { Protor = 0, NACCESS = 1, OONS = 2 }; + enum Classes { Unclassified = 0, APolar = 1, Polar = 2 }; + + Algorithm algorithm; + Classifier classifier; + SASAOpts() : algorithm(LeeRichards), classifier(Protor) {} + SASAOpts(Algorithm alg, Classifier cls) : algorithm(alg), classifier(cls) {} +}; + +//! Classify atoms using standard freesaa classifiers +/*! + Note: + + FreeSASA identified Classes end up in atom.getProp(common_properties::Atom::SASAClassName) + FreeSASA Class names end up in atom.getProp(common_properties::Atom::SASAClassName) + + \param mol: Molecule to analyze + \param radii output vector of radii where radii[idx] is the radius for atom with index idx + \return false if no atoms could be classified +*/ +bool classifyAtoms(RDKit::ROMol &mol, std::vector &radii, + const FreeSASA::SASAOpts &opts = SASAOpts()); + +//! calculate the Solvent Accessible Surface Area using the FreeSASA library. +/*! + SASA atom contribution data is stored in atom.getProp(common_properites::Atom::SASA); + + \param mol: Molecule to analyze + \param radii vector of radii where radii[idx] is the radius for atom with index idx + These can be passed in or calculated with classifyAtoms for some proteins. + \param confIdx specify the conformation [default -1] + \param query query atom to limit the number of atoms to the ones matching the query + precanned query atoms can be made with makeFreeSasaPolarAtomQuery and + makeFreeSasaAPolarAtomQuery for classified polar and apolar atoms respectively. + + \param opts SASAOpts class specifying options. + \return the requested solvent accessible surface area +*/ +double calcSASA(const RDKit::ROMol &mol, const std::vector &radii, + int confIdx=-1, + const RDKit::QueryAtom *query=NULL, + const SASAOpts &opts = SASAOpts()); + + +//! Make a query atom returning the FreeSASA supplied apolar atom classification +/*! + These are atoms that have the "SASAClassName" property set to "Apolar" + after calling classifyAtoms. + + \return QueryAtom pointer +*/ +const RDKit::QueryAtom * makeFreeSasaAPolarAtomQuery(); +//! Make a query atom returning the FreeSASA supplied polar atom classification +/*! + These are atoms that have the "SASAClassName" property set to "Polar" + after calling classifyAtoms. + \return QueryAtom pointer +*/ +const RDKit::QueryAtom * makeFreeSasaPolarAtomQuery(); + +} + +#endif diff --git a/External/FreeSASA/Wrap/CMakeLists.txt b/External/FreeSASA/Wrap/CMakeLists.txt new file mode 100644 index 000000000..bfe32cd67 --- /dev/null +++ b/External/FreeSASA/Wrap/CMakeLists.txt @@ -0,0 +1,8 @@ +include_directories( ${RDKit_ExternalDir}/FreeSASA ) +rdkit_python_extension(rdFreeSASA + rdFreeSASA.cpp + DEST Chem + LINK_LIBRARIES + FreeSASALib freesasa_clib GraphMol DataStructs RDGeometryLib RDGeneral RDBoost) +add_pytest(pyFreeSASA + ${CMAKE_CURRENT_SOURCE_DIR}/testFreeSASA.py) diff --git a/External/FreeSASA/Wrap/rdFreeSASA.cpp b/External/FreeSASA/Wrap/rdFreeSASA.cpp new file mode 100644 index 000000000..9bdd589b0 --- /dev/null +++ b/External/FreeSASA/Wrap/rdFreeSASA.cpp @@ -0,0 +1,175 @@ +// Copyright (c) 2017, Novartis Institutes for BioMedical Research Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Novartis Institutes for BioMedical Research Inc. +// nor the names of its contributors may be used to endorse or promote +// products derived from this software without specific prior written +// permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +#define NO_IMPORT_ARRAY +#include +#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION +#include +#include +//#include +//#include +//#include +#include + +#include +#include +#include +#include +#include + +namespace python = boost::python; + +namespace RDKit { +namespace { +python::object classifyAtomsHelper(RDKit::ROMol &mol, + const FreeSASA::SASAOpts &opts) { + std::vector radii; + python::list l; + if (FreeSASA::classifyAtoms(mol, radii, opts)) { + for(size_t i=0;i(query); + if (!atom) { + throw ValueErrorException("Query is not a query atom!"); + } + } + + std::vector vradii; + + unsigned int sz = python::extract(radii.attr("__len__")()); + for (unsigned int i = 0; i < sz; ++i) { + vradii.push_back(python::extract(radii[i])()); + } + + return FreeSASA::calcSASA(mol, vradii, confIdx, atom, opts); +} +} + +struct freesasa_wrapper { + static void wrap() { + + std::string docString = ""; + python::enum_("SASAAlgorithm") + .value("LeeRichards", FreeSASA::SASAOpts::LeeRichards) + .value("ShrakeRupley", FreeSASA::SASAOpts::ShrakeRupley) + .export_values(); + + python::enum_("SASAClassifier") + .value("Protor", FreeSASA::SASAOpts::Protor) + .value("NACCESS", FreeSASA::SASAOpts::NACCESS) + .value("OONS", FreeSASA::SASAOpts::OONS) + .export_values(); + + python::enum_("SASAClass") + .value("Unclassified", FreeSASA::SASAOpts::Unclassified) + .value("APolar", FreeSASA::SASAOpts::APolar) + .value("Polar", FreeSASA::SASAOpts::Polar) + .export_values(); + + python::class_("SASAOpts", docString.c_str(), + python::init<>("Constructor takes no arguments")) + .def(python::init()) + .def_readwrite("algorithm", &FreeSASA::SASAOpts::algorithm) + .def_readwrite("classifier", &FreeSASA::SASAOpts::classifier) + ; + + + docString = "Classify the atoms in the molecule returning their radii if possible.\n" + "ARGUMENTS:\n" + " - mol: molecule to classify\n" + " - options: FreeSASA options class specifying the classsification method.\n" + " Current classifiers are Protor, NACCESS and OONS\n" + " classification is stored as atom property 'SASAClass' for the integer value\n" + " and 'SASAClassName' for the string name of the class, Polar, APolar...\n" + "\n" + "RETURNS:\n" + " list of radii where radii[atom.GetIdx()] is the radii of the atom.\n" + " If classification fails, NONE is returned\n"; + + python::def("classifyAtoms", classifyAtomsHelper, + (python::arg("mol"), + python::arg("options") = FreeSASA::SASAOpts()), + docString.c_str()); + + docString = "Compute the Solvent Accessible Surface Area using the FreeSASA library\n" + "ARGUMENTS:\n" + " - mol: The molecule to compute.\n" + " - radii: A list of atom raddii where radii[atom.GetIdx()] is the radius of the atom\n" + " These can be passed in or calculated with classifyAtoms for some proteins\n" + " - confIdx: Specify the conformer to use for the 3D geometry [default -1]\n" + " - query: Pass along a query atom to compute the SASA for a subset of atoms.\n" + " precanned query atoms can be made with MakeFreeSasaPolarAtomQuery and\n" + " MakeFreeSasaAPolarAtomQuery for classified polar and apolar atoms respectively.\n" + " - opts: a SASAOpts class specifying the algorithm to use\n" + "\n" + "RETURNS:\n" + "The computed solvent accessible surface area.\n"; + + python::def("CalcSASA", calcSASAHelper, + (python::arg("mol"), + python::arg("radii"), + python::arg("confIdx")=-1, + python::arg("query")=python::object(), + python::arg("opts")=FreeSASA::SASAOpts()), + docString.c_str()); + + + python::def("MakeFreeSasaAPolarAtomQuery", FreeSASA::makeFreeSasaAPolarAtomQuery, + python::return_value_policy(), + "Returns an APolar atom query for use with CalcSASA. An apolar atom has the SASAClass\n" + "and SASAClassName set to the APOLAR class. (see classifyAtoms)"); + + python::def("MakeFreeSasaPolarAtomQuery", FreeSASA::makeFreeSasaPolarAtomQuery, + python::return_value_policy(), + "Returns a polar atom query for use with CalcSASA. An polar atom has the SASAClass\n" + "and SASAClassName set to the POLAR class. (see classifyAtoms)"); + } +}; +} + +BOOST_PYTHON_MODULE(rdFreeSASA) { + python::scope().attr("__doc__") = + "Module containing rdFreeSASA classes and functions."; + RDKit::freesasa_wrapper::wrap(); +} + diff --git a/External/FreeSASA/Wrap/testFreeSASA.py b/External/FreeSASA/Wrap/testFreeSASA.py new file mode 100644 index 000000000..ac630f3ea --- /dev/null +++ b/External/FreeSASA/Wrap/testFreeSASA.py @@ -0,0 +1,384 @@ +# Copyright (c) 2017, Novartis Institutes for BioMedical Research Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Novartis Institutes for BioMedical Research Inc. +# nor the names of its contributors may be used to endorse or promote +# products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +from __future__ import print_function + +import unittest +import os,sys, copy + +from rdkit.Chem import rdFreeSASA +from rdkit import Chem + +expected = [ + [0, 1, "Polar", 1.64], [1, 0, "Apolar", 1.88], + [2, 0, "Apolar", 1.61], [3, 1, "Polar", 1.42], + [4, 0, "Apolar", 1.88], [5, 0, "Apolar", 1.88], + [6, 1, "Polar", 1.77], [7, 0, "Apolar", 1.88], + [8, 1, "Polar", 1.64], [9, 0, "Apolar", 1.88], + [10, 0, "Apolar", 1.61], [11, 1, "Polar", 1.42], + [12, 0, "Apolar", 1.88], [13, 0, "Apolar", 1.88], + [14, 0, "Apolar", 1.61], [15, 1, "Polar", 1.42], + [16, 1, "Polar", 1.64], [17, 1, "Polar", 1.64], + [18, 0, "Apolar", 1.88], [19, 0, "Apolar", 1.61], + [20, 1, "Polar", 1.42], [21, 0, "Apolar", 1.88], + [22, 0, "Apolar", 1.88], [23, 0, "Apolar", 1.88], + [24, 0, "Apolar", 1.88], [25, 1, "Polar", 1.64], + [26, 0, "Apolar", 1.88], [27, 0, "Apolar", 1.61], + [28, 1, "Polar", 1.42], [29, 0, "Apolar", 1.88], + [30, 0, "Apolar", 1.61], [31, 0, "Apolar", 1.76], + [32, 0, "Apolar", 1.76], [33, 0, "Apolar", 1.76], + [34, 0, "Apolar", 1.76], [35, 0, "Apolar", 1.76], + [36, 1, "Polar", 1.64], [37, 0, "Apolar", 1.88], + [38, 0, "Apolar", 1.61], [39, 1, "Polar", 1.42], + [40, 0, "Apolar", 1.88], [41, 0, "Apolar", 1.88], + [42, 0, "Apolar", 1.88], [43, 1, "Polar", 1.64], + [44, 0, "Apolar", 1.88], [45, 0, "Apolar", 1.61], + [46, 1, "Polar", 1.42], [47, 0, "Apolar", 1.88], + [48, 0, "Apolar", 1.88], [49, 0, "Apolar", 1.88], + [50, 0, "Apolar", 1.88], [51, 1, "Polar", 1.64], + [52, 1, "Polar", 1.64], [53, 0, "Apolar", 1.88], + [54, 0, "Apolar", 1.61], [55, 1, "Polar", 1.42], + [56, 0, "Apolar", 1.88], [57, 1, "Polar", 1.46], + [58, 0, "Apolar", 1.88], [59, 1, "Polar", 1.64], + [60, 0, "Apolar", 1.88], [61, 0, "Apolar", 1.61], + [62, 1, "Polar", 1.42], [63, 0, "Apolar", 1.88], + [64, 0, "Apolar", 1.88], [65, 0, "Apolar", 1.88], + [66, 0, "Apolar", 1.88], [67, 1, "Polar", 1.64], + [68, 0, "Apolar", 1.88], [69, 0, "Apolar", 1.61], + [70, 1, "Polar", 1.42], [71, 0, "Apolar", 1.88], + [72, 1, "Polar", 1.46], [73, 0, "Apolar", 1.88], + [74, 1, "Polar", 1.64], [75, 0, "Apolar", 1.88], + [76, 0, "Apolar", 1.61], [77, 1, "Polar", 1.42], + [78, 1, "Polar", 1.64], [79, 0, "Apolar", 1.88], + [80, 0, "Apolar", 1.61], [81, 1, "Polar", 1.42], + [82, 0, "Apolar", 1.88], [83, 0, "Apolar", 1.88], + [84, 0, "Apolar", 1.88], [85, 0, "Apolar", 1.88], + [86, 1, "Polar", 1.64], [87, 1, "Polar", 1.64], + [88, 0, "Apolar", 1.88], [89, 0, "Apolar", 1.61], + [90, 1, "Polar", 1.42], [91, 0, "Apolar", 1.88], + [92, 1, "Polar", 1.46], [93, 0, "Apolar", 1.88], + [94, 1, "Polar", 1.64], [95, 0, "Apolar", 1.88], + [96, 0, "Apolar", 1.61], [97, 1, "Polar", 1.42], + [98, 0, "Apolar", 1.88], [99, 0, "Apolar", 1.88], + [100, 0, "Apolar", 1.88], [101, 0, "Apolar", 1.88], + [102, 1, "Polar", 1.64], [103, 0, "Apolar", 1.88], + [104, 0, "Apolar", 1.61], [105, 1, "Polar", 1.42], + [106, 0, "Apolar", 1.88], [107, 1, "Polar", 1.46], + [108, 0, "Apolar", 1.88], [109, 1, "Polar", 1.64], + [110, 0, "Apolar", 1.88], [111, 0, "Apolar", 1.61], + [112, 1, "Polar", 1.42], [113, 0, "Apolar", 1.88], + [114, 0, "Apolar", 1.88], [115, 0, "Apolar", 1.88], + [116, 0, "Apolar", 1.88], [117, 1, "Polar", 1.64], + [118, 0, "Apolar", 1.88], [119, 0, "Apolar", 1.61], + [120, 1, "Polar", 1.42], [121, 0, "Apolar", 1.88], + [122, 0, "Apolar", 1.88], [123, 0, "Apolar", 1.61], + [124, 1, "Polar", 1.42], [125, 1, "Polar", 1.46], + [126, 1, "Polar", 1.64], [127, 0, "Apolar", 1.88], + [128, 0, "Apolar", 1.61], [129, 1, "Polar", 1.42], + [130, 0, "Apolar", 1.88], [131, 0, "Apolar", 1.88], + [132, 0, "Apolar", 1.88], [133, 1, "Polar", 1.64], + [134, 0, "Apolar", 1.88], [135, 0, "Apolar", 1.61], + [136, 1, "Polar", 1.42], [137, 0, "Apolar", 1.88], + [138, 0, "Apolar", 1.88], [139, 0, "Apolar", 1.61], + [140, 1, "Polar", 1.42], [141, 1, "Polar", 1.46], + [142, 1, "Polar", 1.64], [143, 0, "Apolar", 1.88], + [144, 0, "Apolar", 1.61], [145, 1, "Polar", 1.42], + [146, 0, "Apolar", 1.88], [147, 0, "Apolar", 1.88], + [148, 0, "Apolar", 1.88], [149, 1, "Polar", 1.64], + [150, 0, "Apolar", 1.88], [151, 0, "Apolar", 1.61], + [152, 1, "Polar", 1.42], [153, 0, "Apolar", 1.88], + [154, 1, "Polar", 1.46], [155, 1, "Polar", 1.64], + [156, 0, "Apolar", 1.88], [157, 0, "Apolar", 1.61], + [158, 1, "Polar", 1.42], [159, 0, "Apolar", 1.88], + [160, 0, "Apolar", 1.61], [161, 1, "Polar", 1.42], + [162, 1, "Polar", 1.46], [163, 1, "Polar", 1.64], + [164, 0, "Apolar", 1.88], [165, 0, "Apolar", 1.61], + [166, 1, "Polar", 1.42], [167, 0, "Apolar", 1.88], + [168, 1, "Polar", 1.46], [169, 0, "Apolar", 1.88], + [170, 1, "Polar", 1.64], [171, 0, "Apolar", 1.88], + [172, 0, "Apolar", 1.61], [173, 1, "Polar", 1.42], + [174, 0, "Apolar", 1.88], [175, 0, "Apolar", 1.88], + [176, 0, "Apolar", 1.88], [177, 0, "Apolar", 1.88], + [178, 1, "Polar", 1.64], [179, 0, "Apolar", 1.88], + [180, 0, "Apolar", 1.61], [181, 1, "Polar", 1.42], + [182, 0, "Apolar", 1.88], [183, 0, "Apolar", 1.88], + [184, 0, "Apolar", 1.61], [185, 1, "Polar", 1.42], + [186, 1, "Polar", 1.46], [187, 1, "Polar", 1.64], + [188, 0, "Apolar", 1.88], [189, 0, "Apolar", 1.61], + [190, 1, "Polar", 1.42], [191, 0, "Apolar", 1.88], + [192, 0, "Apolar", 1.61], [193, 1, "Polar", 1.42], + [194, 1, "Polar", 1.64], [195, 1, "Polar", 1.64], + [196, 0, "Apolar", 1.88], [197, 0, "Apolar", 1.61], + [198, 1, "Polar", 1.42], [199, 0, "Apolar", 1.88], + [200, 0, "Apolar", 1.88], [201, 0, "Apolar", 1.88], + [202, 1, "Polar", 1.64], [203, 0, "Apolar", 1.88], + [204, 0, "Apolar", 1.61], [205, 1, "Polar", 1.42], + [206, 0, "Apolar", 1.88], [207, 0, "Apolar", 1.88], + [208, 0, "Apolar", 1.88], [209, 0, "Apolar", 1.88], + [210, 1, "Polar", 1.64], [211, 1, "Polar", 1.64], + [212, 0, "Apolar", 1.88], [213, 0, "Apolar", 1.61], + [214, 1, "Polar", 1.42], [215, 0, "Apolar", 1.88], + [216, 1, "Polar", 1.64], [217, 0, "Apolar", 1.88], + [218, 0, "Apolar", 1.61], [219, 1, "Polar", 1.42], + [220, 0, "Apolar", 1.88], [221, 0, "Apolar", 1.88], + [222, 0, "Apolar", 1.88], [223, 0, "Apolar", 1.88], + [224, 1, "Polar", 1.64], [225, 1, "Polar", 1.64], + [226, 0, "Apolar", 1.88], [227, 0, "Apolar", 1.61], + [228, 1, "Polar", 1.42], [229, 0, "Apolar", 1.88], + [230, 0, "Apolar", 1.88], [231, 0, "Apolar", 1.88], + [232, 0, "Apolar", 1.88], [233, 1, "Polar", 1.64], + [234, 0, "Apolar", 1.88], [235, 0, "Apolar", 1.61], + [236, 1, "Polar", 1.42], [237, 0, "Apolar", 1.88], + [238, 0, "Apolar", 1.88], [239, 0, "Apolar", 1.61], + [240, 1, "Polar", 1.42], [241, 1, "Polar", 1.64], + [242, 1, "Polar", 1.64], [243, 0, "Apolar", 1.88], + [244, 0, "Apolar", 1.61], [245, 1, "Polar", 1.42], + [246, 0, "Apolar", 1.88], [247, 0, "Apolar", 1.61], + [248, 1, "Polar", 1.42], [249, 1, "Polar", 1.46], + [250, 1, "Polar", 1.64], [251, 0, "Apolar", 1.88], + [252, 0, "Apolar", 1.61], [253, 1, "Polar", 1.42], + [254, 0, "Apolar", 1.88], [255, 0, "Apolar", 1.88], + [256, 0, "Apolar", 1.88], [257, 0, "Apolar", 1.88], + [258, 1, "Polar", 1.64], [259, 1, "Polar", 1.64], + [260, 0, "Apolar", 1.88], [261, 0, "Apolar", 1.61], + [262, 1, "Polar", 1.42], [263, 0, "Apolar", 1.88], + [264, 0, "Apolar", 1.88], [265, 0, "Apolar", 1.61], + [266, 1, "Polar", 1.42], [267, 1, "Polar", 1.46], + [268, 1, "Polar", 1.64], [269, 0, "Apolar", 1.88], + [270, 0, "Apolar", 1.61], [271, 1, "Polar", 1.42], + [272, 1, "Polar", 1.64], [273, 0, "Apolar", 1.88], + [274, 0, "Apolar", 1.61], [275, 1, "Polar", 1.42], + [276, 0, "Apolar", 1.88], [277, 0, "Apolar", 1.88], + [278, 0, "Apolar", 1.88], [279, 0, "Apolar", 1.88], + [280, 1, "Polar", 1.64], [281, 0, "Apolar", 1.88], + [282, 0, "Apolar", 1.61], [283, 1, "Polar", 1.42], + [284, 0, "Apolar", 1.88], [285, 0, "Apolar", 1.88], + [286, 0, "Apolar", 1.88], [287, 1, "Polar", 1.64], + [288, 0, "Apolar", 1.88], [289, 0, "Apolar", 1.61], + [290, 1, "Polar", 1.42], [291, 0, "Apolar", 1.88], + [292, 0, "Apolar", 1.88], [293, 0, "Apolar", 1.88], + [294, 1, "Polar", 1.64], [295, 0, "Apolar", 1.88], + [296, 0, "Apolar", 1.61], [297, 1, "Polar", 1.42], + [298, 0, "Apolar", 1.88], [299, 0, "Apolar", 1.61], + [300, 1, "Polar", 1.42], [301, 1, "Polar", 1.46], + [302, 1, "Polar", 1.64], [303, 0, "Apolar", 1.88], + [304, 0, "Apolar", 1.61], [305, 1, "Polar", 1.42], + [306, 0, "Apolar", 1.88], [307, 0, "Apolar", 1.88], + [308, 0, "Apolar", 1.61], [309, 1, "Polar", 1.42], + [310, 1, "Polar", 1.64], [311, 1, "Polar", 1.64], + [312, 0, "Apolar", 1.88], [313, 0, "Apolar", 1.61], + [314, 1, "Polar", 1.42], [315, 0, "Apolar", 1.88], + [316, 0, "Apolar", 1.88], [317, 0, "Apolar", 1.61], + [318, 1, "Polar", 1.42], [319, 1, "Polar", 1.64], + [320, 1, "Polar", 1.64], [321, 0, "Apolar", 1.88], + [322, 0, "Apolar", 1.61], [323, 1, "Polar", 1.42], + [324, 0, "Apolar", 1.88], [325, 0, "Apolar", 1.88], + [326, 0, "Apolar", 1.88], [327, 1, "Polar", 1.64], + [328, 0, "Apolar", 1.61], [329, 1, "Polar", 1.64], + [330, 1, "Polar", 1.64], [331, 1, "Polar", 1.64], + [332, 0, "Apolar", 1.88], [333, 0, "Apolar", 1.61], + [334, 1, "Polar", 1.42], [335, 0, "Apolar", 1.88], + [336, 0, "Apolar", 1.88], [337, 0, "Apolar", 1.88], + [338, 0, "Apolar", 1.88], [339, 1, "Polar", 1.64], + [340, 0, "Apolar", 1.88], [341, 0, "Apolar", 1.61], + [342, 1, "Polar", 1.42], [343, 0, "Apolar", 1.88], + [344, 0, "Apolar", 1.88], [345, 0, "Apolar", 1.88], + [346, 0, "Apolar", 1.88], [347, 1, "Polar", 1.64], + [348, 0, "Apolar", 1.88], [349, 0, "Apolar", 1.61], + [350, 1, "Polar", 1.42], [351, 0, "Apolar", 1.88], + [352, 0, "Apolar", 1.61], [353, 0, "Apolar", 1.76], + [354, 0, "Apolar", 1.76], [355, 0, "Apolar", 1.76], + [356, 0, "Apolar", 1.76], [357, 0, "Apolar", 1.76], + [358, 1, "Polar", 1.64], [359, 0, "Apolar", 1.88], + [360, 0, "Apolar", 1.61], [361, 1, "Polar", 1.42], + [362, 0, "Apolar", 1.88], [363, 1, "Polar", 1.64], + [364, 0, "Apolar", 1.88], [365, 0, "Apolar", 1.61], + [366, 1, "Polar", 1.42], [367, 1, "Polar", 1.64], + [368, 0, "Apolar", 1.88], [369, 0, "Apolar", 1.61], + [370, 1, "Polar", 1.42], [371, 0, "Apolar", 1.88], + [372, 0, "Apolar", 1.88], [373, 0, "Apolar", 1.88], + [374, 0, "Apolar", 1.88], [375, 1, "Polar", 1.64], + [376, 1, "Polar", 1.64], [377, 0, "Apolar", 1.88], + [378, 0, "Apolar", 1.61], [379, 1, "Polar", 1.42], + [380, 0, "Apolar", 1.88], [381, 0, "Apolar", 1.88], + [382, 0, "Apolar", 1.61], [383, 1, "Polar", 1.42], + [384, 1, "Polar", 1.64], [385, 1, "Polar", 1.64], + [386, 0, "Apolar", 1.88], [387, 0, "Apolar", 1.61], + [388, 1, "Polar", 1.42], [389, 0, "Apolar", 1.88], + [390, 0, "Apolar", 1.88], [391, 0, "Apolar", 1.88], + [392, 0, "Apolar", 1.88], [393, 1, "Polar", 1.64], + [394, 0, "Apolar", 1.88], [395, 0, "Apolar", 1.61], + [396, 1, "Polar", 1.42], [397, 0, "Apolar", 1.88], + [398, 0, "Apolar", 1.88], [399, 0, "Apolar", 1.61], + [400, 1, "Polar", 1.42], [401, 1, "Polar", 1.46], + [402, 1, "Polar", 1.64], [403, 0, "Apolar", 1.88], + [404, 0, "Apolar", 1.61], [405, 1, "Polar", 1.42], + [406, 0, "Apolar", 1.88], [407, 0, "Apolar", 1.61], + [408, 1, "Polar", 1.42], [409, 1, "Polar", 1.46], + [410, 1, "Polar", 1.64], [411, 0, "Apolar", 1.88], + [412, 0, "Apolar", 1.61], [413, 1, "Polar", 1.42], + [414, 1, "Polar", 1.64], [415, 0, "Apolar", 1.88], + [416, 0, "Apolar", 1.61], [417, 1, "Polar", 1.42], + [418, 0, "Apolar", 1.88], [419, 0, "Apolar", 1.88], + [420, 0, "Apolar", 1.88], [421, 1, "Polar", 1.64], + [422, 0, "Apolar", 1.61], [423, 1, "Polar", 1.64], + [424, 1, "Polar", 1.64], [425, 1, "Polar", 1.64], + [426, 0, "Apolar", 1.88], [427, 0, "Apolar", 1.61], + [428, 1, "Polar", 1.42], [429, 0, "Apolar", 1.88], + [430, 1, "Polar", 1.46], [431, 0, "Apolar", 1.88], + [432, 1, "Polar", 1.64], [433, 0, "Apolar", 1.88], + [434, 0, "Apolar", 1.61], [435, 1, "Polar", 1.42], + [436, 0, "Apolar", 1.88], [437, 0, "Apolar", 1.88], + [438, 0, "Apolar", 1.88], [439, 0, "Apolar", 1.88], + [440, 1, "Polar", 1.64], [441, 0, "Apolar", 1.88], + [442, 0, "Apolar", 1.61], [443, 1, "Polar", 1.42], + [444, 0, "Apolar", 1.88], [445, 1, "Polar", 1.46], + [446, 1, "Polar", 1.64], [447, 0, "Apolar", 1.88], + [448, 0, "Apolar", 1.61], [449, 1, "Polar", 1.42], + [450, 0, "Apolar", 1.88], [451, 0, "Apolar", 1.61], + [452, 1, "Polar", 1.42], [453, 1, "Polar", 1.46], + [454, 1, "Polar", 1.64], [455, 0, "Apolar", 1.88], + [456, 0, "Apolar", 1.61], [457, 1, "Polar", 1.42], + [458, 0, "Apolar", 1.88], [459, 0, "Apolar", 1.61], + [460, 0, "Apolar", 1.76], [461, 0, "Apolar", 1.76], + [462, 0, "Apolar", 1.76], [463, 0, "Apolar", 1.76], + [464, 0, "Apolar", 1.61], [465, 1, "Polar", 1.46], + [466, 1, "Polar", 1.64], [467, 0, "Apolar", 1.88], + [468, 0, "Apolar", 1.61], [469, 1, "Polar", 1.42], + [470, 0, "Apolar", 1.88], [471, 0, "Apolar", 1.61], + [472, 1, "Polar", 1.42], [473, 1, "Polar", 1.64], + [474, 1, "Polar", 1.64], [475, 0, "Apolar", 1.88], + [476, 0, "Apolar", 1.61], [477, 1, "Polar", 1.42], + [478, 0, "Apolar", 1.88], [479, 0, "Apolar", 1.88], + [480, 0, "Apolar", 1.88], [481, 0, "Apolar", 1.88], + [482, 1, "Polar", 1.64], [483, 0, "Apolar", 1.88], + [484, 0, "Apolar", 1.61], [485, 1, "Polar", 1.42], + [486, 0, "Apolar", 1.88], [487, 0, "Apolar", 1.88], + [488, 0, "Apolar", 1.61], [489, 1, "Polar", 1.42], + [490, 1, "Polar", 1.64], [491, 1, "Polar", 1.64], + [492, 0, "Apolar", 1.88], [493, 0, "Apolar", 1.61], + [494, 1, "Polar", 1.42], [495, 0, "Apolar", 1.88], + [496, 0, "Apolar", 1.88], [497, 0, "Apolar", 1.88], + [498, 0, "Apolar", 1.88], [499, 1, "Polar", 1.64], + [500, 1, "Polar", 1.64], [501, 0, "Apolar", 1.88], + [502, 0, "Apolar", 1.61], [503, 1, "Polar", 1.42], + [504, 0, "Apolar", 1.88], [505, 0, "Apolar", 1.88], + [506, 0, "Apolar", 1.61], [507, 1, "Polar", 1.42], + [508, 1, "Polar", 1.46], [509, 1, "Polar", 1.64], + [510, 0, "Apolar", 1.88], [511, 0, "Apolar", 1.61], + [512, 1, "Polar", 1.42], [513, 0, "Apolar", 1.88], + [514, 1, "Polar", 1.46], [515, 1, "Polar", 1.64], + [516, 0, "Apolar", 1.88], [517, 0, "Apolar", 1.61], + [518, 1, "Polar", 1.42], [519, 0, "Apolar", 1.88], + [520, 1, "Polar", 1.46], [521, 0, "Apolar", 1.88], + [522, 1, "Polar", 1.64], [523, 0, "Apolar", 1.88], + [524, 0, "Apolar", 1.61], [525, 1, "Polar", 1.42], + [526, 0, "Apolar", 1.88], [527, 0, "Apolar", 1.88], + [528, 0, "Apolar", 1.88], [529, 0, "Apolar", 1.88], + [530, 1, "Polar", 1.64], [531, 0, "Apolar", 1.88], + [532, 0, "Apolar", 1.61], [533, 1, "Polar", 1.42], + [534, 0, "Apolar", 1.88], [535, 0, "Apolar", 1.61], + [536, 1, "Polar", 1.64], [537, 0, "Apolar", 1.76], + [538, 0, "Apolar", 1.76], [539, 1, "Polar", 1.64], + [540, 1, "Polar", 1.64], [541, 0, "Apolar", 1.88], + [542, 0, "Apolar", 1.61], [543, 1, "Polar", 1.42], + [544, 0, "Apolar", 1.88], [545, 0, "Apolar", 1.88], + [546, 0, "Apolar", 1.88], [547, 0, "Apolar", 1.88], + [548, 1, "Polar", 1.64], [549, 0, "Apolar", 1.88], + [550, 0, "Apolar", 1.61], [551, 1, "Polar", 1.42], + [552, 0, "Apolar", 1.88], [553, 0, "Apolar", 1.88], + [554, 0, "Apolar", 1.88], [555, 1, "Polar", 1.64], + [556, 0, "Apolar", 1.88], [557, 0, "Apolar", 1.61], + [558, 1, "Polar", 1.42], [559, 0, "Apolar", 1.88], + [560, 0, "Apolar", 1.88], [561, 0, "Apolar", 1.88], + [562, 0, "Apolar", 1.88], [563, 1, "Polar", 1.64], + [564, 0, "Apolar", 1.88], [565, 0, "Apolar", 1.61], + [566, 1, "Polar", 1.42], [567, 0, "Apolar", 1.88], + [568, 0, "Apolar", 1.88], [569, 0, "Apolar", 1.88], + [570, 1, "Polar", 1.64], [571, 0, "Apolar", 1.61], + [572, 1, "Polar", 1.64], [573, 1, "Polar", 1.64], + [574, 1, "Polar", 1.64], [575, 0, "Apolar", 1.88], + [576, 0, "Apolar", 1.61], [577, 1, "Polar", 1.42], + [578, 0, "Apolar", 1.88], [579, 0, "Apolar", 1.88], + [580, 0, "Apolar", 1.88], [581, 0, "Apolar", 1.88], + [582, 1, "Polar", 1.64], [583, 0, "Apolar", 1.88], + [584, 0, "Apolar", 1.61], [585, 1, "Polar", 1.42], + [586, 0, "Apolar", 1.88], [587, 0, "Apolar", 1.88], + [588, 0, "Apolar", 1.88], [589, 1, "Polar", 1.64], + [590, 0, "Apolar", 1.61], [591, 1, "Polar", 1.64], + [592, 1, "Polar", 1.64], [593, 1, "Polar", 1.64], + [594, 0, "Apolar", 1.88], [595, 0, "Apolar", 1.61], + [596, 1, "Polar", 1.42], [597, 1, "Polar", 1.64], + [598, 0, "Apolar", 1.88], [599, 0, "Apolar", 1.61], + [600, 1, "Polar", 1.42], [601, 1, "Polar", 1.46] + ] + +class TestCase(unittest.TestCase) : + def test_basics(self): + fname = os.path.join(os.environ["RDBASE"], + "External", "FreeSASA", "freesasa-master", "tests", "data", "1d3z.pdb") + mol = Chem.MolFromPDBFile(fname) + radii = rdFreeSASA.classifyAtoms(mol) + for atom in mol.GetAtoms(): + self.assertEqual( expected[atom.GetIdx()][3], radii[atom.GetIdx()] ) + leeRichards = 5004.79964427 + shrakerupley = 5000.340175 + + sasa = rdFreeSASA.CalcSASA(mol, radii=radii) + self.assertTrue( (sasa-leeRichards) < 1e-5 ) + + opts = rdFreeSASA.SASAOpts(rdFreeSASA.ShrakeRupley, rdFreeSASA.Protor) + sasa = rdFreeSASA.CalcSASA(mol, radii=radii, opts=opts) + self.assertTrue( (sasa-shrakerupley) < 1e-5 ) + + apolar = rdFreeSASA.CalcSASA(mol, radii, query=rdFreeSASA.MakeFreeSasaAPolarAtomQuery(), opts=opts); + polar = rdFreeSASA.CalcSASA(mol, radii, query=rdFreeSASA.MakeFreeSasaPolarAtomQuery(), opts=opts); + + self.assertTrue( (polar + apolar - 5000.340175) < 1e-5 ) + + def test_opts(self): + fname = os.path.join(os.environ["RDBASE"], + "External", "FreeSASA", "freesasa-master", "tests", "data", "1d3z.pdb") + mol = Chem.MolFromPDBFile(fname) + radii = rdFreeSASA.classifyAtoms(mol) + for atom in mol.GetAtoms(): + self.assertEqual( expected[atom.GetIdx()][3], radii[atom.GetIdx()] ) + leeRichards = 5004.79964427 + shrakerupley = 5000.340175 + opts = rdFreeSASA.SASAOpts() + for alg, res in ( (rdFreeSASA.ShrakeRupley, shrakerupley), + (rdFreeSASA.LeeRichards, leeRichards)): + opts.algorithm = alg + sasa = rdFreeSASA.CalcSASA(mol, radii=radii, opts=opts) + self.assertTrue( abs(sasa-res) < 1e-5 ) + + +if __name__ == '__main__': + unittest.main() diff --git a/External/FreeSASA/freesasa2.c b/External/FreeSASA/freesasa2.c new file mode 100644 index 000000000..f4be418cd --- /dev/null +++ b/External/FreeSASA/freesasa2.c @@ -0,0 +1,259 @@ +/** + This source file contains everything that is in freesasa.h + interface and does not have a natural home in any of the other + source files. + */ + +#if HAVE_CONFIG_H +# include +#endif +#include +#include +#include + +#include "freesasa_internal.h" + +#ifdef PACKAGE_VERSION +const char *freesasa_version = PACKAGE_VERSION; +#else +const char *freesasa_version = ""; +#endif + +#ifdef PACKAGE_STRING +const char *freesasa_string = PACKAGE_STRING; +#else +const char *freesasa_string = "FreeSASA"; +#endif + +// Allows compilation with different defaults +// depending on USE_THREADS. but still exposing the value in a header +// that doesn't depend on USE_THREADS +#ifdef USE_THREADS +#define DEF_NUMBER_THREADS 2 +#else +#define DEF_NUMBER_THREADS 1 +#endif +const int FREESASA_DEF_NUMBER_THREADS = DEF_NUMBER_THREADS; + +const freesasa_parameters freesasa_default_parameters = { + .alg = FREESASA_DEF_ALGORITHM, + .probe_radius = FREESASA_DEF_PROBE_RADIUS, + .shrake_rupley_n_points = FREESASA_DEF_SR_N, + .lee_richards_n_slices = FREESASA_DEF_LR_N, + .n_threads = DEF_NUMBER_THREADS, +}; + +static freesasa_result * +result_new(int n) +{ + freesasa_result *result = malloc(sizeof(freesasa_result)); + + if (result == NULL) { + mem_fail(); + return NULL; + } + + result->sasa = malloc(sizeof(double) * n); + + if (result->sasa == NULL) { + mem_fail(); + freesasa_result_free(result); + return NULL; + } + + result->n_atoms = n; + + return result; +} + +void +freesasa_result_free(freesasa_result *r) +{ + if (r) { + free(r->sasa); + free(r); + } +} + +freesasa_result* +freesasa_calc(const coord_t *c, + const double *radii, + const freesasa_parameters *parameters) + +{ + assert(c); + assert(radii); + + freesasa_result *result = result_new(freesasa_coord_n(c)); + int ret; + + if (result == NULL) { + fail_msg(""); + return NULL; + } + + if (parameters == NULL) parameters = &freesasa_default_parameters; + + switch(parameters->alg) { + case FREESASA_SHRAKE_RUPLEY: + ret = freesasa_shrake_rupley(result->sasa, c, radii, parameters); + break; + case FREESASA_LEE_RICHARDS: + ret = freesasa_lee_richards(result->sasa, c, radii, parameters); + break; + default: + assert(0); //should never get here + break; + } + if (ret == FREESASA_FAIL) { + freesasa_result_free(result); + return NULL; + } + + result->total = 0; + for (int i = 0; i < freesasa_coord_n(c); ++i) { + result->total += result->sasa[i]; + } + result->parameters = *parameters; + + return result; +} + +freesasa_result* +freesasa_calc_coord(const double *xyz, + const double *radii, + int n, + const freesasa_parameters *parameters) +{ + assert(xyz); + assert(radii); + assert(n > 0); + + coord_t *coord = NULL; + freesasa_result *result = NULL; + + coord = freesasa_coord_new_linked(xyz,n); + if (coord != NULL) result = freesasa_calc(coord, radii, parameters); + if (result == NULL) fail_msg(""); + + freesasa_coord_free(coord); + + return result; +} + +freesasa_result* +freesasa_calc_structure(const freesasa_structure* structure, + const freesasa_parameters* parameters) +{ + assert(structure); + + return freesasa_calc(freesasa_structure_xyz(structure), + freesasa_structure_radius(structure), + parameters); +} + +freesasa_node * +freesasa_calc_tree(const freesasa_structure *structure, + const freesasa_parameters *parameters, + const char *name) +{ + assert(structure); + + freesasa_node *tree = NULL; + freesasa_result *result = freesasa_calc(freesasa_structure_xyz(structure), + freesasa_structure_radius(structure), + parameters); + + if (result != NULL) { + tree = freesasa_tree_init(result, structure, name); + } else { + fail_msg(""); + } + + if (tree == NULL) { + fail_msg(""); + } + + freesasa_result_free(result); + + return tree; +} + +static inline void +count_err(int return_value, int *n_err) +{ + if (return_value == FREESASA_FAIL) { + (*n_err)++; + } +} + +int +freesasa_tree_export(FILE *file, + freesasa_node *root, + int options) +{ + assert(freesasa_node_type(root) == FREESASA_NODE_ROOT); + int n_err = 0; + if (options & FREESASA_LOG) { + count_err(freesasa_write_log(file, root), &n_err); + } + if (options & FREESASA_RES) { + count_err(freesasa_write_res(file, root), &n_err); + } + if (options & FREESASA_SEQ) { + count_err(freesasa_write_seq(file, root), &n_err); + } + if (options & FREESASA_PDB) { + count_err(freesasa_write_pdb(file, root), &n_err); + } + if (options & FREESASA_RSA) { + count_err(freesasa_write_rsa(file, root, options), &n_err); + } + if (options & FREESASA_JSON) { +#if USE_JSON + count_err(freesasa_write_json(file, root, options), &n_err); +#else + return fail_msg("library was built without support for JSON output"); +#endif + } + if (options & FREESASA_XML) { +#if USE_XML + count_err(freesasa_write_xml(file, root, options), &n_err); +#else + return fail_msg("library was built without support for XML output"); +#endif + } + if (n_err > 0) { + return fail_msg("there were errors when writing output"); + } + return FREESASA_SUCCESS; +} + +freesasa_result * +freesasa_result_clone(const freesasa_result *result) +{ + freesasa_result *clone = result_new(result->n_atoms); + if (clone == NULL) { + fail_msg(""); + return NULL; + } + + clone->n_atoms = result->n_atoms; + clone->total = result->total; + clone->parameters = result->parameters; + memcpy(clone->sasa, result->sasa, sizeof(double) * clone->n_atoms); + + return clone; +} + +const char* +freesasa_alg_name(freesasa_algorithm alg) +{ + switch(alg) { + case FREESASA_SHRAKE_RUPLEY: + return "Shrake & Rupley"; + case FREESASA_LEE_RICHARDS: + return "Lee & Richards"; + } + assert(0 && "Illegal algorithm"); +} diff --git a/External/FreeSASA/getline.c b/External/FreeSASA/getline.c new file mode 100644 index 000000000..10f96b372 --- /dev/null +++ b/External/FreeSASA/getline.c @@ -0,0 +1,15 @@ +#include +#include +#include +#include + +int +getline (lineptr, n, stream) + char **lineptr; + size_t *n; + FILE *stream; +{ + // do nothing implementation + // we don't use these functionalities of freesasa + return 0; +} diff --git a/External/FreeSASA/testFreeSASA.cpp b/External/FreeSASA/testFreeSASA.cpp new file mode 100644 index 000000000..682ee1f26 --- /dev/null +++ b/External/FreeSASA/testFreeSASA.cpp @@ -0,0 +1,414 @@ +// Copyright (c) 2016, Novartis Institutes for BioMedical Research Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Novartis Institutes for BioMedical Research Inc. +// nor the names of its contributors may be used to endorse or promote +// products derived from this software without specific prior written +// permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +#include "RDFreeSASA.h" + +#include +#include +#include + +using namespace RDKit; + +struct ExpectedClasses { + unsigned int idx; + int cls; + const char *clsname; + double radius; +}; + +ExpectedClasses ExpectedProtor1d3z[] = { + {0, 1, "Polar", 1.64}, {1, 0, "Apolar", 1.88}, + {2, 0, "Apolar", 1.61}, {3, 1, "Polar", 1.42}, + {4, 0, "Apolar", 1.88}, {5, 0, "Apolar", 1.88}, + {6, 1, "Polar", 1.77}, {7, 0, "Apolar", 1.88}, + {8, 1, "Polar", 1.64}, {9, 0, "Apolar", 1.88}, + {10, 0, "Apolar", 1.61}, {11, 1, "Polar", 1.42}, + {12, 0, "Apolar", 1.88}, {13, 0, "Apolar", 1.88}, + {14, 0, "Apolar", 1.61}, {15, 1, "Polar", 1.42}, + {16, 1, "Polar", 1.64}, {17, 1, "Polar", 1.64}, + {18, 0, "Apolar", 1.88}, {19, 0, "Apolar", 1.61}, + {20, 1, "Polar", 1.42}, {21, 0, "Apolar", 1.88}, + {22, 0, "Apolar", 1.88}, {23, 0, "Apolar", 1.88}, + {24, 0, "Apolar", 1.88}, {25, 1, "Polar", 1.64}, + {26, 0, "Apolar", 1.88}, {27, 0, "Apolar", 1.61}, + {28, 1, "Polar", 1.42}, {29, 0, "Apolar", 1.88}, + {30, 0, "Apolar", 1.61}, {31, 0, "Apolar", 1.76}, + {32, 0, "Apolar", 1.76}, {33, 0, "Apolar", 1.76}, + {34, 0, "Apolar", 1.76}, {35, 0, "Apolar", 1.76}, + {36, 1, "Polar", 1.64}, {37, 0, "Apolar", 1.88}, + {38, 0, "Apolar", 1.61}, {39, 1, "Polar", 1.42}, + {40, 0, "Apolar", 1.88}, {41, 0, "Apolar", 1.88}, + {42, 0, "Apolar", 1.88}, {43, 1, "Polar", 1.64}, + {44, 0, "Apolar", 1.88}, {45, 0, "Apolar", 1.61}, + {46, 1, "Polar", 1.42}, {47, 0, "Apolar", 1.88}, + {48, 0, "Apolar", 1.88}, {49, 0, "Apolar", 1.88}, + {50, 0, "Apolar", 1.88}, {51, 1, "Polar", 1.64}, + {52, 1, "Polar", 1.64}, {53, 0, "Apolar", 1.88}, + {54, 0, "Apolar", 1.61}, {55, 1, "Polar", 1.42}, + {56, 0, "Apolar", 1.88}, {57, 1, "Polar", 1.46}, + {58, 0, "Apolar", 1.88}, {59, 1, "Polar", 1.64}, + {60, 0, "Apolar", 1.88}, {61, 0, "Apolar", 1.61}, + {62, 1, "Polar", 1.42}, {63, 0, "Apolar", 1.88}, + {64, 0, "Apolar", 1.88}, {65, 0, "Apolar", 1.88}, + {66, 0, "Apolar", 1.88}, {67, 1, "Polar", 1.64}, + {68, 0, "Apolar", 1.88}, {69, 0, "Apolar", 1.61}, + {70, 1, "Polar", 1.42}, {71, 0, "Apolar", 1.88}, + {72, 1, "Polar", 1.46}, {73, 0, "Apolar", 1.88}, + {74, 1, "Polar", 1.64}, {75, 0, "Apolar", 1.88}, + {76, 0, "Apolar", 1.61}, {77, 1, "Polar", 1.42}, + {78, 1, "Polar", 1.64}, {79, 0, "Apolar", 1.88}, + {80, 0, "Apolar", 1.61}, {81, 1, "Polar", 1.42}, + {82, 0, "Apolar", 1.88}, {83, 0, "Apolar", 1.88}, + {84, 0, "Apolar", 1.88}, {85, 0, "Apolar", 1.88}, + {86, 1, "Polar", 1.64}, {87, 1, "Polar", 1.64}, + {88, 0, "Apolar", 1.88}, {89, 0, "Apolar", 1.61}, + {90, 1, "Polar", 1.42}, {91, 0, "Apolar", 1.88}, + {92, 1, "Polar", 1.46}, {93, 0, "Apolar", 1.88}, + {94, 1, "Polar", 1.64}, {95, 0, "Apolar", 1.88}, + {96, 0, "Apolar", 1.61}, {97, 1, "Polar", 1.42}, + {98, 0, "Apolar", 1.88}, {99, 0, "Apolar", 1.88}, + {100, 0, "Apolar", 1.88}, {101, 0, "Apolar", 1.88}, + {102, 1, "Polar", 1.64}, {103, 0, "Apolar", 1.88}, + {104, 0, "Apolar", 1.61}, {105, 1, "Polar", 1.42}, + {106, 0, "Apolar", 1.88}, {107, 1, "Polar", 1.46}, + {108, 0, "Apolar", 1.88}, {109, 1, "Polar", 1.64}, + {110, 0, "Apolar", 1.88}, {111, 0, "Apolar", 1.61}, + {112, 1, "Polar", 1.42}, {113, 0, "Apolar", 1.88}, + {114, 0, "Apolar", 1.88}, {115, 0, "Apolar", 1.88}, + {116, 0, "Apolar", 1.88}, {117, 1, "Polar", 1.64}, + {118, 0, "Apolar", 1.88}, {119, 0, "Apolar", 1.61}, + {120, 1, "Polar", 1.42}, {121, 0, "Apolar", 1.88}, + {122, 0, "Apolar", 1.88}, {123, 0, "Apolar", 1.61}, + {124, 1, "Polar", 1.42}, {125, 1, "Polar", 1.46}, + {126, 1, "Polar", 1.64}, {127, 0, "Apolar", 1.88}, + {128, 0, "Apolar", 1.61}, {129, 1, "Polar", 1.42}, + {130, 0, "Apolar", 1.88}, {131, 0, "Apolar", 1.88}, + {132, 0, "Apolar", 1.88}, {133, 1, "Polar", 1.64}, + {134, 0, "Apolar", 1.88}, {135, 0, "Apolar", 1.61}, + {136, 1, "Polar", 1.42}, {137, 0, "Apolar", 1.88}, + {138, 0, "Apolar", 1.88}, {139, 0, "Apolar", 1.61}, + {140, 1, "Polar", 1.42}, {141, 1, "Polar", 1.46}, + {142, 1, "Polar", 1.64}, {143, 0, "Apolar", 1.88}, + {144, 0, "Apolar", 1.61}, {145, 1, "Polar", 1.42}, + {146, 0, "Apolar", 1.88}, {147, 0, "Apolar", 1.88}, + {148, 0, "Apolar", 1.88}, {149, 1, "Polar", 1.64}, + {150, 0, "Apolar", 1.88}, {151, 0, "Apolar", 1.61}, + {152, 1, "Polar", 1.42}, {153, 0, "Apolar", 1.88}, + {154, 1, "Polar", 1.46}, {155, 1, "Polar", 1.64}, + {156, 0, "Apolar", 1.88}, {157, 0, "Apolar", 1.61}, + {158, 1, "Polar", 1.42}, {159, 0, "Apolar", 1.88}, + {160, 0, "Apolar", 1.61}, {161, 1, "Polar", 1.42}, + {162, 1, "Polar", 1.46}, {163, 1, "Polar", 1.64}, + {164, 0, "Apolar", 1.88}, {165, 0, "Apolar", 1.61}, + {166, 1, "Polar", 1.42}, {167, 0, "Apolar", 1.88}, + {168, 1, "Polar", 1.46}, {169, 0, "Apolar", 1.88}, + {170, 1, "Polar", 1.64}, {171, 0, "Apolar", 1.88}, + {172, 0, "Apolar", 1.61}, {173, 1, "Polar", 1.42}, + {174, 0, "Apolar", 1.88}, {175, 0, "Apolar", 1.88}, + {176, 0, "Apolar", 1.88}, {177, 0, "Apolar", 1.88}, + {178, 1, "Polar", 1.64}, {179, 0, "Apolar", 1.88}, + {180, 0, "Apolar", 1.61}, {181, 1, "Polar", 1.42}, + {182, 0, "Apolar", 1.88}, {183, 0, "Apolar", 1.88}, + {184, 0, "Apolar", 1.61}, {185, 1, "Polar", 1.42}, + {186, 1, "Polar", 1.46}, {187, 1, "Polar", 1.64}, + {188, 0, "Apolar", 1.88}, {189, 0, "Apolar", 1.61}, + {190, 1, "Polar", 1.42}, {191, 0, "Apolar", 1.88}, + {192, 0, "Apolar", 1.61}, {193, 1, "Polar", 1.42}, + {194, 1, "Polar", 1.64}, {195, 1, "Polar", 1.64}, + {196, 0, "Apolar", 1.88}, {197, 0, "Apolar", 1.61}, + {198, 1, "Polar", 1.42}, {199, 0, "Apolar", 1.88}, + {200, 0, "Apolar", 1.88}, {201, 0, "Apolar", 1.88}, + {202, 1, "Polar", 1.64}, {203, 0, "Apolar", 1.88}, + {204, 0, "Apolar", 1.61}, {205, 1, "Polar", 1.42}, + {206, 0, "Apolar", 1.88}, {207, 0, "Apolar", 1.88}, + {208, 0, "Apolar", 1.88}, {209, 0, "Apolar", 1.88}, + {210, 1, "Polar", 1.64}, {211, 1, "Polar", 1.64}, + {212, 0, "Apolar", 1.88}, {213, 0, "Apolar", 1.61}, + {214, 1, "Polar", 1.42}, {215, 0, "Apolar", 1.88}, + {216, 1, "Polar", 1.64}, {217, 0, "Apolar", 1.88}, + {218, 0, "Apolar", 1.61}, {219, 1, "Polar", 1.42}, + {220, 0, "Apolar", 1.88}, {221, 0, "Apolar", 1.88}, + {222, 0, "Apolar", 1.88}, {223, 0, "Apolar", 1.88}, + {224, 1, "Polar", 1.64}, {225, 1, "Polar", 1.64}, + {226, 0, "Apolar", 1.88}, {227, 0, "Apolar", 1.61}, + {228, 1, "Polar", 1.42}, {229, 0, "Apolar", 1.88}, + {230, 0, "Apolar", 1.88}, {231, 0, "Apolar", 1.88}, + {232, 0, "Apolar", 1.88}, {233, 1, "Polar", 1.64}, + {234, 0, "Apolar", 1.88}, {235, 0, "Apolar", 1.61}, + {236, 1, "Polar", 1.42}, {237, 0, "Apolar", 1.88}, + {238, 0, "Apolar", 1.88}, {239, 0, "Apolar", 1.61}, + {240, 1, "Polar", 1.42}, {241, 1, "Polar", 1.64}, + {242, 1, "Polar", 1.64}, {243, 0, "Apolar", 1.88}, + {244, 0, "Apolar", 1.61}, {245, 1, "Polar", 1.42}, + {246, 0, "Apolar", 1.88}, {247, 0, "Apolar", 1.61}, + {248, 1, "Polar", 1.42}, {249, 1, "Polar", 1.46}, + {250, 1, "Polar", 1.64}, {251, 0, "Apolar", 1.88}, + {252, 0, "Apolar", 1.61}, {253, 1, "Polar", 1.42}, + {254, 0, "Apolar", 1.88}, {255, 0, "Apolar", 1.88}, + {256, 0, "Apolar", 1.88}, {257, 0, "Apolar", 1.88}, + {258, 1, "Polar", 1.64}, {259, 1, "Polar", 1.64}, + {260, 0, "Apolar", 1.88}, {261, 0, "Apolar", 1.61}, + {262, 1, "Polar", 1.42}, {263, 0, "Apolar", 1.88}, + {264, 0, "Apolar", 1.88}, {265, 0, "Apolar", 1.61}, + {266, 1, "Polar", 1.42}, {267, 1, "Polar", 1.46}, + {268, 1, "Polar", 1.64}, {269, 0, "Apolar", 1.88}, + {270, 0, "Apolar", 1.61}, {271, 1, "Polar", 1.42}, + {272, 1, "Polar", 1.64}, {273, 0, "Apolar", 1.88}, + {274, 0, "Apolar", 1.61}, {275, 1, "Polar", 1.42}, + {276, 0, "Apolar", 1.88}, {277, 0, "Apolar", 1.88}, + {278, 0, "Apolar", 1.88}, {279, 0, "Apolar", 1.88}, + {280, 1, "Polar", 1.64}, {281, 0, "Apolar", 1.88}, + {282, 0, "Apolar", 1.61}, {283, 1, "Polar", 1.42}, + {284, 0, "Apolar", 1.88}, {285, 0, "Apolar", 1.88}, + {286, 0, "Apolar", 1.88}, {287, 1, "Polar", 1.64}, + {288, 0, "Apolar", 1.88}, {289, 0, "Apolar", 1.61}, + {290, 1, "Polar", 1.42}, {291, 0, "Apolar", 1.88}, + {292, 0, "Apolar", 1.88}, {293, 0, "Apolar", 1.88}, + {294, 1, "Polar", 1.64}, {295, 0, "Apolar", 1.88}, + {296, 0, "Apolar", 1.61}, {297, 1, "Polar", 1.42}, + {298, 0, "Apolar", 1.88}, {299, 0, "Apolar", 1.61}, + {300, 1, "Polar", 1.42}, {301, 1, "Polar", 1.46}, + {302, 1, "Polar", 1.64}, {303, 0, "Apolar", 1.88}, + {304, 0, "Apolar", 1.61}, {305, 1, "Polar", 1.42}, + {306, 0, "Apolar", 1.88}, {307, 0, "Apolar", 1.88}, + {308, 0, "Apolar", 1.61}, {309, 1, "Polar", 1.42}, + {310, 1, "Polar", 1.64}, {311, 1, "Polar", 1.64}, + {312, 0, "Apolar", 1.88}, {313, 0, "Apolar", 1.61}, + {314, 1, "Polar", 1.42}, {315, 0, "Apolar", 1.88}, + {316, 0, "Apolar", 1.88}, {317, 0, "Apolar", 1.61}, + {318, 1, "Polar", 1.42}, {319, 1, "Polar", 1.64}, + {320, 1, "Polar", 1.64}, {321, 0, "Apolar", 1.88}, + {322, 0, "Apolar", 1.61}, {323, 1, "Polar", 1.42}, + {324, 0, "Apolar", 1.88}, {325, 0, "Apolar", 1.88}, + {326, 0, "Apolar", 1.88}, {327, 1, "Polar", 1.64}, + {328, 0, "Apolar", 1.61}, {329, 1, "Polar", 1.64}, + {330, 1, "Polar", 1.64}, {331, 1, "Polar", 1.64}, + {332, 0, "Apolar", 1.88}, {333, 0, "Apolar", 1.61}, + {334, 1, "Polar", 1.42}, {335, 0, "Apolar", 1.88}, + {336, 0, "Apolar", 1.88}, {337, 0, "Apolar", 1.88}, + {338, 0, "Apolar", 1.88}, {339, 1, "Polar", 1.64}, + {340, 0, "Apolar", 1.88}, {341, 0, "Apolar", 1.61}, + {342, 1, "Polar", 1.42}, {343, 0, "Apolar", 1.88}, + {344, 0, "Apolar", 1.88}, {345, 0, "Apolar", 1.88}, + {346, 0, "Apolar", 1.88}, {347, 1, "Polar", 1.64}, + {348, 0, "Apolar", 1.88}, {349, 0, "Apolar", 1.61}, + {350, 1, "Polar", 1.42}, {351, 0, "Apolar", 1.88}, + {352, 0, "Apolar", 1.61}, {353, 0, "Apolar", 1.76}, + {354, 0, "Apolar", 1.76}, {355, 0, "Apolar", 1.76}, + {356, 0, "Apolar", 1.76}, {357, 0, "Apolar", 1.76}, + {358, 1, "Polar", 1.64}, {359, 0, "Apolar", 1.88}, + {360, 0, "Apolar", 1.61}, {361, 1, "Polar", 1.42}, + {362, 0, "Apolar", 1.88}, {363, 1, "Polar", 1.64}, + {364, 0, "Apolar", 1.88}, {365, 0, "Apolar", 1.61}, + {366, 1, "Polar", 1.42}, {367, 1, "Polar", 1.64}, + {368, 0, "Apolar", 1.88}, {369, 0, "Apolar", 1.61}, + {370, 1, "Polar", 1.42}, {371, 0, "Apolar", 1.88}, + {372, 0, "Apolar", 1.88}, {373, 0, "Apolar", 1.88}, + {374, 0, "Apolar", 1.88}, {375, 1, "Polar", 1.64}, + {376, 1, "Polar", 1.64}, {377, 0, "Apolar", 1.88}, + {378, 0, "Apolar", 1.61}, {379, 1, "Polar", 1.42}, + {380, 0, "Apolar", 1.88}, {381, 0, "Apolar", 1.88}, + {382, 0, "Apolar", 1.61}, {383, 1, "Polar", 1.42}, + {384, 1, "Polar", 1.64}, {385, 1, "Polar", 1.64}, + {386, 0, "Apolar", 1.88}, {387, 0, "Apolar", 1.61}, + {388, 1, "Polar", 1.42}, {389, 0, "Apolar", 1.88}, + {390, 0, "Apolar", 1.88}, {391, 0, "Apolar", 1.88}, + {392, 0, "Apolar", 1.88}, {393, 1, "Polar", 1.64}, + {394, 0, "Apolar", 1.88}, {395, 0, "Apolar", 1.61}, + {396, 1, "Polar", 1.42}, {397, 0, "Apolar", 1.88}, + {398, 0, "Apolar", 1.88}, {399, 0, "Apolar", 1.61}, + {400, 1, "Polar", 1.42}, {401, 1, "Polar", 1.46}, + {402, 1, "Polar", 1.64}, {403, 0, "Apolar", 1.88}, + {404, 0, "Apolar", 1.61}, {405, 1, "Polar", 1.42}, + {406, 0, "Apolar", 1.88}, {407, 0, "Apolar", 1.61}, + {408, 1, "Polar", 1.42}, {409, 1, "Polar", 1.46}, + {410, 1, "Polar", 1.64}, {411, 0, "Apolar", 1.88}, + {412, 0, "Apolar", 1.61}, {413, 1, "Polar", 1.42}, + {414, 1, "Polar", 1.64}, {415, 0, "Apolar", 1.88}, + {416, 0, "Apolar", 1.61}, {417, 1, "Polar", 1.42}, + {418, 0, "Apolar", 1.88}, {419, 0, "Apolar", 1.88}, + {420, 0, "Apolar", 1.88}, {421, 1, "Polar", 1.64}, + {422, 0, "Apolar", 1.61}, {423, 1, "Polar", 1.64}, + {424, 1, "Polar", 1.64}, {425, 1, "Polar", 1.64}, + {426, 0, "Apolar", 1.88}, {427, 0, "Apolar", 1.61}, + {428, 1, "Polar", 1.42}, {429, 0, "Apolar", 1.88}, + {430, 1, "Polar", 1.46}, {431, 0, "Apolar", 1.88}, + {432, 1, "Polar", 1.64}, {433, 0, "Apolar", 1.88}, + {434, 0, "Apolar", 1.61}, {435, 1, "Polar", 1.42}, + {436, 0, "Apolar", 1.88}, {437, 0, "Apolar", 1.88}, + {438, 0, "Apolar", 1.88}, {439, 0, "Apolar", 1.88}, + {440, 1, "Polar", 1.64}, {441, 0, "Apolar", 1.88}, + {442, 0, "Apolar", 1.61}, {443, 1, "Polar", 1.42}, + {444, 0, "Apolar", 1.88}, {445, 1, "Polar", 1.46}, + {446, 1, "Polar", 1.64}, {447, 0, "Apolar", 1.88}, + {448, 0, "Apolar", 1.61}, {449, 1, "Polar", 1.42}, + {450, 0, "Apolar", 1.88}, {451, 0, "Apolar", 1.61}, + {452, 1, "Polar", 1.42}, {453, 1, "Polar", 1.46}, + {454, 1, "Polar", 1.64}, {455, 0, "Apolar", 1.88}, + {456, 0, "Apolar", 1.61}, {457, 1, "Polar", 1.42}, + {458, 0, "Apolar", 1.88}, {459, 0, "Apolar", 1.61}, + {460, 0, "Apolar", 1.76}, {461, 0, "Apolar", 1.76}, + {462, 0, "Apolar", 1.76}, {463, 0, "Apolar", 1.76}, + {464, 0, "Apolar", 1.61}, {465, 1, "Polar", 1.46}, + {466, 1, "Polar", 1.64}, {467, 0, "Apolar", 1.88}, + {468, 0, "Apolar", 1.61}, {469, 1, "Polar", 1.42}, + {470, 0, "Apolar", 1.88}, {471, 0, "Apolar", 1.61}, + {472, 1, "Polar", 1.42}, {473, 1, "Polar", 1.64}, + {474, 1, "Polar", 1.64}, {475, 0, "Apolar", 1.88}, + {476, 0, "Apolar", 1.61}, {477, 1, "Polar", 1.42}, + {478, 0, "Apolar", 1.88}, {479, 0, "Apolar", 1.88}, + {480, 0, "Apolar", 1.88}, {481, 0, "Apolar", 1.88}, + {482, 1, "Polar", 1.64}, {483, 0, "Apolar", 1.88}, + {484, 0, "Apolar", 1.61}, {485, 1, "Polar", 1.42}, + {486, 0, "Apolar", 1.88}, {487, 0, "Apolar", 1.88}, + {488, 0, "Apolar", 1.61}, {489, 1, "Polar", 1.42}, + {490, 1, "Polar", 1.64}, {491, 1, "Polar", 1.64}, + {492, 0, "Apolar", 1.88}, {493, 0, "Apolar", 1.61}, + {494, 1, "Polar", 1.42}, {495, 0, "Apolar", 1.88}, + {496, 0, "Apolar", 1.88}, {497, 0, "Apolar", 1.88}, + {498, 0, "Apolar", 1.88}, {499, 1, "Polar", 1.64}, + {500, 1, "Polar", 1.64}, {501, 0, "Apolar", 1.88}, + {502, 0, "Apolar", 1.61}, {503, 1, "Polar", 1.42}, + {504, 0, "Apolar", 1.88}, {505, 0, "Apolar", 1.88}, + {506, 0, "Apolar", 1.61}, {507, 1, "Polar", 1.42}, + {508, 1, "Polar", 1.46}, {509, 1, "Polar", 1.64}, + {510, 0, "Apolar", 1.88}, {511, 0, "Apolar", 1.61}, + {512, 1, "Polar", 1.42}, {513, 0, "Apolar", 1.88}, + {514, 1, "Polar", 1.46}, {515, 1, "Polar", 1.64}, + {516, 0, "Apolar", 1.88}, {517, 0, "Apolar", 1.61}, + {518, 1, "Polar", 1.42}, {519, 0, "Apolar", 1.88}, + {520, 1, "Polar", 1.46}, {521, 0, "Apolar", 1.88}, + {522, 1, "Polar", 1.64}, {523, 0, "Apolar", 1.88}, + {524, 0, "Apolar", 1.61}, {525, 1, "Polar", 1.42}, + {526, 0, "Apolar", 1.88}, {527, 0, "Apolar", 1.88}, + {528, 0, "Apolar", 1.88}, {529, 0, "Apolar", 1.88}, + {530, 1, "Polar", 1.64}, {531, 0, "Apolar", 1.88}, + {532, 0, "Apolar", 1.61}, {533, 1, "Polar", 1.42}, + {534, 0, "Apolar", 1.88}, {535, 0, "Apolar", 1.61}, + {536, 1, "Polar", 1.64}, {537, 0, "Apolar", 1.76}, + {538, 0, "Apolar", 1.76}, {539, 1, "Polar", 1.64}, + {540, 1, "Polar", 1.64}, {541, 0, "Apolar", 1.88}, + {542, 0, "Apolar", 1.61}, {543, 1, "Polar", 1.42}, + {544, 0, "Apolar", 1.88}, {545, 0, "Apolar", 1.88}, + {546, 0, "Apolar", 1.88}, {547, 0, "Apolar", 1.88}, + {548, 1, "Polar", 1.64}, {549, 0, "Apolar", 1.88}, + {550, 0, "Apolar", 1.61}, {551, 1, "Polar", 1.42}, + {552, 0, "Apolar", 1.88}, {553, 0, "Apolar", 1.88}, + {554, 0, "Apolar", 1.88}, {555, 1, "Polar", 1.64}, + {556, 0, "Apolar", 1.88}, {557, 0, "Apolar", 1.61}, + {558, 1, "Polar", 1.42}, {559, 0, "Apolar", 1.88}, + {560, 0, "Apolar", 1.88}, {561, 0, "Apolar", 1.88}, + {562, 0, "Apolar", 1.88}, {563, 1, "Polar", 1.64}, + {564, 0, "Apolar", 1.88}, {565, 0, "Apolar", 1.61}, + {566, 1, "Polar", 1.42}, {567, 0, "Apolar", 1.88}, + {568, 0, "Apolar", 1.88}, {569, 0, "Apolar", 1.88}, + {570, 1, "Polar", 1.64}, {571, 0, "Apolar", 1.61}, + {572, 1, "Polar", 1.64}, {573, 1, "Polar", 1.64}, + {574, 1, "Polar", 1.64}, {575, 0, "Apolar", 1.88}, + {576, 0, "Apolar", 1.61}, {577, 1, "Polar", 1.42}, + {578, 0, "Apolar", 1.88}, {579, 0, "Apolar", 1.88}, + {580, 0, "Apolar", 1.88}, {581, 0, "Apolar", 1.88}, + {582, 1, "Polar", 1.64}, {583, 0, "Apolar", 1.88}, + {584, 0, "Apolar", 1.61}, {585, 1, "Polar", 1.42}, + {586, 0, "Apolar", 1.88}, {587, 0, "Apolar", 1.88}, + {588, 0, "Apolar", 1.88}, {589, 1, "Polar", 1.64}, + {590, 0, "Apolar", 1.61}, {591, 1, "Polar", 1.64}, + {592, 1, "Polar", 1.64}, {593, 1, "Polar", 1.64}, + {594, 0, "Apolar", 1.88}, {595, 0, "Apolar", 1.61}, + {596, 1, "Polar", 1.42}, {597, 1, "Polar", 1.64}, + {598, 0, "Apolar", 1.88}, {599, 0, "Apolar", 1.61}, + {600, 1, "Polar", 1.42}, {601, 1, "Polar", 1.46}}; + +void testPDB() { + BOOST_LOG(rdInfoLog) << "-----------------------\n Testing FreeSASA basics" + << std::endl; + + std::string rdbase = getenv("RDBASE"); + std::string fName = rdbase += + "/External/FreeSASA/freesasa-master/tests/data/1d3z.pdb"; + + ROMol *m; + { + const bool sanitize=true; + const bool removeHs=true; + m = PDBFileToMol(fName, sanitize, removeHs); + } + + std::vector radii; + FreeSASA::classifyAtoms(*m, radii); + for (ROMol::AtomIterator at = m->beginAtoms(); at != m->endAtoms(); ++at) { + Atom *atom = (*at); + unsigned int idx = atom->getIdx(); + TEST_ASSERT(idx == ExpectedProtor1d3z[idx].idx); + TEST_ASSERT(atom->getProp(common_properties::Atom::SASAClass) == + ExpectedProtor1d3z[idx].cls); + TEST_ASSERT(atom->getProp(common_properties::Atom::SASAClassName) == + ExpectedProtor1d3z[idx].clsname); + TEST_ASSERT(radii[idx] == ExpectedProtor1d3z[idx].radius); + } + + FreeSASA::SASAOpts opts; + opts.algorithm = FreeSASA::SASAOpts::ShrakeRupley; + + double sasa = FreeSASA::calcSASA(*m, radii, -1, NULL, opts); + TEST_ASSERT(fabs(sasa - 5000.340175) < 1e-5); + + + delete m; + { + const bool sanitize=false; + const bool removeHs=false; + m = PDBFileToMol(fName, sanitize, removeHs); + } + ROMol *mnoh = MolOps::removeHs(*m); + FreeSASA::classifyAtoms(*mnoh, radii); + sasa = FreeSASA::calcSASA(*mnoh, radii, -1, NULL, opts); + TEST_ASSERT(fabs(sasa - 5000.340175) < 1e-5); + + const QueryAtom *apolar = FreeSASA::makeFreeSasaAPolarAtomQuery(); + const QueryAtom *polar = FreeSASA::makeFreeSasaPolarAtomQuery(); + double apolard = FreeSASA::calcSASA(*mnoh, radii, -1, apolar, opts); + double polard = FreeSASA::calcSASA(*mnoh, radii, -1, polar, opts); + std::cerr << " polar " << polard << std::endl; + std::cerr << " apolar " << apolard << std::endl; + + TEST_ASSERT(fabs(polard + apolard - 5000.340175) < 1e-5); + + + delete m; + delete mnoh; + BOOST_LOG(rdInfoLog) << "Done" << std::endl; + +} + +int main() { + RDLog::InitLogs(); + testPDB(); +} From 24f7b4d8c57489e94c46e9e5adaf01508d244103 Mon Sep 17 00:00:00 2001 From: gerebtzoff Date: Tue, 26 Sep 2017 09:54:47 +0200 Subject: [PATCH 30/44] Enhanced Similarity Maps depiction (#1594) --- rdkit/Chem/Draw/SimilarityMaps.py | 17 ++++++++++++++--- rdkit/Chem/Draw/mplCanvas.py | 2 +- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/rdkit/Chem/Draw/SimilarityMaps.py b/rdkit/Chem/Draw/SimilarityMaps.py index 650043f8e..306ed5ac1 100644 --- a/rdkit/Chem/Draw/SimilarityMaps.py +++ b/rdkit/Chem/Draw/SimilarityMaps.py @@ -34,6 +34,7 @@ import copy import math from matplotlib import cm +from matplotlib.colors import LinearSegmentedColormap import numpy from rdkit import Chem @@ -118,7 +119,7 @@ def GetStandardizedWeights(weights): return weights, currentMax -def GetSimilarityMapFromWeights(mol, weights, colorMap=cm.PiYG, scale=-1, size=(250, 250), +def GetSimilarityMapFromWeights(mol, weights, colorMap=None, scale=-1, size=(250, 250), sigma=None, coordScale=1.5, step=0.01, colors='k', contourLines=10, alpha=0.5, **kwargs): """ @@ -126,7 +127,7 @@ def GetSimilarityMapFromWeights(mol, weights, colorMap=cm.PiYG, scale=-1, size=( Parameters: mol -- the molecule of interest - colorMap -- the matplotlib color map scheme + colorMap -- the matplotlib color map scheme, default is custom PiWG color map scale -- the scaling: scale < 0 -> the absolute maximum weight is used as maximum scale scale = double -> this is the maximum scale size -- the size of the figure @@ -159,12 +160,22 @@ def GetSimilarityMapFromWeights(mol, weights, colorMap=cm.PiYG, scale=-1, size=( else: maxScale = scale # coloring + if colorMap is None: + PiYG_cmap = cm.get_cmap('PiYG',2) + colorMap = LinearSegmentedColormap.from_list('PiWG', [PiYG_cmap(0), (1.0, 1.0, 1.0), PiYG_cmap(1)], N=255) + fig.axes[0].imshow(z, cmap=colorMap, interpolation='bilinear', origin='lower', extent=(0, 1, 0, 1), vmin=-maxScale, vmax=maxScale) # contour lines # only draw them when at least one weight is not zero if len([w for w in weights if w != 0.0]): - fig.axes[0].contour(x, y, z, contourLines, colors=colors, alpha=alpha, **kwargs) + contourset = fig.axes[0].contour(x, y, z, contourLines, colors=colors, alpha=alpha, **kwargs) + for j, c in enumerate(contourset.collections): + if contourset.levels[j] == 0.0: + c.set_linewidth(0.0) + elif contourset.levels[j] < 0: + c.set_dashes([(0, (3.0, 3.0))]) + fig.axes[0].set_axis_off() return fig diff --git a/rdkit/Chem/Draw/mplCanvas.py b/rdkit/Chem/Draw/mplCanvas.py index b0efd62b1..3e1392976 100644 --- a/rdkit/Chem/Draw/mplCanvas.py +++ b/rdkit/Chem/Draw/mplCanvas.py @@ -60,7 +60,7 @@ class Canvas(CanvasBase): annot = canvas.annotate(text, (pos[0], pos[1]), color=color, verticalalignment=valign, horizontalalignment=halign, weight=font.weight, size=font.size * 2.0, - family=font.face, backgroundcolor='white') + family=font.face) try: bb = annot.get_window_extent(renderer=self._figure.canvas.get_renderer()) From 96b092177e853329bee266f7d566907826bf042d Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Tue, 26 Sep 2017 18:49:33 +0200 Subject: [PATCH 31/44] [WIP] add threshold argument to maxmin picker (#1587) * add threshold argument * expose the new options to python not yet tested, but it at least compiles * support threshold on the python side; fix a bug with the way the threshold is returned --- Code/SimDivPickers/MaxMinPicker.h | 49 ++++++++- Code/SimDivPickers/Wrap/MaxMinPicker.cpp | 122 +++++++++++++++++++---- Code/SimDivPickers/Wrap/testPickers.py | 18 ++++ 3 files changed, 164 insertions(+), 25 deletions(-) diff --git a/Code/SimDivPickers/MaxMinPicker.h b/Code/SimDivPickers/MaxMinPicker.h index d8f4ab6ee..388587655 100644 --- a/Code/SimDivPickers/MaxMinPicker.h +++ b/Code/SimDivPickers/MaxMinPicker.h @@ -68,11 +68,21 @@ class MaxMinPicker : public DistPicker { * \param seed - (optional) seed for the random number generator */ template + RDKit::INT_VECT lazyPick(T &func, unsigned int poolSize, + unsigned int pickSize) const; + + template RDKit::INT_VECT lazyPick(T &func, unsigned int poolSize, unsigned int pickSize, - RDKit::INT_VECT firstPicks = RDKit::INT_VECT(), + const RDKit::INT_VECT &firstPicks, int seed = -1) const; + template + RDKit::INT_VECT lazyPick(T &func, unsigned int poolSize, + unsigned int pickSize, + const RDKit::INT_VECT &firstPicks, int seed, + double &threshold) const; + /*! \brief Contains the implementation for the MaxMin diversity picker * * Here is how the picking algorithm works, refer to @@ -137,8 +147,8 @@ struct MaxMinPickInfo { template RDKit::INT_VECT MaxMinPicker::lazyPick(T &func, unsigned int poolSize, unsigned int pickSize, - RDKit::INT_VECT firstPicks, - int seed) const { + const RDKit::INT_VECT &firstPicks, + int seed, double &threshold) const { if (!poolSize) throw ValueErrorException("empty pool to pick from"); if (poolSize < pickSize) @@ -148,7 +158,10 @@ RDKit::INT_VECT MaxMinPicker::lazyPick(T &func, unsigned int poolSize, unsigned int memsize = (unsigned int)(poolSize * sizeof(MaxMinPickInfo)); MaxMinPickInfo *pinfo = new MaxMinPickInfo[memsize]; - if (!pinfo) return picks; + if (!pinfo) { + threshold = -1.0; + return picks; + } memset(pinfo, 0, memsize); picks.reserve(pickSize); @@ -188,6 +201,7 @@ RDKit::INT_VECT MaxMinPicker::lazyPick(T &func, unsigned int poolSize, } if (picked >= pickSize) { + threshold = -1.0; delete[] pinfo; return picks; } @@ -216,9 +230,11 @@ RDKit::INT_VECT MaxMinPicker::lazyPick(T &func, unsigned int poolSize, } while (*prev != 0); // now pick 1 compound at a time + double maxOFmin = -1.0; + double tmpThreshold = -1.0; while (picked < pickSize) { unsigned int *pick_prev = 0; - double maxOFmin = -1.0; + maxOFmin = -1.0; prev = &pool_list; do { poolIdx = *prev; @@ -246,15 +262,38 @@ RDKit::INT_VECT MaxMinPicker::lazyPick(T &func, unsigned int poolSize, prev = &pinfo[poolIdx].next; } while (*prev != 0); + // if the current distance is closer then threshold, we're done + if (threshold >= 0.0 && maxOFmin < threshold) break; + tmpThreshold = maxOFmin; // now add the new pick to picks and remove it from the pool *pick_prev = pinfo[pick].next; picks.push_back(pick); picked++; } + threshold = tmpThreshold; delete[] pinfo; return picks; } + +template +RDKit::INT_VECT MaxMinPicker::lazyPick(T &func, unsigned int poolSize, + unsigned int pickSize, + const RDKit::INT_VECT &firstPicks, + int seed) const { + double threshold = -1.0; + return MaxMinPicker::lazyPick(func, poolSize, pickSize, firstPicks, seed, + threshold); +} + +template +RDKit::INT_VECT MaxMinPicker::lazyPick(T &func, unsigned int poolSize, + unsigned int pickSize) const { + RDKit::INT_LIST firstPicks; + double threshold = -1.0; + return MaxMinPicker::lazyPick(func, poolSize, pickSize, firstPicks, -1, + threshold); +} }; #endif diff --git a/Code/SimDivPickers/Wrap/MaxMinPicker.cpp b/Code/SimDivPickers/Wrap/MaxMinPicker.cpp index 50df5e201..9bc9f5ef7 100644 --- a/Code/SimDivPickers/Wrap/MaxMinPicker.cpp +++ b/Code/SimDivPickers/Wrap/MaxMinPicker.cpp @@ -66,24 +66,45 @@ class pyobjFunctor { python::object dp_obj; }; -RDKit::INT_VECT LazyMaxMinPicks(MaxMinPicker *picker, python::object distFunc, - int poolSize, int pickSize, - python::object firstPicks, int seed, - python::object useCache) { - if (useCache != python::object()) { - BOOST_LOG(rdWarningLog) << "the useCache argument is deprecated and ignored" - << std::endl; - } +namespace { +template +void LazyMaxMinHelper(MaxMinPicker *picker, T functor, unsigned int poolSize, + unsigned int pickSize, python::object firstPicks, + int seed, RDKit::INT_VECT &res, double &threshold) { RDKit::INT_VECT firstPickVect; for (unsigned int i = 0; i < python::extract(firstPicks.attr("__len__")()); ++i) { firstPickVect.push_back(python::extract(firstPicks[i])); } - RDKit::INT_VECT res; + res = picker->lazyPick(functor, poolSize, pickSize, firstPickVect, seed, + threshold); +} +} // end of anonymous namespace + +RDKit::INT_VECT LazyMaxMinPicks(MaxMinPicker *picker, python::object distFunc, + int poolSize, int pickSize, + python::object firstPicks, int seed, + python::object useCache) { + if (useCache != python::object()) { + BOOST_LOG(rdWarningLog) + << "the useCache argument is deprecated and ignored" << std::endl; + } pyobjFunctor functor(distFunc); - res = picker->lazyPick(functor, poolSize, pickSize, firstPickVect, seed); + RDKit::INT_VECT res; + double threshold = -1.; + LazyMaxMinHelper(picker, functor, poolSize, pickSize, firstPicks, seed, res, + threshold); return res; } +python::tuple LazyMaxMinPicksWithThreshold( + MaxMinPicker *picker, python::object distFunc, int poolSize, int pickSize, + double threshold, python::object firstPicks, int seed) { + pyobjFunctor functor(distFunc); + RDKit::INT_VECT res; + LazyMaxMinHelper(picker, functor, poolSize, pickSize, firstPicks, seed, res, + threshold); + return python::make_tuple(res, threshold); +} // NOTE: TANIMOTO and DICE provably return the same results for the diversity // picking this is still here just in case we ever later want to support other @@ -121,23 +142,37 @@ RDKit::INT_VECT LazyVectorMaxMinPicks(MaxMinPicker *picker, python::object objs, python::object firstPicks, int seed, python::object useCache) { if (useCache != python::object()) { - BOOST_LOG(rdWarningLog) << "the useCache argument is deprecated and ignored" - << std::endl; + BOOST_LOG(rdWarningLog) + << "the useCache argument is deprecated and ignored" << std::endl; } std::vector bvs(poolSize); for (int i = 0; i < poolSize; ++i) { bvs[i] = python::extract(objs[i]); } pyBVFunctor functor(bvs, TANIMOTO); - RDKit::INT_VECT firstPickVect; - for (unsigned int i = 0; - i < python::extract(firstPicks.attr("__len__")()); ++i) { - firstPickVect.push_back(python::extract(firstPicks[i])); - } - RDKit::INT_VECT res = - picker->lazyPick(functor, poolSize, pickSize, firstPickVect, seed); + + RDKit::INT_VECT res; + double threshold = -1.; + LazyMaxMinHelper(picker, functor, poolSize, pickSize, firstPicks, seed, res, + threshold); return res; } + +python::tuple LazyVectorMaxMinPicksWithThreshold( + MaxMinPicker *picker, python::object objs, int poolSize, int pickSize, + double threshold, python::object firstPicks, int seed) { + std::vector bvs(poolSize); + for (int i = 0; i < poolSize; ++i) { + bvs[i] = python::extract(objs[i]); + } + pyBVFunctor functor(bvs, TANIMOTO); + + RDKit::INT_VECT res; + LazyMaxMinHelper(picker, functor, poolSize, pickSize, firstPicks, seed, res, + threshold); + return python::make_tuple(res, threshold); +} + } // end of namespace RDPickers struct MaxMin_wrap { @@ -205,7 +240,54 @@ struct MaxMin_wrap { " - firstPicks: (optional) the first items to be picked (seeds " "the list)\n" " - seed: (optional) seed for the random number generator\n" - " - useCache: IGNORED.\n"); + " - useCache: IGNORED.\n") + + .def("LazyPickWithThreshold", RDPickers::LazyMaxMinPicksWithThreshold, + (python::arg("self"), python::arg("distFunc"), + python::arg("poolSize"), python::arg("pickSize"), + python::arg("threshold"), + python::arg("firstPicks") = python::tuple(), + python::arg("seed") = -1), + "Pick a subset of items from a pool of items using the MaxMin " + "Algorithm\n" + "Ashton, M. et. al., Quant. Struct.-Act. Relat., 21 (2002), " + "598-604 \n" + "ARGUMENTS:\n\n" + " - distFunc: a function that should take two indices and return " + "the\n" + " distance between those two points.\n" + " NOTE: the implementation caches distance values, " + "so the\n" + " client code does not need to do so; indeed, it " + "should not.\n" + " - poolSize: number of items in the pool\n" + " - pickSize: number of items to pick from the pool\n" + " - threshold: stop picking when the distance goes below this " + "value\n" + " - firstPicks: (optional) the first items to be picked (seeds " + "the list)\n" + " - seed: (optional) seed for the random number generator\n") + .def("LazyBitVectorPickWithThreshold", + RDPickers::LazyVectorMaxMinPicksWithThreshold, + (python::arg("self"), python::arg("objects"), + python::arg("poolSize"), python::arg("pickSize"), + python::arg("threshold"), + python::arg("firstPicks") = python::tuple(), + python::arg("seed") = -1), + "Pick a subset of items from a pool of bit vectors using the " + "MaxMin Algorithm\n" + "Ashton, M. et. al., Quant. Struct.-Act. Relat., 21 (2002), " + "598-604 \n" + "ARGUMENTS:\n\n" + " - vectors: a sequence of the bit vectors that should be picked " + "from.\n" + " - poolSize: number of items in the pool\n" + " - pickSize: number of items to pick from the pool\n" + " - threshold: stop picking when the distance goes below this " + "value\n" + " - firstPicks: (optional) the first items to be picked (seeds " + "the list)\n" + " - seed: (optional) seed for the random number generator\n"); }; }; diff --git a/Code/SimDivPickers/Wrap/testPickers.py b/Code/SimDivPickers/Wrap/testPickers.py index 5b5a6939a..8fffb67b2 100755 --- a/Code/SimDivPickers/Wrap/testPickers.py +++ b/Code/SimDivPickers/Wrap/testPickers.py @@ -239,7 +239,25 @@ class TestCase(unittest.TestCase): self.assertEqual(ids,[374,720,690,339,875,842,404,725,120,385,115,868,630,\ 881,516,497,412,718,869,407]) + def testBitVectorMaxMin4(self): + # threshold tests + fname = os.path.join(RDConfig.RDBaseDir, 'Code', 'SimDivPickers', 'Wrap', 'test_data', + 'chembl_cyps.head.fps') + fps = [] + with open(fname) as infil: + for line in infil: + fp = DataStructs.CreateFromFPSText(line.strip()) + fps.append(fp) + mmp =rdSimDivPickers.MaxMinPicker() + ids,threshold=mmp.LazyBitVectorPickWithThreshold(fps,len(fps),20,-1.0) + self.assertEqual(list(ids),[374,720,690,339,875,842,404,725,120,385,115,868,630,\ + 881,516,497,412,718,869,407]) + self.assertAlmostEqual(threshold,0.8977,4) + + ids,threshold=mmp.LazyBitVectorPickWithThreshold(fps,len(fps),20,0.91) + self.assertEqual(list(ids),[374,720,690,339,875,842,404,725,120,385,115,868,630]) + self.assertTrue(threshold>=0.91) if __name__ == '__main__': From 7d73a7508379ca0d942dca97944d01969bdd251f Mon Sep 17 00:00:00 2001 From: Brian Cole Date: Tue, 26 Sep 2017 12:54:53 -0400 Subject: [PATCH 32/44] Improvements to GenerateStereoisomers (#1582) * Improvements to GenerateStereoisomers: - enumerate bond stereo as well - change maxNumCenters to maxIsomers for more fine grained control - allow sampling random subsets from potentially very large isomer spaces Hoping this gets the 'easy' stuff out of the way before I submit the more tricky stuff later at the UGM hack day: de-duplicating isomers; and pseudo-stereo centers. * Addressing comments in pull request 1582: - Use six.moves.range instead of rolling own - Adding double bond stereo to doc examples - test cases for random seeding options - test case for python OverflowError * Make RDKit throw a ValueError when there is too many stereo centers and document the restriction. * The random number generator is different in Python 3, so protect ourselves from that. * Renamed GenerateStereoisomers to EnumerateStereoisomers and moved out of AllChem.py * Getting doc tests to actually work. * Port GenerateStereoisomers tests to EnumerateStereoisomers. * Puts in a safety measure to make sure tryEmbedding can't cause EnumerateStereoisomers to infinite loop. * Test cases for the onlyUnassigned option. * Removing imports no longer needed that EnumerateStereoisomers is located in EnumerateStereoisomers.py. * Actually expecting this test case to fail between Python 2 and Python 3. Maybe the '...' was preventing doc test from working? * Adding a test case to make sure the sampling of isomers is deterministic. Theoretically, the doc test should be doing this, but it didn't fail in Python 3 like expected. I'm expecting this test case to fail on the Travis Python 3 builds so I can grab the proper values from there to insert. Expecting the results to be the same for a given major version of Python. --- rdkit/Chem/AllChem.py | 126 +------------- rdkit/Chem/EnumerateStereoisomers.py | 245 +++++++++++++++++++++++++++ rdkit/Chem/UnitTestDocTestsChem.py | 3 +- rdkit/Chem/UnitTestMol3D.py | 90 ++++++++++ 4 files changed, 339 insertions(+), 125 deletions(-) create mode 100644 rdkit/Chem/EnumerateStereoisomers.py diff --git a/rdkit/Chem/AllChem.py b/rdkit/Chem/AllChem.py index 60c4f3961..9c089c8c0 100644 --- a/rdkit/Chem/AllChem.py +++ b/rdkit/Chem/AllChem.py @@ -10,6 +10,7 @@ """ Import all RDKit chemistry modules """ +import sys import warnings from collections import namedtuple @@ -34,6 +35,7 @@ from rdkit.Chem.rdShapeHelpers import * from rdkit.Chem.rdqueries import * from rdkit.Geometry import rdGeometry from rdkit.RDLogger import logger +from rdkit.Chem.EnumerateStereoisomers import StereoEnumerationOptions, EnumerateStereoisomers try: from rdkit.Chem.rdSLNParse import * @@ -404,130 +406,6 @@ def AssignBondOrdersFromTemplate(refmol, mol): raise ValueError("No matching found") return mol2 -class StereoEnumerationOptions(object): - """ - - tryEmbedding: if set the process attempts to generate a standard RDKit distance geometry - conformation for the stereisomer. If this fails, we assume that the stereoisomer is - non-physical and don't return it. NOTE that this is computationally expensive and is - just a heuristic that could result in stereoisomers being lost. - - - onlyUnassigned: if set (the default), stereocenters which have specified stereochemistry - will not be perturbed - - - maxNumCenters: the maximum number of stereocenters that can/will be handled. - Since every additional stereocenter doubles the number of results - (and execution time) it's important to keep an eye on this. - - """ - __slots__=('tryEmbedding', 'onlyUnassigned', 'maxNumCenters') - def __init__(self, tryEmbedding = False, onlyUnassigned = True, - maxNumCenters = 10): - self.tryEmbedding = tryEmbedding - self.onlyUnassigned = onlyUnassigned - self.maxNumCenters = maxNumCenters - -def GenerateStereoisomers(m,options=StereoEnumerationOptions(),verbose=False): - """ returns a generator that yields possible stereoisomers for a molecule - - Arguments: - - m: the molecule to work with - - - - verbose: toggles how verbose the output is - - - A small example with 3 chiral centers (8 theoretical stereoisomers): - >>> from rdkit.Chem import AllChem - >>> m = AllChem.MolFromSmiles('OC1OC(C2)(F)C2(Cl)C1') - >>> isomers = tuple(AllChem.GenerateStereoisomers(m)) - >>> len(isomers) - 8 - >>> for smi in sorted(AllChem.MolToSmiles(x,isomericSmiles=True) for x in isomers): - ... print(smi) - O[C@@H]1C[C@@]2(Cl)C[C@@]2(F)O1 - O[C@@H]1C[C@@]2(Cl)C[C@]2(F)O1 - O[C@@H]1C[C@]2(Cl)C[C@@]2(F)O1 - O[C@@H]1C[C@]2(Cl)C[C@]2(F)O1 - O[C@H]1C[C@@]2(Cl)C[C@@]2(F)O1 - O[C@H]1C[C@@]2(Cl)C[C@]2(F)O1 - O[C@H]1C[C@]2(Cl)C[C@@]2(F)O1 - O[C@H]1C[C@]2(Cl)C[C@]2(F)O1 - - Because the molecule is constrained, not all of those isomers can - actually exist. We can check that: - >>> opts = StereoEnumerationOptions(tryEmbedding=True) - >>> isomers = tuple(AllChem.GenerateStereoisomers(m, options=opts)) - >>> len(isomers) - 4 - >>> for smi in sorted(AllChem.MolToSmiles(x,isomericSmiles=True) for x in isomers): - ... print(smi) - O[C@@H]1C[C@@]2(Cl)C[C@@]2(F)O1 - O[C@@H]1C[C@]2(Cl)C[C@]2(F)O1 - O[C@H]1C[C@@]2(Cl)C[C@@]2(F)O1 - O[C@H]1C[C@]2(Cl)C[C@]2(F)O1 - - By default the code only expands unspecified stereocenters: - >>> m = AllChem.MolFromSmiles('O[C@H]1OC(C2)(F)C2(Cl)C1') - >>> isomers = tuple(AllChem.GenerateStereoisomers(m)) - >>> len(isomers) - 4 - >>> for smi in sorted(AllChem.MolToSmiles(x,isomericSmiles=True) for x in isomers): - ... print(smi) - O[C@@H]1C[C@@]2(Cl)C[C@@]2(F)O1 - O[C@@H]1C[C@@]2(Cl)C[C@]2(F)O1 - O[C@@H]1C[C@]2(Cl)C[C@@]2(F)O1 - O[C@@H]1C[C@]2(Cl)C[C@]2(F)O1 - - but we can change that behavior: - >>> opts = StereoEnumerationOptions(onlyUnassigned=False) - >>> isomers = tuple(AllChem.GenerateStereoisomers(m, options=opts)) - >>> len(isomers) - 8 - - since the result is a generator, we can allow exploring at least parts of very - large result sets: - >>> m = MolFromSmiles('Br'+'[CH](Cl)'*20+'F') - >>> opts = StereoEnumerationOptions(maxNumCenters=50) - >>> isomers = AllChem.GenerateStereoisomers(m, options=opts) - >>> for x in range(5): - ... print(MolToSmiles(next(isomers),isomericSmiles=True)) - F[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)Br - F[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@H](Cl)Br - F[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@H](Cl)[C@@H](Cl)Br - F[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@H](Cl)[C@H](Cl)Br - F[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@H](Cl)[C@@H](Cl)[C@@H](Cl)Br - - """ - tm = Mol(m) - if options.onlyUnassigned: - possibleCenters = [x for x,y in FindMolChiralCenters(tm, force=True, includeUnassigned=True) if y=='?'] - else: - possibleCenters = [x for x,y in FindMolChiralCenters(tm, force=True, includeUnassigned=True)] - nCenters = len(possibleCenters) - if not nCenters: - yield tm - return - if nCenters>options.maxNumCenters: - raise ValueError("nCenters (%d) larger than maxNumCenters (%d)"%(nCenters,options.maxNumCenters)) - bitflag = (1<=0: - tm = Mol(m) - for i in range(nCenters): - if bitflag & 1<= 0: - yield tm - elif verbose: - print("%s failed to embed"%(MolToSmiles(tm,isomericSmiles=True))) - bitflag -= 1 - # ------------------------------------ # # doctest boilerplate diff --git a/rdkit/Chem/EnumerateStereoisomers.py b/rdkit/Chem/EnumerateStereoisomers.py new file mode 100644 index 000000000..2f9ed4e7a --- /dev/null +++ b/rdkit/Chem/EnumerateStereoisomers.py @@ -0,0 +1,245 @@ +import six +import random +from rdkit import Chem +from rdkit.Chem.rdDistGeom import EmbedMolecule + +class StereoEnumerationOptions(object): + """ + - tryEmbedding: if set the process attempts to generate a standard RDKit distance geometry + conformation for the stereisomer. If this fails, we assume that the stereoisomer is + non-physical and don't return it. NOTE that this is computationally expensive and is + just a heuristic that could result in stereoisomers being lost. + + - onlyUnassigned: if set (the default), stereocenters which have specified stereochemistry + will not be perturbed + + - maxIsomers: the maximum number of isomers to yield, if the + number of possible isomers is greater than maxIsomers, a + random subset will be yielded. If 0, all isomers are + yielded. Since every additional stereo center doubles the + number of results (and execution time) it's important to + keep an eye on this. + """ + __slots__ = ('tryEmbedding', 'onlyUnassigned', 'maxIsomers', 'rand') + def __init__(self, tryEmbedding = False, onlyUnassigned = True, + maxIsomers = 1024, rand = None): + self.tryEmbedding = tryEmbedding + self.onlyUnassigned = onlyUnassigned + self.maxIsomers = maxIsomers + self.rand = rand + +class _BondFlipper(object): + def __init__(self, bond): + self.bond = bond + + def flip(self, flag): + if flag: + self.bond.SetStereo(Chem.BondStereo.STEREOCIS) + else: + self.bond.SetStereo(Chem.BondStereo.STEREOTRANS) + +class _AtomFlipper(object): + def __init__(self, atom): + self.atom = atom + + def flip(self, flag): + if flag: + self.atom.SetChiralTag(Chem.ChiralType.CHI_TETRAHEDRAL_CW) + else: + self.atom.SetChiralTag(Chem.ChiralType.CHI_TETRAHEDRAL_CCW) + +def _getFlippers(mol, options): + Chem.FindPotentialStereoBonds(mol) + + flippers = [] + for atom in mol.GetAtoms(): + if atom.HasProp("_ChiralityPossible"): + if (not options.onlyUnassigned or + atom.GetChiralTag() == Chem.ChiralType.CHI_UNSPECIFIED): + flippers.append(_AtomFlipper(atom)) + + for bond in mol.GetBonds(): + bstereo = bond.GetStereo() + if bstereo != Chem.BondStereo.STEREONONE: + if (not options.onlyUnassigned or + bstereo == Chem.BondStereo.STEREOANY): + flippers.append(_BondFlipper(bond)) + + return flippers + +class _RangeBitsGenerator(object): + def __init__(self, nCenters): + self.nCenters = nCenters + + def __iter__(self): + for val in six.moves.range(2**self.nCenters): + yield val + +class _UniqueRandomBitsGenerator(object): + def __init__(self, nCenters, maxIsomers, rand): + self.nCenters = nCenters + self.maxIsomers = maxIsomers + self.rand = rand + self.already_seen = set() + + def __iter__(self): + # note: important that this is not 'while True' otherwise it + # would be possible to have an infinite loop caused by all + # isomers failing the embedding process + while len(self.already_seen) < 2**self.nCenters: + bits = self.rand.getrandbits(self.nCenters) + if bits in self.already_seen: + continue + + self.already_seen.add(bits) + yield bits + +def EnumerateStereoisomers(m, options=StereoEnumerationOptions(), verbose=False): + """ returns a generator that yields possible stereoisomers for a molecule + + Arguments: + - m: the molecule to work with + - verbose: toggles how verbose the output is + + A small example with 3 chiral atoms and 1 chiral bond (16 theoretical stereoisomers): + >>> from rdkit import Chem + >>> from rdkit.Chem.EnumerateStereoisomers import EnumerateStereoisomers, StereoEnumerationOptions + >>> m = Chem.MolFromSmiles('BrC=CC1OC(C2)(F)C2(Cl)C1') + >>> isomers = tuple(EnumerateStereoisomers(m)) + >>> len(isomers) + 16 + >>> for smi in sorted(Chem.MolToSmiles(x, isomericSmiles=True) for x in isomers): + ... print(smi) + ... + F[C@@]12C[C@@]1(Cl)C[C@@H](/C=C/Br)O2 + F[C@@]12C[C@@]1(Cl)C[C@@H](/C=C\Br)O2 + F[C@@]12C[C@@]1(Cl)C[C@H](/C=C/Br)O2 + F[C@@]12C[C@@]1(Cl)C[C@H](/C=C\Br)O2 + F[C@@]12C[C@]1(Cl)C[C@@H](/C=C/Br)O2 + F[C@@]12C[C@]1(Cl)C[C@@H](/C=C\Br)O2 + F[C@@]12C[C@]1(Cl)C[C@H](/C=C/Br)O2 + F[C@@]12C[C@]1(Cl)C[C@H](/C=C\Br)O2 + F[C@]12C[C@@]1(Cl)C[C@@H](/C=C/Br)O2 + F[C@]12C[C@@]1(Cl)C[C@@H](/C=C\Br)O2 + F[C@]12C[C@@]1(Cl)C[C@H](/C=C/Br)O2 + F[C@]12C[C@@]1(Cl)C[C@H](/C=C\Br)O2 + F[C@]12C[C@]1(Cl)C[C@@H](/C=C/Br)O2 + F[C@]12C[C@]1(Cl)C[C@@H](/C=C\Br)O2 + F[C@]12C[C@]1(Cl)C[C@H](/C=C/Br)O2 + F[C@]12C[C@]1(Cl)C[C@H](/C=C\Br)O2 + + Because the molecule is constrained, not all of those isomers can + actually exist. We can check that: + >>> opts = StereoEnumerationOptions(tryEmbedding=True) + >>> isomers = tuple(EnumerateStereoisomers(m, options=opts)) + >>> len(isomers) + 8 + >>> for smi in sorted(Chem.MolToSmiles(x,isomericSmiles=True) for x in isomers): + ... print(smi) + ... + F[C@@]12C[C@]1(Cl)C[C@@H](/C=C/Br)O2 + F[C@@]12C[C@]1(Cl)C[C@@H](/C=C\Br)O2 + F[C@@]12C[C@]1(Cl)C[C@H](/C=C/Br)O2 + F[C@@]12C[C@]1(Cl)C[C@H](/C=C\Br)O2 + F[C@]12C[C@@]1(Cl)C[C@@H](/C=C/Br)O2 + F[C@]12C[C@@]1(Cl)C[C@@H](/C=C\Br)O2 + F[C@]12C[C@@]1(Cl)C[C@H](/C=C/Br)O2 + F[C@]12C[C@@]1(Cl)C[C@H](/C=C\Br)O2 + + By default the code only expands unspecified stereocenters: + >>> m = Chem.MolFromSmiles('BrC=C[C@H]1OC(C2)(F)C2(Cl)C1') + >>> isomers = tuple(EnumerateStereoisomers(m)) + >>> len(isomers) + 8 + >>> for smi in sorted(Chem.MolToSmiles(x,isomericSmiles=True) for x in isomers): + ... print(smi) + ... + F[C@@]12C[C@@]1(Cl)C[C@@H](/C=C/Br)O2 + F[C@@]12C[C@@]1(Cl)C[C@@H](/C=C\Br)O2 + F[C@@]12C[C@]1(Cl)C[C@@H](/C=C/Br)O2 + F[C@@]12C[C@]1(Cl)C[C@@H](/C=C\Br)O2 + F[C@]12C[C@@]1(Cl)C[C@@H](/C=C/Br)O2 + F[C@]12C[C@@]1(Cl)C[C@@H](/C=C\Br)O2 + F[C@]12C[C@]1(Cl)C[C@@H](/C=C/Br)O2 + F[C@]12C[C@]1(Cl)C[C@@H](/C=C\Br)O2 + + But we can change that behavior: + >>> opts = StereoEnumerationOptions(onlyUnassigned=False) + >>> isomers = tuple(EnumerateStereoisomers(m, options=opts)) + >>> len(isomers) + 16 + + Since the result is a generator, we can allow exploring at least parts of very + large result sets: + >>> m = Chem.MolFromSmiles('Br' + '[CH](Cl)' * 20 + 'F') + >>> opts = StereoEnumerationOptions(maxIsomers=0) + >>> isomers = EnumerateStereoisomers(m, options=opts) + >>> for x in range(5): + ... print(Chem.MolToSmiles(next(isomers),isomericSmiles=True)) + F[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)Br + F[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@H](Cl)Br + F[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@H](Cl)[C@@H](Cl)Br + F[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@H](Cl)[C@H](Cl)Br + F[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@H](Cl)[C@@H](Cl)[C@@H](Cl)Br + + Or randomly sample a small subset: + >>> m = Chem.MolFromSmiles('Br' + '[CH](Cl)' * 20 + 'F') + >>> opts = StereoEnumerationOptions(maxIsomers=3) + >>> isomers = EnumerateStereoisomers(m, options=opts) + >>> for smi in sorted(Chem.MolToSmiles(x, isomericSmiles=True) for x in isomers): + ... print(smi) + F[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@H](Cl)[C@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@H](Cl)[C@@H](Cl)[C@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@H](Cl)[C@H](Cl)[C@H](Cl)[C@H](Cl)[C@H](Cl)[C@@H](Cl)Br + F[C@@H](Cl)[C@H](Cl)[C@@H](Cl)[C@H](Cl)[C@@H](Cl)[C@H](Cl)[C@H](Cl)[C@H](Cl)[C@H](Cl)[C@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@H](Cl)[C@@H](Cl)Br + F[C@H](Cl)[C@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@H](Cl)[C@H](Cl)[C@H](Cl)[C@H](Cl)[C@H](Cl)[C@@H](Cl)[C@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@@H](Cl)[C@H](Cl)[C@@H](Cl)Br + """ + + tm = Chem.Mol(m) + flippers = _getFlippers(tm, options) + nCenters = len(flippers) + if not nCenters: + yield tm + return + + if (options.maxIsomers == 0 or + 2**nCenters <= options.maxIsomers): + bitsource = _RangeBitsGenerator(nCenters) + else: + if options.rand is None: + # deterministic random seed invariant to input atom order + seed = hash(tuple(sorted([(a.GetDegree(), a.GetAtomicNum()) for a in tm.GetAtoms()]))) + rand = random.Random(seed) + elif isinstance(options.rand, random.Random): + # other implementations of Python random number generators + # can inherit from this class to pick up utility methods + rand = options.rand + else: + rand = random.Random(options.rand) + + bitsource = _UniqueRandomBitsGenerator(nCenters, options.maxIsomers, rand) + + numIsomers = 0 + for bitflag in bitsource: + for i in range(nCenters): + flag = bool(bitflag & (1 << i)) + flippers[i].flip(flag) + + isomer = Chem.Mol(tm) + if options.tryEmbedding: + ntm = Chem.AddHs(isomer) + cid = EmbedMolecule(ntm, randomSeed=bitflag) + if cid >= 0: + conf = Chem.Conformer(isomer.GetNumAtoms()) + for aid in range(isomer.GetNumAtoms()): + conf.SetAtomPosition(aid, ntm.GetConformer().GetAtomPosition(aid)) + isomer.AddConformer(conf) + else: + cid = 1 + if cid >= 0: + yield isomer + numIsomers += 1 + if options.maxIsomers != 0 and numIsomers >= options.maxIsomers: + break + elif verbose: + print("%s failed to embed" % (Chem.MolToSmiles(isomer, isomericSmiles=True))) + + diff --git a/rdkit/Chem/UnitTestDocTestsChem.py b/rdkit/Chem/UnitTestDocTestsChem.py index 18456f6f6..bab709ecc 100755 --- a/rdkit/Chem/UnitTestDocTestsChem.py +++ b/rdkit/Chem/UnitTestDocTestsChem.py @@ -4,10 +4,11 @@ import doctest from rdkit import Chem from rdkit.Chem import MCS, FragmentMatcher, MACCSkeys, Descriptors, TemplateAlign from rdkit.Chem import Recap, BRICS, AllChem, PropertyMol, SaltRemover - +from rdkit.Chem import EnumerateStereoisomers def load_tests(loader, tests, ignore): # pylint: disable=unused-argument """ Add the Doctests from the module """ + tests.addTests(doctest.DocTestSuite(EnumerateStereoisomers, optionflags=doctest.ELLIPSIS)) tests.addTests(doctest.DocTestSuite(MCS, optionflags=doctest.ELLIPSIS)) tests.addTests(doctest.DocTestSuite(FragmentMatcher, optionflags=doctest.ELLIPSIS)) tests.addTests(doctest.DocTestSuite(MACCSkeys, optionflags=doctest.ELLIPSIS)) diff --git a/rdkit/Chem/UnitTestMol3D.py b/rdkit/Chem/UnitTestMol3D.py index d3d470546..be9c92f59 100755 --- a/rdkit/Chem/UnitTestMol3D.py +++ b/rdkit/Chem/UnitTestMol3D.py @@ -5,6 +5,7 @@ """ from rdkit import RDConfig import unittest, os +import random from rdkit import Chem from rdkit.Chem import AllChem from rdkit.Chem import TorsionFingerprints @@ -190,6 +191,95 @@ class TestCase(unittest.TestCase): self.assertBondStereoRoundTrips('cis.sdf') self.assertBondStereoRoundTrips('trans.sdf') + def testEnumerateStereoisomersBasic(self): + mol = Chem.MolFromSmiles('CC(F)=CC(Cl)C') + smiles = set(Chem.MolToSmiles(i, isomericSmiles=True) for i in AllChem.EnumerateStereoisomers(mol)) + self.assertEqual(len(smiles), 4) + + def testEnumerateStereoisomersLargeRandomSample(self): + # near max number of stereo centers allowed + mol = Chem.MolFromSmiles('CC(F)=CC(Cl)C' * 31) + smiles = set(Chem.MolToSmiles(i, isomericSmiles=True) for i in AllChem.EnumerateStereoisomers(mol)) + self.assertEqual(len(smiles), 1024) + + def testEnumerateStereoisomersWithCrazyNumberOfCenters(self): + # insanely large numbers of isomers aren't a problem + mol = Chem.MolFromSmiles('CC(F)=CC(Cl)C' * 101) + opts = AllChem.StereoEnumerationOptions(rand=None, maxIsomers=13) + smiles = set(Chem.MolToSmiles(i, isomericSmiles=True) for i in AllChem.EnumerateStereoisomers(mol, opts)) + self.assertEqual(len(smiles), 13) + + def testEnumerateStereoisomersRandomSamplingShouldBeDeterministicAndPortable(self): + mol = Chem.MolFromSmiles('CC(F)=CC(Cl)C=C(Br)C(I)N') + opts = AllChem.StereoEnumerationOptions(maxIsomers=2) + smiles = set(Chem.MolToSmiles(i, isomericSmiles=True) for i in AllChem.EnumerateStereoisomers(mol, opts)) + expected = set([ + 'C/C(F)=C/[C@@H](Cl)/C=C(/Br)[C@@H](N)I', + 'C/C(F)=C/[C@H](Cl)/C=C(\\Br)[C@H](N)I', + ]) + self.assertEqual(smiles, expected) + + def testEnumerateStereoisomersMaxIsomersShouldBeReturnedEvenWithTryEmbedding(self): + m = Chem.MolFromSmiles('BrC=CC1OC(C2)(F)C2(Cl)C1') + opts = AllChem.StereoEnumerationOptions(tryEmbedding=True, maxIsomers=8) + isomers = set() + for x in AllChem.EnumerateStereoisomers(m, options=opts): + isomers.add(Chem.MolToSmiles(x, isomericSmiles=True)) + self.assertEqual(len(isomers), 8) + + def testEnumerateStereoisomersTryEmbeddingShouldNotInfiniteLoopWhenMaxIsomersIsLargerThanActual(self): + m = Chem.MolFromSmiles('BrC=CC1OC(C2)(F)C2(Cl)C1') + opts = AllChem.StereoEnumerationOptions(tryEmbedding=True, maxIsomers=1024) + isomers = set() + for x in AllChem.EnumerateStereoisomers(m, options=opts): + isomers.add(Chem.MolToSmiles(x, isomericSmiles=True)) + self.assertEqual(len(isomers), 8) + + def testEnumerateStereoisomersRandomSeeding(self): + opts = AllChem.StereoEnumerationOptions(rand=None, maxIsomers=3) + mol = Chem.MolFromSmiles('CC(F)=CC(Cl)C') + smiles = set(Chem.MolToSmiles(i, isomericSmiles=True) for i in AllChem.EnumerateStereoisomers(mol, opts)) + assert smiles == set(['C/C(F)=C/[C@@H](C)Cl', 'C/C(F)=C\\[C@H](C)Cl', 'C/C(F)=C\\[C@@H](C)Cl']) + + opts = AllChem.StereoEnumerationOptions(rand=0xDEADBEEF) + mol = Chem.MolFromSmiles('c1ccc2c(c1)C(=O)N(C2=O)C3CCC(=O)NC3=O') + smiles = set(Chem.MolToSmiles(i, isomericSmiles=True) for i in AllChem.EnumerateStereoisomers(mol, opts)) + assert smiles == set(['O=C1CC[C@@H](N2C(=O)c3ccccc3C2=O)C(=O)N1', 'O=C1CC[C@H](N2C(=O)c3ccccc3C2=O)C(=O)N1']) + + class DeterministicRandom(random.Random): + def __init__(self): + random.Random.__init__(self) + self.count = 0 + def getrandbits(self, n_bits): + c = self.count + self.count += 1 + return c + + rand = DeterministicRandom() + opts = AllChem.StereoEnumerationOptions(rand=rand, maxIsomers=3) + mol = Chem.MolFromSmiles('CCCC(=C(CCl)C(C)CBr)[C@H](F)C(C)C') + smiles = [Chem.MolToSmiles(i, isomericSmiles=True) for i in AllChem.EnumerateStereoisomers(mol, opts)] + assert smiles == ['CCC/C(=C(\\CCl)[C@H](C)CBr)[C@H](F)C(C)C', 'CCC/C(=C(\\CCl)[C@@H](C)CBr)[C@H](F)C(C)C', 'CCC/C(=C(/CCl)[C@H](C)CBr)[C@H](F)C(C)C'] + + def testEnumerateStereoisomersOnlyUnassigned(self): + # shouldn't enumerate anything + fully_assigned = Chem.MolFromSmiles('C/C(F)=C/[C@@H](C)Cl') + smiles = set(Chem.MolToSmiles(i, isomericSmiles=True) for i in AllChem.EnumerateStereoisomers(fully_assigned)) + self.assertEquals(smiles, set(['C/C(F)=C/[C@@H](C)Cl'])) + + # should only enuemrate the bond stereo + partially_assigned = Chem.MolFromSmiles('CC(F)=C[C@@H](C)Cl') + smiles = set(Chem.MolToSmiles(i, isomericSmiles=True) for i in AllChem.EnumerateStereoisomers(partially_assigned)) + self.assertEquals(smiles, set(['C/C(F)=C/[C@@H](C)Cl', 'C/C(F)=C\\[C@@H](C)Cl'])) + + # should enumerate everything + opts = AllChem.StereoEnumerationOptions(onlyUnassigned=False) + smiles = set(Chem.MolToSmiles(i, isomericSmiles=True) for i in AllChem.EnumerateStereoisomers(fully_assigned, opts)) + self.assertEquals(smiles, set(['C/C(F)=C\\[C@@H](C)Cl', + 'C/C(F)=C\\[C@H](C)Cl', + 'C/C(F)=C/[C@H](C)Cl', + 'C/C(F)=C/[C@@H](C)Cl',])) + if __name__ == '__main__': unittest.main() From 6ed76d9fffc46eb1f5efb19a05bf6a0ab4572e54 Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Tue, 26 Sep 2017 19:00:53 +0200 Subject: [PATCH 33/44] Expose the MolBundle to python (#1583) * backup * initial mol bundle wrapper * Move the substructure matching wrapper code to a template header file to clean stuff up. * update python docs --- Code/GraphMol/Wrap/CMakeLists.txt | 2 +- Code/GraphMol/Wrap/Mol.cpp | 80 +++----- Code/GraphMol/Wrap/MolBundle.cpp | 195 ++++++++++++++++++++ Code/GraphMol/Wrap/ResonanceMolSupplier.cpp | 33 ++-- Code/GraphMol/Wrap/rdchem.cpp | 2 + Code/GraphMol/Wrap/rough_test.py | 28 +++ Code/GraphMol/Wrap/substructmethods.h | 68 +++++++ 7 files changed, 329 insertions(+), 79 deletions(-) create mode 100644 Code/GraphMol/Wrap/MolBundle.cpp create mode 100644 Code/GraphMol/Wrap/substructmethods.h diff --git a/Code/GraphMol/Wrap/CMakeLists.txt b/Code/GraphMol/Wrap/CMakeLists.txt index d3e62eb11..5c0a5d089 100644 --- a/Code/GraphMol/Wrap/CMakeLists.txt +++ b/Code/GraphMol/Wrap/CMakeLists.txt @@ -1,7 +1,7 @@ rdkit_python_extension(rdchem rdchem.cpp Table.cpp Atom.cpp Bond.cpp Mol.cpp Conformer.cpp RingInfo.cpp EditableMol.cpp MonomerInfo.cpp - ResonanceMolSupplier.cpp + ResonanceMolSupplier.cpp MolBundle.cpp DEST Chem LINK_LIBRARIES SmilesParse ChemTransforms SubstructMatch GraphMol RDGeometryLib RDGeneral RDBoost) diff --git a/Code/GraphMol/Wrap/Mol.cpp b/Code/GraphMol/Wrap/Mol.cpp index 43b051eb3..23375227c 100644 --- a/Code/GraphMol/Wrap/Mol.cpp +++ b/Code/GraphMol/Wrap/Mol.cpp @@ -14,6 +14,8 @@ #include "rdchem.h" #include "seqs.hpp" #include "props.hpp" +#include "substructmethods.h" + // ours #include #include @@ -82,53 +84,6 @@ bool HasSubstructMatchStr(std::string pkl, const ROMol &query, return hasM; } -bool HasSubstructMatch(const ROMol &mol, const ROMol &query, - bool recursionPossible = true, bool useChirality = false, - bool useQueryQueryMatches = false) { - NOGIL gil; - MatchVectType res; - return SubstructMatch(mol, query, res, recursionPossible, useChirality, - useQueryQueryMatches); -} - -PyObject *convertMatches(MatchVectType &matches) { - PyObject *res = PyTuple_New(matches.size()); - MatchVectType::const_iterator i; - for (i = matches.begin(); i != matches.end(); i++) { - PyTuple_SetItem(res, i->first, PyInt_FromLong(i->second)); - } - return res; -} -PyObject *GetSubstructMatch(const ROMol &mol, const ROMol &query, - bool useChirality = false, - bool useQueryQueryMatches = false) { - MatchVectType matches; - { - NOGIL gil; - SubstructMatch(mol, query, matches, true, useChirality, - useQueryQueryMatches); - } - return convertMatches(matches); -} - -PyObject *GetSubstructMatches(const ROMol &mol, const ROMol &query, - bool uniquify = true, bool useChirality = false, - bool useQueryQueryMatches = false, - unsigned int maxMatches = 1000) { - std::vector matches; - int matched; - { - NOGIL gil; - matched = SubstructMatch(mol, query, matches, uniquify, true, useChirality, - useQueryQueryMatches, maxMatches); - } - PyObject *res = PyTuple_New(matched); - for (int idx = 0; idx < matched; idx++) { - PyTuple_SetItem(res, idx, convertMatches(matches[idx])); - } - return res; -} - unsigned int AddMolConformer(ROMol &mol, Conformer *conf, bool assignId = false) { Conformer *nconf = new Conformer(*conf); @@ -247,7 +202,8 @@ class ReadWriteMol : public RWMol { PRECONDITION(atom, "bad atom"); return addAtom(atom, true, false); }; - void ReplaceAtom(unsigned int idx, Atom *atom, bool updateLabel, bool preserveProps) { + void ReplaceAtom(unsigned int idx, Atom *atom, bool updateLabel, + bool preserveProps) { PRECONDITION(atom, "bad atom"); replaceAtom(idx, atom, updateLabel, preserveProps); }; @@ -402,7 +358,8 @@ struct mol_wrapper { " NOTE: bond indices start at 0\n") // substructures - .def("HasSubstructMatch", HasSubstructMatch, + .def("HasSubstructMatch", (bool (*)(const ROMol &m, const ROMol &query, + bool, bool, bool))HasSubstructMatch, (python::arg("self"), python::arg("query"), python::arg("recursionPossible") = true, python::arg("useChirality") = false, @@ -416,7 +373,9 @@ struct mol_wrapper { "matching\n\n" " - useQueryQueryMatches: use query-query matching logic\n\n" " RETURNS: True or False\n") - .def("GetSubstructMatch", GetSubstructMatch, + .def("GetSubstructMatch", + (PyObject * (*)(const ROMol &m, const ROMol &query, bool, bool)) + GetSubstructMatch, (python::arg("self"), python::arg("query"), python::arg("useChirality") = false, python::arg("useQueryQueryMatches") = false), @@ -437,7 +396,9 @@ struct mol_wrapper { " this molecule that matches the first atom in the " "query.\n") - .def("GetSubstructMatches", GetSubstructMatches, + .def("GetSubstructMatches", + (PyObject * (*)(const ROMol &m, const ROMol &query, bool, bool, + bool, unsigned int)) GetSubstructMatches, (python::arg("self"), python::arg("query"), python::arg("uniquify") = true, python::arg("useChirality") = false, @@ -694,25 +655,26 @@ struct mol_wrapper { "Remove the specified bond from the molecule") .def("AddBond", &ReadWriteMol::AddBond, - (python::arg("beginAtomIdx"), - python::arg("endAtomIdx"), + (python::arg("beginAtomIdx"), python::arg("endAtomIdx"), python::arg("order") = Bond::UNSPECIFIED), "add a bond, returns the new number of bonds") - .def("AddAtom", &ReadWriteMol::AddAtom, - (python::arg("atom")), + .def("AddAtom", &ReadWriteMol::AddAtom, (python::arg("atom")), "add an atom, returns the index of the newly added atom") .def("ReplaceAtom", &ReadWriteMol::ReplaceAtom, (python::arg("index"), python::arg("newAtom"), - python::arg("updateLabel")=false, python::arg("preserveProps")=false), + python::arg("updateLabel") = false, + python::arg("preserveProps") = false), "replaces the specified atom with the provided one\n" "If updateLabel is True, the new atom becomes the active atom\n" - "If preserveProps is True preserve keep the existing props unless explicit set on the new atom") + "If preserveProps is True preserve keep the existing props unless " + "explicit set on the new atom") .def("ReplaceBond", &ReadWriteMol::ReplaceBond, (python::arg("index"), python::arg("newBond"), - python::arg("preserveProps")=false), + python::arg("preserveProps") = false), "replaces the specified bond with the provided one.\n" - "If preserveProps is True preserve keep the existing props unless explicit set on the new bond") + "If preserveProps is True preserve keep the existing props unless " + "explicit set on the new bond") .def("GetMol", &ReadWriteMol::GetMol, "Returns a Mol (a normal molecule)", python::return_value_policy()); diff --git a/Code/GraphMol/Wrap/MolBundle.cpp b/Code/GraphMol/Wrap/MolBundle.cpp new file mode 100644 index 000000000..249b38d2a --- /dev/null +++ b/Code/GraphMol/Wrap/MolBundle.cpp @@ -0,0 +1,195 @@ +// +// Copyright (C) 2017 Greg Landrum +// +// @@ All Rights Reserved @@ +// This file is part of the RDKit. +// The contents are covered by the terms of the BSD license +// which is included in the file license.txt, found at the root +// of the RDKit source tree. +// + +#define NO_IMPORT_ARRAY +#include +#include + +// ours +#include +#include +#include +#include + +#include "substructmethods.h" +namespace python = boost::python; + +namespace RDKit { + +std::string molBundleClassDoc = + "A class for storing gropus of related molecules.\n\ + Here related means that the molecules have to have the same number of atoms.\n\ +\n"; +struct molbundle_wrap { + static void wrap() { + python::class_( + "MolBundle", molBundleClassDoc.c_str(), python::init<>()) + .def("__getitem__", &MolBundle::getMol) + .def("__len__", &MolBundle::size) + .def("AddMol", &MolBundle::addMol) + .def("GetMol", &MolBundle::getMol) + .def("Size", &MolBundle::size) + + // substructures + .def("HasSubstructMatch", + (bool (*)(const MolBundle &m, const ROMol &query, bool, bool, + bool))HasSubstructMatch, + (python::arg("self"), python::arg("query"), + python::arg("recursionPossible") = true, + python::arg("useChirality") = false, + python::arg("useQueryQueryMatches") = false), + "Queries whether or not any molecule in the bundle contains a " + "particular substructure.\n\n" + " ARGUMENTS:\n" + " - query: a Molecule\n\n" + " - recursionPossible: (optional)\n\n" + " - useChirality: enables the use of stereochemistry in the " + "matching\n\n" + " - useQueryQueryMatches: use query-query matching logic\n\n" + " RETURNS: True or False\n") + .def("GetSubstructMatch", + (PyObject * (*)(const MolBundle &m, const ROMol &query, bool, + bool))GetSubstructMatch, + (python::arg("self"), python::arg("query"), + python::arg("useChirality") = false, + python::arg("useQueryQueryMatches") = false), + "Returns the indices of the atoms from the first molecule in a " + "bundle that matches a substructure query.\n\n" + " ARGUMENTS:\n" + " - query: a Molecule\n\n" + " - useChirality: enables the use of stereochemistry in the " + "matching\n\n" + " - useQueryQueryMatches: use query-query matching logic\n\n" + " RETURNS: a tuple of integers\n\n" + " NOTES:\n" + " - only a single match is returned\n" + " - the ordering of the indices corresponds to the atom " + "ordering\n" + " in the query. For example, the first index is for the " + "atom in\n" + " this molecule that matches the first atom in the " + "query.\n") + .def("GetSubstructMatches", + (PyObject * (*)(const MolBundle &m, const ROMol &query, bool, bool, + bool, unsigned int))GetSubstructMatches, + (python::arg("self"), python::arg("query"), + python::arg("uniquify") = true, + python::arg("useChirality") = false, + python::arg("useQueryQueryMatches") = false, + python::arg("maxMatches") = 1000), + "Returns tuple of all indices of the atoms from the first " + "molecule in a bundle that matches a substructure query.\n\n" + " ARGUMENTS:\n" + " - query: a molecule.\n" + " - uniquify: (optional) determines whether or not the " + "matches " + "are uniquified.\n" + " Defaults to 1.\n\n" + " - useChirality: enables the use of stereochemistry in the " + "matching\n\n" + " - useQueryQueryMatches: use query-query matching logic\n\n" + " - maxMatches: The maximum number of matches that will be " + "returned.\n" + " In high-symmetry cases with medium-sized " + "molecules, it is\n" + " very easy to end up with a combinatorial " + "explosion in the\n" + " number of possible matches. This argument " + "prevents that from\n" + " having unintended consequences\n\n" + " RETURNS: a tuple of tuples of integers\n\n" + " NOTE:\n" + " - the ordering of the indices corresponds to the atom " + "ordering\n" + " in the query. For example, the first index is for the " + "atom in\n" + " this molecule that matches the first atom in the " + "query.\n") + .def("HasSubstructMatch", + (bool (*)(const MolBundle &m, const MolBundle &query, bool, bool, + bool))HasSubstructMatch, + (python::arg("self"), python::arg("query"), + python::arg("recursionPossible") = true, + python::arg("useChirality") = false, + python::arg("useQueryQueryMatches") = false), + "Queries whether or not any molecule in the first bundle matches " + "any molecule in the second bundle.\n\n" + " ARGUMENTS:\n" + " - query: a MolBundle\n\n" + " - recursionPossible: (optional)\n\n" + " - useChirality: enables the use of stereochemistry in the " + "matching\n\n" + " - useQueryQueryMatches: use query-query matching logic\n\n" + " RETURNS: True or False\n") + .def("GetSubstructMatch", + (PyObject * (*)(const MolBundle &m, const MolBundle &query, bool, + bool))GetSubstructMatch, + (python::arg("self"), python::arg("query"), + python::arg("useChirality") = false, + python::arg("useQueryQueryMatches") = false), + "Returns the indices of the atoms from the first molecule in a " + "bundle that matches a substructure query from a bundle.\n\n" + " ARGUMENTS:\n" + " - query: a MolBundle\n\n" + " - useChirality: enables the use of stereochemistry in the " + "matching\n\n" + " - useQueryQueryMatches: use query-query matching logic\n\n" + " RETURNS: a tuple of integers\n\n" + " NOTES:\n" + " - only a single match is returned\n" + " - the ordering of the indices corresponds to the atom " + "ordering\n" + " in the query. For example, the first index is for the " + "atom in\n" + " this molecule that matches the first atom in the " + "query.\n") + + .def("GetSubstructMatches", + (PyObject * (*)(const MolBundle &m, const MolBundle &query, bool, + bool, bool, unsigned int))GetSubstructMatches, + (python::arg("self"), python::arg("query"), + python::arg("uniquify") = true, + python::arg("useChirality") = false, + python::arg("useQueryQueryMatches") = false, + python::arg("maxMatches") = 1000), + "Returns tuple of all indices of the atoms from the first " + "molecule in a bundle that matches a substructure query from the " + "second bundle.\n\n" + " ARGUMENTS:\n" + " - query: a MolBundle.\n" + " - uniquify: (optional) determines whether or not the " + "matches " + "are uniquified.\n" + " Defaults to 1.\n\n" + " - useChirality: enables the use of stereochemistry in the " + "matching\n\n" + " - useQueryQueryMatches: use query-query matching logic\n\n" + " - maxMatches: The maximum number of matches that will be " + "returned.\n" + " In high-symmetry cases with medium-sized " + "molecules, it is\n" + " very easy to end up with a combinatorial " + "explosion in the\n" + " number of possible matches. This argument " + "prevents that from\n" + " having unintended consequences\n\n" + " RETURNS: a tuple of tuples of integers\n\n" + " NOTE:\n" + " - the ordering of the indices corresponds to the atom " + "ordering\n" + " in the query. For example, the first index is for the " + "atom in\n" + " this molecule that matches the first atom in the " + "query.\n"); + }; +}; +} + +void wrap_molbundle() { RDKit::molbundle_wrap::wrap(); } diff --git a/Code/GraphMol/Wrap/ResonanceMolSupplier.cpp b/Code/GraphMol/Wrap/ResonanceMolSupplier.cpp index 9bba4c841..a33eb7ffc 100644 --- a/Code/GraphMol/Wrap/ResonanceMolSupplier.cpp +++ b/Code/GraphMol/Wrap/ResonanceMolSupplier.cpp @@ -23,21 +23,11 @@ #include #include "MolSupplier.h" +#include "substructmethods.h" namespace python = boost::python; namespace RDKit { -PyObject *convertMatches(MatchVectType &matches); -PyObject *GetResonanceSubstructMatch(ResonanceMolSupplier &suppl, - const ROMol &query, - bool useChirality = false, - bool useQueryQueryMatches = false) { - NOGIL gil; - MatchVectType matches; - SubstructMatch(suppl, query, matches, true, useChirality, - useQueryQueryMatches); - return convertMatches(matches); -} PyObject *GetResonanceSubstructMatches( ResonanceMolSupplier &suppl, const ROMol &query, bool uniquify = false, @@ -105,11 +95,13 @@ struct resmolsup_wrap { python::init( (python::arg("mol"), python::arg("flags") = 0, python::arg("maxStructs") = 1000))) - .def("__iter__", (ResonanceMolSupplier * (*)(ResonanceMolSupplier *)) & - MolSupplIter, - python::return_internal_reference<1>()) - .def(NEXT_METHOD, (ROMol * (*)(ResonanceMolSupplier *)) & - MolSupplNextAcceptNullLastMolecule, + .def( + "__iter__", + (ResonanceMolSupplier * (*)(ResonanceMolSupplier *)) & MolSupplIter, + python::return_internal_reference<1>()) + .def(NEXT_METHOD, + (ROMol * (*)(ResonanceMolSupplier *)) & + MolSupplNextAcceptNullLastMolecule, "Returns the next resonance structure in the supplier. Raises " "_StopIteration_ on end.\n", python::return_value_policy()) @@ -136,8 +128,9 @@ struct resmolsup_wrap { ResonanceMolSupplier::getAtomConjGrpIdx, "Given an atom index, it returns the index of the conjugated group" "the atom belongs to, or -1 if it is not conjugated\n") - .def("SetNumThreads", (void (ResonanceMolSupplier::*)(unsigned int)) & - ResonanceMolSupplier::setNumThreads, + .def("SetNumThreads", + (void (ResonanceMolSupplier::*)(unsigned int)) & + ResonanceMolSupplier::setNumThreads, "Sets the number of threads to be used to enumerate resonance\n" "structures (defaults to 1; 0 selects the number of concurrent\n" "threads supported by the hardware; negative values are added\n" @@ -149,7 +142,9 @@ struct resmolsup_wrap { .def("GetIsEnumerated", &ResonanceMolSupplier::getIsEnumerated, "Returns true if resonance structure enumeration has already " "happened\n") - .def("GetSubstructMatch", GetResonanceSubstructMatch, + .def("GetSubstructMatch", + (PyObject * (*)(ResonanceMolSupplier & m, const ROMol &query, bool, + bool)) GetSubstructMatch, (python::arg("self"), python::arg("query"), python::arg("useChirality") = false, python::arg("useQueryQueryMatches") = false), diff --git a/Code/GraphMol/Wrap/rdchem.cpp b/Code/GraphMol/Wrap/rdchem.cpp index bcf36198c..5ff8a377e 100644 --- a/Code/GraphMol/Wrap/rdchem.cpp +++ b/Code/GraphMol/Wrap/rdchem.cpp @@ -51,6 +51,7 @@ void wrap_ringinfo(); void wrap_EditableMol(); void wrap_monomerinfo(); void wrap_resmolsupplier(); +void wrap_molbundle(); struct PySysErrWrite : std::ostream, std::streambuf { std::string prefix; @@ -187,6 +188,7 @@ BOOST_PYTHON_MODULE(rdchem) { wrap_ringinfo(); wrap_monomerinfo(); wrap_resmolsupplier(); + wrap_molbundle(); //********************************************* // diff --git a/Code/GraphMol/Wrap/rough_test.py b/Code/GraphMol/Wrap/rough_test.py index 7752b97ac..f03ead86d 100644 --- a/Code/GraphMol/Wrap/rough_test.py +++ b/Code/GraphMol/Wrap/rough_test.py @@ -4369,6 +4369,34 @@ M END except RuntimeError: pass + def testMolBundles1(self): + b = Chem.MolBundle() + smis = ('CC(Cl)(F)CC(F)(Br)','C[C@](Cl)(F)C[C@H](F)(Br)','C[C@](Cl)(F)C[C@@H](F)(Br)') + for smi in smis: + b.AddMol(Chem.MolFromSmiles(smi)) + self.assertEqual(len(b),3) + self.assertEqual(b.Size(),3) + self.assertRaises(IndexError,lambda:b[4]) + self.assertEqual(Chem.MolToSmiles(b[1],isomericSmiles=True), + Chem.MolToSmiles(Chem.MolFromSmiles(smis[1]),isomericSmiles=True)) + self.failUnless(b.HasSubstructMatch(Chem.MolFromSmiles('CC(Cl)(F)CC(F)(Br)'),useChirality=True)) + self.failUnless(b.HasSubstructMatch(Chem.MolFromSmiles('C[C@](Cl)(F)C[C@@H](F)(Br)'),useChirality=True)) + self.failUnless(b.HasSubstructMatch(Chem.MolFromSmiles('C[C@@](Cl)(F)C[C@@H](F)(Br)'),useChirality=False)) + self.failIf(b.HasSubstructMatch(Chem.MolFromSmiles('C[C@@](Cl)(F)C[C@@H](F)(Br)'),useChirality=True)) + + self.assertEqual(len(b.GetSubstructMatch(Chem.MolFromSmiles('CC(Cl)(F)CC(F)(Br)'),useChirality=True)),8) + self.assertEqual(len(b.GetSubstructMatch(Chem.MolFromSmiles('C[C@](Cl)(F)C[C@@H](F)(Br)'),useChirality=True)),8) + self.assertEqual(len(b.GetSubstructMatch(Chem.MolFromSmiles('C[C@@](Cl)(F)C[C@@H](F)(Br)'),useChirality=False)),8) + self.assertEqual(len(b.GetSubstructMatch(Chem.MolFromSmiles('C[C@@](Cl)(F)C[C@@H](F)(Br)'),useChirality=True)),0) + + self.assertEqual(len(b.GetSubstructMatches(Chem.MolFromSmiles('CC(Cl)(F)CC(F)(Br)'),useChirality=True)),1) + self.assertEqual(len(b.GetSubstructMatches(Chem.MolFromSmiles('C[C@](Cl)(F)C[C@@H](F)(Br)'),useChirality=True)),1) + self.assertEqual(len(b.GetSubstructMatches(Chem.MolFromSmiles('C[C@@](Cl)(F)C[C@@H](F)(Br)'),useChirality=False)),1) + self.assertEqual(len(b.GetSubstructMatches(Chem.MolFromSmiles('C[C@@](Cl)(F)C[C@@H](F)(Br)'),useChirality=True)),0) + self.assertEqual(len(b.GetSubstructMatches(Chem.MolFromSmiles('CC(Cl)(F)CC(F)(Br)'),useChirality=True)[0]),8) + self.assertEqual(len(b.GetSubstructMatches(Chem.MolFromSmiles('C[C@](Cl)(F)C[C@@H](F)(Br)'),useChirality=True)[0]),8) + self.assertEqual(len(b.GetSubstructMatches(Chem.MolFromSmiles('C[C@@](Cl)(F)C[C@@H](F)(Br)'),useChirality=False)[0]),8) + if __name__ == '__main__': if "RDTESTCASE" in os.environ: suite = unittest.TestSuite() diff --git a/Code/GraphMol/Wrap/substructmethods.h b/Code/GraphMol/Wrap/substructmethods.h new file mode 100644 index 000000000..86c702a99 --- /dev/null +++ b/Code/GraphMol/Wrap/substructmethods.h @@ -0,0 +1,68 @@ +// +// Copyright (C) 2017 Greg Landrum +// +// @@ All Rights Reserved @@ +// This file is part of the RDKit. +// The contents are covered by the terms of the BSD license +// which is included in the file license.txt, found at the root +// of the RDKit source tree. +// +#ifndef RDKIT_SUBSTRUCT_METHODS_H +#define RDKIT_SUBSTRUCT_METHODS_H +#include +#include +#include + +namespace RDKit { + +inline PyObject *convertMatches(MatchVectType &matches) { + PyObject *res = PyTuple_New(matches.size()); + MatchVectType::const_iterator i; + for (i = matches.begin(); i != matches.end(); i++) { + PyTuple_SetItem(res, i->first, PyInt_FromLong(i->second)); + } + return res; +} + +template +bool HasSubstructMatch(T1 &mol, T2 &query, bool recursionPossible = true, + bool useChirality = false, + bool useQueryQueryMatches = false) { + NOGIL gil; + MatchVectType res; + return SubstructMatch(mol, query, res, recursionPossible, useChirality, + useQueryQueryMatches); +} + +template +PyObject *GetSubstructMatch(T1 &mol, T2 &query, bool useChirality = false, + bool useQueryQueryMatches = false) { + MatchVectType matches; + { + NOGIL gil; + SubstructMatch(mol, query, matches, true, useChirality, + useQueryQueryMatches); + } + return convertMatches(matches); +} + +template +PyObject *GetSubstructMatches(T1 &mol, T2 &query, bool uniquify = true, + bool useChirality = false, + bool useQueryQueryMatches = false, + unsigned int maxMatches = 1000) { + std::vector matches; + int matched; + { + NOGIL gil; + matched = SubstructMatch(mol, query, matches, uniquify, true, useChirality, + useQueryQueryMatches, maxMatches); + } + PyObject *res = PyTuple_New(matched); + for (int idx = 0; idx < matched; idx++) { + PyTuple_SetItem(res, idx, convertMatches(matches[idx])); + } + return res; +} +} // end of RDKit namespace +#endif From f3a998f9fe4bde8bbbb06bf35f090dcfc57dc8ef Mon Sep 17 00:00:00 2001 From: Brian Cole Date: Wed, 27 Sep 2017 02:29:02 -0400 Subject: [PATCH 34/44] Use self.assertEqual for better failing test case error messages. (#1595) My fingers are used to having py.test run my test cases! --- rdkit/Chem/UnitTestMol3D.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rdkit/Chem/UnitTestMol3D.py b/rdkit/Chem/UnitTestMol3D.py index be9c92f59..530255882 100755 --- a/rdkit/Chem/UnitTestMol3D.py +++ b/rdkit/Chem/UnitTestMol3D.py @@ -239,12 +239,12 @@ class TestCase(unittest.TestCase): opts = AllChem.StereoEnumerationOptions(rand=None, maxIsomers=3) mol = Chem.MolFromSmiles('CC(F)=CC(Cl)C') smiles = set(Chem.MolToSmiles(i, isomericSmiles=True) for i in AllChem.EnumerateStereoisomers(mol, opts)) - assert smiles == set(['C/C(F)=C/[C@@H](C)Cl', 'C/C(F)=C\\[C@H](C)Cl', 'C/C(F)=C\\[C@@H](C)Cl']) + self.assertEqual(smiles, set(['C/C(F)=C/[C@@H](C)Cl', 'C/C(F)=C\\[C@H](C)Cl', 'C/C(F)=C\\[C@@H](C)Cl'])) opts = AllChem.StereoEnumerationOptions(rand=0xDEADBEEF) mol = Chem.MolFromSmiles('c1ccc2c(c1)C(=O)N(C2=O)C3CCC(=O)NC3=O') smiles = set(Chem.MolToSmiles(i, isomericSmiles=True) for i in AllChem.EnumerateStereoisomers(mol, opts)) - assert smiles == set(['O=C1CC[C@@H](N2C(=O)c3ccccc3C2=O)C(=O)N1', 'O=C1CC[C@H](N2C(=O)c3ccccc3C2=O)C(=O)N1']) + self.assertEqual(smiles, set(['O=C1CC[C@@H](N2C(=O)c3ccccc3C2=O)C(=O)N1', 'O=C1CC[C@H](N2C(=O)c3ccccc3C2=O)C(=O)N1'])) class DeterministicRandom(random.Random): def __init__(self): @@ -259,7 +259,7 @@ class TestCase(unittest.TestCase): opts = AllChem.StereoEnumerationOptions(rand=rand, maxIsomers=3) mol = Chem.MolFromSmiles('CCCC(=C(CCl)C(C)CBr)[C@H](F)C(C)C') smiles = [Chem.MolToSmiles(i, isomericSmiles=True) for i in AllChem.EnumerateStereoisomers(mol, opts)] - assert smiles == ['CCC/C(=C(\\CCl)[C@H](C)CBr)[C@H](F)C(C)C', 'CCC/C(=C(\\CCl)[C@@H](C)CBr)[C@H](F)C(C)C', 'CCC/C(=C(/CCl)[C@H](C)CBr)[C@H](F)C(C)C'] + self.assertEqual(smiles, ['CCC/C(=C(\\CCl)[C@H](C)CBr)[C@H](F)C(C)C', 'CCC/C(=C(\\CCl)[C@@H](C)CBr)[C@H](F)C(C)C', 'CCC/C(=C(/CCl)[C@H](C)CBr)[C@H](F)C(C)C']) def testEnumerateStereoisomersOnlyUnassigned(self): # shouldn't enumerate anything From 3fb234ecd717380afdff7a6d32560a5b689ce62b Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Wed, 27 Sep 2017 08:31:57 +0200 Subject: [PATCH 35/44] small cleanup work --- rdkit/Chem/UnitTestMol3D.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/rdkit/Chem/UnitTestMol3D.py b/rdkit/Chem/UnitTestMol3D.py index 530255882..7a8bb61f6 100755 --- a/rdkit/Chem/UnitTestMol3D.py +++ b/rdkit/Chem/UnitTestMol3D.py @@ -1,5 +1,3 @@ -# $Id$ -# """unit testing code for 3D stuff """ @@ -265,17 +263,17 @@ class TestCase(unittest.TestCase): # shouldn't enumerate anything fully_assigned = Chem.MolFromSmiles('C/C(F)=C/[C@@H](C)Cl') smiles = set(Chem.MolToSmiles(i, isomericSmiles=True) for i in AllChem.EnumerateStereoisomers(fully_assigned)) - self.assertEquals(smiles, set(['C/C(F)=C/[C@@H](C)Cl'])) + self.assertEqual(smiles, set(['C/C(F)=C/[C@@H](C)Cl'])) # should only enuemrate the bond stereo partially_assigned = Chem.MolFromSmiles('CC(F)=C[C@@H](C)Cl') smiles = set(Chem.MolToSmiles(i, isomericSmiles=True) for i in AllChem.EnumerateStereoisomers(partially_assigned)) - self.assertEquals(smiles, set(['C/C(F)=C/[C@@H](C)Cl', 'C/C(F)=C\\[C@@H](C)Cl'])) + self.assertEqual(smiles, set(['C/C(F)=C/[C@@H](C)Cl', 'C/C(F)=C\\[C@@H](C)Cl'])) # should enumerate everything opts = AllChem.StereoEnumerationOptions(onlyUnassigned=False) smiles = set(Chem.MolToSmiles(i, isomericSmiles=True) for i in AllChem.EnumerateStereoisomers(fully_assigned, opts)) - self.assertEquals(smiles, set(['C/C(F)=C\\[C@@H](C)Cl', + self.assertEqual(smiles, set(['C/C(F)=C\\[C@@H](C)Cl', 'C/C(F)=C\\[C@H](C)Cl', 'C/C(F)=C/[C@H](C)Cl', 'C/C(F)=C/[C@@H](C)Cl',])) From 9098291b95c725e7e397fd9ca2bb8a646a98acfb Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Mon, 25 Sep 2017 06:01:13 +0200 Subject: [PATCH 36/44] start release notes --- ReleaseNotes.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/ReleaseNotes.md b/ReleaseNotes.md index b81268a68..fa40406f6 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -1,3 +1,26 @@ +# Release_2017.09.1 +(Changes relative to Release_2017.03.1) + +## Important +- The fix for bug #1567 changes the way fragment SMILES are canonicalized. + MolFragmentToSmiles() and canonicalizeFragment() will now often return + different results + +## Acknowledgements: +Brian Cole, Peter Gedeck, Guillaume Godin, Malitha Kabir, Tuomo Kalliokoski, +Brian Kelley, Noel O'Boyle, Matthew O'Meara, Pavel Polishchuk, Cameron Pye, +Christian Ribeaud, Stephen Roughley, Patrick Savery, Roger Sayle, +Nadine Schneider, Matt Swain, Paolo Tosco, Alain Vaucher, Sam Webb, +'phenethyl', 'xiaotaw' + +## Highlights: + +## New Features and Enhancements: + +## Bug Fixes: + + + # Release_2017.03.1 (Changes relative to Release_2016.09.1) From 3e515ba3b372fa028f77bb0f967697f5fa966567 Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Thu, 28 Sep 2017 12:56:10 +0200 Subject: [PATCH 37/44] start progress on release notes --- ReleaseNotes.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ReleaseNotes.md b/ReleaseNotes.md index fa40406f6..1ae8f1f1d 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -14,6 +14,16 @@ Nadine Schneider, Matt Swain, Paolo Tosco, Alain Vaucher, Sam Webb, 'phenethyl', 'xiaotaw' ## Highlights: +- The new R-Group decomposition code provides a flexible and powerful tool for + building R-group tables or datasets look in $RDBASE/Docs/Notebooks for + example notebooks showing how to use this. +- Drawing of chemical reactions has been greatly improved and is now done using + the C++ rendering code. +- The MaxMinPicker is dramatically faster. +- New descriptors: the QED descriptor has been added as have a large collection + of new 3D descriptors and implementations of the USR and USRCAT fingerprints. + + ## New Features and Enhancements: From 6e3a6b70bf395dac9710305ff0e32d2d9d903ad8 Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Fri, 29 Sep 2017 04:39:56 +0200 Subject: [PATCH 38/44] update release notes --- ReleaseNotes.md | 128 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 1ae8f1f1d..7a17df8f3 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -26,8 +26,136 @@ Nadine Schneider, Matt Swain, Paolo Tosco, Alain Vaucher, Sam Webb, ## New Features and Enhancements: + - Bring back USR and USRCAT descriptors + (github pull #1417 from greglandrum) + - Generate a warning for conflicting bond directions + (github issue #1423 from greglandrum) + - expose and test GetDrawCoords() + (github pull #1427 from greglandrum) + - Improvement suggestions for SaltRemover + (github issue #1431 from ribeaud) + - Remove obsolete scripts from Scripts dir + (github pull #1440 from greglandrum) + - Support drawing reactions from C++ + (github pull #1444 from greglandrum) + - QED code with unit test file + (github pull #1445 from gedeck) + - Add support for other datatypes to ConvertToNumpyArray + (github issue #1447 from pyeguy) + - - updated FindCairo.cmake + (github pull #1455 from ptosco) + - - fixes PgSQL CMakeLists.txt to enable conda build on Windows + (github pull #1457 from ptosco) + - Some cleanups to make Travis builds faster + (github pull #1464 from greglandrum) + - ExplainPairScore does not support includeChirality=True + (github issue #1466 from xiaotaw) + - Add a collection of new 3D descriptors + (github pull #1467 from greglandrum) + - Update cartridge documentation to use ChEMBL 23 + (github issue #1491 from greglandrum) + - First entry of the SubstructLibrary module + (github pull #1493 from bp-kelley) + - assorted fixes to get the current master branch to build on Windows + (github pull #1495 from ptosco) + - Support black and white molecule drawing + (github issue #1510 from greglandrum) + - Missing def_readwrite for backgroundColour in rdMolDraw2D.cpp + (github issue #1519 from goraj) + - Adds canonicalization of atom maps + (github pull #1521 from bp-kelley) + - Implement stereoisomer enumeration + (github pull #1531 from greglandrum) + - Add a MolBundle class + (github pull #1537 from greglandrum) + - Provide support for color palettes in MolDraw2D + (github pull #1546 from greglandrum) + - A few reaction drawing tweaks + (github pull #1549 from greglandrum) + - R group improvements + (github pull #1552 from greglandrum) + - Add a canned Atom query for heavy atom degree + (github issue #1563 from greglandrum) + - Adds FreeSASA adapter + (github pull #1565 from bp-kelley) + - Added C++ version of getBestRMS() + (github pull #1568 from psavery) + - SMILES lexer optimization/enhancement + (github pull #1575 from greglandrum) + - Update IPythonConsole and PandasTools to use new drawing code + (github pull #1577 from greglandrum) + - Squashes warnings on cygwin + (github pull #1578 from bp-kelley) + - Support continuous highlighting in drawMolecules(). + (github pull #1579 from greglandrum) + - Enhanced Similarity Maps depiction + (github pull #1594 from gerebtzoff) ## Bug Fixes: + - RDKit gets stuck on PubChem CID 102128817 + (github issue #1281 from TuomoKalliokoski) + - MMP code not including molecules with no cuts + (github issue #1406 from greglandrum) + - Fixes PandasTools to also work with pandas 0.20 + (github pull #1410 from bp-kelley) + - csharp input files out of date + (github issue #1413 from greglandrum) + - Fix cxsmiles parse on VS2008 + (github pull #1415 from mcs07) + - MaxMinPicker picking non-existent element + (github issue #1421 from greglandrum) + - _isCallable clashes with Celery + (github issue #1434 from momeara) + - Impossible to build the RDKit from source without Python installed + (github issue #1435 from greglandrum) + - RemoveHs() removes H atom attached to dummy if it came from AddHs() + (github issue #1439 from DrrDom) + - fix a couple failing windows tests related to temp file removal + (github pull #1446 from greglandrum) + - SanitizeRxn fails with a runtime exception when unused Rlabels are in product + (github issue #1448 from bp-kelley) + - String module conversion bug + (github pull #1452 from coleb) + - GetConformerRMS() documentation is misleading + (github pull #1459 from greglandrum) + - URANGE_CHECK not doing its job in RWMol::addBond + (github issue #1461 from baoilleach) + - ExplainPairScore does not support includeChirality=True + (github issue #1466 from xiaotaw) + - MolToSmarts does not include atom-map or isotope info for molecules built from SMILES + (github issue #1472 from greglandrum) + - AdjustQueryProperties() removing properties from dummy atoms + (github issue #1474 from greglandrum) + - Fixes lookup for HELM Monomer 'D' + (github pull #1477 from bp-kelley) + - Aromatic rings composed solely of dummy atoms should not be kekulized + (github issue #1478 from bp-kelley) + - Directly specify rotor model used in QED. + (github pull #1483 from bp-kelley) + - Unicode problem with pidPS tests on Mac + (github issue #1490 from greglandrum) + - Pattern fingerprint setting bad bits with degree zero atoms + (github issue #1496 from greglandrum) + - Remove xlocale header + (github pull #1501 from greglandrum) + - Fixes atom documentation + (github pull #1505 from bp-kelley) + - TypeError from PandasTools.SaveXlsxFromFrame + (github issue #1507 from pyeguy) + - Removes trailing spaces after \ to fix windows compilation errors + (github pull #1516 from bp-kelley) + - prepareMolForDrawing() not in SWIG wrappers + (github issue #1522 from greglandrum) + - Bond is missing IsInRing methods in Java wrapper + (github issue #1535 from sroughley) + - Fixes blanking of non-query atom data when QueryAtomData was being pi… + (github pull #1541 from bp-kelley) + - - Fixes failing build with MSVC + (github pull #1547 from ptosco) + - Kekulization error with cores from R-Group Decomposition + (github issue #1550 from greglandrum) + - Fixes double free for Dict::update + (github pull #1571 from bp-kelley) From a2ba841041527c630bda02cc356356a325688343 Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Fri, 29 Sep 2017 04:41:37 +0200 Subject: [PATCH 39/44] release prep --- CMakeLists.txt | 4 ++-- Docs/Book/conf.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index da0eac6b0..b979b90a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,7 +82,7 @@ set(RDK_PYTHON_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/rdkit") # Config variables: set(RDKit_Year "2017") set(RDKit_Month "09") -set(RDKit_Revision "1.dev1") +set(RDKit_Revision "1.b1") set(RDKit_ABI "1") set(RDKit_CodeDir "${CMAKE_CURRENT_SOURCE_DIR}/Code") @@ -322,7 +322,7 @@ else(RDK_TEST_COVERAGE) if (NOT CYGWIN) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") - endif() + endif() endif() if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") # We don't on C_FLAGS warnings to keep Avalon compiling quiet diff --git a/Docs/Book/conf.py b/Docs/Book/conf.py index 3b947370d..e2902597d 100644 --- a/Docs/Book/conf.py +++ b/Docs/Book/conf.py @@ -53,7 +53,7 @@ copyright = u'2017, Greg Landrum' # The short X.Y version. version = '2017.09' # The full version, including alpha/beta/rc tags. -release = '2017.09.1.dev1' +release = '2017.09.1.b1' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. From a6faf74e1cac9bd198757c8715ed146ede162e02 Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Mon, 2 Oct 2017 05:02:26 +0200 Subject: [PATCH 40/44] switch to using boost::isnan instead of std::isnan, which does not exist in MSVC2010 (#1598) --- Code/GraphMol/Descriptors/AUTOCORR3D.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Code/GraphMol/Descriptors/AUTOCORR3D.cpp b/Code/GraphMol/Descriptors/AUTOCORR3D.cpp index 4a95a57b2..0fc2fe94e 100644 --- a/Code/GraphMol/Descriptors/AUTOCORR3D.cpp +++ b/Code/GraphMol/Descriptors/AUTOCORR3D.cpp @@ -42,6 +42,7 @@ #include #include #include +#include using namespace Eigen; namespace RDKit { @@ -117,42 +118,42 @@ void get3DautocorrelationDesc(double* dist3D, double* topologicaldistance, tmp = Wu.transpose() * RBi * Wu; dtmp = (double)tmp(0); - if (std::isnan(dtmp)) dtmp = 0.0; + if (boost::math::isnan(dtmp)) dtmp = 0.0; TDBmat[0][i] = dtmp; tmp = Wm.transpose() * RBi * Wm; dtmp = (double)tmp(0); - if (std::isnan(dtmp)) dtmp = 0.0; + if (boost::math::isnan(dtmp)) dtmp = 0.0; TDBmat[1][i] = dtmp; tmp = Wv.transpose() * RBi * Wv; dtmp = (double)tmp(0); - if (std::isnan(dtmp)) dtmp = 0.0; + if (boost::math::isnan(dtmp)) dtmp = 0.0; TDBmat[2][i] = dtmp; tmp = We.transpose() * RBi * We; dtmp = (double)tmp(0); - if (std::isnan(dtmp)) dtmp = 0.0; + if (boost::math::isnan(dtmp)) dtmp = 0.0; TDBmat[3][i] = dtmp; tmp = Wp.transpose() * RBi * Wp; dtmp = (double)tmp(0); - if (std::isnan(dtmp)) dtmp = 0.0; + if (boost::math::isnan(dtmp)) dtmp = 0.0; TDBmat[4][i] = dtmp; tmp = Wi.transpose() * RBi * Wi; dtmp = (double)tmp(0); - if (std::isnan(dtmp)) dtmp = 0.0; + if (boost::math::isnan(dtmp)) dtmp = 0.0; TDBmat[5][i] = dtmp; tmp = Ws.transpose() * RBi * Ws; dtmp = (double)tmp(0); - if (std::isnan(dtmp)) dtmp = 0.0; + if (boost::math::isnan(dtmp)) dtmp = 0.0; TDBmat[6][i] = dtmp; tmp = Wr.transpose() * RBi * Wr; dtmp = (double)tmp(0); - if (std::isnan(dtmp)) dtmp = 0.0; + if (boost::math::isnan(dtmp)) dtmp = 0.0; TDBmat[7][i] = dtmp; delete[] Bimat; } From c0d3842df13e76ae58019ac45b189b43df06add1 Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Mon, 2 Oct 2017 09:37:18 +0200 Subject: [PATCH 41/44] get the new code building with the old compiler (#1601) --- Code/GraphMol/Descriptors/GETAWAY.cpp | 6 +++--- Code/GraphMol/Descriptors/MolData3Ddescriptors.cpp | 6 ++++-- Code/GraphMol/Descriptors/WHIM.cpp | 8 ++++---- Code/GraphMol/RGroupDecomposition/RGroupDecomp.cpp | 4 ++-- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/Code/GraphMol/Descriptors/GETAWAY.cpp b/Code/GraphMol/Descriptors/GETAWAY.cpp index 26f47cd56..0376028d8 100644 --- a/Code/GraphMol/Descriptors/GETAWAY.cpp +++ b/Code/GraphMol/Descriptors/GETAWAY.cpp @@ -66,7 +66,7 @@ namespace { MolData3Ddescriptors moldata3D; double roundn(double in, int factor) { - return round(in * pow(10, factor)) / pow(10, factor); + return round(in * pow(10., factor)) / pow(10., factor); } double* retreiveMat(MatrixXd matrix) { @@ -96,7 +96,7 @@ double round_to_n_digits(double x, int n) { return round(x * scale) / scale; } -bool IsClose(double a, double b, unsigned int n) { +bool IsClose(double a, double b, int n) { bool isclose = false; if (fabs(a - b) <= pow(0.1, n) * 1.1) { isclose = true; @@ -421,7 +421,7 @@ void getGETAWAYDesc(MatrixXd H, MatrixXd R, MatrixXd Adj, int numAtoms, // what about linear molecule ie (D=1) ? double HIC = 0.0; for (int i = 0; i < numAtoms; i++) { - HIC -= H(i, i) / D * log(H(i, i) / D) / log(2); + HIC -= H(i, i) / D * log(H(i, i) / D) / log(2.); } res[2] = roundn(HIC, 3); diff --git a/Code/GraphMol/Descriptors/MolData3Ddescriptors.cpp b/Code/GraphMol/Descriptors/MolData3Ddescriptors.cpp index db1136a5b..33248f0da 100644 --- a/Code/GraphMol/Descriptors/MolData3Ddescriptors.cpp +++ b/Code/GraphMol/Descriptors/MolData3Ddescriptors.cpp @@ -2,6 +2,8 @@ #include #include "MolData3Ddescriptors.h" #include +#include + #include "GraphMol/PartialCharges/GasteigerCharges.h" #include "GraphMol/PartialCharges/GasteigerParams.h" @@ -128,7 +130,7 @@ std::vector MolData3Ddescriptors::GetIState(const RDKit::ROMol& mol) { int N = GetPrincipalQuantumNumber(atNum); // principal quantum number double d = (double)degree - h; // degree-h if (d > 0) { - Is[i] = round(1000 * (4.0 / (N * N) * dv + 1.0) / d) / 1000; + Is[i] = boost::math::round(1000 * (4.0 / (N * N) * dv + 1.0) / d) / 1000; } } } @@ -153,7 +155,7 @@ std::vector MolData3Ddescriptors::GetIStateDrag( int N = GetPrincipalQuantumNumber(atNum); // principal quantum number double d = (double)degree - h; // degree-h if (d > 0) { - Is[i] = round(1000 * (4.0 / (N * N) * dv + 1.0) / d) / 1000; + Is[i] = boost::math::round(1000 * (4.0 / (N * N) * dv + 1.0) / d) / 1000; } } } diff --git a/Code/GraphMol/Descriptors/WHIM.cpp b/Code/GraphMol/Descriptors/WHIM.cpp index 75f52f62d..0f4131a58 100644 --- a/Code/GraphMol/Descriptors/WHIM.cpp +++ b/Code/GraphMol/Descriptors/WHIM.cpp @@ -49,7 +49,7 @@ namespace { MolData3Ddescriptors moldata3D; double roundn(double in, int factor) { - return round(in * pow(10, factor)) / pow(10, factor); + return round(in * pow(10., factor)) / pow(10., factor); } MatrixXd GetCenterMatrix(MatrixXd &Mat) { @@ -191,11 +191,11 @@ std::vector getWhimD(std::vector weigthvector, gamma[i] = 0.0; double gammainv=1.0; if (ns == 0) { - gammainv = 1.0 - (na / nAT) * log(1.0 / nAT) / log(2); + gammainv = 1.0 - (na / nAT) * log(1.0 / nAT) / log(2.); } if (ns > 0) { - gammainv = 1.0 - ((ns / nAT) * log(ns / nAT) / log(2) + - (na / nAT) * log(1.0 / nAT) / log(2)); + gammainv = 1.0 - ((ns / nAT) * log(ns / nAT) / log(2.) + + (na / nAT) * log(1.0 / nAT) / log(2.)); } gamma[i]=1.0/gammainv; } diff --git a/Code/GraphMol/RGroupDecomposition/RGroupDecomp.cpp b/Code/GraphMol/RGroupDecomposition/RGroupDecomp.cpp index 80f980709..b6b1093c8 100644 --- a/Code/GraphMol/RGroupDecomposition/RGroupDecomp.cpp +++ b/Code/GraphMol/RGroupDecomposition/RGroupDecomp.cpp @@ -567,7 +567,7 @@ struct RGroupDecompData { std::vector > atomsToAdd; // adds -R if necessary // Deal with user supplied labels - for (std::set::iterator it = userLabels.begin(); + for (std::set::const_iterator it = userLabels.begin(); it != userLabels.end(); ++it) { std::map::iterator atm = atoms.find(*it); if (atm == atoms.end()) continue; // label not used in the rgroup @@ -584,7 +584,7 @@ struct RGroupDecompData { } // Deal with non-user supplied labels - for (std::set::iterator it = indexLabels.begin(); + for (std::set::const_iterator it = indexLabels.begin(); it != indexLabels.end(); ++it) { std::map::iterator atm = atoms.find(*it); if (atm == atoms.end()) continue; // label not used in the rgroup From 28f8421644b2a8e4a24e64bd780b61f9178d7f0e Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Tue, 3 Oct 2017 23:46:06 +0200 Subject: [PATCH 42/44] set atom->setQuery() to delete old query (#1604) adjust the rest of the code to respect that --- Code/GraphMol/FileParsers/MolFileParser.cpp | 2 - Code/GraphMol/QueryAtom.h | 7 +- Code/GraphMol/QueryBond.h | 4 +- .../GraphMol/SmilesParse/smarts.tab.cpp.cmake | 135 +++++++++--------- Code/GraphMol/SmilesParse/smarts.yy | 3 - Code/GraphMol/Wrap/MolOps.cpp | 1 - 6 files changed, 73 insertions(+), 79 deletions(-) diff --git a/Code/GraphMol/FileParsers/MolFileParser.cpp b/Code/GraphMol/FileParsers/MolFileParser.cpp index 057fb92d5..f1fab35e4 100644 --- a/Code/GraphMol/FileParsers/MolFileParser.cpp +++ b/Code/GraphMol/FileParsers/MolFileParser.cpp @@ -813,10 +813,8 @@ void ParseNewAtomList(RWMol *mol, const std::string &text, unsigned int line) { if (!i) { a = new QueryAtom(*(mol->getAtomWithIdx(idx))); // replace the query: - Atom::QUERYATOM_QUERY *oq = a->getQuery(); a->setAtomicNum(atNum); a->setQuery(makeAtomNumQuery(atNum)); - delete oq; } else { a->expandQuery(makeAtomNumQuery(atNum), Queries::COMPOSITE_OR, true); } diff --git a/Code/GraphMol/QueryAtom.h b/Code/GraphMol/QueryAtom.h index c35d583da..0ef51e8a9 100644 --- a/Code/GraphMol/QueryAtom.h +++ b/Code/GraphMol/QueryAtom.h @@ -1,5 +1,5 @@ // -// Copyright (C) 2001-2006 Greg Landrum and Rational Discovery LLC +// Copyright (C) 2001-2017 Greg Landrum and Rational Discovery LLC // // @@ All Rights Reserved @@ // This file is part of the RDKit. @@ -43,7 +43,10 @@ class QueryAtom : public Atom { bool hasQuery() const { return dp_query != 0; }; //! replaces our current query with the value passed in - void setQuery(QUERYATOM_QUERY *what) { dp_query = what; } + void setQuery(QUERYATOM_QUERY *what) { + delete dp_query; + dp_query = what; + } //! returns our current query QUERYATOM_QUERY *getQuery() const { return dp_query; }; diff --git a/Code/GraphMol/QueryBond.h b/Code/GraphMol/QueryBond.h index fbbe0d2b8..97d3e4ff6 100644 --- a/Code/GraphMol/QueryBond.h +++ b/Code/GraphMol/QueryBond.h @@ -1,5 +1,5 @@ // -// Copyright (C) 2001-2006 Greg Landrum and Rational Discovery LLC +// Copyright (C) 2001-2017 Greg Landrum and Rational Discovery LLC // // @@ All Rights Reserved @@ // This file is part of the RDKit. @@ -65,7 +65,7 @@ class QueryBond : public Bond { //! replaces our current query with the value passed in void setQuery(QUERYBOND_QUERY *what) { // free up any existing query (Issue255): - if (dp_query) delete dp_query; + delete dp_query; dp_query = what; }; diff --git a/Code/GraphMol/SmilesParse/smarts.tab.cpp.cmake b/Code/GraphMol/SmilesParse/smarts.tab.cpp.cmake index 0c3446289..e3b0632e1 100644 --- a/Code/GraphMol/SmilesParse/smarts.tab.cpp.cmake +++ b/Code/GraphMol/SmilesParse/smarts.tab.cpp.cmake @@ -518,11 +518,11 @@ static const yytype_uint16 yyrline[] = 171, 206, 226, 241, 242, 253, 254, 255, 259, 282, 286, 291, 297, 306, 311, 318, 325, 342, 347, 352, 357, 362, 365, 369, 370, 374, 391, 415, 416, 420, - 421, 425, 426, 430, 431, 434, 435, 439, 440, 444, - 445, 449, 452, 455, 460, 465, 470, 476, 482, 483, - 491, 503, 508, 513, 517, 521, 525, 528, 529, 536, - 537, 543, 549, 555, 560, 567, 568, 569, 570, 571, - 572, 576, 577, 582, 583, 587, 588, 591, 592 + 421, 425, 426, 430, 431, 434, 435, 438, 439, 442, + 443, 446, 449, 452, 457, 462, 467, 473, 479, 480, + 488, 500, 505, 510, 514, 518, 522, 525, 526, 533, + 534, 540, 546, 552, 557, 564, 565, 566, 567, 568, + 569, 573, 574, 579, 580, 584, 585, 588, 589 }; #endif @@ -1908,110 +1908,107 @@ yyreduce: case 46: #line 435 "smarts.yy" /* yacc.c:1646 */ { - delete (yyvsp[-1].atom)->getQuery(); (yyvsp[-1].atom)->setQuery(makeAtomMinRingSizeQuery((yyvsp[0].ival))); } -#line 1915 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 1914 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 48: -#line 440 "smarts.yy" /* yacc.c:1646 */ +#line 439 "smarts.yy" /* yacc.c:1646 */ { - delete (yyvsp[-1].atom)->getQuery(); (yyvsp[-1].atom)->setQuery(makeAtomRingBondCountQuery((yyvsp[0].ival))); } -#line 1924 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 1922 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 50: -#line 445 "smarts.yy" /* yacc.c:1646 */ +#line 443 "smarts.yy" /* yacc.c:1646 */ { - delete (yyvsp[-1].atom)->getQuery(); (yyvsp[-1].atom)->setQuery(makeAtomImplicitHCountQuery((yyvsp[0].ival))); } -#line 1933 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 1930 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 51: -#line 449 "smarts.yy" /* yacc.c:1646 */ +#line 446 "smarts.yy" /* yacc.c:1646 */ { (yyval.atom)->expandQuery(makeAtomHCountQuery((yyvsp[0].ival)),Queries::COMPOSITE_AND); } -#line 1941 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 1938 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 52: -#line 452 "smarts.yy" /* yacc.c:1646 */ +#line 449 "smarts.yy" /* yacc.c:1646 */ { (yyval.atom)->expandQuery(makeAtomHCountQuery(1),Queries::COMPOSITE_AND); } -#line 1949 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 1946 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 53: -#line 455 "smarts.yy" /* yacc.c:1646 */ +#line 452 "smarts.yy" /* yacc.c:1646 */ { QueryAtom *newQ = new QueryAtom(); newQ->setQuery(makeAtomHCountQuery((yyvsp[0].ival))); (yyval.atom)=newQ; } -#line 1959 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 1956 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 54: -#line 460 "smarts.yy" /* yacc.c:1646 */ +#line 457 "smarts.yy" /* yacc.c:1646 */ { QueryAtom *newQ = new QueryAtom(); newQ->setQuery(makeAtomHCountQuery(1)); (yyval.atom)=newQ; } -#line 1969 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 1966 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 55: -#line 465 "smarts.yy" /* yacc.c:1646 */ +#line 462 "smarts.yy" /* yacc.c:1646 */ { QueryAtom *newQ = new QueryAtom(); newQ->setQuery(makeAtomFormalChargeQuery((yyvsp[0].ival))); (yyval.atom)=newQ; } -#line 1979 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 1976 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 56: -#line 470 "smarts.yy" /* yacc.c:1646 */ +#line 467 "smarts.yy" /* yacc.c:1646 */ { QueryAtom *newQ = new QueryAtom(); newQ->setQuery(makeAtomNullQuery()); newQ->setChiralTag(Atom::CHI_TETRAHEDRAL_CW); (yyval.atom)=newQ; } -#line 1990 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 1987 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 57: -#line 476 "smarts.yy" /* yacc.c:1646 */ +#line 473 "smarts.yy" /* yacc.c:1646 */ { QueryAtom *newQ = new QueryAtom(); newQ->setQuery(makeAtomNullQuery()); newQ->setChiralTag(Atom::CHI_TETRAHEDRAL_CCW); (yyval.atom)=newQ; } -#line 2001 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 1998 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 59: -#line 483 "smarts.yy" /* yacc.c:1646 */ +#line 480 "smarts.yy" /* yacc.c:1646 */ { QueryAtom *newQ = new QueryAtom(); newQ->setQuery(makeAtomIsotopeQuery((yyvsp[0].ival))); (yyval.atom)=newQ; } -#line 2011 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 2008 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 60: -#line 491 "smarts.yy" /* yacc.c:1646 */ +#line 488 "smarts.yy" /* yacc.c:1646 */ { // // This construction (and some others) may seem odd, but the @@ -2024,157 +2021,157 @@ yyreduce: (yyval.atom) = new QueryAtom((yyvsp[0].ival)); (yyval.atom)->expandQuery(makeAtomAliphaticQuery(),Queries::COMPOSITE_AND); } -#line 2028 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 2025 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 61: -#line 503 "smarts.yy" /* yacc.c:1646 */ +#line 500 "smarts.yy" /* yacc.c:1646 */ { (yyval.atom) = new QueryAtom((yyvsp[0].ival)); (yyval.atom)->setIsAromatic(true); (yyval.atom)->expandQuery(makeAtomAromaticQuery(),Queries::COMPOSITE_AND); } -#line 2038 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 2035 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 63: -#line 513 "smarts.yy" /* yacc.c:1646 */ +#line 510 "smarts.yy" /* yacc.c:1646 */ { (yyvsp[-2].bond)->expandQuery((yyvsp[0].bond)->getQuery()->copy(),Queries::COMPOSITE_AND,true); delete (yyvsp[0].bond); } -#line 2047 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 2044 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 64: -#line 517 "smarts.yy" /* yacc.c:1646 */ +#line 514 "smarts.yy" /* yacc.c:1646 */ { (yyvsp[-2].bond)->expandQuery((yyvsp[0].bond)->getQuery()->copy(),Queries::COMPOSITE_OR,true); delete (yyvsp[0].bond); } -#line 2056 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 2053 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 65: -#line 521 "smarts.yy" /* yacc.c:1646 */ +#line 518 "smarts.yy" /* yacc.c:1646 */ { (yyvsp[-2].bond)->expandQuery((yyvsp[0].bond)->getQuery()->copy(),Queries::COMPOSITE_AND,true); delete (yyvsp[0].bond); } -#line 2065 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 2062 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 68: -#line 529 "smarts.yy" /* yacc.c:1646 */ +#line 526 "smarts.yy" /* yacc.c:1646 */ { (yyvsp[-1].bond)->expandQuery((yyvsp[0].bond)->getQuery()->copy(),Queries::COMPOSITE_AND,true); delete (yyvsp[0].bond); } -#line 2074 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 2071 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 70: -#line 537 "smarts.yy" /* yacc.c:1646 */ +#line 534 "smarts.yy" /* yacc.c:1646 */ { QueryBond *newB= new QueryBond(); newB->setBondType(Bond::SINGLE); newB->setQuery(makeBondOrderEqualsQuery(Bond::SINGLE)); (yyval.bond) = newB; } -#line 2085 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 2082 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 71: -#line 543 "smarts.yy" /* yacc.c:1646 */ +#line 540 "smarts.yy" /* yacc.c:1646 */ { QueryBond *newB= new QueryBond(); newB->setBondType(Bond::TRIPLE); newB->setQuery(makeBondOrderEqualsQuery(Bond::TRIPLE)); (yyval.bond) = newB; } -#line 2096 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 2093 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 72: -#line 549 "smarts.yy" /* yacc.c:1646 */ +#line 546 "smarts.yy" /* yacc.c:1646 */ { QueryBond *newB= new QueryBond(); newB->setBondType(Bond::AROMATIC); newB->setQuery(makeBondOrderEqualsQuery(Bond::AROMATIC)); (yyval.bond) = newB; } -#line 2107 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 2104 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 73: -#line 555 "smarts.yy" /* yacc.c:1646 */ +#line 552 "smarts.yy" /* yacc.c:1646 */ { QueryBond *newB= new QueryBond(); newB->setQuery(makeBondIsInRingQuery()); (yyval.bond) = newB; } -#line 2117 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 2114 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 74: -#line 560 "smarts.yy" /* yacc.c:1646 */ +#line 557 "smarts.yy" /* yacc.c:1646 */ { (yyvsp[0].bond)->getQuery()->setNegation(!((yyvsp[0].bond)->getQuery()->getNegation())); (yyval.bond) = (yyvsp[0].bond); } -#line 2126 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 2123 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 75: -#line 567 "smarts.yy" /* yacc.c:1646 */ +#line 564 "smarts.yy" /* yacc.c:1646 */ { (yyval.ival)=2; } -#line 2132 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 2129 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 76: -#line 568 "smarts.yy" /* yacc.c:1646 */ +#line 565 "smarts.yy" /* yacc.c:1646 */ { (yyval.ival)=(yyvsp[0].ival); } -#line 2138 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 2135 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 77: -#line 569 "smarts.yy" /* yacc.c:1646 */ +#line 566 "smarts.yy" /* yacc.c:1646 */ { (yyval.ival)=1; } -#line 2144 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 2141 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 78: -#line 570 "smarts.yy" /* yacc.c:1646 */ +#line 567 "smarts.yy" /* yacc.c:1646 */ { (yyval.ival)=-2; } -#line 2150 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 2147 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 79: -#line 571 "smarts.yy" /* yacc.c:1646 */ +#line 568 "smarts.yy" /* yacc.c:1646 */ { (yyval.ival)=-(yyvsp[0].ival); } -#line 2156 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 2153 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 80: -#line 572 "smarts.yy" /* yacc.c:1646 */ +#line 569 "smarts.yy" /* yacc.c:1646 */ { (yyval.ival)=-1; } -#line 2162 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 2159 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 82: -#line 577 "smarts.yy" /* yacc.c:1646 */ +#line 574 "smarts.yy" /* yacc.c:1646 */ { (yyval.ival) = (yyvsp[-1].ival)*10+(yyvsp[0].ival); } -#line 2168 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 2165 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; case 86: -#line 588 "smarts.yy" /* yacc.c:1646 */ +#line 585 "smarts.yy" /* yacc.c:1646 */ { (yyval.ival) = (yyvsp[-1].ival)*10 + (yyvsp[0].ival); } -#line 2174 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 2171 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ break; -#line 2178 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ +#line 2175 "/scratch/RDKit_git/Code/GraphMol/SmilesParse/smarts.tab.cpp" /* yacc.c:1646 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -2402,5 +2399,5 @@ yyreturn: #endif return yyresult; } -#line 595 "smarts.yy" /* yacc.c:1906 */ +#line 592 "smarts.yy" /* yacc.c:1906 */ diff --git a/Code/GraphMol/SmilesParse/smarts.yy b/Code/GraphMol/SmilesParse/smarts.yy index 8d9300728..538eb7550 100644 --- a/Code/GraphMol/SmilesParse/smarts.yy +++ b/Code/GraphMol/SmilesParse/smarts.yy @@ -433,17 +433,14 @@ atom_query: simple_atom } | RINGSIZE_ATOM_QUERY_TOKEN | RINGSIZE_ATOM_QUERY_TOKEN number { - delete $1->getQuery(); $1->setQuery(makeAtomMinRingSizeQuery($2)); } | RINGBOND_ATOM_QUERY_TOKEN | RINGBOND_ATOM_QUERY_TOKEN number { - delete $1->getQuery(); $1->setQuery(makeAtomRingBondCountQuery($2)); } | IMPLICIT_H_ATOM_QUERY_TOKEN | IMPLICIT_H_ATOM_QUERY_TOKEN number { - delete $1->getQuery(); $1->setQuery(makeAtomImplicitHCountQuery($2)); } | simple_atom H_TOKEN number { diff --git a/Code/GraphMol/Wrap/MolOps.cpp b/Code/GraphMol/Wrap/MolOps.cpp index 72ad178f6..23bd84b54 100644 --- a/Code/GraphMol/Wrap/MolOps.cpp +++ b/Code/GraphMol/Wrap/MolOps.cpp @@ -345,7 +345,6 @@ void addRecursiveQuery(ROMol &mol, const ROMol &query, unsigned int atomIdx, } if (!preserveExistingQuery) { - delete oAt->getQuery(); oAt->setQuery(q); } else { oAt->expandQuery(q, Queries::COMPOSITE_AND); From 0775cf0da59d34a152ceeb22214da6062bdf4aca Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Tue, 3 Oct 2017 23:46:44 +0200 Subject: [PATCH 43/44] add substructure searches of Mols using MolBundles from Python (#1603) --- Code/GraphMol/Wrap/Mol.cpp | 30 +++++++++++++++++++++++++++--- Code/GraphMol/Wrap/rough_test.py | 23 +++++++++++++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/Code/GraphMol/Wrap/Mol.cpp b/Code/GraphMol/Wrap/Mol.cpp index 23375227c..30fe25e8e 100644 --- a/Code/GraphMol/Wrap/Mol.cpp +++ b/Code/GraphMol/Wrap/Mol.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -374,8 +375,8 @@ struct mol_wrapper { " - useQueryQueryMatches: use query-query matching logic\n\n" " RETURNS: True or False\n") .def("GetSubstructMatch", - (PyObject * (*)(const ROMol &m, const ROMol &query, bool, bool)) - GetSubstructMatch, + (PyObject * (*)(const ROMol &m, const ROMol &query, bool, + bool))GetSubstructMatch, (python::arg("self"), python::arg("query"), python::arg("useChirality") = false, python::arg("useQueryQueryMatches") = false), @@ -398,7 +399,7 @@ struct mol_wrapper { .def("GetSubstructMatches", (PyObject * (*)(const ROMol &m, const ROMol &query, bool, bool, - bool, unsigned int)) GetSubstructMatches, + bool, unsigned int))GetSubstructMatches, (python::arg("self"), python::arg("query"), python::arg("uniquify") = true, python::arg("useChirality") = false, @@ -434,6 +435,29 @@ struct mol_wrapper { " this molecule that matches the first atom in the " "query.\n") + .def("HasSubstructMatch", + (bool (*)(const ROMol &m, const MolBundle &query, bool, bool, + bool))HasSubstructMatch, + (python::arg("self"), python::arg("query"), + python::arg("recursionPossible") = true, + python::arg("useChirality") = false, + python::arg("useQueryQueryMatches") = false)) + .def("GetSubstructMatch", + (PyObject * (*)(const ROMol &m, const MolBundle &query, bool, + bool))GetSubstructMatch, + (python::arg("self"), python::arg("query"), + python::arg("useChirality") = false, + python::arg("useQueryQueryMatches") = false)) + + .def("GetSubstructMatches", + (PyObject * (*)(const ROMol &m, const MolBundle &query, bool, bool, + bool, unsigned int))GetSubstructMatches, + (python::arg("self"), python::arg("query"), + python::arg("uniquify") = true, + python::arg("useChirality") = false, + python::arg("useQueryQueryMatches") = false, + python::arg("maxMatches") = 1000)) + // properties .def("SetProp", MolSetProp, (python::arg("self"), python::arg("key"), python::arg("val"), diff --git a/Code/GraphMol/Wrap/rough_test.py b/Code/GraphMol/Wrap/rough_test.py index f03ead86d..e48f26c45 100644 --- a/Code/GraphMol/Wrap/rough_test.py +++ b/Code/GraphMol/Wrap/rough_test.py @@ -4397,6 +4397,29 @@ M END self.assertEqual(len(b.GetSubstructMatches(Chem.MolFromSmiles('C[C@](Cl)(F)C[C@@H](F)(Br)'),useChirality=True)[0]),8) self.assertEqual(len(b.GetSubstructMatches(Chem.MolFromSmiles('C[C@@](Cl)(F)C[C@@H](F)(Br)'),useChirality=False)[0]),8) + + def testMolBundles2(self): + b = Chem.MolBundle() + smis = ('Fc1c(Cl)cccc1','Fc1cc(Cl)ccc1','Fc1ccc(Cl)cc1') + for smi in smis: + b.AddMol(Chem.MolFromSmiles(smi)) + self.assertEqual(len(b),3) + self.assertEqual(b.Size(),3) + self.failUnless(Chem.MolFromSmiles('Fc1c(Cl)cccc1').HasSubstructMatch(b)) + self.failUnless(Chem.MolFromSmiles('Fc1cc(Cl)ccc1').HasSubstructMatch(b)) + self.failUnless(Chem.MolFromSmiles('Fc1c(Cl)cccc1C').HasSubstructMatch(b)) + self.failUnless(Chem.MolFromSmiles('Fc1cc(Cl)ccc1C').HasSubstructMatch(b)) + self.failIf(Chem.MolFromSmiles('Fc1c(Br)cccc1').HasSubstructMatch(b)) + + self.assertEqual(len(Chem.MolFromSmiles('Fc1c(Cl)cccc1').GetSubstructMatch(b)),8) + self.assertEqual(len(Chem.MolFromSmiles('Fc1c(Cl)cccc1').GetSubstructMatches(b)),1) + self.assertEqual(len(Chem.MolFromSmiles('Fc1c(Cl)cccc1').GetSubstructMatches(b)[0]),8) + self.assertEqual(len(Chem.MolFromSmiles('Fc1ccc(Cl)cc1').GetSubstructMatches(b)),1) + self.assertEqual(len(Chem.MolFromSmiles('Fc1ccc(Cl)cc1').GetSubstructMatches(b,uniquify=False)),2) + + self.assertEqual(len(Chem.MolFromSmiles('Fc1c(C)cccc1').GetSubstructMatch(b)),0) + self.assertEqual(len(Chem.MolFromSmiles('Fc1c(C)cccc1').GetSubstructMatches(b)),0) + if __name__ == '__main__': if "RDTESTCASE" in os.environ: suite = unittest.TestSuite() From b7d2cfbc8eb9fd1294b7191d6c58727ceda637d6 Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Wed, 4 Oct 2017 04:51:10 +0200 Subject: [PATCH 44/44] update release notes --- ReleaseNotes.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 7a17df8f3..df950bc4a 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -5,6 +5,10 @@ - The fix for bug #1567 changes the way fragment SMILES are canonicalized. MolFragmentToSmiles() and canonicalizeFragment() will now often return different results +- The fix for bug #1604 changes the behavior of QueryAtom::setQuery(), which + now deletes the current query before setting the new value. If you are using + QueryAtom::setQuery() from C++ (or possibly Java), be sure that you are not + also deleting that memory. ## Acknowledgements: Brian Cole, Peter Gedeck, Guillaume Godin, Malitha Kabir, Tuomo Kalliokoski, @@ -23,8 +27,6 @@ Nadine Schneider, Matt Swain, Paolo Tosco, Alain Vaucher, Sam Webb, - New descriptors: the QED descriptor has been added as have a large collection of new 3D descriptors and implementations of the USR and USRCAT fingerprints. - - ## New Features and Enhancements: - Bring back USR and USRCAT descriptors (github pull #1417 from greglandrum) @@ -156,7 +158,8 @@ Nadine Schneider, Matt Swain, Paolo Tosco, Alain Vaucher, Sam Webb, (github issue #1550 from greglandrum) - Fixes double free for Dict::update (github pull #1571 from bp-kelley) - + - QueryAtom::setQuery() should delete the old query first + (github pull #1604 from greglandrum) # Release_2017.03.1