Skip to content

Commit 020a718

Browse files
authored
Updates for GDI metadata v1.1 #5 (#13)
* Updated SHACL schemas from the main branch of the GDI/gdi-metadata repo * Renamed dataset directories to conform with the new identifier requirements * Minor updates to templates.yaml to conform with the new SHACL * Minor code formatting changes
1 parent b1315a6 commit 020a718

12 files changed

Lines changed: 626 additions & 617 deletions

File tree

data/GDIDEMO20251201001D/GRCh37/allele-freq-chr3.4.parquet renamed to data/GDI-DS-20251201001/GRCh37/allele-freq-chr3.4.parquet

File renamed without changes.

data/GDIDEMO20251202001D/GRCh37/individuals-chr3.4.parquet renamed to data/GDI-DS-20251202001/GRCh37/individuals-chr3.4.parquet

File renamed without changes.
File renamed without changes.

mini_node/fdp/api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
from typing import Annotated
22

33
from fastapi import APIRouter, Path, Request
4-
from rdflib import Graph
54
from fastapi.responses import Response, PlainTextResponse
5+
from rdflib import Graph
66
from starlette.status import HTTP_404_NOT_FOUND
77

88
import mini_node.fdp.service as fdp

mini_node/fdp/service/_data.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
from datetime import datetime
22
from typing import Any
3+
34
from mini_node.data import DATA, fdp_config
45

6+
57
def get_last_modified() -> datetime | None:
68
"""Retrieves the latest dataset state update time for all catalogs."""
79
max_modified = fdp_config.since

mini_node/fdp/service/_template.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,9 @@
125125

126126
import re
127127
from datetime import date, datetime
128+
from logging import getLogger
128129
from os.path import dirname, join
129130
from typing import Any
130-
from logging import getLogger
131131

132132
import yaml
133133
from email_validator import validate_email
@@ -146,6 +146,7 @@
146146

147147
_log = getLogger(__name__)
148148

149+
149150
class FdpTemplate(BaseModel):
150151
"""An FDP template is defined by its URL path, static predicates part, and
151152
mapping part for binding runtime values to predicates."""
@@ -398,8 +399,8 @@ def _convert_value(v: Any) -> URIRef | Literal:
398399
validated = validate_email(s)
399400
return URIRef("mailto:" + validated.normalized)
400401
except Exception as e:
401-
_log.warning("Failed to validate email address: %s", s, str(e))
402-
pass
402+
_log.warning(
403+
"Failed to validate email address: %s", s, str(e))
403404

404405
# ISO date or datetime
405406
if ISO_DATETIME.match(s):
Lines changed: 62 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -1,122 +1,66 @@
1-
# These shapes are based on FDP 1.2 and HealthDCAT-AP v5.
2-
# https://specs.fairdatapoint.org/fdp-specs-v1.2.html#catalogmetadata
3-
# https://healthdataeu.pages.code.europa.eu/healthdcat-ap/releases/release-5/#Catalogue
1+
# The following content comes from:
2+
# https://github.com/GenomicDataInfrastructure/gdi-metadata/blob/5578eeaccb70cc164dccfef2faf957e060e29b80/Formulasation(shacl)/core/PiecesShape/Catalog.ttl
43

5-
@prefix dcat: <http://www.w3.org/ns/dcat#> .
6-
@prefix dct: <http://purl.org/dc/terms/> .
7-
@prefix fdp-o: <https://w3id.org/fdp/fdp-o#> .
8-
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
9-
@prefix sh: <http://www.w3.org/ns/shacl#> .
10-
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
4+
# SPDX-FileCopyrightText: 2025 Health-RI
5+
#
6+
# SPDX-License-Identifier: Apache-2.0
117

12-
# CatalogShape is based on FDP 1.2 and HealthDCAT-AP v5.
138

14-
:CatalogShape a sh:NodeShape ;
15-
sh:targetClass dcat:Catalog ;
16-
sh:property [
17-
sh:path dct:conformsTo ;
18-
sh:nodeKind sh:IRI ;
19-
sh:minCount 1 ;
20-
sh:maxCount 1 ;
21-
], [
22-
sh:path dct:description ;
23-
sh:nodeKind sh:Literal ;
24-
sh:minCount 1 ;
25-
], [
26-
sh:path dct:isPartOf ;
27-
sh:nodeKind sh:IRI ;
28-
sh:minCount 1 ;
29-
sh:maxCount 1 ;
30-
], [
31-
sh:path dct:license ;
32-
sh:nodeKind sh:IRI ;
33-
sh:minCount 1 ;
34-
sh:maxCount 1 ;
35-
], [
36-
sh:path dct:publisher ;
37-
sh:node :AgentShape ;
38-
sh:minCount 1 ;
39-
sh:maxCount 1 ;
40-
], [
41-
sh:path dct:title ;
42-
sh:nodeKind sh:Literal ;
43-
sh:minCount 1 ;
44-
], [
45-
sh:path dct:accessRights ;
46-
sh:nodeKind sh:IRI ;
47-
], [
48-
sh:path dct:hasVersion ;
49-
sh:nodeKind sh:Literal ;
50-
sh:maxCount 1 ;
51-
], [
52-
sh:path dct:issued ;
53-
sh:datatype xsd:dateTime ;
54-
sh:maxCount 1 ;
55-
], [
56-
sh:path dct:language ;
57-
sh:nodeKind sh:IRI ;
58-
], [
59-
sh:path dct:modified ;
60-
sh:datatype xsd:dateTime ;
61-
sh:maxCount 1 ;
62-
], [
63-
sh:path dct:rights ;
64-
sh:nodeKind sh:IRI ;
65-
], [
66-
sh:path dcat:themeTaxonomy ;
67-
sh:nodeKind sh:IRI ;
68-
sh:minCount 1 ;
69-
sh:maxCount 1 ;
70-
], [
71-
sh:path dcat:catalog ;
72-
sh:nodeKind sh:IRI ;
73-
], [
74-
sh:path dcat:dataset ;
75-
sh:nodeKind sh:IRI ;
76-
], [
77-
sh:path dcat:record ;
78-
sh:nodeKind sh:IRI ;
79-
], [
80-
sh:path dcat:service ;
81-
sh:nodeKind sh:IRI ;
82-
], [
83-
sh:path foaf:homepage ;
84-
sh:nodeKind sh:IRI ;
85-
sh:maxCount 1 ;
86-
], [
87-
sh:path fdp-o:metadataIdentifier ;
88-
sh:nodeKind sh:IRI ;
89-
sh:minCount 1 ;
90-
sh:maxCount 1 ;
91-
], [
92-
sh:path fdp-o:metadataIssued ;
93-
sh:datatype xsd:dateTime ;
94-
sh:minCount 1 ;
95-
sh:maxCount 1 ;
96-
], [
97-
sh:path fdp-o:metadataModified ;
98-
sh:datatype xsd:dateTime ;
99-
sh:minCount 1 ;
100-
sh:maxCount 1 ;
101-
] .
9+
@prefix owl: <http://www.w3.org/2002/07/owl#> .
10+
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
11+
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
12+
@prefix example: <https://data.sparna.fr/shapes-example/> .
13+
@prefix dct: <http://purl.org/dc/terms/> .
14+
@prefix sh: <http://www.w3.org/ns/shacl#> .
15+
@prefix dcat: <http://www.w3.org/ns/dcat#> .
16+
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
17+
@prefix gdi: <http://data.gdi.eu/core/p2/> .
18+
@prefix dcatap: <http://data.europa.eu/r5r/> .
19+
@prefix vcard: <http://www.w3.org/2006/vcard/ns#> .
20+
@prefix dash: <http://datashapes.org/dash#> .
10221

103-
# This is customised. More info about foaf namespace:
104-
# https://sparontologies.github.io/foaf/current/foaf.html
105-
:AgentShape a sh:NodeShape ;
106-
sh:targetClass foaf:Organization ;
107-
sh:property [
108-
sh:path foaf:name ;
109-
sh:nodeKind sh:Literal ;
110-
sh:minCount 1 ;
111-
sh:maxCount 1 ;
112-
], [
113-
sh:path foaf:mbox ;
114-
sh:nodeKind sh:IRI ;
115-
sh:pattern "^mailto:.+@.+\\..+$" ;
116-
sh:maxCount 1 ;
117-
], [
118-
sh:path foaf:homepage ;
119-
sh:nodeKind sh:IRI ;
120-
sh:pattern "^https?://.+$" ;
121-
sh:maxCount 1 ;
122-
] .
22+
<https://data.sparna.fr/shapes-example#> a owl:Ontology;
23+
rdfs:label "Catalog"@en;
24+
rdfs:comment "Health-RI v2 Catalog."@en;
25+
dct:description "SHACL definitions for GDI v1.1 metadata for Catalog."@en;
26+
owl:versionInfo "0.1";
27+
dct:modified "2025-12-29T13:37:52.800Z"^^xsd:dateTime .
28+
29+
gdi:CatalogShape a sh:NodeShape;
30+
rdfs:label "Catalog"@en;
31+
sh:targetClass dcat:Catalog;
32+
sh:property <http://data.gdi.eu/core/p2/CatalogShape#dcatap:applicableLegislation>,
33+
<http://data.gdi.eu/core/p2/CatalogShape#dcat:dataset>,
34+
<http://data.gdi.eu/core/p2/CatalogShape#dct:description>, <http://data.gdi.eu/core/p2/CatalogShape#dct:title> .
35+
36+
<http://data.gdi.eu/core/p2/CatalogShape#dcatap:applicableLegislation> sh:path
37+
dcatap:applicableLegislation;
38+
sh:name "Applicable Legislation"@en;
39+
sh:description "The legislation that mandates the creation or management of the Catalog."@en;
40+
sh:minCount 1;
41+
sh:nodeKind sh:IRI;
42+
sh:defaultValue <http://data.europa.eu/eli/reg/2025/327/oj>;
43+
dash:viewer dash:URIViewer;
44+
dash:editor dash:URIEditor .
45+
46+
<http://data.gdi.eu/core/p2/CatalogShape#dcat:dataset> sh:path dcat:dataset;
47+
sh:name "dataset"@en;
48+
sh:description "Each catalog contains one or more datasets. This property serves to link datasets to a catalogue. Therefore, a dataset is always contained inside a catalogue."@en .
49+
50+
<http://data.gdi.eu/core/p2/CatalogShape#dct:description> sh:path dct:description;
51+
sh:name "description"@en;
52+
sh:description "Briefly describe the catalog and what it contains. You can repeat this in multiple languages."@en;
53+
sh:minCount 1;
54+
sh:nodeKind sh:Literal;
55+
sh:uniqueLang true;
56+
dash:viewer dash:LiteralViewer;
57+
dash:editor dash:TextAreaEditor .
58+
59+
<http://data.gdi.eu/core/p2/CatalogShape#dct:title> sh:path dct:title;
60+
sh:name "title"@en;
61+
sh:description "Provide a unique title for your catalog, which can be repeated in multiple languages. Example: Healthy Brain Study."@en;
62+
sh:minCount 1;
63+
sh:nodeKind sh:Literal;
64+
sh:uniqueLang true;
65+
dash:viewer dash:LiteralViewer;
66+
dash:editor dash:TextFieldEditor .

0 commit comments

Comments
 (0)