chemicalml 0.2.0 → 0.3.0

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 (450) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/release.yml +7 -1
  3. data/.rubocop.yml +23 -0
  4. data/CLAUDE.md +95 -40
  5. data/README.adoc +154 -26
  6. data/TODO.align/36-molecular-convention-coverage.md +46 -0
  7. data/TODO.align/37-compchem-convention-coverage.md +55 -0
  8. data/TODO.align/38-dictionary-convention-coverage.md +34 -0
  9. data/TODO.align/39-unit-dictionary-convention-coverage.md +33 -0
  10. data/TODO.align/40-unit-type-dictionary-convention-coverage.md +28 -0
  11. data/TODO.align/41-expand-canonical-model-layer.md +43 -0
  12. data/TODO.align/42-translator-wire-new-models.md +31 -0
  13. data/TODO.align/43-dictionary-model-no-to-h.md +39 -0
  14. data/TODO.align/44-schema3-only-and-schema24-module.md +44 -0
  15. data/TODO.align/45-documentation-and-final-verification.md +23 -0
  16. data/TODO.align/46-lattice-vector-content.md +24 -0
  17. data/TODO.align/47-molecule-crystal-spectra-property-lists.md +23 -0
  18. data/TODO.align/48-model-list-and-module-lists.md +21 -0
  19. data/TODO.align/49-more-chemistry-models.md +34 -0
  20. data/TODO.align/50-validation-report.md +29 -0
  21. data/TODO.align/51-convention-auto-detection.md +30 -0
  22. data/TODO.align/52-schema24-legacy-elements.md +28 -0
  23. data/TODO.align/53-round-trip-integration-specs.md +30 -0
  24. data/TODO.align/54-document-versioned-parser-shim.md +38 -0
  25. data/TODO.align/55-molecule-missing-attributes.md +20 -0
  26. data/TODO.align/56-geometry-models.md +24 -0
  27. data/TODO.align/57-compchem-models.md +26 -0
  28. data/TODO.align/58-remaining-models.md +24 -0
  29. data/TODO.align/59-wire-new-models-translator.md +18 -0
  30. data/TODO.align/60-docs-and-final-verification.md +19 -0
  31. data/TODO.align/61-parallel-array-attrs.md +54 -0
  32. data/TODO.align/62-per-element-attribute-gaps.md +49 -0
  33. data/TODO.align/63-universal-children-mixin.md +42 -0
  34. data/TODO.align/64-per-element-child-gaps.md +81 -0
  35. data/TODO.align/65-simple-unit-convention.md +40 -0
  36. data/TODO.align/66-schema24-legacy-children.md +32 -0
  37. data/TODO.align/67-final-verification.md +32 -0
  38. data/TODO.align/68-detection-coverage.md +33 -0
  39. data/TODO.align/69-json-yaml-roundtrip.md +27 -0
  40. data/TODO.align/70-iterative-walker.md +40 -0
  41. data/TODO.align/71-violation-value.md +25 -0
  42. data/TODO.align/72-close-child-gaps.md +66 -0
  43. data/TODO.align/73-schema24-parse-limitation.md +64 -0
  44. data/TODO.align/74-final-verification-round18.md +15 -0
  45. data/TODO.align/75-key-value-mappings.md +43 -0
  46. data/TODO.align/76-schema24-workaround.md +57 -0
  47. data/TODO.align/77-convention-coverage-matrix.md +31 -0
  48. data/TODO.align/78-fixture-audit.md +23 -0
  49. data/TODO.align/79-final-verification-round19.md +15 -0
  50. data/TODO.align/80-xsd-enum-constants.md +35 -0
  51. data/TODO.align/81-enum-validation-constraints.md +29 -0
  52. data/TODO.align/82-reference-resolver.md +33 -0
  53. data/TODO.align/83-toml-roundtrip.md +20 -0
  54. data/TODO.align/84-final-verification-round21.md +16 -0
  55. data/TODO.align/85-bond-distinct-atoms.md +25 -0
  56. data/TODO.align/86-references-should-resolve.md +20 -0
  57. data/TODO.align/87-cli-utility.md +26 -0
  58. data/TODO.align/88-diverse-fixtures.md +26 -0
  59. data/TODO.align/89-final-verification-round22.md +15 -0
  60. data/TODO.align/90-bond-stereo-completeness.md +31 -0
  61. data/TODO.align/91-atomparity-distinct.md +21 -0
  62. data/TODO.align/92-unit-dictionary-completeness.md +28 -0
  63. data/TODO.align/93-yard-docs.md +23 -0
  64. data/TODO.align/94-final-verification-round23.md +15 -0
  65. data/TODO.align/README.round17.md +28 -0
  66. data/TODO.align/README.round18.md +37 -0
  67. data/TODO.align/README.round19.md +40 -0
  68. data/TODO.align/README.round20.md +49 -0
  69. data/TODO.align/README.round21.md +35 -0
  70. data/TODO.align/README.round22.md +48 -0
  71. data/TODO.align/README.round23.md +46 -0
  72. data/TODO.align/README.round24.md +53 -0
  73. data/TODO.align/README.round25.md +66 -0
  74. data/TODO.align/README.round26.md +55 -0
  75. data/TODO.align/README.round27.md +51 -0
  76. data/TODO.align/README.round28.md +61 -0
  77. data/TODO.align/README.round29.md +64 -0
  78. data/TODO.align/README.round30.md +50 -0
  79. data/TODO.align/README.round31.md +54 -0
  80. data/TODO.align/README.round32.md +67 -0
  81. data/TODO.align/README.round33.md +62 -0
  82. data/TODO.align/README.round34.md +70 -0
  83. data/docs/constraints.md +161 -0
  84. data/docs/generate_constraint_docs.rb +44 -0
  85. data/exe/chemicalml +6 -0
  86. data/lib/chemicalml/cli/base.rb +68 -0
  87. data/lib/chemicalml/cli/command.rb +43 -0
  88. data/lib/chemicalml/cli/constraints_command.rb +27 -0
  89. data/lib/chemicalml/cli/conventions_command.rb +14 -0
  90. data/lib/chemicalml/cli/dictionaries_command.rb +14 -0
  91. data/lib/chemicalml/cli/elements_command.rb +17 -0
  92. data/lib/chemicalml/cli/enums_command.rb +17 -0
  93. data/lib/chemicalml/cli/info_command.rb +77 -0
  94. data/lib/chemicalml/cli/inspect_command.rb +39 -0
  95. data/lib/chemicalml/cli/validate_command.rb +54 -0
  96. data/lib/chemicalml/cli.rb +43 -0
  97. data/lib/chemicalml/cml/base/abundance.rb +21 -5
  98. data/lib/chemicalml/cml/base/action.rb +44 -6
  99. data/lib/chemicalml/cml/base/action_list.rb +44 -8
  100. data/lib/chemicalml/cml/base/alternative.rb +37 -0
  101. data/lib/chemicalml/cml/base/amount.rb +15 -5
  102. data/lib/chemicalml/cml/base/angle.rb +34 -7
  103. data/lib/chemicalml/cml/base/annotation.rb +38 -0
  104. data/lib/chemicalml/cml/base/any_cml.rb +12 -5
  105. data/lib/chemicalml/cml/base/appinfo.rb +40 -0
  106. data/lib/chemicalml/cml/base/arg.rb +80 -0
  107. data/lib/chemicalml/cml/base/array.rb +51 -8
  108. data/lib/chemicalml/cml/base/array_list.rb +15 -5
  109. data/lib/chemicalml/cml/base/atom.rb +93 -19
  110. data/lib/chemicalml/cml/base/atom_array.rb +77 -2
  111. data/lib/chemicalml/cml/base/atom_parity.rb +18 -2
  112. data/lib/chemicalml/cml/base/atom_set.rb +15 -5
  113. data/lib/chemicalml/cml/base/atom_type.rb +27 -7
  114. data/lib/chemicalml/cml/base/atom_type_list.rb +23 -7
  115. data/lib/chemicalml/cml/base/atomic_basis_function.rb +35 -11
  116. data/lib/chemicalml/cml/base/band.rb +22 -7
  117. data/lib/chemicalml/cml/base/band_list.rb +15 -7
  118. data/lib/chemicalml/cml/base/basis_set.rb +26 -7
  119. data/lib/chemicalml/cml/base/bond.rb +39 -7
  120. data/lib/chemicalml/cml/base/bond_array.rb +41 -2
  121. data/lib/chemicalml/cml/base/bond_set.rb +15 -5
  122. data/lib/chemicalml/cml/base/bond_stereo.rb +25 -4
  123. data/lib/chemicalml/cml/base/bond_type.rb +24 -7
  124. data/lib/chemicalml/cml/base/bond_type_list.rb +23 -7
  125. data/lib/chemicalml/cml/base/cell_parameter.rb +30 -8
  126. data/lib/chemicalml/cml/base/cml_module.rb +36 -11
  127. data/lib/chemicalml/cml/base/common_children.rb +35 -0
  128. data/lib/chemicalml/cml/base/complex_object.rb +37 -0
  129. data/lib/chemicalml/cml/base/condition_list.rb +28 -8
  130. data/lib/chemicalml/cml/base/crystal.rb +27 -9
  131. data/lib/chemicalml/cml/base/definition.rb +12 -5
  132. data/lib/chemicalml/cml/base/description.rb +15 -5
  133. data/lib/chemicalml/cml/base/dictionary.rb +30 -7
  134. data/lib/chemicalml/cml/base/dictionary_entry.rb +67 -8
  135. data/lib/chemicalml/cml/base/dimension.rb +31 -7
  136. data/lib/chemicalml/cml/base/document.rb +18 -8
  137. data/lib/chemicalml/cml/base/documentation.rb +12 -5
  138. data/lib/chemicalml/cml/base/eigen.rb +33 -7
  139. data/lib/chemicalml/cml/base/electron.rb +29 -9
  140. data/lib/chemicalml/cml/base/enumeration.rb +41 -0
  141. data/lib/chemicalml/cml/base/expression.rb +47 -0
  142. data/lib/chemicalml/cml/base/float.rb +52 -0
  143. data/lib/chemicalml/cml/base/float_array.rb +55 -0
  144. data/lib/chemicalml/cml/base/formula.rb +31 -10
  145. data/lib/chemicalml/cml/base/fragment.rb +33 -9
  146. data/lib/chemicalml/cml/base/fragment_list.rb +26 -7
  147. data/lib/chemicalml/cml/base/gradient.rb +19 -6
  148. data/lib/chemicalml/cml/base/identifier.rb +22 -4
  149. data/lib/chemicalml/cml/base/integer.rb +52 -0
  150. data/lib/chemicalml/cml/base/integer_array.rb +55 -0
  151. data/lib/chemicalml/cml/base/isotope.rb +29 -8
  152. data/lib/chemicalml/cml/base/isotope_list.rb +18 -7
  153. data/lib/chemicalml/cml/base/join.rb +28 -6
  154. data/lib/chemicalml/cml/base/kpoint.rb +17 -6
  155. data/lib/chemicalml/cml/base/kpoint_list.rb +15 -7
  156. data/lib/chemicalml/cml/base/label.rb +15 -5
  157. data/lib/chemicalml/cml/base/lattice.rb +36 -9
  158. data/lib/chemicalml/cml/base/lattice_vector.rb +17 -6
  159. data/lib/chemicalml/cml/base/length.rb +31 -7
  160. data/lib/chemicalml/cml/base/line3.rb +21 -5
  161. data/lib/chemicalml/cml/base/link.rb +51 -10
  162. data/lib/chemicalml/cml/base/list.rb +23 -9
  163. data/lib/chemicalml/cml/base/map.rb +38 -5
  164. data/lib/chemicalml/cml/base/matrix.rb +38 -9
  165. data/lib/chemicalml/cml/base/mechanism.rb +20 -7
  166. data/lib/chemicalml/cml/base/mechanism_component.rb +14 -6
  167. data/lib/chemicalml/cml/base/metadata.rb +20 -6
  168. data/lib/chemicalml/cml/base/metadata_list.rb +30 -5
  169. data/lib/chemicalml/cml/base/molecule.rb +95 -21
  170. data/lib/chemicalml/cml/base/molecule_list.rb +27 -7
  171. data/lib/chemicalml/cml/base/name.rb +11 -3
  172. data/lib/chemicalml/cml/base/object.rb +20 -6
  173. data/lib/chemicalml/cml/base/observation.rb +18 -5
  174. data/lib/chemicalml/cml/base/operator.rb +40 -0
  175. data/lib/chemicalml/cml/base/parameter.rb +38 -8
  176. data/lib/chemicalml/cml/base/parameter_list.rb +30 -5
  177. data/lib/chemicalml/cml/base/particle.rb +23 -6
  178. data/lib/chemicalml/cml/base/peak.rb +86 -11
  179. data/lib/chemicalml/cml/base/peak_group.rb +81 -7
  180. data/lib/chemicalml/cml/base/peak_list.rb +25 -8
  181. data/lib/chemicalml/cml/base/peak_structure.rb +47 -6
  182. data/lib/chemicalml/cml/base/plane3.rb +15 -5
  183. data/lib/chemicalml/cml/base/point3.rb +15 -5
  184. data/lib/chemicalml/cml/base/potential.rb +17 -6
  185. data/lib/chemicalml/cml/base/potential_form.rb +31 -6
  186. data/lib/chemicalml/cml/base/potential_list.rb +15 -7
  187. data/lib/chemicalml/cml/base/product.rb +53 -2
  188. data/lib/chemicalml/cml/base/product_list.rb +36 -2
  189. data/lib/chemicalml/cml/base/property.rb +32 -8
  190. data/lib/chemicalml/cml/base/property_list.rb +26 -5
  191. data/lib/chemicalml/cml/base/reactant.rb +53 -2
  192. data/lib/chemicalml/cml/base/reactant_list.rb +36 -2
  193. data/lib/chemicalml/cml/base/reaction.rb +82 -12
  194. data/lib/chemicalml/cml/base/reaction_list.rb +29 -2
  195. data/lib/chemicalml/cml/base/reaction_scheme.rb +48 -8
  196. data/lib/chemicalml/cml/base/reaction_step.rb +33 -9
  197. data/lib/chemicalml/cml/base/reaction_step_list.rb +34 -7
  198. data/lib/chemicalml/cml/base/reactive_centre.rb +31 -6
  199. data/lib/chemicalml/cml/base/region.rb +24 -5
  200. data/lib/chemicalml/cml/base/related_entry.rb +34 -0
  201. data/lib/chemicalml/cml/base/sample.rb +32 -5
  202. data/lib/chemicalml/cml/base/scalar.rb +41 -6
  203. data/lib/chemicalml/cml/base/spectator.rb +26 -5
  204. data/lib/chemicalml/cml/base/spectator_list.rb +20 -7
  205. data/lib/chemicalml/cml/base/spectrum.rb +63 -12
  206. data/lib/chemicalml/cml/base/spectrum_data.rb +20 -8
  207. data/lib/chemicalml/cml/base/spectrum_list.rb +30 -7
  208. data/lib/chemicalml/cml/base/sphere3.rb +15 -5
  209. data/lib/chemicalml/cml/base/stmml.rb +12 -5
  210. data/lib/chemicalml/cml/base/string.rb +40 -0
  211. data/lib/chemicalml/cml/base/string_array.rb +52 -0
  212. data/lib/chemicalml/cml/base/substance.rb +42 -8
  213. data/lib/chemicalml/cml/base/substance_list.rb +32 -7
  214. data/lib/chemicalml/cml/base/symmetry.rb +33 -7
  215. data/lib/chemicalml/cml/base/system.rb +23 -8
  216. data/lib/chemicalml/cml/base/table.rb +43 -8
  217. data/lib/chemicalml/cml/base/table_cell.rb +12 -5
  218. data/lib/chemicalml/cml/base/table_content.rb +20 -8
  219. data/lib/chemicalml/cml/base/table_header.rb +15 -7
  220. data/lib/chemicalml/cml/base/table_header_cell.rb +27 -5
  221. data/lib/chemicalml/cml/base/table_row.rb +15 -7
  222. data/lib/chemicalml/cml/base/table_row_list.rb +15 -7
  223. data/lib/chemicalml/cml/base/tcell.rb +43 -0
  224. data/lib/chemicalml/cml/base/torsion.rb +34 -7
  225. data/lib/chemicalml/cml/base/transform3.rb +12 -5
  226. data/lib/chemicalml/cml/base/transition_state.rb +23 -5
  227. data/lib/chemicalml/cml/base/trow.rb +48 -0
  228. data/lib/chemicalml/cml/base/unit.rb +45 -10
  229. data/lib/chemicalml/cml/base/unit_list.rb +40 -6
  230. data/lib/chemicalml/cml/base/unit_type.rb +32 -5
  231. data/lib/chemicalml/cml/base/unit_type_list.rb +34 -6
  232. data/lib/chemicalml/cml/base/vector3.rb +15 -5
  233. data/lib/chemicalml/cml/base/xaxis.rb +33 -7
  234. data/lib/chemicalml/cml/base/yaxis.rb +33 -7
  235. data/lib/chemicalml/cml/base/z_matrix.rb +26 -5
  236. data/lib/chemicalml/cml/base.rb +139 -121
  237. data/lib/chemicalml/cml/canonical_comparison.rb +54 -0
  238. data/lib/chemicalml/cml/elements.rb +168 -124
  239. data/lib/chemicalml/cml/enums.rb +55 -0
  240. data/lib/chemicalml/cml/namespace.rb +2 -3
  241. data/lib/chemicalml/cml/patterns.rb +33 -0
  242. data/lib/chemicalml/cml/reference_resolver.rb +137 -0
  243. data/lib/chemicalml/cml/role/alternative.rb +10 -0
  244. data/lib/chemicalml/cml/role/annotation.rb +10 -0
  245. data/lib/chemicalml/cml/role/appinfo.rb +10 -0
  246. data/lib/chemicalml/cml/role/arg.rb +10 -0
  247. data/lib/chemicalml/cml/role/cml_module.rb +2 -3
  248. data/lib/chemicalml/cml/role/complex_object.rb +10 -0
  249. data/lib/chemicalml/cml/role/enumeration.rb +10 -0
  250. data/lib/chemicalml/cml/role/expression.rb +10 -0
  251. data/lib/chemicalml/cml/role/float.rb +10 -0
  252. data/lib/chemicalml/cml/role/float_array.rb +10 -0
  253. data/lib/chemicalml/cml/role/integer.rb +10 -0
  254. data/lib/chemicalml/cml/role/integer_array.rb +10 -0
  255. data/lib/chemicalml/cml/role/operator.rb +10 -0
  256. data/lib/chemicalml/cml/role/related_entry.rb +10 -0
  257. data/lib/chemicalml/cml/role/string.rb +10 -0
  258. data/lib/chemicalml/cml/role/string_array.rb +10 -0
  259. data/lib/chemicalml/cml/role/tcell.rb +10 -0
  260. data/lib/chemicalml/cml/role/trow.rb +10 -0
  261. data/lib/chemicalml/cml/role.rb +138 -121
  262. data/lib/chemicalml/cml/schema24/alternative.rb +14 -0
  263. data/lib/chemicalml/cml/schema24/annotation.rb +15 -0
  264. data/lib/chemicalml/cml/schema24/appinfo.rb +15 -0
  265. data/lib/chemicalml/cml/schema24/arg.rb +14 -0
  266. data/lib/chemicalml/cml/schema24/cml_module.rb +18 -0
  267. data/lib/chemicalml/cml/schema24/complex_object.rb +14 -0
  268. data/lib/chemicalml/cml/schema24/configuration.rb +15 -2
  269. data/lib/chemicalml/cml/schema24/enumeration.rb +16 -0
  270. data/lib/chemicalml/cml/schema24/expression.rb +14 -0
  271. data/lib/chemicalml/cml/schema24/float.rb +14 -0
  272. data/lib/chemicalml/cml/schema24/float_array.rb +14 -0
  273. data/lib/chemicalml/cml/schema24/integer.rb +14 -0
  274. data/lib/chemicalml/cml/schema24/integer_array.rb +14 -0
  275. data/lib/chemicalml/cml/schema24/operator.rb +14 -0
  276. data/lib/chemicalml/cml/schema24/related_entry.rb +14 -0
  277. data/lib/chemicalml/cml/schema24/string.rb +14 -0
  278. data/lib/chemicalml/cml/schema24/string_array.rb +14 -0
  279. data/lib/chemicalml/cml/schema24/tcell.rb +14 -0
  280. data/lib/chemicalml/cml/schema24/trow.rb +14 -0
  281. data/lib/chemicalml/cml/schema24.rb +154 -126
  282. data/lib/chemicalml/cml/schema3.rb +123 -123
  283. data/lib/chemicalml/cml/visitable.rb +77 -3
  284. data/lib/chemicalml/cml/wire_class_registry.rb +3 -3
  285. data/lib/chemicalml/cml.rb +164 -132
  286. data/lib/chemicalml/context_configuration.rb +12 -4
  287. data/lib/chemicalml/convention/base.rb +17 -3
  288. data/lib/chemicalml/convention/cascade/constraints/reaction_scheme_must_have_content.rb +33 -0
  289. data/lib/chemicalml/convention/cascade/constraints/reaction_step_list_must_contain_steps.rb +31 -0
  290. data/lib/chemicalml/convention/cascade/constraints/reaction_step_must_have_reaction_or_lists.rb +33 -0
  291. data/lib/chemicalml/convention/cascade/constraints/reactive_centre_atom_refs_should_be_present.rb +34 -0
  292. data/lib/chemicalml/convention/cascade/constraints.rb +18 -0
  293. data/lib/chemicalml/convention/cascade.rb +43 -0
  294. data/lib/chemicalml/convention/compchem/constraints/array_rules.rb +44 -0
  295. data/lib/chemicalml/convention/compchem/constraints/calculation_requires_finalization.rb +28 -0
  296. data/lib/chemicalml/convention/compchem/constraints/compchem_module_must_contain_job_list.rb +5 -4
  297. data/lib/chemicalml/convention/compchem/constraints/environment_at_most_one_property_list.rb +26 -0
  298. data/lib/chemicalml/convention/compchem/constraints/environment_must_not_contain_parameter.rb +28 -0
  299. data/lib/chemicalml/convention/compchem/constraints/finalization_at_most_one_molecule.rb +26 -0
  300. data/lib/chemicalml/convention/compchem/constraints/finalization_at_most_one_property_list.rb +26 -0
  301. data/lib/chemicalml/convention/compchem/constraints/finalization_must_have_content.rb +44 -0
  302. data/lib/chemicalml/convention/compchem/constraints/finalization_must_not_contain_parameter.rb +27 -0
  303. data/lib/chemicalml/convention/compchem/constraints/initialization_at_most_one_molecule.rb +26 -0
  304. data/lib/chemicalml/convention/compchem/constraints/initialization_at_most_one_parameter_list.rb +26 -0
  305. data/lib/chemicalml/convention/compchem/constraints/initialization_must_have_content.rb +54 -0
  306. data/lib/chemicalml/convention/compchem/constraints/initialization_must_not_contain_property.rb +28 -0
  307. data/lib/chemicalml/convention/compchem/constraints/job_list_module_must_have_id.rb +25 -0
  308. data/lib/chemicalml/convention/compchem/constraints/job_module_at_most_one_environment.rb +25 -0
  309. data/lib/chemicalml/convention/compchem/constraints/job_module_at_most_one_finalization.rb +25 -0
  310. data/lib/chemicalml/convention/compchem/constraints/job_module_must_have_id.rb +25 -0
  311. data/lib/chemicalml/convention/compchem/constraints/job_must_contain_initialization.rb +7 -9
  312. data/lib/chemicalml/convention/compchem/constraints/matrix_rules.rb +48 -0
  313. data/lib/chemicalml/convention/compchem/constraints/module_predicates.rb +50 -0
  314. data/lib/chemicalml/convention/compchem/constraints/scalar_units.rb +42 -0
  315. data/lib/chemicalml/convention/compchem/constraints.rb +40 -2
  316. data/lib/chemicalml/convention/compchem.rb +20 -2
  317. data/lib/chemicalml/convention/constraint.rb +68 -24
  318. data/lib/chemicalml/convention/coordinator.rb +90 -0
  319. data/lib/chemicalml/convention/detection.rb +39 -0
  320. data/lib/chemicalml/convention/dictionary/constraints/dictionary_must_have_namespace.rb +29 -0
  321. data/lib/chemicalml/convention/dictionary/constraints/dictionary_namespace_should_end_with_slash_or_hash.rb +32 -0
  322. data/lib/chemicalml/convention/dictionary/constraints/entry_id_must_match_pattern.rb +33 -0
  323. data/lib/chemicalml/convention/dictionary/constraints/entry_ids_unique_within_dictionary.rb +4 -4
  324. data/lib/chemicalml/convention/dictionary/constraints/entry_must_contain_definition.rb +29 -0
  325. data/lib/chemicalml/convention/dictionary/constraints/entry_must_have_id_and_term.rb +6 -6
  326. data/lib/chemicalml/convention/dictionary/constraints/entry_must_have_unit_type.rb +31 -0
  327. data/lib/chemicalml/convention/dictionary/constraints/entry_units_co_constraints.rb +44 -0
  328. data/lib/chemicalml/convention/dictionary/constraints.rb +14 -2
  329. data/lib/chemicalml/convention/dictionary.rb +8 -2
  330. data/lib/chemicalml/convention/molecular/constraints/atom_array_must_be_child_of_molecule_or_formula.rb +41 -0
  331. data/lib/chemicalml/convention/molecular/constraints/atom_array_must_contain_atoms.rb +18 -9
  332. data/lib/chemicalml/convention/molecular/constraints/atom_coordinates_must_be_paired.rb +6 -6
  333. data/lib/chemicalml/convention/molecular/constraints/atom_element_type_should_be_in_periodic_table.rb +39 -0
  334. data/lib/chemicalml/convention/molecular/constraints/atom_id_must_match_pattern.rb +7 -6
  335. data/lib/chemicalml/convention/molecular/constraints/atom_ids_unique_within_molecule.rb +3 -2
  336. data/lib/chemicalml/convention/molecular/constraints/atom_must_have_element_type.rb +4 -4
  337. data/lib/chemicalml/convention/molecular/constraints/atom_must_have_id.rb +5 -4
  338. data/lib/chemicalml/convention/molecular/constraints/atom_parity_atom_refs4_should_be_distinct.rb +44 -0
  339. data/lib/chemicalml/convention/molecular/constraints/atom_parity_should_include_parent_atom.rb +65 -0
  340. data/lib/chemicalml/convention/molecular/constraints/bond_array_must_be_child_of_molecule.rb +37 -0
  341. data/lib/chemicalml/convention/molecular/constraints/bond_atom_refs2_should_be_distinct.rb +44 -0
  342. data/lib/chemicalml/convention/molecular/constraints/bond_id_should_match_pattern.rb +38 -0
  343. data/lib/chemicalml/convention/molecular/constraints/bond_ids_unique_within_molecule.rb +44 -0
  344. data/lib/chemicalml/convention/molecular/constraints/bond_must_have_atom_refs2.rb +4 -4
  345. data/lib/chemicalml/convention/molecular/constraints/bond_must_have_order.rb +5 -4
  346. data/lib/chemicalml/convention/molecular/constraints/bond_must_reference_atoms_in_same_molecule.rb +4 -3
  347. data/lib/chemicalml/convention/molecular/constraints/bond_order_other_must_have_dict_ref.rb +34 -0
  348. data/lib/chemicalml/convention/molecular/constraints/bond_order_should_be_in_enum.rb +39 -0
  349. data/lib/chemicalml/convention/molecular/constraints/bond_order_should_not_be_numeric.rb +3 -3
  350. data/lib/chemicalml/convention/molecular/constraints/bond_stereo_atom_refs4_should_be_distinct.rb +43 -0
  351. data/lib/chemicalml/convention/molecular/constraints/bond_stereo_cis_trans_must_have_atom_refs4.rb +45 -0
  352. data/lib/chemicalml/convention/molecular/constraints/bond_stereo_other_must_have_dict_ref.rb +33 -0
  353. data/lib/chemicalml/convention/molecular/constraints/bond_stereo_should_be_in_enum.rb +38 -0
  354. data/lib/chemicalml/convention/molecular/constraints/bond_stereo_wedge_hash_must_have_atom_refs2.rb +45 -0
  355. data/lib/chemicalml/convention/molecular/constraints/dict_ref_should_resolve.rb +59 -0
  356. data/lib/chemicalml/convention/molecular/constraints/molecule_atom_array_mutually_exclusive_with_children.rb +33 -0
  357. data/lib/chemicalml/convention/molecular/constraints/molecule_bond_array_mutually_exclusive_with_children.rb +32 -0
  358. data/lib/chemicalml/convention/molecular/constraints/molecule_chirality_should_be_in_enum.rb +38 -0
  359. data/lib/chemicalml/convention/molecular/constraints/molecule_count_must_not_appear_on_top_level.rb +35 -0
  360. data/lib/chemicalml/convention/molecular/constraints/molecule_id_should_match_pattern.rb +38 -0
  361. data/lib/chemicalml/convention/molecular/constraints/molecule_must_have_id.rb +4 -4
  362. data/lib/chemicalml/convention/molecular/constraints/property_must_have_dict_ref.rb +4 -4
  363. data/lib/chemicalml/convention/molecular/constraints/property_scalar_data_type_matches_dictionary.rb +58 -0
  364. data/lib/chemicalml/convention/molecular/constraints/references_should_resolve.rb +37 -0
  365. data/lib/chemicalml/convention/molecular/constraints/scalar_must_have_data_type.rb +4 -4
  366. data/lib/chemicalml/convention/molecular/constraints.rb +59 -13
  367. data/lib/chemicalml/convention/molecular.rb +25 -2
  368. data/lib/chemicalml/convention/registry.rb +95 -10
  369. data/lib/chemicalml/convention/simple_unit/constraints/root_must_be_unit_list.rb +24 -0
  370. data/lib/chemicalml/convention/simple_unit/constraints/unit_must_have_power.rb +32 -0
  371. data/lib/chemicalml/convention/simple_unit/constraints/unit_must_have_symbol.rb +31 -0
  372. data/lib/chemicalml/convention/simple_unit/constraints.rb +16 -0
  373. data/lib/chemicalml/convention/simple_unit.rb +37 -0
  374. data/lib/chemicalml/convention/spectroscopy/constraints/peak_list_must_contain_peaks.rb +31 -0
  375. data/lib/chemicalml/convention/spectroscopy/constraints/peak_should_have_values.rb +34 -0
  376. data/lib/chemicalml/convention/spectroscopy/constraints/spectrum_must_have_content.rb +31 -0
  377. data/lib/chemicalml/convention/spectroscopy/constraints/spectrum_must_have_convention.rb +32 -0
  378. data/lib/chemicalml/convention/spectroscopy/constraints/spectrum_must_have_format.rb +31 -0
  379. data/lib/chemicalml/convention/spectroscopy/constraints.rb +20 -0
  380. data/lib/chemicalml/convention/spectroscopy.rb +41 -0
  381. data/lib/chemicalml/convention/unit_dictionary/constraints/unit_list_must_contain_at_least_one_unit.rb +29 -0
  382. data/lib/chemicalml/convention/unit_dictionary/constraints/unit_list_must_have_namespace.rb +36 -0
  383. data/lib/chemicalml/convention/unit_dictionary/constraints/unit_must_contain_definition.rb +28 -0
  384. data/lib/chemicalml/convention/unit_dictionary/constraints/unit_must_have_id.rb +28 -0
  385. data/lib/chemicalml/convention/unit_dictionary/constraints/unit_must_have_multiplier_or_constant_to_si.rb +34 -0
  386. data/lib/chemicalml/convention/unit_dictionary/constraints/unit_must_have_parent_si.rb +32 -0
  387. data/lib/chemicalml/convention/unit_dictionary/constraints/unit_must_have_symbol_and_unit_type.rb +4 -4
  388. data/lib/chemicalml/convention/unit_dictionary/constraints/unit_must_have_title.rb +32 -0
  389. data/lib/chemicalml/convention/unit_dictionary/constraints/unit_parent_si_should_resolve.rb +45 -0
  390. data/lib/chemicalml/convention/unit_dictionary/constraints/unit_unit_type_should_resolve.rb +46 -0
  391. data/lib/chemicalml/convention/unit_dictionary/constraints.rb +19 -1
  392. data/lib/chemicalml/convention/unit_dictionary.rb +11 -2
  393. data/lib/chemicalml/convention/unit_type_dictionary/constraints/unit_type_id_must_match_pattern.rb +31 -0
  394. data/lib/chemicalml/convention/unit_type_dictionary/constraints/unit_type_list_must_contain_at_least_one_unit_type.rb +28 -0
  395. data/lib/chemicalml/convention/unit_type_dictionary/constraints/unit_type_list_must_have_namespace.rb +35 -0
  396. data/lib/chemicalml/convention/unit_type_dictionary/constraints/unit_type_must_contain_definition.rb +28 -0
  397. data/lib/chemicalml/convention/unit_type_dictionary/constraints/unit_type_must_have_id_and_name.rb +6 -6
  398. data/lib/chemicalml/convention/unit_type_dictionary/constraints.rb +9 -1
  399. data/lib/chemicalml/convention/unit_type_dictionary.rb +6 -2
  400. data/lib/chemicalml/convention/validation_report.rb +90 -0
  401. data/lib/chemicalml/convention/violation.rb +9 -3
  402. data/lib/chemicalml/convention.rb +49 -11
  403. data/lib/chemicalml/dictionary/entry.rb +6 -6
  404. data/lib/chemicalml/dictionary/enum.rb +1 -1
  405. data/lib/chemicalml/dictionary/link.rb +3 -3
  406. data/lib/chemicalml/dictionary/loader.rb +19 -19
  407. data/lib/chemicalml/dictionary/model.rb +5 -5
  408. data/lib/chemicalml/dictionary/registry.rb +9 -9
  409. data/lib/chemicalml/dictionary.rb +13 -9
  410. data/lib/chemicalml/logger.rb +47 -0
  411. data/lib/chemicalml/schema/definition.rb +2 -2
  412. data/lib/chemicalml/schema.rb +7 -7
  413. data/lib/chemicalml/version.rb +1 -1
  414. data/lib/chemicalml/versioned_parser.rb +28 -10
  415. data/lib/chemicalml.rb +79 -17
  416. data/lib/tasks/reference_fetch.rake +30 -31
  417. data/lib/tasks/scrape_fixtures.rake +23 -24
  418. metadata +235 -35
  419. data/lib/chemicalml/cml/child_mappings.rb +0 -168
  420. data/lib/chemicalml/cml/translator/value_translations.rb +0 -270
  421. data/lib/chemicalml/cml/translator.rb +0 -484
  422. data/lib/chemicalml/model/atom.rb +0 -64
  423. data/lib/chemicalml/model/atom_parity.rb +0 -21
  424. data/lib/chemicalml/model/bond.rb +0 -39
  425. data/lib/chemicalml/model/bond_stereo.rb +0 -29
  426. data/lib/chemicalml/model/cml_array.rb +0 -27
  427. data/lib/chemicalml/model/cml_module.rb +0 -45
  428. data/lib/chemicalml/model/document.rb +0 -29
  429. data/lib/chemicalml/model/formula.rb +0 -34
  430. data/lib/chemicalml/model/identifier.rb +0 -21
  431. data/lib/chemicalml/model/label.rb +0 -21
  432. data/lib/chemicalml/model/matrix.rb +0 -29
  433. data/lib/chemicalml/model/metadata.rb +0 -23
  434. data/lib/chemicalml/model/metadata_list.rb +0 -25
  435. data/lib/chemicalml/model/molecule.rb +0 -45
  436. data/lib/chemicalml/model/name.rb +0 -21
  437. data/lib/chemicalml/model/node.rb +0 -45
  438. data/lib/chemicalml/model/parameter.rb +0 -27
  439. data/lib/chemicalml/model/parameter_list.rb +0 -25
  440. data/lib/chemicalml/model/product.rb +0 -21
  441. data/lib/chemicalml/model/product_list.rb +0 -21
  442. data/lib/chemicalml/model/property.rb +0 -28
  443. data/lib/chemicalml/model/property_list.rb +0 -25
  444. data/lib/chemicalml/model/reactant.rb +0 -21
  445. data/lib/chemicalml/model/reactant_list.rb +0 -21
  446. data/lib/chemicalml/model/reaction.rb +0 -41
  447. data/lib/chemicalml/model/reaction_list.rb +0 -23
  448. data/lib/chemicalml/model/scalar.rb +0 -25
  449. data/lib/chemicalml/model/substance.rb +0 -25
  450. data/lib/chemicalml/model.rb +0 -40
@@ -1,484 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Chemicalml
4
- module Cml
5
- # Adapter between the canonical `Chemicalml::Model` and the CML XML
6
- # wire-format layer (`Chemicalml::Cml::*` lutaml-model classes).
7
- #
8
- # Pure transformation. No I/O. Two public class methods, one per
9
- # direction. All helpers are private.
10
- #
11
- # `from_canonical` accepts a `schema:` keyword (`:schema3` default,
12
- # or `:schema24`) and uses `WireClassRegistry` to instantiate the
13
- # right wire class for every nested element — not just the
14
- # Document root.
15
- class Translator
16
- autoload :ValueTranslations, "chemicalml/cml/translator/value_translations"
17
-
18
- # Wire format -> canonical. Polymorphic: accepts either a wire
19
- # Document (`<cml>` root) or a wire Module (`<module>` root).
20
- # Dispatches via Role module checks.
21
- def self.to_canonical(node)
22
- case node
23
- when Chemicalml::Cml::Role::Document
24
- document_to_canonical(node)
25
- when Chemicalml::Cml::Role::Module
26
- module_to_canonical(node)
27
- else
28
- raise ArgumentError,
29
- "to_canonical accepts a wire Document or Module, " \
30
- "got #{node.class}"
31
- end
32
- end
33
-
34
- # Wire Document -> canonical Model::Document.
35
- def self.document_to_canonical(document)
36
- Model::Document.new(
37
- molecules: document.molecules.map { |m| molecule_to_canonical(m) },
38
- reactions: document.reactions.map { |r| reaction_to_canonical(r) }
39
- )
40
- end
41
-
42
- # Wire Module -> canonical Model::Module. Used for compchem
43
- # documents where the root is `<module convention="convention:compchem">`
44
- # rather than `<cml>`.
45
- def self.module_to_canonical(wire_module)
46
- Model::Module.new(
47
- id: wire_module.id,
48
- title: wire_module.title,
49
- dict_ref: wire_module.dict_ref,
50
- convention: wire_module.convention,
51
- molecules: (wire_module.molecules || []).map { |m| molecule_to_canonical(m) },
52
- modules: (wire_module.modules || []).map { |m| module_to_canonical(m) },
53
- parameter_lists: (wire_module.parameter_lists || []).map { |l| parameter_list_to_canonical(l) },
54
- property_lists: (wire_module.property_lists || []).map { |l| property_list_to_canonical(l) },
55
- metadata_lists: (wire_module.metadata_lists || []).map { |l| metadata_list_to_canonical(l) },
56
- lists: []
57
- )
58
- end
59
-
60
- # Canonical -> wire format. Polymorphic: accepts either a
61
- # canonical Document or a canonical Module. `schema:` selects
62
- # the target version (`:schema3` default, or `:schema24`).
63
- def self.from_canonical(node, schema: :schema3)
64
- case node
65
- when Model::Document
66
- document_from_canonical(node, schema: schema)
67
- when Model::Module
68
- module_from_canonical(node, schema: schema)
69
- else
70
- raise ArgumentError,
71
- "from_canonical accepts a canonical Document or " \
72
- "Module, got #{node.class}"
73
- end
74
- end
75
-
76
- # Canonical Document -> wire Document. All nested wire classes
77
- # are looked up via `WireClassRegistry.for(schema, role)` so
78
- # the right version's class is used at every level.
79
- def self.document_from_canonical(document, schema: :schema3)
80
- wire_doc_class(schema).new(
81
- molecules: document.molecules.map { |m| molecule_from_canonical(m, schema: schema) },
82
- reactions: document.reactions.map { |r| reaction_from_canonical(r, schema: schema) }
83
- )
84
- end
85
-
86
- # Canonical Model::Module -> wire Module. Compchem documents
87
- # are rooted at `<module>` rather than `<cml>`; this method
88
- # produces the corresponding wire tree (Schema 3 only — Schema
89
- # 2.4 lacks `<module>`).
90
- def self.module_from_canonical(model_module, schema: :schema3)
91
- registry = Chemicalml::Cml::WireClassRegistry
92
- registry.for(schema, Chemicalml::Cml::Role::Module).new(
93
- id: model_module.id,
94
- title: model_module.title,
95
- dict_ref: model_module.dict_ref,
96
- convention: model_module.convention,
97
- molecules: model_module.molecules.map { |m| molecule_from_canonical(m, schema: schema) },
98
- modules: model_module.modules.map { |m| module_from_canonical(m, schema: schema) },
99
- parameter_lists: model_module.parameter_lists.map { |l| parameter_list_from_canonical(l, schema: schema) },
100
- property_lists: model_module.property_lists.map { |l| property_list_from_canonical(l, schema: schema) },
101
- metadata_lists: model_module.metadata_lists.map { |l| metadata_list_from_canonical(l, schema: schema) },
102
- lists: []
103
- )
104
- end
105
-
106
- # -- CML -> canonical --------------------------------------------
107
-
108
- def self.molecule_to_canonical(cml_mol)
109
- Model::Molecule.new(
110
- id: cml_mol.id,
111
- atoms: cml_mol.atom_array&.atoms&.map { |a| atom_to_canonical(a) } || [],
112
- bonds: cml_mol.bond_array&.bonds&.map { |b| bond_to_canonical(b) } || [],
113
- names: cml_mol.names.map { |n| name_to_canonical(n) },
114
- identifiers: cml_mol.identifiers.map { |i| identifier_to_canonical(i) },
115
- formulas: (cml_mol.formulas || []).map { |f| formula_to_canonical(f) },
116
- properties: (cml_mol.properties || []).map { |p| property_to_canonical(p) },
117
- labels: (cml_mol.labels || []).map { |l| label_to_canonical(l) },
118
- count: cml_mol.count,
119
- formal_charge: cml_mol.formal_charge,
120
- title: cml_mol.title
121
- )
122
- end
123
-
124
- def self.name_to_canonical(cml_name)
125
- return nil unless cml_name
126
-
127
- Model::Name.new(
128
- content: cml_name.content,
129
- convention: cml_name.convention,
130
- dict_ref: cml_name.dict_ref
131
- )
132
- end
133
-
134
- def self.identifier_to_canonical(cml_id)
135
- return nil unless cml_id
136
-
137
- Model::Identifier.new(
138
- value: cml_id.value,
139
- convention: cml_id.convention,
140
- dict_ref: cml_id.dict_ref
141
- )
142
- end
143
-
144
- def self.atom_to_canonical(cml_atom)
145
- Model::Atom.new(
146
- id: cml_atom.id,
147
- element: cml_atom.element_type,
148
- formal_charge: cml_atom.formal_charge,
149
- isotope: cml_atom.isotope,
150
- count: cml_atom.count,
151
- hydrogen_count: cml_atom.hydrogen_count,
152
- spin_multiplicity: cml_atom.spin_multiplicity,
153
- title: cml_atom.title,
154
- x2: cml_atom.x2,
155
- y2: cml_atom.y2,
156
- x3: cml_atom.x3,
157
- y3: cml_atom.y3,
158
- z3: cml_atom.z3,
159
- x_fract: cml_atom.xFract,
160
- y_fract: cml_atom.yFract,
161
- z_fract: cml_atom.zFract,
162
- atom_parity: atom_parity_to_canonical(cml_atom.atom_parity)
163
- )
164
- end
165
-
166
- def self.bond_to_canonical(cml_bond)
167
- Model::Bond.new(
168
- id: cml_bond.id,
169
- atom_refs: cml_bond.atom_refs2&.split(" ") || [],
170
- kind: cml_order_to_kind(cml_bond.order),
171
- bond_stereo: bond_stereo_to_canonical(cml_bond.bond_stereo)
172
- )
173
- end
174
-
175
- def self.atom_parity_to_canonical(cml_ap)
176
- return nil unless cml_ap
177
-
178
- Model::AtomParity.new(
179
- atom_refs4: cml_ap.atom_refs4&.split(" ") || [],
180
- value: cml_ap.content
181
- )
182
- end
183
-
184
- def self.bond_stereo_to_canonical(cml_bs)
185
- return nil unless cml_bs
186
-
187
- Model::BondStereo.new(
188
- value: cml_bs.content,
189
- atom_refs2: cml_bs.atom_refs2&.split(" "),
190
- atom_refs4: cml_bs.atom_refs4&.split(" "),
191
- dict_ref: cml_bs.dict_ref
192
- )
193
- end
194
-
195
- def self.reaction_to_canonical(cml_rxn)
196
- Model::Reaction.new(
197
- id: cml_rxn.id,
198
- reactant_list: reactant_list_to_canonical(cml_rxn.reactant_list),
199
- product_list: product_list_to_canonical(cml_rxn.product_list),
200
- arrow: type_to_arrow(cml_rxn.type || cml_rxn.title),
201
- title: cml_rxn.title,
202
- type: cml_rxn.type
203
- )
204
- end
205
-
206
- def self.reactant_list_to_canonical(cml_list)
207
- return Model::ReactantList.new unless cml_list
208
-
209
- Model::ReactantList.new(
210
- reactants: cml_list.reactants.map do |r|
211
- Model::Reactant.new(
212
- substance: Model::Substance.new(
213
- molecule: molecule_to_canonical(r.substance.molecule),
214
- title: r.substance.title,
215
- role: r.substance.role
216
- )
217
- )
218
- end
219
- )
220
- end
221
-
222
- def self.product_list_to_canonical(cml_list)
223
- return Model::ProductList.new unless cml_list
224
-
225
- Model::ProductList.new(
226
- products: cml_list.products.map do |p|
227
- Model::Product.new(
228
- substance: Model::Substance.new(
229
- molecule: molecule_to_canonical(p.substance.molecule),
230
- title: p.substance.title,
231
- role: p.substance.role
232
- )
233
- )
234
- end
235
- )
236
- end
237
-
238
- def self.property_list_to_canonical(cml_list)
239
- return Model::PropertyList.new unless cml_list
240
-
241
- Model::PropertyList.new(
242
- id: cml_list.id,
243
- title: cml_list.title,
244
- dict_ref: cml_list.dict_ref,
245
- properties: cml_list.properties.map { |p| property_to_canonical(p) }
246
- )
247
- end
248
-
249
- def self.parameter_list_to_canonical(cml_list)
250
- return Model::ParameterList.new unless cml_list
251
-
252
- Model::ParameterList.new(
253
- id: cml_list.id,
254
- title: cml_list.title,
255
- dict_ref: cml_list.dict_ref,
256
- parameters: cml_list.parameters.map { |p| parameter_to_canonical(p) }
257
- )
258
- end
259
-
260
- def self.metadata_list_to_canonical(cml_list)
261
- return Model::MetadataList.new unless cml_list
262
-
263
- Model::MetadataList.new(
264
- id: cml_list.id,
265
- title: cml_list.title,
266
- dict_ref: cml_list.dict_ref,
267
- metadata: cml_list.metadata.map { |m| metadata_to_canonical(m) }
268
- )
269
- end
270
-
271
- def self.property_value_to_canonical(cml_prop)
272
- value_container_to_canonical(cml_prop.scalar) ||
273
- value_container_to_canonical(cml_prop.array) ||
274
- value_container_to_canonical(cml_prop.matrix)
275
- end
276
-
277
- def self.parameter_value_to_canonical(cml_param)
278
- value_container_to_canonical(cml_param.scalar) ||
279
- value_container_to_canonical(cml_param.array) ||
280
- value_container_to_canonical(cml_param.matrix)
281
- end
282
-
283
- # -- Canonical -> CML --------------------------------------------
284
- # Every helper takes `schema:` and looks up wire classes via
285
- # WireClassRegistry so children are the right version.
286
-
287
- def self.molecule_from_canonical(mol, schema:)
288
- registry = Chemicalml::Cml::WireClassRegistry
289
- registry.for(schema, Chemicalml::Cml::Role::Molecule).new(
290
- id: mol.id,
291
- atom_array: mol.atoms.empty? ? nil : registry.for(schema, Chemicalml::Cml::Role::AtomArray).new(
292
- atoms: mol.atoms.map { |a| atom_from_canonical(a, schema: schema) }
293
- ),
294
- bond_array: mol.bonds.empty? ? nil : registry.for(schema, Chemicalml::Cml::Role::BondArray).new(
295
- bonds: mol.bonds.map { |b| bond_from_canonical(b, schema: schema) }
296
- ),
297
- names: mol.names.map { |n| registry.for(schema, Chemicalml::Cml::Role::Name).new(content: n.content, convention: n.convention, dict_ref: n.dict_ref) },
298
- identifiers: mol.identifiers.map { |i| registry.for(schema, Chemicalml::Cml::Role::Identifier).new(value: i.value, convention: i.convention, dict_ref: i.dict_ref) },
299
- formulas: mol.formulas.map { |f| formula_from_canonical(f, schema: schema) },
300
- properties: mol.properties.map { |p| property_from_canonical(p, schema: schema) },
301
- labels: mol.labels.map { |l| label_from_canonical(l, schema: schema) },
302
- count: mol.count,
303
- formal_charge: mol.formal_charge,
304
- title: mol.title
305
- )
306
- end
307
-
308
- def self.atom_from_canonical(atom, schema:)
309
- Chemicalml::Cml::WireClassRegistry
310
- .for(schema, Chemicalml::Cml::Role::Atom)
311
- .new(
312
- id: atom.id,
313
- element_type: atom.element,
314
- formal_charge: atom.formal_charge,
315
- isotope: atom.isotope,
316
- count: atom.count,
317
- hydrogen_count: atom.hydrogen_count,
318
- spin_multiplicity: atom.spin_multiplicity,
319
- title: atom.title,
320
- x2: atom.x2,
321
- y2: atom.y2,
322
- x3: atom.x3,
323
- y3: atom.y3,
324
- z3: atom.z3,
325
- xFract: atom.x_fract,
326
- yFract: atom.y_fract,
327
- zFract: atom.z_fract,
328
- atom_parity: atom_parity_from_canonical(atom.atom_parity, schema: schema)
329
- )
330
- end
331
-
332
- def self.bond_from_canonical(bond, schema:)
333
- Chemicalml::Cml::WireClassRegistry
334
- .for(schema, Chemicalml::Cml::Role::Bond)
335
- .new(
336
- id: bond.id,
337
- atom_refs2: bond.atom_refs.join(" "),
338
- order: bond.cml_order,
339
- bond_stereo: bond_stereo_from_canonical(bond.bond_stereo, schema: schema)
340
- )
341
- end
342
-
343
- def self.atom_parity_from_canonical(ap, schema:)
344
- return nil unless ap
345
-
346
- Chemicalml::Cml::WireClassRegistry
347
- .for(schema, Chemicalml::Cml::Role::AtomParity)
348
- .new(
349
- atom_refs4: [*ap.atom_refs4].join(" "),
350
- content: ap.value
351
- )
352
- end
353
-
354
- def self.bond_stereo_from_canonical(bs, schema:)
355
- return nil unless bs
356
-
357
- Chemicalml::Cml::WireClassRegistry
358
- .for(schema, Chemicalml::Cml::Role::BondStereo)
359
- .new(
360
- content: bs.value,
361
- atom_refs2: bs.atom_refs2 && [*bs.atom_refs2].join(" "),
362
- atom_refs4: bs.atom_refs4 && [*bs.atom_refs4].join(" "),
363
- dict_ref: bs.dict_ref
364
- )
365
- end
366
-
367
- def self.reaction_from_canonical(rxn, schema:)
368
- Chemicalml::Cml::WireClassRegistry
369
- .for(schema, Chemicalml::Cml::Role::Reaction)
370
- .new(
371
- id: rxn.id,
372
- title: rxn.title || rxn.arrow.to_s,
373
- type: rxn.type || rxn.arrow.to_s,
374
- reactant_list: reactant_list_from_canonical(rxn.reactant_list, schema: schema),
375
- product_list: product_list_from_canonical(rxn.product_list, schema: schema)
376
- )
377
- end
378
-
379
- def self.reactant_list_from_canonical(list, schema:)
380
- registry = Chemicalml::Cml::WireClassRegistry
381
- registry.for(schema, Chemicalml::Cml::Role::ReactantList).new(
382
- reactants: list.reactants.map do |r|
383
- registry.for(schema, Chemicalml::Cml::Role::Reactant).new(
384
- substance: registry.for(schema, Chemicalml::Cml::Role::Substance).new(
385
- molecule: molecule_from_canonical(r.substance.molecule, schema: schema),
386
- title: r.substance.title,
387
- role: r.substance.role
388
- )
389
- )
390
- end
391
- )
392
- end
393
-
394
- def self.product_list_from_canonical(list, schema:)
395
- registry = Chemicalml::Cml::WireClassRegistry
396
- registry.for(schema, Chemicalml::Cml::Role::ProductList).new(
397
- products: list.products.map do |p|
398
- registry.for(schema, Chemicalml::Cml::Role::Product).new(
399
- substance: registry.for(schema, Chemicalml::Cml::Role::Substance).new(
400
- molecule: molecule_from_canonical(p.substance.molecule, schema: schema),
401
- title: p.substance.title,
402
- role: p.substance.role
403
- )
404
- )
405
- end
406
- )
407
- end
408
-
409
- def self.property_list_from_canonical(list, schema:)
410
- registry = Chemicalml::Cml::WireClassRegistry
411
- registry.for(schema, Chemicalml::Cml::Role::PropertyList).new(
412
- id: list.id,
413
- title: list.title,
414
- dict_ref: list.dict_ref,
415
- properties: list.properties.map { |p| property_from_canonical(p, schema: schema) }
416
- )
417
- end
418
-
419
- def self.parameter_list_from_canonical(list, schema:)
420
- registry = Chemicalml::Cml::WireClassRegistry
421
- registry.for(schema, Chemicalml::Cml::Role::ParameterList).new(
422
- id: list.id,
423
- title: list.title,
424
- dict_ref: list.dict_ref,
425
- parameters: list.parameters.map { |p| parameter_from_canonical(p, schema: schema) }
426
- )
427
- end
428
-
429
- def self.metadata_list_from_canonical(list, schema:)
430
- registry = Chemicalml::Cml::WireClassRegistry
431
- registry.for(schema, Chemicalml::Cml::Role::MetadataList).new(
432
- id: list.id,
433
- title: list.title,
434
- dict_ref: list.dict_ref,
435
- metadata: list.metadata.map { |m| metadata_from_canonical(m, schema: schema) }
436
- )
437
- end
438
-
439
- # -- Lookup tables -----------------------------------------------
440
-
441
- ORDER_TO_KIND = {
442
- "S" => :single, "D" => :double, "T" => :triple,
443
- "Q" => :quadruple, "A" => :aromatic, "W" => :wedge,
444
- "H" => :hash, "DG" => :dative, "V" => :wavy
445
- }.freeze
446
-
447
- TYPE_TO_ARROW = {
448
- "forward" => :forward,
449
- "reverse" => :reverse,
450
- "equilibrium" => :equilibrium,
451
- "resonance" => :resonance
452
- }.freeze
453
-
454
- def self.cml_order_to_kind(order)
455
- return :single if order.nil?
456
-
457
- ORDER_TO_KIND.fetch(order.upcase, :single)
458
- end
459
-
460
- def self.type_to_arrow(value)
461
- return :forward if value.nil?
462
-
463
- TYPE_TO_ARROW.fetch(value.to_s.downcase, :forward)
464
- end
465
-
466
- def self.wire_doc_class(schema)
467
- Chemicalml::Cml::WireClassRegistry.for(schema, Chemicalml::Cml::Role::Document)
468
- end
469
-
470
- extend ValueTranslations::ClassMethods
471
-
472
- # Truly internal helpers — not part of the public API. Public
473
- # per-element translation methods (`molecule_to_canonical`,
474
- # `scalar_from_canonical`, etc.) remain public because callers
475
- # may need to translate a single element without a full
476
- # Document wrapper.
477
- private_class_method :cml_order_to_kind, :type_to_arrow,
478
- :wire_doc_class,
479
- :document_to_canonical, :document_from_canonical,
480
- :property_value_to_canonical, :parameter_value_to_canonical,
481
- :value_container_to_canonical, :value_container_from_canonical
482
- end
483
- end
484
- end
@@ -1,64 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Chemicalml
4
- module Model
5
- # A chemical atom. Carries every attribute CML's `<atom>` carries
6
- # that's chemistry-relevant: element symbol, formal charge,
7
- # isotope, count (multiplicity), hydrogen count, lone pairs,
8
- # radical electrons, spin multiplicity, 2D/3D coordinates,
9
- # fractional coordinates. Optional `atom_parity` for atom-centre
10
- # chirality.
11
- class Atom < Node
12
- attr_accessor :id, :element, :formal_charge, :isotope,
13
- :count, :hydrogen_count, :lone_pairs,
14
- :radical_electrons, :spin_multiplicity, :title,
15
- :x2, :y2, :x3, :y3, :z3,
16
- :x_fract, :y_fract, :z_fract,
17
- :atom_parity
18
-
19
- def initialize(element:, id: nil, formal_charge: nil,
20
- isotope: nil, count: nil, hydrogen_count: nil,
21
- lone_pairs: nil, radical_electrons: nil,
22
- spin_multiplicity: nil, title: nil,
23
- x2: nil, y2: nil, x3: nil, y3: nil, z3: nil,
24
- x_fract: nil, y_fract: nil, z_fract: nil,
25
- atom_parity: nil)
26
- @element = element
27
- @id = id
28
- @formal_charge = formal_charge
29
- @isotope = isotope
30
- @count = count
31
- @hydrogen_count = hydrogen_count
32
- @lone_pairs = lone_pairs
33
- @radical_electrons = radical_electrons
34
- @spin_multiplicity = spin_multiplicity
35
- @title = title
36
- @x2 = x2
37
- @y2 = y2
38
- @x3 = x3
39
- @y3 = y3
40
- @z3 = z3
41
- @x_fract = x_fract
42
- @y_fract = y_fract
43
- @z_fract = z_fract
44
- @atom_parity = atom_parity
45
- end
46
-
47
- def children
48
- [atom_parity].compact
49
- end
50
-
51
- def value_attributes
52
- {
53
- element: element, id: id, formal_charge: formal_charge,
54
- isotope: isotope, count: count, hydrogen_count: hydrogen_count,
55
- lone_pairs: lone_pairs, radical_electrons: radical_electrons,
56
- spin_multiplicity: spin_multiplicity, title: title,
57
- x2: x2, y2: y2, x3: x3, y3: y3, z3: z3,
58
- x_fract: x_fract, y_fract: y_fract, z_fract: z_fract,
59
- atom_parity: atom_parity
60
- }
61
- end
62
- end
63
- end
64
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Chemicalml
4
- module Model
5
- # Atom-centre chirality. CML `<atomParity>` element with
6
- # `atomRefs4` (four atom IDs in order) and a `value` (typically
7
- # `"1"`, `"-1"`, or `"0"`).
8
- class AtomParity < Node
9
- attr_accessor :atom_refs4, :value
10
-
11
- def initialize(atom_refs4:, value:)
12
- @atom_refs4 = atom_refs4
13
- @value = value
14
- end
15
-
16
- def value_attributes
17
- { atom_refs4: atom_refs4, value: value }
18
- end
19
- end
20
- end
21
- end
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Chemicalml
4
- module Model
5
- # A bond between two atoms. Endpoint references are string IDs
6
- # matching `Atom#id`; the kind enum follows CML conventions.
7
- # Optional `bond_stereo` carries cis/trans/wedge/hatch info.
8
- class Bond < Node
9
- KINDS = %i[single double triple quadruple aromatic wedge hash
10
- dative wavy].freeze
11
-
12
- CML_ORDER = {
13
- single: "S", double: "D", triple: "T", quadruple: "Q",
14
- aromatic: "A", wedge: "W", hash: "H", dative: "DG", wavy: "V"
15
- }.freeze
16
-
17
- attr_accessor :id, :atom_refs, :kind, :bond_stereo
18
-
19
- def initialize(id: nil, atom_refs:, kind: :single, bond_stereo: nil)
20
- @id = id
21
- @atom_refs = atom_refs
22
- @kind = kind
23
- @bond_stereo = bond_stereo
24
- end
25
-
26
- def children
27
- [bond_stereo].compact
28
- end
29
-
30
- def value_attributes
31
- { id: id, atom_refs: atom_refs, kind: kind, bond_stereo: bond_stereo }
32
- end
33
-
34
- def cml_order
35
- CML_ORDER.fetch(kind, "S")
36
- end
37
- end
38
- end
39
- end
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Chemicalml
4
- module Model
5
- # Bond stereochemistry. CML `<bondStereo>` element. Carries
6
- # either `atom_refs2` (for `W`/`H` wedge/hatch) or `atom_refs4`
7
- # (for `C`/`T` cis/trans). The `value` is the convention letter:
8
- # `W`, `H`, `C`, `T`, or `other` (with a `dict_ref`).
9
- class BondStereo < Node
10
- attr_accessor :atom_refs2, :atom_refs4, :dict_ref, :value
11
-
12
- def initialize(value:, atom_refs2: nil, atom_refs4: nil, dict_ref: nil)
13
- @value = value
14
- @atom_refs2 = atom_refs2
15
- @atom_refs4 = atom_refs4
16
- @dict_ref = dict_ref
17
- end
18
-
19
- def value_attributes
20
- {
21
- value: value,
22
- atom_refs2: atom_refs2,
23
- atom_refs4: atom_refs4,
24
- dict_ref: dict_ref
25
- }
26
- end
27
- end
28
- end
29
- end
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Chemicalml
4
- module Model
5
- # A one-dimensional array of values.
6
- class Array < Node
7
- attr_accessor :id, :title, :dict_ref, :data_type, :units,
8
- :size, :values
9
-
10
- def initialize(values:, data_type: nil, units: nil, size: nil,
11
- id: nil, title: nil, dict_ref: nil)
12
- @values = values
13
- @data_type = data_type
14
- @units = units
15
- @size = size
16
- @id = id
17
- @title = title
18
- @dict_ref = dict_ref
19
- end
20
-
21
- def value_attributes
22
- { values: values, data_type: data_type, units: units,
23
- size: size, id: id, title: title, dict_ref: dict_ref }
24
- end
25
- end
26
- end
27
- end