// // Copyright (c) 2016, Guillaume GODIN // 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 Institue of Cancer Research. // 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. // // Created by Guillaume GODIN 2016 #include #include "MORSE.h" #include "MolData3Ddescriptors.h" #include // data checked using book Todeschini R., Consonni V. - Molecular Descriptors // for Chemoinformatics 2009 atomic properties page 21/22 namespace RDKit { namespace Descriptors { namespace { MolData3Ddescriptors moldata3D; std::vector getG(int n) { std::vector res(n); for (int i = 0; i < n; i++) { res[i] = i; } return res; } std::vector prepareIState(const ROMol &mol) { std::vector IState = moldata3D.GetIState(mol); return IState; } void getMORSEDesc(const double *DM, const ROMol &mol, const Conformer &conf, std::vector &res) { int numAtoms = conf.getNumAtoms(); std::vector R = getG(32); std::vector R1(32); std::vector R2(32); std::vector R3(32); std::vector R4(32); std::vector R5(32); std::vector R6(32); std::vector R7(32); std::vector Mass = moldata3D.GetRelativeMW(mol); std::vector RelativePol = moldata3D.GetRelativePol(mol); std::vector IonPol = moldata3D.GetRelativeIonPol(mol); std::vector RelativeElectroNeg = moldata3D.GetRelativeENeg(mol); std::vector RelativeVdW = moldata3D.GetRelativeVdW(mol); std::vector IState = prepareIState(mol); double p; for (size_t i = 0; i < R.size(); i++) { double res1 = 0.0; double res2 = 0.0; double res3 = 0.0; double res4 = 0.0; double res5 = 0.0; double res6 = 0.0; double res7 = 0.0; for (int j = 0; j < numAtoms - 1; j++) { for (int k = j + 1; k < numAtoms; k++) { if (i == 0) { p = 1; } else { p = sin(R[i] * DM[j * numAtoms + k]) / (R[i] * DM[j * numAtoms + k]); } res1 += p; res2 += Mass[j] * Mass[k] * p; res3 += RelativeVdW[j] * RelativeVdW[k] * p; res4 += RelativeElectroNeg[j] * RelativeElectroNeg[k] * p; res5 += RelativePol[j] * RelativePol[k] * p; res6 += IonPol[j] * IonPol[k] * p; res7 += IState[j] * IState[k] * p; } } R1[i] = std::round(1000 * res1) / 1000; R2[i] = std::round(1000 * res2) / 1000; R3[i] = std::round(1000 * res3) / 1000; R4[i] = std::round(1000 * res4) / 1000; R5[i] = std::round(1000 * res5) / 1000; R6[i] = std::round(1000 * res6) / 1000; R7[i] = std::round(1000 * res7) / 1000; } R1.insert(R1.end(), R2.begin(), R2.end()); R1.insert(R1.end(), R3.begin(), R3.end()); R1.insert(R1.end(), R4.begin(), R4.end()); R1.insert(R1.end(), R5.begin(), R5.end()); R1.insert(R1.end(), R6.begin(), R6.end()); R1.insert(R1.end(), R7.begin(), R7.end()); res = R1; } void getMORSEDescCustom(const double *DM, const ROMol &mol, const Conformer &conf, std::vector &res, const std::string &customAtomPropName) { int numAtoms = conf.getNumAtoms(); std::vector R = getG(32); std::vector R1(32); std::vector customAtomArray = moldata3D.GetCustomAtomProp(mol, customAtomPropName); double p; for (size_t i = 0; i < R.size(); i++) { double res1 = 0.0; for (int j = 0; j < numAtoms - 1; j++) { for (int k = j + 1; k < numAtoms; k++) { if (i == 0) { p = 1; } else { p = sin(R[i] * DM[j * numAtoms + k]) / (R[i] * DM[j * numAtoms + k]); } res1 += customAtomArray[j] * customAtomArray[k] * p; // "custom" } } R1[i] = std::round(1000 * res1) / 1000; } res = R1; } void GetMORSE(double *dist3D, const ROMol &mol, const Conformer &conf, std::vector &res) { getMORSEDesc(dist3D, mol, conf, res); } void GetMORSEone(double *dist3D, const ROMol &mol, const Conformer &conf, std::vector &res, const std::string &customAtomPropName) { getMORSEDescCustom(dist3D, mol, conf, res, customAtomPropName); } } // end of anonymous namespace void MORSE(const ROMol &mol, std::vector &res, int confId, const std::string &customAtomPropName) { PRECONDITION(mol.getNumConformers() >= 1, "molecule has no conformers") // Mor01u Mor02u Mor03u Mor04u Mor05u Mor06u Mor07u Mor08u Mor09u // Mor10u Mor11u Mor12u Mor13u Mor14u Mor15u Mor16u Mor17u Mor18u // Mor19u Mor20u Mor21u Mor22u Mor23u Mor24u Mor25u Mor26u Mor27u // Mor28u Mor29u Mor30u Mor31u Mor32u // Mor01m Mor02m Mor03m Mor04m Mor05m Mor06m Mor07m Mor08m Mor09m // Mor10m Mor11m Mor12m Mor13m Mor14m Mor15m Mor16m Mor17m Mor18m // Mor19m Mor20m Mor21m Mor22m Mor23m Mor24m Mor25m Mor26m Mor27m // Mor28m Mor29m Mor30m Mor31m Mor32m // Mor01v Mor02v Mor03v Mor04v Mor05v Mor06v Mor07v Mor08v Mor09v // Mor10v Mor11v Mor12v Mor13v Mor14v Mor15v Mor16v Mor17v Mor18v // Mor19v Mor20v Mor21v Mor22v Mor23v Mor24v Mor25v Mor26v Mor27v // Mor28v Mor29v Mor30v Mor31v Mor32v // Mor01e Mor02e Mor03e Mor04e Mor05e Mor06e Mor07e Mor08e Mor09e // Mor10e Mor11e Mor12e Mor13e Mor14e Mor15e Mor16e Mor17e Mor18e // Mor19e Mor20e Mor21e Mor22e Mor23e Mor24e Mor25e Mor26e Mor27e // Mor28e Mor29e Mor30e Mor31e Mor32e // Mor01p Mor02p Mor03p Mor04p Mor05p Mor06p Mor07p Mor08p Mor09p // Mor10p Mor11p Mor12p Mor13p Mor14p Mor15p Mor16p Mor17p Mor18p // Mor19p Mor20p Mor21p Mor22p Mor23p Mor24p Mor25p Mor26p Mor27p // Mor28p Mor29p Mor30p Mor31p Mor32p // Mor01i Mor02i Mor03i Mor04i Mor05i Mor06i Mor07i Mor08i Mor09i // Mor10i Mor11i Mor12i Mor13i Mor14i Mor15i Mor16i Mor17i Mor18i // Mor19i Mor20i Mor21i Mor22i Mor23i Mor24i Mor25i Mor26i Mor27i // Mor28i Mor29i Mor30i Mor31i Mor32i // Mor01s Mor02s Mor03s Mor04s Mor05s Mor06s Mor07s Mor08s Mor09s // Mor10s Mor11s Mor12s Mor13s Mor14s Mor15s Mor16s Mor17s Mor18s // Mor19s Mor20s Mor21s Mor22s Mor23s Mor24s Mor25s Mor26s Mor27s // Mor28s Mor29s Mor30s Mor31s Mor32s const Conformer &conf = mol.getConformer(confId); double *dist3D = MolOps::get3DDistanceMat(mol, confId, false, true); // 3D distance matrix if (!customAtomPropName.empty()) { res.clear(); res.resize(32); // 7 * 32 GetMORSEone(dist3D, mol, conf, res, customAtomPropName); } else { res.clear(); res.resize(224); // 7 * 32 GetMORSE(dist3D, mol, conf, res); } } } // namespace Descriptors } // namespace RDKit