From 40e27a65bdc603313918221c6f6cff84dff15ca8 Mon Sep 17 00:00:00 2001 From: David Cosgrove Date: Mon, 12 Sep 2022 03:23:38 +0100 Subject: [PATCH 1/8] Fixed drawing of O in aldehydes. (#5515) * Fixed drawing of O in aldehydes. * Added DrawColour::operator!=. * Remove unused variable. * Export doLinesIntersect for test. Co-authored-by: David Cosgrove Co-authored-by: Greg Landrum --- Code/GraphMol/MolDraw2D/DrawMol.cpp | 26 +++++-- Code/GraphMol/MolDraw2D/DrawMol.h | 4 +- Code/GraphMol/MolDraw2D/MolDraw2DHelpers.h | 1 + Code/GraphMol/MolDraw2D/catch_tests.cpp | 80 +++++++++++++++++++--- Code/GraphMol/MolDraw2D/rxn_test1.cpp | 30 ++++---- Code/GraphMol/MolDraw2D/test1.cpp | 4 +- 6 files changed, 110 insertions(+), 35 deletions(-) diff --git a/Code/GraphMol/MolDraw2D/DrawMol.cpp b/Code/GraphMol/MolDraw2D/DrawMol.cpp index 9b39419e7a..57fbbb480d 100644 --- a/Code/GraphMol/MolDraw2D/DrawMol.cpp +++ b/Code/GraphMol/MolDraw2D/DrawMol.cpp @@ -1659,11 +1659,20 @@ void DrawMol::makeDoubleBondLines( // in, for example, an aldehyde, such as in catch_tests.cpp's // testGithub_5269_2.svg, might be asymmetrically shorter, so we don't // want to change colour at halfway - if (bond->getEndAtom()->getDegree() == 1 && !(cols.first == cols.second) && - fabs((l1s - l1f).lengthSq() - (l2s - l2f).lengthSq()) > 0.01) { - double midlen = (l1s - l1f).length() / 2.0; - Point2D lineDir = l2s.directionVector(l2f); - Point2D notMid = l2s + lineDir * midlen; + auto l1 = (l1s - l1f).lengthSq(); + auto l2 = (l2s - l2f).lengthSq(); + if ((bond->getBeginAtom()->getDegree() == 1 || + bond->getEndAtom()->getDegree() == 1) && + cols.first != cols.second && fabs(l1 - l2) > 0.01) { + double midlen = sqrt(l1) / 2.0; + Point2D notMid; + if (bond->getBeginAtom()->getDegree() == 1) { + Point2D lineDir = l2s.directionVector(l2f); + notMid = l2s + lineDir * midlen; + } else { + Point2D lineDir = l2f.directionVector(l2s); + notMid = l2f + lineDir * midlen; + } newBondLine(l2s, notMid, cols.first, cols.first, at1Idx, at2Idx, bondIdx, noDash); newBondLine(notMid, l2f, cols.second, cols.second, at1Idx, at2Idx, @@ -2840,6 +2849,11 @@ void DrawMol::doubleBondTerminal(Atom *at1, Atom *at2, double offset, l2s = at1_cds + perp * offset; l2f = doubleBondEnd(at1->getIdx(), at2->getIdx(), thirdAtom->getIdx(), offset, true); + // if at1 has a label, need to move it so it's centred in between the + // two lines (Github 5511). + if (atomLabels_[at1->getIdx()]) { + atomLabels_[at1->getIdx()]->cds_ += perp * offset * 0.5; + } } if (swapped) { std::swap(l1s, l1f); @@ -2896,8 +2910,6 @@ void DrawMol::findOtherBondVecs(const Atom *atom, const Atom *otherAtom, } for (unsigned int i = 1; i < atom->getDegree(); ++i) { auto thirdAtom = otherNeighbor(atom, otherAtom, i - 1, *drawMol_); - auto bond = - drawMol_->getBondBetweenAtoms(atom->getIdx(), thirdAtom->getIdx()); Point2D const &at1_cds = atCds_[atom->getIdx()]; Point2D const &at2_cds = atCds_[thirdAtom->getIdx()]; otherBondVecs.push_back(at1_cds.directionVector(at2_cds)); diff --git a/Code/GraphMol/MolDraw2D/DrawMol.h b/Code/GraphMol/MolDraw2D/DrawMol.h index 5d82559b8e..35765ed611 100644 --- a/Code/GraphMol/MolDraw2D/DrawMol.h +++ b/Code/GraphMol/MolDraw2D/DrawMol.h @@ -319,8 +319,8 @@ double getHighlightBondWidth( Point2D calcPerpendicular(const Point2D &cds1, const Point2D &cds2); Point2D calcInnerPerpendicular(const Point2D &cds1, const Point2D &cds2, const Point2D &cds3); -// return a point that is end1 moved so as not to clash with any of the -// rects of a label. end1 to end2 and the coords of 2 ends of a bond. +// return a point that is moveEnd moved so as not to clash with any of the +// rects of a label. moveEnd to end2 are the coords of 2 ends of a bond. void adjustBondEndForString( const Point2D &end2, double padding, const std::vector> &rects, Point2D &moveEnd); diff --git a/Code/GraphMol/MolDraw2D/MolDraw2DHelpers.h b/Code/GraphMol/MolDraw2D/MolDraw2DHelpers.h index b5c5f05545..c8b89f176d 100644 --- a/Code/GraphMol/MolDraw2D/MolDraw2DHelpers.h +++ b/Code/GraphMol/MolDraw2D/MolDraw2DHelpers.h @@ -34,6 +34,7 @@ struct DrawColour { bool operator==(const DrawColour &other) const { return r == other.r && g == other.g && b == other.b && a == other.a; } + bool operator!=(const DrawColour &other) const { return !(*this == other); } bool feq(const DrawColour &other, double tol = 0.001, bool ignoreAlpha = true) const { return fabs(r - other.r) <= tol && fabs(g - other.g) <= tol && diff --git a/Code/GraphMol/MolDraw2D/catch_tests.cpp b/Code/GraphMol/MolDraw2D/catch_tests.cpp index 2f6261ecd4..fa9b81c291 100644 --- a/Code/GraphMol/MolDraw2D/catch_tests.cpp +++ b/Code/GraphMol/MolDraw2D/catch_tests.cpp @@ -86,8 +86,8 @@ static const std::map SVG_HASHES = { {"testHandDrawn-2.svg", 2605087576U}, {"testHandDrawn-3.svg", 1015633173U}, {"testHandDrawn-4.svg", 830784921U}, - {"testHandDrawn-5a.svg", 3582113444U}, - {"testHandDrawn-5b.svg", 2974975931U}, + {"testHandDrawn-5a.svg", 2845825621U}, + {"testHandDrawn-5b.svg", 476521352U}, {"testBrackets-1a.svg", 3257646535U}, {"testBrackets-1b.svg", 776088825U}, {"testBrackets-1c.svg", 3257646535U}, @@ -97,10 +97,10 @@ static const std::map SVG_HASHES = { {"testBrackets-2b.svg", 1408188695U}, {"testBrackets-2c.svg", 728321376U}, {"testBrackets-2d.svg", 1408188695U}, - {"testBrackets-3a.svg", 630742918U}, + {"testBrackets-3a.svg", 791450653U}, {"testBrackets-4a.svg", 769125635U}, {"testBrackets-4b.svg", 4066682338U}, - {"testBrackets-5a.svg", 2845825621U}, + {"testBrackets-5a.svg", 1388227932U}, {"testSGroupData-1a.svg", 1463366807U}, {"testSGroupData-1b.svg", 223883202U}, {"testSGroupData-2a.svg", 3547547260U}, @@ -174,8 +174,8 @@ static const std::map SVG_HASHES = { {"testGithub4519_2.svg", 2515716875U}, {"testGithub4519_3.svg", 1017109741U}, {"testGithub4519_4.svg", 645908829U}, - {"testBaseFontSize.1a.svg", 3213010239U}, - {"testBaseFontSize.1b.svg", 1147057058U}, + {"testBaseFontSize.1a.svg", 3939288880U}, + {"testBaseFontSize.1b.svg", 2617787443U}, {"testBaseFontSize.2a.svg", 1031690455U}, {"testBaseFontSize.2b.svg", 3440038194U}, {"testFlexiCanvas.1a.svg", 3145560884U}, @@ -214,7 +214,7 @@ static const std::map SVG_HASHES = { {"testGithub_5061.svg", 1947248304U}, {"testGithub_5185.svg", 2944445711U}, {"testGithub_5269_1.svg", 3660737449U}, - {"testGithub_5269_2.svg", 2580783009U}, + {"testGithub_5269_2.svg", 3987247770U}, {"test_classes_wavy_bonds.svg", 1271445012U}, {"testGithub_5383_1.svg", 1391972140U}, {"github5156_1.svg", 695855770U}, @@ -228,7 +228,7 @@ static const std::map SVG_HASHES = { {"acs1996_4.svg", 55815911U}, {"acs1996_5.svg", 362495488U}, {"acs1996_6.svg", 4274355858U}, - {"acs1996_7.svg", 729001900U}, + {"acs1996_7.svg", 3993278473U}, {"acs1996_8.svg", 2032371436U}, {"acs1996_9.svg", 2589221154U}, {"acs1996_10.svg", 4037187899U}, @@ -244,6 +244,8 @@ static const std::map SVG_HASHES = { {"bond_highlights_7.svg", 2936856212U}, {"bond_highlights_8.svg", 64473502U}, {"testGithub5486_1.svg", 1149144091U}, + {"testGithub5511_1.svg", 940106456U}, + {"testGithub5511_2.svg", 1448975272U} }; // These PNG hashes aren't completely reliable due to floating point cruft, @@ -263,7 +265,7 @@ static const std::map PNG_HASHES = { {"testHandDrawn-2.png", 2979412913U}, {"testHandDrawn-3.png", 1765396301U}, {"testHandDrawn-4.png", 2989933219U}, - {"testHandDrawn-5.png", 3794840403U}, + {"testHandDrawn-5.png", 1526220279U}, {"testGithub4323_1.png", 3711520691U}, {"testGithub4323_3.png", 2300228708U}, {"testFlexiCanvas.2a.png", 3618977786U}, @@ -5713,3 +5715,63 @@ M END)CTAB"_ctab; } } } + +TEST_CASE("Bad O position in aldehydes", "") { + std::string nameBase("testGithub5511_"); + { + auto m1 = "O=Cc1cccc(C=O)c1"_smiles; + REQUIRE(m1); + MolDraw2DUtils::prepareMolForDrawing(*m1); + MolDraw2DSVG drawer(250, 250, -1, -1, NO_FREETYPE); + drawer.drawOptions().addAtomIndices = true; + drawer.drawMolecule(*m1); + drawer.finishDrawing(); + auto text = drawer.getDrawingText(); + std::string filename = nameBase + "1.svg"; + std::ofstream outs(filename); + outs << text; + outs.flush(); + check_file_hash(filename); + } + { + auto m = R"CTAB( + RDKit 2D + + 11 11 0 0 0 0 0 0 0 0999 V2000 + -4.2885 0.5445 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.9895 1.2945 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.6818 0.5394 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.3738 1.2945 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.9342 0.5394 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.2422 1.2945 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.2422 2.7945 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.9342 -0.9708 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.3738 -1.7262 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.6818 -0.9708 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.9895 -1.7262 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 + 2 3 1 0 + 3 4 2 0 + 4 5 1 0 + 5 6 1 0 + 6 7 2 0 + 5 8 2 0 + 8 9 1 0 + 9 10 2 0 + 10 11 1 0 + 10 3 1 0 +M END +)CTAB"_ctab; + REQUIRE(m); + MolDraw2DSVG drawer(250, 250, -1, -1); + drawer.drawOptions().addAtomIndices = true; + drawer.drawMolecule(*m); + drawer.finishDrawing(); + std::string text = drawer.getDrawingText(); + std::string filename = nameBase + "2.svg"; + std::ofstream outs(filename); + outs << text; + outs.flush(); + check_file_hash(filename); + } +} diff --git a/Code/GraphMol/MolDraw2D/rxn_test1.cpp b/Code/GraphMol/MolDraw2D/rxn_test1.cpp index 023103c71d..e9236b7757 100644 --- a/Code/GraphMol/MolDraw2D/rxn_test1.cpp +++ b/Code/GraphMol/MolDraw2D/rxn_test1.cpp @@ -48,25 +48,25 @@ namespace { static const bool DELETE_WITH_GOOD_HASH = true; #ifdef RDK_BUILD_FREETYPE_SUPPORT static const std::map SVG_HASHES = { - {"rxn_test1_1.svg", 46725873U}, {"rxn_test1_2.svg", 2822273042U}, + {"rxn_test1_1.svg", 46725873U}, {"rxn_test1_2.svg", 2822273042U}, {"rxn_test1_3.svg", 3749362740U}, {"rxn_test1_4.svg", 2720989271U}, - {"rxn_test1_5.svg", 3245376196U}, {"rxn_test1_6.svg", 1371904127U}, - {"rxn_test1_7.svg", 3410910592U}, {"rxn_test2_1.svg", 409647324U}, - {"rxn_test2_2_1.svg", 1275078201U}, {"rxn_test2_2_2.svg", 2689198952U}, + {"rxn_test1_5.svg", 3245376196U}, {"rxn_test1_6.svg", 1201850884U}, + {"rxn_test1_7.svg", 3483485271U}, {"rxn_test2_1.svg", 409647324U}, + {"rxn_test2_2_1.svg", 1275078201U}, {"rxn_test2_2_2.svg", 2689198952U}, {"rxn_test2_2_3.svg", 3750657998U}, {"rxn_test2_2_4.svg", 844519751U}, - {"rxn_test3_1.svg", 3370327616U}, {"rxn_test4_1.svg", 1951283390U}, - {"rxn_test4_2.svg", 1355336361U}, + {"rxn_test3_1.svg", 2642962178U}, {"rxn_test4_1.svg", 2201210664U}, + {"rxn_test4_2.svg", 3875105540U}, }; #else static const std::map SVG_HASHES = { {"rxn_test1_1.svg", 3077363070U}, {"rxn_test1_2.svg", 343913088U}, {"rxn_test1_3.svg", 1743857837U}, {"rxn_test1_4.svg", 421748462U}, - {"rxn_test1_5.svg", 2287478842U}, {"rxn_test1_6.svg", 1059343942U}, - {"rxn_test1_7.svg", 301064722U}, {"rxn_test2_1.svg", 2821179072U}, - {"rxn_test2_2_1.svg", 1304295583U}, {"rxn_test2_2_2.svg", 1361778996U}, + {"rxn_test1_5.svg", 2287478842U}, {"rxn_test1_6.svg", 1657115641U}, + {"rxn_test1_7.svg", 2526900298U}, {"rxn_test2_1.svg", 2821179072U}, + {"rxn_test2_2_1.svg", 1304295583U}, {"rxn_test2_2_2.svg", 1361778996U}, {"rxn_test2_2_3.svg", 2608405344U}, {"rxn_test2_2_4.svg", 574045696U}, - {"rxn_test3_1.svg", 265057038U}, {"rxn_test4_1.svg", 684852697U}, - {"rxn_test4_2.svg", 2675536892U}, + {"rxn_test3_1.svg", 2373233565U}, {"rxn_test4_1.svg", 1661501846U}, + {"rxn_test4_2.svg", 638174091U}, }; #endif @@ -83,12 +83,12 @@ static const std::map SVG_HASHES = { static const std::map PNG_HASHES = { {"rxn_test1_1.png", 3579100589U}, {"rxn_test1_2.png", 3996724834U}, {"rxn_test1_3.png", 4153817948U}, {"rxn_test1_4.png", 4175225545U}, - {"rxn_test1_5.png", 3400977230U}, {"rxn_test1_6.png", 2636974466U}, - {"rxn_test1_7.png", 4164917700U}, {"rxn_test2_1.png", 2654417911U}, + {"rxn_test1_5.png", 3400977230U}, {"rxn_test1_6.png", 1819663219U}, + {"rxn_test1_7.png", 3834655428U}, {"rxn_test2_1.png", 2654417911U}, {"rxn_test2_2_1.png", 997060634U}, {"rxn_test2_2_2.png", 2090979640U}, {"rxn_test2_2_3.png", 857100114U}, {"rxn_test2_2_4.png", 610638635U}, - {"rxn_test3_1.png", 501226401U}, {"rxn_test4_1.png", 4259011005U}, - {"rxn_test4_2.png", 2214400478U}, + {"rxn_test3_1.png", 2130633490U}, {"rxn_test4_1.png", 2917597113U}, + {"rxn_test4_2.png", 3031850382U}, }; std::hash_result_t hash_file(const std::string &filename) { diff --git a/Code/GraphMol/MolDraw2D/test1.cpp b/Code/GraphMol/MolDraw2D/test1.cpp index e8ac38217a..644c87f82a 100644 --- a/Code/GraphMol/MolDraw2D/test1.cpp +++ b/Code/GraphMol/MolDraw2D/test1.cpp @@ -158,7 +158,7 @@ static const std::map SVG_HASHES = { {"test21_1.svg", 3363530709U}, {"test21_2.svg", 3470002858U}, {"test22_1.svg", 3716192373U}, - {"test22_2.svg", 1926484323U}, + {"test22_2.svg", 3812042529U}, {"testGithub3112_1.svg", 3236038294U}, {"testGithub3112_2.svg", 1810059147U}, {"testGithub3112_3.svg", 135218742U}, @@ -287,7 +287,7 @@ static const std::map SVG_HASHES = { {"test20_3.svg", 968052569U}, {"test20_4.svg", 2298201486U}, {"test22_1.svg", 3716192373U}, - {"test22_2.svg", 2843125073U}, + {"test22_2.svg", 3258508270U}, {"testGithub3112_1.svg", 2613843920U}, {"testGithub3112_2.svg", 3639942551U}, {"testGithub3112_3.svg", 1107662781U}, From cbdec52048aceddc548e7b09325cdd78d3c480c1 Mon Sep 17 00:00:00 2001 From: David Cosgrove Date: Tue, 13 Sep 2022 11:18:20 +0100 Subject: [PATCH 2/8] Fixed scale (#5519) * Make ACS mode work properly in fixed size drawers. * Extra comment. * Update hash codes. * Export doLinesIntersect. Co-authored-by: David Cosgrove Co-authored-by: Greg Landrum --- Code/GraphMol/MolDraw2D/MolDraw2DUtils.cpp | 4 + Code/GraphMol/MolDraw2D/catch_tests.cpp | 97 ++++++++++++++++------ 2 files changed, 75 insertions(+), 26 deletions(-) diff --git a/Code/GraphMol/MolDraw2D/MolDraw2DUtils.cpp b/Code/GraphMol/MolDraw2D/MolDraw2DUtils.cpp index 884b54381d..b594ff6f6f 100644 --- a/Code/GraphMol/MolDraw2D/MolDraw2DUtils.cpp +++ b/Code/GraphMol/MolDraw2D/MolDraw2DUtils.cpp @@ -440,6 +440,10 @@ void setACS1996Options(MolDrawOptions &opts, double meanBondLen) { // the guideline is for a bond length of 14.4px, and we set things up // in pixels per Angstrom. opts.scalingFactor = 14.4 / meanBondLen; + // setting the fixedBondLength means the drawing won't be scaled + // up in a drawer of defined size, so the bond length won't exceed + // 14.4 pixels. + opts.fixedBondLength = 14.4 / meanBondLen; // offset for multiple bonds is 18% of the bond length. opts.multipleBondOffset = 0.18; opts.highlightBondWidthMultiplier = 32; diff --git a/Code/GraphMol/MolDraw2D/catch_tests.cpp b/Code/GraphMol/MolDraw2D/catch_tests.cpp index fa9b81c291..dc02c8e054 100644 --- a/Code/GraphMol/MolDraw2D/catch_tests.cpp +++ b/Code/GraphMol/MolDraw2D/catch_tests.cpp @@ -113,10 +113,10 @@ static const std::map SVG_HASHES = { {"testPositionVariation-4.svg", 886758688U}, {"testNoAtomLabels-1.svg", 2648234379U}, {"testNoAtomLabels-2.svg", 3213096674U}, - {"testQueryBonds-1a.svg", 674261460U}, - {"testQueryBonds-1b.svg", 1450309284U}, - {"testQueryBonds-1c.svg", 74333858U}, - {"testQueryBonds-2.svg", 1873442183U}, + {"testQueryBonds-1a.svg", 3288272531U}, + {"testQueryBonds-1b.svg", 1706839957U}, + {"testQueryBonds-1c.svg", 333519907U}, + {"testQueryBonds-2.svg", 69341882U}, {"testLinkNodes-2-0.svg", 2952965907U}, {"testLinkNodes-2-30.svg", 4117540200U}, {"testLinkNodes-2-60.svg", 520576199U}, @@ -203,9 +203,9 @@ static const std::map SVG_HASHES = { {"testFlexiCanvas.7b.svg", 4094511140U}, {"testFlexiCanvas.7c.svg", 918094125U}, {"testFlexiCanvas.7d.svg", 918094125U}, - {"testGithub4764.sz1.svg", 2369071854U}, - {"testGithub4764.sz2.svg", 39314673U}, - {"testGithub4764.sz3.svg", 901101991U}, + {"testGithub4764.sz1.svg", 493786705U}, + {"testGithub4764.sz2.svg", 2704253898U}, + {"testGithub4764.sz3.svg", 1328896014U}, {"testDrawArc1.svg", 4039810147U}, {"testMetalWedges.svg", 3278785383U}, {"testVariableLegend_1.svg", 3914441319U}, @@ -213,8 +213,8 @@ static const std::map SVG_HASHES = { {"testVariableLegend_3.svg", 1996551457U}, {"testGithub_5061.svg", 1947248304U}, {"testGithub_5185.svg", 2944445711U}, - {"testGithub_5269_1.svg", 3660737449U}, - {"testGithub_5269_2.svg", 3987247770U}, + {"testGithub_5269_1.svg", 2368496794U}, + {"testGithub_5269_2.svg", 567813292U}, {"test_classes_wavy_bonds.svg", 1271445012U}, {"testGithub_5383_1.svg", 1391972140U}, {"github5156_1.svg", 695855770U}, @@ -222,17 +222,18 @@ static const std::map SVG_HASHES = { {"github5156_3.svg", 3284451122U}, {"test_molblock_wedges.svg", 1106580037U}, {"github5383_1.svg", 2353351393U}, - {"acs1996_1.svg", 773284691U}, - {"acs1996_2.svg", 2884688866U}, - {"acs1996_3.svg", 2540534250U}, - {"acs1996_4.svg", 55815911U}, - {"acs1996_5.svg", 362495488U}, - {"acs1996_6.svg", 4274355858U}, - {"acs1996_7.svg", 3993278473U}, - {"acs1996_8.svg", 2032371436U}, - {"acs1996_9.svg", 2589221154U}, - {"acs1996_10.svg", 4037187899U}, - {"acs1996_11.svg", 3667521405U}, + {"acs1996_1.svg", 51426601U}, + {"acs1996_2.svg", 833573044U}, + {"acs1996_3.svg", 4007912653U}, + {"acs1996_4.svg", 3372558370U}, + {"acs1996_5.svg", 2883542240U}, + {"acs1996_6.svg", 1380727178U}, + {"acs1996_7.svg", 763391533U}, + {"acs1996_8.svg", 939325262U}, + {"acs1996_9.svg", 2607143500U}, + {"acs1996_10.svg", 199499735U}, + {"acs1996_11.svg", 2121789178U}, + {"acs1996_12.svg", 2233727631U}, {"test_unspec_stereo.svg", 599119798U}, {"light_blue_h_no_label_1.svg", 3735371135U}, {"bond_highlights_1.svg", 1150579427U}, @@ -241,7 +242,7 @@ static const std::map SVG_HASHES = { {"bond_highlights_4.svg", 3500788273U}, {"bond_highlights_5.svg", 3500788273U}, {"bond_highlights_6.svg", 3008628729U}, - {"bond_highlights_7.svg", 2936856212U}, + {"bond_highlights_7.svg", 3900018634U}, {"bond_highlights_8.svg", 64473502U}, {"testGithub5486_1.svg", 1149144091U}, {"testGithub5511_1.svg", 940106456U}, @@ -270,13 +271,13 @@ static const std::map PNG_HASHES = { {"testGithub4323_3.png", 2300228708U}, {"testFlexiCanvas.2a.png", 3618977786U}, {"testFlexiCanvas.2b.png", 2780757414U}, - {"testGithub4764.sz1.png", 3594553035U}, - {"testGithub4764.sz2.png", 1203143863U}, - {"testGithub4764.sz3.png", 310017790U}, + {"testGithub4764.sz1.png", 2320783268U}, + {"testGithub4764.sz2.png", 3297570843U}, + {"testGithub4764.sz3.png", 2178018272U}, {"testGithub4238_1.png", 458925131U}, {"github5383_1.png", 2963331215U}, - {"acs1996_1.png", 2814011866U}, - {"acs1996_2.png", 3118288179U}}; + {"acs1996_1.png", 2674458798U}, + {"acs1996_2.png", 83755168U}}; std::hash_result_t hash_file(const std::string &filename) { std::ifstream ifs(filename, std::ios_base::binary); @@ -4812,6 +4813,7 @@ TEST_CASE("ACS 1996 mode") { SECTION("basics") { std::string nameBase = "acs1996_"; #if 1 + { auto m = R"CTAB(mol1 ChemDraw05162216032D @@ -5382,6 +5384,49 @@ M END outs.close(); check_file_hash(nameBase + "11.svg"); } +#endif +#if 1 + auto drawnBondLength = [&](const std::string &r1, + const std::string &t) -> double { + std::regex regex1(r1); + auto match_begin = + std::sregex_iterator(t.begin(), t.end(), regex1); + auto match_end = std::sregex_iterator(); + std::vector ends; + for (std::sregex_iterator i = match_begin; i != match_end; ++i) { + std::smatch match = *i; + ends.push_back(Point2D(std::stod(match[1]), std::stod(match[2]))); + ends.push_back(Point2D(std::stod(match[3]), std::stod(match[4]))); + } + return (ends[0]-ends[1]).length(); + }; + + { + // make sure it also works with an arbitrarily sized drawer. + auto m = "c1ccccc1"_smiles; + REQUIRE(m); + MolDraw2DUtils::prepareMolForDrawing(*m); + MolDraw2DSVG drawer(500, 500); + MolDraw2DUtils::drawMolACS1996(drawer, *m, "Mol 12", nullptr, nullptr); + drawer.finishDrawing(); + std::string text = drawer.getDrawingText(); + std::ofstream outs(nameBase + "12.svg"); + outs << text; + outs.flush(); + outs.close(); + + std::string regex = + R"(class='bond-0 atom-0 atom-1' d='M ([\d.]*),([\d.]*) L ([\d.]*),([\d.]*)')"; + double dbl = drawnBondLength(regex, text); + // the bonds should all be 14.4 long, but the SVG is only written + // to 1 decimal place, so rounding errors are largish. + REQUIRE(dbl == Approx(14.4253)); + regex = + R"(class='bond-1 atom-1 atom-2' d='M ([\d.]*),([\d.]*) L ([\d.]*),([\d.]*)')"; + dbl = drawnBondLength(regex, text); + REQUIRE(dbl == Approx(14.4)); + check_file_hash(nameBase + "12.svg"); + } #endif } } From c1f68ea574b16a63158bab6fb0b00299f785a69a Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Tue, 13 Sep 2022 14:49:45 +0200 Subject: [PATCH 3/8] Fixes #5505: problems when kekulizing molecules with query bonds (#5550) * Fixes #5505 * Switch to using hasBondTypeQuery() * update the docs * ensure we still fail with non-ring aromatic atoms * changes in response to review --- Code/GraphMol/Kekulize.cpp | 174 +++++++++++++++++-------------- Code/GraphMol/MolOps.h | 8 +- Code/GraphMol/Wrap/MolOps.cpp | 36 ++++--- Code/GraphMol/catch_graphmol.cpp | 54 +++++++++- 4 files changed, 177 insertions(+), 95 deletions(-) diff --git a/Code/GraphMol/Kekulize.cpp b/Code/GraphMol/Kekulize.cpp index 780f31b890..a087b7cff9 100644 --- a/Code/GraphMol/Kekulize.cpp +++ b/Code/GraphMol/Kekulize.cpp @@ -8,6 +8,7 @@ // of the RDKit source tree. // #include +#include #include #include #include @@ -503,19 +504,28 @@ void kekulizeFused(RWMol &mol, const VECT_INT_VECT ås, namespace MolOps { namespace details { void KekulizeFragment(RWMol &mol, const boost::dynamic_bitset<> &atomsToUse, - const boost::dynamic_bitset<> &bondsToUse, - bool markAtomsBonds, unsigned int maxBackTracks) { + boost::dynamic_bitset<> bondsToUse, bool markAtomsBonds, + unsigned int maxBackTracks) { PRECONDITION(atomsToUse.size() == mol.getNumAtoms(), "atomsToUse is wrong size"); PRECONDITION(bondsToUse.size() == mol.getNumBonds(), "bondsToUse is wrong size"); + // if there are no atoms to use we can directly return + if (atomsToUse.none()) { + return; + } - // there's no point doing kekulization if there are no aromatic bonds: + // there's no point doing kekulization if there are no aromatic bonds + // without queries: bool foundAromatic = false; for (const auto bond : mol.bonds()) { - if (bondsToUse[bond->getIdx()] && bond->getIsAromatic()) { - foundAromatic = true; - break; + if (bondsToUse[bond->getIdx()]) { + if (QueryOps::hasBondTypeQuery(*bond)) { + // we don't kekulize bonds with bond type queries + bondsToUse[bond->getIdx()] = 0; + } else if (bond->getIsAromatic()) { + foundAromatic = true; + } } } @@ -524,7 +534,8 @@ void KekulizeFragment(RWMol &mol, const boost::dynamic_bitset<> &atomsToUse, // checking auto numAtoms = mol.getNumAtoms(); INT_VECT valences(numAtoms); - boost::dynamic_bitset<> dummyAts(mol.getNumAtoms()); + boost::dynamic_bitset<> dummyAts(numAtoms); + for (auto atom : mol.atoms()) { if (!atomsToUse[atom->getIdx()]) { continue; @@ -541,82 +552,91 @@ void KekulizeFragment(RWMol &mol, const boost::dynamic_bitset<> &atomsToUse, if (!foundAromatic) { return; } - - // A bit on the state of the molecule at this point - // - aromatic and non aromatic atoms and bonds may be mixed up - - // - for all aromatic bonds it is assumed that that both the following - // are true: - // - getIsAromatic returns true - // - getBondType return aromatic - // - all aromatic atoms return true for "getIsAromatic" - - // first find all the simple rings in the molecule that are not - // completely composed of dummy atoms - VECT_INT_VECT allringsSSSR; - if (!mol.getRingInfo()->isInitialized()) { - MolOps::findSSSR(mol, allringsSSSR); - } - const VECT_INT_VECT &allrings = - allringsSSSR.empty() ? mol.getRingInfo()->atomRings() : allringsSSSR; - VECT_INT_VECT arings; - arings.reserve(allrings.size()); - auto copyAtomRingsWithinFragmentUnlessAllDummy = - [&atomsToUse, &dummyAts](const INT_VECT &ring) { - bool ringOk = false; - for (auto ai : ring) { - if (!atomsToUse[ai]) { - return false; - } - if (!dummyAts[ai]) { - ringOk = true; + // if any bonds to kekulize then give it a try: + if (bondsToUse.any()) { + // A bit on the state of the molecule at this point + // - aromatic and non aromatic atoms and bonds may be mixed up + + // - for all aromatic bonds it is assumed that that both the following + // are true: + // - getIsAromatic returns true + // - getBondType return aromatic + // - all aromatic atoms return true for "getIsAromatic" + + // first find all the simple rings in the molecule that are not + // completely composed of dummy atoms + VECT_INT_VECT allringsSSSR; + if (!mol.getRingInfo()->isInitialized()) { + MolOps::findSSSR(mol, allringsSSSR); + } + const VECT_INT_VECT &allrings = + allringsSSSR.empty() ? mol.getRingInfo()->atomRings() : allringsSSSR; + VECT_INT_VECT arings; + arings.reserve(allrings.size()); + auto copyAtomRingsWithinFragmentUnlessAllDummy = + [&atomsToUse, &dummyAts](const INT_VECT &ring) { + bool ringOk = false; + for (auto ai : ring) { + if (!atomsToUse[ai]) { + return false; + } + if (!dummyAts[ai]) { + ringOk = true; + } } + return ringOk; + }; + std::copy_if(allrings.begin(), allrings.end(), std::back_inserter(arings), + copyAtomRingsWithinFragmentUnlessAllDummy); + + VECT_INT_VECT allbrings; + RingUtils::convertToBonds(arings, allbrings, mol); + VECT_INT_VECT brings; + brings.reserve(allbrings.size()); + auto copyBondRingsWithinFragment = [&bondsToUse](const INT_VECT &ring) { + return std::all_of(ring.begin(), ring.end(), [&bondsToUse](const int bi) { + return bondsToUse[bi]; + }); + }; + VECT_INT_VECT aringsRemaining; + aringsRemaining.reserve(arings.size()); + for (unsigned i = 0; i < allbrings.size(); ++i) { + if (copyBondRingsWithinFragment(allbrings[i])) { + brings.push_back(allbrings[i]); + aringsRemaining.push_back(arings[i]); + } + } + arings = std::move(aringsRemaining); + + // make a neighbor map for the rings i.e. a ring is a + // neighbor to another candidate ring if it shares at least + // one bond + // useful to figure out fused systems + INT_INT_VECT_MAP neighMap; + RingUtils::makeRingNeighborMap(brings, neighMap); + + int curr = 0; + int cnrs = rdcast(arings.size()); + boost::dynamic_bitset<> fusDone(cnrs); + while (curr < cnrs) { + INT_VECT fused; + RingUtils::pickFusedRings(curr, neighMap, fused, fusDone); + VECT_INT_VECT frings(fused.size()); + std::transform(fused.begin(), fused.end(), frings.begin(), + [ås](const int ri) { return arings[ri]; }); + kekulizeFused(mol, frings, maxBackTracks); + int rix; + for (rix = 0; rix < cnrs; ++rix) { + if (!fusDone[rix]) { + curr = rix; + break; } - return ringOk; - }; - std::copy_if(allrings.begin(), allrings.end(), std::back_inserter(arings), - copyAtomRingsWithinFragmentUnlessAllDummy); - - VECT_INT_VECT allbrings; - RingUtils::convertToBonds(arings, allbrings, mol); - VECT_INT_VECT brings; - brings.reserve(allbrings.size()); - auto copyBondRingsWithinFragment = [&bondsToUse](const INT_VECT &ring) { - return std::all_of(ring.begin(), ring.end(), - [&bondsToUse](const int bi) { return bondsToUse[bi]; }); - }; - std::copy_if(allbrings.begin(), allbrings.end(), std::back_inserter(brings), - copyBondRingsWithinFragment); - - // make a neighbor map for the rings i.e. a ring is a - // neighbor to another candidate ring if it shares at least - // one bond - // useful to figure out fused systems - INT_INT_VECT_MAP neighMap; - RingUtils::makeRingNeighborMap(brings, neighMap); - - int curr = 0; - int cnrs = rdcast(arings.size()); - boost::dynamic_bitset<> fusDone(cnrs); - while (curr < cnrs) { - INT_VECT fused; - RingUtils::pickFusedRings(curr, neighMap, fused, fusDone); - VECT_INT_VECT frings(fused.size()); - std::transform(fused.begin(), fused.end(), frings.begin(), - [ås](const int ri) { return arings[ri]; }); - kekulizeFused(mol, frings, maxBackTracks); - int rix; - for (rix = 0; rix < cnrs; ++rix) { - if (!fusDone[rix]) { - curr = rix; + } + if (rix == cnrs) { break; } } - if (rix == cnrs) { - break; - } } - if (markAtomsBonds) { // if we want the atoms and bonds to be marked non-aromatic do // that here. diff --git a/Code/GraphMol/MolOps.h b/Code/GraphMol/MolOps.h index 88abdc1f33..464650b58f 100644 --- a/Code/GraphMol/MolOps.h +++ b/Code/GraphMol/MolOps.h @@ -615,8 +615,10 @@ RDKIT_GRAPHMOL_EXPORT void adjustHs(RWMol &mol); double bond if we hit a wall in the kekulization process Notes: - - even if \c markAtomsBonds is \c false the \c BondType for all aromatic - bonds will be changed from \c RDKit::Bond::AROMATIC to \c + - this does not modify query bonds which have bond type queries (like those + which come from SMARTS) or rings containing them. + - even if \c markAtomsBonds is \c false the \c BondType for all modified + aromatic bonds will be changed from \c RDKit::Bond::AROMATIC to \c RDKit::Bond::SINGLE or RDKit::Bond::DOUBLE during Kekulization. */ @@ -1018,7 +1020,7 @@ namespace details { //! not recommended for use in other code RDKIT_GRAPHMOL_EXPORT void KekulizeFragment( RWMol &mol, const boost::dynamic_bitset<> &atomsToUse, - const boost::dynamic_bitset<> &bondsToUse, bool markAtomsBonds = true, + boost::dynamic_bitset<> bondsToUse, bool markAtomsBonds = true, unsigned int maxBackTracks = 100); } // namespace details diff --git a/Code/GraphMol/Wrap/MolOps.cpp b/Code/GraphMol/Wrap/MolOps.cpp index 8d5e106698..63d635be38 100644 --- a/Code/GraphMol/Wrap/MolOps.cpp +++ b/Code/GraphMol/Wrap/MolOps.cpp @@ -1495,20 +1495,28 @@ to the terminal dummy atoms.\n\ // ------------------------------------------------------------------------ docString = - "Kekulizes the molecule\n\ -\n\ - ARGUMENTS:\n\ -\n\ - - mol: the molecule to use\n\ -\n\ - - clearAromaticFlags: (optional) if this toggle is set, all atoms and bonds in the \n\ - molecule will be marked non-aromatic following the kekulization.\n\ - Default value is False.\n\ -\n\ - NOTES:\n\ -\n\ - - The molecule is modified in place.\n\ -\n"; + R"DOC(Kekulizes the molecule + + ARGUMENTS: + + - mol: the molecule to use + + - clearAromaticFlags: (optional) if this toggle is set, all atoms and bonds in the + molecule will be marked non-aromatic following the kekulization. + Default value is False. + + NOTES: + + - The molecule is modified in place. + + - this does not modify query bonds which have bond type queries (like those + which come from SMARTS) or rings containing them. + + - even if clearAromaticFlags is False the BondType for all modified + aromatic bonds will be changed from AROMATIC to SINGLE or DOUBLE + Kekulization. + +)DOC"; python::def("Kekulize", kekulizeMol, (python::arg("mol"), python::arg("clearAromaticFlags") = false), docString.c_str()); diff --git a/Code/GraphMol/catch_graphmol.cpp b/Code/GraphMol/catch_graphmol.cpp index e22bd39f57..b32048b647 100644 --- a/Code/GraphMol/catch_graphmol.cpp +++ b/Code/GraphMol/catch_graphmol.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -2751,4 +2752,55 @@ TEST_CASE( REQUIRE(m); CHECK(m->getAtomWithIdx(0)->getNumRadicalElectrons() == 0); } -} \ No newline at end of file +} + +TEST_CASE( + "github #5505: Running kekulization on mols with query bonds will either fail or return incorrect results") { + SECTION("as reported") { + auto m = "[#6]-c1cccc(-[#6])c1"_smarts; + REQUIRE(m); + REQUIRE(m->getBondWithIdx(2)->hasQuery()); + REQUIRE(m->getBondWithIdx(2)->getBondType() == Bond::BondType::AROMATIC); + MolOps::Kekulize(*m); + REQUIRE(m->getBondWithIdx(2)->hasQuery()); + REQUIRE(m->getBondWithIdx(2)->getBondType() == Bond::BondType::AROMATIC); + } + SECTION("partial kekulization works") { + auto m1 = "c1ccccc1"_smiles; + REQUIRE(m1); + auto m2 = "c1ccccc1"_smarts; + REQUIRE(m2); + m1->insertMol(*m2); + MolOps::findSSSR(*m1); + REQUIRE(!m1->getBondWithIdx(1)->hasQuery()); + REQUIRE(m1->getBondWithIdx(1)->getBondType() == Bond::BondType::AROMATIC); + REQUIRE(m1->getBondWithIdx(6)->hasQuery()); + REQUIRE(m1->getBondWithIdx(6)->getBondType() == Bond::BondType::AROMATIC); + MolOps::Kekulize(*m1); + REQUIRE(!m1->getBondWithIdx(1)->hasQuery()); + REQUIRE(m1->getBondWithIdx(1)->getBondType() != Bond::BondType::AROMATIC); + REQUIRE(m1->getBondWithIdx(6)->hasQuery()); + REQUIRE(m1->getBondWithIdx(6)->getBondType() == Bond::BondType::AROMATIC); + } + SECTION("kekulization with non-bond-type queries works") { + auto m1 = "c1ccccc1"_smiles; + REQUIRE(m1); + QueryBond qbond; + qbond.setBondType(Bond::BondType::AROMATIC); + qbond.setIsAromatic(true); + qbond.setQuery(makeBondIsInRingQuery()); + m1->replaceBond(0, &qbond); + REQUIRE(m1->getBondWithIdx(0)->hasQuery()); + REQUIRE(m1->getBondWithIdx(0)->getBondType() == Bond::BondType::AROMATIC); + MolOps::Kekulize(*m1); + REQUIRE(m1->getBondWithIdx(0)->hasQuery()); + REQUIRE(m1->getBondWithIdx(0)->getBondType() != Bond::BondType::AROMATIC); + } + SECTION("make sure single-atom molecules and mols without rings still fail") { + std::vector expectedFailures = {"p", "c:c"}; + for (const auto &smi : expectedFailures) { + INFO(smi); + CHECK_THROWS_AS(SmilesToMol(smi), MolSanitizeException); + } + } +} From 58cdf0309764327e64aaa722e56a575a5dd8addd Mon Sep 17 00:00:00 2001 From: David Cosgrove Date: Tue, 13 Sep 2022 14:41:52 +0100 Subject: [PATCH 4/8] Fix 5534 (#5535) * Fix crash in brackets extraction. * Add hashcode, tidy. * Remove unused variable. Co-authored-by: David Cosgrove Co-authored-by: Greg Landrum --- Code/GraphMol/MolDraw2D/DrawMol.cpp | 4 +- Code/GraphMol/MolDraw2D/catch_tests.cpp | 125 ++++++++++++++++++++++++ 2 files changed, 127 insertions(+), 2 deletions(-) diff --git a/Code/GraphMol/MolDraw2D/DrawMol.cpp b/Code/GraphMol/MolDraw2D/DrawMol.cpp index 57fbbb480d..7108e9f473 100644 --- a/Code/GraphMol/MolDraw2D/DrawMol.cpp +++ b/Code/GraphMol/MolDraw2D/DrawMol.cpp @@ -595,9 +595,7 @@ void DrawMol::extractBrackets() { } std::vector> sgBondSegments; - int numBrackets = 0; for (auto bndIdx : sg.getBonds()) { - ++numBrackets; const auto bnd = drawMol_->getBondWithIdx(bndIdx); if (std::find(sg.getAtoms().begin(), sg.getAtoms().end(), bnd->getBeginAtomIdx()) != sg.getAtoms().end()) { @@ -610,9 +608,11 @@ void DrawMol::extractBrackets() { atCds_[bnd->getEndAtomIdx()], atCds_[bnd->getBeginAtomIdx()])); } } + int numBrackets = 0; for (const auto &brk : sg.getBrackets()) { // the atom coords have been inverted in y, so the bracket coords // must be, too. + ++numBrackets; Point2D p1{brk[0].x, -brk[0].y}; Point2D p2{brk[1].x, -brk[1].y}; trans.TransformPoint(p1); diff --git a/Code/GraphMol/MolDraw2D/catch_tests.cpp b/Code/GraphMol/MolDraw2D/catch_tests.cpp index dc02c8e054..946047a9c5 100644 --- a/Code/GraphMol/MolDraw2D/catch_tests.cpp +++ b/Code/GraphMol/MolDraw2D/catch_tests.cpp @@ -236,6 +236,7 @@ static const std::map SVG_HASHES = { {"acs1996_12.svg", 2233727631U}, {"test_unspec_stereo.svg", 599119798U}, {"light_blue_h_no_label_1.svg", 3735371135U}, + {"test_github_5534.svg", 574501211U}, {"bond_highlights_1.svg", 1150579427U}, {"bond_highlights_2.svg", 2958558856U}, {"bond_highlights_3.svg", 3466419491U}, @@ -5820,3 +5821,127 @@ M END check_file_hash(filename); } } + +TEST_CASE("Github5534") { + std::string nameBase = "test_github_5534"; + { + auto m = R"CTAB( + INFOCHEM 2D 1 1.00000 0.00000 0 + + 45 45 0 0 0 0 0 0 0 0999 V2000 + -1.3388 1.6804 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.0303 1.6804 0.0000 Si 0 0 0 0 0 0 0 0 0 0 0 0 + -1.0303 1.9890 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.0303 1.3609 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0496 -0.6997 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0496 -0.3581 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0496 -0.0386 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0496 0.2810 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0496 0.6116 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0826 0.9532 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0496 -1.0193 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0496 -1.3499 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0496 -1.6694 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 0.6116 -0.6997 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 0.6116 -0.3581 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 0.6116 -0.0386 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 0.6116 0.2810 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 0.6116 0.6116 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 0.6116 0.9532 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 0.6116 -1.0193 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 0.6116 -1.3499 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 0.6116 -1.6694 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 1.0303 1.6804 0.0000 Si 0 0 0 0 0 0 0 0 0 0 0 0 + 1.0303 2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.0303 1.3609 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.3388 1.6804 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2810 -0.6997 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2810 -0.3581 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2810 -0.0386 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2810 0.2810 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2810 0.6116 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2810 0.9532 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.3361 1.2948 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.1708 1.4601 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.3581 1.6804 0.0000 Si 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0275 1.6804 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.3581 1.9890 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2810 -1.0193 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2810 -1.3499 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2810 -1.6694 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2810 -2.0000 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + -0.6997 1.6804 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.3691 1.6804 0.0000 Si 0 0 0 0 0 0 0 0 0 0 0 0 + -0.3691 1.9890 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.3691 1.3609 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 23 1 0 0 0 0 + 1 35 1 0 0 0 0 + 2 3 1 0 0 0 0 + 2 4 1 0 0 0 0 + 2 42 1 0 0 0 0 + 5 27 1 0 0 0 0 + 6 28 1 0 0 0 0 + 7 29 1 0 0 0 0 + 8 30 1 0 0 0 0 + 9 31 1 0 0 0 0 + 10 32 1 0 0 0 0 + 11 38 1 0 0 0 0 + 12 39 1 0 0 0 0 + 13 40 1 0 0 0 0 + 14 27 1 0 0 0 0 + 15 28 1 0 0 0 0 + 16 29 1 0 0 0 0 + 17 30 1 0 0 0 0 + 18 31 1 0 0 0 0 + 19 32 1 0 0 0 0 + 20 38 1 0 0 0 0 + 21 39 1 0 0 0 0 + 22 40 1 0 0 0 0 + 23 24 1 0 0 0 0 + 23 25 1 0 0 0 0 + 23 26 1 0 0 0 0 + 27 28 1 0 0 0 0 + 27 38 1 0 0 0 0 + 28 29 1 0 0 0 0 + 29 30 1 0 0 0 0 + 30 31 1 0 0 0 0 + 31 32 1 0 0 0 0 + 32 33 1 0 0 0 0 + 33 34 1 0 0 0 0 + 34 35 1 0 0 0 0 + 35 36 1 0 0 0 0 + 35 37 1 0 0 0 0 + 36 43 1 0 0 0 0 + 38 39 1 0 0 0 0 + 39 40 1 0 0 0 0 + 40 41 1 0 0 0 0 + 42 43 1 0 0 0 0 + 43 44 1 0 0 0 0 + 43 45 1 0 0 0 0 +M STY 2 1 GEN 2 GEN +M SAL 1 15 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 +M SBL 1 15 7 16 8 17 9 18 10 19 11 20 12 21 3 39 13 +M SBL 1 5 22 14 23 15 24 +M SDI 1 4 -0.0386 2.0661 -0.0386 1.1846 +M SDI 1 4 0.4683 2.0661 0.4683 1.1846 +M SAL 2 4 42 43 44 45 +M SBL 2 2 6 39 +M SDI 2 4 -0.7658 2.0661 -0.7658 1.1846 +M SDI 2 4 -0.2149 2.0661 -0.2149 1.1846 +M END +)CTAB"_ctab; + REQUIRE(m); + { + MolDraw2DSVG drawer(300, 300, 300, 300, NO_FREETYPE); + drawer.drawMolecule(*m); + drawer.finishDrawing(); + std::string text = drawer.getDrawingText(); + std::ofstream outs(nameBase + ".svg"); + outs << text; + outs.flush(); + outs.close(); + check_file_hash(nameBase + ".svg"); + } + } +} \ No newline at end of file From b47b4891514fc116855469c44531ffc9ae51d10d Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Wed, 14 Sep 2022 04:44:55 +0200 Subject: [PATCH 5/8] Switch yaehmop wrapper to basic cmake (#5558) * switch to basic cmake from external project the external project stuff in cmake is overly opaque * enable yaehmop builds in CI * disable building of the yaehmop binary * Update External/YAeHMOP/CMakeLists.txt Co-authored-by: Ric Co-authored-by: Ric --- .azure-pipelines/linux_build.yml | 1 + .azure-pipelines/linux_build_java.yml | 1 + .azure-pipelines/mac_build.yml | 1 + .azure-pipelines/mac_build_java.yml | 1 + .azure-pipelines/vs_build.yml | 1 + .azure-pipelines/vs_build_dll.yml | 1 + External/YAeHMOP/CMakeLists.txt | 51 +++++++++++++++------------ 7 files changed, 35 insertions(+), 22 deletions(-) diff --git a/.azure-pipelines/linux_build.yml b/.azure-pipelines/linux_build.yml index 27058ea255..59937c050b 100644 --- a/.azure-pipelines/linux_build.yml +++ b/.azure-pipelines/linux_build.yml @@ -32,6 +32,7 @@ steps: -DRDK_BUILD_FREESASA_SUPPORT=ON \ -DRDK_BUILD_AVALON_SUPPORT=ON \ -DRDK_BUILD_INCHI_SUPPORT=ON \ + -DRDK_BUILD_YAEHMOP_SUPPORT=ON \ -DRDK_BUILD_CAIRO_SUPPORT=ON \ -DRDK_BUILD_QT_SUPPORT=ON \ -DQt5_DIR=/usr/lib/x86_64-linux-gnu/cmake/Qt5 \ diff --git a/.azure-pipelines/linux_build_java.yml b/.azure-pipelines/linux_build_java.yml index 5613762949..e03beb83b2 100644 --- a/.azure-pipelines/linux_build_java.yml +++ b/.azure-pipelines/linux_build_java.yml @@ -24,6 +24,7 @@ steps: -DRDK_BUILD_FREESASA_SUPPORT=ON \ -DRDK_BUILD_AVALON_SUPPORT=ON \ -DRDK_BUILD_INCHI_SUPPORT=ON \ + -DRDK_BUILD_YAEHMOP_SUPPORT=ON \ -DRDK_BUILD_SWIG_WRAPPERS=ON \ -DRDK_SWIG_STATIC=ON \ -DRDK_BUILD_THREADSAFE_SSS=ON \ diff --git a/.azure-pipelines/mac_build.yml b/.azure-pipelines/mac_build.yml index 0110912582..4f511ee386 100644 --- a/.azure-pipelines/mac_build.yml +++ b/.azure-pipelines/mac_build.yml @@ -46,6 +46,7 @@ steps: -DRDK_BUILD_FREESASA_SUPPORT=ON \ -DRDK_BUILD_AVALON_SUPPORT=ON \ -DRDK_BUILD_INCHI_SUPPORT=ON \ + -DRDK_BUILD_YAEHMOP_SUPPORT=ON \ -DRDK_BUILD_CAIRO_SUPPORT=ON \ -DRDK_BUILD_QT_SUPPORT=ON \ -DRDK_BUILD_SWIG_WRAPPERS=OFF \ diff --git a/.azure-pipelines/mac_build_java.yml b/.azure-pipelines/mac_build_java.yml index b27a03351c..3c7d0c6894 100644 --- a/.azure-pipelines/mac_build_java.yml +++ b/.azure-pipelines/mac_build_java.yml @@ -42,6 +42,7 @@ steps: -DRDK_BUILD_FREESASA_SUPPORT=ON \ -DRDK_BUILD_AVALON_SUPPORT=ON \ -DRDK_BUILD_INCHI_SUPPORT=ON \ + -DRDK_BUILD_YAEHMOP_SUPPORT=ON \ -DRDK_BUILD_SWIG_WRAPPERS=ON \ -DRDK_SWIG_STATIC=ON \ -DRDK_BUILD_THREADSAFE_SSS=ON \ diff --git a/.azure-pipelines/vs_build.yml b/.azure-pipelines/vs_build.yml index d2f1611725..283791f10c 100644 --- a/.azure-pipelines/vs_build.yml +++ b/.azure-pipelines/vs_build.yml @@ -31,6 +31,7 @@ steps: -DRDK_BUILD_FREESASA_SUPPORT=ON ^ -DRDK_BUILD_AVALON_SUPPORT=ON ^ -DRDK_BUILD_INCHI_SUPPORT=ON ^ + -DRDK_BUILD_YAEHMOP_SUPPORT=ON ^ -DRDK_BUILD_CAIRO_SUPPORT=ON ^ -DRDK_BUILD_THREADSAFE_SSS=ON ^ -DRDK_BUILD_SWIG_WRAPPERS=OFF ^ diff --git a/.azure-pipelines/vs_build_dll.yml b/.azure-pipelines/vs_build_dll.yml index 350af10597..c938854d49 100644 --- a/.azure-pipelines/vs_build_dll.yml +++ b/.azure-pipelines/vs_build_dll.yml @@ -30,6 +30,7 @@ steps: -DRDK_BUILD_FREESASA_SUPPORT=ON ^ -DRDK_BUILD_AVALON_SUPPORT=ON ^ -DRDK_BUILD_INCHI_SUPPORT=ON ^ + -DRDK_BUILD_YAEHMOP_SUPPORT=ON ^ -DRDK_BUILD_CAIRO_SUPPORT=ON ^ -DRDK_BUILD_THREADSAFE_SSS=ON ^ -DRDK_BUILD_SWIG_WRAPPERS=OFF ^ diff --git a/External/YAeHMOP/CMakeLists.txt b/External/YAeHMOP/CMakeLists.txt index 0fe86a7c38..6217745c28 100644 --- a/External/YAeHMOP/CMakeLists.txt +++ b/External/YAeHMOP/CMakeLists.txt @@ -2,12 +2,29 @@ if(NOT RDK_BUILD_YAEHMOP_SUPPORT) return() endif(NOT RDK_BUILD_YAEHMOP_SUPPORT) -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) - add_definitions(-DRDK_BUILD_YAEHMOP_SUPPORT) -include(ExternalProject) +if(NOT DEFINED YAEHMOP_DIR) + set(YAEHMOP_DIR "${CMAKE_CURRENT_SOURCE_DIR}/yaehmop") +endif() + +if(NOT EXISTS "${YAEHMOP_DIR}/tightbind/bind.h") + set(RELEASE_NO "2022.09.1") + set(MD5 "2d5ee5b6b130529544565240597c602a") + downloadAndCheckMD5("https://github.com/greglandrum/yaehmop/archive/refs/tags/v${RELEASE_NO}.tar.gz" + "${CMAKE_CURRENT_SOURCE_DIR}/yaehmop-${RELEASE_NO}.tar.gz" ${MD5}) + execute_process(COMMAND ${CMAKE_COMMAND} -E tar zxf + ${CMAKE_CURRENT_SOURCE_DIR}/yaehmop-${RELEASE_NO}.tar.gz + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + + file(RENAME "yaehmop-${RELEASE_NO}" "${YAEHMOP_DIR}") +else() + message("-- Found YAeHMOP source in ${YAEHMOP_DIR}") +endif() + +set(yaehmop_INCLUDE_DIRS ${YAEHMOP_DIR}/.. + CACHE STRING "yaehmop Include File" FORCE) +include_directories(${yaehmop_INCLUDE_DIRS}) if(CMAKE_COMPILER_IS_GNUCXX AND NOT CYGWIN) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") @@ -16,34 +33,24 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") endif() -include_directories( ${RDKit_ExternalDir}/YAeHMOP ) +# bring in the eHT code, but skip the targets (we'll get yaehmop_eht anyway because it's a dependency) +add_subdirectory(yaehmop/tightbind EXCLUDE_FROM_ALL True) + +# set install dir for the yaehmop library: +INSTALL(TARGETS yaehmop_eht EXPORT rdkit-targets + DESTINATION ${RDKit_LibDir}/${RDKLIB_DEST} + COMPONENT runtime ) + -ExternalProject_Add(yaehmop_project - GIT_REPOSITORY https://github.com/greglandrum/yaehmop.git - GIT_TAG master - UPDATE_COMMAND "" - PATCH_COMMAND "" - PREFIX ${CMAKE_CURRENT_SOURCE_DIR} - SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/yaehmop" - SOURCE_SUBDIR "tightbind" - CMAKE_ARGS -DUSE_BLAS_LAPACK=OFF -DCMAKE_INSTALL_PREFIX=${PROJECT_BINARY_DIR} -DCMAKE_C_FLAGS=${CMAKE_C_FLAGS} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - TEST_COMMAND "") -include_directories(${PROJECT_BINARY_DIR}/include) -link_directories(${PROJECT_BINARY_DIR}/lib) -link_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/yaehmop_project-build) set(EHT_PARAM_FILE ${CMAKE_CURRENT_SOURCE_DIR}/yaehmop/tightbind/eht_parms.dat ) install(FILES ${EHT_PARAM_FILE} DESTINATION ${RDKit_ShareDir}/Data COMPONENT data) -message("YAeHMOP include_dirs: ${PROJECT_BINARY_DIR}/include") -message("YAeHMOP link_dirs: ${PROJECT_BINARY_DIR}/lib ${CMAKE_CURRENT_SOURCE_DIR}/src/yaehmop_project-build") - rdkit_library(EHTLib EHTTools.cpp SHARED LINK_LIBRARIES yaehmop_eht GraphMol ) target_compile_definitions(EHTLib PRIVATE RDKIT_EHTLIB_BUILD) -add_dependencies(EHTLib yaehmop_project) rdkit_headers(EHTTools.h DEST GraphMol) rdkit_catch_test(testEHTLib1 test1.cpp LINK_LIBRARIES EHTLib FileParsers SmilesParse ) From c305f1252bdb679c9d963cd128d63a055c5399c2 Mon Sep 17 00:00:00 2001 From: greg landrum Date: Wed, 14 Sep 2022 04:56:13 +0200 Subject: [PATCH 6/8] make the xyz2mol functionality optional --- CMakeLists.txt | 12 ++++++++++++ Code/GraphMol/CMakeLists.txt | 4 +++- Code/GraphMol/DetermineBonds/CMakeLists.txt | 3 --- Code/RDGeneral/RDConfig.h.cmake | 4 ++++ 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 51b724d03b..809da1e82a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,6 +53,7 @@ option(RDK_BUILD_COORDGEN_SUPPORT "build the rdkit coordgen wrapper" ON ) option(RDK_BUILD_MAEPARSER_SUPPORT "build the rdkit MAE parser wrapper" ON ) option(RDK_BUILD_MOLINTERCHANGE_SUPPORT "build in support for CommonChem molecule interchange" ON ) option(RDK_BUILD_YAEHMOP_SUPPORT "build support for the YAeHMOP wrapper" OFF) +option(RDK_BUILD_XYZ2MOL_SUPPORT "build in support for the RDKit's implementation of xyx2mol (in the DetermineBonds library)" OFF ) option(RDK_BUILD_STRUCTCHECKER_SUPPORT "build in support for the StructChecker alpha (not recommended, use the MolVS integration instead)" OFF ) option(RDK_USE_URF "Build support for Florian Flachsenberg's URF library" ON) option(RDK_INSTALL_DEV_COMPONENT "install libraries and headers" ON) @@ -205,6 +206,17 @@ if(RDK_USE_URF) include_directories(${RDKit_ExternalDir}/RingFamilies/RingDecomposerLib/src/RingDecomposerLib) endif() +if(RDK_BUILD_XYZ2MOL_SUPPORT) + if(NOT RDK_BUILD_YAEHMOP_SUPPORT) + message("Enabling YAeHMOP support because xyz2mol is being built") + set(RDK_BUILD_YAEHMOP_SUPPORT ON) + endif() + add_definitions(-DRDK_BUILD_XYZ2MOL_SUPPORT) + include_directories(${RDKit_ExternalDir}) +endif() + + + if(CMAKE_SIZEOF_VOID_P EQUAL 4) target_compile_definitions(rdkit_base INTERFACE "-DRDK_32BIT_BUILD") diff --git a/Code/GraphMol/CMakeLists.txt b/Code/GraphMol/CMakeLists.txt index fcc8d12239..0cffaa8729 100644 --- a/Code/GraphMol/CMakeLists.txt +++ b/Code/GraphMol/CMakeLists.txt @@ -101,7 +101,9 @@ add_subdirectory(Trajectory) add_subdirectory(SubstructLibrary) add_subdirectory(RGroupDecomposition) -add_subdirectory(DetermineBonds) +if(RDK_BUILD_XYZ2MOL_SUPPORT) + add_subdirectory(DetermineBonds) +endif() if(RDK_BUILD_MOLINTERCHANGE_SUPPORT) add_subdirectory(MolInterchange) diff --git a/Code/GraphMol/DetermineBonds/CMakeLists.txt b/Code/GraphMol/DetermineBonds/CMakeLists.txt index 858f9d9d76..6efd34331b 100644 --- a/Code/GraphMol/DetermineBonds/CMakeLists.txt +++ b/Code/GraphMol/DetermineBonds/CMakeLists.txt @@ -1,6 +1,3 @@ -# FIX: there's probably a better way to do this -link_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../External/YAeHMOP/src/yaehmop_project-build) - rdkit_library(DetermineBonds DetermineBonds.cpp LINK_LIBRARIES GenericGroups GraphMol RDGeneral FileParsers EHTLib) diff --git a/Code/RDGeneral/RDConfig.h.cmake b/Code/RDGeneral/RDConfig.h.cmake index 07fc79cde9..fb302cd990 100644 --- a/Code/RDGeneral/RDConfig.h.cmake +++ b/Code/RDGeneral/RDConfig.h.cmake @@ -41,3 +41,7 @@ #cmakedefine RDK_BUILD_FREETYPE_SUPPORT #cmakedefine RDK_USE_URF + +#cmakedefine RDK_BUILD_YAEHMOP_SUPPORT + +#cmakedefine RDK_BUILD_XYZ2MOL_SUPPORT From 8cb4e7f6da37c5c5b50c637560507502c3ac4afc Mon Sep 17 00:00:00 2001 From: greg landrum Date: Wed, 14 Sep 2022 05:24:14 +0200 Subject: [PATCH 7/8] enable that for the CI builds --- .azure-pipelines/linux_build.yml | 1 + .azure-pipelines/linux_build_java.yml | 1 + .azure-pipelines/mac_build.yml | 1 + .azure-pipelines/mac_build_java.yml | 1 + .azure-pipelines/vs_build.yml | 1 + .azure-pipelines/vs_build_dll.yml | 1 + 6 files changed, 6 insertions(+) diff --git a/.azure-pipelines/linux_build.yml b/.azure-pipelines/linux_build.yml index 59937c050b..8efe04d089 100644 --- a/.azure-pipelines/linux_build.yml +++ b/.azure-pipelines/linux_build.yml @@ -33,6 +33,7 @@ steps: -DRDK_BUILD_AVALON_SUPPORT=ON \ -DRDK_BUILD_INCHI_SUPPORT=ON \ -DRDK_BUILD_YAEHMOP_SUPPORT=ON \ + -DRDK_BUILD_XYZ2MOL_SUPPORT=ON \ -DRDK_BUILD_CAIRO_SUPPORT=ON \ -DRDK_BUILD_QT_SUPPORT=ON \ -DQt5_DIR=/usr/lib/x86_64-linux-gnu/cmake/Qt5 \ diff --git a/.azure-pipelines/linux_build_java.yml b/.azure-pipelines/linux_build_java.yml index e03beb83b2..d80d53947c 100644 --- a/.azure-pipelines/linux_build_java.yml +++ b/.azure-pipelines/linux_build_java.yml @@ -25,6 +25,7 @@ steps: -DRDK_BUILD_AVALON_SUPPORT=ON \ -DRDK_BUILD_INCHI_SUPPORT=ON \ -DRDK_BUILD_YAEHMOP_SUPPORT=ON \ + -DRDK_BUILD_XYZ2MOL_SUPPORT=ON \ -DRDK_BUILD_SWIG_WRAPPERS=ON \ -DRDK_SWIG_STATIC=ON \ -DRDK_BUILD_THREADSAFE_SSS=ON \ diff --git a/.azure-pipelines/mac_build.yml b/.azure-pipelines/mac_build.yml index 4f511ee386..3698adea11 100644 --- a/.azure-pipelines/mac_build.yml +++ b/.azure-pipelines/mac_build.yml @@ -47,6 +47,7 @@ steps: -DRDK_BUILD_AVALON_SUPPORT=ON \ -DRDK_BUILD_INCHI_SUPPORT=ON \ -DRDK_BUILD_YAEHMOP_SUPPORT=ON \ + -DRDK_BUILD_XYZ2MOL_SUPPORT=ON \ -DRDK_BUILD_CAIRO_SUPPORT=ON \ -DRDK_BUILD_QT_SUPPORT=ON \ -DRDK_BUILD_SWIG_WRAPPERS=OFF \ diff --git a/.azure-pipelines/mac_build_java.yml b/.azure-pipelines/mac_build_java.yml index 3c7d0c6894..3d8cc77c88 100644 --- a/.azure-pipelines/mac_build_java.yml +++ b/.azure-pipelines/mac_build_java.yml @@ -43,6 +43,7 @@ steps: -DRDK_BUILD_AVALON_SUPPORT=ON \ -DRDK_BUILD_INCHI_SUPPORT=ON \ -DRDK_BUILD_YAEHMOP_SUPPORT=ON \ + -DRDK_BUILD_XYZ2MOL_SUPPORT=ON \ -DRDK_BUILD_SWIG_WRAPPERS=ON \ -DRDK_SWIG_STATIC=ON \ -DRDK_BUILD_THREADSAFE_SSS=ON \ diff --git a/.azure-pipelines/vs_build.yml b/.azure-pipelines/vs_build.yml index 283791f10c..67b1459945 100644 --- a/.azure-pipelines/vs_build.yml +++ b/.azure-pipelines/vs_build.yml @@ -32,6 +32,7 @@ steps: -DRDK_BUILD_AVALON_SUPPORT=ON ^ -DRDK_BUILD_INCHI_SUPPORT=ON ^ -DRDK_BUILD_YAEHMOP_SUPPORT=ON ^ + -DRDK_BUILD_XYZ2MOL_SUPPORT=ON ^ -DRDK_BUILD_CAIRO_SUPPORT=ON ^ -DRDK_BUILD_THREADSAFE_SSS=ON ^ -DRDK_BUILD_SWIG_WRAPPERS=OFF ^ diff --git a/.azure-pipelines/vs_build_dll.yml b/.azure-pipelines/vs_build_dll.yml index c938854d49..c23e4f89aa 100644 --- a/.azure-pipelines/vs_build_dll.yml +++ b/.azure-pipelines/vs_build_dll.yml @@ -31,6 +31,7 @@ steps: -DRDK_BUILD_AVALON_SUPPORT=ON ^ -DRDK_BUILD_INCHI_SUPPORT=ON ^ -DRDK_BUILD_YAEHMOP_SUPPORT=ON ^ + -DRDK_BUILD_XYZ2MOL_SUPPORT=ON ^ -DRDK_BUILD_CAIRO_SUPPORT=ON ^ -DRDK_BUILD_THREADSAFE_SSS=ON ^ -DRDK_BUILD_SWIG_WRAPPERS=OFF ^ From 35769e26bbedd89d2fcde1d98e6bef286c2d06eb Mon Sep 17 00:00:00 2001 From: Greg Landrum Date: Wed, 14 Sep 2022 13:22:50 +0200 Subject: [PATCH 8/8] Update CMakeLists.txt Co-authored-by: Sreya Gogineni <74024376+gosreya@users.noreply.github.com> --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 809da1e82a..7ef50bbbff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,7 +53,7 @@ option(RDK_BUILD_COORDGEN_SUPPORT "build the rdkit coordgen wrapper" ON ) option(RDK_BUILD_MAEPARSER_SUPPORT "build the rdkit MAE parser wrapper" ON ) option(RDK_BUILD_MOLINTERCHANGE_SUPPORT "build in support for CommonChem molecule interchange" ON ) option(RDK_BUILD_YAEHMOP_SUPPORT "build support for the YAeHMOP wrapper" OFF) -option(RDK_BUILD_XYZ2MOL_SUPPORT "build in support for the RDKit's implementation of xyx2mol (in the DetermineBonds library)" OFF ) +option(RDK_BUILD_XYZ2MOL_SUPPORT "build in support for the RDKit's implementation of xyz2mol (in the DetermineBonds library)" OFF ) option(RDK_BUILD_STRUCTCHECKER_SUPPORT "build in support for the StructChecker alpha (not recommended, use the MolVS integration instead)" OFF ) option(RDK_USE_URF "Build support for Florian Flachsenberg's URF library" ON) option(RDK_INSTALL_DEV_COMPONENT "install libraries and headers" ON)