When converting molecules with wavy bonds (Bond::STEREOANY on double
bonds) through InChI and back, the stereo information was silently
dropped. This affected any workflow using InChI roundtrips for
canonicalization (e.g. with -SUU flag).
Two bugs in External/INCHI-API/inchi.cpp:
Reverse path (InchiToMol): The stereo0D processing loop skipped
INCHI_PARITY_UNDEFINED entries before they could reach the double bond
handler. The handler already had an else clause that correctly sets
Bond::STEREOANY, but it was never reached. Fix: only skip
INCHI_PARITY_NONE at the top level, and add a guard in the Tetrahedral
case to prevent UNDEFINED/UNKNOWN from incorrectly setting chirality.
Forward path (MolToInchi): STEREOANY double bonds were only handled by
collapsing the coordinates — InChI then produced no stereo annotation
under -SUU. Fix: also emit a stereo0D entry with INCHI_PARITY_UNKNOWN
parity so InChI's -SUU output correctly carries the "stereo unknown"
designation. StereoAtoms may be cleared for STEREOANY, so we locate
the two outer neighbors by iterating bonds.
New test testStereoAnyRoundtrip in External/INCHI-API/test.cpp covers
9 representative cases (Schiff base, oxime, cinnamic acid, chalcone,
crotonaldehyde, tamoxifen-like, retinal-like, plus two molecules with
a chiral center adjacent to the wavy bond).
Counts in rdkit/Chem/UnitTestInchi.py shift by 1 (689 same, 492
reasonable) because the new STEREOANY emission produces a more
accurate roundtrip for one entry in the test inventory.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
MolToInchi has called MolOps::Kekulize(*m, false) for years, but PR #9125 changed the default traversal to canonical=true. That pulls rankFragmentAtoms() and the canonicalization path into the InChI conversion even though the tested InChI outputs stay the same.
Validation:
- rdkit.Chem.UnitTestInchi passed before and after this change on upstream/master (18 tests, OK in both runs).
- No InChI output drift was observed between stock and patched builds on Regress/Data/mols.1000.sdf.gz, rdkit/Chem/test_data/pubchem-hard-set.sdf.gz, or the atom-order regression molecules added in Code/GraphMol/catch_graphmol.cpp.
Performance:
- Release_2026_03_1 Python MolToInchi on Regress/Data/mols.1000.sdf.gz improved from 0.40712s to 0.38871s median (-4.52%).
- Release_2026_03_1 rdinchi MolToInchi on the same dataset improved from 0.39755s to 0.37814s median (-4.88%).
- Release_2026_03_1 standalone C++ MolToInchi on /tmp/mols.1000.sdf improved from 7.66775s to 7.03474s wall time (-8.26%), from 20.57B to 19.04B cycles (-7.46%), and from 121.78M to 114.05M cache misses (-6.35%).
* Add MolFromInchiAndAuxInfo to restore original atom order from AuxInfo
Add a new function that reconstructs molecules from InChI + AuxInfo strings,
restoring the original atom ordering and 2D/3D coordinates from the /N: and
/rC: AuxInfo layers. Includes comprehensive tests for round-tripping, stereo
preservation, coordinate restoration, edge cases, and multi-fragment molecules.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Update rdkit/Chem/UnitTestInchi.py
Co-authored-by: Greg Landrum <greg.landrum@gmail.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Greg Landrum <greg.landrum@gmail.com>
isascii() (which is the standard) or __isascii(), but it guesses wrong for
Emscripten builds (which I do during sketcher compilation). This change
passes -D__isascii=isascii when building InChi,
which means that the wrong guess will still wind up with the right
function name.
* move mol weight and formula calculators to MolOps and refactor them a bit.
The descriptors are still there and should remain.
* remove other unnecessary dependencies on Descriptors
* Update adapter.cpp
Co-authored-by: Paolo Tosco <paolo.tosco.mail@gmail.com>
---------
Co-authored-by: Paolo Tosco <paolo.tosco.mail@gmail.com>
* suppress a bunch of warnings from third-party code
get rid of one warning in RDKit code
* corrections
* fix the maeparser flags
* remove some more inchi warnings with clang
* External/INCHI-API: drop unnecessary mutex
A mutex was introduced in 6cfd34 from 2012 around all InChI library
calls, and InChI v1.05 release notes from 2017 announce that they fixed
race conditions to support multithreading.
We find that the InChI library mutex is no longer necessary with v1.05
and this patch removes it, which enables rdkit users to concurrently
call InChI-related methods.
This patch also updates the InChI multithreading tests to cover
`MolBlockToInchi`, so we have test coverage of concurrently making all
InChI calls.
I ran `testInchi` under asan 200x and all runs passed cleanly. I was
unable to configure the build toolchain with msan or tsan, so it is
unclear to me if those sanitizers would flag any issues.
* External/INCHI-API: add second multithreading test
This test covers case where immediate concurrent usage of the InChI
library leads to memory corruption.
* remove ASAN workaround (not needed for InChI 1.06)
clang-format run
update inchi version to 1.06 in docs
Co-authored-by: Jin Pan <jinxp1@gmail.com>
* - fix non-threaded *nix builds that currently fail because
boost flyweight introduces a dependency on pthreads
- make sure that mutexes and futures are only used when
RDK_BUILD_THREADSAFE_SSS is ON
- fix SubstructMatch failing test when RDK_BUILD_THREADSAFE_SSS is OFF
due to misplaced #ifdef's
- rename RDK_TEST_MULTITHREADED to RDK_THREADSAFE_SSS in inchi.cpp
(which is not a test)
* - the limitexternal Linux build is now single-threaded so we make
sure single-threaded builds do not break in the future
(suggestion from Greg)
* reverted unnecessary change to Code/GraphMol/FileParsers/testMultithreadedMolSupplier.cpp
Co-authored-by: Paolo Tosco <paolo.tosco@novartis.com>
* cleanup a bunch of g++ warnings
* make it work with clang
* remove some additional warnings based on CI builds
* fix that version number
* stop being verbose when building
* remove include from headers
* update implementation files
* completely remove BOOST_FOREACH (#7)
* convert those changes to use auto
* get rid of all usage of BOOST_FOREACH
Co-authored-by: Greg Landrum <greg.landrum@gmail.com>
The InChI Trust website has changed the locations of the documentation and FAQ for the InChI software APIs.
I have updated the link for the FAQ, but unfortunately the User Guide is no longer directly linkable, but is available for download as part of a zip file of documentation from the main downloads page.
* Fixes#3365
* update expected inchi results
Note that this actually increases the number of failures with one of the tests.
That's because I believe the expected InChIs to be wrong and these new results to be correct.
* run clang-tidy with modernize-use-default-member-init
* results from modernize-use-emplace
* one uniform initialization per line
otherwise SWIG is unhappy
Co-authored-by: Brian Kelley <fustigator@gmail.com>
* change minimal cmake version to a consistent 3.5
* progress towards a cleanup
* get the basic python deps working
* two more libs
* another round of changes
all tests pass at this point
* next round of changes
all tests pass at this point
* close to done
all tests pass
* very close
* almost done
* shift the RDBoost dependencies around a bit
* remove an extraneous python linkage
this is trying to get the mac builds working again
* Only link to python if it was built shared (#3091)
* change in response to review
Co-Authored-By: Ric <ricrogz@users.noreply.github.com>
* move that suppression of the maybe-uninitialized warning to BoostStartInclude.h
Co-authored-by: Brian Kelley <fustigator@gmail.com>
Co-authored-by: Ric <ricrogz@users.noreply.github.com>
* run clang-tidy with readability-braces-around-statements
clang-format the results
clean up all the parts that clang-tidy-8 broke
* fix problem on windows
* do not use new on loggers
* del pointers in testDistGeom
* Update Dict hasNonPOD status on bulk update
* delete new Dicts in memtest1.cpp
* fixes in MolSuppliers and testFMCS
* PeriodicTable singleton as unique_ptr
* fix EEM_arrays leak
* fix leaks in testPBF
* fix ParamCollection leak in test UFF
* fix leaks in MMFF
* clear prop dict before read in in pickler
* fix leaks in testFreeSASA
* fix leaks in test3D
* modernize Dict.h & SmilesParse.cpp
* fix leaks in testQuery
* fix leaks in testCrystalFF
* fix leaks in cxsmilesTest
* fix leaks in Catalog & mol cat test
* fix leaks in ShapeUtils & tests
* fix leaks in testSubgraphs1
* fix leaks testFingerprintGenerators
* fix leaks in Catalog/FilterCatalog
* fix leaks in graphmolqueryTest
* these changes reduce bison parse leaks
* fixed leaks in testChirality.cpp
* fix leaks + 2 tests in testMolWriter
* fix 4m leaks in substructLibraryTest
* small improvements to molTautomerTest; still leaks
* fix leaks in testRGroupDecomp
* fix leaks in test; parser still leaks
* fix leaks in itertest
* fix 4m leaks in testDepictor
* fixes in smatest; still leaking due to parser
* fixes in testSLNParse; still leaking due to parser
* flex/bison: always add atoms with ownership; smarts error cleanup
* fix leaks in testReaction
* fix leaks in testSubstructMatch
* fix leaks in resMolSupplierTest
* fix leaks in testChemTransforms + bug in ChemTransforms
* fix leaks in testPickler
* fix leaks in testMolTransform
* fix leaks in testFragCatalog
* fix leak in testSLNParse. Still leaks due to Smiles
* fixed most leaks in testMolSupplier
* pre bison fix
* fix some atom & bond parse problems; others still fail
* bison smiles & smarts, atoms & bonds more or less fixed
* fix leaks in molopstest.cpp
* fix leaks in testFingerprints, MACCS.cpp & AtomPairs.cpp
* fix leaks in moldraw2Dtest1
* fix leaks in testDescriptors
* fix leaks in testInchi
* fix leaks in testUFFForceFieldHelpers
* fix leaks in hanoiTest & new_canon.h
* fix leaks in testMMFFForceField
* fix leaks in graphmolTest1
* fix leaks in testMMFFForceFieldHelpers
* fix leaks in testDistGeomHelpers
* fix leaks in testMolAlign
* initialize occupancy & temp facto with default values
* fix leak in TautomerTransform
* updated suppressions
* fix testStructChecker
* fix logging & py tests
* fix TautomerTransform class/struct issue
* remove misplaced delete in testSLNParse
* deinit in testAvalonLib1
* fix Avalon-triggered(?) bug in StructChecker/Pattern.cpp
* fix random testMolWriter/Supplier fails
- diversify output file names to avoid clashing.
- unify Writers close/destruct behavior.
- flushing/closing in tests.
* use reset in FFs Params.cpp
* comments on testMMFFForceField
* unrequired 'if's added to mol suppliers
* correct cast in FilterCatalog.h
* use unique_ptr in MACCS Patterns
* remove unrequred if in new_canon
* update & move suppressions
* this is a rough first pass, needs to be finished and is a strong argument for changing the names of some of the #defines that are currently used
* rationalize the rest of the #defines
add something to the release notes about this
* Fixes#1810
There's still a problem with stereo atoms (see the commented out test),
but this takes care of the basics and that's up next.
* clean up that last problematic bit.
Still needs all tests to run
* this seems to be a necessary workaround for problems with VS2017.
It's a bit ugly, but shouldn't have any performance impact, so I'm not
going to get too worked up.
* This set of changes alters what we get for some of the InChI test cases.
Adjust for that.
* boost::thread mostly gone... still need to get rid of once
everything compiles
* replace boost::call_once
* remove link-time dependency on boost::thread
* first pass at using async
* switch to using async everywhere