chemicalml 0.2.0 → 0.2.1

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 (304) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/release.yml +7 -1
  3. data/CLAUDE.md +48 -41
  4. data/TODO.align/36-molecular-convention-coverage.md +46 -0
  5. data/TODO.align/37-compchem-convention-coverage.md +55 -0
  6. data/TODO.align/38-dictionary-convention-coverage.md +34 -0
  7. data/TODO.align/39-unit-dictionary-convention-coverage.md +33 -0
  8. data/TODO.align/40-unit-type-dictionary-convention-coverage.md +28 -0
  9. data/TODO.align/41-expand-canonical-model-layer.md +43 -0
  10. data/TODO.align/42-translator-wire-new-models.md +31 -0
  11. data/TODO.align/43-dictionary-model-no-to-h.md +39 -0
  12. data/TODO.align/44-schema3-only-and-schema24-module.md +44 -0
  13. data/TODO.align/45-documentation-and-final-verification.md +23 -0
  14. data/TODO.align/46-lattice-vector-content.md +24 -0
  15. data/TODO.align/47-molecule-crystal-spectra-property-lists.md +23 -0
  16. data/TODO.align/48-model-list-and-module-lists.md +21 -0
  17. data/TODO.align/49-more-chemistry-models.md +34 -0
  18. data/TODO.align/50-validation-report.md +29 -0
  19. data/TODO.align/51-convention-auto-detection.md +30 -0
  20. data/TODO.align/52-schema24-legacy-elements.md +28 -0
  21. data/TODO.align/53-round-trip-integration-specs.md +30 -0
  22. data/TODO.align/54-document-versioned-parser-shim.md +38 -0
  23. data/TODO.align/55-molecule-missing-attributes.md +20 -0
  24. data/TODO.align/56-geometry-models.md +24 -0
  25. data/TODO.align/57-compchem-models.md +26 -0
  26. data/TODO.align/58-remaining-models.md +24 -0
  27. data/TODO.align/59-wire-new-models-translator.md +18 -0
  28. data/TODO.align/60-docs-and-final-verification.md +19 -0
  29. data/lib/chemicalml/cml/base/abundance.rb +6 -0
  30. data/lib/chemicalml/cml/base/action.rb +20 -0
  31. data/lib/chemicalml/cml/base/action_list.rb +18 -0
  32. data/lib/chemicalml/cml/base/alternative.rb +28 -0
  33. data/lib/chemicalml/cml/base/amount.rb +2 -0
  34. data/lib/chemicalml/cml/base/angle.rb +12 -0
  35. data/lib/chemicalml/cml/base/annotation.rb +30 -0
  36. data/lib/chemicalml/cml/base/appinfo.rb +32 -0
  37. data/lib/chemicalml/cml/base/arg.rb +46 -0
  38. data/lib/chemicalml/cml/base/array.rb +22 -0
  39. data/lib/chemicalml/cml/base/array_list.rb +2 -0
  40. data/lib/chemicalml/cml/base/atom.rb +18 -0
  41. data/lib/chemicalml/cml/base/atom_array.rb +38 -0
  42. data/lib/chemicalml/cml/base/atom_parity.rb +8 -0
  43. data/lib/chemicalml/cml/base/atom_set.rb +2 -0
  44. data/lib/chemicalml/cml/base/atom_type.rb +4 -0
  45. data/lib/chemicalml/cml/base/atom_type_list.rb +2 -0
  46. data/lib/chemicalml/cml/base/atomic_basis_function.rb +4 -0
  47. data/lib/chemicalml/cml/base/band.rb +2 -0
  48. data/lib/chemicalml/cml/base/basis_set.rb +4 -0
  49. data/lib/chemicalml/cml/base/bond.rb +6 -0
  50. data/lib/chemicalml/cml/base/bond_array.rb +16 -0
  51. data/lib/chemicalml/cml/base/bond_set.rb +2 -0
  52. data/lib/chemicalml/cml/base/bond_stereo.rb +10 -0
  53. data/lib/chemicalml/cml/base/bond_type.rb +2 -0
  54. data/lib/chemicalml/cml/base/bond_type_list.rb +2 -0
  55. data/lib/chemicalml/cml/base/cell_parameter.rb +4 -0
  56. data/lib/chemicalml/cml/base/complex_object.rb +30 -0
  57. data/lib/chemicalml/cml/base/condition_list.rb +4 -0
  58. data/lib/chemicalml/cml/base/crystal.rb +2 -0
  59. data/lib/chemicalml/cml/base/description.rb +2 -0
  60. data/lib/chemicalml/cml/base/dictionary.rb +6 -0
  61. data/lib/chemicalml/cml/base/dimension.rb +10 -0
  62. data/lib/chemicalml/cml/base/eigen.rb +2 -0
  63. data/lib/chemicalml/cml/base/electron.rb +6 -0
  64. data/lib/chemicalml/cml/base/enumeration.rb +32 -0
  65. data/lib/chemicalml/cml/base/expression.rb +32 -0
  66. data/lib/chemicalml/cml/base/float.rb +40 -0
  67. data/lib/chemicalml/cml/base/float_array.rb +42 -0
  68. data/lib/chemicalml/cml/base/fragment.rb +6 -0
  69. data/lib/chemicalml/cml/base/fragment_list.rb +4 -0
  70. data/lib/chemicalml/cml/base/identifier.rb +8 -0
  71. data/lib/chemicalml/cml/base/integer.rb +40 -0
  72. data/lib/chemicalml/cml/base/integer_array.rb +42 -0
  73. data/lib/chemicalml/cml/base/isotope.rb +2 -0
  74. data/lib/chemicalml/cml/base/isotope_list.rb +2 -0
  75. data/lib/chemicalml/cml/base/join.rb +6 -0
  76. data/lib/chemicalml/cml/base/kpoint.rb +2 -0
  77. data/lib/chemicalml/cml/base/label.rb +2 -0
  78. data/lib/chemicalml/cml/base/lattice.rb +2 -0
  79. data/lib/chemicalml/cml/base/lattice_vector.rb +2 -0
  80. data/lib/chemicalml/cml/base/length.rb +10 -0
  81. data/lib/chemicalml/cml/base/line3.rb +6 -0
  82. data/lib/chemicalml/cml/base/link.rb +20 -0
  83. data/lib/chemicalml/cml/base/list.rb +2 -0
  84. data/lib/chemicalml/cml/base/map.rb +12 -0
  85. data/lib/chemicalml/cml/base/matrix.rb +12 -0
  86. data/lib/chemicalml/cml/base/metadata.rb +4 -0
  87. data/lib/chemicalml/cml/base/metadata_list.rb +6 -0
  88. data/lib/chemicalml/cml/base/molecule.rb +10 -0
  89. data/lib/chemicalml/cml/base/molecule_list.rb +2 -0
  90. data/lib/chemicalml/cml/base/name.rb +2 -0
  91. data/lib/chemicalml/cml/base/object.rb +4 -0
  92. data/lib/chemicalml/cml/base/observation.rb +4 -0
  93. data/lib/chemicalml/cml/base/operator.rb +32 -0
  94. data/lib/chemicalml/cml/base/parameter.rb +10 -0
  95. data/lib/chemicalml/cml/base/parameter_list.rb +6 -0
  96. data/lib/chemicalml/cml/base/particle.rb +6 -0
  97. data/lib/chemicalml/cml/base/peak.rb +30 -0
  98. data/lib/chemicalml/cml/base/peak_group.rb +38 -0
  99. data/lib/chemicalml/cml/base/peak_list.rb +2 -0
  100. data/lib/chemicalml/cml/base/peak_structure.rb +14 -0
  101. data/lib/chemicalml/cml/base/plane3.rb +2 -0
  102. data/lib/chemicalml/cml/base/point3.rb +2 -0
  103. data/lib/chemicalml/cml/base/potential_form.rb +2 -0
  104. data/lib/chemicalml/cml/base/product.rb +16 -0
  105. data/lib/chemicalml/cml/base/product_list.rb +14 -0
  106. data/lib/chemicalml/cml/base/property.rb +6 -0
  107. data/lib/chemicalml/cml/base/property_list.rb +6 -0
  108. data/lib/chemicalml/cml/base/reactant.rb +16 -0
  109. data/lib/chemicalml/cml/base/reactant_list.rb +14 -0
  110. data/lib/chemicalml/cml/base/reaction.rb +16 -0
  111. data/lib/chemicalml/cml/base/reaction_list.rb +12 -0
  112. data/lib/chemicalml/cml/base/reaction_scheme.rb +10 -0
  113. data/lib/chemicalml/cml/base/reaction_step.rb +6 -0
  114. data/lib/chemicalml/cml/base/reaction_step_list.rb +8 -0
  115. data/lib/chemicalml/cml/base/region.rb +8 -0
  116. data/lib/chemicalml/cml/base/related_entry.rb +26 -0
  117. data/lib/chemicalml/cml/base/sample.rb +4 -0
  118. data/lib/chemicalml/cml/base/scalar.rb +18 -0
  119. data/lib/chemicalml/cml/base/spectator.rb +2 -0
  120. data/lib/chemicalml/cml/base/spectrum.rb +12 -0
  121. data/lib/chemicalml/cml/base/spectrum_data.rb +2 -0
  122. data/lib/chemicalml/cml/base/spectrum_list.rb +4 -0
  123. data/lib/chemicalml/cml/base/sphere3.rb +2 -0
  124. data/lib/chemicalml/cml/base/string.rb +32 -0
  125. data/lib/chemicalml/cml/base/string_array.rb +40 -0
  126. data/lib/chemicalml/cml/base/substance.rb +12 -0
  127. data/lib/chemicalml/cml/base/substance_list.rb +6 -0
  128. data/lib/chemicalml/cml/base/symmetry.rb +4 -0
  129. data/lib/chemicalml/cml/base/system.rb +4 -0
  130. data/lib/chemicalml/cml/base/table.rb +10 -0
  131. data/lib/chemicalml/cml/base/table_content.rb +2 -0
  132. data/lib/chemicalml/cml/base/table_header_cell.rb +10 -0
  133. data/lib/chemicalml/cml/base/tcell.rb +34 -0
  134. data/lib/chemicalml/cml/base/torsion.rb +12 -0
  135. data/lib/chemicalml/cml/base/trow.rb +32 -0
  136. data/lib/chemicalml/cml/base/unit.rb +12 -0
  137. data/lib/chemicalml/cml/base/unit_list.rb +12 -0
  138. data/lib/chemicalml/cml/base/unit_type.rb +10 -0
  139. data/lib/chemicalml/cml/base/unit_type_list.rb +10 -0
  140. data/lib/chemicalml/cml/base/vector3.rb +2 -0
  141. data/lib/chemicalml/cml/base/xaxis.rb +6 -0
  142. data/lib/chemicalml/cml/base/yaxis.rb +6 -0
  143. data/lib/chemicalml/cml/base.rb +17 -0
  144. data/lib/chemicalml/cml/elements.rb +39 -4
  145. data/lib/chemicalml/cml/role/alternative.rb +10 -0
  146. data/lib/chemicalml/cml/role/annotation.rb +10 -0
  147. data/lib/chemicalml/cml/role/appinfo.rb +10 -0
  148. data/lib/chemicalml/cml/role/arg.rb +10 -0
  149. data/lib/chemicalml/cml/role/cml_module.rb +2 -3
  150. data/lib/chemicalml/cml/role/complex_object.rb +10 -0
  151. data/lib/chemicalml/cml/role/enumeration.rb +10 -0
  152. data/lib/chemicalml/cml/role/expression.rb +10 -0
  153. data/lib/chemicalml/cml/role/float.rb +10 -0
  154. data/lib/chemicalml/cml/role/float_array.rb +10 -0
  155. data/lib/chemicalml/cml/role/integer.rb +10 -0
  156. data/lib/chemicalml/cml/role/integer_array.rb +10 -0
  157. data/lib/chemicalml/cml/role/operator.rb +10 -0
  158. data/lib/chemicalml/cml/role/related_entry.rb +10 -0
  159. data/lib/chemicalml/cml/role/string.rb +10 -0
  160. data/lib/chemicalml/cml/role/string_array.rb +10 -0
  161. data/lib/chemicalml/cml/role/tcell.rb +10 -0
  162. data/lib/chemicalml/cml/role/trow.rb +10 -0
  163. data/lib/chemicalml/cml/role.rb +17 -0
  164. data/lib/chemicalml/cml/schema24/alternative.rb +14 -0
  165. data/lib/chemicalml/cml/schema24/annotation.rb +15 -0
  166. data/lib/chemicalml/cml/schema24/appinfo.rb +15 -0
  167. data/lib/chemicalml/cml/schema24/arg.rb +14 -0
  168. data/lib/chemicalml/cml/schema24/cml_module.rb +18 -0
  169. data/lib/chemicalml/cml/schema24/complex_object.rb +14 -0
  170. data/lib/chemicalml/cml/schema24/configuration.rb +5 -2
  171. data/lib/chemicalml/cml/schema24/enumeration.rb +16 -0
  172. data/lib/chemicalml/cml/schema24/expression.rb +14 -0
  173. data/lib/chemicalml/cml/schema24/float.rb +14 -0
  174. data/lib/chemicalml/cml/schema24/float_array.rb +14 -0
  175. data/lib/chemicalml/cml/schema24/integer.rb +14 -0
  176. data/lib/chemicalml/cml/schema24/integer_array.rb +14 -0
  177. data/lib/chemicalml/cml/schema24/operator.rb +14 -0
  178. data/lib/chemicalml/cml/schema24/related_entry.rb +14 -0
  179. data/lib/chemicalml/cml/schema24/string.rb +14 -0
  180. data/lib/chemicalml/cml/schema24/string_array.rb +14 -0
  181. data/lib/chemicalml/cml/schema24/tcell.rb +14 -0
  182. data/lib/chemicalml/cml/schema24/trow.rb +14 -0
  183. data/lib/chemicalml/cml/schema24.rb +33 -5
  184. data/lib/chemicalml/cml.rb +1 -3
  185. data/lib/chemicalml/context_configuration.rb +8 -2
  186. data/lib/chemicalml/convention/base.rb +17 -3
  187. data/lib/chemicalml/convention/compchem/constraints/array_rules.rb +44 -0
  188. data/lib/chemicalml/convention/compchem/constraints/calculation_requires_finalization.rb +28 -0
  189. data/lib/chemicalml/convention/compchem/constraints/compchem_module_must_contain_job_list.rb +4 -4
  190. data/lib/chemicalml/convention/compchem/constraints/environment_at_most_one_property_list.rb +26 -0
  191. data/lib/chemicalml/convention/compchem/constraints/environment_must_not_contain_parameter.rb +28 -0
  192. data/lib/chemicalml/convention/compchem/constraints/finalization_at_most_one_molecule.rb +26 -0
  193. data/lib/chemicalml/convention/compchem/constraints/finalization_at_most_one_property_list.rb +26 -0
  194. data/lib/chemicalml/convention/compchem/constraints/finalization_must_not_contain_parameter.rb +27 -0
  195. data/lib/chemicalml/convention/compchem/constraints/initialization_at_most_one_molecule.rb +26 -0
  196. data/lib/chemicalml/convention/compchem/constraints/initialization_at_most_one_parameter_list.rb +26 -0
  197. data/lib/chemicalml/convention/compchem/constraints/initialization_must_not_contain_property.rb +28 -0
  198. data/lib/chemicalml/convention/compchem/constraints/job_list_module_must_have_id.rb +24 -0
  199. data/lib/chemicalml/convention/compchem/constraints/job_module_at_most_one_environment.rb +25 -0
  200. data/lib/chemicalml/convention/compchem/constraints/job_module_at_most_one_finalization.rb +25 -0
  201. data/lib/chemicalml/convention/compchem/constraints/job_module_must_have_id.rb +24 -0
  202. data/lib/chemicalml/convention/compchem/constraints/job_must_contain_initialization.rb +6 -9
  203. data/lib/chemicalml/convention/compchem/constraints/matrix_rules.rb +48 -0
  204. data/lib/chemicalml/convention/compchem/constraints/module_predicates.rb +50 -0
  205. data/lib/chemicalml/convention/compchem/constraints/scalar_units.rb +42 -0
  206. data/lib/chemicalml/convention/compchem/constraints.rb +36 -2
  207. data/lib/chemicalml/convention/compchem.rb +16 -0
  208. data/lib/chemicalml/convention/constraint.rb +31 -18
  209. data/lib/chemicalml/convention/coordinator.rb +89 -0
  210. data/lib/chemicalml/convention/detection.rb +33 -0
  211. data/lib/chemicalml/convention/dictionary/constraints/dictionary_must_have_namespace.rb +28 -0
  212. data/lib/chemicalml/convention/dictionary/constraints/dictionary_namespace_should_end_with_slash_or_hash.rb +32 -0
  213. data/lib/chemicalml/convention/dictionary/constraints/entry_id_must_match_pattern.rb +33 -0
  214. data/lib/chemicalml/convention/dictionary/constraints/entry_ids_unique_within_dictionary.rb +3 -3
  215. data/lib/chemicalml/convention/dictionary/constraints/entry_must_contain_definition.rb +28 -0
  216. data/lib/chemicalml/convention/dictionary/constraints/entry_must_have_id_and_term.rb +5 -5
  217. data/lib/chemicalml/convention/dictionary/constraints/entry_must_have_unit_type.rb +30 -0
  218. data/lib/chemicalml/convention/dictionary/constraints/entry_units_co_constraints.rb +44 -0
  219. data/lib/chemicalml/convention/dictionary/constraints.rb +12 -0
  220. data/lib/chemicalml/convention/dictionary.rb +6 -0
  221. data/lib/chemicalml/convention/molecular/constraints/atom_array_must_be_child_of_molecule_or_formula.rb +40 -0
  222. data/lib/chemicalml/convention/molecular/constraints/atom_array_must_contain_atoms.rb +3 -3
  223. data/lib/chemicalml/convention/molecular/constraints/atom_coordinates_must_be_paired.rb +5 -5
  224. data/lib/chemicalml/convention/molecular/constraints/atom_id_must_match_pattern.rb +4 -4
  225. data/lib/chemicalml/convention/molecular/constraints/atom_ids_unique_within_molecule.rb +2 -2
  226. data/lib/chemicalml/convention/molecular/constraints/atom_must_have_element_type.rb +3 -3
  227. data/lib/chemicalml/convention/molecular/constraints/atom_must_have_id.rb +3 -3
  228. data/lib/chemicalml/convention/molecular/constraints/bond_array_must_be_child_of_molecule.rb +36 -0
  229. data/lib/chemicalml/convention/molecular/constraints/bond_ids_unique_within_molecule.rb +43 -0
  230. data/lib/chemicalml/convention/molecular/constraints/bond_must_have_atom_refs2.rb +3 -3
  231. data/lib/chemicalml/convention/molecular/constraints/bond_must_have_order.rb +3 -3
  232. data/lib/chemicalml/convention/molecular/constraints/bond_must_reference_atoms_in_same_molecule.rb +3 -3
  233. data/lib/chemicalml/convention/molecular/constraints/bond_order_other_must_have_dict_ref.rb +33 -0
  234. data/lib/chemicalml/convention/molecular/constraints/bond_order_should_not_be_numeric.rb +2 -2
  235. data/lib/chemicalml/convention/molecular/constraints/bond_stereo_cis_trans_must_have_atom_refs4.rb +45 -0
  236. data/lib/chemicalml/convention/molecular/constraints/bond_stereo_other_must_have_dict_ref.rb +32 -0
  237. data/lib/chemicalml/convention/molecular/constraints/bond_stereo_wedge_hash_must_have_atom_refs2.rb +45 -0
  238. data/lib/chemicalml/convention/molecular/constraints/molecule_atom_array_mutually_exclusive_with_children.rb +32 -0
  239. data/lib/chemicalml/convention/molecular/constraints/molecule_bond_array_mutually_exclusive_with_children.rb +31 -0
  240. data/lib/chemicalml/convention/molecular/constraints/molecule_count_must_not_appear_on_top_level.rb +34 -0
  241. data/lib/chemicalml/convention/molecular/constraints/molecule_must_have_id.rb +3 -3
  242. data/lib/chemicalml/convention/molecular/constraints/property_must_have_dict_ref.rb +3 -3
  243. data/lib/chemicalml/convention/molecular/constraints/scalar_must_have_data_type.rb +3 -3
  244. data/lib/chemicalml/convention/molecular/constraints.rb +20 -0
  245. data/lib/chemicalml/convention/molecular.rb +10 -0
  246. data/lib/chemicalml/convention/registry.rb +17 -0
  247. data/lib/chemicalml/convention/unit_dictionary/constraints/unit_list_must_contain_at_least_one_unit.rb +28 -0
  248. data/lib/chemicalml/convention/unit_dictionary/constraints/unit_list_must_have_namespace.rb +36 -0
  249. data/lib/chemicalml/convention/unit_dictionary/constraints/unit_must_contain_definition.rb +27 -0
  250. data/lib/chemicalml/convention/unit_dictionary/constraints/unit_must_have_id.rb +27 -0
  251. data/lib/chemicalml/convention/unit_dictionary/constraints/unit_must_have_symbol_and_unit_type.rb +3 -3
  252. data/lib/chemicalml/convention/unit_dictionary/constraints.rb +9 -1
  253. data/lib/chemicalml/convention/unit_dictionary.rb +4 -0
  254. data/lib/chemicalml/convention/unit_type_dictionary/constraints/unit_type_id_must_match_pattern.rb +31 -0
  255. data/lib/chemicalml/convention/unit_type_dictionary/constraints/unit_type_list_must_contain_at_least_one_unit_type.rb +27 -0
  256. data/lib/chemicalml/convention/unit_type_dictionary/constraints/unit_type_list_must_have_namespace.rb +35 -0
  257. data/lib/chemicalml/convention/unit_type_dictionary/constraints/unit_type_must_contain_definition.rb +27 -0
  258. data/lib/chemicalml/convention/unit_type_dictionary/constraints/unit_type_must_have_id_and_name.rb +5 -5
  259. data/lib/chemicalml/convention/unit_type_dictionary/constraints.rb +9 -1
  260. data/lib/chemicalml/convention/unit_type_dictionary.rb +4 -0
  261. data/lib/chemicalml/convention/validation_report.rb +63 -0
  262. data/lib/chemicalml/convention.rb +11 -0
  263. data/lib/chemicalml/dictionary/entry.rb +6 -6
  264. data/lib/chemicalml/dictionary/enum.rb +1 -1
  265. data/lib/chemicalml/dictionary/link.rb +3 -3
  266. data/lib/chemicalml/dictionary/loader.rb +19 -19
  267. data/lib/chemicalml/dictionary/model.rb +5 -5
  268. data/lib/chemicalml/dictionary/registry.rb +9 -9
  269. data/lib/chemicalml/version.rb +1 -1
  270. data/lib/chemicalml/versioned_parser.rb +18 -0
  271. data/lib/chemicalml.rb +1 -2
  272. metadata +123 -34
  273. data/lib/chemicalml/cml/child_mappings.rb +0 -168
  274. data/lib/chemicalml/cml/translator/value_translations.rb +0 -270
  275. data/lib/chemicalml/cml/translator.rb +0 -484
  276. data/lib/chemicalml/model/atom.rb +0 -64
  277. data/lib/chemicalml/model/atom_parity.rb +0 -21
  278. data/lib/chemicalml/model/bond.rb +0 -39
  279. data/lib/chemicalml/model/bond_stereo.rb +0 -29
  280. data/lib/chemicalml/model/cml_array.rb +0 -27
  281. data/lib/chemicalml/model/cml_module.rb +0 -45
  282. data/lib/chemicalml/model/document.rb +0 -29
  283. data/lib/chemicalml/model/formula.rb +0 -34
  284. data/lib/chemicalml/model/identifier.rb +0 -21
  285. data/lib/chemicalml/model/label.rb +0 -21
  286. data/lib/chemicalml/model/matrix.rb +0 -29
  287. data/lib/chemicalml/model/metadata.rb +0 -23
  288. data/lib/chemicalml/model/metadata_list.rb +0 -25
  289. data/lib/chemicalml/model/molecule.rb +0 -45
  290. data/lib/chemicalml/model/name.rb +0 -21
  291. data/lib/chemicalml/model/node.rb +0 -45
  292. data/lib/chemicalml/model/parameter.rb +0 -27
  293. data/lib/chemicalml/model/parameter_list.rb +0 -25
  294. data/lib/chemicalml/model/product.rb +0 -21
  295. data/lib/chemicalml/model/product_list.rb +0 -21
  296. data/lib/chemicalml/model/property.rb +0 -28
  297. data/lib/chemicalml/model/property_list.rb +0 -25
  298. data/lib/chemicalml/model/reactant.rb +0 -21
  299. data/lib/chemicalml/model/reactant_list.rb +0 -21
  300. data/lib/chemicalml/model/reaction.rb +0 -41
  301. data/lib/chemicalml/model/reaction_list.rb +0 -23
  302. data/lib/chemicalml/model/scalar.rb +0 -25
  303. data/lib/chemicalml/model/substance.rb +0 -25
  304. data/lib/chemicalml/model.rb +0 -40
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Convention
5
+ module UnitTypeDictionary
6
+ module Constraints
7
+ # A `<unitType>` `id` MUST match `[A-Za-z][A-Za-z0-9._-]*`.
8
+ class UnitTypeIdMustMatchPattern < Chemicalml::Convention::Constraint::NodeConstraint
9
+ applies_to Chemicalml::Cml::Role::UnitType
10
+ PATTERN = /\A[A-Za-z][A-Za-z0-9._-]*\z/
11
+
12
+ def check_node(node, path)
13
+
14
+ id = node.id.to_s
15
+ return [] if id.empty?
16
+ return [] if id.match?(PATTERN)
17
+
18
+ [violation(path: path.join('/'),
19
+ message: "unitType id #{id.inspect} must match [A-Za-z][A-Za-z0-9._-]*")]
20
+ end
21
+
22
+ private
23
+
24
+ def unit_type?(node)
25
+ node.is_a?(Chemicalml::Cml::Role::UnitType)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Convention
5
+ module UnitTypeDictionary
6
+ module Constraints
7
+ # A `<unitTypeList>` MUST contain one or more `<unitType>`
8
+ # children.
9
+ class UnitTypeListMustContainAtLeastOneUnitType < Chemicalml::Convention::Constraint::NodeConstraint
10
+ applies_to Chemicalml::Cml::Role::UnitTypeList
11
+ def check_node(node, path)
12
+ return [] if (node.unit_types || []).length.positive?
13
+
14
+ [violation(path: path.join('/'),
15
+ message: 'unitTypeList must contain at least one unitType child')]
16
+ end
17
+
18
+ private
19
+
20
+ def unit_type_list?(node)
21
+ node.is_a?(Chemicalml::Cml::Role::UnitTypeList)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Convention
5
+ module UnitTypeDictionary
6
+ module Constraints
7
+ # A `<unitTypeList>` MUST have a `namespace` attribute (valid
8
+ # URI, SHOULD end with `/` or `#`).
9
+ class UnitTypeListMustHaveNamespace < Chemicalml::Convention::Constraint::NodeConstraint
10
+ applies_to Chemicalml::Cml::Role::UnitTypeList
11
+ def check_node(node, path)
12
+
13
+ violations = []
14
+ ns = node.namespace.to_s
15
+ if ns.empty?
16
+ violations << violation(path: path.join('/'),
17
+ message: 'unitTypeList must have a namespace attribute')
18
+ elsif !ns.end_with?('/', '#')
19
+ violations << violation(path: path.join('/'),
20
+ message: "unitTypeList namespace #{ns.inspect} should end with / or #",
21
+ severity: :warning)
22
+ end
23
+ violations
24
+ end
25
+
26
+ private
27
+
28
+ def unit_type_list?(node)
29
+ node.is_a?(Chemicalml::Cml::Role::UnitTypeList)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Convention
5
+ module UnitTypeDictionary
6
+ module Constraints
7
+ # A `<unitType>` MUST contain a single `<definition>` child
8
+ # with XHTML content.
9
+ class UnitTypeMustContainDefinition < Chemicalml::Convention::Constraint::NodeConstraint
10
+ applies_to Chemicalml::Cml::Role::UnitType
11
+ def check_node(node, path)
12
+ return [] unless node.definition.to_s.strip.empty?
13
+
14
+ [violation(path: path.join('/'),
15
+ message: "unitType #{node.id.inspect} must contain a single definition child")]
16
+ end
17
+
18
+ private
19
+
20
+ def unit_type?(node)
21
+ node.is_a?(Chemicalml::Cml::Role::UnitType)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -7,17 +7,17 @@ module Chemicalml
7
7
  # Every unitType MUST have an `id` and a `name` attribute per
8
8
  # the unitType-dictionary convention.
9
9
  class UnitTypeMustHaveIdAndName < Chemicalml::Convention::Constraint::NodeConstraint
10
+ applies_to Chemicalml::Cml::Role::UnitType
10
11
  def check_node(node, path)
11
- return [] unless unit_type?(node)
12
12
 
13
13
  violations = []
14
14
  if node.id.to_s.empty?
15
- violations << violation(path: path.join("/"),
16
- message: "unitType must have an id")
15
+ violations << violation(path: path.join('/'),
16
+ message: 'unitType must have an id')
17
17
  end
18
18
  if node.name.to_s.empty?
19
- violations << violation(path: path.join("/"),
20
- message: "unitType must have a name")
19
+ violations << violation(path: path.join('/'),
20
+ message: 'unitType must have a name')
21
21
  end
22
22
  violations
23
23
  end
@@ -5,7 +5,15 @@ module Chemicalml
5
5
  module UnitTypeDictionary
6
6
  module Constraints
7
7
  autoload :UnitTypeMustHaveIdAndName,
8
- "chemicalml/convention/unit_type_dictionary/constraints/unit_type_must_have_id_and_name"
8
+ 'chemicalml/convention/unit_type_dictionary/constraints/unit_type_must_have_id_and_name'
9
+ autoload :UnitTypeIdMustMatchPattern,
10
+ 'chemicalml/convention/unit_type_dictionary/constraints/unit_type_id_must_match_pattern'
11
+ autoload :UnitTypeMustContainDefinition,
12
+ 'chemicalml/convention/unit_type_dictionary/constraints/unit_type_must_contain_definition'
13
+ autoload :UnitTypeListMustHaveNamespace,
14
+ 'chemicalml/convention/unit_type_dictionary/constraints/unit_type_list_must_have_namespace'
15
+ autoload :UnitTypeListMustContainAtLeastOneUnitType,
16
+ 'chemicalml/convention/unit_type_dictionary/constraints/unit_type_list_must_contain_at_least_one_unit_type'
9
17
  end
10
18
  end
11
19
  end
@@ -22,6 +22,10 @@ module Chemicalml
22
22
  end
23
23
 
24
24
  register Constraints::UnitTypeMustHaveIdAndName
25
+ register Constraints::UnitTypeIdMustMatchPattern
26
+ register Constraints::UnitTypeMustContainDefinition
27
+ register Constraints::UnitTypeListMustHaveNamespace
28
+ register Constraints::UnitTypeListMustContainAtLeastOneUnitType
25
29
  end
26
30
  end
27
31
  end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Convention
5
+ # Value object wrapping the violations returned by `validate`.
6
+ # Gives callers severity-based views without losing the raw array
7
+ # (still exposed as `#violations`).
8
+ #
9
+ # Constructed by `Convention.validate_report` (new API) —
10
+ # `Convention.validate` keeps its array return shape so existing
11
+ # callers don't break.
12
+ class ValidationReport
13
+ attr_reader :violations
14
+
15
+ def initialize(violations)
16
+ @violations = violations.to_a.freeze
17
+ end
18
+
19
+ def errors
20
+ @errors ||= violations.select(&:error?).freeze
21
+ end
22
+
23
+ def warnings
24
+ @warnings ||= violations.select(&:warning?).freeze
25
+ end
26
+
27
+ def ok?
28
+ errors.empty?
29
+ end
30
+
31
+ def has_warnings?
32
+ warnings.any?
33
+ end
34
+
35
+ def size
36
+ violations.length
37
+ end
38
+
39
+ def +(other)
40
+ return other if other.nil?
41
+
42
+ unless other.is_a?(ValidationReport)
43
+ raise ArgumentError, "cannot combine ValidationReport with #{other.class}"
44
+ end
45
+
46
+ ValidationReport.new(violations + other.violations)
47
+ end
48
+
49
+ def ==(other)
50
+ other.is_a?(ValidationReport) && violations == other.violations
51
+ end
52
+ alias eql? ==
53
+
54
+ def hash
55
+ violations.hash
56
+ end
57
+
58
+ def to_s
59
+ "#{size} violation(s): #{errors.length} error(s), #{warnings.length} warning(s)"
60
+ end
61
+ end
62
+ end
63
+ end
@@ -19,11 +19,14 @@ module Chemicalml
19
19
  autoload :Base, "chemicalml/convention/base"
20
20
  autoload :Compchem, "chemicalml/convention/compchem"
21
21
  autoload :Constraint, "chemicalml/convention/constraint"
22
+ autoload :Coordinator, "chemicalml/convention/coordinator"
23
+ autoload :Detection, "chemicalml/convention/detection"
22
24
  autoload :Dictionary, "chemicalml/convention/dictionary"
23
25
  autoload :Molecular, "chemicalml/convention/molecular"
24
26
  autoload :Registry, "chemicalml/convention/registry"
25
27
  autoload :UnitDictionary, "chemicalml/convention/unit_dictionary"
26
28
  autoload :UnitTypeDictionary, "chemicalml/convention/unit_type_dictionary"
29
+ autoload :ValidationReport, "chemicalml/convention/validation_report"
27
30
  autoload :Violation, "chemicalml/convention/violation"
28
31
 
29
32
  CONVENTION_NAMESPACE = "http://www.xml-cml.org/convention/".freeze
@@ -35,5 +38,13 @@ module Chemicalml
35
38
  def self.validate(document, qname:)
36
39
  Registry.validate(document, qname: qname)
37
40
  end
41
+
42
+ def self.validate_report(document, qname:)
43
+ Registry.validate_report(document, qname: qname)
44
+ end
45
+
46
+ def self.detect_and_validate(document)
47
+ Registry.detect_and_validate(document)
48
+ end
38
49
  end
39
50
  end
@@ -6,7 +6,7 @@ module Chemicalml
6
6
  # The YAML shape mirrors the structure documented in
7
7
  # `TODO.cml-full/05-dictionary-layer.md`.
8
8
  class Entry
9
- ID_PATTERN = /\A[A-Za-z][A-Za-z0-9._-]*\z/.freeze
9
+ ID_PATTERN = /\A[A-Za-z][A-Za-z0-9._-]*\z/
10
10
 
11
11
  attr_reader :id, :term, :definition, :description,
12
12
  :data_type, :unit_type, :units,
@@ -30,7 +30,7 @@ module Chemicalml
30
30
  freeze
31
31
  end
32
32
 
33
- def to_h
33
+ def value_attributes
34
34
  h = {
35
35
  id: id,
36
36
  term: term,
@@ -40,19 +40,19 @@ module Chemicalml
40
40
  h[:data_type] = data_type if data_type
41
41
  h[:unit_type] = unit_type if unit_type
42
42
  h[:units] = units if units
43
- h[:enum] = enum.to_h if enum
44
- h[:links] = links.map(&:to_h) unless links.empty?
43
+ h[:enum] = enum.value_attributes if enum
44
+ h[:links] = links.map(&:value_attributes) unless links.empty?
45
45
  h[:source_code] = source_code if source_code
46
46
  h
47
47
  end
48
48
 
49
49
  def eql?(other)
50
- other.is_a?(Entry) && id == other.id && to_h == other.to_h
50
+ other.is_a?(Entry) && id == other.id && value_attributes == other.value_attributes
51
51
  end
52
52
  alias == eql?
53
53
 
54
54
  def hash
55
- [id, to_h].hash
55
+ [id, value_attributes].hash
56
56
  end
57
57
  end
58
58
  end
@@ -34,7 +34,7 @@ module Chemicalml
34
34
  values.include?(value)
35
35
  end
36
36
 
37
- def to_h
37
+ def value_attributes
38
38
  { kind: kind, values: values }
39
39
  end
40
40
 
@@ -15,17 +15,17 @@ module Chemicalml
15
15
  freeze
16
16
  end
17
17
 
18
- def to_h
18
+ def value_attributes
19
19
  { rel: rel, href: href, title: title }.compact
20
20
  end
21
21
 
22
22
  def eql?(other)
23
- other.is_a?(Link) && to_h == other.to_h
23
+ other.is_a?(Link) && value_attributes == other.value_attributes
24
24
  end
25
25
  alias == eql?
26
26
 
27
27
  def hash
28
- to_h.hash
28
+ value_attributes.hash
29
29
  end
30
30
  end
31
31
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "yaml"
3
+ require 'yaml'
4
4
 
5
5
  module Chemicalml
6
6
  module Dictionary
@@ -17,26 +17,26 @@ module Chemicalml
17
17
 
18
18
  def self.from_hash(hash)
19
19
  Model.new(
20
- namespace: hash.fetch("namespace"),
21
- prefix: hash.fetch("prefix"),
22
- title: hash.fetch("title"),
23
- description: hash["description"],
24
- entries: (hash["entries"] || []).map { |e| build_entry(e) }
20
+ namespace: hash.fetch('namespace'),
21
+ prefix: hash.fetch('prefix'),
22
+ title: hash.fetch('title'),
23
+ description: hash['description'],
24
+ entries: (hash['entries'] || []).map { |e| build_entry(e) }
25
25
  )
26
26
  end
27
27
 
28
28
  def self.build_entry(h)
29
29
  Entry.new(
30
- id: h.fetch("id"),
31
- term: h.fetch("term"),
32
- definition: h.fetch("definition"),
33
- description: h["description"],
34
- data_type: h["data_type"],
35
- unit_type: h["unit_type"],
36
- units: h["units"],
37
- enum: build_enum(h["enum"]),
38
- links: (h["links"] || []).map { |l| build_link(l) },
39
- source_code: h["source_code"]
30
+ id: h.fetch('id'),
31
+ term: h.fetch('term'),
32
+ definition: h.fetch('definition'),
33
+ description: h['description'],
34
+ data_type: h['data_type'],
35
+ unit_type: h['unit_type'],
36
+ units: h['units'],
37
+ enum: build_enum(h['enum']),
38
+ links: (h['links'] || []).map { |l| build_link(l) },
39
+ source_code: h['source_code']
40
40
  )
41
41
  end
42
42
  private_class_method :build_entry
@@ -45,14 +45,14 @@ module Chemicalml
45
45
  return nil unless h
46
46
 
47
47
  Enum.new(
48
- kind: h["kind"] || :open,
49
- values: h["values"] || []
48
+ kind: h['kind'] || :open,
49
+ values: h['values'] || []
50
50
  )
51
51
  end
52
52
  private_class_method :build_enum
53
53
 
54
54
  def self.build_link(h)
55
- Link.new(rel: h.fetch("rel"), href: h.fetch("href"), title: h["title"])
55
+ Link.new(rel: h.fetch('rel'), href: h.fetch('href'), title: h['title'])
56
56
  end
57
57
  private_class_method :build_link
58
58
  end
@@ -35,29 +35,29 @@ module Chemicalml
35
35
  entries.map(&:id)
36
36
  end
37
37
 
38
- def to_h
38
+ def value_attributes
39
39
  {
40
40
  namespace: namespace,
41
41
  prefix: prefix,
42
42
  title: title,
43
43
  description: description,
44
- entries: entries.map(&:to_h)
44
+ entries: entries.map(&:value_attributes)
45
45
  }
46
46
  end
47
47
 
48
48
  def eql?(other)
49
- other.is_a?(Model) && namespace == other.namespace && to_h == other.to_h
49
+ other.is_a?(Model) && namespace == other.namespace && value_attributes == other.value_attributes
50
50
  end
51
51
  alias == eql?
52
52
 
53
53
  def hash
54
- [namespace, to_h].hash
54
+ [namespace, value_attributes].hash
55
55
  end
56
56
 
57
57
  private
58
58
 
59
59
  def split_qname(qname)
60
- qname.to_s.split(":", 2)
60
+ qname.to_s.split(':', 2)
61
61
  end
62
62
  end
63
63
  end
@@ -13,7 +13,7 @@ module Chemicalml
13
13
  @mutex = Mutex.new
14
14
 
15
15
  def self.lookup(qname)
16
- prefix, id = qname.to_s.split(":", 2)
16
+ prefix, id = qname.to_s.split(':', 2)
17
17
  return nil unless id
18
18
 
19
19
  dict = load_by_prefix(prefix)
@@ -39,7 +39,7 @@ module Chemicalml
39
39
 
40
40
  def self.load_by_prefix(prefix)
41
41
  manifest.each do |name, info|
42
- return load_builtin(name) if info["prefix"] == prefix
42
+ return load_builtin(name) if info['prefix'] == prefix
43
43
  end
44
44
  nil
45
45
  end
@@ -49,27 +49,27 @@ module Chemicalml
49
49
  end
50
50
 
51
51
  def self.builtin_names
52
- Dir.glob(File.join(BUILTIN_DIR, "*.yaml"))
53
- .reject { |p| File.basename(p).start_with?("_") }
54
- .map { |p| File.basename(p, ".yaml").to_sym }
52
+ Dir.glob(File.join(BUILTIN_DIR, '*.yaml'))
53
+ .reject { |p| File.basename(p).start_with?('_') }
54
+ .map { |p| File.basename(p, '.yaml').to_sym }
55
55
  .sort
56
56
  end
57
57
 
58
58
  def self.manifest
59
59
  @manifest ||= begin
60
- path = File.join(BUILTIN_DIR, "_index.yaml")
60
+ path = File.join(BUILTIN_DIR, '_index.yaml')
61
61
  if File.exist?(path)
62
62
  YAML.load_file(path) || {}
63
63
  else
64
- builtin_names.each_with_object({}) do |name, h|
65
- h[name.to_s] = { "prefix" => name.to_s }
64
+ builtin_names.to_h do |name|
65
+ [name.to_s, { 'prefix' => name.to_s }]
66
66
  end
67
67
  end
68
68
  end
69
69
  end
70
70
  private_class_method :manifest
71
71
 
72
- require "yaml"
72
+ require 'yaml'
73
73
  end
74
74
  end
75
75
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Chemicalml
4
- VERSION = "0.2.0"
4
+ VERSION = "0.2.1"
5
5
  end
@@ -9,6 +9,24 @@ module Chemicalml
9
9
  # (Document), `<module>` (compchem Module), `<dictionary>`,
10
10
  # `<unitList>`, `<unitTypeList>`, and the legacy standalone roots
11
11
  # `<molecule>`, `<reaction>`, `<reactionList>`.
12
+ #
13
+ # ---
14
+ #
15
+ # XML processing boundary (read me):
16
+ #
17
+ # The gem uses `lutaml-model` for ALL XML parsing and serialization
18
+ # — 242 wire classes extend `Lutaml::Model::Serializable`, and no
19
+ # `lib/` file defines `to_xml`/`from_xml`/`to_h`/`from_h` on a
20
+ # model class. Zero Nokogiri/REXML references in `lib/`.
21
+ #
22
+ # This file has TWO pre-processing helpers — `root_element_of` and
23
+ # `inject_namespace` — that operate on the XML *string* before
24
+ # `Lutaml::Model::Serializable.from_xml` is called. They are NOT
25
+ # serialization: they don't construct XML nodes, don't traverse
26
+ # trees, don't map attributes to model fields. They are input
27
+ # normalization so callers can pass namespace-less XML or rely on
28
+ # the parser to dispatch by root element name. The actual parse
29
+ # happens on the `const_get(class_name).from_xml(...)` call below.
12
30
  module VersionedParser
13
31
  # Maps root element name → constant name on the schema module.
14
32
  # Adding a new root type = adding one entry here. OCP — no
data/lib/chemicalml.rb CHANGED
@@ -7,7 +7,7 @@ require "lutaml/model"
7
7
  #
8
8
  # Top-level entry points:
9
9
  # Chemicalml::Cml::Document.from_xml(xml) # parse CML
10
- # document.to_xml # serialize back to XML
10
+ # document.to_xml # serialize back to XML
11
11
  #
12
12
  # Each CML element is a Lutaml::Model::Serializable subclass with
13
13
  # declared attributes and an XML mapping block. Serialization is
@@ -18,7 +18,6 @@ module Chemicalml
18
18
  autoload :Convention, "chemicalml/convention"
19
19
  autoload :Dictionary, "chemicalml/dictionary"
20
20
  autoload :Error, "chemicalml/errors"
21
- autoload :Model, "chemicalml/model"
22
21
  autoload :ParseError, "chemicalml/errors"
23
22
  autoload :Schema, "chemicalml/schema"
24
23
  autoload :VERSION, "chemicalml/version"