mirror of
https://github.com/rdkit/rdkit.git
synced 2026-06-03 21:44:30 +08:00
* add flipping of spiro rings as a way to solve clashes
* remove extra function
* add test file
* update coordgen parameters to allow for bond flipping
* fix failing tests
* Update Code/GraphMol/Depictor/EmbeddedFrag.h
Co-authored-by: Greg Landrum <greg.landrum@gmail.com>
* Update Code/GraphMol/Depictor/EmbeddedFrag.cpp
Co-authored-by: Greg Landrum <greg.landrum@gmail.com>
* Update Code/GraphMol/Depictor/EmbeddedFrag.cpp
Co-authored-by: Greg Landrum <greg.landrum@gmail.com>
* Update Code/GraphMol/Depictor/EmbeddedFrag.cpp
Co-authored-by: Greg Landrum <greg.landrum@gmail.com>
* [bot] Update molecular templates header (#9234)
Co-authored-by: github-actions[bot] <github-actions[bot]@noreply.github.com>
* Add some std::ranges support (#9218)
* initial ranges support for Atom/Bond iterators.
needs more testing
* support random access
test sort
more testing please
* compiles on windows
* fix size()
more testing
add some benchmarking
* disable benchmarking code by default
* do not allow modifying the graph through the iterators
---------
Co-authored-by: = <=>
* mention AI tools in the contrib guidelines (#9224)
* mention AI tools in the contrib guidelines
* response to review
---------
Co-authored-by: = <=>
* Add getSGroupDataLabels() to MolDraw2D_detail namespace (#9189)
Adds a new function MolDraw2D_detail::getSGroupDataLabels() that returns
the text and molecule-coordinate positions of DAT SGroup labels, using
the same placement logic as the drawing code. This allows external
renderers to display SGroup labels consistently with RDKit's placement.
Refactors DrawMol::extractSGroupData() to call getSGroupDataLabels()
internally, eliminating the duplicate FIELDDISP parsing and position
computation logic.
Closes #7829
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* MolDraw2D: configurable legend position and vertical side legends (Issue #9023) (#9183)
* Configurable legend position (Top/Left/Right/Bottom) and vertical text (GitHub #9023)
- Add LegendPosition enum and legendPosition, legendVerticalText to MolDrawOptions
- Support legend at Top, Left, Right, Bottom; vertical text for Left/Right
- Python: MolDrawOptions.legendPosition, .legendVerticalText; LegendPosition enum
- Python: MolToSVG() wrapper with legend/drawOptions; doc updates for MolToImage
- JSON: legendPosition (string), legendVerticalText (bool) in draw options
- C++ and Python tests; release note and Cartridge.md docs
* MolDraw2D: legend gutter for horizontal side legends; vertical side height fit
- Reserve horizontal gap between molecule and left/right horizontal legends
(scale mol to molWidth-gutter, align toward legend strip).
- Position horizontal side legend by measured text width from partition edge.
- Vertical side legends: iterative scale so n*max_h+(n-1)*gap fits panel.
- Catch: long vertical side legend section.
* Update legend-position tests and review-driven cleanup
Use enum/default wording for legendPosition docs, move the lightweight Python test to Wrap, add regex-based placement checks (including horizontal side and vertical stacking), and refactor extractLegend helpers per style guidance.
* Fix MolDraw2D legend edge cases
* MolDraw2D: review follow-up (legend tests, bounds, DRY Top/Bottom)
* Update no-FT legend test coords
* Address PR review: document constants, remove release-note text, and simplify extra-padding logic
* make sorting more consistent (#9239)
* Cleanup/get atoms and bonds (#9243)
* Fix bug in inversion term for UFF, add finite difference checker. (#9228)
* Fix copyright
* Address review comments
Removed finite diff from RDKit headers
Used explicit coordinates
* If templates match, skip ring number check (#9217)
* remove ring mathcing for templates
* remove extra code
* remove empty lines
* fix build error
* Tautomer insensitive hash v2, E/Z and stereocenter-preservation (#9128)
* Tautomer insensitive hash v2, E/Z and stereocenter-preservation
* Preserve E/Z stereochemistry and stereocenters in TautomerHashv2
Simplify extension logic to better protect stereocenters connected via
single bonds to aromatic systems. Preserve E/Z stereo on exocyclic
double bonds to distinguish geometric isomers (e.g., E/Z hydrazones).
* add helper function to remove duplicated code
* Fix ring info and bond aromaticity handling in MolHash
- Add fastFindRings check in TautomerHashv2 before ring queries
- Set isAromatic consistent with bond type (true for AROMATIC bonds)
- Fix inverted condition in RegioisomerHash
* more consistent hashes regardless of stereo annotation
* Ensure that StereoGroups don't have duplicate atoms or bonds (#9258)
* check for duplicate atoms/bonds in StereoGroups
* explicit handling of duplicate stereogroup atoms in CTAB and CXSMILES parsers
---------
Co-authored-by: = <=>
* Add Getter functions to MMFF property python interface (#9254)
* Support using iterators with MolSuppliers (#9230)
* iterators for random-access MolSuppliers
add optional caching to SDMolSupplier
* add support to SmilesMolSupplier too
There is a lot of duplicate code between the random-access suppliers that would be worth trying to remove
but at the moment it looks like it would require multiple inheritance, and I think we want to avoid that
* add input iterators for ForwardSDMolSupplier()
* throw when calling begin() on a used supplier
* switch to use the spaceship operator
* init() should reset the mol cache
* Make SDMolSupplier and SmilesMolSupplier safe for multi-threaded reads
* add benchmarking
* add TDTMolSupplier support
improved testing
add benchmarks for parallel iteration
optional TBB support
* better const handling, add reverse iterators
doesn't look like const_iterator is possible since getting data from the underlyng supplier object is non-const
* improve docs
more usings
add reverse iterator to TDTMolSupplier
* tests only try execution::par when it is there
* fix typo
* more testing/demo
* remove accidentally added files
* review changes
* add default ctors
* disable a false-positive compiler warning
it is stupid to have to do this
---------
Co-authored-by: = <=>
* Pandastools improvements (#9251)
* Added automatic parsing functionality
* Added documentation
* Slightly changed check for gzip extension
* Apply suggestions from code review
Added small changes for readability
Co-authored-by: Greg Landrum <greg.landrum@gmail.com>
---------
Co-authored-by: Greg Landrum <greg.landrum@gmail.com>
* Add optional default_val parameter to GetProp() (#9242)
* SHARED-12256: Add test and change function.
* SHARED-12256: Update to only wrapping changes.
* SHARED-12256: Parameterize tests.
* SHARED-12256: GetPropIfPresent changes.
* Revert "SHARED-12256: GetPropIfPresent changes."
This reverts commit f598f8c161.
* SHARED-12256: Make default the keyword in the boost wrappings.
* SHARED-12256: Overload function instead of using a sentinel.
* SHARED-12256: Extend GetProp changes.
* SHARED-12256: Add entry point for tests and fix tests.
* Extended fix for #9101 (#9255)
* fix extended boundary issue (3 mols)
* clang pass
* no change. retrigger CI for failed java test
there's a failing java test that seems to be failing by chance rather than by changes, as it depends on rng. this is just to retrigger the CI pipeline to confirm this
* no change. retrigger the CI (yet again)
* raw strings and removed garbage collector
* CIP labeller performance: Don't calculate auxiliary descriptors unnecessarily (#9171)
* CIP labeller: Don't calculate auxiliary descriptors unnecessarily
The first 3 rules (the constitutional rules) are pretty easy
to understand. After rule 3, we need to calculate auxiliary
stereo descriptors to break ties.
However, we _were actually_ calculating auxiliary stereodescriptors
for all centers! We should only need to calculate auxiliary
stereocenters for sites that are needed to break ties.
This cost time - it also caused errors if the auxiliary descriptors
needed a graph expansion, because bonds in the digraph might be
pointed in the wrong direction.
Example case PDB ID 4AXM
Before this commit, errored with "Could not calculate parity! Carrier mismatch"
after 14s. After this commit, completes successfully in 0.036s.
Labelled centers all match (for the centers that had labels in
the failure case).
Includes a test that I can imagine breaking with this optimization.
The reference labels are from before this change
* Ensure all "arms" of stereo bonds and atropisomer bonds are expanded
For tetrahedral centers, ranking using the constitutional rules
always expands as far as is needed (but no further). For SP2bond
and atropisomers, if the first side is not resolvable, the
second side is never visited.
If the constitutional rules don't resolve a side, we need to
label the auxiliary centers. It's important to label all
auxiliary centers that _will_ be visited, so we need to know
what centers will be visited.
This commit updates the label() call in SP2 and Atropisomer
bonds to always attempt to label both sides if using the
constitutional rule set.
The constitutional rules are cheap, and if they fail, we
always go on to the full rule set. It is not a savings to skip
the search on the second side if we're going to keep going
anyway!
Includes a test that reproduces Ricardo's example.
This has no measurable effect on performance relative to the
original solution
* If any parts of the center have been seen, label it.
I couldn't make an example hit this, but Ric is totally
theoretically right
* Greg's ranges suggestion #2
Co-authored-by: Greg Landrum <greg.landrum@gmail.com>
* any_of for container search
Co-authored-by: Greg Landrum <greg.landrum@gmail.com>
---------
Co-authored-by: Greg Landrum <greg.landrum@gmail.com>
* CIPLabeler performance: Store vector of bonds (#9250)
* CIPLabeler performance: Store vector of bonds
CIPLabelling refers to bonds by index over and over again. This
causes a measurable hit in performance in findConfigs() because
we iterate over a bitset of "allowed" bonds. For very large
molecules with many bonds, this can be a rate-limiting step!
This affects many PDB-sized structures.
2J3N goes from 0.7s to 0.25s with this change.
I had another example for which the findBondWithIdx() call was
taking 500ms of a 700ms call (after the performance update
in #9171 was implemented)
* yikes, XXL reserve
thanks, greg
Co-authored-by: Greg Landrum <greg.landrum@gmail.com>
---------
Co-authored-by: Greg Landrum <greg.landrum@gmail.com>
* Address PR #9204 review feedback
Implemented performance improvements suggested by @greglandrum:
1. Move cheap degree check to start of isSpiroCenter()
- Early bailout eliminates ~95% of candidates immediately
2. Replace std::set with boost::dynamic_bitset<>
- Faster set operations for ring membership tests
- More efficient intersection using bitwise AND
3. Remove expensive PRECONDITION in flipAboutSpiroCenter()
- Caller already validates spiro center, no need to check again
All tests pass (testDepictor: 7.85s).
* Use boost::dynamic_bitset in removeCollisionsBondAndSpiroFlip
Replaced std::set<unsigned int> with boost::dynamic_bitset<> for
spiro center caching in collision resolution:
- Changed spiroCenters from std::set to boost::dynamic_bitset
- Updated tryResolvingCollisionWithSpiroFlip() signature
- Replaced set.find() with bitset.test() for membership checks
- Replaced set.insert() with bitset.set() for marking spiro centers
Benefits:
- Faster membership tests (O(1) bit test vs O(log n) tree lookup)
- Better cache locality (contiguous bit array vs scattered nodes)
- Simpler code (no iterator comparisons)
All tests pass (testDepictor: 2.64s).
* remove unnecessary reformatting
* more unneeded formatting
* even more unecessary formatting
---------
Co-authored-by: Greg Landrum <greg.landrum@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@noreply.github.com>
Co-authored-by: Chris Von Bargen <christopher.vonbargen@schrodinger.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Brandon Novy <142041993+Brandon-Cole@users.noreply.github.com>
Co-authored-by: Ricardo Rodriguez <ricrogz@users.noreply.github.com>
Co-authored-by: Kevin Boyd <kboyd@nvidia.com>
Co-authored-by: Eloy Félix <eloyfelix@gmail.com>
Co-authored-by: Marco Ballarotto <marco.ballarotto@icr.ac.uk>
Co-authored-by: Emily Rhodes <70823163+emilyrrhodes@users.noreply.github.com>
Co-authored-by: Raul Sofia <67133355+RaulSofia@users.noreply.github.com>
Co-authored-by: Dan Nealschneider <dan.nealschneider@schrodinger.com>
2001 lines
74 KiB
C++
2001 lines
74 KiB
C++
//
|
|
// Copyright (C) 2004-2025 Greg Landrum and other RDKit contributors
|
|
//
|
|
// @@ 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 <RDGeneral/test.h>
|
|
#include <RDGeneral/Invariant.h>
|
|
#include <RDGeneral/RDLog.h>
|
|
#include <GraphMol/RDKitBase.h>
|
|
#include <string>
|
|
#include <GraphMol/FileParsers/MolWriters.h>
|
|
#include <GraphMol/FileParsers/FileParsers.h>
|
|
#include <GraphMol/FileParsers/MolSupplier.h>
|
|
#include <RDGeneral/FileParseException.h>
|
|
#include "RDDepictor.h"
|
|
#include "DepictUtils.h"
|
|
#include "Templates.h"
|
|
#include <GraphMol/SmilesParse/SmilesParse.h>
|
|
#include <GraphMol/Substruct/SubstructMatch.h>
|
|
#include <GraphMol/ChemTransforms/ChemTransforms.h>
|
|
#include <GraphMol/MolAlign/AlignMolecules.h>
|
|
#include <GraphMol/Conformer.h>
|
|
#include <GraphMol/MolTransforms/MolTransforms.h>
|
|
#include <Geometry/point.h>
|
|
#include <Geometry/Transform3D.h>
|
|
#include <RDGeneral/utils.h>
|
|
#include <cstdlib>
|
|
#include <cmath>
|
|
|
|
#include <boost/tokenizer.hpp>
|
|
typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
|
|
|
|
using namespace RDKit;
|
|
|
|
auto defaultRDKitBondLen = RDDepict::BOND_LEN;
|
|
|
|
void _compareCoords(const ROMol *mol1, unsigned int cid1, const ROMol *mol2,
|
|
unsigned int cid2, double tol = 0.01) {
|
|
unsigned int nat = mol1->getNumAtoms();
|
|
CHECK_INVARIANT(nat == mol2->getNumAtoms(), "");
|
|
|
|
const RDKit::Conformer &conf1 = mol1->getConformer(cid1);
|
|
const RDKit::Conformer &conf2 = mol2->getConformer(cid2);
|
|
|
|
for (unsigned int i = 0; i < nat; i++) {
|
|
RDGeom::Point3D pt1 = conf1.getAtomPos(i);
|
|
RDGeom::Point3D pt2 = conf2.getAtomPos(i);
|
|
pt2 -= pt1;
|
|
|
|
if ((fabs(pt2.x) >= tol) || (fabs(pt2.y) >= tol)) {
|
|
std::cerr << MolToMolBlock(*mol1, cid1) << std::endl;
|
|
std::cerr << MolToMolBlock(*mol2, cid2) << std::endl;
|
|
break;
|
|
}
|
|
CHECK_INVARIANT(fabs(pt2.x) < tol, "");
|
|
CHECK_INVARIANT(fabs(pt2.y) < tol, "");
|
|
}
|
|
}
|
|
|
|
void test1() {
|
|
// std::string smiString = "OCC(F)(F)C(F)(F)C(F)(F)C(F)F";
|
|
|
|
std::string smiString =
|
|
"CN([CH](Cc3ccc(OS(c2cccc1c2ccnc1)(=O)=O)cc3)C(=O)N5CCN(c4ccccc4)CC5)S(c7cccc6c7ccnc6)(=O)=O \
|
|
C[n](n1)ccc1NC(=O)C(/C#N)=C/c2[s]cc(c2)Br O=C2C1CC3CC(C1)CC2C3 \
|
|
c8cc9cc3c5c(c(=O)cc4n1nc6c2c(ccc(c12)c(cc3)c45)cc7c6cc(=O)cc7)c9cc8 \
|
|
c1cccc(c1)CCCCNC(=O)C(/C#N)=C/c2ccc(O)c(c2)O \
|
|
COc(cc1)ccc1C(=C2)C=C(NC2=C)c3ccc(OC)cc3O \
|
|
CC(OC1C(CCCC3)C3C(CCCC2)C2C1OC(C)=O)=O \
|
|
Cl.C[N+](C)(C)CCO O=C2C1CC3CC(C1)CC2C3 \
|
|
CN3CCC25[CH]4CCC(=O)C5(C)Oc1c(O)ccc(c12)C[CH]34 \
|
|
c1ccccc1\\C=C/C=C\\Cl.c1ccccc1C=C(Cl)C1SCCC1.Cl\\C=C1/SCCC1 Cl\\C=C/Br \
|
|
c1ccccc1\\C=C/C=C\\C=C/Cl c1ccccc1C=C(Cl)C1SCCC1 Cl\\C=C1/SCCC1 Cl\\C=C/Br \
|
|
CN2C3CC(OC(=O)C(CO)c1ccccc1)CC2CC3 \
|
|
N2C3CC(OC(=O)C(CO)c1ccccc1)CC2CC3 \
|
|
C2C3CC(OC(=O)C(CO)c1ccccc1)CC2CC3 \
|
|
ClC=C1SCCC1 C/C=C/C(C1CCCCCC1)=O c1ccccc1\\C=C/C=C\\C=C/Cl \
|
|
C[n](n1)ccc1NC(=O)C(/C#N)=C/c2[s]cc(c2)Br \
|
|
C1CC(C(Cl)(Br)F)CC1 \
|
|
C1(C2)CCC2C=C1 \
|
|
OC2C1(C)CCCCC1CCC2 \
|
|
CC12CCCC3OC1CCCC23 \
|
|
CC(OC1C(CCCC3)C3C(CCCC2)C2C1OC(C)=O)=O \
|
|
ON=C(CC1=CC=CC=C1)[CH](C#N)C2=CC=CC=C2 \
|
|
COc(cc1)ccc1C(=C2/C#N)\\C=C(NC2=C(C#N)C#N)\\c3ccc(OC)cc3O \
|
|
COc(cc1)ccc1C(=C2)C=C(NC2=C)c3ccc(OC)cc3O \
|
|
C1=CC=CC=C1CCCC2=CC(C=CC=C3)=C3C=C2 C/C=C/C(C1CCCCCC1)=O \
|
|
C/C=C/C(C1CCCCCC1)=O.c1ccccc1CC(Cl)=O \
|
|
[I-].CCC[N+](C)(CCC)CCC C1COCCN2CCOCCN(CCO1)CCOCCOCC2 C1CN2CCN1CC2 \
|
|
C(CCCCCCC)(=O)CCCCCC \
|
|
ClCCCCCCCCCCCCCCCCCCCCCCCCCCCC(=O)CCCCCCCCCCCCCCCCCCCCCCCCCCF \
|
|
C(CCCCCCC)(=O)CCCCCC \
|
|
C/C=C/C(C1CCCCCC1)=O C1CC(CC12)C=C2 c1ccccc1\\C=C(Cl)/C#N \
|
|
N#C\\C=C(Cl)/Cc1ccccc1 \
|
|
CN(C)c(cc1)ccc1\\C=C(/C#N)c(n2)c(C#N)c([n]3cccc3)[n]2c(c4)cccc4 \
|
|
CCOC(=O)CN1C(=O)/C=C(/C)c(c12)c(C)n[n]2C \
|
|
C/12=C\\C(=O)c3cc(OC(F)(F)F)ccc3N2C(=O)/C(CC(=O)OC)=C\\1C(=O)OCC \
|
|
C/12=C(\\NC(N2)=O)NC(=O)NC1=O F\\C=C/Cl F/C=C/Cl c1ccccc1\\C=C/C \
|
|
c1ccccc1\\C=C\\C=C\\C=C\\Cl \
|
|
c1ccccc1\\C=C/C=C\\C=C/Cl c1ccccc1\\C=C\\C=C(O)\\C=C(Br)\\Cl \
|
|
c1ccccc1\\C=C/C=C(O)\\C=C(Br)/Cl \
|
|
CC#CCC O=C=O C1=CC=CC=C1 C1CCC1 C1CC1(C#CC) C1CCCCCCC1 C1=CC=CC=C1(CCCCCCC) \
|
|
C1=CC=CC=C1(CC(CCC)CCC(C)(C)C) \
|
|
C1=CC=CC=C1CCCC2=CC(C=CC=C3)=C3C=C2 \
|
|
C1=CC=CC=C1(CC(CCC)CCC(CCC)(CCC)C) \
|
|
C1=CC(C=CC=C2)=C2C=C1 C1=CC(C=C2)=C2C=C1 \
|
|
C1=CC(CCC2)=C2C=C1 C1(CCC3)CCCC2C1C3CCC2 \
|
|
C12=CC=C3C(C4=C(C=CC=C5)C5=C3)C1C(C=C4)=CC=C2 \
|
|
C12CCCC3(CCCCC3)C1CCCC2 \
|
|
C1CCCC2(CC2)C1 C12C3C4C1C5C2C3C45 \
|
|
C2(C=C(C=C5)NC5=C4)=CC(C=C2)=CC1=CC=C(C=C3C=CC4=N3)N1";
|
|
|
|
std::string rdbase = getenv("RDBASE");
|
|
std::string ofile =
|
|
rdbase + "/Code/GraphMol/Depictor/test_data/test1.out.sdf";
|
|
SDWriter writer(ofile);
|
|
std::string ifile = rdbase + "/Code/GraphMol/Depictor/test_data/test1.sdf";
|
|
SDMolSupplier suppl(ifile);
|
|
boost::char_separator<char> spaceSep(" ");
|
|
tokenizer tokens(smiString, spaceSep);
|
|
for (tokenizer::iterator token = tokens.begin(); token != tokens.end();
|
|
++token) {
|
|
std::string smi = *token;
|
|
std::unique_ptr<RWMol> m{SmilesToMol(smi)};
|
|
TEST_ASSERT(m)
|
|
RDDepict::compute2DCoords(*m);
|
|
writer.write(*m);
|
|
std::unique_ptr<ROMol> ref{suppl.next()};
|
|
_compareCoords(m.get(), 0, ref.get(), 0);
|
|
}
|
|
}
|
|
|
|
void testCollisions() {
|
|
std::string smiString =
|
|
"CN([CH](Cc3ccc(OS(c2cccc1c2ccnc1)(=O)=O)cc3)C(=O)N5CCN(c4ccccc4)CC5)S(c7cccc6c7ccnc6)(=O)=O \
|
|
CC(C)C12CCC(C)(CC1)CC2 \
|
|
CC(C)C1CCC2(CC)CCCC1CCC2 \
|
|
CC(OC1C(CCCC3)C3C(CCCC2)C2C1OC(C)=O)=O \
|
|
OC(=O)C1=C(C=CC=C1)C2=C3C=CC(=O)C(=C3OC4=C2C=CC(=C4Br)O)Br \
|
|
CC(CC(=O)OCC(F)(F)C(F)(F)C(F)(F)C(F)F)CC(=O)OCC(F)(F)C(F)(F)C(F)(F)C(F)F \
|
|
CC(=O)Nc1ccccc1C(=O)C1CCCC1C1CCCCC1 \
|
|
Cc1ccc(C(c2ccc(C)o2)c2ccccc2[N+](=O)[O-])o1 \
|
|
CN2C3CC(OC(=O)C(CO)c1ccccc1)CC2CC3";
|
|
// this used to be a test, but it's currently failing catastrophically:
|
|
// CC(C)(C)O[Si](OCC(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)F)(OCC(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)(F)C(F)F)OC(C)(C)C
|
|
|
|
std::string rdbase = getenv("RDBASE");
|
|
std::string ofile =
|
|
rdbase + "/Code/GraphMol/Depictor/test_data/collisions.out.sdf";
|
|
SDWriter writer(ofile);
|
|
|
|
boost::char_separator<char> spaceSep(" ");
|
|
tokenizer tokens(smiString, spaceSep);
|
|
for (tokenizer::iterator token = tokens.begin(); token != tokens.end();
|
|
++token) {
|
|
std::string smi = *token;
|
|
RWMol *m = SmilesToMol(smi, 0, 1);
|
|
TEST_ASSERT(m);
|
|
unsigned int confId = RDDepict::compute2DCoords(*m);
|
|
// check that there are no collisions in the molecules
|
|
const Conformer &conf = m->getConformer(confId);
|
|
writer.write(*m);
|
|
writer.flush();
|
|
int natms = m->getNumAtoms();
|
|
for (int i = 0; i < natms; i++) {
|
|
RDGeom::Point3D loci = conf.getAtomPos(i);
|
|
for (int j = i + 1; j < natms; j++) {
|
|
RDGeom::Point3D locj = conf.getAtomPos(j);
|
|
locj -= loci;
|
|
CHECK_INVARIANT(locj.length() > 0.35, "");
|
|
}
|
|
}
|
|
delete m;
|
|
}
|
|
}
|
|
|
|
void testAddHs() {
|
|
// test for issue 193
|
|
std::string smi = "F[C@H](Cl)Br";
|
|
RWMol *m = SmilesToMol(smi, 0, 1);
|
|
MolOps::addHs(*m);
|
|
RDDepict::compute2DCoords(*m);
|
|
delete m;
|
|
}
|
|
|
|
void testIssue198() {
|
|
std::string smi = "Cl.C[N+](C)(C)CCO";
|
|
RWMol *m = SmilesToMol(smi, 0, 1);
|
|
unsigned int confId = RDDepict::compute2DCoords(*m);
|
|
RDKit::ROMol::AtomIterator ai;
|
|
const Conformer &conf = m->getConformer(confId);
|
|
for (ai = m->beginAtoms(); ai != m->endAtoms(); ai++) {
|
|
RDGeom::Point3D loc = conf.getAtomPos((*ai)->getIdx());
|
|
CHECK_INVARIANT(loc.x < 100.0, "");
|
|
CHECK_INVARIANT(loc.y < 100.0, "");
|
|
CHECK_INVARIANT(loc.z < 100.0, "");
|
|
}
|
|
delete m;
|
|
}
|
|
|
|
void test2() {
|
|
std::string rdbase = getenv("RDBASE");
|
|
std::string smifile =
|
|
rdbase + "/Code/GraphMol/Depictor/test_data/first_200.tpsa.csv";
|
|
SmilesMolSupplier smiSup(smifile, ",", 0, -1);
|
|
|
|
std::string ofile =
|
|
rdbase + "/Code/GraphMol/Depictor/test_data/first_200.out.sdf";
|
|
SDWriter writer(ofile);
|
|
ROMol *mol;
|
|
while (1) {
|
|
try {
|
|
mol = smiSup.next();
|
|
std::string mname;
|
|
// wmol = static_cast<RWMol *>(mol);
|
|
RDDepict::compute2DCoords(*mol);
|
|
writer.write(*mol);
|
|
delete mol;
|
|
} catch (FileParseException &) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void test3() {
|
|
std::string rdbase = getenv("RDBASE");
|
|
std::string smifile =
|
|
rdbase + "/Code/GraphMol/Depictor/test_data/cis_trans_cases.csv";
|
|
SmilesMolSupplier smiSup(smifile, ",", 0, 1);
|
|
|
|
std::string ofile =
|
|
rdbase + "/Code/GraphMol/Depictor/test_data/cis_trans_cpp.out.sdf";
|
|
SDWriter writer(ofile);
|
|
ROMol *mol;
|
|
while (1) {
|
|
try {
|
|
mol = smiSup.next();
|
|
std::string mname;
|
|
// wmol = static_cast<RWMol *>(mol);
|
|
RDDepict::compute2DCoords(*mol);
|
|
writer.write(*mol);
|
|
delete mol;
|
|
} catch (FileParseException &) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void test4() {
|
|
// test prespecified coordinates for various smiles
|
|
RDGeom::INT_POINT2D_MAP crdMap;
|
|
crdMap[0] = RDGeom::Point2D(3.52, 1.30);
|
|
crdMap[1] = RDGeom::Point2D(2.77, 0.0);
|
|
crdMap[2] = RDGeom::Point2D(1.27, 0.0);
|
|
crdMap[3] = RDGeom::Point2D(0.39, 1.21);
|
|
crdMap[4] = RDGeom::Point2D(-1.03, 0.75);
|
|
crdMap[5] = RDGeom::Point2D(-1.03, -0.75);
|
|
crdMap[6] = RDGeom::Point2D(0.39, -1.21);
|
|
|
|
// self check
|
|
std::string smi = "Cl\\C=C1/SCCC1";
|
|
RWMol *m1 = SmilesToMol(smi, 0, 1);
|
|
unsigned int cid1 = RDDepict::compute2DCoords(*m1, &crdMap, false);
|
|
RWMol *mref = SmilesToMol(smi, 0, 1);
|
|
unsigned int cid2 = RDDepict::compute2DCoords(*mref);
|
|
MolToMolFile(*mref, "junk.mol");
|
|
//_compareCoords(m1, mref);
|
|
|
|
delete m1;
|
|
|
|
// now lets remove some of the coordinates
|
|
crdMap.erase(crdMap.find(3));
|
|
crdMap.erase(crdMap.find(4));
|
|
m1 = SmilesToMol(smi, 0, 1);
|
|
cid1 = RDDepict::compute2DCoords(*m1, &crdMap, false);
|
|
// MolToMolFile(m1, "junk.mol");
|
|
//_compareCoords(m1, mref);
|
|
delete m1;
|
|
|
|
// little bit more complicated
|
|
smi = "Cl\\C=C1/SCCC1(CC1CC1)";
|
|
m1 = SmilesToMol(smi, 0, 1);
|
|
cid1 = RDDepict::compute2DCoords(*m1, &crdMap, false);
|
|
// MolToMolFile(m1, "junk1.mol");
|
|
delete mref;
|
|
mref = SmilesToMol(smi, 0, 1);
|
|
RDDepict::compute2DCoords(*mref, nullptr, false);
|
|
_compareCoords(m1, cid1, mref, cid2);
|
|
delete m1;
|
|
|
|
// little more complicate we will specify coordinates from half of both the
|
|
// rings
|
|
crdMap[7] = RDGeom::Point2D(0.85, -2.64);
|
|
crdMap[8] = RDGeom::Point2D(-0.15, -3.75);
|
|
crdMap[9] = RDGeom::Point2D(-0.46, -5.22);
|
|
m1 = SmilesToMol(smi, 0, 1);
|
|
cid1 = RDDepict::compute2DCoords(*m1, &crdMap, false);
|
|
// MolToMolFile(m1, "junk1.mol");
|
|
// MolToMolFile(mref, "junk2.mol");
|
|
_compareCoords(m1, cid1, mref, cid2);
|
|
delete m1;
|
|
|
|
// one final test for a case we know is a pain
|
|
smi = "C1CCCC2(Cl)(CCCCCC12)";
|
|
crdMap.clear();
|
|
crdMap[0] = RDGeom::Point2D(-0.83, 3.12);
|
|
crdMap[1] = RDGeom::Point2D(0.19, 4.22);
|
|
crdMap[2] = RDGeom::Point2D(1.66, 3.88);
|
|
crdMap[3] = RDGeom::Point2D(2.10, 2.45);
|
|
crdMap[4] = RDGeom::Point2D(1.08, 1.35);
|
|
crdMap[5] = RDGeom::Point2D(2.56, 1.12);
|
|
crdMap[6] = RDGeom::Point2D(1.73, 0.00);
|
|
crdMap[7] = RDGeom::Point2D(1.08, -1.35);
|
|
crdMap[8] = RDGeom::Point2D(-0.38, -1.69);
|
|
crdMap[9] = RDGeom::Point2D(-1.56, -0.75);
|
|
crdMap[10] = RDGeom::Point2D(-1.56, 0.75);
|
|
crdMap[11] = RDGeom::Point2D(-0.38, 1.69);
|
|
|
|
delete mref;
|
|
mref = SmilesToMol(smi, 0, 1);
|
|
cid2 = RDDepict::compute2DCoords(*mref, nullptr, false);
|
|
crdMap.erase(crdMap.find(5));
|
|
// MolToMolFile(mref, "junk1.mol");
|
|
// std::cerr << MolToXYZBlock(*mref) << std::endl;
|
|
m1 = SmilesToMol(smi, 0, 1);
|
|
cid1 = RDDepict::compute2DCoords(*m1, &crdMap, false);
|
|
_compareCoords(m1, cid1, mref, cid2);
|
|
delete m1;
|
|
delete mref;
|
|
}
|
|
|
|
void tempTest() {
|
|
int i;
|
|
RDGeom::Point3D pt1, pt2, pt3;
|
|
double cosT, sinT;
|
|
RDGeom::Transform3D trans;
|
|
RDGeom::Point3D rotnAxis;
|
|
double dt;
|
|
for (i = 0; i < 100; i++) {
|
|
pt1.x = (double)(rand() % 1000);
|
|
pt1.y = (double)(rand() % 1000);
|
|
pt1.z = (double)(rand() % 1000);
|
|
pt1.normalize();
|
|
pt2.x = (double)(rand() % 1000);
|
|
pt2.y = (double)(rand() % 1000);
|
|
pt2.z = (double)(rand() % 1000);
|
|
pt2.normalize();
|
|
|
|
cosT = -pt1.dotProduct(pt2);
|
|
sinT = sqrt(1.0 - cosT * cosT);
|
|
rotnAxis = pt1.crossProduct(pt2);
|
|
rotnAxis.normalize();
|
|
trans.setToIdentity();
|
|
trans.SetRotation(cosT, sinT, rotnAxis);
|
|
pt3 = pt2;
|
|
trans.TransformPoint(pt3);
|
|
dt = pt1.dotProduct(pt3);
|
|
if (fabs(dt + 1.0) > 1.0e-3) {
|
|
BOOST_LOG(rdInfoLog) << i << " (" << pt1 << ") (" << pt2 << ") (" << pt3
|
|
<< ") (" << rotnAxis << ") " << dt << "\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
void testIssue248() {
|
|
std::string smiString =
|
|
"OCC(=O)C1(O)[CH](O)C[CH]2[CH]3CCC4=CC(=O)C=CC4(C)C3(F)[CH](O)CC21C \
|
|
CC(C)[CH](OC(C)=O)c1nc2ccccc2c(=O)n1[CH]1CC2(OC1=O)c1c(cccc1)N1C(=O)C(C)(C)N(O)[CH]12 \
|
|
CC(CC(=O)OCC(F)(F)C(F)(F)C(F)(F)C(F)F)CC(=O)OCC(F)(F)C(F)(F)C(F)(F)C(F)F \
|
|
CC(O[CH]1C(=O)C2(C)[CH](O)C[CH]3OCC3(OC(C)=O)[CH]2[CH](OC(=O)c2ccccc2)C2(O)C[CH](OC([CH](O)[CH](NC(=O)c3ccccc3)c3ccccc3)=O)C(C)=C1C2(C)C)=O \
|
|
COc1c2O[CH]3[CH](O)C=C[CH]4C33CCN(C)[CH]4Cc(c32)cc1 \
|
|
CN1CCC23[CH]4Oc5c(O)ccc(c25)C[CH]1[CH]3C=C[CH]4O \
|
|
CN1C2CCC1C[CH](OC(=O)C(CO)c1ccccc1)C2 \
|
|
COC([CH]1C2CCC(C[CH]1OC(c1ccccc1)=O)N2C)=O \
|
|
OCC(=O)C1(O)[CH](O)C[CH]2[CH]3CCC4=CC(=O)C=CC4(C)C3(F)[CH](O)CC21C";
|
|
// COC12C3Oc4c(O)ccc5c4C33CCN(CC4CC4)[CH](C5)C3(C[CH]1C(O)(C)C(C)(C)C)CC2";
|
|
|
|
boost::char_separator<char> spaceSep(" ");
|
|
tokenizer tokens(smiString, spaceSep);
|
|
for (tokenizer::iterator token = tokens.begin(); token != tokens.end();
|
|
++token) {
|
|
std::string smi = *token;
|
|
RWMol *m = SmilesToMol(smi, 0, 1);
|
|
unsigned int confId = RDDepict::compute2DCoords(*m, nullptr, false, true, 3, 100);
|
|
// check that there are no collisions in the molecules
|
|
int natms = m->getNumAtoms();
|
|
int i, j;
|
|
for (i = 0; i < natms; i++) {
|
|
const Conformer &conf = m->getConformer(confId);
|
|
RDGeom::Point3D loci = conf.getAtomPos(i);
|
|
for (j = i + 1; j < natms; j++) {
|
|
RDGeom::Point3D locj = conf.getAtomPos(j);
|
|
locj -= loci;
|
|
if (locj.length() <= 0.30) {
|
|
std::cout << "mismatch: " << i << " " << j << " " << locj.length()
|
|
<< std::endl;
|
|
std::cout << "\t" << smi << std::endl;
|
|
std::cout << MolToMolBlock(*m, true, confId) << std::endl;
|
|
}
|
|
CHECK_INVARIANT(locj.length() > 0.30, "");
|
|
}
|
|
}
|
|
delete m;
|
|
}
|
|
}
|
|
|
|
void testQueries() {
|
|
std::string smaString = "C[C,N] c1cc[c,n]cc1C";
|
|
|
|
boost::char_separator<char> spaceSep(" ");
|
|
tokenizer tokens(smaString, spaceSep);
|
|
for (tokenizer::iterator token = tokens.begin(); token != tokens.end();
|
|
++token) {
|
|
std::string sma = *token;
|
|
RWMol *m = SmartsToMol(sma);
|
|
unsigned int confId = RDDepict::compute2DCoords(*m);
|
|
// check that there are no collisions in the molecules
|
|
int natms = m->getNumAtoms();
|
|
int i, j;
|
|
for (i = 0; i < natms; i++) {
|
|
const Conformer &conf = m->getConformer(confId);
|
|
RDGeom::Point3D loci = conf.getAtomPos(i);
|
|
for (j = i + 1; j < natms; j++) {
|
|
RDGeom::Point3D locj = conf.getAtomPos(j);
|
|
locj -= loci;
|
|
if (locj.length() <= 0.30) {
|
|
std::cout << "mismatch: " << i << " " << j << " " << locj.length()
|
|
<< std::endl;
|
|
std::cout << "\t" << sma << std::endl;
|
|
std::cout << MolToMolBlock(*m, true, confId) << std::endl;
|
|
}
|
|
CHECK_INVARIANT(locj.length() > 0.30, "");
|
|
}
|
|
}
|
|
delete m;
|
|
}
|
|
}
|
|
|
|
void testRemoveHsCrash() {
|
|
std::string rdbase = getenv("RDBASE");
|
|
std::string molfile =
|
|
rdbase + "/Code/GraphMol/Depictor/test_data/hs_crash.mol";
|
|
RWMol *m = MolFileToMol(molfile, true, false);
|
|
TEST_ASSERT(m);
|
|
ROMol *newM = MolOps::removeHs(*static_cast<ROMol *>(m));
|
|
delete m;
|
|
RDDepict::compute2DCoords(*newM);
|
|
delete newM;
|
|
}
|
|
|
|
void testIssue2091304() {
|
|
// the problem here was a crash, so just finishing is success.
|
|
RDGeom::INT_POINT2D_MAP crdMap;
|
|
crdMap[0] = RDGeom::Point2D(0., 1.50);
|
|
|
|
std::string smi = "COC";
|
|
RWMol *m1 = SmilesToMol(smi);
|
|
RDDepict::compute2DCoords(*m1, &crdMap, false);
|
|
delete m1;
|
|
}
|
|
|
|
void testIssue2303566() {
|
|
RDGeom::INT_POINT2D_MAP crdMap;
|
|
crdMap[0] = RDGeom::Point2D(0.0781827, -0.112109);
|
|
crdMap[1] = RDGeom::Point2D(1.13205, -0.415657);
|
|
crdMap[2] = RDGeom::Point2D(0.676323, -1.51974);
|
|
crdMap[3] = RDGeom::Point2D(0.735363, -2.62024);
|
|
crdMap[4] = RDGeom::Point2D(0.974216, -1.5726);
|
|
crdMap[5] = RDGeom::Point2D(1.02041, -1.56945);
|
|
std::string mb =
|
|
"\n\
|
|
RDKit 2D\n\
|
|
\n\
|
|
6 7 0 0 0 0 0 0 0 0999 V2000\n\
|
|
0.0782 -0.1121 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n\
|
|
1.1321 -0.4157 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n\
|
|
0.6763 -1.5197 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n\
|
|
0.7354 -2.6202 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n\
|
|
1.0098 -1.5757 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0\n\
|
|
1.0218 -1.5749 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n\
|
|
1 2 1 0\n\
|
|
1 3 1 0\n\
|
|
3 2 1 0\n\
|
|
3 4 1 0\n\
|
|
5 6 2 0\n\
|
|
2 4 1 0\n\
|
|
1 4 1 0\n\
|
|
M END\n";
|
|
|
|
RWMol *m1 = MolBlockToMol(mb);
|
|
// in the original bug, this led to a crash, so just having it complete
|
|
// means the test passed.
|
|
unsigned int cid1 = RDDepict::compute2DCoords(*m1, &crdMap, false);
|
|
(void)cid1;
|
|
// TEST_ASSERT(cid1>=0);
|
|
delete m1;
|
|
}
|
|
|
|
void testIssue2821647() {
|
|
{
|
|
std::string smi = "CCCCC";
|
|
RWMol *m1 = SmilesToMol(smi);
|
|
unsigned int cid1 = RDDepict::compute2DCoords(*m1, nullptr, true);
|
|
double xx = 0, yy = 0;
|
|
for (unsigned int i = 0; i < m1->getNumAtoms(); i++) {
|
|
const Conformer &conf = m1->getConformer(cid1);
|
|
RDGeom::Point3D loci = conf.getAtomPos(i);
|
|
xx += loci.x * loci.x;
|
|
yy += loci.y * loci.y;
|
|
}
|
|
TEST_ASSERT(xx > yy);
|
|
delete m1;
|
|
}
|
|
{
|
|
std::string smi = "c1ccccc1CCCCCC1CC1";
|
|
RWMol *m1 = SmilesToMol(smi);
|
|
unsigned int cid1 = RDDepict::compute2DCoords(*m1, nullptr, true);
|
|
double xx = 0, yy = 0;
|
|
for (unsigned int i = 0; i < m1->getNumAtoms(); i++) {
|
|
const Conformer &conf = m1->getConformer(cid1);
|
|
RDGeom::Point3D loci = conf.getAtomPos(i);
|
|
xx += loci.x * loci.x;
|
|
yy += loci.y * loci.y;
|
|
}
|
|
TEST_ASSERT(xx > yy);
|
|
delete m1;
|
|
}
|
|
{
|
|
std::string smi = "c1ccc2c(c1)oc1c3ccccc3oc21";
|
|
RWMol *m1 = SmilesToMol(smi);
|
|
unsigned int cid1 = RDDepict::compute2DCoords(*m1, nullptr, true);
|
|
double xx = 0, yy = 0;
|
|
for (unsigned int i = 0; i < m1->getNumAtoms(); i++) {
|
|
const Conformer &conf = m1->getConformer(cid1);
|
|
RDGeom::Point3D loci = conf.getAtomPos(i);
|
|
xx += loci.x * loci.x;
|
|
yy += loci.y * loci.y;
|
|
}
|
|
TEST_ASSERT(xx > yy);
|
|
delete m1;
|
|
}
|
|
{
|
|
std::string smi = "[H]n1c2ccccc2c2n([H])c3ccccc3c12";
|
|
RWMol *m1 = SmilesToMol(smi);
|
|
unsigned int cid1 = RDDepict::compute2DCoords(*m1, nullptr, true);
|
|
double xx = 0, yy = 0;
|
|
for (unsigned int i = 0; i < m1->getNumAtoms(); i++) {
|
|
const Conformer &conf = m1->getConformer(cid1);
|
|
RDGeom::Point3D loci = conf.getAtomPos(i);
|
|
xx += loci.x * loci.x;
|
|
yy += loci.y * loci.y;
|
|
}
|
|
TEST_ASSERT(xx > yy);
|
|
delete m1;
|
|
}
|
|
}
|
|
|
|
void testIssue2948402() {
|
|
{
|
|
std::string smi = "C1C2CC3=CC=CC(C2)CC(O3)C1";
|
|
RWMol *m1 = SmilesToMol(smi);
|
|
unsigned int cid1 = RDDepict::compute2DCoords(*m1, nullptr, true);
|
|
(void)cid1;
|
|
// TEST_ASSERT(cid1>=0);
|
|
delete m1;
|
|
}
|
|
}
|
|
|
|
void testIssue2995724() {
|
|
{
|
|
// the original problem from Thomas Heller:
|
|
std::string smi = "OC(=O)[C@@H]1CCCN1";
|
|
RWMol *m1 = SmilesToMol(smi);
|
|
unsigned int cid1 = RDDepict::compute2DCoords(*m1, nullptr, true);
|
|
|
|
const Conformer &conf = m1->getConformer(cid1);
|
|
for (unsigned int i = 0; i < m1->getNumAtoms(); i++) {
|
|
RDGeom::Point3D loci = conf.getAtomPos(i);
|
|
// we're testing for NaNs here:
|
|
TEST_ASSERT(loci.x > -5.0);
|
|
TEST_ASSERT(loci.x < 5.0);
|
|
TEST_ASSERT(loci.y > -5.0);
|
|
TEST_ASSERT(loci.y < 5.0);
|
|
}
|
|
delete m1;
|
|
}
|
|
{
|
|
// additional test cases from Kirk DeLisle:
|
|
std::string smis[] = {"CCC(N1CCN(CC1)C(CC)O)O.Cl[Pt](Cl)(Cl)(Cl)(Cl)Cl",
|
|
"CN(C)S(=O)(=O)N1CCN(CC1)S(=O)(=O)N(C)C",
|
|
"Cc1ccc(cc1C)Nc2nc(nc(n2)N)CN3CCN(CC3)C",
|
|
"CC1(OC(=C(C(=O)O1)C2=NCCC2)O)C"};
|
|
for (const auto &smi : smis) {
|
|
RWMol *m1 = SmilesToMol(smi);
|
|
unsigned int cid1 = RDDepict::compute2DCoords(*m1, nullptr, true);
|
|
|
|
const Conformer &conf = m1->getConformer(cid1);
|
|
for (unsigned int i = 0; i < m1->getNumAtoms(); i++) {
|
|
RDGeom::Point3D loci = conf.getAtomPos(i);
|
|
TEST_ASSERT(loci.x > -7.0);
|
|
TEST_ASSERT(loci.x < 7.0);
|
|
TEST_ASSERT(loci.y > -6.0);
|
|
TEST_ASSERT(loci.y < 6.0);
|
|
}
|
|
delete m1;
|
|
}
|
|
}
|
|
}
|
|
|
|
void testBondLengthChange() {
|
|
{
|
|
std::string smi = "CC";
|
|
RWMol *m1 = SmilesToMol(smi);
|
|
unsigned int cid1 = RDDepict::compute2DCoords(*m1, nullptr, true);
|
|
|
|
const Conformer &conf = m1->getConformer(cid1);
|
|
TEST_ASSERT(feq(conf.getAtomPos(0).x, -0.75));
|
|
TEST_ASSERT(feq(conf.getAtomPos(1).x, 0.75));
|
|
|
|
delete m1;
|
|
}
|
|
{
|
|
std::string smi = "CC";
|
|
RWMol *m1 = SmilesToMol(smi);
|
|
RDDepict::BOND_LEN = 1.0;
|
|
unsigned int cid1 = RDDepict::compute2DCoords(*m1, nullptr, true);
|
|
|
|
const Conformer &conf = m1->getConformer(cid1);
|
|
TEST_ASSERT(feq(conf.getAtomPos(0).x, -0.5));
|
|
TEST_ASSERT(feq(conf.getAtomPos(1).x, 0.5));
|
|
|
|
delete m1;
|
|
}
|
|
}
|
|
|
|
void testIssue3122141() {
|
|
{
|
|
std::string smi = "ClC1=C(Cl)C2(Cl)C3C(Cl)C=CC3C1(Cl)C2(Cl)Cl";
|
|
RWMol *m1 = SmilesToMol(smi);
|
|
RDGeom::INT_POINT2D_MAP crdMap;
|
|
crdMap[1] = RDGeom::Point2D(1.0, 2.0);
|
|
unsigned int cid1 = RDDepict::compute2DCoords(*m1, &crdMap, false);
|
|
(void)cid1;
|
|
// TEST_ASSERT(cid1>=0);
|
|
delete m1;
|
|
}
|
|
}
|
|
|
|
void testIssue3135833() {
|
|
{
|
|
std::string smi =
|
|
"N#CC(/C=[N+](/c1cccnc1)c1c2cc(C(=O)c3ncsc3-c3cccnc3)ccc2ccc1)=C(/"
|
|
"[NH3+])[S-]";
|
|
RWMol *m1 = SmilesToMol(smi);
|
|
TEST_ASSERT(m1);
|
|
|
|
RDGeom::INT_POINT2D_MAP crdMap;
|
|
crdMap[32] = RDGeom::Point2D(-2.8518, 1.0270);
|
|
crdMap[33] = RDGeom::Point2D(-2.7999, -0.4721);
|
|
crdMap[4] = RDGeom::Point2D(-1.4239, -2.6758);
|
|
crdMap[11] = RDGeom::Point2D(-1.4757, -1.1767);
|
|
crdMap[12] = RDGeom::Point2D(-0.2034, -0.3823);
|
|
crdMap[13] = RDGeom::Point2D(1.1208, -1.0869);
|
|
crdMap[14] = RDGeom::Point2D(2.3931, -0.2924);
|
|
crdMap[15] = RDGeom::Point2D(3.7173, -0.9971);
|
|
crdMap[28] = RDGeom::Point2D(2.3412, 1.2067);
|
|
crdMap[29] = RDGeom::Point2D(1.0170, 1.9113);
|
|
crdMap[30] = RDGeom::Point2D(-0.2553, 1.1168);
|
|
crdMap[31] = RDGeom::Point2D(-1.5795, 1.8215);
|
|
|
|
unsigned int cid1 = RDDepict::compute2DCoords(*m1, &crdMap, false);
|
|
(void)cid1;
|
|
// TEST_ASSERT(cid1>=0);
|
|
delete m1;
|
|
}
|
|
}
|
|
|
|
void testIssue3487469() {
|
|
{
|
|
std::string smi = "C*C";
|
|
RWMol *m1 = SmilesToMol(smi);
|
|
TEST_ASSERT(m1);
|
|
TEST_ASSERT(m1->getAtomWithIdx(1)->getHybridization() == Atom::UNSPECIFIED);
|
|
unsigned int cid1 = RDDepict::compute2DCoords(*m1, nullptr, true);
|
|
const Conformer &conf = m1->getConformer(cid1);
|
|
RDGeom::Point3D p0 = conf.getAtomPos(0);
|
|
RDGeom::Point3D p1 = conf.getAtomPos(1);
|
|
RDGeom::Point3D p2 = conf.getAtomPos(2);
|
|
|
|
RDGeom::Point3D v1 = p0 - p1, v2 = p2 - p1;
|
|
v1.normalize();
|
|
v2.normalize();
|
|
TEST_ASSERT(feq(v1.dotProduct(v2), -0.5, .01))
|
|
delete m1;
|
|
}
|
|
}
|
|
|
|
void testGitHubIssue8() {
|
|
{
|
|
std::string smi = "[I-].C[n+]1c(\\C=C\\2/C=CC=CN2CC=C)sc3ccccc13";
|
|
RWMol *m1 = SmilesToMol(smi);
|
|
TEST_ASSERT(m1);
|
|
RWMol *p = SmilesToMol("[I-]");
|
|
TEST_ASSERT(p);
|
|
ROMol *m2 = deleteSubstructs(*m1, *p);
|
|
TEST_ASSERT(m2);
|
|
TEST_ASSERT(m2->getNumAtoms() == m1->getNumAtoms() - 1);
|
|
unsigned int cid1 = RDDepict::compute2DCoords(*m2);
|
|
TEST_ASSERT(cid1 == 0);
|
|
delete m1;
|
|
delete m2;
|
|
delete p;
|
|
}
|
|
}
|
|
|
|
void testGitHubIssue78() {
|
|
{ // the basic test: the smallest reproducible:
|
|
std::string smi = "C3CCCC1C3C(O2)C2CC1";
|
|
RWMol *m1 = SmilesToMol(smi);
|
|
TEST_ASSERT(m1);
|
|
unsigned int cid1 = RDDepict::compute2DCoords(*m1);
|
|
const Conformer &conf = m1->getConformer(cid1);
|
|
RDGeom::Point3D p5 = conf.getAtomPos(5);
|
|
RDGeom::Point3D p6 = conf.getAtomPos(6);
|
|
RDGeom::Point3D p7 = conf.getAtomPos(7);
|
|
RDGeom::Point3D p8 = conf.getAtomPos(8);
|
|
RDGeom::Point3D p9 = conf.getAtomPos(9);
|
|
|
|
RDGeom::Point3D p87 = p8 - p7;
|
|
RDGeom::Point3D p86 = p8 - p6;
|
|
RDGeom::Point3D p89 = p8 - p9;
|
|
TEST_ASSERT(p87.dotProduct(p86) * p87.dotProduct(p89) < 0);
|
|
|
|
RDGeom::Point3D p67 = p6 - p7;
|
|
RDGeom::Point3D p68 = p6 - p8;
|
|
RDGeom::Point3D p65 = p6 - p5;
|
|
TEST_ASSERT(p67.dotProduct(p68) * p67.dotProduct(p65) < 0);
|
|
|
|
delete m1;
|
|
}
|
|
{ // a collection of previous failures
|
|
std::string smis[4] = {"C1=CC=C2C(=C1)C3=CC=CC=C3C4=C2C(C(C5C4O5)O)O",
|
|
"CC1=C2C=C(C=CC2=NC3=C1C4=C(O4)C5=CC=CC=C53)CO",
|
|
"CC1=C2C=CC3=C(C2=CC4=CC=CC=C14)C5C(O5)C(C3O)O",
|
|
"C1=CC=C2C(=C1)C=C3C=CC4=C5C3=C2C6C(C5=CC=C4)O6"};
|
|
RWMol *p = SmartsToMol("[#6]~[#6]~1-[#8]-[#6]~1~[#6]");
|
|
TEST_ASSERT(p);
|
|
for (const auto &smi : smis) {
|
|
RWMol *m = SmilesToMol(smi);
|
|
TEST_ASSERT(m);
|
|
MatchVectType mv;
|
|
TEST_ASSERT(SubstructMatch(*m, *p, mv));
|
|
TEST_ASSERT(mv.size() == 5);
|
|
|
|
unsigned int cid1 = RDDepict::compute2DCoords(*m);
|
|
const Conformer &conf = m->getConformer(cid1);
|
|
RDGeom::Point3D v10 =
|
|
conf.getAtomPos(mv[1].second) - conf.getAtomPos(mv[0].second);
|
|
RDGeom::Point3D v12 =
|
|
conf.getAtomPos(mv[1].second) - conf.getAtomPos(mv[2].second);
|
|
RDGeom::Point3D v13 =
|
|
conf.getAtomPos(mv[1].second) - conf.getAtomPos(mv[3].second);
|
|
TEST_ASSERT(v12.dotProduct(v10) * v12.dotProduct(v13) < 0);
|
|
|
|
RDGeom::Point3D v31 =
|
|
conf.getAtomPos(mv[3].second) - conf.getAtomPos(mv[1].second);
|
|
RDGeom::Point3D v32 =
|
|
conf.getAtomPos(mv[3].second) - conf.getAtomPos(mv[2].second);
|
|
RDGeom::Point3D v34 =
|
|
conf.getAtomPos(mv[3].second) - conf.getAtomPos(mv[4].second);
|
|
TEST_ASSERT(v32.dotProduct(v32) * v32.dotProduct(v34) < 0);
|
|
|
|
delete m;
|
|
}
|
|
delete p;
|
|
}
|
|
}
|
|
|
|
void testGitHubIssue910() {
|
|
{
|
|
// this is a ChEMBL molecule
|
|
std::string smiles =
|
|
"CSCC[C@H](NC(=O)[C@@H](CCC(N)=O)NC(=O)[C@@H](N)Cc1c[nH]c2ccccc12)C(=O)"
|
|
"NCC(=O)N[C@@H](Cc1c[nH]cn1)C(=O)N[C@@H](CO)C(=O)O";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
|
|
// add chiral Hs, they were part of the problem
|
|
std::vector<unsigned int> chiralAts;
|
|
for (RWMol::AtomIterator atIt = m->beginAtoms(); atIt != m->endAtoms();
|
|
++atIt) {
|
|
if ((*atIt)->getChiralTag() == Atom::CHI_TETRAHEDRAL_CCW ||
|
|
(*atIt)->getChiralTag() == Atom::CHI_TETRAHEDRAL_CW) {
|
|
chiralAts.push_back((*atIt)->getIdx());
|
|
}
|
|
}
|
|
MolOps::addHs(*m, false, false, &chiralAts);
|
|
RDDepict::compute2DCoords(*m, nullptr, true);
|
|
// now look for close contacts.
|
|
const Conformer &conf = m->getConformer();
|
|
for (unsigned int i = 0; i < conf.getNumAtoms(); ++i) {
|
|
for (unsigned int j = i + 1; j < conf.getNumAtoms(); ++j) {
|
|
double l = (conf.getAtomPos(i) - conf.getAtomPos(j)).length();
|
|
TEST_ASSERT(l > 0.5);
|
|
}
|
|
}
|
|
|
|
delete m;
|
|
}
|
|
}
|
|
|
|
void testGitHubIssue1073() {
|
|
// computeInitialCoords() should call the SSSR code before it calls
|
|
// assignStereochemistry()
|
|
{
|
|
std::string smarts = "[a]12[a][a][a][a][a]1[a][a][a]2";
|
|
RWMol *m = SmartsToMol(smarts);
|
|
TEST_ASSERT(m);
|
|
|
|
// compute2DCoords does ring finding internally, so there's no error
|
|
RDDepict::compute2DCoords(*m);
|
|
|
|
// but the molecule itself is not modified
|
|
RingInfo *ri = m->getRingInfo();
|
|
TEST_ASSERT(!ri->isInitialized());
|
|
|
|
delete m;
|
|
}
|
|
}
|
|
|
|
void testConstrainedCoords() {
|
|
std::string rdbase = getenv("RDBASE");
|
|
std::string ofile =
|
|
rdbase + "/Code/GraphMol/Depictor/test_data/constrainedCoords.out.sdf";
|
|
SDWriter writer(ofile);
|
|
|
|
std::string templ_smiles = "c1nccc2n1ccc2";
|
|
ROMol *templ = SmilesToMol(templ_smiles);
|
|
TEST_ASSERT(templ);
|
|
RDDepict::compute2DCoords(*templ);
|
|
std::string smiles = "c1cccc2ncn3cccc3c21";
|
|
ROMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
RDDepict::generateDepictionMatching2DStructure(*m, *templ);
|
|
writer.write(*m);
|
|
|
|
std::string smarts = "*1****2*1***2";
|
|
ROMol *refPatt = SmartsToMol(smarts);
|
|
RDDepict::generateDepictionMatching2DStructure(*m, *templ, -1, refPatt);
|
|
writer.write(*m);
|
|
|
|
delete templ;
|
|
delete m;
|
|
delete refPatt;
|
|
|
|
std::string xp0_file =
|
|
rdbase + "/Code/GraphMol/Depictor/test_data/1XP0_ligand.sdf";
|
|
RDKit::ROMol *xp0_lig = RDKit::MolFileToMol(xp0_file);
|
|
auto *xp0_lig_2d = new RDKit::ROMol(*xp0_lig);
|
|
RDDepict::compute2DCoords(*xp0_lig_2d);
|
|
writer.write(*xp0_lig_2d);
|
|
RDDepict::generateDepictionMatching3DStructure(*xp0_lig_2d, *xp0_lig);
|
|
writer.write(*xp0_lig_2d);
|
|
|
|
delete xp0_lig;
|
|
delete xp0_lig_2d;
|
|
}
|
|
void testGitHubIssue1112() {
|
|
// Bad coordinate generation for H2
|
|
{
|
|
std::string smiles = "[H][H]";
|
|
RWMol *m = SmilesToMol(smiles);
|
|
TEST_ASSERT(m);
|
|
TEST_ASSERT(m->getNumAtoms() == 2);
|
|
|
|
RDDepict::compute2DCoords(*m);
|
|
TEST_ASSERT(m->getNumConformers() == 1);
|
|
TEST_ASSERT(feq(m->getConformer().getAtomPos(0).x, 0));
|
|
TEST_ASSERT(feq(m->getConformer().getAtomPos(0).y, 0));
|
|
TEST_ASSERT(feq(m->getConformer().getAtomPos(0).z, 0));
|
|
TEST_ASSERT(feq(m->getConformer().getAtomPos(1).x, 0));
|
|
TEST_ASSERT(feq(m->getConformer().getAtomPos(1).y, -1));
|
|
TEST_ASSERT(feq(m->getConformer().getAtomPos(1).z, 0));
|
|
|
|
delete m;
|
|
}
|
|
}
|
|
|
|
void testGitHubIssue1286() {
|
|
// GenerateDepictionMatching2DStructure isn't matching 2D structure
|
|
{ // the original report
|
|
std::string smiles = "C(=O)C(C)NC=O";
|
|
RWMol *templ = SmilesToMol(smiles);
|
|
TEST_ASSERT(templ);
|
|
TEST_ASSERT(templ->getNumAtoms() == 7);
|
|
|
|
smiles = "C(=O)C(C)NC(=O)C1CC1";
|
|
RWMol *mol = SmilesToMol(smiles);
|
|
TEST_ASSERT(mol);
|
|
TEST_ASSERT(mol->getNumAtoms() == 10);
|
|
|
|
RDDepict::compute2DCoords(*templ);
|
|
TEST_ASSERT(templ->getNumConformers() == 1);
|
|
RDDepict::generateDepictionMatching2DStructure(*mol, *templ);
|
|
TEST_ASSERT(mol->getNumConformers() == 1);
|
|
|
|
// std::cout << MolToMolBlock(*templ) << std::endl;
|
|
// std::cout << MolToMolBlock(*mol) << std::endl;
|
|
|
|
const Conformer &tconf = templ->getConformer();
|
|
const Conformer &mconf = mol->getConformer();
|
|
for (unsigned int i = 0; i < templ->getNumAtoms(); ++i) {
|
|
const RDGeom::Point3D &tp = tconf.getAtomPos(i);
|
|
const RDGeom::Point3D &mp = mconf.getAtomPos(i);
|
|
// std::cerr << i << ": " << tp << " | " << mp << std::endl;
|
|
TEST_ASSERT(feq(tp.x, mp.x));
|
|
TEST_ASSERT(feq(tp.y, mp.y));
|
|
}
|
|
|
|
delete templ;
|
|
delete mol;
|
|
}
|
|
{ // extremely crowded. This one tests bond shortening and angle opening
|
|
std::string smiles = "CC(=O)C1=CC=CC2=C1C=CC=C2";
|
|
RWMol *templ = SmilesToMol(smiles);
|
|
TEST_ASSERT(templ);
|
|
TEST_ASSERT(templ->getNumAtoms() == 13);
|
|
|
|
smiles = "O=C(N)C1=C(C=CC2=C1C(=CC=C2)C(C)=O)C(C)(C)C";
|
|
RWMol *mol = SmilesToMol(smiles);
|
|
TEST_ASSERT(mol);
|
|
TEST_ASSERT(mol->getNumAtoms() == 20);
|
|
|
|
RDDepict::compute2DCoords(*templ);
|
|
TEST_ASSERT(templ->getNumConformers() == 1);
|
|
RDDepict::generateDepictionMatching2DStructure(*mol, *templ);
|
|
TEST_ASSERT(mol->getNumConformers() == 1);
|
|
|
|
// std::cout << MolToMolBlock(*templ) << std::endl;
|
|
// std::cout << MolToMolBlock(*mol) << std::endl;
|
|
|
|
MatchVectType mv;
|
|
TEST_ASSERT(SubstructMatch(*mol, *templ, mv));
|
|
|
|
const Conformer &tconf = templ->getConformer();
|
|
const Conformer &mconf = mol->getConformer();
|
|
for (unsigned int i = 0; i < templ->getNumAtoms(); ++i) {
|
|
const RDGeom::Point3D &tp = tconf.getAtomPos(mv[i].first);
|
|
const RDGeom::Point3D &mp = mconf.getAtomPos(mv[i].second);
|
|
// std::cerr << i << ": " << tp << " | " << mp << std::endl;
|
|
TEST_ASSERT(feq(tp.x, mp.x));
|
|
TEST_ASSERT(feq(tp.y, mp.y));
|
|
}
|
|
|
|
delete templ;
|
|
delete mol;
|
|
}
|
|
}
|
|
|
|
void testGithub1691() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Testing Github issue "
|
|
"1691: Acetylenic hydrogens not given appropriate 2D coordinates"
|
|
<< std::endl;
|
|
{
|
|
SmilesParserParams ps;
|
|
ps.removeHs = false;
|
|
std::unique_ptr<RWMol> mol(SmilesToMol("C1#C2.[F]1.[F]2", ps));
|
|
|
|
TEST_ASSERT(mol);
|
|
TEST_ASSERT(mol->getNumAtoms() == 4);
|
|
TEST_ASSERT(mol->getBondBetweenAtoms(0, 2));
|
|
TEST_ASSERT(mol->getBondBetweenAtoms(1, 3));
|
|
RDDepict::compute2DCoords(*mol);
|
|
|
|
// std::cerr << MolToMolBlock(*mol) << std::endl;
|
|
const Conformer &conf = mol->getConformer();
|
|
RDGeom::Point3D v20 = conf.getAtomPos(2) - conf.getAtomPos(0);
|
|
RDGeom::Point3D v10 = conf.getAtomPos(1) - conf.getAtomPos(0);
|
|
RDGeom::Point3D v31 = conf.getAtomPos(3) - conf.getAtomPos(1);
|
|
RDGeom::Point3D v01 = conf.getAtomPos(0) - conf.getAtomPos(1);
|
|
// std::cerr << v20.dotProduct(v10) << std::endl;
|
|
// std::cerr << v31.dotProduct(v01) << std::endl;
|
|
TEST_ASSERT(v20.dotProduct(v10) <= -1.0);
|
|
TEST_ASSERT(v31.dotProduct(v01) <= -1.0);
|
|
}
|
|
{
|
|
SmilesParserParams ps;
|
|
ps.removeHs = false;
|
|
std::unique_ptr<RWMol> mol(SmilesToMol("C1#C2.[H]1.[H]2", ps));
|
|
|
|
TEST_ASSERT(mol);
|
|
TEST_ASSERT(mol->getNumAtoms() == 4);
|
|
TEST_ASSERT(mol->getBondBetweenAtoms(0, 2));
|
|
TEST_ASSERT(mol->getBondBetweenAtoms(1, 3));
|
|
RDDepict::compute2DCoords(*mol);
|
|
|
|
// std::cerr << MolToMolBlock(*mol) << std::endl;
|
|
const Conformer &conf = mol->getConformer();
|
|
RDGeom::Point3D v20 = conf.getAtomPos(2) - conf.getAtomPos(0);
|
|
RDGeom::Point3D v10 = conf.getAtomPos(1) - conf.getAtomPos(0);
|
|
RDGeom::Point3D v31 = conf.getAtomPos(3) - conf.getAtomPos(1);
|
|
RDGeom::Point3D v01 = conf.getAtomPos(0) - conf.getAtomPos(1);
|
|
// std::cerr << v20.dotProduct(v10) << std::endl;
|
|
// std::cerr << v31.dotProduct(v01) << std::endl;
|
|
TEST_ASSERT(v20.dotProduct(v10) <= -1.0);
|
|
TEST_ASSERT(v31.dotProduct(v01) <= -1.0);
|
|
}
|
|
{
|
|
std::unique_ptr<RWMol> mol(SmilesToMol("C#C"));
|
|
|
|
TEST_ASSERT(mol);
|
|
TEST_ASSERT(mol->getNumAtoms() == 2);
|
|
MolOps::addHs(*mol);
|
|
TEST_ASSERT(mol->getNumAtoms() == 4);
|
|
TEST_ASSERT(mol->getBondBetweenAtoms(0, 2));
|
|
TEST_ASSERT(mol->getBondBetweenAtoms(1, 3));
|
|
RDDepict::compute2DCoords(*mol);
|
|
|
|
// std::cerr << MolToMolBlock(*mol) << std::endl;
|
|
const Conformer &conf = mol->getConformer();
|
|
RDGeom::Point3D v20 = conf.getAtomPos(2) - conf.getAtomPos(0);
|
|
RDGeom::Point3D v10 = conf.getAtomPos(1) - conf.getAtomPos(0);
|
|
RDGeom::Point3D v31 = conf.getAtomPos(3) - conf.getAtomPos(1);
|
|
RDGeom::Point3D v01 = conf.getAtomPos(0) - conf.getAtomPos(1);
|
|
// std::cerr << v20.dotProduct(v10) << std::endl;
|
|
// std::cerr << v31.dotProduct(v01) << std::endl;
|
|
TEST_ASSERT(v20.dotProduct(v10) <= -1.0);
|
|
TEST_ASSERT(v31.dotProduct(v01) <= -1.0);
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGithub2027() {
|
|
BOOST_LOG(rdInfoLog) << "-----------------------\n Testing Github issue "
|
|
"2027: \"linear\" fragments not canonically oriented"
|
|
<< std::endl;
|
|
{
|
|
std::unique_ptr<RWMol> mol(SmilesToMol("C#CC#CC#CC#CC#CC#CC#C"));
|
|
TEST_ASSERT(mol);
|
|
RDDepict::compute2DCoords(*mol, nullptr, true);
|
|
const Conformer &conf = mol->getConformer();
|
|
TEST_ASSERT(feq(conf.getAtomPos(0).y, 0.0));
|
|
TEST_ASSERT(feq(conf.getAtomPos(1).y, 0.0));
|
|
TEST_ASSERT(feq(conf.getAtomPos(2).y, 0.0));
|
|
}
|
|
{
|
|
std::unique_ptr<RWMol> mol(SmilesToMol("C1=CC=CC2=CC3=CC=CC=C3C=C12"));
|
|
TEST_ASSERT(mol);
|
|
RDDepict::compute2DCoords(*mol, nullptr, true);
|
|
|
|
// a stupidly simple test to ensure that we're oriented along the x axis:
|
|
const Conformer &conf = mol->getConformer();
|
|
RDGeom::Point2D paccum(0, 0);
|
|
for (const auto &pt : conf.getPositions()) {
|
|
paccum.x += fabs(pt.x);
|
|
paccum.y += fabs(pt.y);
|
|
}
|
|
TEST_ASSERT(paccum.x > paccum.y);
|
|
}
|
|
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGenerate2DDepictionRefPatternMatchVect() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Test "
|
|
"generateDepictionMatching2DStructure with refPattern and matchVect"
|
|
<< std::endl;
|
|
auto indazoleRef = R"RES(
|
|
RDKit 2D
|
|
|
|
9 10 0 0 0 0 0 0 0 0999 V2000
|
|
-6.0878 2.4335 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-7.3867 1.6835 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-7.3867 0.1833 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-6.0878 -0.5666 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-4.7887 0.1833 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-4.7887 1.6835 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-3.4897 -0.5664 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-2.1906 1.6833 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-2.1906 0.1835 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1 2 2 0
|
|
2 3 1 0
|
|
3 4 2 0
|
|
4 5 1 0
|
|
5 6 2 0
|
|
6 1 1 0
|
|
8 9 2 0
|
|
6 8 1 0
|
|
7 9 1 0
|
|
7 5 1 0
|
|
M END)RES"_ctab;
|
|
auto cycloheptylPyrazole = "c1cc(C2CCCCCC2)[nH]n1"_smiles;
|
|
double msd;
|
|
bool raised;
|
|
|
|
// test using refPattern
|
|
auto refPatt = "a1aan[nH]1"_smarts;
|
|
RDDepict::generateDepictionMatching2DStructure(
|
|
*cycloheptylPyrazole, *indazoleRef, -1, refPatt.get());
|
|
TEST_ASSERT(cycloheptylPyrazole->getNumConformers() == 1);
|
|
MatchVectType molMatchVect;
|
|
TEST_ASSERT(SubstructMatch(*cycloheptylPyrazole, *refPatt, molMatchVect));
|
|
MatchVectType refMatchVect;
|
|
TEST_ASSERT(SubstructMatch(*indazoleRef, *refPatt, refMatchVect));
|
|
TEST_ASSERT(molMatchVect.size() == refMatchVect.size());
|
|
msd = 0.0;
|
|
for (size_t i = 0; i < molMatchVect.size(); ++i) {
|
|
msd += (indazoleRef->getConformer().getAtomPos(refMatchVect.at(i).second) -
|
|
cycloheptylPyrazole->getConformer().getAtomPos(
|
|
molMatchVect.at(i).second))
|
|
.lengthSq();
|
|
}
|
|
msd /= static_cast<double>(molMatchVect.size());
|
|
TEST_ASSERT(msd < 1.0e-4);
|
|
// try with a pattern larger than the reference molecule
|
|
auto hugePatt = "CCCCCCCCCCCCCCCCCCCCCCCCCCC"_smarts;
|
|
raised = false;
|
|
try {
|
|
RDDepict::generateDepictionMatching2DStructure(
|
|
*cycloheptylPyrazole, *indazoleRef, -1, hugePatt.get());
|
|
} catch (const RDDepict::DepictException &) {
|
|
raised = true;
|
|
}
|
|
TEST_ASSERT(raised);
|
|
// try with an out of range confId
|
|
raised = false;
|
|
try {
|
|
RDDepict::generateDepictionMatching2DStructure(
|
|
*cycloheptylPyrazole, *indazoleRef, 1, refPatt.get());
|
|
} catch (const RDKit::ConformerException &) {
|
|
raised = true;
|
|
}
|
|
|
|
// test using matchVect directly
|
|
cycloheptylPyrazole->removeConformer(0);
|
|
MatchVectType matchVect;
|
|
for (size_t i = 0; i < molMatchVect.size(); ++i) {
|
|
matchVect.emplace_back(
|
|
std::make_pair(refMatchVect.at(i).second, molMatchVect.at(i).second));
|
|
}
|
|
RDDepict::generateDepictionMatching2DStructure(*cycloheptylPyrazole,
|
|
*indazoleRef, matchVect);
|
|
TEST_ASSERT(cycloheptylPyrazole->getNumConformers() == 1);
|
|
msd = 0.0;
|
|
for (const auto &pair : matchVect) {
|
|
msd += (indazoleRef->getConformer().getAtomPos(pair.first) -
|
|
cycloheptylPyrazole->getConformer().getAtomPos(pair.second))
|
|
.lengthSq();
|
|
}
|
|
msd /= static_cast<double>(matchVect.size());
|
|
TEST_ASSERT(msd < 1.0e-4);
|
|
// try with a matchVect larger than the reference molecule
|
|
MatchVectType matchVectHuge(matchVect);
|
|
for (size_t i = 0; i < indazoleRef->getNumAtoms(); ++i) {
|
|
matchVectHuge.emplace_back(std::make_pair(0, 0));
|
|
}
|
|
raised = false;
|
|
try {
|
|
RDDepict::generateDepictionMatching2DStructure(*cycloheptylPyrazole,
|
|
*indazoleRef, matchVectHuge);
|
|
} catch (const RDDepict::DepictException &) {
|
|
raised = true;
|
|
}
|
|
// try with a matchVect with out of range indices
|
|
MatchVectType matchVectOutOfRange(matchVect);
|
|
matchVectOutOfRange.emplace_back(std::make_pair(100, 100));
|
|
raised = false;
|
|
try {
|
|
RDDepict::generateDepictionMatching2DStructure(
|
|
*cycloheptylPyrazole, *indazoleRef, matchVectOutOfRange);
|
|
} catch (const RDDepict::DepictException &) {
|
|
raised = true;
|
|
}
|
|
// try with an out of range confId
|
|
raised = false;
|
|
try {
|
|
RDDepict::generateDepictionMatching2DStructure(*cycloheptylPyrazole,
|
|
*indazoleRef, matchVect, 1);
|
|
} catch (const RDKit::ConformerException &) {
|
|
raised = true;
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGenerate2DDepictionAllowRGroupsOrig() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Test "
|
|
"generateDepictionMatching2DStructure with allowRGroups"
|
|
<< std::endl;
|
|
auto templateRef = R"RES(
|
|
RDKit 2D
|
|
|
|
9 9 0 0 0 0 0 0 0 0999 V2000
|
|
-0.8929 1.0942 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-2.1919 0.3442 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-2.1919 -1.1558 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-0.8929 -1.9059 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.4060 -1.1558 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.4060 0.3442 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-3.4910 1.0942 0.0000 R1 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1.7051 1.0942 0.0000 R2 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-3.4910 -1.9059 0.0000 R3 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1 2 2 0
|
|
2 3 1 0
|
|
3 4 2 0
|
|
4 5 1 0
|
|
5 6 2 0
|
|
6 1 1 0
|
|
6 8 1 0
|
|
3 9 1 0
|
|
2 7 1 0
|
|
M RGP 3 7 1 8 2 9 3
|
|
M END)RES"_ctab;
|
|
auto orthoMeta = "c1ccc(-c2ccc(-c3ccccc3)c(-c3ccccc3)c2)cc1"_smiles;
|
|
auto ortho = "c1ccc(-c2ccccc2-c2ccccc2)cc1"_smiles;
|
|
auto meta = "c1ccc(-c2cccc(-c3ccccc3)c2)cc1"_smiles;
|
|
auto biphenyl = "c1ccccc1-c1ccccc1"_smiles;
|
|
auto phenyl = "c1ccccc1"_smiles;
|
|
|
|
RDDepict::generateDepictionMatching2DStructure(*orthoMeta, *templateRef);
|
|
TEST_ASSERT(orthoMeta->getNumConformers() == 1);
|
|
|
|
for (auto mol : {ortho.get(), meta.get(), biphenyl.get(), phenyl.get()}) {
|
|
// fails as does not match template
|
|
bool raised = false;
|
|
try {
|
|
RDDepict::generateDepictionMatching2DStructure(*mol, *templateRef);
|
|
} catch (const RDDepict::DepictException &) {
|
|
raised = true;
|
|
}
|
|
TEST_ASSERT(raised);
|
|
|
|
// succeeds with allowRGroups = true
|
|
auto matchVect = RDDepict::generateDepictionMatching2DStructure(
|
|
*mol, *templateRef, -1, nullptr, false, false, true);
|
|
TEST_ASSERT(mol->getNumConformers() == 1);
|
|
double msd = 0.0;
|
|
for (const auto &pair : matchVect) {
|
|
msd += (templateRef->getConformer().getAtomPos(pair.first) -
|
|
mol->getConformer().getAtomPos(pair.second))
|
|
.lengthSq();
|
|
}
|
|
msd /= static_cast<double>(matchVect.size());
|
|
TEST_ASSERT(msd < 1.0e-4);
|
|
}
|
|
|
|
// test that using a refPattern with R groups and a reference without works
|
|
auto pyridineRef = R"RES(
|
|
RDKit 2D
|
|
|
|
6 6 0 0 0 0 0 0 0 0999 V2000
|
|
-0.8929 1.0942 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-2.1919 0.3442 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-2.1919 -1.1558 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-0.8929 -1.9059 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.4060 -1.1558 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.4060 0.3442 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1 2 2 0
|
|
2 3 1 0
|
|
3 4 2 0
|
|
4 5 1 0
|
|
5 6 2 0
|
|
6 1 1 0
|
|
M END)RES"_ctab;
|
|
auto genericRefPatternWithRGroups = "[*:3]a1a([*:1])aa([*:2])aa1"_smarts;
|
|
std::unique_ptr<ROMol> pyridineRefHs(
|
|
MolOps::addHs(static_cast<const ROMol &>(*pyridineRef)));
|
|
|
|
for (auto mol : {ortho.get(), meta.get(), biphenyl.get(), phenyl.get()}) {
|
|
auto matchVect = RDDepict::generateDepictionMatching2DStructure(
|
|
*mol, *pyridineRef, -1, genericRefPatternWithRGroups.get(), false,
|
|
false, true);
|
|
TEST_ASSERT(mol->getNumConformers() == 1);
|
|
double msd = 0.0;
|
|
for (const auto &pair : matchVect) {
|
|
msd += (pyridineRef->getConformer().getAtomPos(pair.first) -
|
|
mol->getConformer().getAtomPos(pair.second))
|
|
.lengthSq();
|
|
}
|
|
msd /= static_cast<double>(matchVect.size());
|
|
TEST_ASSERT(msd < 1.0e-4);
|
|
}
|
|
|
|
// test that using a reference with query atoms including H works
|
|
auto scaffold = R"CTAB(
|
|
MJ201100
|
|
|
|
12 13 0 0 0 0 0 0 0 0999 V2000
|
|
-0.5398 0.0400 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-1.3648 0.0400 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-1.7773 -0.6745 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-1.3649 -1.3889 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-0.5399 -1.3889 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-0.1273 -0.6744 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.6976 -0.6744 0.0000 L 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-1.9167 0.6531 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-2.6704 0.3176 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-2.5842 -0.5028 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-3.3849 0.7302 0.0000 L 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-1.7451 1.4600 0.0000 L 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1 2 2 0 0 0 0
|
|
2 3 1 0 0 0 0
|
|
3 4 2 0 0 0 0
|
|
4 5 1 0 0 0 0
|
|
5 6 2 0 0 0 0
|
|
6 1 1 0 0 0 0
|
|
6 7 1 0 0 0 0
|
|
8 9 2 0 0 0 0
|
|
2 8 1 0 0 0 0
|
|
9 10 1 0 0 0 0
|
|
3 10 1 0 0 0 0
|
|
9 11 1 0 0 0 0
|
|
8 12 1 0 0 0 0
|
|
M ALS 7 10 F H C N O F P S Cl Br I
|
|
M ALS 11 10 F H C N O F P S Cl Br I
|
|
M ALS 12 10 F H C N O F P S Cl Br I
|
|
M END
|
|
)CTAB"_ctab;
|
|
auto mol = R"CTAB(
|
|
MJ201100
|
|
|
|
13 14 0 0 0 0 0 0 0 0999 V2000
|
|
-0.6112 0.3665 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-1.3648 0.0310 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-1.4510 -0.7895 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-0.7836 -1.2744 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-0.0299 -0.9389 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.0562 -0.1183 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.8099 0.2172 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-2.1184 0.3666 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-2.6705 -0.2464 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-2.2580 -0.9608 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.6374 -1.4238 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.8961 1.0377 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.5512 -2.2443 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1 2 2 0 0 0 0
|
|
2 3 1 0 0 0 0
|
|
3 4 2 0 0 0 0
|
|
4 5 1 0 0 0 0
|
|
5 6 2 0 0 0 0
|
|
6 1 1 0 0 0 0
|
|
8 9 2 0 0 0 0
|
|
2 8 1 0 0 0 0
|
|
9 10 1 0 0 0 0
|
|
3 10 1 0 0 0 0
|
|
6 7 1 0 0 0 0
|
|
5 11 1 0 0 0 0
|
|
7 12 1 0 0 0 0
|
|
11 13 1 0 0 0 0
|
|
M END
|
|
)CTAB"_ctab;
|
|
auto matchVect = RDDepict::generateDepictionMatching2DStructure(
|
|
*mol, *scaffold, -1, nullptr, false, false, true);
|
|
TEST_ASSERT(mol->getNumConformers() == 1);
|
|
TEST_ASSERT(matchVect.size() == 10);
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testGenerate2DDepictionAllowRGroups() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Test "
|
|
"generateDepictionMatching2DStructure with allowRGroups"
|
|
<< std::endl;
|
|
auto templateRef = R"RES(
|
|
RDKit 2D
|
|
|
|
9 9 0 0 0 0 0 0 0 0999 V2000
|
|
-0.8929 1.0942 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-2.1919 0.3442 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-2.1919 -1.1558 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-0.8929 -1.9059 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.4060 -1.1558 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.4060 0.3442 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-3.4910 1.0942 0.0000 R1 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1.7051 1.0942 0.0000 R2 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-3.4910 -1.9059 0.0000 R3 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1 2 2 0
|
|
2 3 1 0
|
|
3 4 2 0
|
|
4 5 1 0
|
|
5 6 2 0
|
|
6 1 1 0
|
|
6 8 1 0
|
|
3 9 1 0
|
|
2 7 1 0
|
|
M RGP 3 7 1 8 2 9 3
|
|
M END)RES"_ctab;
|
|
TEST_ASSERT(templateRef);
|
|
auto orthoMeta = "c1ccc(-c2ccc(-c3ccccc3)c(-c3ccccc3)c2)cc1"_smiles;
|
|
auto ortho = "c1ccc(-c2ccccc2-c2ccccc2)cc1"_smiles;
|
|
auto meta = "c1ccc(-c2cccc(-c3ccccc3)c2)cc1"_smiles;
|
|
auto para = "c1ccc(-c2ccc(-c3ccccc3)cc2)cc1"_smiles;
|
|
auto biphenyl = "c1ccccc1-c1ccccc1"_smiles;
|
|
auto phenyl = "c1ccccc1"_smiles;
|
|
|
|
auto prevBondLen = RDDepict::BOND_LEN;
|
|
RDDepict::BOND_LEN = defaultRDKitBondLen;
|
|
RDDepict::generateDepictionMatching2DStructure(*orthoMeta, *templateRef);
|
|
TEST_ASSERT(orthoMeta->getNumConformers() == 1);
|
|
for (bool alignOnly : {true, false}) {
|
|
for (auto mol :
|
|
{ortho.get(), meta.get(), para.get(), biphenyl.get(), phenyl.get()}) {
|
|
TEST_ASSERT(mol);
|
|
RDDepict::ConstrainedDepictionParams p;
|
|
p.allowRGroups = true;
|
|
p.alignOnly = alignOnly;
|
|
// fails as does not match template
|
|
bool raised = false;
|
|
try {
|
|
RDDepict::generateDepictionMatching2DStructure(*mol, *templateRef);
|
|
} catch (const RDDepict::DepictException &) {
|
|
raised = true;
|
|
}
|
|
TEST_ASSERT(raised);
|
|
|
|
// succeeds with allowRGroups = true
|
|
auto matchVect = RDDepict::generateDepictionMatching2DStructure(
|
|
*mol, *templateRef, -1, nullptr, p);
|
|
TEST_ASSERT(!matchVect.empty());
|
|
TEST_ASSERT(mol->getNumConformers() == 1);
|
|
double msd = 0.0;
|
|
for (const auto &pair : matchVect) {
|
|
msd += (templateRef->getConformer().getAtomPos(pair.first) -
|
|
mol->getConformer().getAtomPos(pair.second))
|
|
.lengthSq();
|
|
}
|
|
msd /= static_cast<double>(matchVect.size());
|
|
TEST_ASSERT(msd < 1.0e-4);
|
|
}
|
|
|
|
// test that using a refPattern with R groups and a reference missing one
|
|
// works
|
|
auto pyridineRef = R"RES(
|
|
RDKit 2D
|
|
|
|
8 8 0 0 0 0 0 0 0 0999 V2000
|
|
0.0000 1.5469 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-1.3395 0.7734 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-1.3395 -0.7732 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.0000 -1.5469 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1.3395 -0.7732 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1.3395 0.7734 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.0000 3.0938 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.0000 -3.0938 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1 2 2 0
|
|
2 3 1 0
|
|
3 4 2 0
|
|
4 5 1 0
|
|
5 6 2 0
|
|
6 1 1 0
|
|
1 7 1 0
|
|
4 8 1 0
|
|
M END)RES"_ctab;
|
|
TEST_ASSERT(pyridineRef);
|
|
auto genericRefPatternWithRGroups = "[*:3]a1a([*:1])aa([*:2])aa1"_smarts;
|
|
TEST_ASSERT(genericRefPatternWithRGroups);
|
|
for (auto [numExpectedMatches, mol] :
|
|
std::vector<std::pair<unsigned int, ROMol *>>{{8, orthoMeta.get()},
|
|
{7, ortho.get()},
|
|
{7, meta.get()},
|
|
{8, para.get()},
|
|
{7, biphenyl.get()},
|
|
{6, phenyl.get()}}) {
|
|
RDDepict::ConstrainedDepictionParams p;
|
|
p.allowRGroups = true;
|
|
p.alignOnly = alignOnly;
|
|
auto matchVect = RDDepict::generateDepictionMatching2DStructure(
|
|
*mol, *pyridineRef, -1, genericRefPatternWithRGroups.get(), p);
|
|
TEST_ASSERT(matchVect.size() == numExpectedMatches);
|
|
TEST_ASSERT(mol->getNumConformers() == 1);
|
|
double msd = 0.0;
|
|
for (const auto &pair : matchVect) {
|
|
msd += (pyridineRef->getConformer().getAtomPos(pair.first) -
|
|
mol->getConformer().getAtomPos(pair.second))
|
|
.lengthSq();
|
|
}
|
|
msd /= static_cast<double>(matchVect.size());
|
|
TEST_ASSERT(msd < (alignOnly ? 5.e-3 : 1.0e-4));
|
|
}
|
|
|
|
// test that using a reference with query atoms including H works
|
|
auto scaffold = R"CTAB(
|
|
MJ201100
|
|
|
|
12 13 0 0 0 0 0 0 0 0999 V2000
|
|
-0.5398 0.0400 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-1.3648 0.0400 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-1.7773 -0.6745 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-1.3649 -1.3889 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-0.5399 -1.3889 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-0.1273 -0.6744 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.6976 -0.6744 0.0000 L 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-1.9167 0.6531 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-2.6704 0.3176 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-2.5842 -0.5028 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-3.3849 0.7302 0.0000 L 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-1.7451 1.4600 0.0000 L 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1 2 2 0 0 0 0
|
|
2 3 1 0 0 0 0
|
|
3 4 2 0 0 0 0
|
|
4 5 1 0 0 0 0
|
|
5 6 2 0 0 0 0
|
|
6 1 1 0 0 0 0
|
|
6 7 1 0 0 0 0
|
|
8 9 2 0 0 0 0
|
|
2 8 1 0 0 0 0
|
|
9 10 1 0 0 0 0
|
|
3 10 1 0 0 0 0
|
|
9 11 1 0 0 0 0
|
|
8 12 1 0 0 0 0
|
|
M ALS 7 10 F H C N O F P S Cl Br I
|
|
M ALS 11 10 F H C N O F P S Cl Br I
|
|
M ALS 12 10 F H C N O F P S Cl Br I
|
|
M END
|
|
)CTAB"_ctab;
|
|
TEST_ASSERT(scaffold);
|
|
auto mol = R"CTAB(
|
|
MJ201100
|
|
|
|
13 14 0 0 0 0 0 0 0 0999 V2000
|
|
-0.6112 0.3665 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-1.3648 0.0310 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-1.4510 -0.7895 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-0.7836 -1.2744 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-0.0299 -0.9389 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.0562 -0.1183 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.8099 0.2172 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-2.1184 0.3666 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-2.6705 -0.2464 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-2.2580 -0.9608 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.6374 -1.4238 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.8961 1.0377 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.5512 -2.2443 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1 2 2 0 0 0 0
|
|
2 3 1 0 0 0 0
|
|
3 4 2 0 0 0 0
|
|
4 5 1 0 0 0 0
|
|
5 6 2 0 0 0 0
|
|
6 1 1 0 0 0 0
|
|
8 9 2 0 0 0 0
|
|
2 8 1 0 0 0 0
|
|
9 10 1 0 0 0 0
|
|
3 10 1 0 0 0 0
|
|
6 7 1 0 0 0 0
|
|
5 11 1 0 0 0 0
|
|
7 12 1 0 0 0 0
|
|
11 13 1 0 0 0 0
|
|
M END
|
|
)CTAB"_ctab;
|
|
TEST_ASSERT(mol);
|
|
auto matchVect = RDDepict::generateDepictionMatching2DStructure(
|
|
*mol, *scaffold, -1, nullptr, false, false, true);
|
|
TEST_ASSERT(mol->getNumConformers() == 1);
|
|
TEST_ASSERT(matchVect.size() == 10);
|
|
}
|
|
RDDepict::BOND_LEN = prevBondLen;
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testNormalizeStraighten() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Test normalize and straighten depiction"
|
|
<< std::endl;
|
|
|
|
auto noradrenalineMJ = R"RES(
|
|
MJ201100
|
|
|
|
12 12 0 0 1 0 0 0 0 0999 V2000
|
|
2.2687 1.0716 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1.4437 1.0716 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1.0312 0.3572 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1.4437 -0.3572 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.2062 0.3572 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-0.2062 -0.3572 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-1.0312 -0.3572 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-1.4437 -1.0716 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-1.4437 0.3572 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-2.2687 0.3572 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-1.0312 1.0716 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-0.2062 1.0716 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1 2 1 0 0 0 0
|
|
3 2 1 0 0 0 0
|
|
3 4 1 6 0 0 0
|
|
3 5 1 0 0 0 0
|
|
5 6 2 0 0 0 0
|
|
6 7 1 0 0 0 0
|
|
7 8 1 0 0 0 0
|
|
7 9 2 0 0 0 0
|
|
9 10 1 0 0 0 0
|
|
9 11 1 0 0 0 0
|
|
11 12 2 0 0 0 0
|
|
5 12 1 0 0 0 0
|
|
M END)RES"_ctab;
|
|
{
|
|
auto noradrenalineMJCopy =
|
|
std::unique_ptr<RWMol>(new RWMol(*noradrenalineMJ));
|
|
const auto &conformer0 = noradrenalineMJCopy->getConformer(0);
|
|
auto conformer1 = new Conformer(conformer0);
|
|
noradrenalineMJCopy->addConformer(conformer1, true);
|
|
TEST_ASSERT(MolAlign::CalcRMS(*noradrenalineMJ, *noradrenalineMJCopy, 0,
|
|
0) < 1.e-5);
|
|
TEST_ASSERT(MolAlign::CalcRMS(*noradrenalineMJ, *noradrenalineMJCopy, 0,
|
|
1) < 1.e-5);
|
|
auto scalingFactor = RDDepict::normalizeDepiction(*noradrenalineMJCopy, 1);
|
|
TEST_ASSERT(MolAlign::CalcRMS(*noradrenalineMJ, *noradrenalineMJCopy, 0,
|
|
0) < 1.e-5);
|
|
TEST_ASSERT(MolAlign::CalcRMS(*noradrenalineMJ, *noradrenalineMJCopy, 0,
|
|
1) > 1.e-5);
|
|
TEST_ASSERT(RDKit::feq(scalingFactor, 1.875, 1.e-3));
|
|
auto conformer2 = new Conformer(*conformer1);
|
|
noradrenalineMJCopy->addConformer(conformer2, true);
|
|
auto bond10_11Conf0 = conformer0.getAtomPos(11) - conformer0.getAtomPos(10);
|
|
TEST_ASSERT(RDKit::feq(bond10_11Conf0.x, 0.825, 1.e-3));
|
|
TEST_ASSERT(RDKit::feq(bond10_11Conf0.y, 0.0, 1.e-3));
|
|
auto bond10_11Conf1 =
|
|
conformer1->getAtomPos(11) - conformer1->getAtomPos(10);
|
|
TEST_ASSERT(RDKit::feq(bond10_11Conf1.x, 1.513, 1.e-3));
|
|
TEST_ASSERT(RDKit::feq(bond10_11Conf1.y, -0.321, 1.e-3));
|
|
RDDepict::straightenDepiction(*noradrenalineMJCopy, 1);
|
|
bond10_11Conf1 = conformer1->getAtomPos(11) - conformer1->getAtomPos(10);
|
|
TEST_ASSERT(RDKit::feq(bond10_11Conf1.x, 1.340, 1.e-3));
|
|
TEST_ASSERT(RDKit::feq(bond10_11Conf1.y, -0.773, 1.e-3));
|
|
auto bond4_11Conf1 = conformer1->getAtomPos(11) - conformer1->getAtomPos(4);
|
|
TEST_ASSERT(RDKit::feq(bond4_11Conf1.x, 0.0, 1.e-3));
|
|
TEST_ASSERT(RDKit::feq(bond4_11Conf1.y, 1.547, 1.e-3));
|
|
RDDepict::straightenDepiction(*noradrenalineMJCopy, 2, true);
|
|
auto bond10_11Conf2 =
|
|
conformer2->getAtomPos(11) - conformer2->getAtomPos(10);
|
|
TEST_ASSERT(RDKit::feq(bond10_11Conf2.x, 1.547, 1.e-3));
|
|
TEST_ASSERT(RDKit::feq(bond10_11Conf2.y, 0.0, 1.e-3));
|
|
auto bond4_11Conf2 = conformer2->getAtomPos(11) - conformer2->getAtomPos(4);
|
|
TEST_ASSERT(RDKit::feq(bond4_11Conf2.x, -0.773, 1.e-3));
|
|
TEST_ASSERT(RDKit::feq(bond4_11Conf2.y, 1.339, 1.e-3));
|
|
}
|
|
{
|
|
auto noradrenalineMJCopy =
|
|
std::unique_ptr<RWMol>(new RWMol(*noradrenalineMJ));
|
|
const auto &conformer0 = noradrenalineMJCopy->getConformer(0);
|
|
auto conformer1 = new Conformer(conformer0);
|
|
noradrenalineMJCopy->addConformer(conformer1, true);
|
|
auto scalingFactor =
|
|
RDDepict::normalizeDepiction(*noradrenalineMJCopy, 1, -1);
|
|
TEST_ASSERT(MolAlign::CalcRMS(*noradrenalineMJ, *noradrenalineMJCopy, 0,
|
|
0) < 1.e-5);
|
|
TEST_ASSERT(MolAlign::CalcRMS(*noradrenalineMJ, *noradrenalineMJCopy, 0,
|
|
1) > 1.e-5);
|
|
TEST_ASSERT(RDKit::feq(scalingFactor, 1.875, 1.e-3));
|
|
auto conformer2 = new Conformer(*conformer1);
|
|
noradrenalineMJCopy->addConformer(conformer2, true);
|
|
auto bond10_11Conf0 = conformer0.getAtomPos(11) - conformer0.getAtomPos(10);
|
|
TEST_ASSERT(RDKit::feq(bond10_11Conf0.x, 0.825, 1.e-3));
|
|
TEST_ASSERT(RDKit::feq(bond10_11Conf0.y, 0.0, 1.e-3));
|
|
auto bond10_11Conf1 =
|
|
conformer1->getAtomPos(11) - conformer1->getAtomPos(10);
|
|
TEST_ASSERT(RDKit::feq(bond10_11Conf1.x, 0.321, 1.e-3));
|
|
TEST_ASSERT(RDKit::feq(bond10_11Conf1.y, 1.513, 1.e-3));
|
|
RDDepict::straightenDepiction(*noradrenalineMJCopy, 1);
|
|
bond10_11Conf1 = conformer1->getAtomPos(11) - conformer1->getAtomPos(10);
|
|
TEST_ASSERT(RDKit::feq(bond10_11Conf1.x, 0.0, 1.e-3));
|
|
TEST_ASSERT(RDKit::feq(bond10_11Conf1.y, 1.547, 1.e-3));
|
|
RDDepict::straightenDepiction(*noradrenalineMJCopy, 2, true);
|
|
auto bond10_11Conf2 =
|
|
conformer2->getAtomPos(11) - conformer2->getAtomPos(10);
|
|
TEST_ASSERT(RDKit::feq(bond10_11Conf2.x, bond10_11Conf1.x, 1.e-3));
|
|
TEST_ASSERT(RDKit::feq(bond10_11Conf2.y, bond10_11Conf1.y, 1.e-3));
|
|
}
|
|
{
|
|
auto noradrenalineMJCopy =
|
|
std::unique_ptr<RWMol>(new RWMol(*noradrenalineMJ));
|
|
const auto &conformer0 = noradrenalineMJCopy->getConformer(0);
|
|
auto conformer1 = new Conformer(conformer0);
|
|
noradrenalineMJCopy->addConformer(conformer1, true);
|
|
auto scalingFactor =
|
|
RDDepict::normalizeDepiction(*noradrenalineMJCopy, 1, 0, 3.0);
|
|
TEST_ASSERT(MolAlign::CalcRMS(*noradrenalineMJ, *noradrenalineMJCopy, 0,
|
|
0) < 1.e-5);
|
|
TEST_ASSERT(MolAlign::CalcRMS(*noradrenalineMJ, *noradrenalineMJCopy, 0,
|
|
1) > 1.e-5);
|
|
TEST_ASSERT(RDKit::feq(scalingFactor, 3.0, 1.e-3));
|
|
auto conformer2 = new Conformer(*conformer1);
|
|
noradrenalineMJCopy->addConformer(conformer2, true);
|
|
auto conformer3 = new Conformer(*conformer1);
|
|
noradrenalineMJCopy->addConformer(conformer3, true);
|
|
auto bond10_11Conf0 = conformer0.getAtomPos(11) - conformer0.getAtomPos(10);
|
|
TEST_ASSERT(RDKit::feq(bond10_11Conf0.x, 0.825, 1.e-3));
|
|
TEST_ASSERT(RDKit::feq(bond10_11Conf0.y, 0.0, 1.e-3));
|
|
auto bond10_11Conf1 =
|
|
conformer1->getAtomPos(11) - conformer1->getAtomPos(10);
|
|
TEST_ASSERT(RDKit::feq(bond10_11Conf1.x, 2.475, 1.e-3));
|
|
TEST_ASSERT(RDKit::feq(bond10_11Conf1.y, 0.0, 1.e-3));
|
|
RDDepict::straightenDepiction(*noradrenalineMJCopy, 1);
|
|
bond10_11Conf1 = conformer1->getAtomPos(11) - conformer1->getAtomPos(10);
|
|
TEST_ASSERT(RDKit::feq(bond10_11Conf1.x, 2.143, 1.e-3));
|
|
TEST_ASSERT(RDKit::feq(bond10_11Conf1.y, -1.237, 1.e-3));
|
|
auto bond4_11Conf1 = conformer1->getAtomPos(11) - conformer1->getAtomPos(4);
|
|
TEST_ASSERT(RDKit::feq(bond4_11Conf1.x, 0.0, 1.e-3));
|
|
TEST_ASSERT(RDKit::feq(bond4_11Conf1.y, 2.475, 1.e-3));
|
|
RDDepict::straightenDepiction(*noradrenalineMJCopy, 2, true);
|
|
auto bond10_11Conf2 =
|
|
conformer2->getAtomPos(11) - conformer2->getAtomPos(10);
|
|
auto bond10_11Conf3 =
|
|
conformer3->getAtomPos(11) - conformer3->getAtomPos(10);
|
|
TEST_ASSERT(RDKit::feq(bond10_11Conf2.x, bond10_11Conf3.x, 1.e-3));
|
|
TEST_ASSERT(RDKit::feq(bond10_11Conf2.y, bond10_11Conf3.y, 1.e-3));
|
|
auto bond4_11Conf2 = conformer2->getAtomPos(11) - conformer2->getAtomPos(4);
|
|
auto bond4_11Conf3 = conformer3->getAtomPos(11) - conformer3->getAtomPos(4);
|
|
TEST_ASSERT(RDKit::feq(bond4_11Conf2.x, bond4_11Conf3.x, 1.e-3));
|
|
TEST_ASSERT(RDKit::feq(bond4_11Conf2.y, bond4_11Conf3.y, 1.e-3));
|
|
}
|
|
{
|
|
auto zeroCoordCTab = R"RES(
|
|
RDKit 2D
|
|
|
|
6 6 0 0 0 0 0 0 0 0999 V2000
|
|
0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1 2 1 0
|
|
2 3 2 0
|
|
3 4 1 0
|
|
4 5 2 0
|
|
5 6 1 0
|
|
6 1 2 0
|
|
M END
|
|
)RES";
|
|
std::unique_ptr<RWMol> zeroCoordBenzene(MolBlockToMol(zeroCoordCTab));
|
|
auto res = RDDepict::normalizeDepiction(*zeroCoordBenzene);
|
|
TEST_ASSERT(res < 0.);
|
|
TEST_ASSERT(MolToMolBlock(*zeroCoordBenzene) == zeroCoordCTab);
|
|
}
|
|
{
|
|
// cyclopentadiene which is already straight should not be biased
|
|
// towards a 30-degree angle rotate since it has no bonds
|
|
// whose angle with the X axis is multiple of 60 degrees
|
|
auto cpSittingOnHorizontalBondCTab = R"RES(
|
|
MJ201100
|
|
|
|
5 5 0 0 0 0 0 0 0 0999 V2000
|
|
-2.3660 0.3892 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-3.0334 -0.0957 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-2.7785 -0.8803 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-1.9535 -0.8803 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
-1.6986 -0.0957 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
|
|
1 2 1 0 0 0 0
|
|
1 5 1 0 0 0 0
|
|
2 3 2 0 0 0 0
|
|
3 4 1 0 0 0 0
|
|
4 5 2 0 0 0 0
|
|
M END
|
|
)RES";
|
|
std::unique_ptr<RWMol> cpSittingOnHorizontalBond(
|
|
MolBlockToMol(cpSittingOnHorizontalBondCTab));
|
|
std::unique_ptr<RWMol> cpSittingOnHorizontalBondCopy(
|
|
new RWMol(*cpSittingOnHorizontalBond));
|
|
RDDepict::straightenDepiction(*cpSittingOnHorizontalBond);
|
|
TEST_ASSERT(MolAlign::CalcRMS(*cpSittingOnHorizontalBond,
|
|
*cpSittingOnHorizontalBondCopy) < 1.e-3);
|
|
RDGeom::Transform3D trans;
|
|
// rotate by 90 degrees
|
|
trans.SetRotation(0.5 * M_PI, RDGeom::Z_Axis);
|
|
MolTransforms::transformConformer(cpSittingOnHorizontalBond->getConformer(),
|
|
trans);
|
|
cpSittingOnHorizontalBondCopy.reset(new RWMol(*cpSittingOnHorizontalBond));
|
|
RDDepict::straightenDepiction(*cpSittingOnHorizontalBond);
|
|
TEST_ASSERT(MolAlign::CalcRMS(*cpSittingOnHorizontalBond,
|
|
*cpSittingOnHorizontalBondCopy) < 1.e-3);
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
void testValidRingSystemTemplates() {
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "-----------------------\n Test that ring system templates are valid "
|
|
<< std::endl;
|
|
for (auto &smarts : TEMPLATE_SMARTS) {
|
|
std::unique_ptr<ROMol> mol{SmartsToMol(smarts)};
|
|
// Initialize ring info using symmetrizeSSSR to match depictor ring counting
|
|
RDKit::VECT_INT_VECT arings;
|
|
RDKit::MolOps::symmetrizeSSSR(*mol, arings);
|
|
RDDepict::CoordinateTemplates::assertValidTemplate(*mol, smarts);
|
|
}
|
|
BOOST_LOG(rdInfoLog) << "Finished" << std::endl;
|
|
}
|
|
|
|
int main() {
|
|
#ifdef RDK_BUILD_COORDGEN_SUPPORT
|
|
RDDepict::preferCoordGen = false;
|
|
#endif
|
|
|
|
RDLog::InitLogs();
|
|
boost::logging::enable_logs("rdApp.info");
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
BOOST_LOG(rdInfoLog) << " test1 \n";
|
|
test1();
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n\n";
|
|
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
BOOST_LOG(rdInfoLog) << " testCollisions \n";
|
|
testCollisions();
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n\n";
|
|
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
BOOST_LOG(rdInfoLog) << " testAddHs \n";
|
|
testAddHs();
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n\n";
|
|
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
BOOST_LOG(rdInfoLog) << " test198 \n";
|
|
testIssue198();
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n\n";
|
|
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
BOOST_LOG(rdInfoLog) << " test2 \n";
|
|
test2();
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
BOOST_LOG(rdInfoLog) << " test3 \n";
|
|
test3();
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
BOOST_LOG(rdInfoLog) << " test4 \n";
|
|
test4();
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
BOOST_LOG(rdInfoLog) << " tempTest \n";
|
|
tempTest();
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
BOOST_LOG(rdInfoLog) << " Issue248 \n";
|
|
testIssue248();
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
BOOST_LOG(rdInfoLog) << " Test Queries \n";
|
|
testQueries();
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
BOOST_LOG(rdInfoLog) << " Test crashes associated with RemoveHs \n";
|
|
testRemoveHsCrash();
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
BOOST_LOG(rdInfoLog) << " Test Issue 2091304\n";
|
|
testIssue2091304();
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
BOOST_LOG(rdInfoLog) << " Test Issue 2821647\n";
|
|
testIssue2821647();
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
BOOST_LOG(rdInfoLog) << " Test Issue 2948402\n";
|
|
testIssue2948402();
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
BOOST_LOG(rdInfoLog) << " Test Issue 2995724\n";
|
|
testIssue2995724();
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
BOOST_LOG(rdInfoLog) << " Testing a change of the depictor bond length\n";
|
|
testBondLengthChange();
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
BOOST_LOG(rdInfoLog) << " Test Issue 3122141\n";
|
|
testIssue3122141();
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
BOOST_LOG(rdInfoLog) << " Test Issue 3135833\n";
|
|
testIssue3135833();
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
BOOST_LOG(rdInfoLog) << " Test Issue 3487469\n";
|
|
testIssue3487469();
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
BOOST_LOG(rdInfoLog) << " Test GitHub Issue 8\n";
|
|
testGitHubIssue8();
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
BOOST_LOG(rdInfoLog) << " Test GitHub Issue 78\n";
|
|
testGitHubIssue78();
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
BOOST_LOG(rdInfoLog) << " Test GitHub Issue 910\n";
|
|
testGitHubIssue910();
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
BOOST_LOG(rdInfoLog) << " Test GitHub Issue 1073\n";
|
|
testGitHubIssue1073();
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
BOOST_LOG(rdInfoLog) << " testConstrainedCoords\n";
|
|
testConstrainedCoords();
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
BOOST_LOG(rdInfoLog)
|
|
<< " Test GitHub Issue 1112: Bad coordinate generation for H2\n";
|
|
testGitHubIssue1112();
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
BOOST_LOG(rdInfoLog) << " Test Issue 2303566\n";
|
|
testIssue2303566();
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
BOOST_LOG(rdInfoLog) << " Test GitHub Issue 1286: "
|
|
"GenerateDepictionMatching2DStructure isn't matching "
|
|
"2D structure\n";
|
|
testGitHubIssue1286();
|
|
BOOST_LOG(rdInfoLog)
|
|
<< "***********************************************************\n";
|
|
testGithub1691();
|
|
testGithub2027();
|
|
testGenerate2DDepictionRefPatternMatchVect();
|
|
testGenerate2DDepictionAllowRGroupsOrig();
|
|
testGenerate2DDepictionAllowRGroups();
|
|
testNormalizeStraighten();
|
|
testValidRingSystemTemplates();
|
|
|
|
return (0);
|
|
}
|