mirror of
https://github.com/rdkit/rdkit.git
synced 2026-06-05 22:04:27 +08:00
555 lines
18 KiB
C++
555 lines
18 KiB
C++
//
|
|
// Copyright (C) 2019 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 CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do
|
|
// this in one cpp file
|
|
#include "catch.hpp"
|
|
|
|
#include <GraphMol/RDKitBase.h>
|
|
|
|
#include <GraphMol/SmilesParse/SmilesParse.h>
|
|
#include <GraphMol/FileParsers/FileParsers.h>
|
|
#include <GraphMol/MolDraw2D/MolDraw2D.h>
|
|
#include <GraphMol/MolDraw2D/MolDraw2DSVG.h>
|
|
#include <GraphMol/MolDraw2D/MolDraw2DUtils.h>
|
|
#include <boost/algorithm/string/split.hpp>
|
|
|
|
#ifdef RDK_BUILD_CAIRO_SUPPORT
|
|
#include <cairo.h>
|
|
#include "MolDraw2DCairo.h"
|
|
#endif
|
|
|
|
using namespace RDKit;
|
|
|
|
TEST_CASE("prepareAndDrawMolecule", "[drawing]") {
|
|
SECTION("basics") {
|
|
auto m1 = "C1N[C@@H]2OCC12"_smiles;
|
|
REQUIRE(m1);
|
|
|
|
// we will be able to recognize that the prep worked because there
|
|
// will be an H in the output:
|
|
MolDraw2DSVG drawer(200, 200);
|
|
MolDraw2DUtils::prepareAndDrawMolecule(drawer, *m1);
|
|
drawer.finishDrawing();
|
|
std::string text = drawer.getDrawingText();
|
|
CHECK(text.find("<tspan>H</tspan>") != std::string::npos);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("tag atoms in SVG", "[drawing, SVG]") {
|
|
SECTION("basics") {
|
|
auto m1 = "C1N[C@@H]2OCC12"_smiles;
|
|
REQUIRE(m1);
|
|
|
|
MolDraw2DSVG drawer(200, 200);
|
|
MolDraw2DUtils::prepareMolForDrawing(*m1);
|
|
drawer.drawMolecule(*m1);
|
|
std::map<std::string, std::string> actions;
|
|
actions["onclick"] = "alert";
|
|
double radius = 0.2;
|
|
drawer.tagAtoms(*m1, radius, actions);
|
|
drawer.finishDrawing();
|
|
std::string text = drawer.getDrawingText();
|
|
std::ofstream outs("testAtomTags_1.svg");
|
|
outs << text;
|
|
outs.flush();
|
|
|
|
CHECK(text.find("<circle") != std::string::npos);
|
|
CHECK(text.find("<circle") != std::string::npos);
|
|
CHECK(text.find("atom-selector") != std::string::npos);
|
|
CHECK(text.find("bond-selector") != std::string::npos);
|
|
}
|
|
}
|
|
TEST_CASE("contour data", "[drawing, conrec]") {
|
|
auto m1 = "C1N[C@@H]2OCC12"_smiles;
|
|
REQUIRE(m1);
|
|
SECTION("grid basics") {
|
|
MolDraw2DSVG drawer(250, 250);
|
|
MolDraw2DUtils::prepareMolForDrawing(*m1);
|
|
|
|
const size_t gridSz = 100;
|
|
auto *grid = new double[gridSz * gridSz];
|
|
std::vector<double> xps(gridSz);
|
|
std::vector<double> yps(gridSz);
|
|
|
|
double minX = 1000, minY = 1000, maxX = -1000, maxY = -1000;
|
|
const auto conf = m1->getConformer();
|
|
for (size_t i = 0; i < conf.getNumAtoms(); ++i) {
|
|
minX = std::min(minX, conf.getAtomPos(i).x);
|
|
minY = std::min(minY, conf.getAtomPos(i).y);
|
|
maxX = std::max(maxX, conf.getAtomPos(i).x);
|
|
maxY = std::max(maxY, conf.getAtomPos(i).y);
|
|
}
|
|
double x1 = minX - 0.5, y1 = minY - 0.5, x2 = maxX + 0.5, y2 = maxY + 0.5;
|
|
double dx = (x2 - x1) / gridSz, dy = (y2 - y1) / gridSz;
|
|
double maxV = 0.0;
|
|
for (size_t ix = 0; ix < gridSz; ++ix) {
|
|
auto px = x1 + ix * dx;
|
|
xps[ix] = px;
|
|
for (size_t iy = 0; iy < gridSz; ++iy) {
|
|
auto py = y1 + iy * dy;
|
|
if (ix == 0) {
|
|
yps[iy] = py;
|
|
}
|
|
RDGeom::Point2D loc(px, py);
|
|
double val = 0.0;
|
|
for (size_t ia = 0; ia < conf.getNumAtoms(); ++ia) {
|
|
auto dv = loc - RDGeom::Point2D(conf.getAtomPos(ia).x,
|
|
conf.getAtomPos(ia).y);
|
|
auto r = dv.length();
|
|
if (r > 0.1) {
|
|
val += 1 / r;
|
|
}
|
|
}
|
|
maxV = std::max(val, maxV);
|
|
grid[ix * gridSz + iy] = val;
|
|
}
|
|
}
|
|
|
|
std::vector<double> levels;
|
|
drawer.clearDrawing();
|
|
MolDraw2DUtils::contourAndDrawGrid(drawer, grid, xps, yps, 10, levels);
|
|
drawer.drawOptions().clearBackground = false;
|
|
drawer.drawMolecule(*m1);
|
|
drawer.finishDrawing();
|
|
std::string text = drawer.getDrawingText();
|
|
std::ofstream outs("contourMol_1.svg");
|
|
outs << text;
|
|
outs.flush();
|
|
delete[] grid;
|
|
}
|
|
SECTION("gaussian basics") {
|
|
MolDraw2DSVG drawer(250, 250);
|
|
MolDraw2DUtils::prepareMolForDrawing(*m1);
|
|
drawer.drawOptions().padding = 0.1;
|
|
|
|
const auto conf = m1->getConformer();
|
|
std::vector<Point2D> cents(conf.getNumAtoms());
|
|
std::vector<double> weights(conf.getNumAtoms());
|
|
std::vector<double> widths(conf.getNumAtoms());
|
|
for (size_t i = 0; i < conf.getNumAtoms(); ++i) {
|
|
cents[i] = Point2D(conf.getAtomPos(i).x, conf.getAtomPos(i).y);
|
|
weights[i] = 1;
|
|
widths[i] = 0.4 * PeriodicTable::getTable()->getRcovalent(
|
|
m1->getAtomWithIdx(i)->getAtomicNum());
|
|
}
|
|
|
|
std::vector<double> levels;
|
|
drawer.clearDrawing();
|
|
MolDraw2DUtils::contourAndDrawGaussians(drawer, cents, weights, widths, 10,
|
|
levels);
|
|
|
|
drawer.drawOptions().clearBackground = false;
|
|
drawer.drawMolecule(*m1);
|
|
drawer.finishDrawing();
|
|
std::string text = drawer.getDrawingText();
|
|
std::ofstream outs("contourMol_2.svg");
|
|
outs << text;
|
|
outs.flush();
|
|
}
|
|
SECTION("gaussian fill") {
|
|
MolDraw2DSVG drawer(250, 250);
|
|
MolDraw2DUtils::prepareMolForDrawing(*m1);
|
|
drawer.drawOptions().padding = 0.1;
|
|
|
|
const auto conf = m1->getConformer();
|
|
std::vector<Point2D> cents(conf.getNumAtoms());
|
|
std::vector<double> weights(conf.getNumAtoms());
|
|
std::vector<double> widths(conf.getNumAtoms());
|
|
for (size_t i = 0; i < conf.getNumAtoms(); ++i) {
|
|
cents[i] = Point2D(conf.getAtomPos(i).x, conf.getAtomPos(i).y);
|
|
weights[i] = i % 2 ? -0.5 : 1;
|
|
widths[i] = 0.4 * PeriodicTable::getTable()->getRcovalent(
|
|
m1->getAtomWithIdx(i)->getAtomicNum());
|
|
}
|
|
|
|
std::vector<double> levels;
|
|
MolDraw2DUtils::ContourParams cps;
|
|
cps.fillGrid = true;
|
|
drawer.clearDrawing();
|
|
MolDraw2DUtils::contourAndDrawGaussians(drawer, cents, weights, widths, 10,
|
|
levels, cps);
|
|
|
|
drawer.drawOptions().clearBackground = false;
|
|
drawer.drawMolecule(*m1);
|
|
drawer.finishDrawing();
|
|
std::string text = drawer.getDrawingText();
|
|
std::ofstream outs("contourMol_3.svg");
|
|
outs << text;
|
|
outs.flush();
|
|
}
|
|
|
|
SECTION("gaussian fill 2") {
|
|
auto m2 = "C1N[C@@H]2OCC12C=CC"_smiles;
|
|
REQUIRE(m2);
|
|
|
|
MolDraw2DSVG drawer(450, 250);
|
|
MolDraw2DUtils::prepareMolForDrawing(*m2);
|
|
drawer.drawOptions().padding = 0.1;
|
|
|
|
const auto conf = m2->getConformer();
|
|
std::vector<Point2D> cents(conf.getNumAtoms());
|
|
std::vector<double> weights(conf.getNumAtoms());
|
|
std::vector<double> widths(conf.getNumAtoms());
|
|
for (size_t i = 0; i < conf.getNumAtoms(); ++i) {
|
|
cents[i] = Point2D(conf.getAtomPos(i).x, conf.getAtomPos(i).y);
|
|
weights[i] = i % 2 ? -0.5 : 1;
|
|
widths[i] = 0.3 * PeriodicTable::getTable()->getRcovalent(
|
|
m2->getAtomWithIdx(i)->getAtomicNum());
|
|
}
|
|
|
|
std::vector<double> levels;
|
|
MolDraw2DUtils::ContourParams cps;
|
|
cps.fillGrid = true;
|
|
cps.gridResolution = 0.5;
|
|
drawer.clearDrawing();
|
|
MolDraw2DUtils::contourAndDrawGaussians(drawer, cents, weights, widths, 10,
|
|
levels, cps);
|
|
|
|
drawer.drawOptions().clearBackground = false;
|
|
drawer.drawMolecule(*m2);
|
|
drawer.finishDrawing();
|
|
std::string text = drawer.getDrawingText();
|
|
std::ofstream outs("contourMol_4.svg");
|
|
outs << text;
|
|
outs.flush();
|
|
}
|
|
}
|
|
|
|
TEST_CASE("dative bonds", "[drawing, organometallics]") {
|
|
SECTION("basics") {
|
|
auto m1 = "N->[Pt]"_smiles;
|
|
REQUIRE(m1);
|
|
MolDraw2DSVG drawer(200, 200);
|
|
MolDraw2DUtils::prepareMolForDrawing(*m1);
|
|
drawer.drawMolecule(*m1);
|
|
drawer.finishDrawing();
|
|
std::string text = drawer.getDrawingText();
|
|
std::ofstream outs("testDativeBonds_1.svg");
|
|
outs << text;
|
|
outs.flush();
|
|
|
|
CHECK(text.find("<path class='bond-0' d='M 55.1495,101.204"
|
|
" L 52.2436,100 L 55.1495,98.7964") != std::string::npos);
|
|
}
|
|
SECTION("more complex") {
|
|
auto m1 = "N->1[C@@H]2CCCC[C@H]2N->[Pt]11OC(=O)C(=O)O1"_smiles;
|
|
REQUIRE(m1);
|
|
MolDraw2DSVG drawer(200, 200);
|
|
MolDraw2DUtils::prepareMolForDrawing(*m1);
|
|
drawer.drawMolecule(*m1);
|
|
drawer.finishDrawing();
|
|
std::string text = drawer.getDrawingText();
|
|
std::ofstream outs("testDativeBonds_2.svg");
|
|
outs << text;
|
|
outs.flush();
|
|
|
|
CHECK(text.find("<path class='bond-7' d='M 92.9861,93.568"
|
|
" L 92.2758,94.0033 L 92.4703,93.1932") !=
|
|
std::string::npos);
|
|
}
|
|
SECTION("test colours") {
|
|
// the dative bonds point the wrong way, but the point is to test
|
|
// if the tip of the arrow is blue.
|
|
auto m1 = "[Cu++]->1->2.N1CCN2"_smiles;
|
|
REQUIRE(m1);
|
|
MolDraw2DSVG drawer(200, 200);
|
|
MolDraw2DUtils::prepareMolForDrawing(*m1);
|
|
drawer.drawMolecule(*m1);
|
|
drawer.finishDrawing();
|
|
std::string text = drawer.getDrawingText();
|
|
std::ofstream outs("testDativeBonds_3.svg");
|
|
outs << text;
|
|
outs.flush();
|
|
|
|
CHECK(text.find("<path class='bond-2' d='M 61.7343,143.825"
|
|
" L 89.7427,152.925' style='fill:none;"
|
|
"fill-rule:evenodd;stroke:#0000FF") != std::string::npos);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("zero-order bonds", "[drawing, organometallics]") {
|
|
SECTION("basics") {
|
|
auto m1 = "N-[Pt]"_smiles;
|
|
REQUIRE(m1);
|
|
m1->getBondWithIdx(0)->setBondType(Bond::ZERO);
|
|
MolDraw2DSVG drawer(200, 200);
|
|
MolDraw2DUtils::prepareMolForDrawing(*m1);
|
|
drawer.drawMolecule(*m1);
|
|
drawer.finishDrawing();
|
|
std::string text = drawer.getDrawingText();
|
|
std::ofstream outs("testZeroOrderBonds_1.svg");
|
|
outs << text;
|
|
outs.flush();
|
|
|
|
CHECK(text.find("stroke-dasharray:2,2") != std::string::npos);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("copying drawing options", "[drawing]") {
|
|
auto m1 = "C1N[C@@H]2OCC12"_smiles;
|
|
REQUIRE(m1);
|
|
SECTION("foundations") {
|
|
{
|
|
MolDraw2DSVG drawer(200, 200);
|
|
MolDraw2DUtils::prepareAndDrawMolecule(drawer, *m1);
|
|
drawer.finishDrawing();
|
|
std::string text = drawer.getDrawingText();
|
|
CHECK(text.find("fill:#0000FF' ><tspan>HN") != std::string::npos);
|
|
}
|
|
{
|
|
MolDraw2DSVG drawer(200, 200);
|
|
assignBWPalette(drawer.drawOptions().atomColourPalette);
|
|
MolDraw2DUtils::prepareAndDrawMolecule(drawer, *m1);
|
|
drawer.finishDrawing();
|
|
std::string text = drawer.getDrawingText();
|
|
CHECK(text.find("fill:#0000FF' ><tspan>HN") == std::string::npos);
|
|
CHECK(text.find("fill:#000000' ><tspan>HN") != std::string::npos);
|
|
}
|
|
}
|
|
SECTION("test") {
|
|
{
|
|
MolDraw2DSVG drawer(200, 200);
|
|
MolDrawOptions options = drawer.drawOptions();
|
|
assignBWPalette(options.atomColourPalette);
|
|
drawer.drawOptions() = options;
|
|
MolDraw2DUtils::prepareAndDrawMolecule(drawer, *m1);
|
|
drawer.finishDrawing();
|
|
std::string text = drawer.getDrawingText();
|
|
CHECK(text.find("fill:#0000FF' ><tspan>HN") == std::string::npos);
|
|
CHECK(text.find("fill:#000000' ><tspan>HN") != std::string::npos);
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_CASE("bad DrawMolecules() when molecules are not kekulized",
|
|
"[drawing,bug]") {
|
|
auto m1 = "CCN(CC)CCn1nc2c3ccccc3sc3c(CNS(C)(=O)=O)ccc1c32"_smiles;
|
|
REQUIRE(m1);
|
|
SECTION("foundations") {
|
|
MolDraw2DSVG drawer(500, 200, 250, 200);
|
|
drawer.drawOptions().prepareMolsBeforeDrawing = false;
|
|
RWMol dm1(*m1);
|
|
RWMol dm2(*m1);
|
|
bool kekulize = false;
|
|
MolDraw2DUtils::prepareMolForDrawing(dm1, kekulize);
|
|
kekulize = true;
|
|
MolDraw2DUtils::prepareMolForDrawing(dm2, kekulize);
|
|
MOL_PTR_VECT ms{&dm1, &dm2};
|
|
drawer.drawMolecule(dm1);
|
|
drawer.finishDrawing();
|
|
std::string text = drawer.getDrawingText();
|
|
std::ofstream outs("testKekulizationProblems_1.svg");
|
|
outs << text;
|
|
outs.flush();
|
|
|
|
// this is a very crude test - really we just need to look at the SVG - but
|
|
// it's better than nothing.
|
|
CHECK(text.find(
|
|
"<path class='bond-18' d='M 169.076,79.056 L 191.285,69.2653' "
|
|
"style='fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:"
|
|
"2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;"
|
|
"stroke-dasharray:6,6' />") == std::string::npos);
|
|
}
|
|
}
|
|
TEST_CASE("draw atom/bond indices", "[drawing]") {
|
|
auto m1 = "C[C@H](F)N"_smiles;
|
|
REQUIRE(m1);
|
|
SECTION("foundations") {
|
|
{
|
|
MolDraw2DSVG drawer(250, 200);
|
|
drawer.drawMolecule(*m1);
|
|
drawer.finishDrawing();
|
|
std::string text = drawer.getDrawingText();
|
|
std::ofstream outs("testAtomBondIndices_1.svg");
|
|
outs << text;
|
|
outs.flush();
|
|
CHECK(text.find("<tspan>1</tspan>") == std::string::npos);
|
|
CHECK(text.find("<tspan>1,(S)</tspan>") == std::string::npos);
|
|
}
|
|
{
|
|
MolDraw2DSVG drawer(250, 200);
|
|
drawer.drawOptions().addAtomIndices = true;
|
|
drawer.drawMolecule(*m1);
|
|
drawer.finishDrawing();
|
|
std::string text = drawer.getDrawingText();
|
|
std::ofstream outs("testAtomBondIndices_2.svg");
|
|
outs << text;
|
|
outs.flush();
|
|
CHECK(text.find("<tspan>1</tspan>") != std::string::npos);
|
|
// it only appears once though:
|
|
CHECK(text.find("<tspan>1</tspan>", text.find("<tspan>1</tspan>") + 1) ==
|
|
std::string::npos);
|
|
CHECK(text.find("1,(S)") == std::string::npos);
|
|
}
|
|
{
|
|
MolDraw2DSVG drawer(250, 200);
|
|
drawer.drawOptions().addBondIndices = true;
|
|
drawer.drawMolecule(*m1);
|
|
drawer.finishDrawing();
|
|
std::string text = drawer.getDrawingText();
|
|
std::ofstream outs("testAtomBondIndices_3.svg");
|
|
outs << text;
|
|
outs.flush();
|
|
CHECK(text.find("<tspan>1</tspan>") != std::string::npos);
|
|
// it only appears once though:
|
|
CHECK(text.find("<tspan>1</tspan>", text.find("<tspan>1</tspan>") + 1) ==
|
|
std::string::npos);
|
|
}
|
|
{
|
|
MolDraw2DSVG drawer(250, 200);
|
|
drawer.drawOptions().addAtomIndices = true;
|
|
drawer.drawOptions().addBondIndices = true;
|
|
drawer.drawMolecule(*m1);
|
|
drawer.finishDrawing();
|
|
std::string text = drawer.getDrawingText();
|
|
std::ofstream outs("testAtomBondIndices_4.svg");
|
|
outs << text;
|
|
outs.flush();
|
|
CHECK(text.find("<tspan>1</tspan>") != std::string::npos);
|
|
// it appears twice:
|
|
CHECK(text.find("<tspan>1</tspan>", text.find("<tspan>1</tspan>") + 1) !=
|
|
std::string::npos);
|
|
}
|
|
{
|
|
MolDraw2DSVG drawer(250, 200);
|
|
m1->getAtomWithIdx(2)->setProp(common_properties::atomNote, "foo");
|
|
drawer.drawOptions().addAtomIndices = true;
|
|
drawer.drawOptions().addStereoAnnotation = true;
|
|
drawer.drawMolecule(*m1);
|
|
m1->getAtomWithIdx(2)->clearProp(common_properties::atomNote);
|
|
drawer.finishDrawing();
|
|
std::string text = drawer.getDrawingText();
|
|
std::ofstream outs("testAtomBondIndices_5.svg");
|
|
outs << text;
|
|
outs.flush();
|
|
CHECK(text.find("<tspan>1,(S)</tspan>") != std::string::npos);
|
|
CHECK(text.find("<tspan>2,foo</tspan>") != std::string::npos);
|
|
CHECK(text.find("<tspan>1</tspan>") == std::string::npos);
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Github #3226: Lines in wedge bonds being drawn too closely together",
|
|
"[drawing]") {
|
|
auto m1 =
|
|
"C[C@H](C1=C(C=CC(=C1Cl)F)Cl)OC2=C(N=CC(=C2)C3=CN(N=C3)C4CCNCC4)N"_smiles;
|
|
REQUIRE(m1);
|
|
SECTION("larger SVG") {
|
|
{
|
|
MolDraw2DSVG drawer(450, 400);
|
|
drawer.drawMolecule(*m1);
|
|
drawer.finishDrawing();
|
|
std::string text = drawer.getDrawingText();
|
|
std::ofstream outs("testGithub3226_1.svg");
|
|
outs << text;
|
|
outs.flush();
|
|
std::vector<std::string> tkns;
|
|
boost::algorithm::find_all(tkns, text, "bond-0");
|
|
CHECK(tkns.size() == 6);
|
|
}
|
|
}
|
|
#ifdef RDK_BUILD_CAIRO_SUPPORT
|
|
SECTION("larger PNG") {
|
|
{
|
|
MolDraw2DCairo drawer(450, 400);
|
|
drawer.drawMolecule(*m1);
|
|
drawer.finishDrawing();
|
|
drawer.writeDrawingText("testGithub3226_1.png");
|
|
}
|
|
}
|
|
#endif
|
|
SECTION("smaller SVG") {
|
|
{
|
|
MolDraw2DSVG drawer(200, 150);
|
|
drawer.drawMolecule(*m1);
|
|
drawer.finishDrawing();
|
|
std::string text = drawer.getDrawingText();
|
|
std::ofstream outs("testGithub3226_2.svg");
|
|
outs << text;
|
|
outs.flush();
|
|
std::vector<std::string> tkns;
|
|
boost::algorithm::find_all(tkns, text, "bond-0");
|
|
CHECK(tkns.size() == 3);
|
|
}
|
|
}
|
|
#ifdef RDK_BUILD_CAIRO_SUPPORT
|
|
SECTION("smaller PNG") {
|
|
{
|
|
MolDraw2DCairo drawer(200, 150);
|
|
drawer.drawMolecule(*m1);
|
|
drawer.finishDrawing();
|
|
drawer.writeDrawingText("testGithub3226_2.png");
|
|
}
|
|
}
|
|
#endif
|
|
SECTION("middle SVG") {
|
|
{
|
|
MolDraw2DSVG drawer(250, 200);
|
|
drawer.drawMolecule(*m1);
|
|
drawer.finishDrawing();
|
|
std::string text = drawer.getDrawingText();
|
|
std::ofstream outs("testGithub3226_3.svg");
|
|
outs << text;
|
|
outs.flush();
|
|
std::vector<std::string> tkns;
|
|
boost::algorithm::find_all(tkns, text, "bond-0");
|
|
CHECK(tkns.size() == 3);
|
|
}
|
|
}
|
|
#ifdef RDK_BUILD_CAIRO_SUPPORT
|
|
SECTION("middle PNG") {
|
|
{
|
|
MolDraw2DCairo drawer(250, 200);
|
|
drawer.drawMolecule(*m1);
|
|
drawer.finishDrawing();
|
|
drawer.writeDrawingText("testGithub3226_3.png");
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
TEST_CASE("github #3258: ", "[drawing][bug]") {
|
|
auto m1 = "CCN"_smiles;
|
|
REQUIRE(m1);
|
|
SECTION("foundations") {
|
|
MolDraw2DSVG drawer(500, 200, 250, 200);
|
|
drawer.drawOptions().addAtomIndices = true;
|
|
drawer.drawOptions().addBondIndices = true;
|
|
RWMol dm1(*m1);
|
|
RWMol dm2(*m1);
|
|
MOL_PTR_VECT ms{&dm1, &dm2};
|
|
drawer.drawMolecules(ms);
|
|
drawer.finishDrawing();
|
|
std::string text = drawer.getDrawingText();
|
|
CHECK(text.find(">,</text>") == std::string::npos);
|
|
CHECK(!dm1.hasProp("_atomIndicesAdded"));
|
|
CHECK(!dm1.hasProp("_bondIndicesAdded"));
|
|
}
|
|
}
|
|
|
|
TEST_CASE(
|
|
"github #3392: prepareMolForDrawing() incorrectly adds chiral Hs if no "
|
|
"ring info is present",
|
|
"[bug]") {
|
|
SECTION("foundations") {
|
|
SmilesParserParams ps;
|
|
ps.sanitize = false;
|
|
ps.removeHs = false;
|
|
std::unique_ptr<RWMol> m1(SmilesToMol("C[C@H](F)Cl", ps));
|
|
REQUIRE(m1);
|
|
m1->updatePropertyCache();
|
|
CHECK(m1->getNumAtoms() == 4);
|
|
const bool kekulize = false;
|
|
const bool addChiralHs = true;
|
|
MolDraw2DUtils::prepareMolForDrawing(*m1, kekulize, addChiralHs);
|
|
CHECK(m1->getNumAtoms() == 4);
|
|
}
|
|
}
|