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
@@ -9,137 +9,181 @@ module Chemicalml
9
9
  module Elements
10
10
  ALL = {
11
11
  # Originally modeled elements
12
- Array: :array,
13
- Atom: :atom,
14
- AtomArray: :atomArray,
15
- AtomParity: :atomParity,
16
- Bond: :bond,
17
- BondArray: :bondArray,
18
- BondStereo: :bondStereo,
19
- Dictionary: :dictionary,
20
- DictionaryEntry: :entry,
21
- Document: :document,
22
- Formula: :formula,
23
- Identifier: :identifier,
24
- Label: :label,
25
- List: :list,
26
- Matrix: :matrix,
27
- Metadata: :metadata,
28
- MetadataList: :metadataList,
29
- Module: :module,
30
- Molecule: :molecule,
31
- Name: :name,
32
- Parameter: :parameter,
33
- ParameterList: :parameterList,
34
- Product: :product,
35
- ProductList: :productList,
36
- Property: :property,
37
- PropertyList: :propertyList,
38
- Reaction: :reaction,
39
- ReactionList: :reactionList,
40
- Reactant: :reactant,
41
- ReactantList: :reactantList,
42
- Scalar: :scalar,
43
- Substance: :substance,
44
- Unit: :unit,
45
- UnitList: :unitList,
46
- UnitType: :unitType,
47
- UnitTypeList: :unitTypeList,
12
+ Array: :array,
13
+ Atom: :atom,
14
+ AtomArray: :atomArray,
15
+ AtomParity: :atomParity,
16
+ Bond: :bond,
17
+ BondArray: :bondArray,
18
+ BondStereo: :bondStereo,
19
+ Dictionary: :dictionary,
20
+ DictionaryEntry: :entry,
21
+ Document: :document,
22
+ Formula: :formula,
23
+ Identifier: :identifier,
24
+ Label: :label,
25
+ List: :list,
26
+ Matrix: :matrix,
27
+ Metadata: :metadata,
28
+ MetadataList: :metadataList,
29
+ Module: :module,
30
+ Molecule: :molecule,
31
+ Name: :name,
32
+ Parameter: :parameter,
33
+ ParameterList: :parameterList,
34
+ Product: :product,
35
+ ProductList: :productList,
36
+ Property: :property,
37
+ PropertyList: :propertyList,
38
+ Reaction: :reaction,
39
+ ReactionList: :reactionList,
40
+ Reactant: :reactant,
41
+ ReactantList: :reactantList,
42
+ Scalar: :scalar,
43
+ Substance: :substance,
44
+ Unit: :unit,
45
+ UnitList: :unitList,
46
+ UnitType: :unitType,
47
+ UnitTypeList: :unitTypeList,
48
48
  # Full schema coverage — every CML element from the XSD
49
- Abundance: :abundance,
50
- Action: :action,
51
- ActionList: :actionList,
52
- Amount: :amount,
53
- Angle: :angle,
54
- AnyCml: :anyCml,
55
- ArrayList: :arrayList,
56
- AtomSet: :atomSet,
57
- AtomType: :atomType,
58
- AtomTypeList: :atomTypeList,
49
+ Abundance: :abundance,
50
+ Action: :action,
51
+ ActionList: :actionList,
52
+ Amount: :amount,
53
+ Angle: :angle,
54
+ AnyCml: :anyCml,
55
+ ArrayList: :arrayList,
56
+ AtomSet: :atomSet,
57
+ AtomType: :atomType,
58
+ AtomTypeList: :atomTypeList,
59
59
  AtomicBasisFunction: :atomicBasisFunction,
60
- Band: :band,
61
- BandList: :bandList,
62
- BasisSet: :basisSet,
63
- BondSet: :bondSet,
64
- BondType: :bondType,
65
- BondTypeList: :bondTypeList,
66
- CellParameter: :cellParameter,
67
- ConditionList: :conditionList,
68
- Crystal: :crystal,
69
- Definition: :definition,
70
- Description: :description,
71
- Dimension: :dimension,
72
- Documentation: :documentation,
73
- Eigen: :eigen,
74
- Electron: :electron,
75
- Fragment: :fragment,
76
- FragmentList: :fragmentList,
77
- Gradient: :gradient,
78
- Isotope: :isotope,
79
- IsotopeList: :isotopeList,
80
- Join: :join,
81
- Kpoint: :kpoint,
82
- KpointList: :kpointList,
83
- Lattice: :lattice,
84
- LatticeVector: :latticeVector,
85
- Length: :length,
86
- Line3: :line3,
87
- Link: :link,
88
- Map: :map,
89
- Mechanism: :mechanism,
90
- MechanismComponent: :mechanismComponent,
91
- MoleculeList: :moleculeList,
92
- Object: :object,
93
- Observation: :observation,
94
- Particle: :particle,
95
- Peak: :peak,
96
- PeakGroup: :peakGroup,
97
- PeakList: :peakList,
98
- PeakStructure: :peakStructure,
99
- Plane3: :plane3,
100
- Point3: :point3,
101
- Potential: :potential,
102
- PotentialForm: :potentialForm,
103
- PotentialList: :potentialList,
104
- ReactionScheme: :reactionScheme,
105
- ReactionStep: :reactionStep,
106
- ReactionStepList: :reactionStepList,
107
- ReactiveCentre: :reactiveCentre,
108
- Region: :region,
109
- Sample: :sample,
110
- Spectator: :spectator,
111
- SpectatorList: :spectatorList,
112
- Spectrum: :spectrum,
113
- SpectrumData: :spectrumData,
114
- SpectrumList: :spectrumList,
115
- Sphere3: :sphere3,
116
- Stmml: :stmml,
117
- SubstanceList: :substanceList,
118
- Symmetry: :symmetry,
119
- System: :system,
120
- Table: :table,
121
- TableCell: :tableCell,
122
- TableContent: :tableContent,
123
- TableHeader: :tableHeader,
124
- TableHeaderCell: :tableHeaderCell,
125
- TableRow: :tableRow,
126
- TableRowList: :tableRowList,
127
- Torsion: :torsion,
128
- Transform3: :transform3,
129
- TransitionState: :transitionState,
130
- Vector3: :vector3,
131
- Xaxis: :xaxis,
132
- Yaxis: :yaxis,
133
- ZMatrix: :zMatrix,
60
+ Band: :band,
61
+ BandList: :bandList,
62
+ BasisSet: :basisSet,
63
+ BondSet: :bondSet,
64
+ BondType: :bondType,
65
+ BondTypeList: :bondTypeList,
66
+ CellParameter: :cellParameter,
67
+ ConditionList: :conditionList,
68
+ Crystal: :crystal,
69
+ Definition: :definition,
70
+ Description: :description,
71
+ Dimension: :dimension,
72
+ Documentation: :documentation,
73
+ Eigen: :eigen,
74
+ Electron: :electron,
75
+ Fragment: :fragment,
76
+ FragmentList: :fragmentList,
77
+ Gradient: :gradient,
78
+ Isotope: :isotope,
79
+ IsotopeList: :isotopeList,
80
+ Join: :join,
81
+ Kpoint: :kpoint,
82
+ KpointList: :kpointList,
83
+ Lattice: :lattice,
84
+ LatticeVector: :latticeVector,
85
+ Length: :length,
86
+ Line3: :line3,
87
+ Link: :link,
88
+ Map: :map,
89
+ Mechanism: :mechanism,
90
+ MechanismComponent: :mechanismComponent,
91
+ MoleculeList: :moleculeList,
92
+ Object: :object,
93
+ Observation: :observation,
94
+ Particle: :particle,
95
+ Peak: :peak,
96
+ PeakGroup: :peakGroup,
97
+ PeakList: :peakList,
98
+ PeakStructure: :peakStructure,
99
+ Plane3: :plane3,
100
+ Point3: :point3,
101
+ Potential: :potential,
102
+ PotentialForm: :potentialForm,
103
+ PotentialList: :potentialList,
104
+ ReactionScheme: :reactionScheme,
105
+ ReactionStep: :reactionStep,
106
+ ReactionStepList: :reactionStepList,
107
+ ReactiveCentre: :reactiveCentre,
108
+ Region: :region,
109
+ Sample: :sample,
110
+ Spectator: :spectator,
111
+ SpectatorList: :spectatorList,
112
+ Spectrum: :spectrum,
113
+ SpectrumData: :spectrumData,
114
+ SpectrumList: :spectrumList,
115
+ Sphere3: :sphere3,
116
+ Stmml: :stmml,
117
+ SubstanceList: :substanceList,
118
+ Symmetry: :symmetry,
119
+ System: :system,
120
+ Table: :table,
121
+ TableCell: :tableCell,
122
+ TableContent: :tableContent,
123
+ TableHeader: :tableHeader,
124
+ TableHeaderCell: :tableHeaderCell,
125
+ TableRow: :tableRow,
126
+ TableRowList: :tableRowList,
127
+ Torsion: :torsion,
128
+ Transform3: :transform3,
129
+ TransitionState: :transitionState,
130
+ Vector3: :vector3,
131
+ Xaxis: :xaxis,
132
+ Yaxis: :yaxis,
133
+ ZMatrix: :zMatrix
134
134
  }.freeze
135
135
 
136
- # Elements that exist in Schema 3 but NOT in Schema 2.4.
137
- SCHEMA3_ONLY = %i[Module].freeze
136
+ # Elements declared in the Schema 3 XSD but absent from the
137
+ # Schema 2.4 XSD. Verified by diffing the actual XSDs in
138
+ # `reference-docs/schemas/`: Schema 3 declares `<anyCml>` while
139
+ # Schema 2.4 does not. Conversely, Schema 2.4 declares 17 legacy
140
+ # elements (`alternative`, `annotation`, `appinfo`, `arg`,
141
+ # `complexObject`, `enumeration`, `expression`, `float`,
142
+ # `floatArray`, `integer`, `integerArray`, `operator`,
143
+ # `relatedEntry`, `string`, `stringArray`, `tcell`, `trow`) that
144
+ # are either redundant with Schema 3's unified types or outside
145
+ # the gem's scope.
146
+ SCHEMA3_ONLY = %i[AnyCml].freeze
147
+
148
+ # Subset of the Schema-2.4-only legacy elements that the gem
149
+ # explicitly models. Maps Ruby class name → XML element id so
150
+ # `Schema24::Configuration` can register them without polluting
151
+ # `Elements::ALL` (which mirrors Schema 3's element set).
152
+ SCHEMA24_ONLY = {
153
+ Alternative: :alternative,
154
+ Annotation: :annotation,
155
+ Appinfo: :appinfo,
156
+ Arg: :arg,
157
+ ComplexObject: :complexObject,
158
+ Enumeration: :enumeration,
159
+ Expression: :expression,
160
+ Float: :float,
161
+ FloatArray: :floatArray,
162
+ Integer: :integer,
163
+ IntegerArray: :integerArray,
164
+ Operator: :operator,
165
+ RelatedEntry: :relatedEntry,
166
+ String: :string,
167
+ StringArray: :stringArray,
168
+ Tcell: :tcell,
169
+ Trow: :trow
170
+ }.freeze
171
+
172
+ # Schema24-only elements whose XML element id collides with a
173
+ # lutaml-model primitive type name (`:string`, `:integer`,
174
+ # `:float`). Registering them as types would shadow the
175
+ # primitive, breaking every `attribute :foo, :string` cast.
176
+ # They remain defined as wire classes and parseable as roots,
177
+ # but `register_elements!` skips registering them in the
178
+ # schema24 type context.
179
+ SCHEMA24_TYPE_COLLISIONS = %i[Float Integer String].freeze
138
180
 
139
181
  # Reverse index: XML element name (String) → Ruby class name
140
182
  # (Symbol). O(1) lookup for VersionedParser root detection.
141
- XML_TO_CLASS = ALL.each_with_object({}) do |(cls, xml_id), h|
142
- h[xml_id.to_s] = cls
183
+ # Includes both Schema 3 elements and the modeled Schema 2.4
184
+ # legacy elements.
185
+ XML_TO_CLASS = [ALL, SCHEMA24_ONLY].each_with_object({}) do |src, h|
186
+ src.each { |cls, xml_id| h[xml_id.to_s] = cls }
143
187
  end.freeze
144
188
  end
145
189
  end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Cml
5
+ # Canonical Ruby source of truth for every XSD simpleType that
6
+ # restricts to an enumeration. Generated from
7
+ # `reference-docs/schemas/schema3/schema.xsd`. Constants are
8
+ # frozen Sets — adding a new value means changing the XSD, then
9
+ # regenerating this file.
10
+ #
11
+ # Naming: XSD `fooType` → Ruby `FOO_VALUES`. The `Type` suffix is
12
+ # stripped before uppercasing. Constants ending in `_VALUES` are
13
+ # Sets of allowed string values for the corresponding attribute.
14
+ module Enums
15
+ ACTIONORDER_VALUES = Set.new(%w[sequential parallel]).freeze
16
+ # All 120 element type codes from XSD elementTypeType, including
17
+ # the special "Du" (dummy) and "R" (undefined/group placeholder).
18
+ # Use this to validate atom.elementType values.
19
+ ELEMENT_TYPE_VALUES = Set.new(%w[Ac Al Ag Am Ar As At Au B Ba Bh Bi Be Bk Br C Ca Cd Ce Cf Cl Cm Co Cr Cs Cu Db
20
+ Dy Er Es Eu F Fe Fm Fr Ga Gd Ge H He Hf Hg Ho Hs I In Ir K Kr La Li Lr Lu Md Mg Mn Mo Mt N Na Nb Nd Ne Ni No Np O Os P Pa Pb Pd Pm Po Pr Pt Pu Ra Rb Re Rf Rh Rn Ru S Sb Sc Se Sg Si Sm Sn Sr Ta Tb Tc Te Th Ti Tl Tm U Uun Uuu Uub Uut Uuq Uup Uuh Uus Uuo V W Xe Y Yb Zn Zr Du R]).freeze
21
+ ANGLEUNITS_VALUES = Set.new(%w[degrees radians]).freeze
22
+ CELLPARAMETER_VALUES = Set.new(%w[length angle]).freeze
23
+ CHIRALITY_VALUES = Set.new(%w[enantiomer racemate unknown other]).freeze
24
+ DIMENSION_VALUES = Set.new(%w[mass length time current amount luminosity temperature dimensionless angle]).freeze
25
+ EIGENORIENTATION_VALUES = Set.new(%w[columnVectors rowVectors other]).freeze
26
+ ERRORBASIS_VALUES = Set.new(%w[observedRange observedStandardDeviation observedStandardError
27
+ estimatedStandardDeviation estimatedStandardError other]).freeze
28
+ FORMAT_VALUES = Set.new(%w[1D 2Dsymm 2Dasymm other]).freeze
29
+ FT_VALUES = Set.new(%w[raw transformed none other]).freeze
30
+ INHERIT_VALUES = Set.new(%w[merge replace delete]).freeze
31
+ LATTICE_VALUES = Set.new(%w[primitive full aCentred other]).freeze
32
+ LINKTYPE_VALUES = Set.new(%w[extended locator arc]).freeze
33
+ LM_VALUES = Set.new(%w[s p px py pz d dxy dyz dxz dx2y2 dz2 f g]).freeze
34
+ MATRIX_VALUES = Set.new(%w[rectangular square squareSymmetric squareSymmetricLT squareSymmetricUT
35
+ squareAntisymmetric squareAntisymmetricLT squareAntisymmetricUT diagonal upperTriangular upperTriangularUT lowerTriangular lowerTriangularLT unit unitary rowEigenvectors rotation22 rotationTranslation32 homogeneous33 rotation33 rotationTranslation43 homogeneous44 other]).freeze
36
+ MEASUREMENT_VALUES = Set.new(%w[transmittance absorbance other]).freeze
37
+ ORDER_VALUES = Set.new(%w[S 1 D 2 T 3 A unknown other]).freeze
38
+ PEAKMULTIPLICITY_VALUES = Set.new(%w[singlet doublet triplet quartet quintet sextuplet multiplet other]).freeze
39
+ PEAKSHAPE_VALUES = Set.new(%w[sharp broad shoulder other]).freeze
40
+ PEAKSTRUCTURETYPE_VALUES = Set.new(%w[coupling splitting other]).freeze
41
+ REACTIONFORMAT_VALUES = Set.new(%w[reactantProduct cmlSnap other]).freeze
42
+ REACTIONROLE_VALUES = Set.new(%w[complete overall rateDeterminingStep step steps other]).freeze
43
+ REACTIONSTEPLISTTYPE_VALUES = Set.new(%w[unknown consecutive choice simultaneous other]).freeze
44
+ REACTIONTYPE_VALUES = Set.new(%w[chainReaction initiation termination reversible other]).freeze
45
+ SCHEME_VALUES = Set.new(%w[unknown sequence choice and other]).freeze
46
+ SHAPE_VALUES = Set.new(%w[rectangular triangularDecreasing. triangularIncreasing. irregular other]).freeze
47
+ SPACE_VALUES = Set.new(%w[real k-space Fourier reciprocal other]).freeze
48
+ SPECTRUMTYPE_VALUES = Set.new(%w[infrared massSpectrum NMR UV/VIS other]).freeze
49
+ STATE_VALUES = Set.new(%w[aqueous gas glass liquid nematic smectic solid solidSolution solution other]).freeze
50
+ STEREO_VALUES = Set.new(%w[C T W H undefined other]).freeze
51
+ SUBSTANCELISTTYPE_VALUES = Set.new(%w[solution mixture other]).freeze
52
+ TABLETYPE_VALUES = Set.new(%w[rowBased arrayBased contentBased other]).freeze
53
+ end
54
+ end
55
+ end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
-
4
3
  module Chemicalml
5
4
  module Cml
6
5
  # The default CML XML namespace. CML itself doesn't actually
@@ -9,8 +8,8 @@ module Chemicalml
9
8
  # future schema-validation work and so consumers can request
10
9
  # namespaced output via the `namespace:` serialisation option.
11
10
  class Namespace < Lutaml::Xml::W3c::XmlNamespace
12
- uri "http://www.xml-cml.org/schema"
13
- prefix_default "cml"
11
+ uri 'http://www.xml-cml.org/schema'
12
+ prefix_default 'cml'
14
13
  element_form_default :unqualified
15
14
  end
16
15
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Cml
5
+ # Canonical Ruby source of truth for every XSD simpleType that
6
+ # restricts by `xsd:pattern`. Generated from
7
+ # `reference-docs/schemas/schema3/schema.xsd`. Constants are
8
+ # frozen Regexp objects — adding a new pattern means changing
9
+ # the XSD, then regenerating this file.
10
+ #
11
+ # Naming: XSD `fooType` → Ruby `FOO_PATTERN`. The `Type` suffix
12
+ # is stripped before uppercasing.
13
+ module Patterns
14
+ ATOM_ID_PATTERN = /[A-Za-z_][A-Za-z0-9_-]*(:[A-Za-z0-9_-]+)?/
15
+ BOND_REF_PATTERN = /[A-Za-z0-9_-]+(:[A-Za-z0-9_-]+)?/
16
+ DELIMITER_PATTERN = %r{[!%\^*@~;#,|/]}
17
+ DICTIONARY_PREFIX_PATTERN = /[A-Za-z][A-Za-z0-9_.-]*/
18
+ # formulaType pattern from the XSD. Allows concise formula
19
+ # notation like "C 2 H 6 O 1".
20
+ FORMULA_PATTERN = /\s*([A-Z][a-z]?\s+(([0-9]+(\.[0-9]*)?)|(\.[0-9]*))?\s*)+(\s+-?[0-9]+)?\s*/
21
+ HEAD_PATTERN = /[A-Za-z][A-Za-z0-9_]*/
22
+ ID_PATTERN = /[A-Za-z][A-Za-z0-9.\-_]*/
23
+ ISOTOPIC_SPIN_PATTERN = /\d{1,}(\d+)?/
24
+ MOLECULE_ID_PATTERN = /[A-Za-z_][A-Za-z0-9_-]*(:[A-Za-z0-9_-]+)?/
25
+ NAMESPACE_REF_PATTERN = /[A-Za-z][A-Za-z0-9_]*:[A-Za-z][A-Za-z0-9_.-]*/
26
+ NAMESPACE_PATTERN = %r{http://[A-Za-z][A-Za-z0-9_.-]*(/[A-Za-z0-9_.-]+)+[/#]?}
27
+ REF_PATTERN = /([A-Za-z_][A-Za-z0-9_.-]*:)?[A-Za-z_][A-Za-z0-9_.-]*/
28
+ REPEAT_PATTERN = /[A-Za-z]+ [A-Za-z0-9_\-+]+ [A-Za-z0-9_\-+]+/
29
+ TAIL_PATTERN = /[A-Za-z][A-Za-z0-9_]*/
30
+ VERSION_PATTERN = /[0-9]+(\.[0-9]+[A-Za-z0-9.\-_]*)*/
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Cml
5
+ # Walks a CML document and resolves id-based references to the
6
+ # actual target wire instances. Useful for callers that need to
7
+ # follow CML references programmatically (e.g. bond → atoms,
8
+ # atomParity → atoms, map → molecules).
9
+ #
10
+ # References are attribute values like `atomRefs2="a1 a2"`,
11
+ # `atomRefs4="a1 a2 a3 a4"`, `bondRefs="b1 b2"`, `ref="m1"`.
12
+ # The values are whitespace-separated lists of ids.
13
+ #
14
+ # The resolver is opt-in: it does not modify the wire tree. Callers
15
+ # use it to perform lookups; unresolved refs are reported in a
16
+ # list (a constraint turns this list into warnings).
17
+ class ReferenceResolver
18
+ attr_reader :document
19
+
20
+ # @param document [Lutaml::Model::Serializable] the CML document
21
+ # to walk. Must include `Chemicalml::Cml::Visitable` (the
22
+ # standard wire classes do).
23
+ def initialize(document)
24
+ @document = document
25
+ @atom_index = nil
26
+ @bond_index = nil
27
+ end
28
+
29
+ # Lazily-built {id => Atom} index. Speeds up `find_atom` and
30
+ # reference-resolution lookups from O(n) to O(1).
31
+ def atom_index
32
+ @atom_index ||= begin
33
+ hash = {}
34
+ document.each_atom { |a| hash[a.id] = a if a.id }
35
+ hash
36
+ end
37
+ end
38
+
39
+ # Lazily-built {id => Bond} index.
40
+ def bond_index
41
+ @bond_index ||= begin
42
+ hash = {}
43
+ document.each_bond { |b| hash[b.id] = b if b.id }
44
+ hash
45
+ end
46
+ end
47
+
48
+ # Returns the Atom with the given id within the given molecule,
49
+ # or nil if not found.
50
+ def find_atom(_molecule, atom_id)
51
+ return nil unless atom_id
52
+
53
+ atom_index[atom_id]
54
+ end
55
+
56
+ # Returns the Bond with the given id within the given molecule,
57
+ # or nil if not found.
58
+ def find_bond(_molecule, bond_id)
59
+ return nil unless bond_id
60
+
61
+ bond_index[bond_id]
62
+ end
63
+
64
+ # Resolves `bond.atom_refs2` to a pair of [Atom, Atom]. Returns
65
+ # nils for missing atoms so callers can detect partial misses.
66
+ def resolve_atom_refs2(bond, molecule = containing_molecule(bond))
67
+ ids = parse_refs(bond&.atom_refs2)
68
+ return [] if ids.empty?
69
+ return [nil, nil] if ids.size != 2
70
+
71
+ ids.map { |id| find_atom(molecule, id) }
72
+ end
73
+
74
+ # Walks the whole document and reports every reference attribute
75
+ # whose target id is missing. Returns a list of hashes:
76
+ #
77
+ # { node: <Bond>, attr: :atom_refs2, missing: ["a99"] }
78
+ def unresolved_refs
79
+ results = []
80
+ visit(@document) do |node|
81
+ results.concat(unresolved_for(node))
82
+ end
83
+ results
84
+ end
85
+
86
+ private
87
+
88
+ def visit(node, &block)
89
+ return unless node.is_a?(Lutaml::Model::Serializable)
90
+
91
+ yield(node)
92
+ return unless node.is_a?(Chemicalml::Cml::Visitable)
93
+
94
+ node.wire_children.each { |child| visit(child, &block) }
95
+ end
96
+
97
+ # Returns all molecules in the document (top-level + nested)
98
+ def all_molecules
99
+ result = []
100
+ visit(@document) do |node|
101
+ result << node if node.is_a?(Chemicalml::Cml::Role::Molecule)
102
+ end
103
+ result
104
+ end
105
+
106
+ def containing_molecule(node)
107
+ # The constraint walker doesn't track parents. For now, return
108
+ # the first molecule in document order — the common case is
109
+ # that bond atoms live in the same parent molecule.
110
+ all_molecules.find { |m| m.bond_array && (m.bond_array.bonds || []).include?(node) }
111
+ end
112
+
113
+ def parse_refs(value)
114
+ return [] if value.nil?
115
+
116
+ value.to_s.split(/\s+/).reject(&:empty?)
117
+ end
118
+
119
+ def unresolved_for(node)
120
+ return [] unless node.is_a?(Chemicalml::Cml::Role::Bond)
121
+
122
+ ids = parse_refs(node.atom_refs2)
123
+ return [] if ids.empty?
124
+
125
+ # Use the global atom_index (O(1) per lookup) — the
126
+ # `containing_molecule` indirection is unnecessary for
127
+ # reference resolution at the document level. CML semantics
128
+ # already enforce that bond refs live in the parent molecule
129
+ # (caught by `BondMustReferenceAtomsInSameMolecule`).
130
+ missing = ids.reject { |id| atom_index[id] }
131
+ return [] if missing.empty?
132
+
133
+ [{ node: node, attr: :atom_refs2, missing: missing }]
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Cml
5
+ module Role
6
+ module Alternative
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Cml
5
+ module Role
6
+ module Annotation
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Cml
5
+ module Role
6
+ module Appinfo
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Cml
5
+ module Role
6
+ module Arg
7
+ end
8
+ end
9
+ end
10
+ end
@@ -4,9 +4,8 @@ module Chemicalml
4
4
  module Cml
5
5
  module Role
6
6
  # Type marker for any wire class implementing the CML
7
- # <module> element. Included by Schema3::Module.
8
- # (Schema24::Module does not exist - schema 2.4 lacks the
9
- # generic <module> element.)
7
+ # <module> element. Included by both Schema3::Module and
8
+ # Schema24::Module.
10
9
  module Module
11
10
  end
12
11
  end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Cml
5
+ module Role
6
+ module ComplexObject
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Cml
5
+ module Role
6
+ module Enumeration
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Cml
5
+ module Role
6
+ module Expression
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Cml
5
+ module Role
6
+ module Float
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Cml
5
+ module Role
6
+ module FloatArray
7
+ end
8
+ end
9
+ end
10
+ end