chemicalml 0.2.1 → 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.
- checksums.yaml +4 -4
- data/.rubocop.yml +23 -0
- data/CLAUDE.md +49 -1
- data/README.adoc +154 -26
- data/TODO.align/61-parallel-array-attrs.md +54 -0
- data/TODO.align/62-per-element-attribute-gaps.md +49 -0
- data/TODO.align/63-universal-children-mixin.md +42 -0
- data/TODO.align/64-per-element-child-gaps.md +81 -0
- data/TODO.align/65-simple-unit-convention.md +40 -0
- data/TODO.align/66-schema24-legacy-children.md +32 -0
- data/TODO.align/67-final-verification.md +32 -0
- data/TODO.align/68-detection-coverage.md +33 -0
- data/TODO.align/69-json-yaml-roundtrip.md +27 -0
- data/TODO.align/70-iterative-walker.md +40 -0
- data/TODO.align/71-violation-value.md +25 -0
- data/TODO.align/72-close-child-gaps.md +66 -0
- data/TODO.align/73-schema24-parse-limitation.md +64 -0
- data/TODO.align/74-final-verification-round18.md +15 -0
- data/TODO.align/75-key-value-mappings.md +43 -0
- data/TODO.align/76-schema24-workaround.md +57 -0
- data/TODO.align/77-convention-coverage-matrix.md +31 -0
- data/TODO.align/78-fixture-audit.md +23 -0
- data/TODO.align/79-final-verification-round19.md +15 -0
- data/TODO.align/80-xsd-enum-constants.md +35 -0
- data/TODO.align/81-enum-validation-constraints.md +29 -0
- data/TODO.align/82-reference-resolver.md +33 -0
- data/TODO.align/83-toml-roundtrip.md +20 -0
- data/TODO.align/84-final-verification-round21.md +16 -0
- data/TODO.align/85-bond-distinct-atoms.md +25 -0
- data/TODO.align/86-references-should-resolve.md +20 -0
- data/TODO.align/87-cli-utility.md +26 -0
- data/TODO.align/88-diverse-fixtures.md +26 -0
- data/TODO.align/89-final-verification-round22.md +15 -0
- data/TODO.align/90-bond-stereo-completeness.md +31 -0
- data/TODO.align/91-atomparity-distinct.md +21 -0
- data/TODO.align/92-unit-dictionary-completeness.md +28 -0
- data/TODO.align/93-yard-docs.md +23 -0
- data/TODO.align/94-final-verification-round23.md +15 -0
- data/TODO.align/README.round17.md +28 -0
- data/TODO.align/README.round18.md +37 -0
- data/TODO.align/README.round19.md +40 -0
- data/TODO.align/README.round20.md +49 -0
- data/TODO.align/README.round21.md +35 -0
- data/TODO.align/README.round22.md +48 -0
- data/TODO.align/README.round23.md +46 -0
- data/TODO.align/README.round24.md +53 -0
- data/TODO.align/README.round25.md +66 -0
- data/TODO.align/README.round26.md +55 -0
- data/TODO.align/README.round27.md +51 -0
- data/TODO.align/README.round28.md +61 -0
- data/TODO.align/README.round29.md +64 -0
- data/TODO.align/README.round30.md +50 -0
- data/TODO.align/README.round31.md +54 -0
- data/TODO.align/README.round32.md +67 -0
- data/TODO.align/README.round33.md +62 -0
- data/TODO.align/README.round34.md +70 -0
- data/docs/constraints.md +161 -0
- data/docs/generate_constraint_docs.rb +44 -0
- data/exe/chemicalml +6 -0
- data/lib/chemicalml/cli/base.rb +68 -0
- data/lib/chemicalml/cli/command.rb +43 -0
- data/lib/chemicalml/cli/constraints_command.rb +27 -0
- data/lib/chemicalml/cli/conventions_command.rb +14 -0
- data/lib/chemicalml/cli/dictionaries_command.rb +14 -0
- data/lib/chemicalml/cli/elements_command.rb +17 -0
- data/lib/chemicalml/cli/enums_command.rb +17 -0
- data/lib/chemicalml/cli/info_command.rb +77 -0
- data/lib/chemicalml/cli/inspect_command.rb +39 -0
- data/lib/chemicalml/cli/validate_command.rb +54 -0
- data/lib/chemicalml/cli.rb +43 -0
- data/lib/chemicalml/cml/base/abundance.rb +18 -8
- data/lib/chemicalml/cml/base/action.rb +34 -16
- data/lib/chemicalml/cml/base/action_list.rb +35 -17
- data/lib/chemicalml/cml/base/alternative.rb +13 -4
- data/lib/chemicalml/cml/base/amount.rb +14 -6
- data/lib/chemicalml/cml/base/angle.rb +28 -13
- data/lib/chemicalml/cml/base/annotation.rb +14 -6
- data/lib/chemicalml/cml/base/any_cml.rb +12 -5
- data/lib/chemicalml/cml/base/appinfo.rb +14 -6
- data/lib/chemicalml/cml/base/arg.rb +47 -13
- data/lib/chemicalml/cml/base/array.rb +40 -19
- data/lib/chemicalml/cml/base/array_list.rb +14 -6
- data/lib/chemicalml/cml/base/atom.rb +84 -28
- data/lib/chemicalml/cml/base/atom_array.rb +60 -23
- data/lib/chemicalml/cml/base/atom_parity.rb +14 -6
- data/lib/chemicalml/cml/base/atom_set.rb +14 -6
- data/lib/chemicalml/cml/base/atom_type.rb +25 -9
- data/lib/chemicalml/cml/base/atom_type_list.rb +22 -8
- data/lib/chemicalml/cml/base/atomic_basis_function.rb +33 -13
- data/lib/chemicalml/cml/base/band.rb +21 -8
- data/lib/chemicalml/cml/base/band_list.rb +15 -7
- data/lib/chemicalml/cml/base/basis_set.rb +24 -9
- data/lib/chemicalml/cml/base/bond.rb +36 -10
- data/lib/chemicalml/cml/base/bond_array.rb +34 -11
- data/lib/chemicalml/cml/base/bond_set.rb +14 -6
- data/lib/chemicalml/cml/base/bond_stereo.rb +20 -9
- data/lib/chemicalml/cml/base/bond_type.rb +23 -8
- data/lib/chemicalml/cml/base/bond_type_list.rb +22 -8
- data/lib/chemicalml/cml/base/cell_parameter.rb +28 -10
- data/lib/chemicalml/cml/base/cml_module.rb +36 -11
- data/lib/chemicalml/cml/base/common_children.rb +35 -0
- data/lib/chemicalml/cml/base/complex_object.rb +12 -5
- data/lib/chemicalml/cml/base/condition_list.rb +26 -10
- data/lib/chemicalml/cml/base/crystal.rb +26 -10
- data/lib/chemicalml/cml/base/definition.rb +12 -5
- data/lib/chemicalml/cml/base/description.rb +14 -6
- data/lib/chemicalml/cml/base/dictionary.rb +27 -10
- data/lib/chemicalml/cml/base/dictionary_entry.rb +67 -8
- data/lib/chemicalml/cml/base/dimension.rb +26 -12
- data/lib/chemicalml/cml/base/document.rb +18 -8
- data/lib/chemicalml/cml/base/documentation.rb +12 -5
- data/lib/chemicalml/cml/base/eigen.rb +32 -8
- data/lib/chemicalml/cml/base/electron.rb +26 -12
- data/lib/chemicalml/cml/base/enumeration.rb +16 -7
- data/lib/chemicalml/cml/base/expression.rb +21 -6
- data/lib/chemicalml/cml/base/float.rb +22 -10
- data/lib/chemicalml/cml/base/float_array.rb +24 -11
- data/lib/chemicalml/cml/base/formula.rb +31 -10
- data/lib/chemicalml/cml/base/fragment.rb +30 -12
- data/lib/chemicalml/cml/base/fragment_list.rb +24 -9
- data/lib/chemicalml/cml/base/gradient.rb +19 -6
- data/lib/chemicalml/cml/base/identifier.rb +18 -8
- data/lib/chemicalml/cml/base/integer.rb +22 -10
- data/lib/chemicalml/cml/base/integer_array.rb +24 -11
- data/lib/chemicalml/cml/base/isotope.rb +28 -9
- data/lib/chemicalml/cml/base/isotope_list.rb +17 -8
- data/lib/chemicalml/cml/base/join.rb +25 -9
- data/lib/chemicalml/cml/base/kpoint.rb +16 -7
- data/lib/chemicalml/cml/base/kpoint_list.rb +15 -7
- data/lib/chemicalml/cml/base/label.rb +14 -6
- data/lib/chemicalml/cml/base/lattice.rb +35 -10
- data/lib/chemicalml/cml/base/lattice_vector.rb +16 -7
- data/lib/chemicalml/cml/base/length.rb +26 -12
- data/lib/chemicalml/cml/base/line3.rb +18 -8
- data/lib/chemicalml/cml/base/link.rb +41 -20
- data/lib/chemicalml/cml/base/list.rb +22 -10
- data/lib/chemicalml/cml/base/map.rb +32 -11
- data/lib/chemicalml/cml/base/matrix.rb +32 -15
- data/lib/chemicalml/cml/base/mechanism.rb +20 -7
- data/lib/chemicalml/cml/base/mechanism_component.rb +14 -6
- data/lib/chemicalml/cml/base/metadata.rb +18 -8
- data/lib/chemicalml/cml/base/metadata_list.rb +27 -8
- data/lib/chemicalml/cml/base/molecule.rb +90 -26
- data/lib/chemicalml/cml/base/molecule_list.rb +26 -8
- data/lib/chemicalml/cml/base/name.rb +10 -4
- data/lib/chemicalml/cml/base/object.rb +18 -8
- data/lib/chemicalml/cml/base/observation.rb +16 -7
- data/lib/chemicalml/cml/base/operator.rb +14 -6
- data/lib/chemicalml/cml/base/parameter.rb +33 -13
- data/lib/chemicalml/cml/base/parameter_list.rb +27 -8
- data/lib/chemicalml/cml/base/particle.rb +20 -9
- data/lib/chemicalml/cml/base/peak.rb +71 -26
- data/lib/chemicalml/cml/base/peak_group.rb +62 -26
- data/lib/chemicalml/cml/base/peak_list.rb +24 -9
- data/lib/chemicalml/cml/base/peak_structure.rb +40 -13
- data/lib/chemicalml/cml/base/plane3.rb +14 -6
- data/lib/chemicalml/cml/base/point3.rb +14 -6
- data/lib/chemicalml/cml/base/potential.rb +17 -6
- data/lib/chemicalml/cml/base/potential_form.rb +30 -7
- data/lib/chemicalml/cml/base/potential_list.rb +15 -7
- data/lib/chemicalml/cml/base/product.rb +45 -10
- data/lib/chemicalml/cml/base/product_list.rb +29 -9
- data/lib/chemicalml/cml/base/property.rb +29 -11
- data/lib/chemicalml/cml/base/property_list.rb +23 -8
- data/lib/chemicalml/cml/base/reactant.rb +45 -10
- data/lib/chemicalml/cml/base/reactant_list.rb +29 -9
- data/lib/chemicalml/cml/base/reaction.rb +74 -20
- data/lib/chemicalml/cml/base/reaction_list.rb +23 -8
- data/lib/chemicalml/cml/base/reaction_scheme.rb +43 -13
- data/lib/chemicalml/cml/base/reaction_step.rb +30 -12
- data/lib/chemicalml/cml/base/reaction_step_list.rb +30 -11
- data/lib/chemicalml/cml/base/reactive_centre.rb +31 -6
- data/lib/chemicalml/cml/base/region.rb +20 -9
- data/lib/chemicalml/cml/base/related_entry.rb +11 -3
- data/lib/chemicalml/cml/base/sample.rb +30 -7
- data/lib/chemicalml/cml/base/scalar.rb +32 -15
- data/lib/chemicalml/cml/base/spectator.rb +25 -6
- data/lib/chemicalml/cml/base/spectator_list.rb +20 -7
- data/lib/chemicalml/cml/base/spectrum.rb +57 -18
- data/lib/chemicalml/cml/base/spectrum_data.rb +19 -9
- data/lib/chemicalml/cml/base/spectrum_list.rb +28 -9
- data/lib/chemicalml/cml/base/sphere3.rb +14 -6
- data/lib/chemicalml/cml/base/stmml.rb +12 -5
- data/lib/chemicalml/cml/base/string.rb +14 -6
- data/lib/chemicalml/cml/base/string_array.rb +22 -10
- data/lib/chemicalml/cml/base/substance.rb +36 -14
- data/lib/chemicalml/cml/base/substance_list.rb +29 -10
- data/lib/chemicalml/cml/base/symmetry.rb +31 -9
- data/lib/chemicalml/cml/base/system.rb +21 -10
- data/lib/chemicalml/cml/base/table.rb +38 -13
- data/lib/chemicalml/cml/base/table_cell.rb +12 -5
- data/lib/chemicalml/cml/base/table_content.rb +19 -9
- data/lib/chemicalml/cml/base/table_header.rb +15 -7
- data/lib/chemicalml/cml/base/table_header_cell.rb +22 -10
- data/lib/chemicalml/cml/base/table_row.rb +15 -7
- data/lib/chemicalml/cml/base/table_row_list.rb +15 -7
- data/lib/chemicalml/cml/base/tcell.rb +16 -7
- data/lib/chemicalml/cml/base/torsion.rb +28 -13
- data/lib/chemicalml/cml/base/transform3.rb +12 -5
- data/lib/chemicalml/cml/base/transition_state.rb +23 -5
- data/lib/chemicalml/cml/base/trow.rb +22 -6
- data/lib/chemicalml/cml/base/unit.rb +39 -16
- data/lib/chemicalml/cml/base/unit_list.rb +34 -12
- data/lib/chemicalml/cml/base/unit_type.rb +27 -10
- data/lib/chemicalml/cml/base/unit_type_list.rb +29 -11
- data/lib/chemicalml/cml/base/vector3.rb +14 -6
- data/lib/chemicalml/cml/base/xaxis.rb +30 -10
- data/lib/chemicalml/cml/base/yaxis.rb +30 -10
- data/lib/chemicalml/cml/base/z_matrix.rb +26 -5
- data/lib/chemicalml/cml/base.rb +139 -138
- data/lib/chemicalml/cml/canonical_comparison.rb +54 -0
- data/lib/chemicalml/cml/elements.rb +145 -136
- data/lib/chemicalml/cml/enums.rb +55 -0
- data/lib/chemicalml/cml/namespace.rb +2 -3
- data/lib/chemicalml/cml/patterns.rb +33 -0
- data/lib/chemicalml/cml/reference_resolver.rb +137 -0
- data/lib/chemicalml/cml/role.rb +138 -138
- data/lib/chemicalml/cml/schema24/configuration.rb +11 -1
- data/lib/chemicalml/cml/schema24.rb +139 -139
- data/lib/chemicalml/cml/schema3.rb +123 -123
- data/lib/chemicalml/cml/visitable.rb +77 -3
- data/lib/chemicalml/cml/wire_class_registry.rb +3 -3
- data/lib/chemicalml/cml.rb +163 -129
- data/lib/chemicalml/context_configuration.rb +4 -2
- data/lib/chemicalml/convention/cascade/constraints/reaction_scheme_must_have_content.rb +33 -0
- data/lib/chemicalml/convention/cascade/constraints/reaction_step_list_must_contain_steps.rb +31 -0
- data/lib/chemicalml/convention/cascade/constraints/reaction_step_must_have_reaction_or_lists.rb +33 -0
- data/lib/chemicalml/convention/cascade/constraints/reactive_centre_atom_refs_should_be_present.rb +34 -0
- data/lib/chemicalml/convention/cascade/constraints.rb +18 -0
- data/lib/chemicalml/convention/cascade.rb +43 -0
- data/lib/chemicalml/convention/compchem/constraints/array_rules.rb +1 -1
- data/lib/chemicalml/convention/compchem/constraints/calculation_requires_finalization.rb +1 -1
- data/lib/chemicalml/convention/compchem/constraints/compchem_module_must_contain_job_list.rb +2 -1
- data/lib/chemicalml/convention/compchem/constraints/environment_at_most_one_property_list.rb +1 -1
- data/lib/chemicalml/convention/compchem/constraints/environment_must_not_contain_parameter.rb +1 -1
- data/lib/chemicalml/convention/compchem/constraints/finalization_at_most_one_molecule.rb +1 -1
- data/lib/chemicalml/convention/compchem/constraints/finalization_at_most_one_property_list.rb +1 -1
- data/lib/chemicalml/convention/compchem/constraints/finalization_must_have_content.rb +44 -0
- data/lib/chemicalml/convention/compchem/constraints/finalization_must_not_contain_parameter.rb +1 -1
- data/lib/chemicalml/convention/compchem/constraints/initialization_at_most_one_molecule.rb +1 -1
- data/lib/chemicalml/convention/compchem/constraints/initialization_at_most_one_parameter_list.rb +1 -1
- data/lib/chemicalml/convention/compchem/constraints/initialization_must_have_content.rb +54 -0
- data/lib/chemicalml/convention/compchem/constraints/initialization_must_not_contain_property.rb +1 -1
- data/lib/chemicalml/convention/compchem/constraints/job_list_module_must_have_id.rb +1 -0
- data/lib/chemicalml/convention/compchem/constraints/job_module_at_most_one_environment.rb +1 -1
- data/lib/chemicalml/convention/compchem/constraints/job_module_at_most_one_finalization.rb +1 -1
- data/lib/chemicalml/convention/compchem/constraints/job_module_must_have_id.rb +1 -0
- data/lib/chemicalml/convention/compchem/constraints/job_must_contain_initialization.rb +1 -0
- data/lib/chemicalml/convention/compchem/constraints/matrix_rules.rb +1 -1
- data/lib/chemicalml/convention/compchem/constraints/scalar_units.rb +1 -1
- data/lib/chemicalml/convention/compchem/constraints.rb +4 -0
- data/lib/chemicalml/convention/compchem.rb +4 -2
- data/lib/chemicalml/convention/constraint.rb +40 -9
- data/lib/chemicalml/convention/coordinator.rb +4 -3
- data/lib/chemicalml/convention/detection.rb +10 -4
- data/lib/chemicalml/convention/dictionary/constraints/dictionary_must_have_namespace.rb +1 -0
- data/lib/chemicalml/convention/dictionary/constraints/dictionary_namespace_should_end_with_slash_or_hash.rb +1 -1
- data/lib/chemicalml/convention/dictionary/constraints/entry_id_must_match_pattern.rb +1 -1
- data/lib/chemicalml/convention/dictionary/constraints/entry_ids_unique_within_dictionary.rb +1 -1
- data/lib/chemicalml/convention/dictionary/constraints/entry_must_contain_definition.rb +1 -0
- data/lib/chemicalml/convention/dictionary/constraints/entry_must_have_id_and_term.rb +1 -1
- data/lib/chemicalml/convention/dictionary/constraints/entry_must_have_unit_type.rb +1 -0
- data/lib/chemicalml/convention/dictionary/constraints/entry_units_co_constraints.rb +1 -1
- data/lib/chemicalml/convention/dictionary/constraints.rb +8 -8
- data/lib/chemicalml/convention/dictionary.rb +2 -2
- data/lib/chemicalml/convention/molecular/constraints/atom_array_must_be_child_of_molecule_or_formula.rb +1 -0
- data/lib/chemicalml/convention/molecular/constraints/atom_array_must_contain_atoms.rb +15 -6
- data/lib/chemicalml/convention/molecular/constraints/atom_coordinates_must_be_paired.rb +1 -1
- data/lib/chemicalml/convention/molecular/constraints/atom_element_type_should_be_in_periodic_table.rb +39 -0
- data/lib/chemicalml/convention/molecular/constraints/atom_id_must_match_pattern.rb +3 -2
- data/lib/chemicalml/convention/molecular/constraints/atom_ids_unique_within_molecule.rb +1 -0
- data/lib/chemicalml/convention/molecular/constraints/atom_must_have_element_type.rb +1 -1
- data/lib/chemicalml/convention/molecular/constraints/atom_must_have_id.rb +2 -1
- data/lib/chemicalml/convention/molecular/constraints/atom_parity_atom_refs4_should_be_distinct.rb +44 -0
- data/lib/chemicalml/convention/molecular/constraints/atom_parity_should_include_parent_atom.rb +65 -0
- data/lib/chemicalml/convention/molecular/constraints/bond_array_must_be_child_of_molecule.rb +1 -0
- data/lib/chemicalml/convention/molecular/constraints/bond_atom_refs2_should_be_distinct.rb +44 -0
- data/lib/chemicalml/convention/molecular/constraints/bond_id_should_match_pattern.rb +38 -0
- data/lib/chemicalml/convention/molecular/constraints/bond_ids_unique_within_molecule.rb +1 -0
- data/lib/chemicalml/convention/molecular/constraints/bond_must_have_atom_refs2.rb +1 -1
- data/lib/chemicalml/convention/molecular/constraints/bond_must_have_order.rb +2 -1
- data/lib/chemicalml/convention/molecular/constraints/bond_must_reference_atoms_in_same_molecule.rb +1 -0
- data/lib/chemicalml/convention/molecular/constraints/bond_order_other_must_have_dict_ref.rb +1 -0
- data/lib/chemicalml/convention/molecular/constraints/bond_order_should_be_in_enum.rb +39 -0
- data/lib/chemicalml/convention/molecular/constraints/bond_order_should_not_be_numeric.rb +1 -1
- data/lib/chemicalml/convention/molecular/constraints/bond_stereo_atom_refs4_should_be_distinct.rb +43 -0
- data/lib/chemicalml/convention/molecular/constraints/bond_stereo_cis_trans_must_have_atom_refs4.rb +1 -1
- data/lib/chemicalml/convention/molecular/constraints/bond_stereo_other_must_have_dict_ref.rb +1 -0
- data/lib/chemicalml/convention/molecular/constraints/bond_stereo_should_be_in_enum.rb +38 -0
- data/lib/chemicalml/convention/molecular/constraints/bond_stereo_wedge_hash_must_have_atom_refs2.rb +1 -1
- data/lib/chemicalml/convention/molecular/constraints/dict_ref_should_resolve.rb +59 -0
- data/lib/chemicalml/convention/molecular/constraints/molecule_atom_array_mutually_exclusive_with_children.rb +1 -0
- data/lib/chemicalml/convention/molecular/constraints/molecule_bond_array_mutually_exclusive_with_children.rb +1 -0
- data/lib/chemicalml/convention/molecular/constraints/molecule_chirality_should_be_in_enum.rb +38 -0
- data/lib/chemicalml/convention/molecular/constraints/molecule_count_must_not_appear_on_top_level.rb +1 -0
- data/lib/chemicalml/convention/molecular/constraints/molecule_id_should_match_pattern.rb +38 -0
- data/lib/chemicalml/convention/molecular/constraints/molecule_must_have_id.rb +1 -1
- data/lib/chemicalml/convention/molecular/constraints/property_must_have_dict_ref.rb +1 -1
- data/lib/chemicalml/convention/molecular/constraints/property_scalar_data_type_matches_dictionary.rb +58 -0
- data/lib/chemicalml/convention/molecular/constraints/references_should_resolve.rb +37 -0
- data/lib/chemicalml/convention/molecular/constraints/scalar_must_have_data_type.rb +1 -1
- data/lib/chemicalml/convention/molecular/constraints.rb +49 -23
- data/lib/chemicalml/convention/molecular.rb +15 -2
- data/lib/chemicalml/convention/registry.rb +79 -11
- data/lib/chemicalml/convention/simple_unit/constraints/root_must_be_unit_list.rb +24 -0
- data/lib/chemicalml/convention/simple_unit/constraints/unit_must_have_power.rb +32 -0
- data/lib/chemicalml/convention/simple_unit/constraints/unit_must_have_symbol.rb +31 -0
- data/lib/chemicalml/convention/simple_unit/constraints.rb +16 -0
- data/lib/chemicalml/convention/simple_unit.rb +37 -0
- data/lib/chemicalml/convention/spectroscopy/constraints/peak_list_must_contain_peaks.rb +31 -0
- data/lib/chemicalml/convention/spectroscopy/constraints/peak_should_have_values.rb +34 -0
- data/lib/chemicalml/convention/spectroscopy/constraints/spectrum_must_have_content.rb +31 -0
- data/lib/chemicalml/convention/spectroscopy/constraints/spectrum_must_have_convention.rb +32 -0
- data/lib/chemicalml/convention/spectroscopy/constraints/spectrum_must_have_format.rb +31 -0
- data/lib/chemicalml/convention/spectroscopy/constraints.rb +20 -0
- data/lib/chemicalml/convention/spectroscopy.rb +41 -0
- data/lib/chemicalml/convention/unit_dictionary/constraints/unit_list_must_contain_at_least_one_unit.rb +1 -0
- data/lib/chemicalml/convention/unit_dictionary/constraints/unit_list_must_have_namespace.rb +1 -1
- data/lib/chemicalml/convention/unit_dictionary/constraints/unit_must_contain_definition.rb +1 -0
- data/lib/chemicalml/convention/unit_dictionary/constraints/unit_must_have_id.rb +1 -0
- data/lib/chemicalml/convention/unit_dictionary/constraints/unit_must_have_multiplier_or_constant_to_si.rb +34 -0
- data/lib/chemicalml/convention/unit_dictionary/constraints/unit_must_have_parent_si.rb +32 -0
- data/lib/chemicalml/convention/unit_dictionary/constraints/unit_must_have_symbol_and_unit_type.rb +1 -1
- data/lib/chemicalml/convention/unit_dictionary/constraints/unit_must_have_title.rb +32 -0
- data/lib/chemicalml/convention/unit_dictionary/constraints/unit_parent_si_should_resolve.rb +45 -0
- data/lib/chemicalml/convention/unit_dictionary/constraints/unit_unit_type_should_resolve.rb +46 -0
- data/lib/chemicalml/convention/unit_dictionary/constraints.rb +10 -0
- data/lib/chemicalml/convention/unit_dictionary.rb +7 -2
- data/lib/chemicalml/convention/unit_type_dictionary/constraints/unit_type_id_must_match_pattern.rb +1 -1
- data/lib/chemicalml/convention/unit_type_dictionary/constraints/unit_type_list_must_contain_at_least_one_unit_type.rb +1 -0
- data/lib/chemicalml/convention/unit_type_dictionary/constraints/unit_type_list_must_have_namespace.rb +1 -1
- data/lib/chemicalml/convention/unit_type_dictionary/constraints/unit_type_must_contain_definition.rb +1 -0
- data/lib/chemicalml/convention/unit_type_dictionary/constraints/unit_type_must_have_id_and_name.rb +1 -1
- data/lib/chemicalml/convention/unit_type_dictionary.rb +2 -2
- data/lib/chemicalml/convention/validation_report.rb +30 -3
- data/lib/chemicalml/convention/violation.rb +9 -3
- data/lib/chemicalml/convention.rb +41 -14
- data/lib/chemicalml/dictionary.rb +13 -9
- data/lib/chemicalml/logger.rb +47 -0
- data/lib/chemicalml/schema/definition.rb +2 -2
- data/lib/chemicalml/schema.rb +7 -7
- data/lib/chemicalml/version.rb +1 -1
- data/lib/chemicalml/versioned_parser.rb +10 -10
- data/lib/chemicalml.rb +78 -15
- data/lib/tasks/reference_fetch.rake +30 -31
- data/lib/tasks/scrape_fixtures.rake +23 -24
- metadata +114 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ed7130181d6d55cbadb29d2630668ab4f16746f10dc20db9c9d1d0ff066586c6
|
|
4
|
+
data.tar.gz: ac78d79e906862aa42639b2d237ec66661a8c3061e4b25c04535f8941520b3d3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5909cc1b258048f0c5aefba5844fff9136f2db4713d5cd5b80a22c07045e60a5ee5ead34680a841a9044039824c76cd4913d48d8f3410f86bf99b043f5739ba4
|
|
7
|
+
data.tar.gz: ff4f54de5ce734ae649554f593cfc1affa766b7e541fef394704bcd1b4d192dbae3e788241ced6a4dc6306bacf62b409fad2fdafe6861617497d7ff2ced16dee
|
data/.rubocop.yml
CHANGED
|
@@ -10,11 +10,34 @@ AllCops:
|
|
|
10
10
|
- "coverage/**/*"
|
|
11
11
|
- "reference-docs/**/*"
|
|
12
12
|
- "spec/fixtures/**/*"
|
|
13
|
+
- "data/**/*"
|
|
13
14
|
|
|
14
15
|
Metrics/BlockLength:
|
|
15
16
|
Exclude:
|
|
16
17
|
- "spec/**/*"
|
|
17
18
|
- "*.gemspec"
|
|
19
|
+
- "lib/chemicalml/cml/base/**/*.rb"
|
|
20
|
+
|
|
21
|
+
# Base::* modules are structurally long: each declares every attribute
|
|
22
|
+
# and both xml + key_value mapping blocks for one CML element in a
|
|
23
|
+
# single `self.included` hook. This is the correct structure — the
|
|
24
|
+
# alternative (splitting into smaller methods) would scatter one
|
|
25
|
+
# element's declarations across multiple files.
|
|
26
|
+
Metrics/MethodLength:
|
|
27
|
+
Exclude:
|
|
28
|
+
- "lib/chemicalml/cml/base/**/*.rb"
|
|
29
|
+
|
|
30
|
+
Metrics/AbcSize:
|
|
31
|
+
Exclude:
|
|
32
|
+
- "lib/chemicalml/cml/base/**/*.rb"
|
|
33
|
+
|
|
34
|
+
Metrics/ModuleLength:
|
|
35
|
+
Exclude:
|
|
36
|
+
- "lib/chemicalml/cml/base/**/*.rb"
|
|
37
|
+
|
|
38
|
+
Layout/LineLength:
|
|
39
|
+
Exclude:
|
|
40
|
+
- "lib/chemicalml/cml/base/**/*.rb"
|
|
18
41
|
|
|
19
42
|
Style/Documentation:
|
|
20
43
|
Enabled: false
|
data/CLAUDE.md
CHANGED
|
@@ -26,6 +26,9 @@ bundle exec rspec -e "round-trips" # by name match
|
|
|
26
26
|
bundle exec rake # alias for rspec
|
|
27
27
|
bundle exec rubocop # lint
|
|
28
28
|
bundle exec rubocop -A # autocorrect
|
|
29
|
+
bundle exec chemicalml validate <file.cml> # CLI validation
|
|
30
|
+
bundle exec chemicalml conventions # list registered conventions
|
|
31
|
+
bundle exec chemicalml dictionaries # list built-in dictionaries
|
|
29
32
|
```
|
|
30
33
|
|
|
31
34
|
`spec/examples.txt` and `Gemfile.lock` are gitignored — `spec/examples.txt`
|
|
@@ -126,17 +129,35 @@ Schema 3's unified `scalar`/`array`/`table` machinery.
|
|
|
126
129
|
The framework handles (de)serialization; **never** add `def to_xml` /
|
|
127
130
|
`def from_xml` / `def to_h` to these classes.
|
|
128
131
|
|
|
132
|
+
### JSON / YAML wire names
|
|
133
|
+
|
|
134
|
+
Every `Base::*` module declares a `key_value do ... end` block
|
|
135
|
+
alongside its `xml do ... end` block, mirroring the XML wire names
|
|
136
|
+
explicitly. JSON and YAML output carry CML wire names
|
|
137
|
+
(`elementType`, `atomArray`) rather than Ruby snake_case names.
|
|
138
|
+
The blocks are written out by hand per Base module — no runtime
|
|
139
|
+
introspection.
|
|
140
|
+
|
|
129
141
|
### Schema versions
|
|
130
142
|
|
|
131
143
|
`Chemicalml::Schema::Registry` is the registry for schema versions
|
|
132
144
|
(`schema24`, `schema3`). The schema XSDs are **archival source** —
|
|
133
145
|
they must never be deleted, edited, or regenerated from code.
|
|
134
146
|
|
|
147
|
+
**Type-name collision**: Schema24's legacy `<string>`, `<integer>`,
|
|
148
|
+
`<float>` elements share their XML names with lutaml-model primitives
|
|
149
|
+
(`:string`, `:integer`, `:float`). They are NOT registered as types
|
|
150
|
+
in the Schema24 context (would shadow the primitive, breaking every
|
|
151
|
+
`:string` attribute cast). They remain defined as wire classes and
|
|
152
|
+
parseable as document roots. See
|
|
153
|
+
`Cml::Elements::SCHEMA24_TYPE_COLLISIONS`.
|
|
154
|
+
|
|
135
155
|
### Conventions
|
|
136
156
|
|
|
137
157
|
`Chemicalml::Convention` is a registry of named constraint sets
|
|
138
158
|
(`molecular`, `compchem`, `dictionary`, `unit-dictionary`,
|
|
139
|
-
`unitType-dictionary`).
|
|
159
|
+
`unitType-dictionary`, `spectroscopy`, `cascade`, `simpleUnit`).
|
|
160
|
+
Each convention owns:
|
|
140
161
|
|
|
141
162
|
- a namespace URI (e.g. `http://www.xml-cml.org/convention/molecular`)
|
|
142
163
|
- a set of constraint classes registered against it
|
|
@@ -148,6 +169,33 @@ renderer code (Open/Closed Principle).
|
|
|
148
169
|
The constraint walker uses `Cml::Visitable#wire_children` to traverse
|
|
149
170
|
the tree — no `respond_to?` duck typing.
|
|
150
171
|
|
|
172
|
+
The shared `Cml::Base::CommonChildren` mixin provides `metadataList`,
|
|
173
|
+
`label`, `name`, and `description` children that the XSD grants to
|
|
174
|
+
most container elements. Including it in a `Base::*` module is the
|
|
175
|
+
DRY way to declare the universal child set.
|
|
176
|
+
|
|
177
|
+
`Cml::Enums` is the canonical Ruby source of truth for every XSD
|
|
178
|
+
enum simpleType. Three constraints validate against it
|
|
179
|
+
(`BondOrderShouldBeInEnum`, `BondStereoShouldBeInEnum`,
|
|
180
|
+
`MoleculeChiralityShouldBeInEnum`) at warning severity — extension
|
|
181
|
+
values are permitted but flagged.
|
|
182
|
+
|
|
183
|
+
`Cml::ReferenceResolver` walks a document and resolves
|
|
184
|
+
id-references (`atomRefs2`, `atomRefs4`, `bondRefs`, `ref`) to
|
|
185
|
+
target wire instances. `unresolved_refs` lists missing targets;
|
|
186
|
+
useful for callers that need to follow CML references.
|
|
187
|
+
|
|
188
|
+
### Parallel-array serialisation
|
|
189
|
+
|
|
190
|
+
`<atomArray>` and `<bondArray>` support two equivalent XML forms: the
|
|
191
|
+
child form (`<atomArray><atom.../><atom.../></atomArray>`) and the
|
|
192
|
+
parallel-array form (`<atomArray atomID="a1 a2" elementType="C O"/>`).
|
|
193
|
+
The wire attribute names in the parallel-array form match the
|
|
194
|
+
singular `<atom>` / `<bond>` attribute names (e.g. `elementType`,
|
|
195
|
+
`atomRef1`) — the XSD attribute *group* is named `elementTypeArray`
|
|
196
|
+
etc., but the wire attribute is `elementType`. Ruby attribute names
|
|
197
|
+
carry an `_array` suffix for clarity at the call site.
|
|
198
|
+
|
|
151
199
|
### Dictionaries
|
|
152
200
|
|
|
153
201
|
`Chemicalml::Dictionary` is the model; entries have `id`, `term`,
|
data/README.adoc
CHANGED
|
@@ -4,13 +4,19 @@ ChemML provides a https://www.xml-cml.org/[Chemical Markup Language (CML)]
|
|
|
4
4
|
object model for Ruby, built on
|
|
5
5
|
{lutaml-model}[https://github.com/lutaml/lutaml-model].
|
|
6
6
|
|
|
7
|
-
==
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
== Features
|
|
8
|
+
|
|
9
|
+
* Full Schema 3 and Schema 2.4 coverage — every CML element, attribute,
|
|
10
|
+
and XSD enum/pattern modelled as Ruby classes.
|
|
11
|
+
* Format-agnostic serialization — XML, JSON, YAML, and TOML round-trip
|
|
12
|
+
via lutaml-model adapters.
|
|
13
|
+
* Eight built-in conventions with 88+ registered constraints:
|
|
14
|
+
`molecular`, `compchem`, `dictionary`, `unit-dictionary`,
|
|
15
|
+
`unitType-dictionary`, `spectroscopy`, `cascade`, `simpleUnit`.
|
|
16
|
+
* Built-in dictionaries (cml, compchem, cif, unit_si, unit_non_si,
|
|
17
|
+
unit_type, cml_name, cml_formula) loaded from YAML.
|
|
18
|
+
* CLI for command-line validation and inspection.
|
|
19
|
+
* Ruby-native query API (`doc.find_atom(id)`, `doc.each_molecule`).
|
|
14
20
|
|
|
15
21
|
== Install
|
|
16
22
|
|
|
@@ -30,45 +36,167 @@ $ gem install chemicalml
|
|
|
30
36
|
|
|
31
37
|
== Usage
|
|
32
38
|
|
|
33
|
-
Parse a CML document
|
|
39
|
+
=== Parse a CML document
|
|
34
40
|
|
|
35
41
|
[source,ruby]
|
|
36
42
|
----
|
|
37
43
|
require "chemicalml"
|
|
38
44
|
|
|
39
|
-
doc = Chemicalml
|
|
40
|
-
doc.molecules.first.atoms.first.element_type # => "C"
|
|
45
|
+
doc = Chemicalml.parse_file("ethanol.cml")
|
|
46
|
+
doc.molecules.first.atom_array.atoms.first.element_type # => "C"
|
|
47
|
+
----
|
|
48
|
+
|
|
49
|
+
=== Validate against a convention
|
|
50
|
+
|
|
51
|
+
[source,ruby]
|
|
52
|
+
----
|
|
53
|
+
report = Chemicalml.validate(doc)
|
|
54
|
+
puts report.summary
|
|
55
|
+
puts report.errors.map(&:message)
|
|
41
56
|
----
|
|
42
57
|
|
|
43
|
-
Build a document programmatically
|
|
58
|
+
=== Build a document programmatically
|
|
44
59
|
|
|
45
60
|
[source,ruby]
|
|
46
61
|
----
|
|
47
62
|
atom = Chemicalml::Cml::Atom.new(id: "a1", element_type: "C")
|
|
48
|
-
mol = Chemicalml::Cml::Molecule.new(
|
|
63
|
+
mol = Chemicalml::Cml::Molecule.new(
|
|
64
|
+
id: "m1",
|
|
65
|
+
atom_array: Chemicalml::Cml::AtomArray.new(atoms: [atom])
|
|
66
|
+
)
|
|
49
67
|
doc = Chemicalml::Cml::Document.new(molecules: [mol])
|
|
50
68
|
|
|
51
69
|
doc.to_xml # => well-formed CML XML
|
|
52
70
|
----
|
|
53
71
|
|
|
54
|
-
|
|
72
|
+
=== Query the tree
|
|
55
73
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
74
|
+
[source,ruby]
|
|
75
|
+
----
|
|
76
|
+
doc.each_atom { |a| puts "#{a.id}: #{a.element_type}" }
|
|
77
|
+
doc.find_atom("a1") # => Atom instance
|
|
78
|
+
doc.atom_count # => recursive count
|
|
79
|
+
doc.find_molecule("m1") # => Molecule instance
|
|
80
|
+
----
|
|
81
|
+
|
|
82
|
+
=== Cross-format serialisation
|
|
83
|
+
|
|
84
|
+
[source,ruby]
|
|
85
|
+
----
|
|
86
|
+
doc.to_xml # CML XML
|
|
87
|
+
doc.to_json # JSON with CML wire names (elementType, atomArray, ...)
|
|
88
|
+
doc.to_yaml # YAML
|
|
89
|
+
----
|
|
90
|
+
|
|
91
|
+
=== Resolve references
|
|
92
|
+
|
|
93
|
+
[source,ruby]
|
|
94
|
+
----
|
|
95
|
+
resolver = Chemicalml::Cml::ReferenceResolver.new(doc)
|
|
96
|
+
resolver.unresolved_refs # => [{ node: <Bond>, attr: :atom_refs2, missing: ["a99"] }]
|
|
97
|
+
----
|
|
98
|
+
|
|
99
|
+
== CLI
|
|
100
|
+
|
|
101
|
+
[source,sh]
|
|
102
|
+
----
|
|
103
|
+
$ chemicalml validate file.cml # auto-detect convention, print violations
|
|
104
|
+
$ chemicalml inspect file.cml # tree-style summary
|
|
105
|
+
$ chemicalml conventions # list 8 registered conventions
|
|
106
|
+
$ chemicalml dictionaries # list built-in YAML dictionaries
|
|
107
|
+
$ chemicalml elements # list all CML wire classes
|
|
108
|
+
----
|
|
109
|
+
|
|
110
|
+
== Conventions
|
|
111
|
+
|
|
112
|
+
Eight conventions register 88+ constraints:
|
|
113
|
+
|
|
114
|
+
[cols="1,1,1"]
|
|
115
|
+
|===
|
|
116
|
+
| Convention | Constraints | Description
|
|
117
|
+
|
|
118
|
+
| molecular | 35 | Atom/bond/molecule well-formedness, id patterns,
|
|
119
|
+
element type validation, dictRef resolution, AtomParity parent
|
|
120
|
+
check, references-resolve check.
|
|
121
|
+
| compchem | 20 | JobList/Job/Initialization/Calculation/Finalization
|
|
122
|
+
module structure, scalar/array/matrix value rules.
|
|
123
|
+
| dictionary | 8 | Dictionary namespace, prefix, entry id/term/definition,
|
|
124
|
+
unitType/units co-constraints.
|
|
125
|
+
| unit-dictionary | 8 | UnitList namespace, unit id/title/symbol/parentSI/
|
|
126
|
+
multiplierToSI, definition child.
|
|
127
|
+
| unitType-dictionary | 5 | UnitTypeList namespace, unitType id/name/definition.
|
|
128
|
+
| spectroscopy | 5 | Spectrum convention/format/content, peakList, peak values.
|
|
129
|
+
| cascade | 4 | ReactionScheme content, reactionStepList, reactiveCentre atomRefs.
|
|
130
|
+
| simpleUnit | 3 | simpleUnit root, unit power, unit symbol.
|
|
131
|
+
|===
|
|
132
|
+
|
|
133
|
+
Add a custom convention at runtime:
|
|
134
|
+
|
|
135
|
+
[source,ruby]
|
|
136
|
+
----
|
|
137
|
+
module MyConvention
|
|
138
|
+
extend Chemicalml::Convention::Base
|
|
139
|
+
|
|
140
|
+
def self.qname; "convention:my"; end
|
|
141
|
+
def self.namespace_uri; "http://example.com/my"; end
|
|
142
|
+
|
|
143
|
+
register MyConstraintClass
|
|
144
|
+
end
|
|
59
145
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
146
|
+
Chemicalml::Convention::Registry.register_custom(MyConvention)
|
|
147
|
+
----
|
|
148
|
+
|
|
149
|
+
== Dictionaries
|
|
150
|
+
|
|
151
|
+
Eight built-in YAML dictionaries ship under `data/dictionaries/`:
|
|
152
|
+
|
|
153
|
+
[cols="1,1"]
|
|
154
|
+
|===
|
|
155
|
+
| Dictionary | Prefix
|
|
156
|
+
|
|
157
|
+
| cml | cml
|
|
158
|
+
| cml_name | cmlName
|
|
159
|
+
| cml_formula | cmlFormula
|
|
160
|
+
| cif | cif
|
|
161
|
+
| compchem | compchem
|
|
162
|
+
| unit_si | si
|
|
163
|
+
| unit_non_si | nonsi
|
|
164
|
+
| unit_type | unitType
|
|
165
|
+
|===
|
|
166
|
+
|
|
167
|
+
Load via:
|
|
63
168
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
169
|
+
[source,ruby]
|
|
170
|
+
----
|
|
171
|
+
dict = Chemicalml::Dictionary.load(:cml)
|
|
172
|
+
entry = Chemicalml::Dictionary::Registry.lookup("cml:bp")
|
|
173
|
+
entry.term # => "Boiling Point"
|
|
174
|
+
entry.definition # => "The temperature at which a substance boils..."
|
|
175
|
+
----
|
|
67
176
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
`
|
|
177
|
+
== Design
|
|
178
|
+
|
|
179
|
+
Each CML element is a `Lutaml::Model::Serializable` subclass with
|
|
180
|
+
declared attributes and parallel `xml do ... end` and
|
|
181
|
+
`key_value do ... end` mapping blocks. Serialisation is fully
|
|
182
|
+
framework-backed — no hand-rolled XML.
|
|
183
|
+
|
|
184
|
+
* `Cml::Base::*` modules declare shared attributes (mixed into both
|
|
185
|
+
Schema3 and Schema24 wire classes).
|
|
186
|
+
* `Cml::Role::*` modules are type-markers used by the convention
|
|
187
|
+
constraint walker for `is_a?` dispatch.
|
|
188
|
+
* `Cml::Elements::ALL` is the single source of truth for the CML
|
|
189
|
+
element table.
|
|
190
|
+
* `Cml::Enums` and `Cml::Patterns` mirror XSD simpleTypes.
|
|
191
|
+
* `Cml::CommonChildren` provides the universal `metadataList`,
|
|
192
|
+
`label`, `name`, `description` child set as a DRY mixin.
|
|
193
|
+
|
|
194
|
+
== Reference docs
|
|
195
|
+
|
|
196
|
+
`reference-docs/` holds archival source material from xml-cml.org:
|
|
197
|
+
the XSDs (`schemas/schema3/schema.xsd`, `schemas/schema24/schema.xsd`),
|
|
198
|
+
the convention specifications, and the CMLLite paper. These are
|
|
199
|
+
**source material, not derived output** — never delete or edit them.
|
|
72
200
|
|
|
73
201
|
== Acknowledgements
|
|
74
202
|
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# 61 — Parallel-array attrs for atomArray/bondArray
|
|
2
|
+
|
|
3
|
+
## Why
|
|
4
|
+
|
|
5
|
+
CML supports two equivalent serialisations of atom/bond tables:
|
|
6
|
+
|
|
7
|
+
```xml
|
|
8
|
+
<!-- child form (we already model this) -->
|
|
9
|
+
<atomArray><atom id="a1" elementType="C" x3="1.0" .../><atom .../></atomArray>
|
|
10
|
+
|
|
11
|
+
<!-- parallel-array form (we do NOT model this) -->
|
|
12
|
+
<atomArray atomID="a1 a2" elementType="C O" x3="1.0 2.0" .../>
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The parallel-array form is heavily used in real CML documents and is
|
|
16
|
+
the only form some legacy tools emit. Round-trip currently drops these
|
|
17
|
+
attributes silently.
|
|
18
|
+
|
|
19
|
+
## Source of truth
|
|
20
|
+
|
|
21
|
+
`reference-docs/schemas/schema3/schema.xsd` — `atomArrayType` complexType
|
|
22
|
+
declares these 14 parallel-array attributes:
|
|
23
|
+
|
|
24
|
+
- `atomID` (idArrayType)
|
|
25
|
+
- `count`, `countArrayType`
|
|
26
|
+
- `elementType`, `elementTypeArrayType`
|
|
27
|
+
- `formalCharge`, `formalChargeArrayType`
|
|
28
|
+
- `hydrogenCount`, `hydrogenCountArrayType`
|
|
29
|
+
- `occupancy`, `occupancyArrayType`
|
|
30
|
+
- `x2`, `y2` (coordinateComponentArrayType)
|
|
31
|
+
- `x3`, `y3`, `z3` (coordinateComponentArrayType)
|
|
32
|
+
- `xFract`, `yFract`, `zFract` (coordinateComponentArrayType)
|
|
33
|
+
|
|
34
|
+
`bondArrayType` declares 4:
|
|
35
|
+
|
|
36
|
+
- `atomRef1`, `atomRef2` (atomRefArrayType)
|
|
37
|
+
- `bondID` (idArrayType)
|
|
38
|
+
- `order` (orderArrayType)
|
|
39
|
+
|
|
40
|
+
## Work
|
|
41
|
+
|
|
42
|
+
1. `lib/chemicalml/cml/base/atom_array.rb` — declare the 14 attributes
|
|
43
|
+
as `:string` (lutaml-model does not need to validate the inner
|
|
44
|
+
whitespace-separated format) with matching `map_attribute` entries.
|
|
45
|
+
2. `lib/chemicalml/cml/base/bond_array.rb` — declare the 4 attributes.
|
|
46
|
+
3. Add specs in `spec/chemicalml/cml/parallel_array_spec.rb` asserting
|
|
47
|
+
round-trip for both forms.
|
|
48
|
+
|
|
49
|
+
## Acceptance
|
|
50
|
+
|
|
51
|
+
- `Chemicalml.parse` of a parallel-array `<atomArray>` populates the
|
|
52
|
+
attributes; `Chemicalml.serialize` emits them back unchanged.
|
|
53
|
+
- Both forms supported for Schema3 and Schema24.
|
|
54
|
+
- Specs green.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# 62 — Per-element attribute gaps
|
|
2
|
+
|
|
3
|
+
## Why
|
|
4
|
+
|
|
5
|
+
XSD vs Ruby Base comparison reveals 53 (schema3) / 58 (schema24)
|
|
6
|
+
attribute declarations that are not yet modelled. They cluster across
|
|
7
|
+
20 elements. Most are 1-3 missing attributes; the parallel-array
|
|
8
|
+
attributes for atomArray/bondArray are split out into TODO 61.
|
|
9
|
+
|
|
10
|
+
## Gaps (after TODO 61 closes)
|
|
11
|
+
|
|
12
|
+
| Element | Missing |
|
|
13
|
+
|---|---|
|
|
14
|
+
| alternative | type |
|
|
15
|
+
| band | kpoint (schema24 only) |
|
|
16
|
+
| bond | atomRefs (singular, not atomRefs2) |
|
|
17
|
+
| cellParameter | error, type |
|
|
18
|
+
| cml (module) | fileId, version |
|
|
19
|
+
| eigen | orientation |
|
|
20
|
+
| entry | convention, title, columns, rows, length, minLength, maxLength, pattern, minExclusive, minInclusive, maxExclusive, maxInclusive, fractionDigits, totalDigits, whiteSpace (XSD facets) |
|
|
21
|
+
| isotope | spin |
|
|
22
|
+
| module | role, serial |
|
|
23
|
+
| molecule | formula |
|
|
24
|
+
| peakStructure | type |
|
|
25
|
+
| potential | form |
|
|
26
|
+
| reaction | format, role |
|
|
27
|
+
| reactionScheme | format, role, type |
|
|
28
|
+
| reactionStepList | format |
|
|
29
|
+
| relatedEntry | type (schema24 only) |
|
|
30
|
+
| spectrum | type |
|
|
31
|
+
| substance | id |
|
|
32
|
+
| substanceList | type |
|
|
33
|
+
| unitList | type |
|
|
34
|
+
|
|
35
|
+
## Work
|
|
36
|
+
|
|
37
|
+
For each row above, add `attribute :foo, :string` + `map_attribute "foo", to: :foo`
|
|
38
|
+
to the relevant `lib/chemicalml/cml/base/*.rb` module.
|
|
39
|
+
|
|
40
|
+
The 15 XSD facets on `entry` (columns, fractionDigits, etc.) are
|
|
41
|
+
genuine CML — they describe the data type the entry represents, and
|
|
42
|
+
are emitted by the upstream dictionary files. They are not internal
|
|
43
|
+
XSD noise.
|
|
44
|
+
|
|
45
|
+
## Acceptance
|
|
46
|
+
|
|
47
|
+
- XSD vs Ruby comparison reports 0 attribute gaps.
|
|
48
|
+
- Round-trip of an example with `entry/@pattern` etc. is preserved.
|
|
49
|
+
- Spec coverage for at least one new attribute on each touched element.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# 63 — Universal children mixin
|
|
2
|
+
|
|
3
|
+
## Why
|
|
4
|
+
|
|
5
|
+
The CML Schema 2.4 XSD declares `metadataList`, `label`, `name`, and
|
|
6
|
+
`description` as children of nearly every element. Adding these four
|
|
7
|
+
declarations to every `Base::*` module individually is a DRY
|
|
8
|
+
violation: the same 16 lines of `attribute` + `map_element` would
|
|
9
|
+
appear in ~50 files.
|
|
10
|
+
|
|
11
|
+
## Solution
|
|
12
|
+
|
|
13
|
+
Introduce a shared mixin `Chemicalml::Cml::Base::CommonChildren`
|
|
14
|
+
that declares:
|
|
15
|
+
|
|
16
|
+
```ruby
|
|
17
|
+
attribute :metadata_lists, :metadataList, collection: true
|
|
18
|
+
attribute :labels, :label, collection: true
|
|
19
|
+
attribute :names, :name, collection: true
|
|
20
|
+
attribute :descriptions, :description, collection: true
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
with matching `map_element` declarations. The mixin is included by
|
|
24
|
+
the `Base::*` modules whose XSD declares these children.
|
|
25
|
+
|
|
26
|
+
The mixin is **opt-in** — elements that the XSD does not grant these
|
|
27
|
+
children to (e.g. `<atom>`, `<bond>` in schema24) do not include it.
|
|
28
|
+
This keeps MECE discipline: one place owns the universal child set.
|
|
29
|
+
|
|
30
|
+
## Work
|
|
31
|
+
|
|
32
|
+
1. Create `lib/chemicalml/cml/base/common_children.rb`.
|
|
33
|
+
2. For each Base module where the XSD declares metadataList/label/name/description as a child, add `include CommonChildren` and remove the now-redundant individual declarations.
|
|
34
|
+
3. Add a spec `spec/chemicalml/cml/common_children_spec.rb` asserting
|
|
35
|
+
the children appear after `include CommonChildren` and round-trip
|
|
36
|
+
through XML.
|
|
37
|
+
|
|
38
|
+
## Acceptance
|
|
39
|
+
|
|
40
|
+
- `CommonChildren` exists and is included by at least 10 Base modules.
|
|
41
|
+
- No Base module re-declares `metadata_lists` / `labels` / `names` / `descriptions` individually.
|
|
42
|
+
- Specs green.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# 64 — Per-element child element gaps (Schema 2.4)
|
|
2
|
+
|
|
3
|
+
## Why
|
|
4
|
+
|
|
5
|
+
XSD vs Ruby Base comparison reveals 235 missing child declarations
|
|
6
|
+
across ~60 Schema 2.4 elements. These are real CML elements that
|
|
7
|
+
real CML documents contain but our Ruby model drops silently.
|
|
8
|
+
|
|
9
|
+
The Schema 3 XSD declares `<anyCml>` (a wildcard) as a child of every
|
|
10
|
+
element — that is intentionally NOT modelled as a concrete child,
|
|
11
|
+
because doing so would defeat the type system. The Schema 2.4 gaps
|
|
12
|
+
below are *specific* named children, not wildcards.
|
|
13
|
+
|
|
14
|
+
## Largest clusters
|
|
15
|
+
|
|
16
|
+
| Element | Missing children |
|
|
17
|
+
|---|---|
|
|
18
|
+
| molecule | angle, arg, array, crystal, electron, join, length, list, matrix, metadataList, propertyList, scalar, symmetry, torsion, zMatrix |
|
|
19
|
+
| reaction | conditionList, identifier, label, map, mechanism, metadataList, name, object, propertyList, reactiveCentre, spectatorList, substanceList, transitionState |
|
|
20
|
+
| reactant, product | amount, electron, formula, identifier, label, metadataList, molecule, name, substanceList |
|
|
21
|
+
| atom | array, atomType, electron, label, matrix, name, particle, scalar, vector3 |
|
|
22
|
+
| atomType, bondType | array, atom/bond, label, matrix, molecule, property, scalar |
|
|
23
|
+
| join | angle, arg, label, length, metadataList, molecule, torsion |
|
|
24
|
+
| peak, peakGroup | atom, bond, metadataList, molecule, peakStructure/peakGroup |
|
|
25
|
+
| spectrum | metadataList, parameterList, sample, spectrumData, substanceList |
|
|
26
|
+
| reactiveCentre | atomSet, atomTypeList, bondSet, bondTypeList, description |
|
|
27
|
+
| parameter | expression, gradient, property |
|
|
28
|
+
| property | metadataList, name |
|
|
29
|
+
| parameterList, productList, reactantList, reactionStepList | metadataList, name, *(selfRef)* |
|
|
30
|
+
| moleculeList | list, metadataList, moleculeList |
|
|
31
|
+
| sample | metadataList, molecule, substance, substanceList |
|
|
32
|
+
| spectator | label, metadataList, molecule, object |
|
|
33
|
+
| substance | amount, metadataList, property |
|
|
34
|
+
| substanceList | amount, metadataList, propertyList |
|
|
35
|
+
| lattice | matrix, scalar, symmetry |
|
|
36
|
+
| gradient | array, matrix, property, scalar |
|
|
37
|
+
| table | arrayList, tableRowList |
|
|
38
|
+
| transitionState | molecule, propertyList |
|
|
39
|
+
| unit | annotation, metadata, metadataList, unit, unitType |
|
|
40
|
+
| unitType | annotation, dimension |
|
|
41
|
+
| zMatrix | angle, length, torsion |
|
|
42
|
+
| symmetry | matrix, transform3 |
|
|
43
|
+
| eigen | array, matrix |
|
|
44
|
+
| xaxis, yaxis | array |
|
|
45
|
+
| metadataList | metadataList |
|
|
46
|
+
| crystal | cellParameter |
|
|
47
|
+
| formula | formula |
|
|
48
|
+
| dictionary | annotation, unitList |
|
|
49
|
+
| dictionary entry | alternative, annotation, enumeration, metadataList, relatedEntry |
|
|
50
|
+
| map | link |
|
|
51
|
+
| mechanism | description, label, name |
|
|
52
|
+
| peakStructure | metadataList, peakStructure |
|
|
53
|
+
| reactionList | metadataList, reactionScheme |
|
|
54
|
+
| reactionScheme | identifier, label, metadataList, name, reactionScheme |
|
|
55
|
+
| reactionStep | label, metadataList, name, reactionScheme |
|
|
56
|
+
| potentialForm | arg, expression, parameter |
|
|
57
|
+
| trow | tcell |
|
|
58
|
+
| peakList | metadataList |
|
|
59
|
+
| atomTypeList, bondTypeList, basisSet | metadataList, name |
|
|
60
|
+
| conditionList | list, metadataList, name |
|
|
61
|
+
| propertyList | metadataList, name, observation, propertyList |
|
|
62
|
+
| spectrumList | list, metadataList, spectrumList |
|
|
63
|
+
|
|
64
|
+
## Strategy
|
|
65
|
+
|
|
66
|
+
After TODO 63 (CommonChildren mixin) closes, ~80% of the
|
|
67
|
+
`metadataList`/`label`/`name`/`description` gaps are absorbed by
|
|
68
|
+
adding one `include CommonChildren` line. The remaining ~150 gaps are
|
|
69
|
+
element-specific and require individual declarations.
|
|
70
|
+
|
|
71
|
+
## Work
|
|
72
|
+
|
|
73
|
+
1. Apply CommonChildren where the XSD permits.
|
|
74
|
+
2. For each remaining gap, add the specific `attribute` + `map_element` declarations.
|
|
75
|
+
3. Add at least one spec per touched element covering a round-trip
|
|
76
|
+
with the new child.
|
|
77
|
+
|
|
78
|
+
## Acceptance
|
|
79
|
+
|
|
80
|
+
- XSD vs Ruby child comparison reports only `<anyCml>` Schema3 wildcard gaps (intentionally unmodelled).
|
|
81
|
+
- Specs green.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# 65 — SimpleUnit convention
|
|
2
|
+
|
|
3
|
+
## Why
|
|
4
|
+
|
|
5
|
+
`reference-docs/conventions/index.md` lists six CML conventions.
|
|
6
|
+
We implement five + two added later (spectroscopy, cascade). The
|
|
7
|
+
sixth "official" one is `simpleUnit`, used as the worked example in
|
|
8
|
+
the CMLLite paper. Without it, the convention set is incomplete
|
|
9
|
+
relative to the upstream CML spec.
|
|
10
|
+
|
|
11
|
+
## Source
|
|
12
|
+
|
|
13
|
+
`reference-docs/schemas/schema3/schema.xsd` — does not define
|
|
14
|
+
convention rules; the rules come from the CMLLite paper. The
|
|
15
|
+
namespace is `http://www.xml-cml.org/convention/simpleUnit`.
|
|
16
|
+
|
|
17
|
+
The paper's simpleUnit example constraints:
|
|
18
|
+
|
|
19
|
+
- A `<unit>` under simpleUnit MUST have a `power` attribute (integer).
|
|
20
|
+
- A `<unit>` under simpleUnit MUST have a `symbol` attribute (non-empty string).
|
|
21
|
+
- The root must be a `<unitList>` declaring `convention='convention:simpleUnit'`.
|
|
22
|
+
|
|
23
|
+
## Work
|
|
24
|
+
|
|
25
|
+
1. `lib/chemicalml/convention/simple_unit.rb` — main module (QNAME =
|
|
26
|
+
`convention:simpleUnit`, NAMESPACE_URI ends in `/simpleUnit`).
|
|
27
|
+
2. `lib/chemicalml/convention/simple_unit/constraints.rb` — autoload registry.
|
|
28
|
+
3. Three constraint files:
|
|
29
|
+
- `unit_must_have_power.rb` — applies_to Role::Unit
|
|
30
|
+
- `unit_must_have_symbol.rb` — applies_to Role::Unit
|
|
31
|
+
- `root_must_be_unit_list.rb` — DocumentConstraint
|
|
32
|
+
4. Register in `Convention::Registry.load_cache`.
|
|
33
|
+
5. Add `autoload :SimpleUnit` to `lib/chemicalml/convention.rb`.
|
|
34
|
+
6. Specs at `spec/chemicalml/convention/simple_unit_spec.rb`.
|
|
35
|
+
|
|
36
|
+
## Acceptance
|
|
37
|
+
|
|
38
|
+
- `Chemicalml::Convention.lookup("convention:simpleUnit")` returns the module.
|
|
39
|
+
- Specs cover all three constraints (positive + negative cases).
|
|
40
|
+
- Full suite green.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# 66 — Schema24-only legacy element children
|
|
2
|
+
|
|
3
|
+
## Why
|
|
4
|
+
|
|
5
|
+
Schema 2.4 declares 17 elements absent from Schema 3 (TODO 52 modelled
|
|
6
|
+
them). Of those, several have non-trivial child models that were
|
|
7
|
+
skipped during initial modelling. XSD vs Ruby comparison shows:
|
|
8
|
+
|
|
9
|
+
| Element | Missing children |
|
|
10
|
+
|---|---|
|
|
11
|
+
| annotation | appinfo |
|
|
12
|
+
| arg | array, atom, atomType, expression, matrix, scalar |
|
|
13
|
+
| atomType | array, atom, label, matrix, molecule, property, scalar |
|
|
14
|
+
| bondType | array, bond, label, matrix, molecule, property, scalar |
|
|
15
|
+
| expression | operator, parameter |
|
|
16
|
+
| enumeration | annotation |
|
|
17
|
+
| potentialForm | arg, expression, parameter |
|
|
18
|
+
|
|
19
|
+
These are real Schema 2.4 features; the rest of the legacy set
|
|
20
|
+
(`float`, `integer`, `string`, `tcell`, `trow`, etc.) are scalar
|
|
21
|
+
leaves without children.
|
|
22
|
+
|
|
23
|
+
## Work
|
|
24
|
+
|
|
25
|
+
1. Update each Schema24-only `Base::*` module to declare the missing
|
|
26
|
+
children + matching `map_element`.
|
|
27
|
+
2. Add a spec per touched element.
|
|
28
|
+
|
|
29
|
+
## Acceptance
|
|
30
|
+
|
|
31
|
+
- XSD vs Ruby child comparison reports 0 Schema24-only-legacy gaps.
|
|
32
|
+
- Specs green.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# 67 — Final spec / lint / docs verification
|
|
2
|
+
|
|
3
|
+
## Why
|
|
4
|
+
|
|
5
|
+
After TODOs 61-66 land, the public surface area grows by ~330 element
|
|
6
|
+
attribute/child declarations plus a new convention. CLAUDE.md and the
|
|
7
|
+
spec suite need to reflect the new state.
|
|
8
|
+
|
|
9
|
+
## Work
|
|
10
|
+
|
|
11
|
+
1. Update `CLAUDE.md`:
|
|
12
|
+
- List 8 conventions (molecular, compchem, dictionary, unit-dictionary,
|
|
13
|
+
unitType-dictionary, spectroscopy, cascade, simpleUnit).
|
|
14
|
+
- Note the parallel-array atomArray/bondArray serialisation forms.
|
|
15
|
+
- Note the `CommonChildren` mixin pattern.
|
|
16
|
+
2. Scan the codebase for forbidden patterns:
|
|
17
|
+
- `require_relative` inside `lib/`
|
|
18
|
+
- `def to_h`, `def from_h`, `def to_xml`, `def from_xml`, `def to_json`, `def from_json` on model classes
|
|
19
|
+
- `double(` in specs
|
|
20
|
+
- `\.send(`, `instance_variable_set`, `instance_variable_get`, `respond_to?`
|
|
21
|
+
- AI attribution trailers in commit history
|
|
22
|
+
3. Run full `bundle exec rspec` — must be green.
|
|
23
|
+
4. Run `bundle exec rubocop` on touched files — must be clean.
|
|
24
|
+
5. Add a top-level README under `TODO.align/` summarising rounds 1-17.
|
|
25
|
+
|
|
26
|
+
## Acceptance
|
|
27
|
+
|
|
28
|
+
- `bundle exec rspec` exits 0.
|
|
29
|
+
- `grep -rn 'require_relative' lib/` returns nothing.
|
|
30
|
+
- `grep -rn 'def to_h\|def from_h' lib/chemicalml/cml/` returns nothing.
|
|
31
|
+
- `grep -rn 'double(' spec/` returns nothing.
|
|
32
|
+
- CLAUDE.md convention list is current.
|