← Back to demo

Manufacturing-X Pipeline — Steel 316/4401

How stainless steel inspection data travels from an AAS 3.0 document to PMDCO-conformant RDF.

1. Source: AAS 3.0 Inspection Document

The Manufacturing-X dataspace exposes steel inspection data as AAS (Asset Administration Shell) 3.0 documents following the EN 10204 standard for metallic materials test reports. AAS 3.0 uses a hierarchical submodel tree with idShort identifiers and semantic IDs referencing IDTA (Industrial Digital Twin Association) submodel templates.

Unlike the Catena-X SAMM JSON, AAS encodes property semantics via external semantic IDs (e.g., https://admin-shell.io/idta/InspectionDocumentsOfSteelProducts/TensileStrengthMean/1/0) rather than field names. The structure is fundamentally incompatible with SAMM without a dedicated transformation.

{
  "assetAdministrationShells": [{ "idShort": "InspectionDocumentsOfSteelProductsAAS" }],
  "submodels": [{
    "idShort": "InspectionDocumentsOfSteelProducts",
    "submodelElements": [
      /* MechanicalTests — TensileTest__00__ sub-collection */
      {
        "idShort": "TensileStrengthMean",
        "semanticId": { "keys": [{
          "value": "https://admin-shell.io/idta/...TensileStrengthMean/1/0"
        }]},
        "value": "632", "modelType": "Property"
      },
      { "idShort": "YieldOrProofStrengthMean", "value": "276", "modelType": "Property" },
      { "idShort": "ElongationAfterFractureMean", "value": "60", "modelType": "Property" },
      /* ChemicalAnalysis sub-collection — 9 mass fractions with values */
      { "idShort": "MassFraction_C",  "value": "0.022", "modelType": "Property" },
      { "idShort": "MassFraction_Cr", "value": "16.9",  "modelType": "Property" },
      { "idShort": "MassFraction_Mn", "value": "1.51",  "modelType": "Property" },
      { "idShort": "MassFraction_Mo", "value": "2.01",  "modelType": "Property" },
      { "idShort": "MassFraction_N",  "value": "0.024", "modelType": "Property" },
      { "idShort": "MassFraction_Ni", "value": "10",    "modelType": "Property" },
      { "idShort": "MassFraction_P",  "value": "0.036", "modelType": "Property" },
      { "idShort": "MassFraction_S",  "value": "0.002", "modelType": "Property" },
      { "idShort": "MassFraction_Si", "value": "0.4",   "modelType": "Property" }
    ]
  }]
}
EN 10204 section codes, idShort references, and IDTA semantic IRIs — none of which align with the Catena-X SAMM keys or standard QUDT units.
View source file on data portal ↗

2. Step 1: AAS → RDF (py-aas-rdf + AAS2KG)

The AAS 3.0 JSON is first converted to RDF using py-aas-rdf, which produces AAS-conformant RDF triples stored in a pyoxigraph in-memory store. The resulting RDF faithfully represents the AAS structure (submodel elements, semantic IDs, display names) as linked data.

At this stage the RDF is "AAS/RDF" — the hierarchical AAS structure is preserved but not yet aligned with PMDCO. A subsequent SPARQL INSERT (the AAS2KG mapping) performs the PMDCO alignment in the next step.

The AAS2KG tool chain is developed by MI-Fraunhofer IWM. The steel inspection document pipeline is documented at: dataportal.material-digital.de/dataset/steel-inspection-document-mapro ↗

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

The AAS2KG mapping is a SPARQL INSERT that reads AAS/RDF from the staging graph and writes PMDCO-conformant output. Each IDTA semantic ID is resolved to a TTO (Taxonomy Thermodynamic Ontology) or PMDCO quality class, and numeric values are linked via OBI datum + QUDT QuantityValue patterns.

PREFIX aas:  <https://admin-shell.io/aas/3/0/>
PREFIX tto:  <https://w3id.org/pmd/tto/>
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/>

INSERT { GRAPH <urn:graph:mfgx> {
  # Component is a PMDCO Object
  ex:PLACEHOLDER_material a pmd:PMD_0000000, obo:BFO_0000040 ;
    rdfs:label ?materialNameValueFinal .

  # Tensile strength: TTO class + OBI datum chain
  ex:PLACEHOLDER_tensile_strength a tto:TTO_0000053 ;
    obo:RO_0000052 ex:PLACEHOLDER_material ;
    obo:IAO_0000417 ex:PLACEHOLDER_tensile_strength_svs .

  ex:PLACEHOLDER_tensile_strength_svs a obo:OBI_0001931 ;
    obo:OBI_0001938 ex:PLACEHOLDER_tensile_strength_value .

  ex:PLACEHOLDER_tensile_strength_value a qudt:QuantityValue ;
    qudt:unit unit:MegaPA ;
    qudt:numericValue ?tensileStrengthValueFinal .

  # Yield strength: TTO_0000009
  ex:PLACEHOLDER_yield_strength a tto:TTO_0000009 ; # yield strength
    obo:OBI_0001938 ex:PLACEHOLDER_yield_strength_value .
  ex:PLACEHOLDER_yield_strength_value qudt:numericValue ?yieldStrengthValueFinal ;
    qudt:unit unit:MegaPA .

  # Elongation at fracture: TTO_0000033
  ex:PLACEHOLDER_elongation a tto:TTO_0000033 ;
    obo:OBI_0001938 ex:PLACEHOLDER_elongation_value .
  ex:PLACEHOLDER_elongation_value qudt:numericValue ?elongationAfterFractureValueFinal ;
    qudt:unit unit:PERCENT .
} }
WHERE { GRAPH <urn:graph:mfgx-aas> {
  # Resolve AAS semanticId → property value
  OPTIONAL {
    ?tensileStrengthProp a aas:Property ;
        ns1:value ?tensileStrengthValue ;
        ns5:semanticId ?tensileStrengthSS .
    ?tensileStrengthSS ns3:keys ?tensileStrengthKey .
    ?tensileStrengthKey ns2:value
      "https://admin-shell.io/idta/…/TensileStrengthMean/1/0" .
  }
  BIND(COALESCE(?tensileStrengthValue, "N/A") AS ?tensileStrengthValueFinal)
  /* … analogous OPTIONAL blocks for yield strength (276) and elongation (60);
     chemical composition mass fractions (C=0.022, Cr=16.9, Mn=1.51, Mo=2.01,
     N=0.024, Ni=10, P=0.036, S=0.002, Si=0.4) are written to urn:graph:mfgx
     as pmd:PMD_0025997 fraction individuals linked via obo:OBI_0001937 … */
} }
View full SPARQL on data portal ↗

4. Output — Steel Properties as PMDCO Qualities

The INSERT writes into urn:graph:mfgx a graph where a material entity holds the steel qualities via obo:RO_0000086 — the same structural pattern as the Catena-X pipeline. Each quality is linked to an OBI measurement datum which carries a QUDT QuantityValue with qudt:numericValue. Because both pipelines land on this shared predicate chain, the cross-dataspace query can traverse both graphs with a single path — no UNION.

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

# Material entity (linked from component in assembly graph)
<http://www.example.org/#316-4401_material>
    rdfs:label "Steel 316/4401" ;
    obo:RO_0000086
      <…/tensile_strength_quality>,
      <…/yield_strength_quality>,
      <…/elon_af_quality> .

# Tensile strength quality — typed with TTO class
<…/tensile_strength_quality>
    a tto:TTO_0000053 ;              # tensile strength
    obo:IAO_0000417 <…/tensile_strength_datum> .

<…/tensile_strength_datum>
    a obo:OBI_0001931 ;
    obo:OBI_0001938 <…/tensile_strength_qv> .

<…/tensile_strength_qv>
    qudt:numericValue "632" .          # same predicate as Catena-X

# Yield strength: TTO_0000009
<…/yield_strength_qv> qudt:numericValue "276" .

# Elongation at fracture: TTO_0000033
<…/elon_af_qv> qudt:numericValue "60" .
View output TTL on data portal ↗

5. Round-trip verification

Because all values from the original AAS document are stored faithfully in urn:graph:mfgx-aas as AAS-ontology RDF, a SPARQL SELECT can reconstruct the source data directly from the graph — without consulting the original file. The demo includes a Manufacturing-X: retrieve source JSON query (KG Inspector panel) that traverses MechanicalTests and ChemicalAnalysis SubmodelElementCollection nodes and assembles the values back into JSON via SPARQL CONCAT aggregation:

# Reconstruct mechanical test results from AAS/RDF staging graph
SELECT (CONCAT('{"mechanicalTests":{', ?mechJson, '},"chemicalAnalysis":{', ?chemJson, '}}') AS ?json)
FROM <urn:graph:mfgx-aas>
WHERE {
  { SELECT (GROUP_CONCAT(CONCAT('"', ?idShort, '":', ?val) ; SEPARATOR=',') AS ?mechJson)
    WHERE { ?mech aasRf:idShort "MechanicalTests" ; aasSMC:value ?run .
            ?run aasSMC:value ?prop . ?prop aasRf:idShort ?idShort ; aasP:value ?val .
            FILTER(REGEX(?val, '^[0-9]')) } }
  { SELECT (GROUP_CONCAT(CONCAT('"', ?idShort, '":', ?val) ; SEPARATOR=',') AS ?chemJson)
    WHERE { ?chem aasRf:idShort "ChemicalAnalysis" ; aasSMC:value ?prop .
            ?prop aasRf:idShort ?idShort ; aasP:value ?val .
            FILTER(REGEX(?val, '^[0-9]')) } }
}

The reconstructed JSON is automatically asserted against the reference values extracted from inspectiondocument_316_4401_alloy.json, confirming that the AAS → RDF conversion preserves all numeric values without loss.