← Back to demo

Catena-X Pipeline — PA6GF30

How glass-fiber polyamide material data travels from a Catena-X SAMM aspect model to PMDCO-conformant RDF.

1. Source: SAMM Aspect Model

The Catena-X dataspace exposes material data as SAMM (Semantic Aspect Meta Model) aspect models. SAMM is Catena-X's framework for describing data schemas semantically — it specifies property names, units, and data types, but uses Catena-X-specific identifiers that have no direct mapping to cross-domain ontologies like PMDCO or BFO (Basic Formal Ontology) without explicit transformation.

The PA6GF30 (glass-fiber reinforced polyamide) data is retrieved via EDC (Eclipse Dataspace Connector) and arrives as a JSON document structured according to the io.catenax.material_data:1.0.0 aspect model.

{
  "materialInformation": {
    "materialName": "PA6GF30",
    "materialIdentifier": "Z1234"
  },
  "mechanicalProperty": {
    "impactStrength": 74,
    "youngsModulus": 9800,
    "strainAtBreak": 3,
    "stressAtBreak": 140,
    "flexuralStrength": 210,
    "flexuralModulus": 8600
  },
  "thermophysicalProperty": {
    "humidity": 2.1,
    "meltingTemperature": 223,
    "glassTransitionTemperature": 20,
    "waterAbsorption": 6.5,
    "linearThermalExpansionCoefficient": {
      "linearThermalExpansionCoefficientParallel": 0.0025,
      "linearThermalExpansionCoefficientTransverse": 0.0115
    }
  },
  "physicalProperty": { "density": 1530 },
  "pvt": [ /* 547 entries — { "temperature": 279.085, "specificVolume": 0.838…, "pressure": 10.0 }, … */ ]
}
View source file on data portal ↗

2. Step 1: JSON → RDF (YARRRML + RDFConverter)

The SAMM JSON is first converted to RDF using YARRRML (Yet Another RDF Mapping Language) rules processed by RDFConverter. YARRRML provides a human-friendly YAML syntax for R2RML-style mappings that transform JSON into RDF triples. The resulting intermediate RDF preserves the SAMM structure (property names, group hierarchy, units) but is now represented as linked data.

At this stage the RDF is "SAMM/RDF" — structurally equivalent to the JSON, but expressed as triples. PMDCO alignment has not yet occurred. The SAMM unit vocabulary (urn:samm:org.eclipse.esmf.samm:unit:2.2.0#megapascal) is not the same as QUDT (https://qudt.org/vocab/unit/MegaPA), and property IRIs are SAMM-specific.

Both files are loaded together into the staging graph urn:graph:catx-samm:

  • Instance data — catx-samm.ttl: the YARRRML-transformed measurement values
  • SAMM aspect model — catx-samm-model.ttl: defines each samm:Property, its samm:characteristic, and samm-c:unit — the schema the PMDCO Transform INSERT reads to identify property semantics and units

YARRRML mappings for this pipeline are maintained at: futurecarproduction.materialsdata.space/group/mappings ↗

The pipeline is verified by a round-trip query: a SPARQL SELECT over urn:graph:catx-samm reconstructs the original JSON sections via CONCAT aggregation and the result is asserted against the reference file material_data_test_pa6gf30.json. Run it from the KG Inspector panel ("Catena-X: retrieve source JSON").

3. Step 2: SAMM/RDF → PMDCO (SPARQL INSERT)

The core transformation is a SPARQL INSERT that reads from the SAMM/RDF graph and writes PMDCO-conformant triples into a new named graph. Each SAMM property is mapped to a PMDCO quality class, SAMM units are converted to QUDT units (with SI conversion factors where needed), and a standard PMDCO quality individual + OBI datum + QUDT QuantityValue chain is minted.

PREFIX samm:   <urn:samm:org.eclipse.esmf.samm:meta-model:2.2.0#>
PREFIX mat:    <urn:samm:io.catenax.material_data:1.0.0#>
PREFIX qudt:   <https://qudt.org/schema/qudt/>
PREFIX unit:   <https://qudt.org/vocab/unit/>
PREFIX obo:    <http://purl.obolibrary.org/obo/>
PREFIX pmd:    <https://w3id.org/pmd/co/>

INSERT { GRAPH <pmdco> {
  # Material entity (BFO:material entity)
  ?material a obo:BFO_0000040 ;
            rdfs:label ?matLabel .

  # Quality individual — typed with PMDco quality class
  ?quality a              ?qualityClass ;
           obo:RO_0000052 ?material ;       # characteristic of
           obo:IAO_0000417 ?datum .         # is quality measured as
  ?material obo:RO_0000086 ?quality .       # has quality

  # Measurement datum — scalar value specification (OBI)
  ?datum a               obo:OBI_0001931 ;
         obo:OBI_0001938  ?qv .             # has value specification

  # QuantityValue (QUDT)
  ?qv a                  qudt:QuantityValue ;
      qudt:unit          ?qdtUnit ;
      qudt:numericValue  ?convertedValue .
} }
WHERE {
  GRAPH ?dataGraph {
    ?dataEntity ?prop ?value .
    FILTER(isLiteral(?value))
    ?materialData a mat:MaterialData ;
                 ?groupProp ?dataEntity .
  }
  GRAPH ?schemaGraph {
    ?prop a samm:Property ;
          samm:characteristic ?char .
    ?char samm-c:unit ?sammUnit ;
          samm:dataType ?dtype .
    OPTIONAL { ?prop samm:preferredName ?propLabel .
               FILTER(LANG(?propLabel) = "en") }
  }
  FILTER(?dtype IN (xsd:float, xsd:double, xsd:decimal,
                     xsd:integer, xsd:int, xsd:long))

  # SAMM unit → QUDT unit + SI conversion factor
  VALUES (?sammUnit ?qdtUnit ?factor) {
    ( sunit:megapascal              unit:MegaPA            1    )
    ( sunit:percent                 unit:PERCENT           1    )
    ( sunit:degreeCelsius           unit:DEG_C             1    )
    ( sunit:kilogramPerCubicMetre   unit:KiloGM-PER-M3     1    )
    ( mat:kiloJoulePerSquareMeter   unit:J-PER-M2          1000 ) # kJ/m² → J/m²
  }
  # SAMM property → PMDco quality class
  VALUES (?prop ?qualityClass) {
    ( mat:stressAtBreak    pmd:PMD_0000952 ) # strength
    ( mat:youngsModulus    pmd:PMD_0000618 ) # elastic modulus
    ( mat:impactStrength   pmd:PMD_0000518 ) # impact
    ( mat:meltingTemperature pmd:PMD_0000851 ) # melting point
  }
  BIND(xsd:decimal(?value) * ?factor AS ?convertedValue)
  BIND(IRI(CONCAT(STR(?materialData), "-material")) AS ?material)
  BIND(IRI(CONCAT(STR(?dataEntity), "-qual-",  STRAFTER(STR(?prop), "#"))) AS ?quality)
  BIND(IRI(CONCAT(STR(?dataEntity), "-datum-", STRAFTER(STR(?prop), "#"))) AS ?datum)
  BIND(IRI(CONCAT(STR(?dataEntity), "-qv-",    STRAFTER(STR(?prop), "#"))) AS ?qv)
}
View full SPARQL on data portal ↗

4. Output — PMDCO-Conformant RDF

The INSERT produces PMDCO quality individuals with QUDT-typed quantity values. Each property from the SAMM JSON is now represented as a quality individual typed with the appropriate PMDCO or TTO (Thermodynamics and Transport Ontology) class, linked to an OBI scalar value specification holding the numeric value and QUDT unit.

@prefix pmd:  <https://w3id.org/pmd/co/> .
@prefix obo:  <http://purl.obolibrary.org/obo/> .
@prefix qudt: <https://qudt.org/schema/qudt/> .
@prefix unit: <https://qudt.org/vocab/unit/> .

@prefix catx: <https://pmdx.materials-data.space/catx/> .

# Material entity
catx:MaterialData_Z1234-material
    a obo:BFO_0000040 ;
    rdfs:label "PA6GF30 (Z1234)" .

# Stress at break quality
catx:MechanicalProperty_210_9800-qual-stressAtBreak
    a pmd:PMD_0000952 ;           # strength
    obo:RO_0000052 catx:MaterialData_Z1234-material ;
    obo:IAO_0000417 catx:MechanicalProperty_210_9800-datum-stressAtBreak .

# Datum + quantity value
catx:MechanicalProperty_210_9800-datum-stressAtBreak
    a obo:OBI_0001931 ;
    obo:OBI_0001938 catx:MechanicalProperty_210_9800-qv-stressAtBreak .

catx:MechanicalProperty_210_9800-qv-stressAtBreak
    a qudt:QuantityValue ;
    qudt:unit unit:MegaPA ;
    qudt:numericValue 140 .

# Impact strength (with kJ/m² → J/m² unit conversion)
<…-qv-impactStrength>
    qudt:unit unit:J-PER-M2 ;
    qudt:numericValue 74000 .
View output TTL on data portal ↗