How can I use application profiles from NFDI4Ing AIMS?#
NFDI4Ing AIMS can be used to define application profiles. An application profile describes which metadata a resource should provide and which constraints that metadata should satisfy. Since AIMS profiles can be expressed as SHACL shapes, they fit naturally into h5rdmtoolbox linked data workflows.
A typical workflow is:
Create or select an application profile in AIMS.
Export or obtain the profile as SHACL shapes.
Annotate HDF5 groups, datasets, and attributes with RDF terms, for example from Metadata4Ing (M4I) or other controlled vocabularies.
Validate the RDF representation of the file against the AIMS application profile with
validate_hdf.
This helps check missing or inconsistent metadata before sharing, catalog indexing, repository upload, or publication.
The validation call follows the same pattern as other SHACL validations in h5rdmtoolbox:
import h5rdmtoolbox as h5tbx
res = h5tbx.validate_hdf(
hdf_source="my_file.hdf",
shacl_data="aims_application_profile.ttl",
)
res.conforms
Example
Let’s assume we defined a profile and copied it as text or downloaded it as a ttl file. Here is the content of the application profile:
application_profile = """
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix m4i: <http://w3id.org/nfdi4ing/metadata4ing#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix qudt: <http://qudt.org/schema/qudt/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix aps: <https://w3id.org/nfdi4ing/profiles/> .
<
> dcterms:created "2024-08-22"^^xsd:date ;
dcterms:creator "Metadata4Ing" ;
dcterms:description "Eine Variable, die einen Double oder Integer als Wert erwartet"@de, "A variable that expects a double or integer as value"@en ;
dcterms:license <http://spdx.org/licenses/CC0-1.0> ;
dcterms:title "m4i Numerische Variable"@de, "m4i Numerical Variable"@en ;
a sh:NodeShape ;
owl:imports <http://qudt.org/vocab/quantitykind>, <http://qudt.org/vocab/unit/>, <https://w3id.org/nfdi4ing/profiles/d7d86748-b7ec-448f-9e45-cb1a1fd26b7e/> ;
sh:closed false ;
sh:node <https://w3id.org/nfdi4ing/profiles/d7d86748-b7ec-448f-9e45-cb1a1fd26b7e/> ;
sh:property [
sh:order 1 ;
sh:maxCount 1 ;
sh:minCount 1 ;
sh:name "Quantity Kind"@en, "Größenart"@de ;
sh:path m4i:hasKindOfQuantity ;
sh:class qudt:QuantityKind ;
], [
sh:order 2 ;
sh:maxCount 1 ;
sh:minCount 1 ;
sh:name "Numerical Value"@en, "Numerischer Wert"@de ;
sh:path m4i:hasNumericalValue ;
sh:xone (
[
rdfs:label "Ganzzahl"@de, "Integer"@en ;
sh:datatype xsd:integer ;
]
[
rdfs:label "Floating point"@en, "Fließkommazahl"@de ;
sh:datatype xsd:double ;
]
) ;
], [
sh:order 3 ;
sh:maxCount 1 ;
sh:minCount 1 ;
sh:name "Unit"@en, "Einheit"@de ;
sh:path m4i:hasUnit ;
sh:class qudt:Unit ;
] ;
sh:targetClass m4i:NumericalVariable .
"""
Now we create two HDF5 files and validate both against the application profile.
The first file will fail, because we don’t describe the unit correctly. The second file conforms with the application profile.
import h5rdmtoolbox as h5tbx
from ontolutils import M4I, QUDT_UNIT, QUDT_KIND
with h5tbx.File() as h5:
ds = h5.create_dataset("u", data=1, attrs=dict(unit="m/s", qk="vel"))
ds.rdf.type = M4I.NumericalVariable
ds.rdf.data_predicate = M4I.hasNumericalValue
ds.rdf["qk"].predicate = M4I.hasKindOfQuantity
ds.rdf["qk"].object = QUDT_KIND.Velocity
filename1 = h5.hdf_filename
with h5tbx.File() as h5:
ds = h5.create_dataset("u", data=1, attrs=dict(unit="m/s", qk="vel"))
ds.rdf.type = M4I.NumericalVariable
ds.rdf.data_predicate = M4I.hasNumericalValue
ds.rdf["unit"].predicate = M4I.hasUnit
ds.rdf["unit"].object = QUDT_UNIT.M_PER_SEC
ds.rdf["qk"].predicate = M4I.hasKindOfQuantity
ds.rdf["qk"].object = QUDT_KIND.Velocity
filename2 = h5.hdf_filename
v1 = h5tbx.validate_hdf(
hdf_source=filename1,
shacl_data=application_profile,
inference="rdfs",
do_owl_imports=True,
)
v1.messages
['Value does not have class qudt:QuantityKind',
'Less than 1 values on <https://example.org/hdf5file#tmp0.hdf/u>->m4i:hasUnit']
v2 = h5tbx.validate_hdf(
hdf_source=filename1,
shacl_data=application_profile,
inference="rdfs",
do_owl_imports=True,
)
v2.messages
['Value does not have class qudt:QuantityKind',
'Less than 1 values on <https://example.org/hdf5file#tmp0.hdf/u>->m4i:hasUnit']
See the SHACL validation guide for a complete example of validating HDF5 metadata against an AIMS-style application profile.