diff --git a/docs/about.md b/docs/about.md
index b2c4bd17f..b95dbf738 100644
--- a/docs/about.md
+++ b/docs/about.md
@@ -1,14 +1,14 @@
-# About CatCore
-Robust data-sharing guidelines are essential in catalysis research to guarantee high-quality metadata, reproducibility, and the sustained progress of digital catalysis. To establish community-accepted guidelines for reporting metadata in this field, CatCore (an initiative under NFDI4Cat) specifies the minimum information that go beyond the conventional field-independent metadata, and should be reported with the catalysis research data. This guideline should help users to handle and standarise data in this versatile research field based on the FAIR principle (F-indable, A-ccessible, I-nteroperable, R-eusable). Integration of CatCore into data repositories ensures the availability of high-quality metadata and facilitates efficient access to and querying of published datasets.
-The terminology employed in CatCore is based on Voc4Cat (developed under NFDI4Cat), which supports standardized semantic representation and advances ontology development efforts. Terms not yet covered by Voc4Cat are provisionally defined within the model and incorporated as the vocabulary is updated. Structurally, the model consists of two parts: “Inner CatCore” and “Expanded CatCore”. Within these layers, data fields are organized hierarchically, following a parent–child relationship. The inner CatCore describes the most fundamental metadata which is mandatory to describe the research on the most general level with the goal of facilitating a categorization of the research data and help researchers to make their data findable. The expanded CatCore contains the data classes 'Synthesis', 'Reaction', 'Characterization' and 'Simulation'. The data fields are classified as “Mandatory,” “Recommended,” and “Optional” to reflect their relative priority. This classification helps users identify the minimum required metadata necessary to ensure data quality, while also allowing the inclusion of additional information that, although not mandatory, further enhances the value and usability of the data. Moreover, this prioritization facilitates the efficient handling and management of the large volumes of metadata generated by experimental devices and computation.
-The CatCore model is a “living organism” that evolves through user feedback on the addition, removal, and modification of data fields, for which provisions are provided on this webpage through the “Submit Term Feedback” button. All feedback and suggestions are reviewed by the CatCore development team and incorporated as appropriate based on their relevance and impact.
+# About CoreMeta4Cat
+Robust data-sharing guidelines are essential in catalysis research to guarantee high-quality metadata, reproducibility, and the sustained progress of digital catalysis. To establish community-accepted guidelines for reporting metadata in this field, CoreMeta4Cat (an initiative under NFDI4Cat) specifies the minimum information that go beyond the conventional field-independent metadata, and should be reported with the catalysis research data. This guideline should help users to handle and standarise data in this versatile research field based on the FAIR principle (F-indable, A-ccessible, I-nteroperable, R-eusable). Integration of CoreMeta4Cat into data repositories ensures the availability of high-quality metadata and facilitates efficient access to and querying of published datasets.
+The terminology employed in CoreMeta4Cat is based on Voc4Cat (developed under NFDI4Cat), which supports standardized semantic representation and advances ontology development efforts. Terms not yet covered by Voc4Cat are provisionally defined within the model and incorporated as the vocabulary is updated. Structurally, the model consists of two parts: “Inner CoreMeta4Cat” and “Expanded CoreMeta4Cat”. Within these layers, data fields are organized hierarchically, following a parent–child relationship. The inner CoreMeta4Cat describes the most fundamental metadata which is mandatory to describe the research on the most general level with the goal of facilitating a categorization of the research data and help researchers to make their data findable. The expanded CoreMeta4Cat contains the data classes 'Synthesis', 'Reaction', 'Characterization' and 'Simulation'. The data fields are classified as “Mandatory,” “Recommended,” and “Optional” to reflect their relative priority. This classification helps users identify the minimum required metadata necessary to ensure data quality, while also allowing the inclusion of additional information that, although not mandatory, further enhances the value and usability of the data. Moreover, this prioritization facilitates the efficient handling and management of the large volumes of metadata generated by experimental devices and computation.
+The CoreMeta4Cat model is a “living organism” that evolves through user feedback on the addition, removal, and modification of data fields, for which provisions are provided on this webpage through the “Submit Term Feedback” button. All feedback and suggestions are reviewed by the CoreMeta4Cat development team and incorporated as appropriate based on their relevance and impact.
-Inner CatCore: The inner CatCore defines the most fundamental metadata, which are mandatory for describing research at a general level. Its goal is to facilitate consistent categorization of research data and assist researchers in making their datasets more easily findable. The data classes in the inner CatCore consists of Catalysis Research Field (Mandatory), Reaction type (Mandatory), Active Site (Recommended) and Identifier (Recommended).
+Inner CoreMeta4Cat: The inner CoreMeta4Cat defines the most fundamental metadata, which are mandatory for describing research at a general level. Its goal is to facilitate consistent categorization of research data and assist researchers in making their datasets more easily findable. The data classes in the inner CoreMeta4Cat consists of Catalysis Research Field (Mandatory), Reaction type (Mandatory), Active Site (Recommended) and Identifier (Recommended).
Catalysis Research Field: This section describes the different types of catalysis, including homogeneous, heterogeneous, electrocatalysis, and hybrid catalysis. It also provides provisions for specifying other types of catalysis that do not fall within these categories.
Reaction type: The catalytic reaction under investigation (examples: hydrogenation, oxidation, hydroformylation, etc.)
Active Site: It is recommended to specify the primary species in the catalyst responsible for catalytic activity. The expected value for this field is a text entry identifying a molecule, element, or other relevant species, with the option to provide multiple entries if applicable.
diff --git a/docs/index.md b/docs/index.md
index 3fdc01fda..990d819ea 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -1,8 +1,19 @@
-# CatCore
+# CoreMeta4Cat
-Catcore is a metadata collection for catalysis related research, which is intended to be developed into several schema's, such that we can harmonize Metadata representation of various research topics int the domain of catalysis.
+Robust data-sharing guidelines are essential in catalysis research to guarantee high-quality metadata, reproducibility, and the sustained progress of digital catalysis. To establish community-accepted guidelines for reporting metadata in this field, CoreMeta4Cat (an initiative under NFDI4Cat) specifies the minimum information that go beyond the conventional field-independent metadata, and should be reported with the catalysis research data. This guideline should help users to handle and standarise data in this versatile research field based on the FAIR principle (F-indable, A-ccessible, I-nteroperable, R-eusable). Integration of CoreMeta4Cat into data repositories ensures the availability of high-quality metadata and facilitates efficient access to and querying of published datasets.
+The terminology employed in CoreMeta4Cat is based on Voc4Cat (developed under NFDI4Cat), which supports standardized semantic representation and advances ontology development efforts. Terms not yet covered by Voc4Cat are provisionally defined within the model and incorporated as the vocabulary is updated. Structurally, the model consists of two parts: “Inner CoreMeta4Cat” and “Expanded CoreMeta4Cat”. Within these layers, data fields are organized hierarchically, following a parent–child relationship. The inner CoreMeta4Cat describes the most fundamental metadata which is mandatory to describe the research on the most general level with the goal of facilitating a categorization of the research data and help researchers to make their data findable. The expanded CoreMeta4Cat contains the data classes 'Synthesis', 'Reaction', 'Characterization' and 'Simulation'. The data fields are classified as “Mandatory,” “Recommended,” and “Optional” to reflect their relative priority. This classification helps users identify the minimum required metadata necessary to ensure data quality, while also allowing the inclusion of additional information that, although not mandatory, further enhances the value and usability of the data. Moreover, this prioritization facilitates the efficient handling and management of the large volumes of metadata generated by experimental devices and computation.
+The CoreMeta4Cat model is a “living organism” that evolves through user feedback on the addition, removal, and modification of data fields, for which provisions are provided on this webpage through the “Submit Term Feedback” button. All feedback and suggestions are reviewed by the CoreMeta4Cat development team and incorporated as appropriate based on their relevance and impact.
-As bepicted below, CatCore is devided into four major branches, Reaction, Synthesis, Characterisation and Simulation, each described with respective metadata terminology.
+
+
+
+
+
+Inner CoreMeta4Cat: The inner CoreMeta4Cat defines the most fundamental metadata, which are mandatory for describing research at a general level. Its goal is to facilitate consistent categorization of research data and assist researchers in making their datasets more easily findable. The data classes in the inner CoreMeta4Cat consists of Catalysis Research Field (Mandatory), Reaction type (Mandatory), Active Site (Recommended) and Identifier (Recommended).
+Catalysis Research Field: This section describes the different types of catalysis, including homogeneous, heterogeneous, electrocatalysis, and hybrid catalysis. It also provides provisions for specifying other types of catalysis that do not fall within these categories.
+Reaction type: The catalytic reaction under investigation (examples: hydrogenation, oxidation, hydroformylation, etc.)
+Active Site: It is recommended to specify the primary species in the catalyst responsible for catalytic activity. The expected value for this field is a text entry identifying a molecule, element, or other relevant species, with the option to provide multiple entries if applicable.
+Identifier: It is the identification of the catalyst through user defined labels.
diff --git a/docs/overview.md b/docs/overview.md
index e9f3fd610..44d346fdf 100644
--- a/docs/overview.md
+++ b/docs/overview.md
@@ -19,7 +19,7 @@ description: Comprehensive Metadata Guidelines for Catalysis Research Data
Eight reactor design types, flattened operation parameter slots, and product identification links.
-- :material-cpu-64-bit: **Simulation**
+- :octicons-cpu-16: **Simulation**
Four computational methods (DFT, MD, Microkinetics, Monte Carlo) with 12 calculated property classes.
diff --git a/mkdocs.yml b/mkdocs.yml
index bca75cc42..68b40cbcc 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -70,3 +70,6 @@ markdown_extensions:
- md_in_html
- admonition
- attr_list
+ - pymdownx.emoji:
+ emoji_index: !!python/name:material.extensions.emoji.twemoji
+ emoji_generator: !!python/name:material.extensions.emoji.to_svg
diff --git a/src/catcore/datamodel/catcore.py b/src/catcore/datamodel/catcore.py
index 23e98fc46..51f940969 100644
--- a/src/catcore/datamodel/catcore.py
+++ b/src/catcore/datamodel/catcore.py
@@ -1,5 +1,5 @@
# Auto generated from catcore.yaml by pythongen.py version: 0.0.1
-# Generation date: 2026-03-04T09:35:08
+# Generation date: 2026-03-04T22:31:48
# Schema: catcore-metadata
#
# id: https://w3id.org/nfdi4cat/catcore
diff --git a/tests/data/valid/Characterization-001.yaml b/tests/data/valid/Characterization-001.yaml
deleted file mode 100644
index 830434528..000000000
--- a/tests/data/valid/Characterization-001.yaml
+++ /dev/null
@@ -1,14 +0,0 @@
----
-# Complete Characterization Instance
-# This represents a Characterization object as defined in the schema
-
-identifier: "CHAR_001_Pt_Al2O3"
-equipment: ["Bruker D8 Advance diffractometer"]
-sample_state: ["powder"]
-sample_description: ["5 wt% Pt/Al2O3 catalyst after calcination at 450C"]
-detector_type: ["Lynxeye detector"]
-sample_preparation: ["pressed into sample holder without binder"]
-sample_pretreatment: ["calcined at 450C for 4 hours"]
-
-characterization_technique:
- - identifier: "CHAR_TECH_001"
\ No newline at end of file
diff --git a/tests/data/valid/Simulation-001.yaml b/tests/data/valid/Simulation-001.yaml
deleted file mode 100644
index 52d7fa8fb..000000000
--- a/tests/data/valid/Simulation-001.yaml
+++ /dev/null
@@ -1,12 +0,0 @@
----
-# Complete Simulation Instance
-# This represents a Simulation object as defined in the schema
-
-identifier: "SIM_001_CO_Pt111"
-software_package: ["VASP 6.3.0"]
-
-simulation_method:
- - identifier: "SIM_METHOD_001"
-
-calculated_property:
- - identifier: "CALC_PROP_001"
diff --git a/tests/data/valid/Synthesis-001.yaml b/tests/data/valid/Synthesis-001.yaml
index bee3c97ac..cc3215903 100644
--- a/tests/data/valid/Synthesis-001.yaml
+++ b/tests/data/valid/Synthesis-001.yaml
@@ -1,20 +1,30 @@
---
-# Complete Synthesis Instance
-# This represents a Synthesis object as defined in the schema
+# Synthesis-001 -- Incipient wetness impregnation of 5 wt% Pt/Al2O3
+# Target class: Synthesis
+#
+# NOTE: realized_plan range is PreparationMethod (abstract, no domain slots).
+# Domain synthesis parameters that live on catcore_common ARE accepted on Synthesis directly.
+# realized_plan: title/description only — the loader cannot dispatch to Impregnation subclass.
+id: "catcore:SYNTH_001_Pt_Al2O3"
+nominal_composition:
+ - "5 wt% Pt/Al2O3"
+catalyst_measured_properties:
+ - "BET surface area: 185 m2/g, Pt particle size: 2.3 nm (TEM), Pt loading: 4.8 wt% (ICP-AES)"
+storage_conditions:
+ - "stored in desiccator under argon atmosphere at room temperature"
+support:
+ - "gamma-Al2O3, Sasol Puralox, 200 m2/g"
+solvent:
+ - "deionized water"
+sample_pretreatment:
+ - "reduction in H2 at 400 deg C for 2 hours prior to catalytic testing"
+had_input_entity:
+ - id: "catcore:PREC_001_H2PtCl6"
+ title: "chloroplatinic acid hexahydrate"
+ precursor_quantity:
+ - 0.0485
-
-identifier: "SYNTH_001_Pt_Al2O3"
-nominal_composition: "5 wt% Pt/Al2O3"
-catalyst_measured_properties: "BET surface area: 185 m²/g, Pt particle size: 2.3 nm (TEM), Pt loading: 4.8 wt% (ICP-AES)"
-storage_conditions: ["stored in desiccator under argon atmosphere at room temperature"]
-support: ["γ-Al2O3, Sasol Puralox, 200 m²/g"]
-solvent: ["deionized water", "ethanol"]
-sample_pretreatment: ["reduction in H2 at 400°C for 2 hours prior to catalytic testing"]
-
-precursor:
- - identifier: "PREC_001"
- precursor_quantity: [0.0485]
-
-preparation_method:
- - identifier: "PREP_001"
\ No newline at end of file
+realized_plan:
+ title: "incipient wetness impregnation"
+ description: "incipient_wetness, 25 deg C, 12 h"
diff --git a/tests/test_data.py b/tests/test_data.py
index 6b31c5e55..0d4ca5c57 100644
--- a/tests/test_data.py
+++ b/tests/test_data.py
@@ -1,11 +1,10 @@
+"""Data test."""
import os
import glob
import pytest
-import yaml
from pathlib import Path
-from typing import Dict, Any, Union, List
-from catcore.datamodel import catcore
+import src.catcore.datamodel.catcore
from linkml_runtime.loaders import yaml_loader
DATA_DIR_VALID = Path(__file__).parent / "data" / "valid"
@@ -14,190 +13,14 @@
VALID_EXAMPLE_FILES = glob.glob(os.path.join(DATA_DIR_VALID, '*.yaml'))
INVALID_EXAMPLE_FILES = glob.glob(os.path.join(DATA_DIR_INVALID, '*.yaml'))
-# Mapping from identifier patterns or context to concrete class names
-CHARACTERIZATION_TECHNIQUE_MAP = {
- 'xray_source': {
- 'Cu Kalpha': 'PowderXRD',
- 'Al Kalpha': 'XPS',
- },
- 'adsorbate_gas': 'BET',
- 'reducing_gas_composition': 'TPR',
- 'oxidizing_gas_composition': 'TPO',
- 'excitation_laser_wavelength': 'RamanSpectroscopy',
- 'minimum_wavenumber': 'InfraredSpectroscopy',
- 'element_analyzed': 'XRayAbsorptionSpectroscopy',
- 'nucleus': 'NMRSpectroscopy',
- 'gun_type': 'TransmissionElectronMicroscopy',
- 'image_resolution': 'ScanningElectronMicroscopy',
- 'initial_temperature': 'Thermogravimetry',
- 'combustion_temperature': 'ElementalAnalysis',
- 'minimum_wavelength': 'UVVisSpectroscopy',
- 'adsorption_gas': 'DRIFTS',
- 'scan_rate': 'CyclicVoltammetry',
- 'light_wavelength': 'DynamicLightScattering',
- 'spray_voltage': 'ESI_MS',
- 'excitation_wavelength': 'PhotoluminescenceSpectroscopy',
- 'lifetime_fitting_model': 'PhotoluminescenceLifetime',
- 'eluent': 'SizeExclusionChromatography',
- 'gradient_program': 'HPLC_MS',
- 'primary_energy': 'EDX',
- 'electrode_configuration': 'ConductivityMeasurement',
-}
-
-PREPARATION_METHOD_MAP = {
- 'impregnation_type': 'Impregnation',
- 'precipitating_agent': 'CoPrecipitation',
- 'hydrolysis_ratio': 'SolGel',
- 'filling_volume': 'Solvothermal',
- 'plasma_type': 'PlasmaAssisted',
- 'fuel': 'CombustionSynthesis',
- 'substrate': 'AtomicLayerDeposition',
- 'microwave_frequency': 'MicrowaveAssisted',
- 'sonication_power': 'SonochemicalSynthesis',
- 'flame_type': 'FlameSprayPyrolysis',
- 'ball_material': 'MechanochemicalSynthesis',
- 'reaction_vessel': 'MolecularSynthesis',
-}
-
-SIMULATION_METHOD_MAP = {
- 'exchange_correlation_functional': 'DFT',
- 'force_field': 'MolecularDynamics',
- 'rate_constants': 'Microkinetics',
- 'interaction_potential': 'MonteCarlo',
-}
-
-CALCULATED_PROPERTY_MAP = {
- 'formation_energy': 'ThermodynamicStability',
- 'piezoelectric_tensor': 'Piezoelectricity',
- 'elastic_tensor': 'ElasticConstants',
- 'surface_energy': 'Surfaces',
- 'band_path': 'ElectronicStructure',
- 'polarization_direction': 'Ferroelectrics',
- 'direct_indirect': 'BandGap',
- 'material_composition': 'DielectricTensors',
- 'force_constant_method': 'PhononDispersion',
- 'fit_method': 'EquationsOfState',
- 'ph_range': 'AqueousStability',
- 'grain_boundary_plane': 'GrainBoundaries',
-}
-
-REACTOR_DESIGN_MAP = {
- 'gas_distributor_type': 'FluidizedBedReactor',
-}
-
-# Default classes for abstract types when no specific fields are found
-DEFAULT_CLASSES = {
- 'reactor_design_type': 'FixedBedReactor',
- 'product_identification_method': 'GCMS',
-}
-
-
-def infer_class_type(data: Dict[str, Any], type_map: Dict[str, Any], default_class: str = None) -> str:
- """Infer the concrete class type based on present fields."""
- for key, class_name in type_map.items():
- if key in data:
- if isinstance(class_name, dict):
- # Need to check value
- for value_pattern, cn in class_name.items():
- if value_pattern in str(data[key]):
- return cn
- else:
- return class_name
-
- # Return default class if no specific fields found
- return default_class
-
-
-def instantiate_polymorphic_objects(data: Union[Dict, List], parent_key: str = None) -> Union[Dict, List]:
- """Recursively instantiate concrete classes for polymorphic fields."""
- if isinstance(data, list):
- return [instantiate_polymorphic_objects(item, parent_key) for item in data]
-
- if not isinstance(data, dict):
- return data
-
- # Check for explicit type hint (both 'type' and '@type' for LinkML compatibility)
- explicit_type = data.get('type') or data.get('@type')
-
- # Recursively process nested structures first
- result = {}
- for key, value in data.items():
- if key in ('type', '@type'): # Skip the type hint fields
- continue
- result[key] = instantiate_polymorphic_objects(value, key)
-
- # Now handle polymorphic instantiation for specific keys
- if parent_key == 'characterization_technique':
- class_name = explicit_type or infer_class_type(result, CHARACTERIZATION_TECHNIQUE_MAP)
- if class_name:
- cls = getattr(catcore, class_name)
- return cls(**result)
-
- elif parent_key == 'preparation_method':
- class_name = explicit_type or infer_class_type(result, PREPARATION_METHOD_MAP)
- if class_name:
- cls = getattr(catcore, class_name)
- return cls(**result)
-
- elif parent_key == 'simulation_method':
- class_name = explicit_type or infer_class_type(result, SIMULATION_METHOD_MAP)
- if class_name:
- cls = getattr(catcore, class_name)
- return cls(**result)
-
- elif parent_key == 'calculated_property':
- class_name = explicit_type or infer_class_type(result, CALCULATED_PROPERTY_MAP)
- if class_name:
- cls = getattr(catcore, class_name)
- return cls(**result)
-
- elif parent_key == 'reactor_design_type':
- class_name = explicit_type or infer_class_type(result, REACTOR_DESIGN_MAP,
- DEFAULT_CLASSES.get('reactor_design_type'))
- if class_name:
- cls = getattr(catcore, class_name)
- return cls(**result)
-
- elif parent_key == 'product_identification_method':
- # For now, use GCMS as default if no specific fields found
- class_name = explicit_type or DEFAULT_CLASSES.get('product_identification_method')
- if class_name:
- cls = getattr(catcore, class_name)
- return cls(**result)
-
- return result
-
@pytest.mark.parametrize("filepath", VALID_EXAMPLE_FILES)
def test_valid_data_files(filepath):
"""Test loading of all valid data files."""
target_class_name = Path(filepath).stem.split("-")[0]
- tgt_class = getattr(catcore, target_class_name)
-
- # Load the YAML content
- with open(filepath, 'r') as f:
- data_dict = yaml.safe_load(f)
-
- # Handle polymorphic fields by instantiating concrete classes
- poly_fields = [
- 'characterization_technique',
- 'preparation_method',
- 'simulation_method',
- 'calculated_property',
- 'reactor_design_type',
- 'product_identification_method',
- 'operation_parameters',
- 'precursor'
- ]
-
- for poly_field in poly_fields:
- if poly_field in data_dict and data_dict[poly_field]:
- data_dict[poly_field] = instantiate_polymorphic_objects(
- data_dict[poly_field],
- poly_field
- )
-
- # Instantiate the target class
- obj = tgt_class(**data_dict)
-
+ tgt_class = getattr(
+ src.catcore.datamodel.catcore,
+ target_class_name,
+ )
+ obj = yaml_loader.load(filepath, target_class=tgt_class)
assert obj