/src/rdkit/Code/GraphMol/SmilesParse/SmilesParse.h
Line | Count | Source |
1 | | // |
2 | | // Copyright (C) 2001-2021 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_SMILESPARSE_H |
12 | | #define RD_SMILESPARSE_H |
13 | | |
14 | | #include <GraphMol/SanitException.h> |
15 | | #include <string> |
16 | | #include <exception> |
17 | | #include <map> |
18 | | #include <memory> |
19 | | |
20 | | namespace RDKit { |
21 | | class RWMol; |
22 | | class Atom; |
23 | | class Bond; |
24 | | |
25 | | namespace SmilesParse { |
26 | | class RDKIT_SMILESPARSE_EXPORT SmilesParseException : public std::exception { |
27 | | public: |
28 | 820 | SmilesParseException(const char *msg) : _msg(msg) {} |
29 | 863 | SmilesParseException(const std::string msg) : _msg(msg) {} |
30 | 0 | const char *what() const noexcept override { return _msg.c_str(); } |
31 | 1.68k | ~SmilesParseException() noexcept override = default; |
32 | | |
33 | | private: |
34 | | std::string _msg; |
35 | | }; |
36 | | |
37 | | } // namespace SmilesParse |
38 | | |
39 | | namespace v2 { |
40 | | namespace SmilesParse { |
41 | | using RDKit::SmilesParse::SmilesParseException; |
42 | | |
43 | | struct RDKIT_SMILESPARSE_EXPORT SmilesParserParams { |
44 | | bool sanitize = true; /**< sanitize the molecule after building it */ |
45 | | bool allowCXSMILES = true; /**< recognize and parse CXSMILES*/ |
46 | | bool strictCXSMILES = |
47 | | true; /**< throw an exception if the CXSMILES parsing fails */ |
48 | | bool parseName = true; /**< parse (and set) the molecule name as well */ |
49 | | bool removeHs = true; /**< remove Hs after constructing the molecule */ |
50 | | bool skipCleanup = false; /**< skip the final cleanup stage */ |
51 | | bool debugParse = false; /**< enable debugging in the SMILES parser*/ |
52 | | std::map<std::string, std::string> |
53 | | replacements{}; /**< allows SMILES "macros" */ |
54 | | }; |
55 | | |
56 | | struct RDKIT_SMILESPARSE_EXPORT SmartsParserParams { |
57 | | bool allowCXSMILES = true; /**< recognize and parse CXSMILES extensions */ |
58 | | bool strictCXSMILES = |
59 | | true; /**< throw an exception if the CXSMILES parsing fails */ |
60 | | bool parseName = true; /**< parse (and set) the molecule name as well */ |
61 | | bool mergeHs = |
62 | | false; /**< toggles merging H atoms in the SMARTS into neighboring atoms*/ |
63 | | bool skipCleanup = false; /**< skip the final cleanup stage */ |
64 | | bool debugParse = false; /**< enable debugging in the SMARTS parser*/ |
65 | | std::map<std::string, std::string> |
66 | | replacements{}; /**< allows SMARTS "macros" */ |
67 | | }; |
68 | | |
69 | | RDKIT_SMILESPARSE_EXPORT std::unique_ptr<RDKit::RWMol> MolFromSmiles( |
70 | | const std::string &smi, |
71 | | const SmilesParserParams ¶ms = SmilesParserParams()); |
72 | | RDKIT_SMILESPARSE_EXPORT std::unique_ptr<RDKit::RWMol> MolFromSmarts( |
73 | | const std::string &sma, |
74 | | const SmartsParserParams ¶ms = SmartsParserParams()); |
75 | | |
76 | | RDKIT_SMILESPARSE_EXPORT std::unique_ptr<RDKit::Atom> AtomFromSmiles( |
77 | | const std::string &smi); |
78 | | RDKIT_SMILESPARSE_EXPORT std::unique_ptr<RDKit::Bond> BondFromSmiles( |
79 | | const std::string &smi); |
80 | | |
81 | | RDKIT_SMILESPARSE_EXPORT std::unique_ptr<RDKit::Atom> AtomFromSmarts( |
82 | | const std::string &sma); |
83 | | RDKIT_SMILESPARSE_EXPORT std::unique_ptr<RDKit::Bond> BondFromSmarts( |
84 | | const std::string &sma); |
85 | | |
86 | | } // namespace SmilesParse |
87 | | } // namespace v2 |
88 | | |
89 | | inline namespace v1 { |
90 | | using RDKit::SmilesParse::SmilesParseException; |
91 | | |
92 | | struct RDKIT_SMILESPARSE_EXPORT SmilesParserParams { |
93 | | int debugParse = 0; /**< enable debugging in the SMILES parser*/ |
94 | | bool sanitize = true; /**< sanitize the molecule after building it */ |
95 | | std::map<std::string, std::string> *replacements = |
96 | | nullptr; /**< allows SMILES "macros" */ |
97 | | bool allowCXSMILES = true; /**< recognize and parse CXSMILES*/ |
98 | | bool strictCXSMILES = |
99 | | true; /**< throw an exception if the CXSMILES parsing fails */ |
100 | | bool parseName = true; /**< parse (and set) the molecule name as well */ |
101 | | bool removeHs = true; /**< remove Hs after constructing the molecule */ |
102 | | bool skipCleanup = false; /**< skip the final cleanup stage */ |
103 | | }; |
104 | | |
105 | | struct RDKIT_SMILESPARSE_EXPORT SmartsParserParams { |
106 | | int debugParse = 0; /**< enable debugging in the SMARTS parser*/ |
107 | | std::map<std::string, std::string> *replacements = |
108 | | nullptr; /**< allows SMARTS "macros" */ |
109 | | bool allowCXSMILES = true; /**< recognize and parse CXSMILES extensions */ |
110 | | bool strictCXSMILES = |
111 | | true; /**< throw an exception if the CXSMILES parsing fails */ |
112 | | bool parseName = true; /**< parse (and set) the molecule name as well */ |
113 | | bool mergeHs = |
114 | | false; /**< toggles merging H atoms in the SMARTS into neighboring atoms*/ |
115 | | bool skipCleanup = false; /**< skip the final cleanup stage */ |
116 | | }; |
117 | | |
118 | | inline RDKit::RWMol *SmilesToMol(const std::string &smi, |
119 | 0 | const SmilesParserParams &ps) { |
120 | 0 | RDKit::v2::SmilesParse::SmilesParserParams v2ps; |
121 | 0 | v2ps.debugParse = ps.debugParse; |
122 | 0 | v2ps.sanitize = ps.sanitize; |
123 | 0 |
|
124 | 0 | if (ps.replacements) { |
125 | 0 | v2ps.replacements = *ps.replacements; |
126 | 0 | } |
127 | 0 | v2ps.allowCXSMILES = ps.allowCXSMILES; |
128 | 0 | v2ps.strictCXSMILES = ps.strictCXSMILES; |
129 | 0 | v2ps.parseName = ps.parseName; |
130 | 0 | v2ps.removeHs = ps.removeHs; |
131 | 0 | v2ps.skipCleanup = ps.skipCleanup; |
132 | 0 | return RDKit::v2::SmilesParse::MolFromSmiles(smi, v2ps).release(); |
133 | 0 | } |
134 | | |
135 | 0 | inline Atom *SmilesToAtom(const std::string &smi) { |
136 | 0 | auto res = RDKit::v2::SmilesParse::AtomFromSmiles(smi).release(); |
137 | 0 | return res; |
138 | 0 | } |
139 | | |
140 | 0 | inline Bond *SmilesToBond(const std::string &smi) { |
141 | 0 | return RDKit::v2::SmilesParse::BondFromSmiles(smi).release(); |
142 | 0 | } |
143 | | |
144 | | //! Construct a molecule from a SMILES string |
145 | | /*! |
146 | | \param smi the SMILES to convert |
147 | | \param debugParse toggles verbose debugging information from the parser |
148 | | \param sanitize toggles H removal and sanitization of the molecule |
149 | | \param replacements a string->string map of replacement strings. See below |
150 | | for more information about replacements. |
151 | | |
152 | | \return a pointer to the new molecule; the caller is responsible for free'ing |
153 | | this. |
154 | | |
155 | | The optional replacements map can be used to do string substitution of |
156 | | abbreviations |
157 | | in the input SMILES. The set of substitutions is repeatedly looped through |
158 | | until |
159 | | the string no longer changes. It is the responsibility of the caller to make |
160 | | sure |
161 | | that substitutions results in legal and sensible SMILES. |
162 | | |
163 | | Examples of substitutions: |
164 | | \code |
165 | | CC{Q}C with {"{Q}":"OCCO"} -> CCOCCOC |
166 | | C{A}C{Q}C with {"{Q}":"OCCO", "{A}":"C1(CC1)"} -> CC1(CC1)COCCOC |
167 | | C{A}C{Q}C with {"{Q}":"{X}CC{X}", "{A}":"C1CC1", "{X}":"N"} -> CC1CC1CNCCNC |
168 | | \endcode |
169 | | |
170 | | */ |
171 | | inline RWMol *SmilesToMol( |
172 | | const std::string &smi, int debugParse = 0, bool sanitize = true, |
173 | 311 | std::map<std::string, std::string> *replacements = nullptr) { |
174 | 311 | RDKit::v2::SmilesParse::SmilesParserParams params; |
175 | 311 | params.debugParse = debugParse; |
176 | 311 | if (replacements) { |
177 | 0 | params.replacements = *replacements; |
178 | 0 | } |
179 | 311 | if (sanitize) { |
180 | 223 | params.sanitize = true; |
181 | 223 | params.removeHs = true; |
182 | 223 | } else { |
183 | 88 | params.sanitize = false; |
184 | 88 | params.removeHs = false; |
185 | 88 | } |
186 | 311 | return RDKit::v2::SmilesParse::MolFromSmiles(smi, params).release(); |
187 | 311 | }; |
188 | | |
189 | | inline RWMol *SmartsToMol(const std::string &sma, |
190 | 0 | const SmartsParserParams &ps) { |
191 | 0 | RDKit::v2::SmilesParse::SmartsParserParams v2ps; |
192 | 0 | v2ps.debugParse = ps.debugParse; |
193 | 0 | if (ps.replacements) { |
194 | 0 | v2ps.replacements = *ps.replacements; |
195 | 0 | } |
196 | 0 | v2ps.allowCXSMILES = ps.allowCXSMILES; |
197 | 0 | v2ps.strictCXSMILES = ps.strictCXSMILES; |
198 | 0 | v2ps.parseName = ps.parseName; |
199 | 0 | v2ps.mergeHs = ps.mergeHs; |
200 | 0 | v2ps.skipCleanup = ps.skipCleanup; |
201 | 0 |
|
202 | 0 | return RDKit::v2::SmilesParse::MolFromSmarts(sma, v2ps).release(); |
203 | 0 | } |
204 | | |
205 | | //! Construct a molecule from a SMARTS string |
206 | | /*! |
207 | | \param sma the SMARTS to convert |
208 | | \param debugParse toggles verbose debugging information from the parser |
209 | | \param mergeHs toggles merging H atoms in the SMARTS into neighboring |
210 | | atoms |
211 | | \param replacements a string->string map of replacement strings. |
212 | | \see SmilesToMol for more information about replacements |
213 | | |
214 | | \return a pointer to the new molecule; the caller is responsible for free'ing |
215 | | this. |
216 | | */ |
217 | | inline RWMol *SmartsToMol( |
218 | | const std::string &sma, int debugParse = 0, bool mergeHs = false, |
219 | 33.6k | std::map<std::string, std::string> *replacements = nullptr) { |
220 | 33.6k | RDKit::v2::SmilesParse::SmartsParserParams ps; |
221 | 33.6k | ps.debugParse = debugParse; |
222 | 33.6k | ps.mergeHs = mergeHs; |
223 | 33.6k | if (replacements) { |
224 | 0 | ps.replacements = *replacements; |
225 | 0 | } |
226 | 33.6k | return RDKit::v2::SmilesParse::MolFromSmarts(sma, ps).release(); |
227 | 33.6k | }; |
228 | | |
229 | 0 | inline Atom *SmartsToAtom(const std::string &sma) { |
230 | 0 | return RDKit::v2::SmilesParse::AtomFromSmarts(sma).release(); |
231 | 0 | } |
232 | 0 | inline Bond *SmartsToBond(const std::string &sma) { |
233 | 0 | return RDKit::v2::SmilesParse::BondFromSmarts(sma).release(); |
234 | 0 | } |
235 | | } // namespace v1 |
236 | | |
237 | | inline std::unique_ptr<RDKit::RWMol> operator""_smiles(const char *text, |
238 | 0 | size_t len) { |
239 | 0 | std::string smi(text, len); |
240 | 0 | try { |
241 | 0 | return v2::SmilesParse::MolFromSmiles(smi); |
242 | 0 | } catch (const RDKit::MolSanitizeException &) { |
243 | 0 | return nullptr; |
244 | 0 | } |
245 | 0 | } |
246 | | inline std::unique_ptr<RDKit::RWMol> operator""_smarts(const char *text, |
247 | 0 | size_t len) { |
248 | 0 | std::string smi(text, len); |
249 | 0 | return v2::SmilesParse::MolFromSmarts(smi); |
250 | 0 | } |
251 | | |
252 | | } // namespace RDKit |
253 | | |
254 | | #endif |