chython 2.19__cp313-cp313-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. chython/__init__.py +35 -0
  2. chython/_functions.py +95 -0
  3. chython/_java.py +57 -0
  4. chython/algorithms/__init__.py +18 -0
  5. chython/algorithms/_isomorphism.cp313-win_amd64.pyd +0 -0
  6. chython/algorithms/_isomorphism.pyx +189 -0
  7. chython/algorithms/_rings.cp313-win_amd64.pyd +0 -0
  8. chython/algorithms/_rings.pyx +478 -0
  9. chython/algorithms/aromatics/__init__.py +27 -0
  10. chython/algorithms/aromatics/_rules.py +124 -0
  11. chython/algorithms/aromatics/kekule.py +532 -0
  12. chython/algorithms/aromatics/test/__init__.py +18 -0
  13. chython/algorithms/aromatics/test/test_kekule.py +160 -0
  14. chython/algorithms/aromatics/test/test_thiele.py +263 -0
  15. chython/algorithms/aromatics/thiele.py +222 -0
  16. chython/algorithms/calculate2d/__init__.py +23 -0
  17. chython/algorithms/calculate2d/clean2d.js +1 -0
  18. chython/algorithms/calculate2d/molecule.py +191 -0
  19. chython/algorithms/calculate2d/reaction.py +75 -0
  20. chython/algorithms/conformers.py +106 -0
  21. chython/algorithms/depict.py +596 -0
  22. chython/algorithms/fingerprints/__init__.py +43 -0
  23. chython/algorithms/fingerprints/linear.py +202 -0
  24. chython/algorithms/fingerprints/morgan.py +132 -0
  25. chython/algorithms/fingerprints/test/__init__.py +18 -0
  26. chython/algorithms/fingerprints/test/test_linear.py +127 -0
  27. chython/algorithms/fingerprints/test/test_morgan.py +79 -0
  28. chython/algorithms/groups/__init__.py +212 -0
  29. chython/algorithms/groups/_functional.py +290 -0
  30. chython/algorithms/groups/_oxidations.py +70 -0
  31. chython/algorithms/groups/_protective.py +964 -0
  32. chython/algorithms/groups/_reactions.py +809 -0
  33. chython/algorithms/groups/_reductions.py +88 -0
  34. chython/algorithms/groups/_transformations.py +278 -0
  35. chython/algorithms/groups/test/__init__.py +18 -0
  36. chython/algorithms/groups/test/test_deprotection.py +108 -0
  37. chython/algorithms/groups/test/test_reactions.py +377 -0
  38. chython/algorithms/isomorphism.py +664 -0
  39. chython/algorithms/mapping/__init__.py +188 -0
  40. chython/algorithms/mapping/_groups.py +94 -0
  41. chython/algorithms/mapping/_reactions.py +72 -0
  42. chython/algorithms/mapping/attention.py +266 -0
  43. chython/algorithms/mapping/reconstruct.py +346 -0
  44. chython/algorithms/mcs.py +201 -0
  45. chython/algorithms/morgan.py +77 -0
  46. chython/algorithms/rings.py +178 -0
  47. chython/algorithms/smiles.py +597 -0
  48. chython/algorithms/standardize/__init__.py +30 -0
  49. chython/algorithms/standardize/_groups.py +958 -0
  50. chython/algorithms/standardize/_isomers.py +330 -0
  51. chython/algorithms/standardize/_metal_organics.py +189 -0
  52. chython/algorithms/standardize/_reagents.py +44 -0
  53. chython/algorithms/standardize/_salts.py +68 -0
  54. chython/algorithms/standardize/molecule.py +475 -0
  55. chython/algorithms/standardize/reaction.py +384 -0
  56. chython/algorithms/standardize/resonance.py +191 -0
  57. chython/algorithms/standardize/salts.py +128 -0
  58. chython/algorithms/standardize/saturation.py +373 -0
  59. chython/algorithms/standardize/test/__init__.py +18 -0
  60. chython/algorithms/standardize/test/test_canonicalize.py +66 -0
  61. chython/algorithms/standardize/test/test_groups.py +146 -0
  62. chython/algorithms/standardize/test/test_isomers.py +198 -0
  63. chython/algorithms/stereo.py +1215 -0
  64. chython/algorithms/tautomers/__init__.py +167 -0
  65. chython/algorithms/tautomers/_acid.py +59 -0
  66. chython/algorithms/tautomers/_base.py +116 -0
  67. chython/algorithms/tautomers/_keto_enol.py +107 -0
  68. chython/algorithms/tautomers/acid_base.py +208 -0
  69. chython/algorithms/tautomers/heteroarenes.py +103 -0
  70. chython/algorithms/tautomers/keto_enol.py +143 -0
  71. chython/algorithms/tautomers/test/__init__.py +18 -0
  72. chython/algorithms/tautomers/test/test_tautomers.py +80 -0
  73. chython/algorithms/test/__init__.py +18 -0
  74. chython/algorithms/test/test_isomorphism.py +58 -0
  75. chython/algorithms/test/test_smiles.py +76 -0
  76. chython/algorithms/x3dom.py +350 -0
  77. chython/containers/__init__.py +48 -0
  78. chython/containers/_pack_v2.cp313-win_amd64.pyd +0 -0
  79. chython/containers/_pack_v2.pyx +271 -0
  80. chython/containers/_unpack_v0v2.cp313-win_amd64.pyd +0 -0
  81. chython/containers/_unpack_v0v2.pyx +302 -0
  82. chython/containers/bonds.py +255 -0
  83. chython/containers/cgr.py +115 -0
  84. chython/containers/chimera.py +63 -0
  85. chython/containers/graph.py +199 -0
  86. chython/containers/molecule.py +817 -0
  87. chython/containers/query.py +71 -0
  88. chython/containers/rdkit.py +183 -0
  89. chython/containers/reaction.py +324 -0
  90. chython/containers/test/__init__.py +18 -0
  91. chython/containers/test/test_molecule.py +117 -0
  92. chython/containers/test/test_pack.py +60 -0
  93. chython/containers/test/test_rdkit.py +70 -0
  94. chython/containers/test/test_reaction.py +40 -0
  95. chython/exceptions.py +114 -0
  96. chython/files/MRVrw.py +532 -0
  97. chython/files/PDBrw.py +255 -0
  98. chython/files/RDFrw.py +309 -0
  99. chython/files/SDFrw.py +221 -0
  100. chython/files/__init__.py +30 -0
  101. chython/files/_convert.py +207 -0
  102. chython/files/_mapping.py +117 -0
  103. chython/files/_xyz.cp313-win_amd64.pyd +0 -0
  104. chython/files/_xyz.pyx +74 -0
  105. chython/files/daylight/__init__.py +24 -0
  106. chython/files/daylight/parser.py +157 -0
  107. chython/files/daylight/smarts.py +107 -0
  108. chython/files/daylight/smiles.py +260 -0
  109. chython/files/daylight/test/__init__.py +18 -0
  110. chython/files/daylight/test/test_daylight_smarts.py +289 -0
  111. chython/files/daylight/test/test_daylight_smiles.py +101 -0
  112. chython/files/daylight/test/test_parser.py +118 -0
  113. chython/files/daylight/test/test_tokenize.py +77 -0
  114. chython/files/daylight/tokenize.py +376 -0
  115. chython/files/libinchi/__init__.py +22 -0
  116. chython/files/libinchi/libinchi.dll +0 -0
  117. chython/files/libinchi/wrapper.py +554 -0
  118. chython/files/mdl/__init__.py +25 -0
  119. chython/files/mdl/emol.py +251 -0
  120. chython/files/mdl/erxn.py +67 -0
  121. chython/files/mdl/mol.py +186 -0
  122. chython/files/mdl/read.py +223 -0
  123. chython/files/mdl/rxn.py +67 -0
  124. chython/files/mdl/stereo.py +63 -0
  125. chython/files/mdl/write.py +201 -0
  126. chython/files/opsin.py +35 -0
  127. chython/files/test/__init__.py +0 -0
  128. chython/files/test/test_inchi.py +27 -0
  129. chython/files/test/test_mrv.py +47 -0
  130. chython/files/test/test_sdf_rdf.py +64 -0
  131. chython/files/test/test_xyz.py +20 -0
  132. chython/files/xyz.py +78 -0
  133. chython/periodictable/__init__.py +69 -0
  134. chython/periodictable/base/__init__.py +25 -0
  135. chython/periodictable/base/dynamic.py +149 -0
  136. chython/periodictable/base/element.py +451 -0
  137. chython/periodictable/base/groups.py +90 -0
  138. chython/periodictable/base/periods.py +46 -0
  139. chython/periodictable/base/query.py +473 -0
  140. chython/periodictable/base/vector.py +119 -0
  141. chython/periodictable/groupI.py +252 -0
  142. chython/periodictable/groupII.py +223 -0
  143. chython/periodictable/groupIII.py +1154 -0
  144. chython/periodictable/groupIV.py +210 -0
  145. chython/periodictable/groupIX.py +196 -0
  146. chython/periodictable/groupV.py +192 -0
  147. chython/periodictable/groupVI.py +183 -0
  148. chython/periodictable/groupVII.py +162 -0
  149. chython/periodictable/groupVIII.py +161 -0
  150. chython/periodictable/groupX.py +166 -0
  151. chython/periodictable/groupXI.py +164 -0
  152. chython/periodictable/groupXII.py +158 -0
  153. chython/periodictable/groupXIII.py +239 -0
  154. chython/periodictable/groupXIV.py +262 -0
  155. chython/periodictable/groupXV.py +276 -0
  156. chython/periodictable/groupXVI.py +457 -0
  157. chython/periodictable/groupXVII.py +324 -0
  158. chython/periodictable/groupXVIII.py +260 -0
  159. chython/periodictable/test/__init__.py +0 -0
  160. chython/periodictable/test/test_element.py +100 -0
  161. chython/reactor/__init__.py +24 -0
  162. chython/reactor/base.py +222 -0
  163. chython/reactor/reactor.py +177 -0
  164. chython/reactor/test/__init__.py +18 -0
  165. chython/reactor/test/test_reactor.py +40 -0
  166. chython/reactor/test/test_transformer.py +78 -0
  167. chython/reactor/transformer.py +72 -0
  168. chython/utils/__init__.py +50 -0
  169. chython/utils/free_wilson.py +114 -0
  170. chython/utils/grid.py +130 -0
  171. chython/utils/retro.py +139 -0
  172. chython-2.19.dist-info/METADATA +105 -0
  173. chython-2.19.dist-info/RECORD +175 -0
  174. chython-2.19.dist-info/WHEEL +4 -0
  175. chython-2.19.dist-info/licenses/LICENSE +165 -0
@@ -0,0 +1,958 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright 2021-2026 Ramil Nugmanov <nougmanoff@protonmail.com>
4
+ # This file is part of chython.
5
+ #
6
+ # chython is free software; you can redistribute it and/or modify
7
+ # it under the terms of the GNU Lesser General Public License as published by
8
+ # the Free Software Foundation; either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Lesser General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public License
17
+ # along with this program; if not, see <https://www.gnu.org/licenses/>.
18
+ #
19
+ from lazy_object_proxy import Proxy
20
+
21
+
22
+ def _rules():
23
+ """
24
+ rules without overlapping. these rules can match once to same set of atoms.
25
+ """
26
+ from ... import smarts
27
+ from ...containers import QueryContainer
28
+
29
+ rules = []
30
+
31
+ #
32
+ # A A
33
+ # | |
34
+ # P >> [P+]
35
+ # / | \ / | \
36
+ # A A A A A A
37
+ #
38
+ q = smarts('[P;D4;x0;z1]')
39
+ atom_fix = {1: (1, None)}
40
+ bonds_fix = ()
41
+ rules.append((q, atom_fix, bonds_fix, False))
42
+
43
+ #
44
+ # A H A A H A
45
+ # \ / \ / \ .. \ /
46
+ # B B >> B B
47
+ # / \ / \ / \ .. \
48
+ # A H A A H A
49
+ #
50
+ q = smarts('[B;z1:1]1[H;D2:3][B;z1:2][H;D2:4]1')
51
+ atom_fix = {}
52
+ bonds_fix = ((1, 3, 8), (2, 4, 8))
53
+ rules.append((q, atom_fix, bonds_fix, False))
54
+
55
+ # OGB DS
56
+ #
57
+ # O* A [O-] A
58
+ # \ / \ /
59
+ # N >> [N+]
60
+ # | ||
61
+ # C,N* C,N
62
+ #
63
+ q = smarts('[O;D1;z1][N;D3;z1][C,N;z1] |^1:0,2|')
64
+ atom_fix = {1: (-1, False), 2: (1, None), 3: (0, False)}
65
+ bonds_fix = ((2, 3, 2),)
66
+ rules.append((q, atom_fix, bonds_fix, False))
67
+
68
+ #
69
+ # | |
70
+ # O* -- S -- O* >> O=S=O
71
+ # | |
72
+ #
73
+ q = smarts('[O,S;D1;z1][S;D4;z1][O;D1;z1] |^1:0,2|')
74
+ atom_fix = {1: (0, False), 3: (0, False)}
75
+ bonds_fix = ((1, 2, 2), (2, 3, 2))
76
+ rules.append((q, atom_fix, bonds_fix, False))
77
+
78
+ #
79
+ # A A
80
+ # // //
81
+ # B - N >> B .. N
82
+ # \ \
83
+ # A A
84
+ #
85
+ q = smarts('[B]-[N;D3;z2]')
86
+ atom_fix = {}
87
+ bonds_fix = ((1, 2, 8),)
88
+ rules.append((q, atom_fix, bonds_fix, False))
89
+
90
+ #
91
+ # A A
92
+ # | |
93
+ # B = N - A >> B .. N - A
94
+ # | |
95
+ # A A
96
+ #
97
+ q = smarts('[B;z1,z2]-,=[N;D4;z1,z2]')
98
+ atom_fix = {}
99
+ bonds_fix = ((1, 2, 8),)
100
+ rules.append((q, atom_fix, bonds_fix, False))
101
+
102
+ #
103
+ # R2S - B >> R2S .. B
104
+ #
105
+ q = smarts('[B;z1]-[O,S;D3;z1]')
106
+ atom_fix = {}
107
+ bonds_fix = ((1, 2, 8),)
108
+ rules.append((q, atom_fix, bonds_fix, False))
109
+
110
+ #
111
+ # [B-] = [N+] >> B - N
112
+ #
113
+ q = smarts('[B;z2;-]=[N;D1,D2,D3;z2;+]')
114
+ atom_fix = {1: (1, None), 2: (-1, None)}
115
+ bonds_fix = ((1, 2, 1),)
116
+ rules.append((q, atom_fix, bonds_fix, False))
117
+
118
+ #
119
+ # [A-] A
120
+ # | |
121
+ # [A-] - [B+3] - [A-] >> A - [B-] - A
122
+ # | |
123
+ # [A-] A
124
+ #
125
+ q = smarts('[B;D4;z1;+3]([A;-])([A;-])([A;-])[A;-]')
126
+ atom_fix = {1: (-4, None), 2: (1, None), 3: (1, None), 4: (1, None), 5: (1, None)}
127
+ bonds_fix = ()
128
+ rules.append((q, atom_fix, bonds_fix, False))
129
+
130
+ #
131
+ # A A
132
+ # | |
133
+ # [A-] - B - A >> A - [B-] - A
134
+ # | |
135
+ # A A
136
+ #
137
+ q = smarts('[B;D4;z1]-[A;-]')
138
+ atom_fix = {1: (-1, None), 2: (1, None)}
139
+ bonds_fix = ()
140
+ rules.append((q, atom_fix, bonds_fix, False))
141
+
142
+ #
143
+ # A A
144
+ # | |
145
+ # A - B - A >> A - [B-] - A
146
+ # | |
147
+ # A A
148
+ #
149
+ q = smarts('[B;D4;z1]')
150
+ atom_fix = {1: (-1, None)}
151
+ bonds_fix = ()
152
+ rules.append((q, atom_fix, bonds_fix, False))
153
+
154
+ #
155
+ # A A
156
+ # | |
157
+ # N >> [N+]
158
+ # / | \ / | \
159
+ # A A A A A A
160
+ #
161
+ q = smarts('[N;D4;z1]')
162
+ atom_fix = {1: (1, None)}
163
+ bonds_fix = ()
164
+ rules.append((q, atom_fix, bonds_fix, False))
165
+
166
+ # aci-nitro
167
+ # O O
168
+ # // //
169
+ # C = N >> C - [N+]
170
+ # \ \
171
+ # OH [O-]
172
+ #
173
+ q = smarts('[N;D3;z3;x2](=[O;D1])([O;D1])=C')
174
+ atom_fix = {1: (1, None), 3: (-1, None)}
175
+ bonds_fix = ((1, 4, 1),)
176
+ rules.append((q, atom_fix, bonds_fix, True))
177
+
178
+ #
179
+ # O [O-]
180
+ # // /
181
+ # [C,N,O] = N >> [C,N,O] = [N+]
182
+ # \ \
183
+ # A A
184
+ #
185
+ q = smarts('[N;D3;z3](=[O;D1])(=[C,N,O])-[A]')
186
+ atom_fix = {1: (1, None), 2: (-1, None)}
187
+ bonds_fix = ((1, 2, 1),)
188
+ rules.append((q, atom_fix, bonds_fix, False))
189
+
190
+ # fix aci-nitro
191
+ # [O-] [O-]
192
+ # / /
193
+ # C = [N+ ] >> C - [N+]
194
+ # \ \\
195
+ # OH O
196
+ #
197
+ q = smarts('[N;D3;z2;x2;+]([O;D1;-])([O;D1])=C')
198
+ atom_fix = {}
199
+ bonds_fix = ((1, 3, 2), (1, 4, 1))
200
+ rules.append((q, atom_fix, bonds_fix, True))
201
+
202
+ # fix CN(=O)=N(=O)C
203
+ #
204
+ # [N+] = N = O >> [N+] = [N+] - O-
205
+ # | |
206
+ # A A
207
+ #
208
+ q = smarts('[N;D3;z3](=[N;D3;z2;+])(=[O;D1])[A]')
209
+ atom_fix = {1: (1, None), 3: (-1, None)}
210
+ bonds_fix = ((1, 3, 1),)
211
+ rules.append((q, atom_fix, bonds_fix, False))
212
+
213
+ # Fix CN(=O)=N(=N)C
214
+ # [N+] = N = N - ? >> [N+] = [N+] - [N-] - ?
215
+ # | |
216
+ # A A
217
+ #
218
+ q = smarts('[N;D3;z3](=[N;D3;z2;+])(=[N;D1,D2;z2])[A]')
219
+ atom_fix = {1: (1, None), 3: (-1, None)}
220
+ bonds_fix = ((1, 3, 1),)
221
+ rules.append((q, atom_fix, bonds_fix, False))
222
+
223
+ # For N-case is not unique!
224
+ # N [N-]
225
+ # // /
226
+ # [C,N] = N >> [C,N] = [N+]
227
+ # \ \
228
+ # A A
229
+ #
230
+ q = smarts('[N;D3;z3](=[N;D1,D2;z2])(=[C,N])[A]')
231
+ atom_fix = {1: (1, None), 2: (-1, None)}
232
+ bonds_fix = ((1, 2, 1),)
233
+ rules.append((q, atom_fix, bonds_fix, False))
234
+
235
+ #
236
+ # [N-] - [N+] = O >> N = [N+] - [O-]
237
+ # | |
238
+ # A A
239
+ #
240
+ q = smarts('[N;D3;z2;+](=[O;D1])[N;D1,D2;z1;-]')
241
+ atom_fix = {2: (-1, None), 3: (1, None)}
242
+ bonds_fix = ((1, 2, 1), (1, 3, 2))
243
+ rules.append((q, atom_fix, bonds_fix, False))
244
+
245
+ #
246
+ # O [O-]
247
+ # // /
248
+ # [A-] - N >> [A-] - [N+]
249
+ # \\ \\
250
+ # O O
251
+ #
252
+ q = smarts('[N;D3;z3](=[O;D1])(=[O;D1])[A;-]')
253
+ atom_fix = {1: (1, None), 2: (-1, None)}
254
+ bonds_fix = ((1, 2, 1),)
255
+ rules.append((q, atom_fix, bonds_fix, False))
256
+
257
+ #
258
+ # O : N : O O = [N+] - [O-]
259
+ # | >> |
260
+ # A A
261
+ #
262
+ q = smarts('[N;D3;a](:[O;D1])(:[O;D1])[A]')
263
+ atom_fix = {1: (1, None), 2: (-1, None)}
264
+ bonds_fix = ((1, 2, 1), (1, 3, 2))
265
+ rules.append((q, atom_fix, bonds_fix, False))
266
+
267
+ # Nitrite
268
+ #
269
+ # O [O-]
270
+ # // /
271
+ # [N-] >> N
272
+ # \\ \\
273
+ # O O
274
+ #
275
+ q = smarts('[N;D2;z3;x2;-](=[O;D1])=[O;D1]')
276
+ atom_fix = {1: (1, None), 2: (-1, None)}
277
+ bonds_fix = ((1, 2, 1),)
278
+ rules.append((q, atom_fix, bonds_fix, False))
279
+
280
+ #
281
+ # [O,C,N] = N # N >> [O,C,N] = [N+] = [N-]
282
+ #
283
+ q = smarts('[N;D2;z3](#[N;D1])=[C,N,O]')
284
+ atom_fix = {1: (1, None), 2: (-1, None)}
285
+ bonds_fix = ((1, 2, 2),)
286
+ rules.append((q, atom_fix, bonds_fix, False))
287
+
288
+ #
289
+ # [C,N,O-] - [N+] # N >> [C,N,O] = [N+] = [N-]
290
+ #
291
+ q = smarts('[N;D2;z3;+](#[N;D1])[C,N,O;z1;-]')
292
+ atom_fix = {2: (-1, None), 3: (1, None)}
293
+ bonds_fix = ((1, 2, 2), (1, 3, 2))
294
+ rules.append((q, atom_fix, bonds_fix, False))
295
+
296
+ #
297
+ # A - [N+] # N = [N-] >> A - N = [N+] = [N-]
298
+ #
299
+ q = smarts('[N;D2;z3;x2](#[N;D2;+][A])=[N;D1;-]')
300
+ atom_fix = {1: (1, None), 2: (-1, None)}
301
+ bonds_fix = ((1, 2, 2),)
302
+ rules.append((q, atom_fix, bonds_fix, False))
303
+
304
+ #
305
+ # A - N = N = N >> A - N = [N+] = [N-]
306
+ #
307
+ q = smarts('[N;D2;z3;x2](=[N;D2;z2])=[N;D1]')
308
+ atom_fix = {1: (1, None), 3: (-1, None)}
309
+ bonds_fix = ()
310
+ rules.append((q, atom_fix, bonds_fix, False))
311
+
312
+ #
313
+ # A - NH - N # N >> A - N = [N+] = [N-]
314
+ #
315
+ q = smarts('[N;D2;z3;x2]([N;D2;z1])#[N;D1]')
316
+ atom_fix = {1: (1, None), 3: (-1, None)}
317
+ bonds_fix = ((1, 2, 2), (1, 3, 2))
318
+ rules.append((q, atom_fix, bonds_fix, False))
319
+
320
+ #
321
+ # [N-] # N = N - A >> [N-] == [N+] == N - A
322
+ #
323
+ q = smarts('[N;D2;z3;x2](=[N;D2;z2])#[N;D1;-]')
324
+ atom_fix = {1: (1, None)}
325
+ bonds_fix = ((1, 3, 2),)
326
+ rules.append((q, atom_fix, bonds_fix, False))
327
+
328
+ #
329
+ # [N-] == N # N >> [N-] == [N+] == [N-]
330
+ #
331
+ q = smarts('[N;D2;z3;x2](=[N;D1;-])#[N;D1]')
332
+ atom_fix = {1: (1, None), 3: (-1, None)}
333
+ bonds_fix = ((1, 3, 2),)
334
+ rules.append((q, atom_fix, bonds_fix, False))
335
+
336
+ #
337
+ # A - C # N = NH >> A - [CH] = [N+] = [N-]
338
+ #
339
+ q = smarts('[N;D2;z3;x1](=[N;D1])#[C;D1,D2]')
340
+ atom_fix = {1: (1, None), 2: (-1, None)}
341
+ bonds_fix = ((1, 3, 2),)
342
+ rules.append((q, atom_fix, bonds_fix, False))
343
+
344
+ # note: order dependent
345
+ # A - C # N = [O,N] >> A - C # [N+] - [O,N-]
346
+ #
347
+ q = smarts('[N;D2;z3;x1](=[N,O;z2])#[C;D1,D2]')
348
+ atom_fix = {1: (1, None), 2: (-1, None)}
349
+ bonds_fix = ((1, 2, 1),)
350
+ rules.append((q, atom_fix, bonds_fix, False))
351
+
352
+ #
353
+ # [NH2,OH,SH] - N # C - A >> [NH,O,S-] - [N+] # C - A
354
+ #
355
+ q = smarts('[N;D2;z3;x1]([N,O,S;D1])#[C;D1,D2]')
356
+ atom_fix = {1: (1, None), 2: (-1, None)}
357
+ bonds_fix = ()
358
+ rules.append((q, atom_fix, bonds_fix, False))
359
+
360
+ #
361
+ # A - [NH] - N # C >> A - [N-] - [N+] # C
362
+ #
363
+ q = smarts('[N;D2;z3;x1]([N;D2;z1])#[C;D1,D2]')
364
+ atom_fix = {1: (1, None), 2: (-1, None)}
365
+ bonds_fix = ()
366
+ rules.append((q, atom_fix, bonds_fix, False))
367
+
368
+ #
369
+ # [NH2,OH,SH] - [N+] # [C-] >> [NH,O,S-] - [N+] # [CH]
370
+ #
371
+ q = smarts('[N;D2;z3;x1;+]([N,O,S;D1])#[C;D1;-]')
372
+ atom_fix = {2: (-1, None), 3: (1, None)}
373
+ bonds_fix = ()
374
+ rules.append((q, atom_fix, bonds_fix, True))
375
+
376
+ #
377
+ # A - [NH] - [N+] # [C-] >> A - [N-] - [N+] # [CH]
378
+ #
379
+ q = smarts('[N;D2;z3;x1;+]([N;D2;z1])#[C;D1;-]')
380
+ atom_fix = {2: (-1, None), 3: (1, None)}
381
+ bonds_fix = ()
382
+ rules.append((q, atom_fix, bonds_fix, True))
383
+
384
+ #
385
+ # A - N # C >> A - [N+] # [C-]
386
+ #
387
+ q = smarts('[N;D2;z3]([A])#[C;D1]')
388
+ atom_fix = {1: (1, None), 3: (-1, None)}
389
+ bonds_fix = ()
390
+ rules.append((q, atom_fix, bonds_fix, False))
391
+
392
+ # fix old diazo rule
393
+ #
394
+ # A - [C-] = [N+] = [NH] >> A - [CH] = [N+] = [N-]
395
+ #
396
+ q = smarts('[N;D2;z3;x1;+](=[N;D1])=[C;D1,D2;z2;-]')
397
+ atom_fix = {2: (-1, None), 3: (1, None)}
398
+ bonds_fix = ()
399
+ rules.append((q, atom_fix, bonds_fix, False))
400
+
401
+ #
402
+ # | |
403
+ # - N - >> - [N+] -
404
+ # \\ |
405
+ # [O,N] [O,N-]
406
+ #
407
+ q = smarts('[N;D4;z2]=[O,N;z2]')
408
+ atom_fix = {1: (1, None), 2: (-1, None)}
409
+ bonds_fix = ((1, 2, 1),)
410
+ rules.append((q, atom_fix, bonds_fix, False))
411
+
412
+ # N-oxide radical
413
+ #
414
+ # | |
415
+ # - N* >> - N
416
+ # \\ |
417
+ # O O*
418
+ #
419
+ q = smarts('[N;D3;z2]=[O;D1] |^1:0|')
420
+ atom_fix = {1: (0, False), 2: (0, True)}
421
+ bonds_fix = ((1, 2, 1),)
422
+ rules.append((q, atom_fix, bonds_fix, False))
423
+
424
+ # false N-oxide radical
425
+ #
426
+ # | |
427
+ # = N >> = [N+]
428
+ # \ \
429
+ # O* [O-]
430
+ #
431
+ q = smarts('[O;D1][N;D3;z2] |^1:0|')
432
+ atom_fix = {1: (-1, False), 2: (1, False)}
433
+ bonds_fix = ()
434
+ rules.append((q, atom_fix, bonds_fix, False))
435
+
436
+ #
437
+ # C C
438
+ # \ \
439
+ # N # N >> [N+] = [N-]
440
+ # / /
441
+ # C C
442
+ #
443
+ q = smarts('[N;D3;z3;x1](#[N;D1])(C)C')
444
+ atom_fix = {1: (1, None), 2: (-1, None)}
445
+ bonds_fix = ((1, 2, 2),)
446
+ rules.append((q, atom_fix, bonds_fix, False))
447
+
448
+ #
449
+ # C - N = [N+] >> C - [N+] # N
450
+ #
451
+ q = smarts('[N;D1;z2;x1;+]=[N;D2;x1;z2]')
452
+ atom_fix = {1: (-1, None), 2: (1, None)}
453
+ bonds_fix = ((1, 2, 3),)
454
+ rules.append((q, atom_fix, bonds_fix, False))
455
+
456
+ #
457
+ # [N+] - [C-] = O >> N = C = O
458
+ #
459
+ q = smarts('[C;D2;z2;x2;-]([N;D1,D2;z1;+])=[O;D1]')
460
+ atom_fix = {1: (1, None), 2: (-1, None)}
461
+ bonds_fix = ((1, 2, 2),)
462
+ rules.append((q, atom_fix, bonds_fix, False))
463
+
464
+ #
465
+ # N # C - OH >> HN = C = O
466
+ #
467
+ q = smarts('[N;D1;x0;z3]#[C;D2;z3;x2][O;D1]')
468
+ atom_fix = {}
469
+ bonds_fix = ((1, 2, 2), (2, 3, 2))
470
+ rules.append((q, atom_fix, bonds_fix, True))
471
+
472
+ #
473
+ # N # C - [O-] >> [N-] = C = O
474
+ #
475
+ q = smarts('[N;D1;x0;z3]#[C;D2;z3;x2][O;D1;-]')
476
+ atom_fix = {1: (-1, None), 3: (1, None)}
477
+ bonds_fix = ((1, 2, 2), (2, 3, 2))
478
+ rules.append((q, atom_fix, bonds_fix, False))
479
+
480
+ #
481
+ # - [N+] - [O-] >> - N = O
482
+ #
483
+ q = smarts('[O;D1;z1;x1;-][N;D2;z1;+]')
484
+ atom_fix = {1: (1, None), 2: (-1, None)}
485
+ bonds_fix = ((1, 2, 2),)
486
+ rules.append((q, atom_fix, bonds_fix, False))
487
+
488
+ #
489
+ # CH-N=O >> C=N-OH
490
+ #
491
+ q = smarts('[O;D1;z2;x1]=[N;D2;x1;z2][C;D1,D2,D3;z1]')
492
+ atom_fix = {}
493
+ bonds_fix = ((1, 2, 1), (2, 3, 2))
494
+ rules.append((q, atom_fix, bonds_fix, True))
495
+
496
+ #
497
+ # [O+]R [O]R
498
+ # // /
499
+ # R2N - C >> R2[N+] = C
500
+ #
501
+ q = smarts('[O;D2;z2;+]=[C;z2][N;D1,D2,D3;z1]')
502
+ atom_fix = {1: (-1, None), 3: (1, None)}
503
+ bonds_fix = ((1, 2, 1), (2, 3, 2))
504
+ rules.append((q, atom_fix, bonds_fix, False))
505
+
506
+ #
507
+ # fix pyrylium dearomatization. restore O+ in aromatic ring from N+ form.
508
+ # e.g. O1C(=[NH+]...)... -> [O+]1=C(N...)...
509
+ #
510
+ q = smarts('[O;D2;r6]1[C;z2](=[N;+])[A;z2]-,=[A;z2]-,=[A;z2]-,=[A;z2]1')
511
+ atom_fix = {1: (1, None), 3: (-1, None)}
512
+ bonds_fix = ((1, 2, 2), (2, 3, 1))
513
+ rules.append((q, atom_fix, bonds_fix, False))
514
+
515
+ #
516
+ # 6-membered ring amidation (kekule form: OH on C with C=N in ring)
517
+ # e.g. OC1=CC=NC=N1 >> O=C1NC=NC=C1 (pyrimidinone)
518
+ # OC1=CC=CC=N1 >> O=C1NC=CC=C1 (pyridinone)
519
+ #
520
+ q = smarts('[O,S;D1;z1;x0]-[C;r6;z2]=2[N;z2]=[A;z2][A;z2]=[A;z2][A;z2]=2')
521
+ atom_fix = {}
522
+ bonds_fix = ((1, 2, 2), (2, 7, 1), (3, 4, 1), (4, 5, 2), (5, 6, 1), (6, 7, 2))
523
+ rules.append((q, atom_fix, bonds_fix, True))
524
+
525
+ #
526
+ # 6-membered ring 1,3-diketone amidation (one N already sp3)
527
+ # e.g. OC1=NC(=O)NC=C1 >> O=C1NC=CC(=O)N1 (uracil kekule)
528
+ #
529
+ q = smarts('[O,S;D1;z1;x0]-[C;r6;z2]=2[N;z1][C;z2][N;z2]=[A;z2][A;z2]=2')
530
+ atom_fix = {}
531
+ bonds_fix = ((1, 2, 2), (2, 7, 1), (7, 6, 2), (6, 5, 1))
532
+ rules.append((q, atom_fix, bonds_fix, True))
533
+
534
+ #
535
+ # [O,S]H [O,S]
536
+ # / //
537
+ # N = C >> NH - C
538
+ #
539
+ q = smarts('[N;z2]=[C;D2,D3;z2]-[O,S;D1]')
540
+ atom_fix = {}
541
+ bonds_fix = ((1, 2, 1), (2, 3, 2))
542
+ rules.append((q, atom_fix, bonds_fix, True))
543
+
544
+ #
545
+ # 6-membered ring hydroxypyridine to pyridone
546
+ # e.g. OC1=CC=NC=C1 >> O=C1C=CNC=C1 (4-pyridone)
547
+ #
548
+ q = smarts('[O,S;D1;z1;x0]-[C;r6;z2]1=[A;z2][A;z2]=[N;D2][A;z2]-,=[A;z2]1')
549
+ atom_fix = {}
550
+ bonds_fix = ((1, 2, 2), (2, 3, 1), (3, 4, 2), (4, 5, 1))
551
+ rules.append((q, atom_fix, bonds_fix, True))
552
+
553
+ # acyclic keto-enol
554
+ # OH O
555
+ # / //
556
+ # C,H - C = C - C,H >> C,H - C - C - C,H
557
+ #
558
+ q = smarts('[O;D1;z1;x0][C;D2,D3;z2;x1;!R]=[C;z2;x0]')
559
+ atom_fix = {}
560
+ bonds_fix = ((1, 2, 2), (2, 3, 1))
561
+ rules.append((q, atom_fix, bonds_fix, True))
562
+
563
+ # 5-membered ring amidation (short flip, N adjacent to C=N)
564
+ # e.g. CN1C=CC(O)=N1 >> CN1NC(=O)C=C1
565
+ #
566
+ q = smarts('[O,S;D1;z1;x0]-[C;r5;z2]1=N[N;z1][A;z2]-,=[A;z2]1')
567
+ atom_fix = {}
568
+ bonds_fix = ((1, 2, 2), (2, 3, 1))
569
+ rules.append((q, atom_fix, bonds_fix, True))
570
+
571
+ # 5-membered ring amidation (long flip, N far from C=N)
572
+ # e.g. CN1N=CC=C1O >> CN1NC=CC1=O
573
+ #
574
+ q = smarts('[O,S;D1;z1;x0]-[C;r5;z2]1=[A;z2][A;z2]=N[N;z1]1')
575
+ atom_fix = {}
576
+ bonds_fix = ((1, 2, 2), (2, 3, 1), (3, 4, 2), (4, 5, 1))
577
+ rules.append((q, atom_fix, bonds_fix, True))
578
+
579
+ # 6-membered ring N=C-CH adjacent to C=O (short flip)
580
+ # e.g. O=C1C=CCC=N1 >> O=C1NC=CC=C1
581
+ #
582
+ q = smarts('[N;r6;z2]1=[A;z2][C;h1,h2][A;z2]-,=[A;z2]C1=O')
583
+ atom_fix = {}
584
+ bonds_fix = ((1, 2, 1), (2, 3, 2))
585
+ rules.append((q, atom_fix, bonds_fix, True))
586
+
587
+ # 6-membered ring N=C-C=C-CH adjacent to C=O (long flip)
588
+ # e.g. O=C1CC=CC=N1 >> O=C1NC=CC=C1
589
+ #
590
+ q = smarts('[N;r6;z2]1=[A;z2][A;z2]=[A;z2][C;h1,h2]C1=O')
591
+ atom_fix = {}
592
+ bonds_fix = ((1, 2, 1), (2, 3, 2), (3, 4, 1), (4, 5, 2))
593
+ rules.append((q, atom_fix, bonds_fix, True))
594
+
595
+ # 6-membered ring N=C-CH adjacent to C=O (C=O between CH and ring end)
596
+ # e.g. O=C1CC=NC=C1 >> O=C1C=CNC=C1
597
+ #
598
+ q = smarts('[N;r6;z2]1=[A;z2][C;h1,h2]C(=O)[A;z2]-,=[A;z2]1')
599
+ atom_fix = {}
600
+ bonds_fix = ((1, 2, 1), (2, 3, 2))
601
+ rules.append((q, atom_fix, bonds_fix, True))
602
+
603
+ # 5-membered ring N=C-CH >> NH-C=C
604
+ # e.g. C1C=NC=N1 >> N1C=CN=C1
605
+ #
606
+ q = smarts('[N;r5;z2]1=[A;z2][C;h1,h2][A;z2]-,=[A;z2]1')
607
+ atom_fix = {}
608
+ bonds_fix = ((1, 2, 1), (2, 3, 2))
609
+ rules.append((q, atom_fix, bonds_fix, True))
610
+
611
+ # 5-membered ring N=C-CH with sp3 N,O closure
612
+ # e.g. CN1N=CCC1=O >> CN1NC=CC1=O
613
+ #
614
+ q = smarts('[N;r5;z2]1=[A;z2][C;h1,h2][A;z2][N,O;z1]1')
615
+ atom_fix = {}
616
+ bonds_fix = ((1, 2, 1), (2, 3, 2))
617
+ rules.append((q, atom_fix, bonds_fix, True))
618
+
619
+ # N=C1NC=CC(=O)N1 >> NC1=NC=CC(=O)N1
620
+ q = smarts('[O,S;D1;z2]=[C;D3;r6]1[N;z1][C;D3:1](=[N:2])[N;h1:3][A]-,=[A]1')
621
+ atom_fix = {}
622
+ bonds_fix = ((1, 2, 1), (1, 3, 2))
623
+ rules.append((q, atom_fix, bonds_fix, True))
624
+
625
+ #
626
+ # A A
627
+ # | |
628
+ # A - [P+] - [O-] >> A - P = O
629
+ # | |
630
+ # A A
631
+ #
632
+ q = smarts('[P;D4;z1;+][O;D1;-]')
633
+ atom_fix = {1: (-1, None), 2: (1, None)}
634
+ bonds_fix = ((1, 2, 2),)
635
+ rules.append((q, atom_fix, bonds_fix, False))
636
+
637
+ #
638
+ # A A
639
+ # | |
640
+ # A - [P-] - [C+] >> A - P = C
641
+ # | |
642
+ # A A
643
+ #
644
+ q = smarts('[P;D4;z1;-][C;D1,D2,D3;z1;+]')
645
+ atom_fix = {1: (1, None), 2: (-1, None)}
646
+ bonds_fix = ((1, 2, 2),)
647
+ rules.append((q, atom_fix, bonds_fix, False))
648
+
649
+ #
650
+ # F F F F
651
+ # \ / \ /
652
+ # F - P - F >> F - [P-] - F
653
+ # / \ / \
654
+ # F F F F
655
+ #
656
+ q = smarts('[P;D6;z1]([F;D1])([F;D1])([F;D1])([F;D1])([F;D1])[F;D1]')
657
+ atom_fix = {1: (-1, None)}
658
+ bonds_fix = ()
659
+ rules.append((q, atom_fix, bonds_fix, False))
660
+
661
+ #
662
+ # O O
663
+ # \\ \\
664
+ # A - [P-] - A >> A - P - A
665
+ # // /
666
+ # O [O-]
667
+ #
668
+ q = smarts('[P;D4;z3;-](=[O;D1])(=[O;D1])([A])[A]')
669
+ atom_fix = {1: (1, None), 2: (-1, None)}
670
+ bonds_fix = ((1, 2, 1),)
671
+ rules.append((q, atom_fix, bonds_fix, False))
672
+
673
+ #
674
+ # O [O-]
675
+ # \\ \
676
+ # A - P - A >> A - P - A
677
+ # / //
678
+ # [S-] S
679
+ #
680
+ q = smarts('[S;D1;z1;x1;-][P;D4;z2]=[O;D1]')
681
+ atom_fix = {1: (1, None), 3: (-1, None)}
682
+ bonds_fix = ((1, 2, 2), (2, 3, 1))
683
+ rules.append((q, atom_fix, bonds_fix, False))
684
+
685
+ #
686
+ # O [OH]
687
+ # \\ \
688
+ # A - P - A >> A - P - A
689
+ # / //
690
+ # [SH] S
691
+ #
692
+ q = smarts('[S;D1;z1;x1][P;D4;z2]=[O;D1]')
693
+ atom_fix = {}
694
+ bonds_fix = ((1, 2, 2), (2, 3, 1))
695
+ rules.append((q, atom_fix, bonds_fix, True))
696
+
697
+ #
698
+ # A A
699
+ # \\ \\
700
+ # A - S - [S-] >> A - S - [O-]
701
+ # // //
702
+ # O S
703
+ #
704
+ q = smarts('[S;D1;-][S;D4;z3](=[O;D1])(=[A])[A]')
705
+ atom_fix = {1: (1, None), 3: (-1, None)}
706
+ bonds_fix = ((1, 2, 2), (2, 3, 1))
707
+ rules.append((q, atom_fix, bonds_fix, False))
708
+
709
+ #
710
+ # A A
711
+ # \\ \
712
+ # A - S - [SH] >> A - S - [OH]
713
+ # // //
714
+ # O S
715
+ #
716
+ q = smarts('[S;D1][S;D4;z3](=[O;D1])(=[A])[A]')
717
+ atom_fix = {}
718
+ bonds_fix = ((1, 2, 2), (2, 3, 1))
719
+ rules.append((q, atom_fix, bonds_fix, True))
720
+
721
+ #
722
+ # A A
723
+ # / /
724
+ # [O-] - [S,Si,Se+] >> O = [S,Si,Se]
725
+ # \ \
726
+ # A A
727
+ #
728
+ q = smarts('[S,Se,Si;D3;z1;+][O;D1;-]')
729
+ atom_fix = {1: (-1, None), 2: (1, None)}
730
+ bonds_fix = ((1, 2, 2),)
731
+ rules.append((q, atom_fix, bonds_fix, False))
732
+
733
+ #
734
+ # A? A?
735
+ # | |
736
+ # A = [S+] - [O-] >> A = S = O
737
+ # | |
738
+ # A? A?
739
+ #
740
+ q = smarts('[S;D2,D4;z2;+][O;D1;-]')
741
+ atom_fix = {1: (-1, None), 2: (1, None)}
742
+ bonds_fix = ((1, 2, 2),)
743
+ rules.append((q, atom_fix, bonds_fix, False))
744
+
745
+ #
746
+ # [O-] O
747
+ # / //
748
+ # A = [S+2] >> A = S
749
+ # \ \\
750
+ # [O-] O
751
+ #
752
+ q = smarts('[S;D3;z2;+2]([O;D1;-])[O;D1;-]')
753
+ atom_fix = {1: (-2, None), 2: (1, None), 3: (1, None)}
754
+ bonds_fix = ((1, 2, 2), (1, 3, 2))
755
+ rules.append((q, atom_fix, bonds_fix, False))
756
+
757
+ #
758
+ # A A
759
+ # | |
760
+ # [O-] - [S+2] - [O-] >> O = S = O
761
+ # | |
762
+ # A A
763
+ #
764
+ q = smarts('[S;D4;z1;+2]([O;D1;-])[O;D1;-]')
765
+ atom_fix = {1: (-2, None), 2: (1, None), 3: (1, None)}
766
+ bonds_fix = ((1, 2, 2), (1, 3, 2))
767
+ rules.append((q, atom_fix, bonds_fix, False))
768
+
769
+ #
770
+ # A - [S-] - [C+] >> A - S = C
771
+ # | |
772
+ # A A
773
+ #
774
+ q = smarts('[S;D3;z1;-]([C;D1,D2,D3;z1;+])')
775
+ atom_fix = {1: (1, None), 2: (-1, None)}
776
+ bonds_fix = ((1, 2, 2),)
777
+ rules.append((q, atom_fix, bonds_fix, False))
778
+
779
+ #
780
+ # O O
781
+ # \\ \\
782
+ # [S-] - A >> S - A
783
+ # // /
784
+ # O [O-]
785
+ #
786
+ q = smarts('[S;D3;z3;-](=[O;D1])(=[O;D1])[A]')
787
+ atom_fix = {1: (1, None), 2: (-1, None)}
788
+ bonds_fix = ((1, 2, 1),)
789
+ rules.append((q, atom_fix, bonds_fix, False))
790
+
791
+ #
792
+ # O [O-]
793
+ # \\ \
794
+ # A - [S-] = O >> A - S = O
795
+ # // //
796
+ # O O
797
+ #
798
+ q = smarts('[S;D4;z3;-](=[O;D1])(=[O;D1])(=[O;D1])[A]')
799
+ atom_fix = {1: (1, None), 2: (-1, None)}
800
+ bonds_fix = ((1, 2, 1),)
801
+ rules.append((q, atom_fix, bonds_fix, False))
802
+
803
+ #
804
+ # O [O-]
805
+ # \\ \
806
+ # [S-] - [S-] >> S = S
807
+ # // /
808
+ # O [O-]
809
+ #
810
+ q = smarts('[S;D3;z3;x3;-]([S;D1;-])(=[O;D1])=[O;D1]')
811
+ atom_fix = {1: (1, None), 2: (1, None), 3: (-1, None), 4: (-1, None)}
812
+ bonds_fix = ((1, 2, 2), (1, 3, 1), (1, 4, 1))
813
+ rules.append((q, atom_fix, bonds_fix, False))
814
+
815
+ #
816
+ # A A
817
+ # \ \
818
+ # A - S = O >> A - S = O
819
+ # / //
820
+ # [OH] O
821
+ #
822
+ q = smarts('[S;D4;z2](=[O;D1])[O;D1]')
823
+ atom_fix = {}
824
+ bonds_fix = ((1, 3, 2),)
825
+ rules.append((q, atom_fix, bonds_fix, False))
826
+
827
+ #
828
+ # A A
829
+ # \ \
830
+ # A - S = O >> A - S = O
831
+ # / //
832
+ # [NH] N
833
+ #
834
+ q = smarts('[S;D4;z2](=[O;D1])[N;D1,D2;z1]')
835
+ atom_fix = {}
836
+ bonds_fix = ((1, 3, 2),)
837
+ rules.append((q, atom_fix, bonds_fix, False))
838
+
839
+ #
840
+ # A{1,3} A{1,3}
841
+ # | |
842
+ # N = S - [OH] >> [NH] - S = O
843
+ #
844
+ q = smarts('[S;D3,D5;z2](=[N;D1,D2;z2])[O;D1]')
845
+ atom_fix = {}
846
+ bonds_fix = ((1, 2, 1), (1, 3, 2))
847
+ rules.append((q, atom_fix, bonds_fix, True))
848
+
849
+ #
850
+ # [OH] O
851
+ # | //
852
+ # N = S = A >> [NH] - S = A (duplicated for overlapping groups)
853
+ # | |
854
+ # A A
855
+ #
856
+ q = smarts('[S;D4;z3:1]([O;D1:2])(=[N;D1,D2;z2:3])(=[A])[A]')
857
+ atom_fix = {}
858
+ bonds_fix = ((1, 2, 2), (1, 3, 1))
859
+ rules.append((q, atom_fix, bonds_fix, True))
860
+ rules.append((q, atom_fix, bonds_fix, True)) # second shot for overlapping groups
861
+
862
+ #
863
+ # C # C - [O,NH,S]H >> C=C=[O,NH,S]
864
+ #
865
+ q = smarts('[C;D2;z3;x1]([N,O,S;D1])#[C;D1,D2]')
866
+ atom_fix = {}
867
+ bonds_fix = ((1, 2, 2), (1, 3, 2))
868
+ rules.append((q, atom_fix, bonds_fix, True))
869
+
870
+ #
871
+ # C # C - [NH]R >> C=C=NR
872
+ #
873
+ q = smarts('[C;D2;z3;x1]([N;D2;z1])#[C;D1,D2]')
874
+ atom_fix = {}
875
+ bonds_fix = ((1, 2, 2), (1, 3, 2))
876
+ rules.append((q, atom_fix, bonds_fix, True))
877
+
878
+ # Carbon Monoxide
879
+ #
880
+ # [CX1] = O >> [С-] # [O+]
881
+ #
882
+ q = smarts('[C;D1;x1;z2]=[O;D1] |^1:0|')
883
+ atom_fix = {1: (-1, False), 2: (1, None)}
884
+ bonds_fix = ((1, 2, 3),)
885
+ rules.append((q, atom_fix, bonds_fix, False))
886
+
887
+ # Ozone
888
+ #
889
+ # [O*] -- O -- [O*] >> O == [O+] -- [O-]
890
+ #
891
+ q = smarts('[O;D1][O;D2][O;D1] |^1:0,2|')
892
+ atom_fix = {1: (0, False), 2: (1, None), 3: (-1, False)}
893
+ bonds_fix = ((1, 2, 2),)
894
+ rules.append((q, atom_fix, bonds_fix, False))
895
+
896
+ # only after [A-] - [C+] rules!
897
+ # [C+] - N(R2) >> C = [N+](R2)
898
+ #
899
+ q = smarts('[C;D1,D2,D3;z1;+]-[N;D3;z1;x0]')
900
+ atom_fix = {1: (-1, None), 2: (1, None)}
901
+ bonds_fix = ((1, 2, 2),)
902
+ rules.append((q, atom_fix, bonds_fix, False))
903
+
904
+ # low priority for hetero-N
905
+ # [C+] - N(X2) >> C = [N+](X2)
906
+ #
907
+ q = smarts('[C;D1,D2,D3;z1;+]-[N;D3;z1]')
908
+ atom_fix = {1: (-1, None), 2: (1, None)}
909
+ bonds_fix = ((1, 2, 2),)
910
+ rules.append((q, atom_fix, bonds_fix, False))
911
+
912
+ #
913
+ # [C+] = N(R) >> C # [N+](R)
914
+ #
915
+ q = smarts('[C;D1,D2;z2;x1;+]=[N;D1,D2;z2]')
916
+ atom_fix = {1: (-1, None), 2: (1, None)}
917
+ bonds_fix = ((1, 2, 3),)
918
+ rules.append((q, atom_fix, bonds_fix, False))
919
+
920
+ # fix rdkit
921
+ # A-[Cl,Br,I+] - [O-] >> X = O
922
+ #
923
+ q = smarts('[Cl,Br,I;D2;z1;+][O;D1;-]')
924
+ atom_fix = {1: (-1, None), 2: (1, None)}
925
+ bonds_fix = ((1, 2, 2),)
926
+ rules.append((q, atom_fix, bonds_fix, False))
927
+
928
+ # fix rdkit
929
+ # A-[Hal+2]([O-])2
930
+ #
931
+ q = smarts('[Cl,Br,I;D3;z1;+2]([O;D1;-])[O;D1;-]')
932
+ atom_fix = {1: (-2, None), 2: (1, None), 3: (1, None)}
933
+ bonds_fix = ((1, 2, 2), (1, 3, 2))
934
+ rules.append((q, atom_fix, bonds_fix, False))
935
+
936
+ # fix rdkit
937
+ # A-[Hal+3]([O-])3
938
+ #
939
+ q = smarts('[Cl,Br,I;D4;z1;+3]([O;D1;-])([O;D1;-])[O;D1;-]')
940
+ atom_fix = {1: (-3, None), 2: (1, None), 3: (1, None), 4: (1, None)}
941
+ bonds_fix = ((1, 2, 2), (1, 3, 2), (1, 4, 2))
942
+ rules.append((q, atom_fix, bonds_fix, False))
943
+
944
+ # fix reaxys [Cl-]=O > Cl-[O-]
945
+ q = smarts('[Cl,Br,I;D1;z2;-]=[O;D1]')
946
+ atom_fix = {1: (1, None), 2: (-1, None)}
947
+ bonds_fix = ((1, 2, 1),)
948
+ rules.append((q, atom_fix, bonds_fix, False))
949
+
950
+ return [(q, atom_fix, bonds_fix,
951
+ [n for n, a in q.atoms() if a.atomic_symbol == 'A' and n not in atom_fix], is_tautomer)
952
+ for q, atom_fix, bonds_fix, is_tautomer in rules]
953
+
954
+
955
+ rules = Proxy(_rules)
956
+
957
+
958
+ __all__ = ['rules']