oxidane 0.2.0__tar.gz

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 (328) hide show
  1. oxidane-0.2.0/.github/workflows/python.yml +48 -0
  2. oxidane-0.2.0/.github/workflows/release.yml +90 -0
  3. oxidane-0.2.0/.github/workflows/wheels.yml +165 -0
  4. oxidane-0.2.0/.gitignore +14 -0
  5. oxidane-0.2.0/CITATION.cff +18 -0
  6. oxidane-0.2.0/CODE_OF_CONDUCT.md +18 -0
  7. oxidane-0.2.0/CONTRIBUTING.md +40 -0
  8. oxidane-0.2.0/Cargo.lock +1658 -0
  9. oxidane-0.2.0/Cargo.toml +80 -0
  10. oxidane-0.2.0/LICENSE +21 -0
  11. oxidane-0.2.0/PKG-INFO +45 -0
  12. oxidane-0.2.0/README.md +266 -0
  13. oxidane-0.2.0/RELEASING.md +23 -0
  14. oxidane-0.2.0/THIRD_PARTY.md +143 -0
  15. oxidane-0.2.0/bindings/python/.gitignore +7 -0
  16. oxidane-0.2.0/bindings/python/Cargo.lock +651 -0
  17. oxidane-0.2.0/bindings/python/Cargo.toml +16 -0
  18. oxidane-0.2.0/bindings/python/README.md +366 -0
  19. oxidane-0.2.0/bindings/python/examples/legacy_usage.py +34 -0
  20. oxidane-0.2.0/bindings/python/examples/normalize_sqlite.py +56 -0
  21. oxidane-0.2.0/bindings/python/examples/notebook_display.ipynb +97 -0
  22. oxidane-0.2.0/bindings/python/src/lib.rs +673 -0
  23. oxidane-0.2.0/bindings/python/tests/cyclohexane.xyz +39 -0
  24. oxidane-0.2.0/bindings/python/tests/pentene.sdf +129 -0
  25. oxidane-0.2.0/bindings/python/tests/test_api.py +431 -0
  26. oxidane-0.2.0/bindings/python/tests/test_notebook.py +77 -0
  27. oxidane-0.2.0/bindings/python/uv.lock +1943 -0
  28. oxidane-0.2.0/docs/CHECKS.md +48 -0
  29. oxidane-0.2.0/docs/CONSTANTS.md +35 -0
  30. oxidane-0.2.0/docs/COOKBOOK.md +468 -0
  31. oxidane-0.2.0/docs/SMALL_RING_BOUNDS.md +53 -0
  32. oxidane-0.2.0/examples/aromaticity_trace.rs +145 -0
  33. oxidane-0.2.0/examples/autoencode_smiles.rs +380 -0
  34. oxidane-0.2.0/examples/bde_to_bonds.rs +322 -0
  35. oxidane-0.2.0/examples/bench_full.rs +48 -0
  36. oxidane-0.2.0/examples/bounds_dump.rs +59 -0
  37. oxidane-0.2.0/examples/canon_probe.rs +53 -0
  38. oxidane-0.2.0/examples/canon_skeleton_probe.rs +58 -0
  39. oxidane-0.2.0/examples/canon_stdin.rs +32 -0
  40. oxidane-0.2.0/examples/cip_diff.rs +103 -0
  41. oxidane-0.2.0/examples/cip_perf.rs +36 -0
  42. oxidane-0.2.0/examples/crippen_diff.rs +98 -0
  43. oxidane-0.2.0/examples/cxsmarts_demo.rs +218 -0
  44. oxidane-0.2.0/examples/descriptor_stdin.rs +40 -0
  45. oxidane-0.2.0/examples/draw_cleanup.rs +61 -0
  46. oxidane-0.2.0/examples/draw_gallery.rs +65 -0
  47. oxidane-0.2.0/examples/draw_svg.rs +20 -0
  48. oxidane-0.2.0/examples/dump_graphs.rs +170 -0
  49. oxidane-0.2.0/examples/dump_splits.rs +97 -0
  50. oxidane-0.2.0/examples/embed_budget.rs +61 -0
  51. oxidane-0.2.0/examples/embed_timed.rs +51 -0
  52. oxidane-0.2.0/examples/embed_xyz.rs +38 -0
  53. oxidane-0.2.0/examples/encoder_reference.rs +160 -0
  54. oxidane-0.2.0/examples/fingerprint_bench.rs +140 -0
  55. oxidane-0.2.0/examples/fingerprint_stdin.rs +114 -0
  56. oxidane-0.2.0/examples/formula_stdin.rs +37 -0
  57. oxidane-0.2.0/examples/hybridization_diff.rs +78 -0
  58. oxidane-0.2.0/examples/logo.rs +198 -0
  59. oxidane-0.2.0/examples/maccs_bits.rs +52 -0
  60. oxidane-0.2.0/examples/maccs_diff.rs +85 -0
  61. oxidane-0.2.0/examples/mcs_timing.rs +32 -0
  62. oxidane-0.2.0/examples/mmff_energy.rs +66 -0
  63. oxidane-0.2.0/examples/mmff_types.rs +71 -0
  64. oxidane-0.2.0/examples/normalize_keys.rs +16 -0
  65. oxidane-0.2.0/examples/normalize_sweep.rs +129 -0
  66. oxidane-0.2.0/examples/parse_split.rs +31 -0
  67. oxidane-0.2.0/examples/parse_write_bench.rs +70 -0
  68. oxidane-0.2.0/examples/perceive_only.rs +27 -0
  69. oxidane-0.2.0/examples/perception_probe.rs +72 -0
  70. oxidane-0.2.0/examples/pipeline_bench.rs +149 -0
  71. oxidane-0.2.0/examples/pretrain_encoder.rs +259 -0
  72. oxidane-0.2.0/examples/pretrain_supervised.rs +248 -0
  73. oxidane-0.2.0/examples/pubchem_sweep.rs +896 -0
  74. oxidane-0.2.0/examples/reaction_diff.rs +59 -0
  75. oxidane-0.2.0/examples/reaction_oracle.py +139 -0
  76. oxidane-0.2.0/examples/readme_figures.rs +182 -0
  77. oxidane-0.2.0/examples/ring_bench.rs +75 -0
  78. oxidane-0.2.0/examples/ring_family_probe.rs +103 -0
  79. oxidane-0.2.0/examples/ring_subgraph_probe.rs +54 -0
  80. oxidane-0.2.0/examples/scaffold_diff.rs +37 -0
  81. oxidane-0.2.0/examples/sdf_property_diff.rs +132 -0
  82. oxidane-0.2.0/examples/sdf_read_diff.rs +45 -0
  83. oxidane-0.2.0/examples/shape_diff.rs +142 -0
  84. oxidane-0.2.0/examples/slow_records.rs +54 -0
  85. oxidane-0.2.0/examples/smarts_diff.rs +52 -0
  86. oxidane-0.2.0/examples/stereo_probe.rs +111 -0
  87. oxidane-0.2.0/examples/submol_diff.rs +34 -0
  88. oxidane-0.2.0/examples/tautomer_keys.rs +41 -0
  89. oxidane-0.2.0/examples/tie_stats.rs +71 -0
  90. oxidane-0.2.0/examples/train_mpnn.rs +1077 -0
  91. oxidane-0.2.0/examples/uff_energy.rs +24 -0
  92. oxidane-0.2.0/examples/uff_relax.rs +53 -0
  93. oxidane-0.2.0/pyproject.toml +67 -0
  94. oxidane-0.2.0/python/molecules/__init__.py +3 -0
  95. oxidane-0.2.0/python/oxidane/__init__.py +25 -0
  96. oxidane-0.2.0/python/oxidane/__main__.py +81 -0
  97. oxidane-0.2.0/python/oxidane/_display.py +155 -0
  98. oxidane-0.2.0/python/oxidane/_display.pyi +12 -0
  99. oxidane-0.2.0/python/oxidane/_files.py +169 -0
  100. oxidane-0.2.0/python/oxidane/_oxidane.pyi +118 -0
  101. oxidane-0.2.0/python/oxidane/py.typed +0 -0
  102. oxidane-0.2.0/scripts/ci-local.sh +170 -0
  103. oxidane-0.2.0/scripts/pubchem_summary.slurm +13 -0
  104. oxidane-0.2.0/scripts/pubchem_sweep.slurm +43 -0
  105. oxidane-0.2.0/scripts/summarize_pubchem_sweep.py +56 -0
  106. oxidane-0.2.0/src/atom.rs +349 -0
  107. oxidane-0.2.0/src/consts/mod.rs +7 -0
  108. oxidane-0.2.0/src/graph_algorithms/mces/driver.rs +250 -0
  109. oxidane-0.2.0/src/graph_algorithms/mces/line_graph.rs +62 -0
  110. oxidane-0.2.0/src/graph_algorithms/mces/mod.rs +221 -0
  111. oxidane-0.2.0/src/graph_algorithms/mces/modular_product.rs +86 -0
  112. oxidane-0.2.0/src/graph_algorithms/mces/reconstruct.rs +390 -0
  113. oxidane-0.2.0/src/graph_algorithms/mces/search.rs +309 -0
  114. oxidane-0.2.0/src/graph_algorithms/mces/types.rs +107 -0
  115. oxidane-0.2.0/src/graph_algorithms/mcsplit/graph.rs +198 -0
  116. oxidane-0.2.0/src/graph_algorithms/mcsplit/line_graph.rs +108 -0
  117. oxidane-0.2.0/src/graph_algorithms/mcsplit/mod.rs +449 -0
  118. oxidane-0.2.0/src/graph_algorithms/mcsplit/reconstruct.rs +100 -0
  119. oxidane-0.2.0/src/graph_algorithms/mcsplit/search.rs +201 -0
  120. oxidane-0.2.0/src/graph_algorithms/mod.rs +4 -0
  121. oxidane-0.2.0/src/graph_algorithms/mol_canonization.rs +2673 -0
  122. oxidane-0.2.0/src/graph_algorithms/monomorphism.rs +258 -0
  123. oxidane-0.2.0/src/io/cxsmarts.rs +2288 -0
  124. oxidane-0.2.0/src/io/dot.rs +18 -0
  125. oxidane-0.2.0/src/io/gml.rs +110 -0
  126. oxidane-0.2.0/src/io/gml_rule.rs +436 -0
  127. oxidane-0.2.0/src/io/inchi/elements.rs +162 -0
  128. oxidane-0.2.0/src/io/inchi/layers.rs +734 -0
  129. oxidane-0.2.0/src/io/inchi/mod.rs +86 -0
  130. oxidane-0.2.0/src/io/inchi/structure.rs +1155 -0
  131. oxidane-0.2.0/src/io/mod.rs +20 -0
  132. oxidane-0.2.0/src/io/molfile.rs +556 -0
  133. oxidane-0.2.0/src/io/sdf.rs +771 -0
  134. oxidane-0.2.0/src/io/smarts_stereo.rs +286 -0
  135. oxidane-0.2.0/src/io/smiles.rs +3781 -0
  136. oxidane-0.2.0/src/io/subgraph_matching.rs +968 -0
  137. oxidane-0.2.0/src/lib.rs +17 -0
  138. oxidane-0.2.0/src/ml/batch.rs +349 -0
  139. oxidane-0.2.0/src/ml/dataset.rs +507 -0
  140. oxidane-0.2.0/src/ml/mod.rs +46 -0
  141. oxidane-0.2.0/src/ml/nn/autoencoder.rs +334 -0
  142. oxidane-0.2.0/src/ml/nn/decoder.rs +380 -0
  143. oxidane-0.2.0/src/ml/nn/layers.rs +119 -0
  144. oxidane-0.2.0/src/ml/nn/loss.rs +86 -0
  145. oxidane-0.2.0/src/ml/nn/mod.rs +56 -0
  146. oxidane-0.2.0/src/ml/nn/model.rs +334 -0
  147. oxidane-0.2.0/src/ml/nn/molecule_autoencoder.rs +350 -0
  148. oxidane-0.2.0/src/ml/nn/mpnn.rs +347 -0
  149. oxidane-0.2.0/src/ml/nn/pretrain.rs +300 -0
  150. oxidane-0.2.0/src/ml/nn/seed.rs +274 -0
  151. oxidane-0.2.0/src/ml/nn/tensors.rs +259 -0
  152. oxidane-0.2.0/src/ml/nn/train.rs +879 -0
  153. oxidane-0.2.0/src/ml/normalize.rs +696 -0
  154. oxidane-0.2.0/src/ml/split.rs +312 -0
  155. oxidane-0.2.0/src/ml/tokenize.rs +337 -0
  156. oxidane-0.2.0/src/molecular_formula.rs +576 -0
  157. oxidane-0.2.0/src/molecule/aromaticity.rs +2355 -0
  158. oxidane-0.2.0/src/molecule/base.rs +1705 -0
  159. oxidane-0.2.0/src/molecule/bond.rs +217 -0
  160. oxidane-0.2.0/src/molecule/charges.rs +771 -0
  161. oxidane-0.2.0/src/molecule/chirality.rs +2140 -0
  162. oxidane-0.2.0/src/molecule/cip/configs.rs +435 -0
  163. oxidane-0.2.0/src/molecule/cip/descriptor.rs +144 -0
  164. oxidane-0.2.0/src/molecule/cip/digraph.rs +395 -0
  165. oxidane-0.2.0/src/molecule/cip/mod.rs +670 -0
  166. oxidane-0.2.0/src/molecule/cip/mol.rs +466 -0
  167. oxidane-0.2.0/src/molecule/cip/rules.rs +798 -0
  168. oxidane-0.2.0/src/molecule/crippen.rs +805 -0
  169. oxidane-0.2.0/src/molecule/descriptors.rs +579 -0
  170. oxidane-0.2.0/src/molecule/draw/cleanup.rs +356 -0
  171. oxidane-0.2.0/src/molecule/draw/layout.rs +535 -0
  172. oxidane-0.2.0/src/molecule/draw/stereo.rs +408 -0
  173. oxidane-0.2.0/src/molecule/draw.rs +779 -0
  174. oxidane-0.2.0/src/molecule/embed/bounds.rs +1900 -0
  175. oxidane-0.2.0/src/molecule/embed/chirality.rs +690 -0
  176. oxidane-0.2.0/src/molecule/embed/forcefield.rs +1353 -0
  177. oxidane-0.2.0/src/molecule/embed/fourd.rs +173 -0
  178. oxidane-0.2.0/src/molecule/embed/matrix.rs +81 -0
  179. oxidane-0.2.0/src/molecule/embed/mds.rs +221 -0
  180. oxidane-0.2.0/src/molecule/embed/mod.rs +934 -0
  181. oxidane-0.2.0/src/molecule/embed/planarity.rs +459 -0
  182. oxidane-0.2.0/src/molecule/embed/refine.rs +142 -0
  183. oxidane-0.2.0/src/molecule/embed/tests.rs +60 -0
  184. oxidane-0.2.0/src/molecule/embed/torsion_preferences.rs +918 -0
  185. oxidane-0.2.0/src/molecule/embed/torsion_search.rs +1623 -0
  186. oxidane-0.2.0/src/molecule/experimental.rs +780 -0
  187. oxidane-0.2.0/src/molecule/featurize.rs +989 -0
  188. oxidane-0.2.0/src/molecule/fingerprint/circular.rs +398 -0
  189. oxidane-0.2.0/src/molecule/fingerprint/heavy.rs +117 -0
  190. oxidane-0.2.0/src/molecule/fingerprint/maccs.rs +365 -0
  191. oxidane-0.2.0/src/molecule/fingerprint/minhash.rs +115 -0
  192. oxidane-0.2.0/src/molecule/fingerprint/mod.rs +417 -0
  193. oxidane-0.2.0/src/molecule/fingerprint/pairs.rs +186 -0
  194. oxidane-0.2.0/src/molecule/fingerprint/shingles.rs +157 -0
  195. oxidane-0.2.0/src/molecule/forcefield/lanes.rs +214 -0
  196. oxidane-0.2.0/src/molecule/forcefield/mmff/assign.rs +581 -0
  197. oxidane-0.2.0/src/molecule/forcefield/mmff/charges.rs +250 -0
  198. oxidane-0.2.0/src/molecule/forcefield/mmff/field.rs +483 -0
  199. oxidane-0.2.0/src/molecule/forcefield/mmff/mod.rs +163 -0
  200. oxidane-0.2.0/src/molecule/forcefield/mmff/params.rs +3 -0
  201. oxidane-0.2.0/src/molecule/forcefield/mmff/perception.rs +315 -0
  202. oxidane-0.2.0/src/molecule/forcefield/mmff/terms.rs +997 -0
  203. oxidane-0.2.0/src/molecule/forcefield/mmff/typing.rs +1077 -0
  204. oxidane-0.2.0/src/molecule/forcefield/mod.rs +150 -0
  205. oxidane-0.2.0/src/molecule/forcefield/uff/mod.rs +681 -0
  206. oxidane-0.2.0/src/molecule/forcefield/uff/params.rs +3 -0
  207. oxidane-0.2.0/src/molecule/forcefield/uff/terms.rs +757 -0
  208. oxidane-0.2.0/src/molecule/forcefield/uff/typing.rs +134 -0
  209. oxidane-0.2.0/src/molecule/graph/mod.rs +5 -0
  210. oxidane-0.2.0/src/molecule/graph/molecular_graph.rs +1600 -0
  211. oxidane-0.2.0/src/molecule/graph/node.rs +40 -0
  212. oxidane-0.2.0/src/molecule/mass_spec.rs +1091 -0
  213. oxidane-0.2.0/src/molecule/matching.rs +1299 -0
  214. oxidane-0.2.0/src/molecule/minimize.rs +993 -0
  215. oxidane-0.2.0/src/molecule/mod.rs +46 -0
  216. oxidane-0.2.0/src/molecule/molecular_graph.rs +563 -0
  217. oxidane-0.2.0/src/molecule/molecular_system.rs +198 -0
  218. oxidane-0.2.0/src/molecule/molecule3d.rs +978 -0
  219. oxidane-0.2.0/src/molecule/neighbor_grid.rs +136 -0
  220. oxidane-0.2.0/src/molecule/pi_system.rs +390 -0
  221. oxidane-0.2.0/src/molecule/reaction.rs +2078 -0
  222. oxidane-0.2.0/src/molecule/ring_aromaticity.rs +1572 -0
  223. oxidane-0.2.0/src/molecule/rule_algebra.rs +1013 -0
  224. oxidane-0.2.0/src/molecule/scaffold.rs +243 -0
  225. oxidane-0.2.0/src/molecule/shape.rs +584 -0
  226. oxidane-0.2.0/src/molecule/substructure.rs +84 -0
  227. oxidane-0.2.0/src/molecule/tautomer.rs +4944 -0
  228. oxidane-0.2.0/src/molecule/topology.rs +193 -0
  229. oxidane-0.2.0/src/molecule/traits.rs +8 -0
  230. oxidane-0.2.0/src/molecule/utils.rs +89 -0
  231. oxidane-0.2.0/src/prelude.rs +38 -0
  232. oxidane-0.2.0/src/random.rs +138 -0
  233. oxidane-0.2.0/src/tests/canonization_stress_tests.rs +751 -0
  234. oxidane-0.2.0/src/tests/charges_tests.rs +404 -0
  235. oxidane-0.2.0/src/tests/chiral_canonization_tests.rs +680 -0
  236. oxidane-0.2.0/src/tests/chirality_tests.rs +249 -0
  237. oxidane-0.2.0/src/tests/cip_tests.rs +479 -0
  238. oxidane-0.2.0/src/tests/embed_tests.rs +1186 -0
  239. oxidane-0.2.0/src/tests/fingerprint_tests.rs +1385 -0
  240. oxidane-0.2.0/src/tests/forcefield_tests.rs +268 -0
  241. oxidane-0.2.0/src/tests/inchi_tests.rs +337 -0
  242. oxidane-0.2.0/src/tests/mass_spec_tests.rs +592 -0
  243. oxidane-0.2.0/src/tests/matching_tests.rs +116 -0
  244. oxidane-0.2.0/src/tests/mces_tests.rs +262 -0
  245. oxidane-0.2.0/src/tests/mcsplit_tests.rs +402 -0
  246. oxidane-0.2.0/src/tests/ml_tests.rs +1435 -0
  247. oxidane-0.2.0/src/tests/mmff_tests.rs +303 -0
  248. oxidane-0.2.0/src/tests/mod.rs +26 -0
  249. oxidane-0.2.0/src/tests/nn_tests.rs +2780 -0
  250. oxidane-0.2.0/src/tests/publication_regression_tests.rs +76 -0
  251. oxidane-0.2.0/src/tests/reaction_tests.rs +1042 -0
  252. oxidane-0.2.0/src/tests/ring_aromaticity_tests.rs +429 -0
  253. oxidane-0.2.0/src/tests/sdf_tests.rs +535 -0
  254. oxidane-0.2.0/src/tests/smarts_tests.rs +432 -0
  255. oxidane-0.2.0/src/tests/smiles_tests.rs +1731 -0
  256. oxidane-0.2.0/src/tests/split_tests.rs +484 -0
  257. oxidane-0.2.0/src/tests/tautomer_tests.rs +1947 -0
  258. oxidane-0.2.0/src/vector.rs +1270 -0
  259. oxidane-0.2.0/tests/acceptor_typing.rs +37 -0
  260. oxidane-0.2.0/tests/aromatization_tests.smi +54 -0
  261. oxidane-0.2.0/tests/atom_label_alignment.rs +49 -0
  262. oxidane-0.2.0/tests/bounds_quality.py +204 -0
  263. oxidane-0.2.0/tests/bounds_reference_geometry.tsv +499 -0
  264. oxidane-0.2.0/tests/chiral_canon_oracle.py +74 -0
  265. oxidane-0.2.0/tests/cip_oracle.py +63 -0
  266. oxidane-0.2.0/tests/cis_2_butene.sdf +120 -0
  267. oxidane-0.2.0/tests/cisplatin_sp2.xyz +7 -0
  268. oxidane-0.2.0/tests/component_identity.rs +106 -0
  269. oxidane-0.2.0/tests/crippen_oracle.py +49 -0
  270. oxidane-0.2.0/tests/cyclohexane.xyz +20 -0
  271. oxidane-0.2.0/tests/derive_stereo_tables.py +93 -0
  272. oxidane-0.2.0/tests/draw_oracle.py +23 -0
  273. oxidane-0.2.0/tests/embed_benchmark.py +331 -0
  274. oxidane-0.2.0/tests/embed_budget_benchmark.py +220 -0
  275. oxidane-0.2.0/tests/embed_corpus.tsv +91 -0
  276. oxidane-0.2.0/tests/embed_corpus_arbiter.tsv +311 -0
  277. oxidane-0.2.0/tests/embed_corpus_heldout.tsv +413 -0
  278. oxidane-0.2.0/tests/embed_corpus_pubchem.tsv +291 -0
  279. oxidane-0.2.0/tests/embed_corpus_stress.tsv +81 -0
  280. oxidane-0.2.0/tests/embed_corpus_verification.tsv +1817 -0
  281. oxidane-0.2.0/tests/embed_corpus_verification2.tsv +1217 -0
  282. oxidane-0.2.0/tests/embed_oracle.py +277 -0
  283. oxidane-0.2.0/tests/embed_speed.py +134 -0
  284. oxidane-0.2.0/tests/ethane.xyz +10 -0
  285. oxidane-0.2.0/tests/formula_parsing.rs +41 -0
  286. oxidane-0.2.0/tests/geometry_audit.py +304 -0
  287. oxidane-0.2.0/tests/hbond_acceptors.tsv +53 -0
  288. oxidane-0.2.0/tests/hybridization_oracle.py +36 -0
  289. oxidane-0.2.0/tests/isotope_masses.rs +54 -0
  290. oxidane-0.2.0/tests/maccs_oracle.py +21 -0
  291. oxidane-0.2.0/tests/masked_mean.rs +35 -0
  292. oxidane-0.2.0/tests/mces_embeddings.rs +68 -0
  293. oxidane-0.2.0/tests/mces_many.rs +47 -0
  294. oxidane-0.2.0/tests/mmff_energy_oracle.py +137 -0
  295. oxidane-0.2.0/tests/mmff_oracle.py +189 -0
  296. oxidane-0.2.0/tests/molecule_contains.rs +102 -0
  297. oxidane-0.2.0/tests/molfile_integrity.rs +51 -0
  298. oxidane-0.2.0/tests/ordered_molecules.sdf +1316 -0
  299. oxidane-0.2.0/tests/pentene.sdf +129 -0
  300. oxidane-0.2.0/tests/protomer_oracle.py +154 -0
  301. oxidane-0.2.0/tests/pubchem_normalization_regressions.tsv +8 -0
  302. oxidane-0.2.0/tests/pubchem_stereo_permutation_regressions.tsv +22 -0
  303. oxidane-0.2.0/tests/random_directions.rs +27 -0
  304. oxidane-0.2.0/tests/scaffold_oracle.py +44 -0
  305. oxidane-0.2.0/tests/sdf_properties.rs +45 -0
  306. oxidane-0.2.0/tests/shape_oracle.py +62 -0
  307. oxidane-0.2.0/tests/small_ring_geometry.rs +56 -0
  308. oxidane-0.2.0/tests/smarts_hydrogen.rs +70 -0
  309. oxidane-0.2.0/tests/smarts_incomplete.rs +28 -0
  310. oxidane-0.2.0/tests/smarts_numbers.rs +95 -0
  311. oxidane-0.2.0/tests/smarts_oracle.py +47 -0
  312. oxidane-0.2.0/tests/smarts_stereo.rs +97 -0
  313. oxidane-0.2.0/tests/smarts_tb.rs +49 -0
  314. oxidane-0.2.0/tests/smiles.txt +66 -0
  315. oxidane-0.2.0/tests/smiles_filter.py +65 -0
  316. oxidane-0.2.0/tests/stereo_benchmark.py +165 -0
  317. oxidane-0.2.0/tests/tautomer_oracle.py +226 -0
  318. oxidane-0.2.0/tests/test_forcefield_oracles.py +95 -0
  319. oxidane-0.2.0/tests/trans_2_butene.sdf +121 -0
  320. oxidane-0.2.0/tests/transplatin_sp1.xyz +7 -0
  321. oxidane-0.2.0/tests/transplatin_sp2.xyz +7 -0
  322. oxidane-0.2.0/tests/transplatin_sp3.xyz +7 -0
  323. oxidane-0.2.0/tests/uff_oracle.py +79 -0
  324. oxidane-0.2.0/tests/uff_xtb_probe.py +309 -0
  325. oxidane-0.2.0/tests/valence_validation.rs +59 -0
  326. oxidane-0.2.0/tests/validate_test_smiles.py +63 -0
  327. oxidane-0.2.0/tests/validation_loss.rs +82 -0
  328. oxidane-0.2.0/tests/xtb_oracle.py +153 -0
@@ -0,0 +1,48 @@
1
+ name: Test the Python bindings
2
+
3
+ # Linux only by default; macOS and Windows too when run by hand, on a tag, or
4
+ # on a pull request labelled full-ci. scripts/ci-local.sh runs the same tests.
5
+ on:
6
+ pull_request:
7
+ types: [opened, synchronize, reopened, labeled]
8
+ paths-ignore: ['**.md', 'docs/**', 'assets/**', 'LICENSE']
9
+ push:
10
+ branches: [main]
11
+ tags: ['v*']
12
+ paths-ignore: ['**.md', 'docs/**', 'assets/**', 'LICENSE']
13
+ workflow_dispatch:
14
+
15
+ permissions:
16
+ contents: read
17
+
18
+ concurrency:
19
+ group: ${{ github.workflow }}-${{ github.ref }}
20
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
21
+
22
+ jobs:
23
+ python:
24
+ if: github.event.action != 'labeled' || github.event.label.name == 'full-ci'
25
+ strategy:
26
+ fail-fast: false
27
+ matrix:
28
+ include: >-
29
+ ${{ fromJSON((github.event_name == 'workflow_dispatch' || startsWith(github.ref, 'refs/tags/') || contains(github.event.pull_request.labels.*.name, 'full-ci'))
30
+ && '[{"os":"ubuntu-latest","python":"3.9"},{"os":"ubuntu-latest","python":"3.14"},{"os":"macos-latest","python":"3.12"},{"os":"windows-latest","python":"3.12"}]'
31
+ || '[{"os":"ubuntu-latest","python":"3.9"},{"os":"ubuntu-latest","python":"3.14"}]') }}
32
+ runs-on: ${{ matrix.os }}
33
+ env:
34
+ CARGO_BUILD_JOBS: "1"
35
+ RAYON_NUM_THREADS: "1"
36
+ steps:
37
+ - uses: actions/checkout@v7
38
+ with:
39
+ persist-credentials: false
40
+ - name: Install Rust
41
+ run: rustup toolchain install stable --profile minimal
42
+ - uses: astral-sh/setup-uv@v10.3.0
43
+ with:
44
+ python-version: ${{ matrix.python }}
45
+ - name: Build and install the local bindings and test dependencies
46
+ run: uv sync --locked --project bindings/python --extra notebook
47
+ - name: Test the API and notebook display
48
+ run: uv run --no-sync --project bindings/python pytest bindings/python/tests
@@ -0,0 +1,90 @@
1
+ name: Test and package the library
2
+
3
+ # Linux only on pull requests; macOS and Windows too when run by hand, on a
4
+ # tag, or on a pull request labelled full-ci. scripts/ci-local.sh runs the same
5
+ # checks.
6
+ on:
7
+ pull_request:
8
+ types: [opened, synchronize, reopened, labeled]
9
+ paths-ignore: ['**.md', 'docs/**', 'assets/**', 'LICENSE']
10
+ push:
11
+ tags:
12
+ - 'v*'
13
+ workflow_dispatch:
14
+
15
+ permissions:
16
+ contents: read
17
+
18
+ concurrency:
19
+ group: ${{ github.workflow }}-${{ github.ref }}
20
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
21
+
22
+ defaults:
23
+ run:
24
+ shell: bash
25
+
26
+ jobs:
27
+ test:
28
+ name: Test on ${{ matrix.os }}
29
+ if: github.event.action != 'labeled' || github.event.label.name == 'full-ci'
30
+ runs-on: ${{ matrix.os }}
31
+ strategy:
32
+ fail-fast: false
33
+ matrix:
34
+ os: >-
35
+ ${{ fromJSON((github.event_name == 'workflow_dispatch' || startsWith(github.ref, 'refs/tags/') || contains(github.event.pull_request.labels.*.name, 'full-ci'))
36
+ && '["ubuntu-latest","macos-latest","windows-latest"]' || '["ubuntu-latest"]') }}
37
+ env:
38
+ # Debug info in every example and test binary fills the Linux runner's disk.
39
+ CARGO_PROFILE_DEV_DEBUG: "0"
40
+ CARGO_INCREMENTAL: "0"
41
+ steps:
42
+ - uses: actions/checkout@v7
43
+ with:
44
+ persist-credentials: false
45
+ - name: Install Rust
46
+ run: rustup toolchain install stable --profile minimal
47
+ - uses: Swatinem/rust-cache@v2
48
+ - name: Check every target
49
+ run: cargo +stable check --locked --all-features --all-targets
50
+ - name: Run library, regression and documentation tests
51
+ run: cargo +stable test --locked --all-features
52
+
53
+ release:
54
+ name: Draft a source release
55
+ if: startsWith(github.ref, 'refs/tags/v')
56
+ needs: test
57
+ runs-on: ubuntu-latest
58
+ permissions:
59
+ contents: write
60
+ steps:
61
+ - uses: actions/checkout@v7
62
+ with:
63
+ persist-credentials: false
64
+ - name: Install Rust
65
+ run: rustup toolchain install stable --profile minimal
66
+ - name: Archive the tagged library and verify its contents
67
+ env:
68
+ RELEASE_TAG: ${{ github.ref_name }}
69
+ run: |
70
+ set -euo pipefail
71
+ package_version=$(cargo +stable metadata --no-deps --format-version 1 | jq -r '.packages[] | select(.name == "oxidane") | .version')
72
+ test "$RELEASE_TAG" = "v$package_version"
73
+ release_name="oxidane-$package_version"
74
+ archive_path="$RUNNER_TEMP/$release_name.tar.gz"
75
+ git archive --format=tar --prefix="$release_name/" HEAD | gzip -n > "$archive_path"
76
+ tar -xzf "$archive_path" -C "$RUNNER_TEMP"
77
+ cargo +stable check --locked --all-features --all-targets --manifest-path "$RUNNER_TEMP/$release_name/Cargo.toml"
78
+ (
79
+ cd "$RUNNER_TEMP"
80
+ sha256sum "$release_name.tar.gz" > "$release_name.tar.gz.sha256"
81
+ )
82
+ echo "RELEASE_ARCHIVE=$archive_path" >> "$GITHUB_ENV"
83
+ - name: Create a draft with the source and its checksum
84
+ env:
85
+ GH_TOKEN: ${{ github.token }}
86
+ RELEASE_TAG: ${{ github.ref_name }}
87
+ run: |
88
+ gh release create "$RELEASE_TAG" \
89
+ "$RELEASE_ARCHIVE" "$RELEASE_ARCHIVE.sha256" \
90
+ --verify-tag --draft --generate-notes --title "$RELEASE_TAG"
@@ -0,0 +1,165 @@
1
+ name: Build the Python wheels
2
+
3
+ # Only when run by hand (Actions tab, "Run workflow"), on a tag, or on a pull
4
+ # request labelled full-ci; scripts/ci-local.sh builds the same wheels locally.
5
+ # A v* tag uploads the wheels and sdist to PyPI; a manual run can upload them
6
+ # to TestPyPI instead. Both use trusted publishing, so no token is stored.
7
+ on:
8
+ pull_request:
9
+ types: [opened, synchronize, reopened, labeled]
10
+ push:
11
+ tags:
12
+ - 'v*'
13
+ workflow_dispatch:
14
+ inputs:
15
+ testpypi:
16
+ description: Upload the build to TestPyPI
17
+ type: boolean
18
+ default: false
19
+
20
+ permissions:
21
+ contents: read
22
+
23
+ concurrency:
24
+ group: ${{ github.workflow }}-${{ github.ref }}
25
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
26
+
27
+ defaults:
28
+ run:
29
+ shell: bash
30
+
31
+ jobs:
32
+ wheel:
33
+ name: Wheel for ${{ matrix.name }}
34
+ if: >-
35
+ github.event_name != 'pull_request'
36
+ || (contains(github.event.pull_request.labels.*.name, 'full-ci')
37
+ && (github.event.action != 'labeled' || github.event.label.name == 'full-ci'))
38
+ runs-on: ${{ matrix.runner }}
39
+ strategy:
40
+ fail-fast: false
41
+ matrix:
42
+ include:
43
+ - { name: Linux x86-64, runner: ubuntu-latest, target: x86_64, manylinux: '2014', image: 'python:3.12-slim', platform: linux/amd64 }
44
+ - { name: Linux ARM64, runner: ubuntu-latest, target: aarch64, manylinux: '2014', image: 'python:3.12-slim', platform: linux/arm64 }
45
+ - { name: Linux x86-64 musl, runner: ubuntu-latest, target: x86_64, manylinux: musllinux_1_2, image: 'python:3.12-alpine', platform: linux/amd64 }
46
+ - { name: Linux ARM64 musl, runner: ubuntu-latest, target: aarch64, manylinux: musllinux_1_2, image: 'python:3.12-alpine', platform: linux/arm64 }
47
+ - { name: macOS Intel, runner: macos-15-intel, target: x86_64, native: true }
48
+ - { name: macOS Apple silicon, runner: macos-latest, target: aarch64, native: true }
49
+ - { name: Windows x64, runner: windows-latest, target: x64, native: true }
50
+ - { name: Windows ARM64, runner: windows-latest, target: aarch64 }
51
+ steps:
52
+ - uses: actions/checkout@v7
53
+ with:
54
+ persist-credentials: false
55
+ - uses: actions/setup-python@v6
56
+ with:
57
+ python-version: '3.12'
58
+ - name: Build an abi3 wheel
59
+ uses: PyO3/maturin-action@v1
60
+ with:
61
+ working-directory: bindings/python
62
+ target: ${{ matrix.target }}
63
+ manylinux: ${{ matrix.manylinux || 'auto' }}
64
+ args: --release --locked --out dist
65
+ - name: Set up emulation for the Linux test container
66
+ if: matrix.platform == 'linux/arm64'
67
+ uses: docker/setup-qemu-action@v3
68
+ - name: Install the wheel and normalize a file (Linux container)
69
+ if: matrix.image
70
+ run: |
71
+ docker run --rm --platform ${{ matrix.platform }} -v "$PWD/bindings/python:/io" -w /tmp ${{ matrix.image }} sh -euc '
72
+ pip install --quiet /io/dist/*.whl
73
+ printf "id,smiles\n1,Oc1ccccn1\n" > in.csv
74
+ oxidane-normalize in.csv out.csv -s smiles
75
+ grep -q "O=c1\[nH\]cccc1" out.csv
76
+ python -c "import oxidane as ox; assert ox.canonical_tautomer(\"Oc1ccccn1\") == \"O=c1[nH]cccc1\""'
77
+ - name: Install the wheel and normalize a file
78
+ if: matrix.native
79
+ run: |
80
+ python -m venv "$RUNNER_TEMP/venv"
81
+ if [ -d "$RUNNER_TEMP/venv/Scripts" ]; then bin="$RUNNER_TEMP/venv/Scripts"; else bin="$RUNNER_TEMP/venv/bin"; fi
82
+ "$bin/python" -m pip install --quiet bindings/python/dist/*.whl
83
+ cd "$RUNNER_TEMP"
84
+ printf 'id,smiles\n1,Oc1ccccn1\n' > in.csv
85
+ "$bin/oxidane-normalize" in.csv out.csv -s smiles
86
+ grep -q 'O=c1\[nH\]cccc1' out.csv
87
+ "$bin/python" -c 'import oxidane as ox; assert ox.canonical_tautomer("Oc1ccccn1") == "O=c1[nH]cccc1"'
88
+ - uses: actions/upload-artifact@v5
89
+ with:
90
+ name: wheel-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.manylinux || 'native' }}
91
+ path: bindings/python/dist/*.whl
92
+
93
+ sdist:
94
+ name: Source distribution
95
+ needs: wheel
96
+ runs-on: ubuntu-latest
97
+ steps:
98
+ - uses: actions/checkout@v7
99
+ with:
100
+ persist-credentials: false
101
+ - uses: PyO3/maturin-action@v1
102
+ with:
103
+ working-directory: bindings/python
104
+ command: sdist
105
+ args: --out dist
106
+ - uses: actions/upload-artifact@v5
107
+ with:
108
+ name: sdist
109
+ path: bindings/python/dist/*.tar.gz
110
+
111
+ wheels:
112
+ name: All wheels in one download
113
+ needs: [wheel, sdist]
114
+ runs-on: ubuntu-latest
115
+ steps:
116
+ - uses: actions/download-artifact@v6
117
+ with:
118
+ path: dist
119
+ merge-multiple: true
120
+ - run: ls -l dist
121
+ - uses: actions/upload-artifact@v5
122
+ with:
123
+ name: oxidane-python-wheels
124
+ path: dist/*
125
+
126
+ publish:
127
+ name: Publish to ${{ startsWith(github.ref, 'refs/tags/v') && 'PyPI' || 'TestPyPI' }}
128
+ needs: wheels
129
+ if: >-
130
+ (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v'))
131
+ || (github.event_name == 'workflow_dispatch' && inputs.testpypi)
132
+ runs-on: ubuntu-latest
133
+ environment:
134
+ name: ${{ startsWith(github.ref, 'refs/tags/v') && 'pypi' || 'testpypi' }}
135
+ url: ${{ startsWith(github.ref, 'refs/tags/v') && 'https://pypi.org/p/oxidane' || 'https://test.pypi.org/p/oxidane' }}
136
+ permissions:
137
+ id-token: write
138
+ steps:
139
+ - uses: actions/checkout@v7
140
+ with:
141
+ persist-credentials: false
142
+ - name: Check that the tag matches the package versions
143
+ if: startsWith(github.ref, 'refs/tags/v')
144
+ env:
145
+ RELEASE_TAG: ${{ github.ref_name }}
146
+ run: |
147
+ set -euo pipefail
148
+ for manifest in Cargo.toml bindings/python/Cargo.toml bindings/python/pyproject.toml; do
149
+ version=$(sed -n 's/^version = "\(.*\)"$/\1/p' "$manifest" | head -1)
150
+ echo "$manifest: $version"
151
+ test "$RELEASE_TAG" = "v$version"
152
+ done
153
+ - uses: actions/download-artifact@v6
154
+ with:
155
+ name: oxidane-python-wheels
156
+ path: dist
157
+ - run: ls -l dist
158
+ - name: Upload to PyPI
159
+ if: startsWith(github.ref, 'refs/tags/v')
160
+ uses: pypa/gh-action-pypi-publish@release/v1
161
+ - name: Upload to TestPyPI
162
+ if: "!startsWith(github.ref, 'refs/tags/v')"
163
+ uses: pypa/gh-action-pypi-publish@release/v1
164
+ with:
165
+ repository-url: https://test.pypi.org/legacy/
@@ -0,0 +1,14 @@
1
+ target/
2
+ src/test_io.sh
3
+ git_pusher.sh
4
+ __pycache__/
5
+ .DS_Store
6
+ flamegraph.sh
7
+ # Written by the ignored canonicalization benchmark
8
+ tests/wrong_smiles.txt
9
+
10
+ # Local working notes, not for publication
11
+ notes/
12
+ manuscript/
13
+ publication/
14
+ examples/publication.rs
@@ -0,0 +1,18 @@
1
+ cff-version: 1.2.0
2
+ message: "If you use oxidane, please cite it as below."
3
+ title: "oxidane: a cheminformatics toolkit in Rust"
4
+ type: software
5
+ license: MIT
6
+ repository-code: "https://github.com/um-univie/oxidane"
7
+ version: 0.2.0
8
+ authors:
9
+ - family-names: Uhlir
10
+ given-names: Manuel
11
+ affiliation: "University of Vienna"
12
+ keywords:
13
+ - cheminformatics
14
+ - Rust
15
+ - SMILES
16
+ - canonicalization
17
+ - tautomers
18
+ - conformer generation
@@ -0,0 +1,18 @@
1
+ # Code of Conduct
2
+
3
+ This project adopts the [Contributor Covenant, version 2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct/).
4
+
5
+ We are committed to a harassment-free experience for everyone, regardless of
6
+ age, body size, visible or invisible disability, ethnicity, sex
7
+ characteristics, gender identity and expression, level of experience,
8
+ education, socio-economic status, nationality, personal appearance, race,
9
+ religion, or sexual identity and orientation.
10
+
11
+ Be respectful and constructive in issues, pull requests and discussions.
12
+ Harassment, personal attacks and publishing others' private information are
13
+ not tolerated.
14
+
15
+ Report unacceptable behaviour to the maintainers at <manuel.uhlir@univie.ac.at>.
16
+ Reports are handled confidentially. Maintainers may remove comments, commits
17
+ or contributions that violate this code, and may ban contributors temporarily
18
+ or permanently.
@@ -0,0 +1,40 @@
1
+ # Contributing to oxidane
2
+
3
+ Bug reports, questions and pull requests are welcome.
4
+
5
+ ## Reporting problems
6
+
7
+ Open an issue at <https://github.com/um-univie/oxidane/issues>. For a wrong
8
+ chemical result, include the input (SMILES, SMARTS or a minimal SDF), what
9
+ oxidane returned, what you expected, and if possible what RDKit or another
10
+ toolkit returns. State the oxidane version or commit.
11
+
12
+ ## Development setup
13
+
14
+ ```sh
15
+ git clone https://github.com/um-univie/oxidane
16
+ cd oxidane
17
+ cargo test --locked --all-features
18
+ ```
19
+
20
+ Python bindings live in `bindings/python` and are built with maturin:
21
+
22
+ ```sh
23
+ cd bindings/python
24
+ uv run maturin develop
25
+ uv run pytest
26
+ ```
27
+
28
+ ## Pull requests
29
+
30
+ - Branch from `main`; keep a pull request to one change.
31
+ - Add a test for every bug fix and new feature. Chemistry fixes should include
32
+ the molecule that exposed the problem.
33
+ - Run `cargo fmt`, `cargo clippy --all-targets --all-features` and
34
+ `cargo test --locked --all-features` before pushing.
35
+ - Code derived from other projects must be license-compatible with MIT and
36
+ recorded in `THIRD_PARTY.md`.
37
+
38
+ ## Code of conduct
39
+
40
+ This project follows the [Code of Conduct](CODE_OF_CONDUCT.md).