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
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Chemicalml
|
|
4
|
+
module Convention
|
|
5
|
+
# The Cascade convention. A chemicalml-specific convention for CML
|
|
6
|
+
# reaction cascades — multi-step reaction networks encoded via
|
|
7
|
+
# `<reactionScheme>`, `<reactionStepList>`, `<reactionStep>`,
|
|
8
|
+
# `<reaction>`, and `<reactiveCentre>`.
|
|
9
|
+
#
|
|
10
|
+
# Upstream CML does not publish a dedicated cascade convention; the
|
|
11
|
+
# wire elements exist in the XSD but no constraints guard their
|
|
12
|
+
# well-formedness. This convention covers the gaps:
|
|
13
|
+
#
|
|
14
|
+
# - reactionScheme MUST contain at least one reactionStepList or
|
|
15
|
+
# reaction (an empty scheme carries no cascade)
|
|
16
|
+
# - reactionStepList MUST contain at least one reactionStep
|
|
17
|
+
# - reactionStep MUST contain a reaction or explicit reactant/product
|
|
18
|
+
# lists (an empty step is a dead-end in the cascade)
|
|
19
|
+
# - reactiveCentre atomRefs SHOULD be parseable atom references
|
|
20
|
+
# (warning — gracefully degrades when context is missing)
|
|
21
|
+
module Cascade
|
|
22
|
+
extend Base
|
|
23
|
+
|
|
24
|
+
autoload :Constraints, 'chemicalml/convention/cascade/constraints'
|
|
25
|
+
|
|
26
|
+
QNAME = 'convention:cascade'
|
|
27
|
+
NAMESPACE_URI = "#{Chemicalml::Convention::CONVENTION_NAMESPACE}cascade".freeze
|
|
28
|
+
|
|
29
|
+
def self.qname
|
|
30
|
+
QNAME
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def self.namespace_uri
|
|
34
|
+
NAMESPACE_URI
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
register Constraints::ReactionSchemeMustHaveContent
|
|
38
|
+
register Constraints::ReactionStepListMustContainSteps
|
|
39
|
+
register Constraints::ReactionStepMustHaveReactionOrLists
|
|
40
|
+
register Constraints::ReactiveCentreAtomRefsShouldBePresent
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -8,13 +8,13 @@ module Chemicalml
|
|
|
8
8
|
# attribute (≥ 1); `dataType` MUST be integer or double;
|
|
9
9
|
# MUST have `units`.
|
|
10
10
|
class ArrayRules < Chemicalml::Convention::Constraint::NodeConstraint
|
|
11
|
+
self.description = 'CompChem `array` value-container rules: MUST have `size` attribute (≥ 1); `dataType` MUST be integer or double; MUST have `units`.'
|
|
11
12
|
applies_to Chemicalml::Cml::Role::Array
|
|
12
13
|
include ModulePredicates
|
|
13
14
|
|
|
14
15
|
ALLOWED_TYPES = %w[xsd:integer xsd:double].freeze
|
|
15
16
|
|
|
16
17
|
def check_node(node, path)
|
|
17
|
-
|
|
18
18
|
violations = []
|
|
19
19
|
if node.size.to_s.empty? || node.size.to_i < 1
|
|
20
20
|
violations << violation(path: path.join('/'),
|
|
@@ -7,11 +7,11 @@ module Chemicalml
|
|
|
7
7
|
# Co-constraint: if a calculation module is present inside a
|
|
8
8
|
# job, a finalization MUST also be present.
|
|
9
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.'
|
|
10
11
|
applies_to Chemicalml::Cml::Role::Module
|
|
11
12
|
include ModulePredicates
|
|
12
13
|
|
|
13
14
|
def check_node(node, path)
|
|
14
|
-
|
|
15
15
|
calculations = child_modules_with(node, 'compchem:calculation')
|
|
16
16
|
finalizations = child_modules_with(node, 'compchem:finalization')
|
|
17
17
|
return [] if calculations.empty?
|
data/lib/chemicalml/convention/compchem/constraints/compchem_module_must_contain_job_list.rb
CHANGED
|
@@ -7,10 +7,11 @@ 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
17
|
[violation(path: path.join('/'),
|
data/lib/chemicalml/convention/compchem/constraints/environment_at_most_one_property_list.rb
CHANGED
|
@@ -7,11 +7,11 @@ module Chemicalml
|
|
|
7
7
|
# The environment module MUST NOT contain more than one
|
|
8
8
|
# propertyList child.
|
|
9
9
|
class EnvironmentAtMostOnePropertyList < Chemicalml::Convention::Constraint::NodeConstraint
|
|
10
|
+
self.description = 'The environment module MUST NOT contain more than one propertyList child.'
|
|
10
11
|
applies_to Chemicalml::Cml::Role::Module
|
|
11
12
|
include ModulePredicates
|
|
12
13
|
|
|
13
14
|
def check_node(node, path)
|
|
14
|
-
|
|
15
15
|
lists = node.property_lists || []
|
|
16
16
|
return [] if lists.length <= 1
|
|
17
17
|
|
data/lib/chemicalml/convention/compchem/constraints/environment_must_not_contain_parameter.rb
CHANGED
|
@@ -8,11 +8,11 @@ module Chemicalml
|
|
|
8
8
|
# parameterList children directly. It MAY contain a
|
|
9
9
|
# propertyList (which itself can hold parameters).
|
|
10
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).'
|
|
11
12
|
applies_to Chemicalml::Cml::Role::Module
|
|
12
13
|
include ModulePredicates
|
|
13
14
|
|
|
14
15
|
def check_node(node, path)
|
|
15
|
-
|
|
16
16
|
violations = []
|
|
17
17
|
unless (node.parameter_lists || []).empty?
|
|
18
18
|
violations << violation(path: path.join('/'),
|
|
@@ -7,11 +7,11 @@ module Chemicalml
|
|
|
7
7
|
# The finalization module MUST NOT contain more than one
|
|
8
8
|
# molecule child.
|
|
9
9
|
class FinalizationAtMostOneMolecule < Chemicalml::Convention::Constraint::NodeConstraint
|
|
10
|
+
self.description = 'The finalization module MUST NOT contain more than one molecule child.'
|
|
10
11
|
applies_to Chemicalml::Cml::Role::Module
|
|
11
12
|
include ModulePredicates
|
|
12
13
|
|
|
13
14
|
def check_node(node, path)
|
|
14
|
-
|
|
15
15
|
molecules = node.molecules || []
|
|
16
16
|
return [] if molecules.length <= 1
|
|
17
17
|
|
data/lib/chemicalml/convention/compchem/constraints/finalization_at_most_one_property_list.rb
CHANGED
|
@@ -7,11 +7,11 @@ module Chemicalml
|
|
|
7
7
|
# The finalization module MUST NOT contain more than one
|
|
8
8
|
# propertyList child.
|
|
9
9
|
class FinalizationAtMostOnePropertyList < Chemicalml::Convention::Constraint::NodeConstraint
|
|
10
|
+
self.description = 'The finalization module MUST NOT contain more than one propertyList child.'
|
|
10
11
|
applies_to Chemicalml::Cml::Role::Module
|
|
11
12
|
include ModulePredicates
|
|
12
13
|
|
|
13
14
|
def check_node(node, path)
|
|
14
|
-
|
|
15
15
|
lists = node.property_lists || []
|
|
16
16
|
return [] if lists.length <= 1
|
|
17
17
|
|
|
@@ -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
|
data/lib/chemicalml/convention/compchem/constraints/finalization_must_not_contain_parameter.rb
CHANGED
|
@@ -8,11 +8,11 @@ module Chemicalml
|
|
|
8
8
|
# parameterList children directly. (Parameters belong in
|
|
9
9
|
# initialization.)
|
|
10
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.)'
|
|
11
12
|
applies_to Chemicalml::Cml::Role::Module
|
|
12
13
|
include ModulePredicates
|
|
13
14
|
|
|
14
15
|
def check_node(node, path)
|
|
15
|
-
|
|
16
16
|
violations = []
|
|
17
17
|
unless (node.parameter_lists || []).empty?
|
|
18
18
|
violations << violation(path: path.join('/'),
|
|
@@ -7,11 +7,11 @@ module Chemicalml
|
|
|
7
7
|
# The initialization module MUST NOT contain more than one
|
|
8
8
|
# molecule child.
|
|
9
9
|
class InitializationAtMostOneMolecule < Chemicalml::Convention::Constraint::NodeConstraint
|
|
10
|
+
self.description = 'The initialization module MUST NOT contain more than one molecule child.'
|
|
10
11
|
applies_to Chemicalml::Cml::Role::Module
|
|
11
12
|
include ModulePredicates
|
|
12
13
|
|
|
13
14
|
def check_node(node, path)
|
|
14
|
-
|
|
15
15
|
molecules = node.molecules || []
|
|
16
16
|
return [] if molecules.length <= 1
|
|
17
17
|
|
data/lib/chemicalml/convention/compchem/constraints/initialization_at_most_one_parameter_list.rb
CHANGED
|
@@ -7,11 +7,11 @@ module Chemicalml
|
|
|
7
7
|
# The initialization module MUST NOT contain more than one
|
|
8
8
|
# parameterList child.
|
|
9
9
|
class InitializationAtMostOneParameterList < Chemicalml::Convention::Constraint::NodeConstraint
|
|
10
|
+
self.description = 'The initialization module MUST NOT contain more than one parameterList child.'
|
|
10
11
|
applies_to Chemicalml::Cml::Role::Module
|
|
11
12
|
include ModulePredicates
|
|
12
13
|
|
|
13
14
|
def check_node(node, path)
|
|
14
|
-
|
|
15
15
|
lists = node.parameter_lists || []
|
|
16
16
|
return [] if lists.length <= 1
|
|
17
17
|
|
|
@@ -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
|
data/lib/chemicalml/convention/compchem/constraints/initialization_must_not_contain_property.rb
CHANGED
|
@@ -8,11 +8,11 @@ module Chemicalml
|
|
|
8
8
|
# propertyList children directly. (Properties belong in
|
|
9
9
|
# finalization.)
|
|
10
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.)'
|
|
11
12
|
applies_to Chemicalml::Cml::Role::Module
|
|
12
13
|
include ModulePredicates
|
|
13
14
|
|
|
14
15
|
def check_node(node, path)
|
|
15
|
-
|
|
16
16
|
violations = []
|
|
17
17
|
unless (node.property_lists || []).empty?
|
|
18
18
|
violations << violation(path: path.join('/'),
|
|
@@ -7,6 +7,7 @@ module Chemicalml
|
|
|
7
7
|
# A jobList module MUST have an `id` unique within the
|
|
8
8
|
# compchem module.
|
|
9
9
|
class JobListModuleMustHaveId < Chemicalml::Convention::Constraint::NodeConstraint
|
|
10
|
+
self.description = 'A jobList module MUST have an `id` unique within the compchem module.'
|
|
10
11
|
applies_to Chemicalml::Cml::Role::Module
|
|
11
12
|
include ModulePredicates
|
|
12
13
|
|
|
@@ -6,11 +6,11 @@ module Chemicalml
|
|
|
6
6
|
module Constraints
|
|
7
7
|
# A job module MUST contain at most one environment module.
|
|
8
8
|
class JobModuleAtMostOneEnvironment < Chemicalml::Convention::Constraint::NodeConstraint
|
|
9
|
+
self.description = 'A job module MUST contain at most one environment module.'
|
|
9
10
|
applies_to Chemicalml::Cml::Role::Module
|
|
10
11
|
include ModulePredicates
|
|
11
12
|
|
|
12
13
|
def check_node(node, path)
|
|
13
|
-
|
|
14
14
|
environments = child_modules_with(node, 'compchem:environment')
|
|
15
15
|
return [] if environments.length <= 1
|
|
16
16
|
|
|
@@ -6,11 +6,11 @@ module Chemicalml
|
|
|
6
6
|
module Constraints
|
|
7
7
|
# A job module MUST contain at most one finalization module.
|
|
8
8
|
class JobModuleAtMostOneFinalization < Chemicalml::Convention::Constraint::NodeConstraint
|
|
9
|
+
self.description = 'A job module MUST contain at most one finalization module.'
|
|
9
10
|
applies_to Chemicalml::Cml::Role::Module
|
|
10
11
|
include ModulePredicates
|
|
11
12
|
|
|
12
13
|
def check_node(node, path)
|
|
13
|
-
|
|
14
14
|
finalizations = child_modules_with(node, 'compchem:finalization')
|
|
15
15
|
return [] if finalizations.length <= 1
|
|
16
16
|
|
|
@@ -7,6 +7,7 @@ module Chemicalml
|
|
|
7
7
|
# A job module MUST have an `id` unique within the compchem
|
|
8
8
|
# module.
|
|
9
9
|
class JobModuleMustHaveId < Chemicalml::Convention::Constraint::NodeConstraint
|
|
10
|
+
self.description = 'A job module MUST have an `id` unique within the compchem module.'
|
|
10
11
|
applies_to Chemicalml::Cml::Role::Module
|
|
11
12
|
include ModulePredicates
|
|
12
13
|
|
|
@@ -7,6 +7,7 @@ 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.'
|
|
10
11
|
applies_to Chemicalml::Cml::Role::Module
|
|
11
12
|
def check_node(node, path)
|
|
12
13
|
return [] unless node.dict_ref == 'compchem:job'
|
|
@@ -8,13 +8,13 @@ module Chemicalml
|
|
|
8
8
|
# and `columns` attributes (each ≥ 1); `dataType` MUST be
|
|
9
9
|
# integer or double; MUST have `units`.
|
|
10
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`.'
|
|
11
12
|
applies_to Chemicalml::Cml::Role::Matrix
|
|
12
13
|
include ModulePredicates
|
|
13
14
|
|
|
14
15
|
ALLOWED_TYPES = %w[xsd:integer xsd:double].freeze
|
|
15
16
|
|
|
16
17
|
def check_node(node, path)
|
|
17
|
-
|
|
18
18
|
violations = []
|
|
19
19
|
if node.rows.to_s.empty? || node.rows.to_i < 1
|
|
20
20
|
violations << violation(path: path.join('/'),
|
|
@@ -8,13 +8,13 @@ module Chemicalml
|
|
|
8
8
|
# `xsd:integer` or `xsd:double` MUST have `units`; `scalar`
|
|
9
9
|
# with dataType `xsd:string` MUST NOT have `units`.
|
|
10
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`.'
|
|
11
12
|
applies_to Chemicalml::Cml::Role::Scalar
|
|
12
13
|
include ModulePredicates
|
|
13
14
|
|
|
14
15
|
NUMERIC_TYPES = %w[xsd:integer xsd:double].freeze
|
|
15
16
|
|
|
16
17
|
def check_node(node, path)
|
|
17
|
-
|
|
18
18
|
data_type = node.data_type.to_s
|
|
19
19
|
units = node.units.to_s
|
|
20
20
|
violations = []
|
|
@@ -42,6 +42,10 @@ module Chemicalml
|
|
|
42
42
|
'chemicalml/convention/compchem/constraints/array_rules'
|
|
43
43
|
autoload :MatrixRules,
|
|
44
44
|
'chemicalml/convention/compchem/constraints/matrix_rules'
|
|
45
|
+
autoload :InitializationMustHaveContent,
|
|
46
|
+
'chemicalml/convention/compchem/constraints/initialization_must_have_content'
|
|
47
|
+
autoload :FinalizationMustHaveContent,
|
|
48
|
+
'chemicalml/convention/compchem/constraints/finalization_must_have_content'
|
|
45
49
|
end
|
|
46
50
|
end
|
|
47
51
|
end
|
|
@@ -8,9 +8,9 @@ module Chemicalml
|
|
|
8
8
|
module Compchem
|
|
9
9
|
extend Base
|
|
10
10
|
|
|
11
|
-
autoload :Constraints,
|
|
11
|
+
autoload :Constraints, 'chemicalml/convention/compchem/constraints'
|
|
12
12
|
|
|
13
|
-
QNAME =
|
|
13
|
+
QNAME = 'convention:compchem'
|
|
14
14
|
NAMESPACE_URI = "#{Chemicalml::Convention::CONVENTION_NAMESPACE}compchem".freeze
|
|
15
15
|
|
|
16
16
|
def self.qname
|
|
@@ -39,6 +39,8 @@ module Chemicalml
|
|
|
39
39
|
register Constraints::ScalarUnits
|
|
40
40
|
register Constraints::ArrayRules
|
|
41
41
|
register Constraints::MatrixRules
|
|
42
|
+
register Constraints::InitializationMustHaveContent
|
|
43
|
+
register Constraints::FinalizationMustHaveContent
|
|
42
44
|
end
|
|
43
45
|
end
|
|
44
46
|
end
|
|
@@ -15,9 +15,7 @@ module Chemicalml
|
|
|
15
15
|
class << self
|
|
16
16
|
# Returns the Role module(s) this constraint applies to, or
|
|
17
17
|
# nil if it must run for every node.
|
|
18
|
-
|
|
19
|
-
@applies_to_roles
|
|
20
|
-
end
|
|
18
|
+
attr_reader :applies_to_roles
|
|
21
19
|
|
|
22
20
|
# Declare one or more Role modules this constraint handles.
|
|
23
21
|
# applies_to Chemicalml::Cml::Role::Atom
|
|
@@ -25,6 +23,28 @@ module Chemicalml
|
|
|
25
23
|
def applies_to(*roles)
|
|
26
24
|
@applies_to_roles = roles.flatten.freeze
|
|
27
25
|
end
|
|
26
|
+
|
|
27
|
+
# Human-readable description of the rule this constraint
|
|
28
|
+
# enforces. Subclasses MAY override. Falls back to the class
|
|
29
|
+
# name. Used by `chemicalml constraints` and the auto-generated
|
|
30
|
+
# constraint docs.
|
|
31
|
+
#
|
|
32
|
+
# @return [String]
|
|
33
|
+
def description
|
|
34
|
+
@description || name.split('::').last
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Set the description (DSL for subclasses).
|
|
38
|
+
# description "A <bond> must have an order attribute"
|
|
39
|
+
attr_writer :description
|
|
40
|
+
|
|
41
|
+
# Severity this constraint emits. Subclasses MAY override.
|
|
42
|
+
# Default `:error` — warning subclasses override to `:warning`.
|
|
43
|
+
#
|
|
44
|
+
# @return [Symbol] `:error` or `:warning`.
|
|
45
|
+
def default_severity
|
|
46
|
+
:error
|
|
47
|
+
end
|
|
28
48
|
end
|
|
29
49
|
|
|
30
50
|
def initialize
|
|
@@ -38,21 +58,32 @@ module Chemicalml
|
|
|
38
58
|
|
|
39
59
|
protected
|
|
40
60
|
|
|
41
|
-
def violation(path:, message:, severity: :error)
|
|
61
|
+
def violation(path:, message:, severity: :error, value: nil)
|
|
42
62
|
Violation.new(path: path, message: message,
|
|
43
|
-
severity: severity, constraint: self.class
|
|
63
|
+
severity: severity, constraint: self.class,
|
|
64
|
+
value: value)
|
|
44
65
|
end
|
|
45
66
|
|
|
46
67
|
# Walk every wire node reachable from `node`. Yields (node, path)
|
|
47
68
|
# pairs. Path is a slash-joined breadcrumb. Nodes that don't
|
|
48
69
|
# include `Chemicalml::Cml::Visitable` are skipped.
|
|
49
|
-
|
|
70
|
+
#
|
|
71
|
+
# Iterative (worklist) implementation — does not recurse, so
|
|
72
|
+
# deeply-nested documents cannot overflow the stack. Traversal
|
|
73
|
+
# order is DFS pre-order, matching the prior recursive walker.
|
|
74
|
+
def walk_nodes(node, path = [])
|
|
50
75
|
return unless node
|
|
51
76
|
return unless visitable?(node)
|
|
52
77
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
78
|
+
worklist = [[node, path]]
|
|
79
|
+
until worklist.empty?
|
|
80
|
+
current, current_path = worklist.shift
|
|
81
|
+
yield(current, current_path)
|
|
82
|
+
current.wire_children.reverse_each do |child|
|
|
83
|
+
next unless visitable?(child)
|
|
84
|
+
|
|
85
|
+
worklist.unshift([child, current_path + [describe(child)]])
|
|
86
|
+
end
|
|
56
87
|
end
|
|
57
88
|
end
|
|
58
89
|
|
|
@@ -16,10 +16,10 @@ module Chemicalml
|
|
|
16
16
|
|
|
17
17
|
def initialize(constraint_classes)
|
|
18
18
|
@document_constraints = constraint_classes
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
.select { |c| c < Constraint::DocumentConstraint }
|
|
20
|
+
.map(&:new)
|
|
21
21
|
@node_constraints = constraint_constraints(constraint_classes)
|
|
22
|
-
|
|
22
|
+
.map(&:new)
|
|
23
23
|
@always_applicable = []
|
|
24
24
|
@by_role = Hash.new { |h, k| h[k] = [] }
|
|
25
25
|
@node_constraints.each { |c| register(c) }
|
|
@@ -62,6 +62,7 @@ module Chemicalml
|
|
|
62
62
|
applicable = @always_applicable
|
|
63
63
|
node.class.ancestors.each do |ancestor|
|
|
64
64
|
next unless ancestor.is_a?(::Module)
|
|
65
|
+
|
|
65
66
|
bucket = @by_role[ancestor]
|
|
66
67
|
next unless bucket
|
|
67
68
|
|
|
@@ -3,21 +3,27 @@
|
|
|
3
3
|
module Chemicalml
|
|
4
4
|
module Convention
|
|
5
5
|
# Convention detection from a wire document. Reads the
|
|
6
|
-
# `convention` attribute from the root element
|
|
7
|
-
#
|
|
8
|
-
# the QName string (e.g. "convention:molecular").
|
|
6
|
+
# `convention` attribute from the root element and returns the
|
|
7
|
+
# QName string (e.g. "convention:molecular").
|
|
9
8
|
#
|
|
10
9
|
# Used by `Registry.detect_and_validate` and reusable by callers
|
|
11
10
|
# that want to know which convention a document declares without
|
|
12
11
|
# running validation.
|
|
13
12
|
module Detection
|
|
13
|
+
# Wire roles that may carry a top-level convention attribute.
|
|
14
|
+
# Adding a new convention whose root is a new element type =
|
|
15
|
+
# adding one role here. OCP — no existing code changes.
|
|
14
16
|
CONVENTION_ROOTS = [
|
|
15
17
|
Chemicalml::Cml::Role::Document,
|
|
16
18
|
Chemicalml::Cml::Role::Module,
|
|
17
19
|
Chemicalml::Cml::Role::Molecule,
|
|
18
20
|
Chemicalml::Cml::Role::Dictionary,
|
|
19
21
|
Chemicalml::Cml::Role::UnitList,
|
|
20
|
-
Chemicalml::Cml::Role::UnitTypeList
|
|
22
|
+
Chemicalml::Cml::Role::UnitTypeList,
|
|
23
|
+
Chemicalml::Cml::Role::Spectrum,
|
|
24
|
+
Chemicalml::Cml::Role::SpectrumList,
|
|
25
|
+
Chemicalml::Cml::Role::ReactionScheme,
|
|
26
|
+
Chemicalml::Cml::Role::ReactionList
|
|
21
27
|
].freeze
|
|
22
28
|
|
|
23
29
|
def self.convention_of(document)
|
|
@@ -8,6 +8,7 @@ module Chemicalml
|
|
|
8
8
|
# whose value is a valid URI defining the scope within which
|
|
9
9
|
# the entry terms are unique.
|
|
10
10
|
class DictionaryMustHaveNamespace < Chemicalml::Convention::Constraint::NodeConstraint
|
|
11
|
+
self.description = 'A `<dictionary>` element MUST have a `namespace` attribute whose value is a valid URI defining the scope within which the entry terms are unique.'
|
|
11
12
|
applies_to Chemicalml::Cml::Role::Dictionary
|
|
12
13
|
def check_node(node, path)
|
|
13
14
|
return [] unless node.namespace.to_s.empty?
|
|
@@ -7,9 +7,9 @@ module Chemicalml
|
|
|
7
7
|
# The `namespace` URI SHOULD end with `/` or `#` so terms can
|
|
8
8
|
# be referenced by appending them to the URI. Warning level.
|
|
9
9
|
class DictionaryNamespaceShouldEndWithSlashOrHash < Chemicalml::Convention::Constraint::NodeConstraint
|
|
10
|
+
self.description = 'The `namespace` URI SHOULD end with `/` or `#` so terms can be referenced by appending them to the URI. Warning level.'
|
|
10
11
|
applies_to Chemicalml::Cml::Role::Dictionary
|
|
11
12
|
def check_node(node, path)
|
|
12
|
-
|
|
13
13
|
ns = node.namespace.to_s
|
|
14
14
|
return [] if ns.empty?
|
|
15
15
|
return [] if ns.end_with?('/', '#')
|
|
@@ -8,11 +8,11 @@ module Chemicalml
|
|
|
8
8
|
# start with a letter, followed by letters/digits/dot/hyphen/
|
|
9
9
|
# underscore. Mirrors the upstream IdStartChar / IdChar BNF.
|
|
10
10
|
class EntryIdMustMatchPattern < Chemicalml::Convention::Constraint::NodeConstraint
|
|
11
|
+
self.description = 'An `<entry>` `id` MUST match `[A-Za-z][A-Za-z0-9._-]*` — start with a letter, followed by letters/digits/dot/hyphen/ underscore. Mirrors the upstream IdStartChar / IdChar BNF.'
|
|
11
12
|
applies_to Chemicalml::Cml::Role::DictionaryEntry
|
|
12
13
|
PATTERN = /\A[A-Za-z][A-Za-z0-9._-]*\z/
|
|
13
14
|
|
|
14
15
|
def check_node(node, path)
|
|
15
|
-
|
|
16
16
|
id = node.id.to_s
|
|
17
17
|
return [] if id.empty?
|
|
18
18
|
return [] if id.match?(PATTERN)
|
|
@@ -7,9 +7,9 @@ module Chemicalml
|
|
|
7
7
|
# Entry ids MUST be unique within the parent dictionary per
|
|
8
8
|
# the dictionary convention.
|
|
9
9
|
class EntryIdsUniqueWithinDictionary < Chemicalml::Convention::Constraint::NodeConstraint
|
|
10
|
+
self.description = 'Entry ids MUST be unique within the parent dictionary per the dictionary convention.'
|
|
10
11
|
applies_to Chemicalml::Cml::Role::Dictionary
|
|
11
12
|
def check_node(node, path)
|
|
12
|
-
|
|
13
13
|
entries = node.entries || []
|
|
14
14
|
ids = entries.map(&:id).compact
|
|
15
15
|
duplicates = ids.group_by { |x| x }.select { |_, v| v.length > 1 }.keys
|
|
@@ -8,6 +8,7 @@ module Chemicalml
|
|
|
8
8
|
# element. The schema allows it as a string; this constraint
|
|
9
9
|
# enforces presence.
|
|
10
10
|
class EntryMustContainDefinition < Chemicalml::Convention::Constraint::NodeConstraint
|
|
11
|
+
self.description = 'An `<entry>` MUST contain a single `definition` child element. The schema allows it as a string; this constraint enforces presence.'
|
|
11
12
|
applies_to Chemicalml::Cml::Role::DictionaryEntry
|
|
12
13
|
def check_node(node, path)
|
|
13
14
|
return [] unless node.definition.to_s.strip.empty?
|
|
@@ -7,9 +7,9 @@ module Chemicalml
|
|
|
7
7
|
# Every entry MUST have an `id` and a `term` attribute per the
|
|
8
8
|
# dictionary convention.
|
|
9
9
|
class EntryMustHaveIdAndTerm < Chemicalml::Convention::Constraint::NodeConstraint
|
|
10
|
+
self.description = 'Every entry MUST have an `id` and a `term` attribute per the dictionary convention.'
|
|
10
11
|
applies_to Chemicalml::Cml::Role::DictionaryEntry
|
|
11
12
|
def check_node(node, path)
|
|
12
|
-
|
|
13
13
|
violations = []
|
|
14
14
|
if node.id.to_s.empty?
|
|
15
15
|
violations << violation(path: path.join('/'),
|
|
@@ -9,6 +9,7 @@ module Chemicalml
|
|
|
9
9
|
# of a program) should reference `none` in the standard CML
|
|
10
10
|
# unitType dictionary.
|
|
11
11
|
class EntryMustHaveUnitType < Chemicalml::Convention::Constraint::NodeConstraint
|
|
12
|
+
self.description = 'An `<entry>` MUST have a `unitType` attribute. Entries describing concepts that should not have units (e.g. name of a program) should reference `none` in the standard CML'
|
|
12
13
|
applies_to Chemicalml::Cml::Role::DictionaryEntry
|
|
13
14
|
def check_node(node, path)
|
|
14
15
|
return [] unless node.unit_type.to_s.empty?
|