HDF5 and RDF: FAIR Attributes#
According to F1 of the FAIR Principles attributes shall be assigned to globally unique and persistent identifiers.
Here’s what www.go-fair.org says about it:
“Globally unique and persistent identifiers remove ambiguity in the meaning of your published data by assigning a unique identifier to every element of metadata and every concept/measurement in your dataset. In this context, identifiers consist of an internet link (e.g., a URL that resolves to a web page that defines the concept such as a particular human protein). Many data repositories will automatically generate globally unique and persistent identifiers to deposited datasets. Identifiers can help other people understand exactly what you mean, and they allow computers to interpret your data in a meaningful way (i.e., computers that are searching for your data or trying to automatically integrate them). Identifiers are essential to the human-machine interoperation that is key to the vision of Open Science. In addition, identifiers will help others to properly cite your work when reusing your data.”
The h5rdmtoolbox allows assigning attributes (and their data) to identifiers. For this, each name and value of an attribute may obtain an IRI (internationalized resource identifier). The following outlines, how it is done.
Concept#
We can interpret HDF5 objects, their attribute names and attribute values as RDF triples (subject-predicate-object), where…
… a group or dataset is a subject
… the attribute name is a predicate
… and the attriute value is an object
In the following, we would like to describe the content of an HDF5 file. There will be a dataset or random data generated by a person, which can be identified/described by a researcher ID (ORCID).
We as humans may understand the content of such an HDF5 file. For machines to interpret the data, we need to associate URIs with the HDF5 objects. In fact, sometimes it may also not very clear to humans, what is meant with a certain attribute. To be unambiguous about it, a URI helps. Think of the attribute “contact”, we will define. Is it a person or an organization? Note, that URI and IRI may be used synonymously - IRI is built on URI by expanding the set of permitted characters.
Let’s build the example step by step. We start with creating the group “contact”:
import h5rdmtoolbox as h5tbx
Describing an HDF5 file with persistent metadata#
Example part 1: A contact person#
The file is written by an author. We create a group. It contains all relevant contact data, i.e. the ORCID. The content if the group thus describes the contact person and therefore is a person. The group itself, however, gets the predicate has author:
with h5tbx.File(mode='w') as h5:
grp = h5.create_group('contact', attrs=dict(orcid='https://orcid.org/0000-0001-8729-0482'))
grp.rdf.predicate = 'https://schema.org/author'
grp.rdf.type = 'http://xmlns.com/foaf/0.1/Person' # what the content of group is, namely a foaf:Person
grp.rdf.subject = 'https://orcid.org/0000-0001-8729-0482' # corresponds to @ID in JSON-LD
grp.rdf.predicate['orcid'] = 'http://w3id.org/nfdi4ing/metadata4ing#orcidId'
grp.attrs['first_name', 'http://xmlns.com/foaf/0.1/firstName'] = 'Matthias'
o = grp.rdf.predicate['orcid']
h5.dump(collapsed=False)
hdf_filename = h5.hdf_filename
Using the rdf accessory, we can assign the objects (dataset, groups, attributes) with the internationalized resource identifier (IRI). An IRI a web resource and points to the definition in an ontology, e.g. “contact” is a “Person” and is defined in the ontology FOAF: ‘http://xmlns.com/foaf/0.1/Person’. The person “has a researcher ID”. This predicate is described in the M4i (metadata4ing) ontology: ‘http://w3id.org/nfdi4ing/metadata4ing#orcid’
Assigning metadata to the file rather than the rootgroup#
If we want to describe the file using attributes, the rootgroup “/” is the way to go. However, there we might want to distinguish between the actual file and the root group. For this, we can also use the accessory frdf, which allows assigning rdf triples to the file.
In the following example, we add the creation date as a rootgroup-attribute but explain it as a file attribute rather than a group attribute. For the effect, check out the jsonld-dump:
from datetime import datetime
with h5tbx.File(mode='w') as h5:
h5.attrs["creation_date"] = datetime.today()
h5.frdf["creation_date"].predicate = "http://purl.org/dc/terms/created"
print(h5.dump_jsonld(structural=True, indent=2))
{
"@context": {
"dcterms": "http://purl.org/dc/terms/",
"hdf5": "http://purl.allotrope.org/ontologies/hdf5/1.8#"
},
"@graph": [
{
"@id": "_:Na4106238a83a44ceb9e408986c568a3e",
"@type": "hdf5:File",
"dcterms:created": {
"@id": "20250208182556830408"
},
"hdf5:rootGroup": {
"@id": "_:N6a912973040b4c4283c3961cbf40681c",
"@type": "hdf5:Group",
"hdf5:attribute": {
"@id": "_:N11c30f3902f94ffa81d2f3dadf3bfc01",
"@type": "hdf5:Attribute",
"hdf5:name": "creation_date",
"hdf5:value": "20250208182556830408"
},
"hdf5:name": "/"
}
}
]
}
From now on, let’s same some work and use the package namespacelib, which simplifies the work with the namespaces, so that we don’t have to type the full IRI address. Some popular ones are implemented in the rdflib package, too:
from ontolutils.namespacelib import M4I, OBO, QUDT_UNIT, QUDT_KIND
from rdflib.namespace import FOAF
As a result, we can type the following:
M4I.orcidId # equal to http://w3id.org/nfdi4ing/metadata4ing#orcidId
rdflib.term.URIRef('http://w3id.org/nfdi4ing/metadata4ing#orcidId')
Example part 2: A random data dataset#
Next, we add the random data dataset with units. We can even describe what type the data is. In our case it shall be velocity data. Without this specification it would otherwise not be clear to the user (or a machine):
import numpy as np
with h5tbx.File(hdf_filename, mode='r+') as h5:
ds = h5.create_dataset('grp/random_velocity', data=np.random.random(100))
ds.attrs.create('units',
rdf_predicate=M4I.hasUnit,
data='m/s',
rdf_object=QUDT_UNIT.M_PER_SEC)
ds.attrs.create('quantity_kind',
data='velocity',
rdf_predicate=M4I.hasKindOfQuantity,
rdf_object=QUDT_KIND.Velocity)
h5.dump(collapsed=False)
-
-
-
(100) [float64]
Now, let’s go further and describe how the random dataset was created and that the contact was involved in it:
from datetime import datetime
with h5tbx.File(hdf_filename, mode='r+') as h5:
proc = h5.create_group('processing_info')
proc.rdf.subject = M4I.ProcessingStep
proc.attrs['has_participants', OBO.has_participant] = h5['contact']
start_time = datetime.today()
end_time = datetime.today()
proc.attrs.create('start_time', data=start_time,
rdf_predicate='https://schema.org/startTime')
proc.attrs.create('end_time', data=end_time,
rdf_predicate='https://schema.org/startTime')
proc.attrs['output', 'http://purl.obolibrary.org/obo/RO_0002234'] = h5['grp/random_velocity'].name
h5tbx.dump(hdf_filename, collapsed=False)
-
-
-
(100) [float64]
-
- end_time
https://schema.org/startTime: 2025-02-08T18:25:56.866437 - has_participants
http://purl.obolibrary.org/obo/RO_0000057: /contact - output
http://purl.obolibrary.org/obo/RO_0002234: /grp/random_velocity - start_time
https://schema.org/startTime: 2025-02-08T18:25:56.866432
- end_time
Example part 3: Assigning JSON-LD to describe data#
Until now, we used IRIs to assign meaning to HDF5 attributes, e.g. proc.rdf.subject = M4I.ProcessingStep.
Sometimes, data cannot be expressed by a single IRI, because there is no globally unique identifier. Let’s examine this case by using the SSNO Ontology.
In the example below, the attribute “standard_name” of the dataset “u” refers to “x_velocity” being the Standard name of the HDF5 dataset “u”. A Standard name has a name, description and SI unit and may be associated to a Standard Name Table in which it is listed. In our case, the Standard name “x_velocity” has no globally unique identifier, hence we need to describe it by a JOSN-LD string:
sn_xvel = """{
"@context": {
"ssno": "https://matthiasprobst.github.io/ssno#"
},
"@type": "ssno:StandardName",
"ssno:standardName": "x_velocity",
"ssno:unit": "http://qudt.org/vocab/unit/M-PER-SEC",
"ssno:description": "X-component of a velocity vector."
}"""
with h5tbx.File() as h5:
h5.create_dataset("u", data=[1,2,3], attrs={"standard_name": "x_velocity"})
h5.u.rdf["standard_name"].predicate = "https://matthiasprobst.github.io/ssno#hasStandardName"
# h5.u.rdf["standard_name"].object = sn_xvel
h5.u.rdf["standard_name"].object = sn_xvel
h5.dump(False)
h5jld = h5.dump_jsonld(indent=2, structural=False)
-
-
(3) [int64]
- standard_name
https://matthiasprobst.github.io/ssno#hasStandardName: x_velocity
{ "@context": { "ssno": "https://matthiasprobst.github.io/ssno#" }, "@type": "ssno:StandardName", "ssno:standardName": "x_velocity", "ssno:unit": "http://qudt.org/vocab/unit/M-PER-SEC", "ssno:description": "X-component of a velocity vector." }
- standard_name
The JSON-LD dump shows that “standard_name” is correctly associated with our JSON-LD string for the ssno:StandardName:
print(h5jld)
{
"@context": {
"hdf5": "http://purl.allotrope.org/ontologies/hdf5/1.8#",
"ssno": "https://matthiasprobst.github.io/ssno#"
},
"@graph": [
{
"@id": "_:N9b8ec79f2cff4e26ae821db239380509",
"ssno:hasStandardName": [
{
"@id": "_:N30440285b3114bec9c97202391a339fc",
"@type": "ssno:StandardName",
"ssno:description": "X-component of a velocity vector.",
"ssno:standardName": "x_velocity",
"ssno:unit": "http://qudt.org/vocab/unit/M-PER-SEC"
},
"x_velocity"
]
}
]
}
How to make use of the FAIR HDF5 file?#
There are three ways, how the above IRI assignments help us and how we might want to use the information:
Visual inspection by dumping the content to screen: This will outline the file (meta) content and we can click on the attributes with IRIs, which will explain the attribute (data)
We can extract a JSON-LD file. This is useful for other processes. We can also investigate this file further with tools like JSON-LD-playground.
Access IRI in (Python) code
1. Visual inspection#
The dump() method will now add IRI-icons. Click on it and get redirected to the resources:
h5tbx.dump(hdf_filename, collapsed=False)
-
-
-
(100) [float64]
-
- end_time
https://schema.org/startTime: 2025-02-08T18:25:56.866437 - has_participants
http://purl.obolibrary.org/obo/RO_0000057: /contact - output
http://purl.obolibrary.org/obo/RO_0002234: /grp/random_velocity - start_time
https://schema.org/startTime: 2025-02-08T18:25:56.866432
- end_time
2. JSON-LD extraction#
Write the JSON-LD file and share it with others or a repository. The toolbox provides dump-methods through the jsonld module. It might look a bit overwelming, however dedicated scripts can perfectly work with it while humans still can read it (with a bit of practice and patience…):
print(
h5tbx.dump_jsonld(
hdf_filename,
indent=2,
context={'m4i': 'http://w3id.org/nfdi4ing/metadata4ing#',
'foaf': 'http://xmlns.com/foaf/0.1/'}
)
)
{
"@context": {
"foaf": "http://xmlns.com/foaf/0.1/",
"hdf5": "http://purl.allotrope.org/ontologies/hdf5/1.8#",
"m4i": "http://w3id.org/nfdi4ing/metadata4ing#",
"obo": "http://purl.obolibrary.org/obo/",
"schema": "https://schema.org/"
},
"@graph": [
{
"@id": "_:N899b84cb1ef549f78859b6b3368d53c4",
"@type": "hdf5:File",
"hdf5:rootGroup": {
"@id": "_:Ned95842074914f2d81088c185de05d46",
"@type": "hdf5:Group",
"hdf5:member": [
{
"@id": "https://orcid.org/0000-0001-8729-0482",
"@type": [
"hdf5:Group",
"foaf:Person"
],
"foaf:firstName": "Matthias",
"hdf5:attribute": [
{
"@id": "_:N2876255d964141228159780f7529c057",
"@type": "hdf5:Attribute",
"hdf5:name": "first_name",
"hdf5:value": "Matthias"
},
{
"@id": "_:N4d499b0fb0574507a2bd795a263d4f95",
"@type": "hdf5:Attribute",
"hdf5:name": "orcid",
"hdf5:value": {
"@type": "http://www.w3.org/2001/XMLSchema#anyURI",
"@value": "https://orcid.org/0000-0001-8729-0482"
}
}
],
"hdf5:name": "/contact",
"m4i:orcidId": {
"@type": "http://www.w3.org/2001/XMLSchema#anyURI",
"@value": "https://orcid.org/0000-0001-8729-0482"
}
},
{
"@id": "_:N98522107156844909950b3b966ef0638",
"@type": "hdf5:Group",
"hdf5:member": {
"@id": "_:N9fb9ccc69ae140098536046df253b7ea",
"@type": "hdf5:Dataset",
"hdf5:attribute": [
{
"@id": "_:Ne722f7465524431fb1c1d1f7064d96bc",
"@type": "hdf5:Attribute",
"hdf5:name": "quantity_kind",
"hdf5:value": [
"velocity",
{
"@id": "http://qudt.org/vocab/quantitykind/Velocity",
"http://www.w3.org/2004/02/skos/core#prefLabel": "velocity"
}
]
},
{
"@id": "_:Nb134d8d2306842d792d09f693ef0a833",
"@type": "hdf5:Attribute",
"hdf5:name": "units",
"hdf5:value": [
"m/s",
{
"@id": "http://qudt.org/vocab/unit/M-PER-SEC",
"http://www.w3.org/2004/02/skos/core#prefLabel": "m/s"
}
]
}
],
"hdf5:datatype": "H5T_FLOAT",
"hdf5:dimension": 1,
"hdf5:name": "/grp/random_velocity",
"hdf5:size": 100,
"m4i:hasKindOfQuantity": {
"@id": "http://qudt.org/vocab/quantitykind/Velocity"
},
"m4i:hasUnit": {
"@id": "http://qudt.org/vocab/unit/M-PER-SEC"
}
},
"hdf5:name": "/grp"
},
{
"@id": "m4i:ProcessingStep",
"@type": "hdf5:Group",
"hdf5:attribute": [
{
"@id": "_:N9c8bd14fab634010a2fdd7c75a6305ed",
"@type": "hdf5:Attribute",
"hdf5:name": "end_time",
"hdf5:value": "2025-02-08T18:25:56.866437"
},
{
"@id": "_:N632d9498a3d141609a68f77bff6f1d22",
"@type": "hdf5:Attribute",
"hdf5:name": "has_participants",
"hdf5:value": "/contact"
},
{
"@id": "_:N53bea4e5125a47d49cd420d5c2e78581",
"@type": "hdf5:Attribute",
"hdf5:name": "output",
"hdf5:value": "/grp/random_velocity"
},
{
"@id": "_:N22fc83d7f4604bb1bac46de88ffe73e6",
"@type": "hdf5:Attribute",
"hdf5:name": "start_time",
"hdf5:value": "2025-02-08T18:25:56.866432"
}
],
"hdf5:name": "/processing_info",
"obo:RO_0000057": "/contact",
"obo:RO_0002234": "/grp/random_velocity",
"schema:startTime": [
"2025-02-08T18:25:56.866437",
"2025-02-08T18:25:56.866432"
]
}
],
"hdf5:name": "/"
}
}
]
}
Dump it to the file rather than to the screen:
from h5rdmtoolbox import jsonld
with open('hdf_meta.jsonld', 'w') as f:
jsonld.dump(hdf_filename, f, indent=2,
context={'m4i': 'http://w3id.org/nfdi4ing/metadata4ing#',
'foaf': 'http://xmlns.com/foaf/0.1/'})
# context={'foaf': 'http://xmlns.com/foaf/0.1/',
# 'm4i': 'http://w3id.org/nfdi4ing/metadata4ing#'})
3. Access IRI in code#
You may want to access the IRI of an attribute with Python within the HDF5 file. E.g. while working with the file, you may ask “Hey, what is ‘contact’ exactly?” or “What does the attribute ‘orcid’ mean?”
with h5tbx.File(hdf_filename) as h5:
person_iri = h5.contact.rdf.subject
orcid_iri = h5.contact.rdf.predicate['orcid']
… Well “contact” is a “Person” defined by the FOAF ontology:
person_iri
'https://orcid.org/0000-0001-8729-0482'
… and “orcid” is a predicate defined by the metadata4ing ontology:
orcid_iri
'http://w3id.org/nfdi4ing/metadata4ing#orcidId'
3.1 Find data based on IRIs#
import rdflib.graph as g
graph = g.Graph()
graph.parse('hdf_meta.jsonld', format='json-ld')
<Graph identifier=N4807bf7e412e4f11a930b98e82909f73 (<class 'rdflib.graph.Graph'>)>
Note, that we need to provide the PREFIXES, if the json-ld data/file does not include the context.
res = graph.query("""
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX m4i: <http://w3id.org/nfdi4ing/metadata4ing#>
SELECT ?id ?orcid
WHERE {
?id a foaf:Person .
?id m4i:orcid ?orcid .
}
""")
for r in res:
print(r)
4. Examples:#
4.1 Read metadata from JSON and write to HDF5#
Suppose we want to store information about the used software to the HDF5 file. It exists as a JSON-LD file based on the codemeta ontolog. For this example, we use the h5rdmtoolbox codemeta.json file from the github repository:
from h5rdmtoolbox.utils import download_file
from pprint import pprint
Download the file:
codemeta_url = 'https://raw.githubusercontent.com/matthiasprobst/h5RDMtoolbox/main/codemeta.json'
dowloaded_filename = download_file(codemeta_url)
2025-02-08_18:25:57,95 WARNING [utils.py:70] No hash given! This is recommended when downloading files from the web.
Read the data with ontolutils.dquery:
from ontolutils import dquery
data = dquery(subject='schema:SoftwareSourceCode',
source=dowloaded_filename,
context={"schema": "http://schema.org/"})
pprint(data[0])
{'@context': {'applicationCategory': 'http://schema.org/applicationCategory',
'author': 'http://schema.org/author',
'codeRepository': 'http://schema.org/codeRepository',
'description': 'http://schema.org/description',
'license': 'http://schema.org/license',
'name': 'http://schema.org/name',
'operatingSystem': 'http://schema.org/operatingSystem',
'programmingLanguage': 'http://schema.org/programmingLanguage',
'version': 'http://schema.org/version'},
'@id': '_:N16ed2ed22a90463fb1ae5448a299053e',
'@type': 'http://schema.org/SoftwareSourceCode',
'applicationCategory': 'file:///home/docs/.cache/h5rdmtoolbox/1.6.2/Engineering',
'author': [{'@id': 'https://orcid.org/0000-0001-9560-500X',
'@type': 'http://schema.org/Person',
'affiliation': {'@id': 'https://ror.org/04t3en479',
'@type': 'http://schema.org/Organization',
'name': 'Karlsruhe Institute of Technology, '
'Institute of Thermal Turbomachinery'},
'familyName': 'Pritz',
'givenName': 'Balazs'},
{'@id': 'https://orcid.org/0000-0001-8729-0482',
'@type': 'http://schema.org/Person',
'affiliation': {'@id': 'https://ror.org/04t3en479',
'@type': 'http://schema.org/Organization',
'name': 'Karlsruhe Institute of Technology, '
'Institute of Thermal Turbomachinery'},
'email': 'matth.probst@gmail.com',
'familyName': 'Probst',
'givenName': 'Matthias'},
{'@id': 'https://orcid.org/0000-0002-4116-0065',
'@type': 'http://schema.org/Person',
'affiliation': {'@id': 'https://ror.org/04t3en479',
'@type': 'http://schema.org/Organization',
'name': 'Karlsruhe Institute of Technology, '
'Institute of Thermal Turbomachinery'},
'familyName': 'Büttner',
'givenName': 'Lucas'}],
'codeRepository': 'git+https://github.com/matthiasprobst/h5RDMtoolbox.git',
'description': 'Supporting a FAIR Research Data lifecycle using Python and '
'HDF5.',
'license': 'https://spdx.org/licenses/MIT',
'name': 'h5RDMtoolbox',
'operatingSystem': ['Linux', 'Windows', 'macOS'],
'programmingLanguage': ['Python 3',
'Python 3.8',
'Python 3.9',
'Python 3.10',
'Python 3.11',
'Python 3.12'],
'version': '1.6.2'}
The data are written into the HDF5 file by using jsonld.to_hdf():
with h5tbx.File('test.hdf', 'w') as h5:
jsonld.to_hdf(data=data[0],
grp=h5.create_group('software_code'))
h5.dump(False)
-
-
- applicationCategory
http://schema.org/applicationCategory: ///home/docs/.cache/h5rdmtoolbox/1.6.2/Engineering - codeRepository
http://schema.org/codeRepository: //github.com/matthiasprobst/h5RDMtoolbox.git - description
http://schema.org/description: Supporting a FAIR Research Data lifecycle using Python and HDF5. - license
http://schema.org/license: https://spdx.org/licenses/MIT - name
http://schema.org/name: h5RDMtoolbox - operatingSystem
http://schema.org/operatingSystem: Linux, Windows, macOS - programmingLanguage
http://schema.org/programmingLanguage: Python 3, Python 3.8, Python 3.9, Python 3.10, Python 3.11, Python 3.12 - version
http://schema.org/version: 1.6.2
-
- familyName: Pritz
- givenName: Balazs
-
- name
http://schema.org/name: Karlsruhe Institute of Technology, Institute of Thermal Turbomachinery
- name
-
- email: matth.probst@gmail.com
- familyName: Probst
- givenName: Matthias
-
- name
http://schema.org/name: Karlsruhe Institute of Technology, Institute of Thermal Turbomachinery
- name
-
- familyName: Büttner
- givenName: Lucas
-
- name
http://schema.org/name: Karlsruhe Institute of Technology, Institute of Thermal Turbomachinery
- name
- applicationCategory
-
import ontolutils
with h5tbx.File(mode='w') as h5:
_ = h5.create_dataset('test_dataset', data=np.array([[1, 2], [3, 4], [5.4, 1.9]]))
_ = h5.create_dataset('test_dataset 2', data=4.5)
h5.create_dataset('grp/subgrp/vel', data=4)
h5.attrs['name', ontolutils.SCHEMA.name] = 'test attr'
# _ = h5.create_dataset('test_dataset', data=5.4)
jd = jsonld.dumpd(h5, structural=True)
jds = jsonld.dumps(h5, structural=True, indent=2)
from pprint import pprint
pprint(jd, indent=1)
{'@context': {'hdf5': 'http://purl.allotrope.org/ontologies/hdf5/1.8#',
'schema': 'https://schema.org/'},
'@graph': [{'@id': '_:N68426685fdd847a9bf851a64f9224af2',
'@type': 'hdf5:File',
'hdf5:rootGroup': {'@id': '_:N105fe10f726c4f598cbb5f7a02ae8cd4',
'@type': 'hdf5:Group',
'hdf5:attribute': {'@id': '_:N0f4c18d313454375a72694259570dc88',
'@type': 'hdf5:Attribute',
'hdf5:name': 'name',
'hdf5:value': 'test attr'},
'hdf5:member': [{'@id': '_:Nc09f66ce0f034b3fa74f946857778668',
'@type': 'hdf5:Group',
'hdf5:member': {'@id': '_:N848bba62383e467ea4ee87af6161113f',
'@type': 'hdf5:Group',
'hdf5:member': {'@id': '_:N5fe689468dcd4ef5aa022c2b89199b6d',
'@type': 'hdf5:Dataset',
'hdf5:datatype': 'H5T_INTEGER',
'hdf5:dimension': 0,
'hdf5:name': '/grp/subgrp/vel',
'hdf5:size': 1,
'hdf5:value': '4'},
'hdf5:name': '/grp/subgrp'},
'hdf5:name': '/grp'},
{'@id': '_:Nc3ba532f96f240cfafd0293f546701e3',
'@type': 'hdf5:Dataset',
'hdf5:datatype': 'H5T_FLOAT',
'hdf5:dimension': 2,
'hdf5:name': '/test_dataset',
'hdf5:size': 6,
'hdf5:value': '[[1.0, 2.0], '
'[3.0, 4.0], '
'[5.4, 1.9]]'},
{'@id': '_:Nee51ec48994d4e6c957434ca9923d73a',
'@type': 'hdf5:Dataset',
'hdf5:datatype': 'H5T_FLOAT',
'hdf5:dimension': 0,
'hdf5:name': '/test_dataset 2',
'hdf5:size': 1,
'hdf5:value': 4.5}],
'hdf5:name': '/',
'schema:name': 'test attr'}}]}
Describing attribute meanings without RDF#
Sometimes, there is no IRI (yet) defined but the need to give an additional comment on the attribute. This can be done by as follows:
with h5tbx.File() as h5:
grp = h5.create_group('contact')
# Set an attribute as usual
grp.attrs['type'] = 'Contact'
# Update the attribute definition afterwards:
grp.rdf['type'].definition = 'The role of the Person'
# Alternatively, it can be assigned simultaneously via h5tbx.Attribute:
grp.attrs['fname'] = h5tbx.Attribute(value='Matthias',
definition='The first name of the contact')
h5.dump(False)
jdict = h5.dump_jsonld(h5.hdf_filename, indent=2)
-
-
- fname: Matthias
The first name of the contact - type: Contact
The role of the Person
- fname
-
print(jdict)
{
"@context": {
"hdf5": "http://purl.allotrope.org/ontologies/hdf5/1.8#",
"skos": "http://www.w3.org/2004/02/skos/core#"
},
"@graph": [
{
"@id": "_:N23153257b06049459e384cd5ec85d23a",
"@type": "hdf5:File",
"hdf5:rootGroup": {
"@id": "_:Nbb2fa720b14b4eb1934f83615da0003c",
"@type": "hdf5:Group",
"hdf5:member": {
"@id": "_:N06b39eac8e4f46cb89ab002c9ff7b816",
"@type": "hdf5:Group",
"hdf5:attribute": [
{
"@id": "_:Nf43866a6a34d48928333167defb9c093",
"@type": "hdf5:Attribute",
"hdf5:name": "fname",
"hdf5:value": "Matthias",
"skos:definition": "The first name of the contact"
},
{
"@id": "_:N92a9383ef06d43929063f38c1959e5c5",
"@type": "hdf5:Attribute",
"hdf5:name": "type",
"hdf5:value": "Contact",
"skos:definition": "The role of the Person"
}
],
"hdf5:name": "/contact"
},
"hdf5:name": "/"
}
}
]
}