Article

LinkML ↔ ASM Interoperability Analysis

A technical analysis of interoperability between LinkML and ASM, defining a canonical mapping subset and identifying where semantic gaps make translation irreversible.

Abstract visualization of LinkML and ASM model interoperability

1. Executive Summary

This document analyzes the interoperability between LinkML and ASM (Allotrope Simple Model) - two data modeling frameworks with overlapping goals but fundamentally different architectures. It defines a common canonical subset that enables bidirectional mapping and enumerates hard gaps where information is irreversibly lost in translation.

LinkML is a technology-neutral, YAML-authored data modeling language that generates downstream artifacts (JSON-Schema, SHACL, OWL, Python dataclasses, SQL DDL, etc.). It targets general-purpose data modeling with semantic hooks.

ASM is a data modeling framework for scientific and operational data, designed to support GxP-regulated environments but not limited to them. It combines JSON Schema (Draft 2020-12) with custom $asm.* extension keywords, RDF/OWL vocabularies for semantic typing, and QUDT for units of measurement. ASM instance documents are plain JSON - not JSON-LD, not RDF.

Dimension

LinkML

ASM

Primary audience

Data modelers, ontologists, developers

Life sciences, manufacturing, GxP-regulated industries

Schema language

YAML (custom metamodel)

JSON Schema 2020-12 + $asm.* extensions

Semantic layer

Optional (class_uri, slot_uri, mappings)

Required (RDF/OWL vocabulary)

Instance format

JSON, YAML, CSV, RDF (multi-target)

JSON (normative); any format representing the JSON metamodel (YAML, TOON, etc.) is usable in principle

Composition model

Import chain (named dependency DAG)

Manifest root declaration + implicit $ref DAG

Validation strategy

Single schema (generated from model)

Two-layer: JSON Schema + vocabulary resolution

Unit system

Annotation metadata (unit: slot)

Validated type system (QUDT symbol → IRI mapping)


2. Framework Profiles

2.1 LinkML

2.1.1 Core Metamodel Elements

Element

Purpose

Key Properties

SchemaDefinition

Top-level container

id (IRI), nameprefixesimportsdefault_rangeclassesslotstypesenumssubsets

ClassDefinition

Entity template (≈ table, JSON object type)

is_amixinsslotsattributesslot_usageabstractmixinclass_uriunique_keysrulestree_root

SlotDefinition

Field/property (≈ column, JSON key)

rangemultivaluedrequiredrecommendedidentifierminimum_valuemaximum_valuepatternslot_uriinverseifabsentany_of

TypeDefinition

Scalar type extending XSD

typeofuri (XSD datatype), base (Python type)

EnumDefinition

Controlled vocabulary

permissible_values (with meaningdescription), reachable_from (dynamic enums)

SubsetDefinition

Organizational grouping

Tag-based; no runtime semantics

2.1.2 Inheritance Model

  • Single is_a - forms a strict tree; slots propagate down
  • Multiple mixins - cross-cutting concerns; homeomorphic rule (mixin → mixinnon-mixin → non-mixin)
  • slot_usage - per-class monotonic refinement of inherited slots (can narrow range, add constraints; cannot widen)
  • abstract - prevents direct instantiation
  • Materialization - linkml generator can flatten all inherited slots into leaf classes

2.1.3 Slot System

Feature

Description

Range

Class, Type, Enum, linkml:Any, or boolean combination (any_ofall_ofnone_ofexactly_one_of)

Cardinality

requiredmultivaluedminimum_cardinalitymaximum_cardinalityexact_cardinality

Identity

identifier: true (primary key), key: true (alternate key)

Default values

ifabsent with typed syntax: string(...)int(...)float(...)True/False

Inlining

inlinedinlined_as_listinlined_as_dict - controls JSON serialization of object references

Logical properties

transitivesymmetricantisymmetricreflexivelocally_reflexive

Inverse

inverse names the reverse relationship

Refinement

slot_usage narrows constraints monotonically per class

2.1.4 Type System

Built-in types wrapping XSD:

LinkML Type

XSD

Python

JSON

string

xsd:string

str

string

integer

xsd:integer

int

integer

float

xsd:float

float

number

double

xsd:double

float

number

decimal

xsd:decimal

Decimal

number

boolean

xsd:boolean

bool

boolean

date

xsd:date

date

string

datetime

xsd:dateTime

datetime

string

time

xsd:time

time

string

uri

xsd:anyURI

URI

string

curie

-

Curie

string

uriorcurie

-

URIorCURIE

string

nodeidentifier

-

NodeIdentifier

string

Custom types extend built-ins via typeof.

2.1.5 Enumerations

enums:
  SampleRoleType:
    permissible_values:
      CONTROL:
        description: A control sample
        meaning: OBI:0000070
      STANDARD:
        description: A reference standard
        meaning: OBI:0000938
  • Static permissible values with optional meaning (ontology CURIE)
  • Dynamic enums via reachable_from (query ontology branch at schema-build time)
  • Enum values can have descriptions, aliases, annotations

2.1.6 Arrays (NDArray)

classes:
  SpectralData:
    attributes:
      intensities:
        range: float
        array:
          dimensions:
            - alias: wavelength
              minimum_cardinality: 1
            - alias: time_point
          minimum_number_dimensions: 1
          maximum_number_dimensions: 3
  • Shape constraints: min/max/exact dimensions, per-dimension cardinality
  • Dtype constraint via slot range
  • Integration: numpy, dask, zarr, HDF5, video files (via numpydantic)
  • No per-dimension semantic metadata (units, scale, concept)

2.1.7 Constraints and Rules

Mechanism

Scope

Example

pattern

Slot value regex

pattern: "^[A-Z]{2}\\d{4}$"

structured_pattern

Reusable sub-patterns

syntax: "{float} {unit.length}"

minimum_value / maximum_value

Numeric bounds

minimum_value: 0maximum_value: 999

unique_keys

Compound uniqueness

Multiple slots forming a unique tuple

rules

If-then logic

preconditions → postconditions on slot values

Boolean combinators

Slot-level

any_ofall_ofnone_ofexactly_one_of

equals_expression

Computed/derived values

"{age_in_months} / 12"

string_serialization

Derived string from other slots

"{first} {last}"

2.1.8 Semantic Layer

  • class_uri / slot_uri - map elements to ontology IRIs
  • prefixes - CURIE prefix declarations
  • mappings - exact_mappingsclose_mappingsrelated_mappingsnarrow_mappingsbroad_mappings
  • meaning on enum values - ontology term CURIE
  • JSON-LD context generation - automatic from schema
  • Generators - SHACL, ShEx, OWL export

2.1.9 Modularity

  • imports - dependency chain (local files or remote URIs)
  • linkml:types - standard type library
  • Subsets - tag elements for organizational purposes (no runtime effect)
  • Programmatic manipulation - SchemaView API for traversal and derivation

2.1.10 Metadata and Annotations

Slot

Purpose

description

Human-readable description (markdown OK)

aliases

Alternative names

structured_aliases

With predicate, source, language

deprecated

Deprecation notice

comments

Author notes

notes

Implementation notes

see_also

Reference URIs

annotations

Arbitrary key-value pairs (extensible)

unit

UCUM/QUDT/IEC61360 annotation

instantiates

Metamodel extension reference

2.1.11 Generators (Output Targets)

JSON-Schema, SHACL, ShEx, OWL, Python dataclasses, Pydantic, SQL DDL, SQL Alchemy, TypeScript, Java, GraphQL, Protobuf, Markdown documentation, CSV/TSV data dictionaries.


2.2 ASM (Allotrope Simple Model)

2.2.1 Architecture Overview

ASM is a two-layer validation system:

Key architectural principle: ASM is NOT JSON-LD. Property names like @type and @id resemble JSON-LD but have no JSON-LD processing semantics. There is no @context, no expansion/compaction, no graph normalization.

2.2.2 Schema Portfolio

Schema

Content

core.schema

Primitive value types, XSD mappings, polymorphic value wrappers

manifest.schema

Document-level metadata: @id@typevocabulary[]json-schemas[]shapes[]

hierarchy.schema

Reusable document structure patterns (aggregate, indexed, value, quantity, class, binary datum)

cube.schema

Multidimensional scientific data (W3C Data Cube adapted)

units.schema

Auto-generated unit symbol catalog (QUDT + Allotrope extensions); located under qudt/REC/

<domain>.schema

Domain-specific models (e.g., uv-vis.schemaqpcr.schemahplc.schemaelectronic-lab-notebook.schema)

2.2.3 Value Type System

ASM uses polymorphic value types - each value can appear in simple literal form OR as a typed object:

Type

Simple Form

Typed Object Form

tStringValue

"text"

{"@type": "sample identifier", "value": "text"}

tDoubleValue

3.14

{"@type": "peak area", "value": 3.14}

tIntegerValue

42

{"@type": "cycle count", "value": 42}

tBooleanValue

true

{"@type": "detection flag", "value": true}

tDateTimeValue

"2026-06-17T10:30:00Z"

{"@type": "measurement time", "value": "..."}

Additional structured types:

Type

Structure

Purpose

tQuantityValue

{value: number, unit: string}

Physical measurement with SI unit

tRangeValue

{minInclusive?, maxInclusive?, minExclusive?, maxExclusive?, unit?}

Interval specification with mutual-exclusion constraints

tClass

"control sample role"

Ontology class label (resolved via skos:prefLabel)

tUnit

"µg/mL"

Unit symbol mapped to QUDT IRI

tNamed

Named individual with namespace

Identity reference

tReference

JSON Pointer or IRI

Cross-document reference

The polymorphic dual form is a fundamental ASM design decision - it allows the same field to carry semantic type information when needed while remaining lightweight when context is sufficient.

2.2.4 Document Pattern System ($asm.pattern)

Every structural element in an ASM document conforms to one of ten named patterns:

Pattern

Purpose

Key Characteristics

aggregate datum

Container grouping related documents

Root-level; contains arrays of child documents

indexed datum

Array of homogeneous items

Ordered (@index) or unordered

value datum

Leaf scalar property

Single typed value

quantity datum

Physical measurement

{value, unit} pair with optional unit constraint

class datum

Enumerated ontology class

String constrained to subclass labels via $asm.value-sub-class-of — open taxonomy (extending the vocabulary adds valid values)

category datum

Enumerated named individual

String constrained to instance labels via $asm.value-instance-of — closed enumeration (fixed set of named individuals)

boolean datum

Boolean scalar property

Leaf tBooleanValue (e.g., auto focus enabled setting)

any datum

Unconstrained value

Property accepting any value type (e.g., description in electronicProjectRecord)

binary datum

File reference

POSIX path to co-located companion file

datacube

Multidimensional array

Dimension/measure structure with metadata

These patterns are declared via $asm.pattern in the schema and form the structural grammar of ASM documents. Every node in the document tree is classifiable by pattern.

class datum vs category datum: Both constrain string values to vocabulary-backed labels, but differ in resolution semantics:

  • class datum uses $asm.value-sub-class-of - permissible values are skos:prefLabels of OWL classes that are rdfs:subClassOf a specified parent class. The enumeration is open: adding a new subclass to the vocabulary automatically extends the set of valid values. Used for open taxonomies (device types, material role types, technique types).
  • category datum uses $asm.value-instance-of - permissible values are skos:prefLabels of OWL named individuals that are instances of a specified class. The enumeration is closed: the set of named individuals is fixed by the ontology. Used for closed enumerations (lifecycle status, analysis type, verdict types).

The Digital Analytical Method schema (CR/2026/06) is the first ASM schema to use category datum — for analysis type (11 fixed analysis categories) and life cycle status (5 lifecycle states).

2.2.5 Datacube Model

Adapted from W3C Data Cube for multidimensional scientific data:

{
  "cube-structure": {
    "dimensions": [
      {
        "@componentDatatype": "double",
        "concept": "wavelength",
        "unit": "nm",
        "scale": "interval"
      }
    ],
    "measures": [
      {
        "@componentDatatype": "double",
        "concept": "absorbance",
        "unit": "AU",
        "$asm.fill-value": -999.0
      }
    ]
  },
  "data": {
    "dimensions": [[200.0, 201.0, 202.0, ...]],
    "measures": [[0.142, 0.156, 0.173, ...]],
    "points": [[200.0, 0.142], [201.0, 0.156], [202.0, 0.173]]
  }
}

Key datacube features:

  • Per-dimension semantic metadata: concept name, unit, measurement scale (nominal/ordinal/cardinal/interval/range)
  • Per-measure fill values ($asm.fill-value) for sparse data representation
  • Supported datatypes: doublefloatdecimalintegerbyteintshortlongstringbooleandateTime
  • Dimensions and measures as parallel flat arrays (columnar layout)
  • Points: row-oriented representation (array of tuples) as an alternative to the columnar dimensions/measures layout

2.2.6 Enumeration and Vocabulary Resolution

ASM enumerations use a two-level resolution mechanism:

  • Schema level - enum array with human-readable labels:

json "sample role type": { "$asm.pattern": "class datum", "$asm.value-sub-class-of": "http://purl.allotrope.org/ontologies/role#AFRL_0000035", "enum": ["control sample role", "standard sample role", "blank role"], "type": "string" }

  • Vocabulary level - each label resolves to an ontology class IRI via skos:prefLabel lookup against the vocabulary closure declared in the manifest.

The constraint $asm.value-sub-class-of ensures all permissible values are labels of classes that are subclasses of the specified parent class in the ontology.

Category datum resolution — the Digital Analytical Method schema (CR/2026/06) introduces $asm.value-instance-of, which constrains values to labels of named individuals (OWL instances) rather than classes:

json "life cycle status": { "$asm.pattern": "category datum", "$asm.value-instance-of": "http://purl.allotrope.org/ontologies/result#AFR_0003289", "enum": ["draft life cycle status", "approved life cycle status", "rejected life cycle status", "effective life cycle status", "obsolete life cycle status"], "type": "string" }

The distinction: class datum enumerations are open (extending the vocabulary adds valid values); category datum enumerations are closed (the named individuals are a fixed set).

2.2.7 Array Semantics

Annotation

Purpose

Instance Effect

$asm.array-ordered: true

Semantic ordering significant

Items include "@index": 1 (1-based) via orderedItem wrapper

$asm.array-mixed: true

Polymorphic item types

Items include "@type": "item-class" discriminator via mixedItem wrapper

Neither

Unordered homogeneous array

Plain JSON array

Ordered arrays inject the @index property into each item via an allOf composition with the orderedItem definition. This is structural - the index is part of the validated JSON instance.

2.2.8 Unit System (QUDT)

  • Symbols follow strict formatting: / (division), . (multiplication), ^ (exponents), _ (subscripts)
  • No Unicode superscripts/subscripts - m^2 not 
  • Symbol → IRI mapping validated at schema level via $asm.unit-iri
  • Two namespaces: base QUDT (http://qudt.org/vocab/unit#), Allotrope extensions (http://purl.allotrope.org/ontology/qudt-ext/unit#)
  • units.schema (qudt/REC/units.schema.json) is auto-generated from the QUDT ontology and Allotrope extensions

2.2.9 Manifest and Closure Model

Every ASM document begins with a manifest declaring the semantic resources required for interpretation:

{
  "manifest": {
    "@id": "http://example.org/documents/experiment-2024-001",
    "@type": "http://purl.allotrope.org/ontologies/manifest#Manifest",
    "vocabulary": [
      "http://purl.allotrope.org/voc/afo/merged/REC/2026/03/merged-without-qudt-and-inferred",
      "http://purl.allotrope.org/voc/qudt/REC/2026/03/qudt-ext"
    ],
    "json-schemas": [
      "http://purl.allotrope.org/json-schemas/adm/uv-vis/REC/2026/06/uv-vis.schema"
    ]
  }
}

The manifest schema (core/REC/manifest.schema.json) defines three optional arrays — vocabularyjson-schemas, and shapes (for SHACL constraints) — of which vocabulary and json-schemas are required. Each array lists entry-point URIs, not the full transitive closure: schema $ref chains are resolved transitively by the validator; vocabularies are either pre-merged offline (a single merged .ttl file containing the OWL import closure) or resolved via owl:imports at load time. The manifest is the root declaration that scopes what validates a document.

2.2.10 $asm.* Extension Keywords

Keyword

Scope

Purpose

$asm.type

Property

Maps JSON type to XSD datatype IRI

$asm.pattern

Object

Declares structural document pattern

$asm.property-class

Property

RDF property IRI for this field

$asm.lookup-property

Property

Property used for label→IRI resolution (typically skos:prefLabel)

$asm.value-sub-class-of

Enum property (class datum)

Constrains enum values to subclasses of a specified class (open taxonomy)

$asm.value-instance-of

Enum property (category datum)

Constrains enum values to instances of a specified class (closed enumeration)

$asm.unit-iri

Unit property

Maps symbol string to QUDT IRI

$asm.fill-value

Datacube measure

Sentinel for missing/sparse values

$asm.array-ordered

Array

Semantic ordering with index injection

$asm.array-mixed

Array

Polymorphic items with type discriminator

$asm.binary-datum

Object

Boolean flag marking aggregate datums as binary content containers

$asm.manifest

Document

Manifest schema reference

These keywords are not JSON Schema vocabulary extensions in the formal sense - they are convention-based annotations processed by ASM-aware tooling.

2.2.11 Vocabulary Ontology (RDF/OWL)

ASM vocabularies are full OWL ontologies in Turtle format:

af-r:AFR_0002889 a owl:Class ;
  rdfs:subClassOf af-r:AFR_0001234 ;
  rdfs:subClassOf [
    a owl:Restriction ;
    owl:onProperty af-r:has_quantity ;
    owl:someValuesFrom qudt:QuantityValue
  ] ;
  skos:prefLabel "peak area" ;
  skos:definition "The integrated area under a chromatographic peak." ;
  rdfs:isDefinedBy <http://purl.allotrope.org/ontologies/result> .

Key ontology modules:

  • Process (techniques, assays, separations)
  • Material (samples, reagents, preparations)
  • Equipment (instruments, detectors, columns)
  • Quality (properties, quantities, measurements)
  • Result (calculated values, statistics)
  • Role (sample roles, analyst roles)

2.2.12 Extensibility Model

ASM is designed for extension without modification to the core schemas. Four mechanisms operate at different levels:

Custom information aggregate document - the customInformationAggregateDocument pattern (defined in core/REC/hierarchy.schema.json) provides a generic extension point at any document level. Items use polymorphic values (double, string, timestamp, boolean) with a datum label key. This is the designated escape hatch for data that does not fit standard ASM properties.

Schema composition - technique schemas compose core building blocks via allOf + $ref:

{
  "allOf": [
    { "$ref": "hierarchy.schema#/$defs/techniqueDocument" },
    {
      "properties": {
        "peak area": { "$asm.pattern": "quantity datum", "...": "..." }
      }
    }
  ]
}

This injects technique-specific properties into the standard hierarchy without copying or modifying the base definitions.

Vocabulary extension - custom .voc.ttl files define new OWL classes and properties that extend the AFO namespace:

ex:EXT_0001 a owl:Class ;
  rdfs:subClassOf af-r:AFR_0002889 ;
  skos:prefLabel "custom peak metric" ;
  skos:definition "A vendor-specific peak quality metric." ;
  rdfs:isDefinedBy <http://example.org/ontologies/custom> .

New vocabulary classes immediately become valid enum values for any class datum whose $asm.value-sub-class-of ancestor matches (§2.2.6).

Manifest-level integration — the manifest (§2.2.9) is the mechanism that activates schema and vocabulary extensions. Its arrays form the document's validation closure:

Array

Content

Effect

json-schemas[]

URI of the entry-point JSON Schema

Defines the root schema; transitive $ref targets are resolved automatically

vocabulary[]

URIs of pre-merged .ttl ontology files

Defines which class/property labels are valid for resolution

shapes[]

URIs of SHACL shapes graphs

Defines additional constraint shapes for validation

To integrate an extension, the document author creates a custom entry-point schema that $refs the standard technique schema and adds extension-specific properties, then declares it in the manifest:

{
  "manifest": {
    "vocabulary": [
      "http://purl.allotrope.org/voc/afo/merged/REC/2026/03/merged-without-qudt-and-inferred",
      "http://purl.allotrope.org/voc/qudt/REC/2026/03/qudt-ext",
      "http://example.org/voc/custom/2026/06/custom-extension"
    ],
    "json-schemas": [
      "http://example.org/json-schemas/adm/custom/2026/06/custom-hplc-extension.schema"
    ]
  }
}

The custom schema internally $refhplc.schema, which in turn $refhierarchy.schemacore.schemacube.schema, and units.schema — all resolved transitively by the validator without explicit manifest listing.

Key integration rules:

  • Schemas: The manifest json-schemas[] array lists only the entry-point technique schema. All dependencies (core.schemahierarchy.schemacube.schemaunits.schema, detector sub-schemas) are resolved transitively via JSON Schema $ref — they do not appear in the manifest. A custom extension schema that $refs the standard hierarchy simply becomes the new entry-point listed in the manifest; the validator follows $ref chains to resolve all dependencies.
  • Vocabularies: A custom .voc.ttl that introduces new subclasses (e.g., new sample roles, new result types) must be listed in vocabulary[]. Once listed, any class datum field whose $asm.value-sub-class-of constraint matches an ancestor of the new class will accept the new skos:prefLabel as a valid enum value - without modifying the technique schema's enum array.
  • Units: Custom units are introduced by extending the QUDT namespace via the Allotrope extensions namespace (http://purl.allotrope.org/ontology/qudt-ext/unit#). A corresponding entry in units.schema maps the symbol string to the new unit IRI via $asm.unit-iri. Both unit namespaces (§2.2.8) — base QUDT and Allotrope extensions — are resolved through the same units.schema catalog.

The manifest is additive-only - adding a vocabulary or schema can make previously invalid documents valid (new enum values, new properties) but cannot invalidate a document that was valid under a smaller closure. This monotonicity is an architectural invariant.

2.2.13 Domain-Specific Document Hierarchies

ASM's ten structural patterns (aggregate, indexed, value, quantity, class, category, boolean, any, binary, datacube datum) are domain-agnostic building blocks. They compose into document hierarchies for specific domains - from atomic data primitives (materials, samples, analytical runs, results, methods, specifications, instruments, equipment) through compositional workflows (tests, experiments, procedures, recipes), systemic aggregations (studies, programs, regulatory submissions), to enterprise integration systems (ELN, LIMS, MES, ERP).

The Allotrope Connected Domains initiative (proposed CR/2026/06) targets seven of these as interconnected schemas: Materials, Methods, Instruments, Results, Equipment, Processes, and Specifications - enabling cross-domain ASM documents for use cases such as reaction analysis and stability study data.

For detailed domain model proposals - including BFO-aligned ontology mappings, proposed ASM document hierarchies, and current coverage assessments for each tier - see Colsman (2026).


3. Common Canonical Subset

The following concepts exist in both frameworks and can be mapped bidirectionally without information loss. This subset defines the viable interoperability surface.

3.1 Structural Modeling

Canonical Concept

LinkML Realization

ASM Realization

Round-trip Fidelity

Entity / Record type

ClassDefinition

JSON Schema object with properties

Lossless

Field / Property

SlotDefinition (or attributes entry)

JSON Schema property declaration

Lossless

Scalar string

range: string

tStringValue (simple form), "type": "string"

Lossless

Scalar integer

range: integer

tIntegerValue"type": "integer"

Lossless

Scalar float/double

range: float / range: double

tDoubleValue"type": "number"

Lossless

Scalar boolean

range: boolean

tBooleanValue"type": "boolean"

Lossless

Date/DateTime

range: date / range: datetime

tDateTimeValuetDateValue"format": "date-time"

Lossless

Duration

range: string + pattern

tDurationValue, ISO 8601 format

Lossless

URI/IRI

range: uri

tIRIValue"format": "iri"

Lossless

Required field

required: true

Property name in "required": [...] array

Lossless

Optional field

required: false (default)

Property name absent from required array

Lossless

Multivalued (list)

multivalued: true

"type": "array"

Lossless

Min items

minimum_cardinality: n

"minItems": n

Lossless

Max items

maximum_cardinality: n

"maxItems": n

Lossless

Composition (nested object)

Slot with class range, inlined: true

"$ref": "#/$defs/ChildType" or inline properties

Lossless

Pattern constraint

pattern: "^[A-Z]\\d+$"

"pattern": "^[A-Z]\\d+$"

Lossless

Numeric bounds

minimum_value: 0maximum_value: 100

"minimum": 0"maximum": 100

Lossless

Const/fixed value

equals_string: "fixed"

"const": "fixed"

Lossless

Description

description: "..."

"description": "..." (JSON Schema) or skos:definition (vocab)

Lossless (schema-level)

3.2 Semantic Modeling

Canonical Concept

LinkML Realization

ASM Realization

Round-trip Fidelity

Semantic type IRI for class

class_uri: schema:Person

$asm.property-class or @type value

Lossless

Semantic type IRI for property

slot_uri: schema:name

$asm.property-class on property

Lossless

Closed enumeration (category datum)

Static permissible_values with meaning: <named-individual IRI>

$asm.pattern: category datum$asm.value-instance-of, static enum

Lossless - both sides declare a fixed set; IRIs preserved as meaning: values

Open taxonomy enumeration (class datum)

Dynamic reachable_from enum (build-time materialization)

$asm.pattern: class datum$asm.value-sub-class-of, static enum

Near-lossless - open-taxonomy intent preserved; ASM resolves at runtime, LinkML materializes at build time (see §5.2.4)

Identifier property

identifier: true

@id property declaration

Lossless

Prefix declarations

prefixes: block

Vocabulary ontology prefixes

Lossless (at vocabulary level)

3.3 Quantity Modeling

Canonical Concept

LinkML Realization

ASM Realization

Round-trip Fidelity

Quantity (value + unit)

Class with value: float + unit: string slots; unit: annotation with UCUM/QUDT

tQuantityValue{"value": 3.14, "unit": "mg/mL"}

Near-lossless - structure matches; unit validation depth differs

Unit reference

unit: { ucum_code: mg/mL } or annotation

$asm.unit-iri mapping to QUDT IRI

Lossless if both use QUDT

3.4 Instance Data Mapping (JSON)

For the common subset, instance data can be translated mechanically:

LinkML instance (JSON):

{
  "id": "SAMPLE-001",
  "name": "Reference Standard A",
  "concentration": 5.0,
  "concentration_unit": "mg/mL",
  "role": "STANDARD"
}

ASM instance (JSON):

{
  "sample identifier": "SAMPLE-001",
  "sample document": {
    "sample name": "Reference Standard A",
    "mass concentration": { "value": 5.0, "unit": "mg/mL" },
    "sample role type": "standard sample role"
  }
}

The structural mapping is deterministic for the canonical subset, though field names follow different conventions (camelCase/snake_case in LinkML vs. space-separated natural language in ASM).


4. Gaps: LinkML to ASM

Features present in LinkML that cannot be faithfully represented in ASM.

4.1 HIGH Severity (Fundamental Incompatibility)

4.1.1 Slot Usage Refinement

LinkML:

classes:
  Vehicle:
    slots:
      - parts
  Car:
    is_a: Vehicle
    slot_usage:
      parts:
        range: CarPart  # narrows from VehiclePart
        minimum_cardinality: 4

Why unmappable: ASM has no mechanism for per-class monotonic slot refinement. Each technique schema is a standalone JSON Schema file - there is no way to express "this property, when used in this context, has a narrower range." You must duplicate the full property definition in each schema that needs different constraints.

Impact: Schema authors must manually maintain constraint consistency across technique schemas that share properties with different constraints.


4.1.2 NDArray Shape/Dtype Constraints

LinkML:

classes:
  Spectrum:
    attributes:
      intensities:
        range: float
        array:
          dimensions:
            - alias: wavelength
              minimum_cardinality: 100
              maximum_cardinality: 4096
          exact_number_dimensions: 1

Why unmappable: ASM's datacube model is structurally incompatible with LinkML's NDArray concept. ASM datacubes carry per-dimension semantic metadata (concept name, unit, scale type), use a columnar parallel-arrays layout, and support fill values for sparse data. LinkML NDArrays are shape-constrained typed tensors with named dimensions but no semantic metadata per dimension.

These are different abstractions solving overlapping problems:

  • LinkML NDArray: "a 1D array of floats with 100–4096 elements"
  • ASM Datacube: "a wavelength dimension (nm, interval scale) paired with an absorbance measure (AU, with fill value -999.0)"

Neither subsumes the other.


4.1.3 Mixin Inheritance

LinkML:

classes:
  HasAliases:
    mixin: true
    slots:
      - aliases
  HasTimestamps:
    mixin: true
    slots:
      - created_at
      - modified_at
  Person:
    is_a: NamedThing
    mixins:
      - HasAliases
      - HasTimestamps

Why unmappable: ASM has no mixin concept. JSON Schema allOf can achieve structural composition, but:

  • There is no propagation through an inheritance tree
  • There is no diamond resolution
  • There is no mixin: true marker distinguishing interface-like composition from structural inheritance
  • The vocabulary (rdfs:subClassOf) is single-inheritance only

Approximation: Flatten mixins into each consuming class (losing reusability metadata).


4.2 MEDIUM Severity (Lossy but Approximable)

4.2.1 is_a Hierarchy in Validation Schema

LinkML: Class hierarchies directly affect validation - abstract classes cannot be instantiated, inherited slots are automatically valid.

ASM gap: The class hierarchy lives in the vocabulary (RDF/OWL rdfs:subClassOf), not in the JSON Schema. The validation schema does not enforce inheritance - each technique schema is self-contained.

Approximation: Generate separate JSON Schema per leaf class with all inherited properties flattened.


4.2.2 Rules (Preconditions/Postconditions)

LinkML:

classes:
  Address:
    rules:
      - preconditions:
          slot_conditions:
            country:
              equals_string: USA
        postconditions:
          slot_conditions:
            postal_code:
              pattern: "[0-9]{5}(-[0-9]{4})?"

ASM gap: JSON Schema has if/then/else which is structurally similar but operates on JSON Schema applicators rather than slot-level conditions. The semantic framing is different (structural schema branching vs. logical rules).

Approximation: Translate to JSON Schema if/then/else with some loss of semantic clarity.


4.2.3 Computed/Derived Slots (equals_expression)

LinkML:

slots:
  age_in_years:
    equals_expression: "{age_in_months} / 12"

ASM gap: No derived field mechanism. All ASM fields are stored values. The converter that produces the ASM instance is responsible for computing derived values - the schema cannot express derivation rules.

Approximation: Document the derivation in the vocabulary definition (skos:definition) - no runtime enforcement.


4.2.4 Dynamic Enumerations (open taxonomies only)

LinkML:

enums:
  CellType:
    reachable_from:
      source_ontology: obo:cl
      source_nodes:
        - CL:0000000
      include_self: false
      relationship_types:
        - rdfs:subClassOf

ASM gap: Enumerations in ASM JSON Schema are static enum arrays. The vocabulary contains the full class hierarchy, but the schema enum list is materialized at build time.

Note: This gap applies only to open taxonomy (class datum$asm.value-sub-class-of) fields. Closed enumerations (category datum$asm.value-instance-of) have a fixed named-individual set - static permissible_values with meaning: maps to them losslessly and there is nothing to materialize.

Approximation: Materialize the dynamic enum at schema-generation time (losing dynamic update capability).


4.2.5 Compound Unique Keys

LinkML:

classes:
  Isotope:
    unique_keys:
      main:
        unique_key_slots:
          - atomic_number
          - neutron_number

ASM gap: No native compound uniqueness constraint. JSON Schema does not support tuple uniqueness.

Approximation: Enforce at application level; document in vocabulary.


4.2.6 Import Chains (Named Module Composition)

LinkML: imports: [base, extensions/lab] — forms a named dependency graph. Each import is a logical module name; the import chain is explicit in the schema source and traversable by tooling.

ASM gap: ASM schemas do have transitive composition via JSON Schema $ref (absolute URI resolution), but there is no named-module concept. The $ref targets are opaque URIs — there is no imports: declaration enumerating dependencies, no logical module names, and no tooling for traversing the import graph as a first-class concept. Reusability is implicit in the $ref structure rather than declared.

Approximation: The $ref graph already provides transitive composition. The gap is in tooling ergonomics (no named imports, no schema-level dependency declaration, no import-graph visualization) rather than capability.


4.2.7 Type Designators

LinkML: designates_type: true - a slot whose value determines the runtime class of the instance.

ASM gap: @type serves a similar purpose but is always constrained to a fixed vocabulary class label, not an arbitrary discriminator dispatching across a class hierarchy.


4.3 LOW Severity (Metadata/Documentation Loss)

Feature

Why lost

Impact

Subsets

No equivalent grouping in ASM

Organizational info lost

Inverse slots

No inverse declaration (documentation-only in LinkML too)

Minimal

Logical characteristics (transitive, symmetric)

Would need OWL axioms in vocabulary

Documentation only

default_range

ASM requires explicit typing per property

Syntactic convenience only

recommended

No "advisory but non-validating" marker in JSON Schema

Soft validation signal lost

Structured aliases

Vocabulary has skos:altLabel but no source/language metadata in schema

Metadata loss

ifabsent (defaults)

JSON Schema default keyword exists but semantics differ

Near-mappable


5. Gaps: ASM to LinkML

Features present in ASM that cannot be faithfully represented in LinkML.

5.1 HIGH Severity (Fundamental Incompatibility)

5.1.1 Polymorphic Value Types (Dual-Form)

ASM:

{
  "sample identifier": "SAMPLE-001",
  "peak area": { "@type": "peak area", "value": 42.5 }
}

Both forms are valid for the same field: a bare literal ("SAMPLE-001") or a typed object ({"@type": "...", "value": ...}). This is ASM's fundamental design pattern - it allows any scalar value to optionally carry semantic type metadata.

Why unmappable: LinkML slots have a single range. A slot cannot simultaneously accept string AND an object with {@type, value} structure. The any_of combinator can approximate this:

slots:
  sample_identifier:
    any_of:
      - range: string
      - range: TypedStringValue

But this loses:

  • The guarantee that both forms represent the same semantic concept
  • The @type value being drawn from the vocabulary
  • The structural guarantee that typed form always has exactly {@type, value}

Impact: Any LinkML-authored schema that needs ASM instance compatibility must model every scalar field as a union type, defeating LinkML's type safety.


5.1.2 Document Pattern System ($asm.pattern)

ASM: Every structural element is tagged with one of ten patterns (aggregate datumindexed datumvalue datumquantity datumclass datumcategory datumboolean datumany datumbinary datumdatacube). These patterns:

  • Drive tooling behavior (editors, validators, generators)
  • Define the structural grammar of documents
  • Are machine-readable structural classifications

Why unmappable: LinkML has no metamodel concept for "structural pattern classification." You could use annotations:

classes:
  MeasurementAggregateDocument:
    annotations:
      asm_pattern: aggregate datum

But annotations are:

  • Unvalidated by default (any string accepted)
  • Not part of the generated JSON Schema
  • Not usable for tool dispatch
  • Not inherited through is_a

Impact: ASM's structural grammar - which determines how documents are traversed, displayed, and validated - has no LinkML representation that preserves its role as a first-class modeling concept.


5.1.3 Datacube with Per-Dimension Semantic Metadata

ASM:

{
  "cube-structure": {
    "dimensions": [{
      "@componentDatatype": "double",
      "concept": "wavelength",
      "unit": "nm",
      "scale": "interval"
    }],
    "measures": [{
      "@componentDatatype": "double",
      "concept": "absorbance",
      "unit": "AU",
      "$asm.fill-value": -999.0
    }]
  }
}

Why unmappable: LinkML NDArrays provide shape and dtype constraints but have no per-dimension metadata:

  • No concept (what the dimension means)
  • No unit (what units the values are in)
  • No scale (nominal/ordinal/interval/ratio)
  • No fill-value (sentinel for sparse data)
  • No separation of dimensions vs. measures

The ASM datacube is closer to a self-describing scientific dataset format (like NetCDF or HDF5 with attributes) than to a shaped array type.

Approximation: Model as a class with explicit slots for structure metadata + array slots for data. Loses the integrated datacube semantics and cannot round-trip through LinkML's array machinery.


5.2 MEDIUM Severity (Lossy but Approximable)

5.2.1 Ordered Arrays with Index Injection (@index)

ASM:

{
  "measurement document": [
    { "@index": 1, "sample identifier": "S1", ... },
    { "@index": 2, "sample identifier": "S2", ... }
  ]
}

The @index property is injected into instances by the schema (via allOf + orderedItem). Array position has semantic meaning and is explicitly encoded in the data.

LinkML gap: Multivalued slots are ordered by default in JSON, but:

  • There is no mechanism to inject an explicit index property into items
  • The @index property would need to be declared as a slot on the item class, conflating structural metadata with domain content

Approximation: Add an explicit index: integer slot. Loses the automatic injection semantics and the separation of structural ordering from domain modeling.


5.2.2 Mixed/Polymorphic Arrays with Type Discriminator

ASM:

{
  "custom information document": [
    { "@type": "string datum", "value": "note text" },
    { "@type": "quantity datum", "value": 3.14, "unit": "mg" }
  ]
}

$asm.array-mixed: true declares that array items are heterogeneous, with @type serving as the discriminator.

LinkML gap: any_of on a multivalued slot's range can express heterogeneity:

slots:
  custom_info:
    multivalued: true
    any_of:
      - range: StringDatum
      - range: QuantityDatum

But LinkML does not inject a @type discriminator key - the consumer must infer type from structure. JSON Schema oneOf with const on a type field is the standard approach, which LinkML can generate, but the @type key name and vocabulary-backed value are ASM-specific.


5.2.3 Manifest Closure Model

ASM: Document validity requires a manifest declaring the entry-point schemas and vocabularies. However, the manifest is not a flat, self-contained closure — both layers have transitive dependencies:

  • JSON Schema layer: The manifest's json-schemas[] array lists only the top-level technique schema (e.g., liquid-chromatography.tabular.schema). That schema transitively $refcore.schemahierarchy.schemacube.schemaunits.schema, and potentially multiple detector/sub-technique schemas. For example, the LC tabular schema directly references 12 distinct external schema files, none of which appear in the manifest. JSON Schema $ref resolution follows absolute URIs transitively — the validator must resolve the full $ref graph to validate an instance.
  • Vocabulary layer: The manifest's vocabulary[] array typically lists a pre-merged ontology file (e.g., merged-without-qudt-and-inferred) plus a QUDT extension. The "merged" vocabulary is itself the output of an OWL import closure computation performed offline — it inlines all transitive owl:imports. The manifest TTL format also carries explicit owl:imports triples for tooling that performs import resolution at runtime.

The manifest's role is therefore to declare roots — not to enumerate every resource in the transitive closure. The closure is computed by following $ref chains (schemas) and owl:imports chains or pre-merged bundles (vocabularies). Adding a new vocabulary to the manifest can change which enum values are valid (because new subclasses become available), but the schema dependency graph is fixed by the $ref structure.

LinkML gap: Uses an explicit imports: chain (directed acyclic graph). Adding an import adds new schema elements transitively. Both systems have transitive dependency resolution, but they differ in how the "root set" is declared:

Aspect

ASM

LinkML

Schema dependencies

Explicit via json-schemas[] + implicit via JSON Schema $ref (absolute URIs)

Explicit via imports: (named modules)

Vocabulary dependencies

Pre-merged offline or owl:imports chains

Dynamic reachable_from or static enum materialization

Root declaration

Manifest json-schemas[] + vocabulary[]

Top-level schema file with imports:

Closure computation

$ref resolution (schemas), pre-merge or runtime import (vocabs)

Import chain traversal at schema-load time

Approximation: Model the manifest as a top-level class with vocabulary and schema arrays. The transitive $ref graph maps naturally to LinkML imports:. The vocabulary-scope gating (runtime enum resolution dependent on manifest vocabulary list) has no LinkML equivalent.


5.2.4 $asm.lookup-property (Runtime Label Resolution - class datum only)

ASM: For class datum fields ($asm.value-sub-class-of), enum values such as "control sample role" are validated by looking up the label in the vocabulary using the property specified by $asm.lookup-property (typically skos:prefLabel). The resolution is runtime - the valid enum values are determined by what OWL subclasses exist in the vocabulary closure at validation time.

Scope: This gap applies exclusively to open taxonomy (class datum) fields. Category datum fields ($asm.value-instance-of) constrain values to a fixed set of named individuals - those are enumerated statically in both the ASM schema and the equivalent LinkML permissible_values block, so no runtime resolution gap exists.

LinkML gap: Enums are resolved at schema-build timemeaning maps a permissible value to an ontology term, but the permissible values themselves are explicitly listed in the schema. There is no "query the vocabulary at runtime" mechanism (dynamic enums exist but are materialized at build time).

Impact: An ASM class datum field can gain or lose valid values by changing the manifest's vocabulary list without touching the schema. The equivalent LinkML schema must be regenerated to reflect the change. Category datum fields are unaffected.


5.2.5 Validated Unit Symbol → IRI Mapping

ASM: $asm.unit-iri creates a validated bidirectional mapping between a unit symbol string and its QUDT IRI:

"µg/mL": {
  "$asm.unit-iri": "http://qudt.org/vocab/unit#MicrogramPerMilliliter",
  "const": "µg/mL"
}

LinkML gap: The unit: annotation is metadata - it documents what unit a slot holds but does not validate that the instance value matches an allowed unit symbol from a controlled registry.

Approximation: Model units as an enum with each permissible value annotated with its QUDT IRI. Loses the auto-generated nature and the bidirectional symbol↔IRI contract.


5.2.6 Technique Hierarchy as Reusable Template

ASM: The 3-tier hierarchy (AggregateDocument → Document → MeasurementAggregateDocument) is a structural template reused across 50+ technique schemas (Colsman, 2026, §3 Analytical). Each new technique instantiates this template and adds domain-specific content at defined extension points. The same aggregate/indexed patterns extend beyond analytical data into 19 proposed domain-specific document hierarchies across four tiers (Colsman, 2026), from atomic data primitives (materials, samples) through enterprise integration systems (ELN, LIMS, MES, ERP).

LinkML gap: No native "structural template" or "document pattern template" mechanism. You can model this as abstract base classes:

classes:
  TechniqueAggregateDocument:
    abstract: true
    slots:
      - data_system_document
      - technique_documents
  UVVisAggregateDocument:
    is_a: TechniqueAggregateDocument
    slot_usage:
      technique_documents:
        range: UVVisDocument

This works but is verbose and loses the "this is a reusable structural pattern that all techniques share" concept. Each technique must re-express the full hierarchy rather than saying "I'm an instance of the technique pattern with these specifics."


5.2.7 $asm.fill-value (Sparse Data Representation)

ASM: Datacube measures can declare a fill value (e.g., -999.0) that represents "no data" in a dense array representation.

LinkML gap: No sentinel/fill-value concept for arrays. The standard LinkML approach would be to use nullable types or optional slots, but this doesn't map to the "dense array with sentinel" pattern used in scientific data.


5.2.8 Schema-Level Semantic Annotations ($asm.*)

ASM's $asm.* keywords are processed by tooling to drive validation, resolution, and serialization behavior. They are part of the schema's operational semantics.

LinkML gap: annotations are extensible key-value metadata, but:

  • They are not operationally processed by LinkML tooling
  • They are not part of the generated downstream artifacts (annotations don't appear in generated JSON-Schema by default)
  • They cannot drive tool behavior in the same way

Approximation: Use annotations with instantiates for typed validation (experimental feature).


5.2.9 Companion File Model (Binary Datum)

ASM: The binary datum pattern ($asm.pattern: "binary datum", property class AFR_0001928) models references to external binary content - images, raw detector frames, binary blobs - that accompany the structured JSON document. The value is always a POSIX-style relative path (tStringValue) to a companion file co-located with the .asm output.

This is an architectural pattern, not just a scalar type:

  • Co-location contract - companion files must reside alongside the .asm file. The converter is responsible for extracting/copying them to the output directory.
  • Hierarchy-aware placement - the binary datum sits at the document level that owns the data:

Companion type

Placement level

Example

Per-measurement image

measurementDocument

Fluorescence stage image per cycle

Per-run raw trace

measurementAggregateDocument

Complete detector dump

Instrument calibration

deviceControlAggregateDocument

Calibration snapshot

Document-level attachment

<domain> document

Protocol PDF, audit export

  • Array pattern - multiple companion files are modeled as an aggregate document containing an array of binary datum objects, each with its own POSIX path.
  • Semantic identity - the property name is always POSIX path, typed to AFO property "has POSIX path". This is not a generic string field.

LinkML gap: No native binary, file, or path type. Approximations:

LinkML approach

What it captures

What it loses

range: uri

External reference

Co-location contract, POSIX path convention, hierarchy placement rules

range: string + pattern

Path syntax

Semantic identity (AFR_0001928), companion file lifecycle

Custom TypeDefinition

Named type

No tooling awareness - generators ignore it

annotations carrying $asm.pattern

Metadata roundtrip

Not processed by any LinkML generator

The fundamental mismatch: LinkML treats file references as opaque string values. ASM treats them as a managed artifact relationship with co-location, hierarchy placement, and semantic typing. A LinkML-authored schema can represent the path string but cannot express the converter's obligation to extract companion files or the placement rules that determine where in the document hierarchy the reference belongs.


5.3 LOW Severity

Feature

Why lost

Impact

Electronic signatures

Model as a regular class

Domain convention, not structural gap

Unit formatting rules (µ vs μ, ^ for exponents)

Use pattern constraints

Validation possible, intent unclear

Vocabulary-level OWL restrictions

LinkML generates OWL but doesn't consume OWL restrictions for validation

Complementary, not conflicting

orderedItem / mixedItem wrapper injection

Must be modeled as explicit class composition

Structural overhead


6. Interoperability Strategy

6.1 Canonical Intermediate Representation (CIR)

Define a minimal intermediate representation capturing the common subset from §3:

The CIR contains:

  • Entity definitions with fields, types, cardinality, descriptions
  • Enumerations with permissible values and optional ontology IRIs
  • Quantity types with unit references (QUDT IRIs)
  • Composition relationships (parent → child)
  • Identifier declarations
  • Pattern and numeric constraints

The CIR does not contain:

  • Inheritance hierarchies (flattened at boundary)
  • Mixins (flattened at boundary)
  • Datacubes (domain-specific, handled separately)
  • Document patterns (ASM-specific)
  • NDArrays (LinkML-specific)
  • Computed slots (LinkML-specific)
  • Polymorphic value dual-form (ASM-specific)

6.2 Transformation Pipelines

L2C: LinkML → CIR

  • Materialize all inherited slots via SchemaView.all_slots(class_name)
  • Flatten mixins into consuming classes
  • Resolve dynamic enums to static permissible-value lists
  • Evaluate equals_expression to documentation annotations
  • Convert NDArrays to annotated multivalued slots (losing shape constraints)
  • Convert rules to documentation annotations

C2A: CIR → ASM

  • Map each CIR entity to a JSON Schema object with properties
  • Apply $asm.pattern based on structural heuristics:
    • Entity with only scalars → value datum pattern fields
    • Entity with child arrays → aggregate datum
    • Enum fields → class datum with $asm.value-sub-class-of
    • Quantity fields → quantity datum
  • Generate $asm.type from CIR scalar types
  • Generate $asm.property-class from CIR semantic IRIs
  • Generate vocabulary stubs (.voc.ttl) with:
    • Class declarations for entities
    • skos:prefLabel for enum labels
    • rdfs:subClassOf for enum parent classes
  • Generate manifest template listing produced schemas and vocabularies

A2C: ASM → CIR

  • Parse JSON Schema properties → CIR fields
  • Resolve $asm.pattern to determine field category
  • Extract type information from $asm.type or JSON Schema type
  • Extract enum values from enum arrays
  • Extract quantity structure from tQuantityValue pattern
  • Map $asm.property-class → CIR semantic IRI
  • Discard: $asm.fill-value$asm.array-ordered$asm.array-mixed, datacube structure, polymorphic dual-form

C2L: CIR → LinkML

  • Map each CIR entity to a ClassDefinition
  • Map fields to SlotDefinition with appropriate ranges
  • Map enums to EnumDefinition with meaning for ontology-backed values
  • Map quantities to a class with value + unit slots, annotated with unit:
  • Map compositions to inlined class ranges
  • Preserve semantic IRIs as class_uri / slot_uri

6.3 Lossless Extensions (Round-Trip Annotations)

For concepts that exist in one framework but not the other, define passthrough annotations that preserve information during round-tripping:

In LinkML (for ASM-specific concepts):

classes:
  MeasurementDocument:
    annotations:
      asm_pattern: "indexed datum"
      asm_array_ordered: true
    attributes:
      wavelength:
        annotations:
          asm_fill_value: -999.0
          asm_property_class: "http://purl.allotrope.org/ontologies/result#AFR_0002889"

In ASM (for LinkML-specific concepts):

{
  "$comment": "linkml:is_a = NamedThing",
  "$comment": "linkml:mixins = [HasAliases, HasTimestamps]",
  "properties": { ... }
}

These annotations enable round-tripping but carry no operational semantics in the target framework.

6.4 Recommended Approach

Use Case

Recommendation

New technique schema (simple)

Author in LinkML → generate ASM via C2A pipeline → manually add datacube/polymorphic patterns

New technique schema (complex with datacubes)

Author datacube portion in ASM natively; author entity/enum portions in LinkML

Existing ASM schema → documentation

Use A2C → C2L pipeline to generate LinkML for documentation/browsing

Validation

Always validate against ASM JSON Schema (authoritative); use LinkML for authoring ergonomics only

Vocabulary authoring

Author enums in LinkML with meaning → generate vocabulary .voc.ttl stubs

Schema evolution

Track canonical subset changes in LinkML (better diff/merge tooling); regenerate ASM artifacts

6.5 What Cannot Interoperate (Hard Boundaries)

The following scenarios require framework-native authoring - no automated translation is viable:

  • Datacubes with full dimension semantics - must be authored in ASM JSON Schema
  • Polymorphic value dual-form fields - must be authored in ASM; LinkML union types are a poor approximation
  • Document pattern hierarchy - the 3-tier technique template must be ASM-native
  • Runtime vocabulary resolution - ASM's manifest-gated enum validation has no LinkML equivalent
  • Computed/derived slots with enforcement - must remain LinkML-only (no ASM representation)
  • NDArray with shape constraints - must remain LinkML-only (ASM datacube is different)
  • Mixin-based reuse - must remain LinkML-only (flatten for ASM)


7. Worked Examples

7.1 Mass Measurement (Successful Round-Trip)

A simple mass measurement field - fully within the canonical subset.

LinkML:

id: https://example.org/mass-measurement
name: mass_measurement
prefixes:
  qudt: http://qudt.org/vocab/unit/
  linkml: https://w3id.org/linkml/
imports:
  - linkml:types

classes:
  MassMeasurement:
    class_uri: http://purl.allotrope.org/ontologies/result#AFR_0001234
    description: A single mass measurement reading
    attributes:
      sample_identifier:
        range: string
        required: true
        description: Unique identifier for the sample
      mass:
        range: float
        required: true
        minimum_value: 0
        description: Measured mass value
        unit:
          ucum_code: mg
      mass_unit:
        range: MassUnitEnum
        required: true

enums:
  MassUnitEnum:
    permissible_values:
      mg:
        meaning: qudt:Milligram
      g:
        meaning: qudt:Gram
      kg:
        meaning: qudt:Kilogram

ASM JSON Schema:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$defs": {
    "massMeasurementDocument": {
      "$asm.pattern": "indexed datum",
      "type": "object",
      "properties": {
        "sample identifier": {
          "$asm.pattern": "value datum",
          "$asm.type": "http://www.w3.org/2001/XMLSchema#string",
          "$asm.property-class": "http://purl.allotrope.org/ontologies/result#AFR_0005678",
          "type": "string"
        },
        "mass": {
          "$asm.pattern": "quantity datum",
          "$asm.property-class": "http://purl.allotrope.org/ontologies/result#AFR_0001234",
          "type": "object",
          "properties": {
            "value": { "type": "number", "minimum": 0 },
            "unit": { "$ref": "#/$defs/massUnits" }
          },
          "required": ["value", "unit"]
        }
      },
      "required": ["sample identifier", "mass"]
    },
    "massUnits": {
      "type": "string",
      "enum": ["mg", "g", "kg"]
    }
  }
}

ASM Vocabulary stub (.voc.ttl):

@prefix af-r: <http://purl.allotrope.org/ontologies/result#> .
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .

af-r:AFR_0001234 a owl:Class ;
    skos:prefLabel "mass" ;
    skos:definition "A measured mass value." .

Round-trip fidelity: Complete - all information preserved in both directions.


7.2 UV-Vis Spectrum (Partial - Mapping Boundary)

A UV-Vis absorbance measurement showing where the canonical subset ends.

LinkML (expressible portion):

classes:
  UVVisDocument:
    description: A single UV-Vis measurement result
    attributes:
      sample_identifier:
        range: string
        required: true
      wavelength_range_start:
        range: float
        unit:
          ucum_code: nm
      wavelength_range_end:
        range: float
        unit:
          ucum_code: nm
      detector_type:
        range: DetectorTypeEnum
      # CANNOT EXPRESS: the absorbance spectrum datacube
      # CANNOT EXPRESS: ordered measurement documents with @index
      # CANNOT EXPRESS: polymorphic custom information items

enums:
  DetectorTypeEnum:
    permissible_values:
      photodiode_array:
        meaning: http://purl.allotrope.org/ontologies/equipment#AFE_0001234
      single_wavelength:
        meaning: http://purl.allotrope.org/ontologies/equipment#AFE_0005678

ASM (full representation):

{
  "$asm.pattern": "aggregate datum",
  "UV-vis absorbance spectrum aggregate document": {
    "data system document": { ... },
    "UV-vis absorbance spectrum document": [{
      "@index": 1,
      "$asm.pattern": "indexed datum",
      "measurement aggregate document": {
        "measurement document": [{
          "@index": 1,
          "sample document": {
            "sample identifier": "SAMPLE-001"
          },
          "device control aggregate document": {
            "device control document": [{
              "@index": 1,
              "detector type": "photodiode array detector"
            }]
          },
          "absorbance spectrum": {
            "$asm.pattern": "datacube",
            "cube-structure": {
              "dimensions": [{
                "@componentDatatype": "double",
                "concept": "wavelength",
                "unit": "nm",
                "scale": "interval"
              }],
              "measures": [{
                "@componentDatatype": "double",
                "concept": "absorbance",
                "unit": "AU",
                "$asm.fill-value": -999.0
              }]
            },
            "data": {
              "dimensions": [[200.0, 201.0, 202.0, 203.0]],
              "measures": [[0.142, 0.156, 0.173, -999.0]]
            }
          }
        }]
      }
    }]
  }
}

What maps (canonical subset): sample identifier, detector type enum, wavelength range scalars.

What does NOT map:

Feature

Direction

Reason

Datacube structure

ASM → LinkML

No per-dimension metadata in NDArray

@index injection

ASM → LinkML

No automatic index property

3-tier document hierarchy

ASM → LinkML

No structural template mechanism

$asm.fill-value: -999.0

ASM → LinkML

No sentinel concept

Polymorphic value form

ASM → LinkML

Single range per slot

Mixin-based composition

LinkML → ASM

No mixin in JSON Schema

slot_usage refinement

LinkML → ASM

No per-context narrowing


7.3 Datacube (Mapping Failure)

Demonstrating a complete mapping failure - the datacube concept is structurally incompatible.

ASM Datacube (source of truth):

{
  "$asm.pattern": "datacube",
  "cube-structure": {
    "dimensions": [
      { "@componentDatatype": "double", "concept": "retention time", "unit": "s", "scale": "interval" },
      { "@componentDatatype": "double", "concept": "wavelength", "unit": "nm", "scale": "interval" }
    ],
    "measures": [
      { "@componentDatatype": "double", "concept": "absorbance", "unit": "AU", "$asm.fill-value": 0.0 }
    ]
  },
  "data": {
    "dimensions": [
      [0.0, 0.5, 1.0, 1.5, 2.0],
      [200.0, 250.0, 300.0, 350.0]
    ],
    "measures": [
      [[0.1, 0.2, 0.3, 0.4], [0.2, 0.3, 0.4, 0.5], [0.3, 0.4, 0.5, 0.6], [0.15, 0.25, 0.35, 0.45], [0.05, 0.1, 0.15, 0.2]]
    ]
  }
}

Closest LinkML approximation:

classes:
  AbsorbanceCube:
    description: 2D absorbance data (retention time × wavelength)
    attributes:
      retention_times:
        range: float
        multivalued: true
        # LOST: concept="retention time", unit="s", scale="interval"
        # LOST: @componentDatatype
        annotations:
          asm_concept: retention time
          asm_unit: s
          asm_scale: interval
      wavelengths:
        range: float
        multivalued: true
        annotations:
          asm_concept: wavelength
          asm_unit: nm
          asm_scale: interval
      absorbance_matrix:
        range: float
        multivalued: true
        # LOST: 2D structure (this is a flat list)
        # LOST: fill-value semantics
        # LOST: relationship between dimensions and measures
        annotations:
          asm_fill_value: "0.0"

What is lost:

  • The structural relationship between dimensions and measures (the "cube" concept)
  • The 2D nature of the measure data (flattened to 1D list)
  • Per-dimension semantic metadata as first-class validated properties
  • Fill-value semantics (sentinel vs. actual value distinction)
  • The columnar parallel-array layout (dimensions[0] aligns with data[0])
  • Component datatype declarations separate from range

Conclusion: The datacube is not approximable in LinkML. It must be authored and validated in ASM natively. A LinkML schema for a technique that includes datacubes should either:

  • Omit the datacube and reference it as an opaque sub-document
  • Model it as an annotated class with best-effort slot structure (losing validation power)
  • Accept that the datacube portion cannot round-trip


8. Summary Matrix

Category

Canonical (bidirectional)

LinkML-only (no ASM)

ASM-only (no LinkML)

Entity/Class

-

-

Field/Slot

-

-

Scalar types

-

Polymorphic dual-form

Required/Optional

recommended

-

Cardinality

-

-

Composition

-

-

Enum (static)

-

-

Enum (dynamic/runtime)

-

reachable_from

Manifest-gated vocab resolution

Quantity

-

-

Unit reference

(QUDT)

-

Validated symbol→IRI mapping

Semantic IRI

-

-

Pattern constraint

Structured patterns

-

Numeric bounds

-

-

Inheritance

-

is_a + mixins + slot_usage

rdfs:subClassOf (vocab only)

Arrays

(basic)

NDArray shape/dtype

Ordered+indexed, mixed+typed

Datacube

-

-

Full cube model

Document patterns

$asm.pattern (10 patterns)

Computed fields

-

equals_expression

-

Rules (if-then)

-

preconditions/postconditions

JSON Schema if/then (different semantics)

Unique keys

-

unique_keys (compound)

-

Annotations

(passthrough)

Extensible, validated via instantiates

$asm.* (operational)

Modularity

Import chain (named DAG)

$ref graph (implicit DAG) + manifest root declaration

Vocabulary

(basic)

-

Full OWL with restrictions


9. LinkML Tooling Applicability to ASM

This section analyzes whether existing LinkML tools can be applied directly to ASM schemas or ASM instance data, and where custom tooling is required.

9.1 Tool Inventory

Tool

Purpose

Applicable to ASM?

gen-json-schema

Generate JSON Schema from LinkML YAML

⚠️ Partial - generates standard JSON Schema but cannot emit $asm.* keywords

linkml-validate

Validate instance data against schema

No - cannot validate ASM instances (polymorphic values, $asm.* semantics)

gen-owl

Generate OWL ontology

Yes - can generate vocabulary stubs for ASM .voc.ttl

gen-python / gen-pydantic

Generate Python dataclasses/models

⚠️ Partial - useful for tooling code, not for ASM validation

gen-doc

Generate Markdown/HTML documentation

Yes - works for documenting the LinkML-authored subset

linkml-convert

Convert data between JSON/YAML/CSV/RDF

No - ASM JSON structure (polymorphic values, @type/@index) is incompatible

schema-automator

Bootstrap schema from data samples

⚠️ Partial - can infer basic structure from ASM JSON but misses all $asm.* semantics

SchemaView (Python API)

Programmatic schema traversal

Yes - useful for building custom ASM generators

gen-erdiagram

Generate ER diagrams

Yes - works for the LinkML-authored portion

schemasheets

Author schemas from spreadsheets

Yes - viable authoring surface for technique field inventories

9.2 Schema Generation: gen-json-schema → ASM

What it produces:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$defs": {
    "Person": {
      "type": "object",
      "properties": {
        "id": { "type": "string" },
        "name": { "type": "string" },
        "age": { "type": "integer", "minimum": 0 }
      },
      "required": ["id"],
      "additionalProperties": false
    }
  }
}

What ASM needs:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$defs": {
    "sampleDocument": {
      "$asm.pattern": "indexed datum",
      "type": "object",
      "properties": {
        "sample identifier": {
          "$asm.pattern": "value datum",
          "$asm.type": "http://www.w3.org/2001/XMLSchema#string",
          "$asm.property-class": "http://purl.allotrope.org/ontologies/result#AFR_0005678",
          "type": "string"
        }
      },
      "required": ["sample identifier"]
    }
  }
}

Gaps:

Aspect

gen-json-schema output

ASM requirement

JSON Schema draft

Draft-07

Draft 2020-12

$asm.* keywords

Not emitted

Required on every property

Property naming

camelCase/snake_case

Space-separated natural language

additionalProperties

false (closed world)

Typically absent (open for extensions)

Polymorphic values

Not supported

Required for most fields

Document patterns

Not emitted

Required structural classification

Quantity values

Separate slots for value and unit

Single {value, unit} object

Verdict: gen-json-schema cannot produce valid ASM schemas directly. A custom ASM generator is required - but it can reuse LinkML's SchemaView API and LifecycleMixin hooks to build one.

9.3 Vocabulary Generation: gen-owl → ASM .voc.ttl

What it produces:

@prefix linkml: <https://w3id.org/linkml/> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

ex:Person a owl:Class ;
  rdfs:label "Person" ;
  rdfs:subClassOf ex:NamedThing .

ex:name a owl:DatatypeProperty ;
  rdfs:label "name" ;
  rdfs:domain ex:Person ;
  rdfs:range xsd:string .

What ASM vocabularies need:

af-r:AFR_0005678 a owl:Class ;
  rdfs:subClassOf af-r:AFR_0001000 ;
  skos:prefLabel "sample identifier" ;
  skos:definition "A unique string identifying a sample." ;
  rdfs:isDefinedBy <http://purl.allotrope.org/ontologies/result> .

Gaps:

Aspect

gen-owl output

ASM vocabulary requirement

Identifier scheme

Human-readable URIs

Opaque AFO-style IRIs (AFR_XXXXXXX)

Label property

rdfs:label

skos:prefLabel (required for $asm.lookup-property resolution)

Documentation

rdfs:comment

skos:definition

Ontology header

Minimal

Full OWL ontology with owl:importsowl:versionIRIdct:titledct:created

Class hierarchy source

LinkML is_a

May differ from AFO taxonomy

Namespace

Schema-derived

Must match AFO/ZONTAL namespace conventions

Verdict: gen-owl produces a useful starting point for vocabulary stubs. A post-processing step can:

  • Replace rdfs:label with skos:prefLabel
  • Add skos:definition from LinkML description
  • Add ontology header boilerplate
  • Reassign IRIs to AFO namespace pattern

This is viable as a semi-automated pipeline with manual IRI assignment.

9.4 Data Validation: linkml-validate on ASM Instances

Can linkml-validate validate ASM .asm files?

No. The fundamental blockers are:

  • Polymorphic value types - ASM fields accept both "text" and {"@type": "label", "value": "text"}. LinkML validation expects a single consistent shape per slot.
  • Property naming - ASM uses space-separated names ("sample identifier"). LinkML expects identifiers conforming to programming language conventions. The preserve-names flag in gen-json-schema helps but doesn't solve runtime validation.
  • @type and @index injection - These structural properties are not part of any LinkML class definition but are present in ASM instances.
  • Datacube structure - Not expressible in LinkML; would fail validation.
  • Manifest-gated vocabulary resolution - LinkML validates against a fixed schema; it cannot resolve enum validity based on a runtime manifest.

Partial use case: If an ASM instance is pre-processed to strip polymorphic wrappers, remove @index/@type injections, and flatten quantities into separate value/unit slots, then linkml-validate could validate the resulting normalized form. This is useful for pipeline testing (validate converter output structure before ASM-specific decoration) but not for final ASM compliance.

9.5 Schema Authoring: schemasheets for Technique Field Inventories

schemasheets allows authoring LinkML schemas from spreadsheets - a natural fit for the tabular field inventories that precede technique schema authoring.

Example spreadsheet:

class

field

range

required

description

unit

meaning

UVVisMeasurement

wavelength

float

true

Excitation wavelength

nm

AFR_0002001

UVVisMeasurement

absorbance

float

true

Measured absorbance

AU

AFR_0002002

UVVisMeasurement

sample_id

string

true

Sample identifier


AFR_0005678

UVVisMeasurement

detector_type

DetectorTypeEnum

true

Detector technology



Workflow:

  • Domain expert fills spreadsheet with field inventory
  • schemasheets converts to LinkML YAML
  • Custom generator transforms to ASM JSON Schema + vocabulary stubs
  • Schema author manually adds datacubes, document hierarchy, polymorphic patterns

Verdict: Viable and ergonomic for the ~60% of technique schema content that falls within the canonical subset.

9.6 Documentation: gen-doc for ASM Schema Browsing

gen-doc generates Markdown/HTML documentation from LinkML schemas - useful for producing browsable technique schema documentation.

What works:

  • Class descriptions with slot tables
  • Enum value listings with ontology links
  • Inheritance diagrams (ER diagrams via gen-erdiagram)
  • Cross-references between classes

What doesn't work:

  • Datacube visualization
  • Document pattern hierarchy rendering
  • Polymorphic value form documentation
  • Manifest closure information

Verdict: Useful for the canonical subset. ASM-specific content (datacubes, patterns) requires supplementary documentation.

9.7 Programmatic API: SchemaView for Custom ASM Generators

The most productive use of LinkML tooling for ASM is building a custom generator using the SchemaView programmatic API:

from linkml_runtime.utils.schemaview import SchemaView

sv = SchemaView("technique.yaml")

for cls in sv.all_classes().values():
  if cls.abstract:
    continue
  # Generate ASM JSON Schema object
  asm_obj = {
    "$asm.pattern": infer_pattern(cls),
    "type": "object",
    "properties": {}
  }
  for slot in sv.class_induced_slots(cls.name):
    asm_obj["properties"][to_asm_name(slot.name)] = {
      "$asm.pattern": "value datum",
      "$asm.type": range_to_xsd(slot.range),
      "$asm.property-class": slot.slot_uri,
      "type": range_to_json_type(slot.range)
    }

This approach:

  • Leverages LinkML's inheritance resolution (class_induced_slots flattens hierarchy)
  • Allows custom $asm.* annotation injection
  • Can read annotations from LinkML slots to carry ASM-specific metadata
  • Produces ASM-compliant output with full control over naming, patterns, and structure

Verdict: The recommended integration path. SchemaView + custom generator = LinkML authoring with ASM output.

9.8 Summary: Tooling Applicability Matrix

Use Case

Tool

Applicability

Custom Work Required

Author technique field inventory

schemasheets

Direct

Spreadsheet template

Author technique schema

LinkML YAML

Direct

None (for canonical subset)

Generate ASM JSON Schema

gen-json-schema

Insufficient

Custom ASM generator via SchemaView

Generate vocabulary stubs

gen-owl

⚠️ Partial

Post-processing (labels, headers, IRIs)

Validate ASM instances

linkml-validate

Incompatible

Dedicated ASM validator

Validate pre-ASM pipeline output

linkml-validate

⚠️ After normalization

Normalization pre-processor

Generate documentation

gen-doc + gen-erdiagram

Direct

Supplement for ASM-specific content

Bootstrap schema from samples

schema-automator

⚠️ Basic structure only

Manual $asm.* annotation

Build custom generators

SchemaView API

Direct

Generator implementation

Convert instance formats

linkml-convert

Incompatible

Custom ASM serializer

9.9 Recommended Toolchain

Spreadsheet Field inventory
schemasheets Import and transform
LinkML YAML technique.yaml authoring layer
SchemaView (Python API) Shared traversal layer for ASM schema generation, vocabulary stubs, and documentation artifacts
Custom ASM Generator Emit ASM JSON Schema + $asm.* keywords
gen-owl + Post-process Produce .voc.ttl vocabulary stubs
gen-doc + gen-erdiagram Generate browsable HTML/Markdown docs
ASM JSON Schema + $asm.* extensions
.voc.ttl Stubs Vocabulary scaffold outputs
HTML/MD Docs Browsable generated documentation

Key insight: The existing LinkML toolchain provides ~40% of the pipeline out of the box. The critical missing piece is a custom ASM generator (analogous to gen-json-schema but emitting ASM-compliant output with $asm.* keywords, polymorphic value patterns, and document hierarchy structure). This generator would use SchemaView for schema traversal and LinkML annotations to carry ASM-specific metadata through the authoring layer.


10. Conclusions

10.1 Interoperability Viability

The common canonical subset covers approximately 60–70% of typical technique schema content (entity definitions, scalar fields, enumerations, quantities, compositions, basic constraints). This is sufficient to use LinkML as an authoring surface for the majority of a technique schema, with targeted ASM-native authoring for:

  • Datacubes (100% ASM-native)
  • Polymorphic value patterns (100% ASM-native)
  • Document hierarchy template structure (ASM-native, though LinkML class hierarchy can approximate)
  • Ordered/mixed array semantics (partial ASM-native augmentation)

10.2 Recommended Architecture

LinkML Schema (authoring) - Entities, fields, enums
- Quantities with QUDT units
- Compositions
- Constraints, descriptions

Custom ASM Generator

ASM JSON Schema (validation) + $asm.* annotations
+ Manual datacube additions
+ Manual polymorphic patterns
Vocabulary .voc.ttl (semantic) Generated stubs + manual OWL
Manifest + Instance Documents

10.3 Key Takeaway

LinkML and ASM are complementary, not competing frameworks. LinkML excels at schema authoring ergonomics (YAML, inheritance, modularity, multi-target generation). ASM excels at scientific data validation (two-layer architecture, domain-specific patterns, GxP compliance). ASM's ten structural patterns are domain-agnostic — the technique schema hierarchy is the first and most mature instantiation, but the same patterns extend to 19 document hierarchies spanning materials, samples, analytical, results, methods, specifications, instruments, equipment, tests, experiments, procedures, recipes, studies, programs, regulatory submissions, ELN, LIMS, MES, and ERP (Colsman, 2026). A viable interoperability strategy uses LinkML for authoring the common subset and ASM for the final validation artifact, with clear boundaries at the three high-severity gaps (datacubes, polymorphic values, document patterns).


References

Allotrope Foundation. (2024). Allotrope Framework and Simple Model (ASM). Available at: https://www.allotrope.org/product-asm

Colsman, W. (2026). The Connected Domains Model for the Pharmaceutical and Life Sciences Industry: 19 Domain-Specific Document Models for the ICAD Context Graph. ZONTAL Inc.

More to Read

Continue exploring insights on scientific data interoperability.