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
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Convention
5
+ module Compchem
6
+ module Constraints
7
+ # Co-constraint: if a calculation module is present inside a
8
+ # job, a finalization MUST also be present.
9
+ class CalculationRequiresFinalization < Chemicalml::Convention::Constraint::NodeConstraint
10
+ self.description = 'Co-constraint: if a calculation module is present inside a job, a finalization MUST also be present.'
11
+ applies_to Chemicalml::Cml::Role::Module
12
+ include ModulePredicates
13
+
14
+ def check_node(node, path)
15
+ calculations = child_modules_with(node, 'compchem:calculation')
16
+ finalizations = child_modules_with(node, 'compchem:finalization')
17
+ return [] if calculations.empty?
18
+ return [] unless finalizations.empty?
19
+
20
+ [violation(path: path.join('/'),
21
+ message: 'job module has a calculation but no finalization ' \
22
+ '(finalization MUST be present when calculation is)')]
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -7,20 +7,21 @@ module Chemicalml
7
7
  # A CompChem module MUST contain at least one jobList module
8
8
  # child per the compchem convention.
9
9
  class CompchemModuleMustContainJobList < Chemicalml::Convention::Constraint::NodeConstraint
10
+ self.description = 'A CompChem module MUST contain at least one jobList module child per the compchem convention.'
10
11
  def check_node(node, path)
11
12
  return [] unless compchem_root?(node)
12
13
 
13
- job_lists = node.modules.select { |m| m.dict_ref == "compchem:jobList" }
14
+ job_lists = (node.modules || []).select { |m| m.dict_ref == 'compchem:jobList' }
14
15
  return [] unless job_lists.empty?
15
16
 
16
- [violation(path: path.join("/"),
17
- message: "compchem module must contain at least one jobList module")]
17
+ [violation(path: path.join('/'),
18
+ message: 'compchem module must contain at least one jobList module')]
18
19
  end
19
20
 
20
21
  private
21
22
 
22
23
  def compchem_root?(node)
23
- module?(node) && node.convention == "convention:compchem"
24
+ module?(node) && node.convention == 'convention:compchem'
24
25
  end
25
26
 
26
27
  def module?(node)
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Convention
5
+ module Compchem
6
+ module Constraints
7
+ # The environment module MUST NOT contain more than one
8
+ # propertyList child.
9
+ class EnvironmentAtMostOnePropertyList < Chemicalml::Convention::Constraint::NodeConstraint
10
+ self.description = 'The environment module MUST NOT contain more than one propertyList child.'
11
+ applies_to Chemicalml::Cml::Role::Module
12
+ include ModulePredicates
13
+
14
+ def check_node(node, path)
15
+ lists = node.property_lists || []
16
+ return [] if lists.length <= 1
17
+
18
+ [violation(path: path.join('/'),
19
+ message: 'environment module must not contain more than ' \
20
+ "one propertyList (found #{lists.length})")]
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Convention
5
+ module Compchem
6
+ module Constraints
7
+ # The environment module MUST NOT contain parameter or
8
+ # parameterList children directly. It MAY contain a
9
+ # propertyList (which itself can hold parameters).
10
+ class EnvironmentMustNotContainParameter < Chemicalml::Convention::Constraint::NodeConstraint
11
+ self.description = 'The environment module MUST NOT contain parameter or parameterList children directly. It MAY contain a propertyList (which itself can hold parameters).'
12
+ applies_to Chemicalml::Cml::Role::Module
13
+ include ModulePredicates
14
+
15
+ def check_node(node, path)
16
+ violations = []
17
+ unless (node.parameter_lists || []).empty?
18
+ violations << violation(path: path.join('/'),
19
+ message: 'environment module must not contain parameterList children ' \
20
+ '(use propertyList instead)')
21
+ end
22
+ violations
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Convention
5
+ module Compchem
6
+ module Constraints
7
+ # The finalization module MUST NOT contain more than one
8
+ # molecule child.
9
+ class FinalizationAtMostOneMolecule < Chemicalml::Convention::Constraint::NodeConstraint
10
+ self.description = 'The finalization module MUST NOT contain more than one molecule child.'
11
+ applies_to Chemicalml::Cml::Role::Module
12
+ include ModulePredicates
13
+
14
+ def check_node(node, path)
15
+ molecules = node.molecules || []
16
+ return [] if molecules.length <= 1
17
+
18
+ [violation(path: path.join('/'),
19
+ message: 'finalization module must not contain more than ' \
20
+ "one molecule (found #{molecules.length})")]
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Convention
5
+ module Compchem
6
+ module Constraints
7
+ # The finalization module MUST NOT contain more than one
8
+ # propertyList child.
9
+ class FinalizationAtMostOnePropertyList < Chemicalml::Convention::Constraint::NodeConstraint
10
+ self.description = 'The finalization module MUST NOT contain more than one propertyList child.'
11
+ applies_to Chemicalml::Cml::Role::Module
12
+ include ModulePredicates
13
+
14
+ def check_node(node, path)
15
+ lists = node.property_lists || []
16
+ return [] if lists.length <= 1
17
+
18
+ [violation(path: path.join('/'),
19
+ message: 'finalization module must not contain more than ' \
20
+ "one propertyList (found #{lists.length})")]
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Convention
5
+ module Compchem
6
+ module Constraints
7
+ # A `finalization` module MUST contain at least one of:
8
+ # `molecule`, `propertyList`, or a user-defined module child.
9
+ # Per the compchem convention spec.
10
+ class FinalizationMustHaveContent < Chemicalml::Convention::Constraint::NodeConstraint
11
+ self.description = 'A `finalization` module MUST contain at least one of: `molecule`, `propertyList`, or a user-defined module child. Per the compchem convention spec.'
12
+ applies_to Chemicalml::Cml::Role::Module
13
+
14
+ def check_node(node, path)
15
+ return [] unless node.dict_ref == 'compchem:finalization'
16
+
17
+ has_molecule = (node.molecules || []).any?
18
+ has_prop_list = (node.property_lists || []).any?
19
+ has_user_module = user_module_count(node).positive?
20
+ return [] if has_molecule || has_prop_list || has_user_module
21
+
22
+ [violation(path: path.join('/'),
23
+ message: 'finalization module must contain at least one of: ' \
24
+ 'molecule, propertyList, or user-defined module')]
25
+ end
26
+
27
+ private
28
+
29
+ COMPCHEM_ROLES = %w[
30
+ compchem:jobList compchem:job compchem:initialization
31
+ compchem:calculation compchem:finalization compchem:environment
32
+ ].freeze
33
+
34
+ def user_module_count(node)
35
+ (node.modules || []).count do |m|
36
+ dr = m.dict_ref.to_s
37
+ !dr.empty? && !COMPCHEM_ROLES.include?(dr)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Convention
5
+ module Compchem
6
+ module Constraints
7
+ # The finalization module MUST NOT contain parameter or
8
+ # parameterList children directly. (Parameters belong in
9
+ # initialization.)
10
+ class FinalizationMustNotContainParameter < Chemicalml::Convention::Constraint::NodeConstraint
11
+ self.description = 'The finalization module MUST NOT contain parameter or parameterList children directly. (Parameters belong in initialization.)'
12
+ applies_to Chemicalml::Cml::Role::Module
13
+ include ModulePredicates
14
+
15
+ def check_node(node, path)
16
+ violations = []
17
+ unless (node.parameter_lists || []).empty?
18
+ violations << violation(path: path.join('/'),
19
+ message: 'finalization module must not contain parameterList children')
20
+ end
21
+ violations
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Convention
5
+ module Compchem
6
+ module Constraints
7
+ # The initialization module MUST NOT contain more than one
8
+ # molecule child.
9
+ class InitializationAtMostOneMolecule < Chemicalml::Convention::Constraint::NodeConstraint
10
+ self.description = 'The initialization module MUST NOT contain more than one molecule child.'
11
+ applies_to Chemicalml::Cml::Role::Module
12
+ include ModulePredicates
13
+
14
+ def check_node(node, path)
15
+ molecules = node.molecules || []
16
+ return [] if molecules.length <= 1
17
+
18
+ [violation(path: path.join('/'),
19
+ message: 'initialization module must not contain more than ' \
20
+ "one molecule (found #{molecules.length})")]
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Convention
5
+ module Compchem
6
+ module Constraints
7
+ # The initialization module MUST NOT contain more than one
8
+ # parameterList child.
9
+ class InitializationAtMostOneParameterList < Chemicalml::Convention::Constraint::NodeConstraint
10
+ self.description = 'The initialization module MUST NOT contain more than one parameterList child.'
11
+ applies_to Chemicalml::Cml::Role::Module
12
+ include ModulePredicates
13
+
14
+ def check_node(node, path)
15
+ lists = node.parameter_lists || []
16
+ return [] if lists.length <= 1
17
+
18
+ [violation(path: path.join('/'),
19
+ message: 'initialization module must not contain more than ' \
20
+ "one parameterList (found #{lists.length})")]
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Convention
5
+ module Compchem
6
+ module Constraints
7
+ # An `initialization` module MUST contain at least one of:
8
+ # `molecule`, `parameterList`, or a user-defined module child.
9
+ # Per the compchem convention spec.
10
+ class InitializationMustHaveContent < Chemicalml::Convention::Constraint::NodeConstraint
11
+ self.description = 'An `initialization` module MUST contain at least one of: `molecule`, `parameterList`, or a user-defined module child. Per the compchem convention spec.'
12
+ applies_to Chemicalml::Cml::Role::Module
13
+
14
+ def check_node(node, path)
15
+ return [] unless node.dict_ref == 'compchem:initialization'
16
+
17
+ has_molecule = molecule_count(node).positive?
18
+ has_param_list = parameter_list_count(node).positive?
19
+ has_user_module = user_module_count(node).positive?
20
+ return [] if has_molecule || has_param_list || has_user_module
21
+
22
+ [violation(path: path.join('/'),
23
+ message: 'initialization module must contain at least one of: ' \
24
+ 'molecule, parameterList, or user-defined module')]
25
+ end
26
+
27
+ private
28
+
29
+ def molecule_count(node)
30
+ (node.molecules || []).size
31
+ end
32
+
33
+ def parameter_list_count(node)
34
+ (node.parameter_lists || []).size
35
+ end
36
+
37
+ # User-defined modules: any module child whose dict_ref is
38
+ # not one of the compchem-defined roles.
39
+ COMPCHEM_ROLES = %w[
40
+ compchem:jobList compchem:job compchem:initialization
41
+ compchem:calculation compchem:finalization compchem:environment
42
+ ].freeze
43
+
44
+ def user_module_count(node)
45
+ (node.modules || []).count do |m|
46
+ dr = m.dict_ref.to_s
47
+ !dr.empty? && !COMPCHEM_ROLES.include?(dr)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Convention
5
+ module Compchem
6
+ module Constraints
7
+ # The initialization module MUST NOT contain property or
8
+ # propertyList children directly. (Properties belong in
9
+ # finalization.)
10
+ class InitializationMustNotContainProperty < Chemicalml::Convention::Constraint::NodeConstraint
11
+ self.description = 'The initialization module MUST NOT contain property or propertyList children directly. (Properties belong in finalization.)'
12
+ applies_to Chemicalml::Cml::Role::Module
13
+ include ModulePredicates
14
+
15
+ def check_node(node, path)
16
+ violations = []
17
+ unless (node.property_lists || []).empty?
18
+ violations << violation(path: path.join('/'),
19
+ message: 'initialization module must not contain propertyList children ' \
20
+ '(properties belong in finalization)')
21
+ end
22
+ violations
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Convention
5
+ module Compchem
6
+ module Constraints
7
+ # A jobList module MUST have an `id` unique within the
8
+ # compchem module.
9
+ class JobListModuleMustHaveId < Chemicalml::Convention::Constraint::NodeConstraint
10
+ self.description = 'A jobList module MUST have an `id` unique within the compchem module.'
11
+ applies_to Chemicalml::Cml::Role::Module
12
+ include ModulePredicates
13
+
14
+ def check_node(node, path)
15
+ return [] unless node.dict_ref == 'compchem:jobList'
16
+ return [] unless node.id.to_s.empty?
17
+
18
+ [violation(path: path.join('/'),
19
+ message: 'jobList module must have an id unique within the compchem module')]
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Convention
5
+ module Compchem
6
+ module Constraints
7
+ # A job module MUST contain at most one environment module.
8
+ class JobModuleAtMostOneEnvironment < Chemicalml::Convention::Constraint::NodeConstraint
9
+ self.description = 'A job module MUST contain at most one environment module.'
10
+ applies_to Chemicalml::Cml::Role::Module
11
+ include ModulePredicates
12
+
13
+ def check_node(node, path)
14
+ environments = child_modules_with(node, 'compchem:environment')
15
+ return [] if environments.length <= 1
16
+
17
+ [violation(path: path.join('/'),
18
+ message: 'job module must contain at most one environment ' \
19
+ "(found #{environments.length})")]
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Convention
5
+ module Compchem
6
+ module Constraints
7
+ # A job module MUST contain at most one finalization module.
8
+ class JobModuleAtMostOneFinalization < Chemicalml::Convention::Constraint::NodeConstraint
9
+ self.description = 'A job module MUST contain at most one finalization module.'
10
+ applies_to Chemicalml::Cml::Role::Module
11
+ include ModulePredicates
12
+
13
+ def check_node(node, path)
14
+ finalizations = child_modules_with(node, 'compchem:finalization')
15
+ return [] if finalizations.length <= 1
16
+
17
+ [violation(path: path.join('/'),
18
+ message: 'job module must contain at most one finalization ' \
19
+ "(found #{finalizations.length})")]
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Convention
5
+ module Compchem
6
+ module Constraints
7
+ # A job module MUST have an `id` unique within the compchem
8
+ # module.
9
+ class JobModuleMustHaveId < Chemicalml::Convention::Constraint::NodeConstraint
10
+ self.description = 'A job module MUST have an `id` unique within the compchem module.'
11
+ applies_to Chemicalml::Cml::Role::Module
12
+ include ModulePredicates
13
+
14
+ def check_node(node, path)
15
+ return [] unless node.dict_ref == 'compchem:job'
16
+ return [] unless node.id.to_s.empty?
17
+
18
+ [violation(path: path.join('/'),
19
+ message: 'job module must have an id unique within the compchem module')]
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -7,29 +7,27 @@ module Chemicalml
7
7
  # A job module MUST contain exactly one initialization module
8
8
  # child per the compchem convention.
9
9
  class JobMustContainInitialization < Chemicalml::Convention::Constraint::NodeConstraint
10
+ self.description = 'A job module MUST contain exactly one initialization module child per the compchem convention.'
11
+ applies_to Chemicalml::Cml::Role::Module
10
12
  def check_node(node, path)
11
- return [] unless job_module?(node)
13
+ return [] unless node.dict_ref == 'compchem:job'
12
14
 
13
15
  modules = node.modules || []
14
- inits = modules.select { |m| m.dict_ref == "compchem:initialization" }
16
+ inits = modules.select { |m| m.dict_ref == 'compchem:initialization' }
15
17
  return [] if inits.length == 1
16
18
 
17
19
  message = if inits.empty?
18
- "job module must contain exactly one initialization module (found 0)"
20
+ 'job module must contain exactly one initialization module (found 0)'
19
21
  else
20
22
  "job module must contain exactly one initialization module (found #{inits.length})"
21
23
  end
22
- [violation(path: path.join("/"), message: message)]
24
+ [violation(path: path.join('/'), message: message)]
23
25
  end
24
26
 
25
27
  private
26
28
 
27
29
  def job_module?(node)
28
- module?(node) && node.dict_ref == "compchem:job"
29
- end
30
-
31
- def module?(node)
32
- node.is_a?(Chemicalml::Cml::Role::Module)
30
+ node.is_a?(Chemicalml::Cml::Role::Module) && node.dict_ref == 'compchem:job'
33
31
  end
34
32
  end
35
33
  end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Convention
5
+ module Compchem
6
+ module Constraints
7
+ # CompChem `matrix` value-container rules: MUST have `rows`
8
+ # and `columns` attributes (each ≥ 1); `dataType` MUST be
9
+ # integer or double; MUST have `units`.
10
+ class MatrixRules < Chemicalml::Convention::Constraint::NodeConstraint
11
+ self.description = 'CompChem `matrix` value-container rules: MUST have `rows` and `columns` attributes (each ≥ 1); `dataType` MUST be integer or double; MUST have `units`.'
12
+ applies_to Chemicalml::Cml::Role::Matrix
13
+ include ModulePredicates
14
+
15
+ ALLOWED_TYPES = %w[xsd:integer xsd:double].freeze
16
+
17
+ def check_node(node, path)
18
+ violations = []
19
+ if node.rows.to_s.empty? || node.rows.to_i < 1
20
+ violations << violation(path: path.join('/'),
21
+ message: 'matrix must have a rows attribute (minimum 1)')
22
+ end
23
+ if node.columns.to_s.empty? || node.columns.to_i < 1
24
+ violations << violation(path: path.join('/'),
25
+ message: 'matrix must have a columns attribute (minimum 1)')
26
+ end
27
+ unless ALLOWED_TYPES.include?(node.data_type.to_s)
28
+ violations << violation(path: path.join('/'),
29
+ message: 'matrix dataType must be xsd:integer or xsd:double ' \
30
+ "(got #{node.data_type.inspect})")
31
+ end
32
+ if node.units.to_s.empty?
33
+ violations << violation(path: path.join('/'),
34
+ message: 'matrix must have units (even if dimensionless)')
35
+ end
36
+ violations
37
+ end
38
+
39
+ private
40
+
41
+ def matrix?(node)
42
+ node.is_a?(Chemicalml::Cml::Role::Matrix)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Convention
5
+ module Compchem
6
+ module Constraints
7
+ # Internal: helpers shared by every compchem constraint. Mixed
8
+ # into each constraint class so the role + dictRef checks
9
+ # live in one place (DRY).
10
+ module ModulePredicates
11
+ def cml_module?(node)
12
+ node.is_a?(Chemicalml::Cml::Role::Module)
13
+ end
14
+
15
+ def compchem_root?(node)
16
+ cml_module?(node) && node.convention == 'convention:compchem'
17
+ end
18
+
19
+ def job_list_module?(node)
20
+ cml_module?(node) && node.dict_ref == 'compchem:jobList'
21
+ end
22
+
23
+ def job_module?(node)
24
+ cml_module?(node) && node.dict_ref == 'compchem:job'
25
+ end
26
+
27
+ def initialization_module?(node)
28
+ cml_module?(node) && node.dict_ref == 'compchem:initialization'
29
+ end
30
+
31
+ def calculation_module?(node)
32
+ cml_module?(node) && node.dict_ref == 'compchem:calculation'
33
+ end
34
+
35
+ def finalization_module?(node)
36
+ cml_module?(node) && node.dict_ref == 'compchem:finalization'
37
+ end
38
+
39
+ def environment_module?(node)
40
+ cml_module?(node) && node.dict_ref == 'compchem:environment'
41
+ end
42
+
43
+ def child_modules_with(node, dict_ref)
44
+ (node.modules || []).select { |m| m.dict_ref == dict_ref }
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chemicalml
4
+ module Convention
5
+ module Compchem
6
+ module Constraints
7
+ # CompChem value-container rules: `scalar` with dataType
8
+ # `xsd:integer` or `xsd:double` MUST have `units`; `scalar`
9
+ # with dataType `xsd:string` MUST NOT have `units`.
10
+ class ScalarUnits < Chemicalml::Convention::Constraint::NodeConstraint
11
+ self.description = 'CompChem value-container rules: `scalar` with dataType `xsd:integer` or `xsd:double` MUST have `units`; `scalar` with dataType `xsd:string` MUST NOT have `units`.'
12
+ applies_to Chemicalml::Cml::Role::Scalar
13
+ include ModulePredicates
14
+
15
+ NUMERIC_TYPES = %w[xsd:integer xsd:double].freeze
16
+
17
+ def check_node(node, path)
18
+ data_type = node.data_type.to_s
19
+ units = node.units.to_s
20
+ violations = []
21
+
22
+ if NUMERIC_TYPES.include?(data_type) && units.empty?
23
+ violations << violation(path: path.join('/'),
24
+ message: "scalar with dataType #{data_type.inspect} must have units")
25
+ end
26
+ if data_type == 'xsd:string' && !units.empty?
27
+ violations << violation(path: path.join('/'),
28
+ message: "scalar with dataType 'xsd:string' must not have units")
29
+ end
30
+ violations
31
+ end
32
+
33
+ private
34
+
35
+ def scalar?(node)
36
+ node.is_a?(Chemicalml::Cml::Role::Scalar)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end