RDKit
Open-source cheminformatics and machine learning.
Loading...
Searching...
No Matches
SubstructMatch.h
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2025 Greg Landrum and other RDKit contributors
3//
4// @@ All Rights Reserved @@
5// This file is part of the RDKit.
6// The contents are covered by the terms of the BSD license
7// which is included in the file license.txt, found at the root
8// of the RDKit source tree.
9//
10#include <RDGeneral/export.h>
11#ifndef RD_SUBSTRUCTMATCH_H
12#define RD_SUBSTRUCTMATCH_H
13
14// std bits
15#include <vector>
16
17#include <unordered_set>
18#include <functional>
19#include <unordered_map>
20#include <cstdint>
21#include <string>
22#include <span>
23
24#include <boost/dynamic_bitset.hpp>
25#if BOOST_VERSION >= 107100
26#define RDK_INTERNAL_BITSET_HAS_HASH
27#endif
28
30
31namespace RDKit {
32class ROMol;
33class Atom;
34class Bond;
36class MolBundle;
37
38//! \brief used to return matches from substructure searching,
39//! The format is (queryAtomIdx, molAtomIdx)
40typedef std::vector<std::pair<int, int>> MatchVectType;
41
43 bool useChirality = false; //!< Use chirality in determining whether or not
44 //!< atoms/bonds match
45 bool useEnhancedStereo = false; //!< Use enhanced stereochemistry in
46 //!< determining whether atoms/bonds match
47 bool aromaticMatchesConjugated = false; //!< Aromatic and conjugated bonds
48 //!< match each other
49 bool useQueryQueryMatches = false; //!< Consider query-query matches, not
50 //!< just simple matches
51 bool useGenericMatchers = false; //!< Looks for generic atoms in the query
52 //!< and uses them as part of the matching
53 bool recursionPossible = true; //!< Allow recursive queries
54 bool uniquify = true; //!< uniquify (by atom index) match results
55 unsigned int maxMatches = 1000; //!< maximum number of matches to return
56 int numThreads = 1; //!< number of threads to use when multi-threading
57 //!< is possible. 0 selects the number of
58 //!< concurrent threads supported by the hardware
59 //!< negative values are added to the number of
60 //!< concurrent threads supported by the hardware
61 std::vector<std::string> atomProperties; //!< atom properties that must be
62 //!< equivalent in order to match
63 std::vector<std::string> bondProperties; //!< bond properties that must be
64 //!< equivalent in order to match
65 std::function<bool(const ROMol &mol,
66 std::span<const unsigned int> match)>
67 extraFinalCheck; //!< a function to be called at the end to validate a
68 //!< match
69 unsigned int maxRecursiveMatches =
70 1000; //!< maximum number of matches that the recursive substructure
71 //!< matching should return
73 false; //!< If set, query atoms and bonds with specified stereochemistry
74 //!< will match atoms and bonds with unspecified stereochemistry
75 bool aromaticMatchesSingleOrDouble = false; //!< Aromatic bonds match single
76 //!< or double bonds
77 std::function<bool(const Atom &queryAtom, const Atom &molAtom)>
78 extraAtomCheck; //!< a function to be called after other atom comparisons
79 //!< have passed
81 false; //!< if set, only the extraAtomCheck will be used to determine
82 //!< whether or not atoms match
83 std::function<bool(const Bond &queryBond, const Bond &molBond)>
84 extraBondCheck; //!< a function to be called after other bond comparisons
85 //!< have passed
87 false; //!< if set, only the extraBondCheck will be used to determine
88 //!< whether or not bonds match
90};
91
93 SubstructMatchParameters &params, const std::string &json);
95 const SubstructMatchParameters &params);
96
97//! Find a substructure match for a query in a molecule
98/*!
99 \param mol The ROMol to be searched
100 \param query The query ROMol
101 \param matchParams Parameters controlling the matching
102
103 \return The matches, if any
104
105*/
107 const ROMol &mol, const ROMol &query,
109
110//! Count substructure matches for a query in a molecule without materializing
111//! the full match vectors.
112/*!
113 \param mol The ROMol to be searched
114 \param query The query ROMol
115 \param matchParams Parameters controlling the matching
116
117 \return The number of matches found (capped by params.maxMatches)
118
119*/
121 const ROMol &mol, const ROMol &query,
123
124//! Find all substructure matches for a query in a ResonanceMolSupplier object
125/*!
126 \param resMolSuppl The ResonanceMolSupplier object to be searched
127 \param query The query ROMol
128 \param matchParams Parameters controlling the matching
129
130 \return The matches, if any
131
132*/
134 ResonanceMolSupplier &resMolSuppl, const ROMol &query,
136
138 const MolBundle &bundle, const ROMol &query,
141 const ROMol &mol, const MolBundle &query,
144 const MolBundle &bundle, const MolBundle &query,
146
147//! Find a substructure match for a query
148/*!
149 \param mol The object to be searched
150 \param query The query
151 \param matchVect Used to return the match
152 (pre-existing contents will be deleted)
153 \param recursionPossible flags whether or not recursive matches are allowed
154 \param useChirality use atomic CIP codes as part of the comparison
155 \param useQueryQueryMatches if set, the contents of atom and bond queries
156 will be used as part of the matching
157
158 \return whether or not a match was found
159
160*/
161template <typename T1, typename T2>
162bool SubstructMatch(T1 &mol, const T2 &query, MatchVectType &matchVect,
163 bool recursionPossible = true, bool useChirality = false,
164 bool useQueryQueryMatches = false) {
166 params.recursionPossible = recursionPossible;
167 params.useChirality = useChirality;
168 params.useQueryQueryMatches = useQueryQueryMatches;
169 params.maxMatches = 1;
170 std::vector<MatchVectType> matchVects = SubstructMatch(mol, query, params);
171 if (matchVects.size()) {
172 matchVect = matchVects.front();
173 } else {
174 matchVect.clear();
175 }
176 return matchVect.size() != 0;
177};
178
179//! Find all substructure matches for a query
180/*!
181 \param mol The object to be searched
182 \param query The query
183 \param matchVect Used to return the matches
184 (pre-existing contents will be deleted)
185 \param uniquify Toggles uniquification (by atom index) of the results
186 \param recursionPossible flags whether or not recursive matches are allowed
187 \param useChirality use atomic CIP codes as part of the comparison
188 \param useQueryQueryMatches if set, the contents of atom and bond queries
189 will be used as part of the matching
190 \param maxMatches The maximum number of matches that will be returned.
191 In high-symmetry cases with medium-sized molecules, it is
192 very
193 easy to end up with a combinatorial explosion in the
194 number of
195 possible matches. This argument prevents that from having
196 unintended consequences
197
198 \return the number of matches found
199
200*/
201template <typename T1, typename T2>
202unsigned int SubstructMatch(T1 &mol, const T2 &query,
203 std::vector<MatchVectType> &matchVect,
204 bool uniquify = true, bool recursionPossible = true,
205 bool useChirality = false,
206 bool useQueryQueryMatches = false,
207 unsigned int maxMatches = 1000,
208 int numThreads = 1) {
210 params.uniquify = uniquify;
211 params.recursionPossible = recursionPossible;
212 params.useChirality = useChirality;
213 params.useQueryQueryMatches = useQueryQueryMatches;
214 params.maxMatches = maxMatches;
215 params.numThreads = numThreads;
216 matchVect = SubstructMatch(mol, query, params);
217 return static_cast<unsigned int>(matchVect.size());
218};
219
220// ----------------------------------------------
221//
222// find one match in ResonanceMolSupplier object
223//
224template <>
225inline bool SubstructMatch(ResonanceMolSupplier &resMolSupplier,
226 const ROMol &query, MatchVectType &matchVect,
227 bool recursionPossible, bool useChirality,
228 bool useQueryQueryMatches) {
230 params.recursionPossible = recursionPossible;
231 params.useChirality = useChirality;
232 params.useQueryQueryMatches = useQueryQueryMatches;
233 params.maxMatches = 1;
234 std::vector<MatchVectType> matchVects =
235 SubstructMatch(resMolSupplier, query, params);
236 if (matchVects.size()) {
237 matchVect = matchVects.front();
238 } else {
239 matchVect.clear();
240 }
241 return matchVect.size() != 0;
242}
243
244template <>
245inline unsigned int SubstructMatch(ResonanceMolSupplier &resMolSupplier,
246 const ROMol &query,
247 std::vector<MatchVectType> &matchVect,
248 bool uniquify, bool recursionPossible,
249 bool useChirality, bool useQueryQueryMatches,
250 unsigned int maxMatches, int numThreads) {
252 params.uniquify = uniquify;
253 params.recursionPossible = recursionPossible;
254 params.useChirality = useChirality;
255 params.useQueryQueryMatches = useQueryQueryMatches;
256 params.maxMatches = maxMatches;
257 params.numThreads = numThreads;
258 matchVect = SubstructMatch(resMolSupplier, query, params);
259 return static_cast<unsigned int>(matchVect.size());
260};
261
262//! Class used as a final step to confirm whether or not a given atom->atom
263//! mapping is a valid substructure match.
265 public:
266 MolMatchFinalCheckFunctor(const ROMol &query, const ROMol &mol,
267 const SubstructMatchParameters &ps);
268
269 bool operator()(const std::uint32_t q_c[], const std::uint32_t m_c[]);
270
271 private:
272 const ROMol &d_query;
273 const ROMol &d_mol;
274 const SubstructMatchParameters &d_params;
275 std::unordered_map<unsigned int, StereoGroup const *> d_molStereoGroups;
276#ifdef RDK_INTERNAL_BITSET_HAS_HASH
277 // Boost 1.71 added support for std::hash with dynamic_bitset.
278 using HashedStorageType = boost::dynamic_bitset<>;
279#else
280 // otherwise we use a less elegant solution
281 using HashedStorageType = std::string;
282#endif
283 std::unordered_set<HashedStorageType> matchesSeen;
284};
285
287 int d_refConfId = -1;
289 double d_tol2 = 1e-8; //< squared distance tolerance
290 AtomCoordsMatchFunctor(int refConfId = -1, int queryConfId = -1,
291 double tol = 1e-4)
292 : d_refConfId(refConfId), d_queryConfId(queryConfId), d_tol2(tol * tol){};
293
294 bool operator()(const Atom &queryAtom, const Atom &targetAtom) const;
295};
296
297} // namespace RDKit
298
299#endif
Defines the class StereoGroup which stores relationships between the absolute configurations of atoms...
The class for representing atoms.
Definition Atom.h:75
class for representing a bond
Definition Bond.h:48
MolBundle contains a collection of related ROMols.
Definition MolBundle.h:59
MolMatchFinalCheckFunctor(const ROMol &query, const ROMol &mol, const SubstructMatchParameters &ps)
bool operator()(const std::uint32_t q_c[], const std::uint32_t m_c[])
#define RDKIT_SUBSTRUCTMATCH_EXPORT
Definition export.h:721
Std stuff.
RDKIT_SUBSTRUCTMATCH_EXPORT unsigned int SubstructMatchCount(const ROMol &mol, const ROMol &query, const SubstructMatchParameters &params=SubstructMatchParameters())
std::vector< std::pair< int, int > > MatchVectType
used to return matches from substructure searching, The format is (queryAtomIdx, molAtomIdx)
RDKIT_SUBSTRUCTMATCH_EXPORT std::vector< MatchVectType > SubstructMatch(const ROMol &mol, const ROMol &query, const SubstructMatchParameters &params=SubstructMatchParameters())
Find a substructure match for a query in a molecule.
RDKIT_SUBSTRUCTMATCH_EXPORT void updateSubstructMatchParamsFromJSON(SubstructMatchParameters &params, const std::string &json)
RDKIT_SUBSTRUCTMATCH_EXPORT std::string substructMatchParamsToJSON(const SubstructMatchParameters &params)
bool operator()(const Atom &queryAtom, const Atom &targetAtom) const
AtomCoordsMatchFunctor(int refConfId=-1, int queryConfId=-1, double tol=1e-4)
std::function< bool(const ROMol &mol, std::span< const unsigned int > match)> extraFinalCheck
unsigned int maxMatches
maximum number of matches to return
bool uniquify
uniquify (by atom index) match results
std::vector< std::string > atomProperties
std::vector< std::string > bondProperties
bool recursionPossible
Allow recursive queries.
unsigned int maxRecursiveMatches
matching should return
std::function< bool(const Atom &queryAtom, const Atom &molAtom)> extraAtomCheck
std::function< bool(const Bond &queryBond, const Bond &molBond)> extraBondCheck