lehr-und-forschungsbereiche/toturtle.py
Michał Szczepanik 70d7abd8d7 Add display notes about selecting narrower subject areas.
The same way we did it last year - as `display_note` (`SKOS:note`).

The DFG does not ask for that specific input, but with all the
structured we are spoiled for choice - and whenever someone selects a
subject area, broader categories follow unambiguously via `part_of`.
2026-07-28 19:24:20 +02:00

91 lines
3.3 KiB
Python

from pathlib import Path
import tomllib
from rdflib import Graph, URIRef, Literal, Namespace, BNode
from rdflib.namespace import DCTERMS, RDF, SKOS
def get_label_and_desc(record: dict):
"""Get label and description from a record
We stored prefLabel.de (always) and prefLabel.en (usually). The
schema does not support internationalization, so we prefer using
english label as the prefLabel and put the German one into
description.
"""
prefLabel = record["prefLabel"]
try:
label = prefLabel["en"]
except KeyError:
label = prefLabel["de"]
description = prefLabel["de"]
return label, description
def add_discipline(g: Graph, uriref: URIRef, label: str, desc: str, identifier: str, note: str | None = None):
g.add((uriref, RDF.type, trr379cps.Discipline))
g.add((uriref, SKOS.prefLabel, Literal(label)))
g.add((uriref, trr379cps.name, Literal(label))) # redundant?
g.add((uriref, DCTERMS.description, Literal(desc)))
g.add((uriref, DCTERMS.identifier, create_identifier(g, identifier))) # or dlthings.identifiers?
if note is not None:
g.add((uriref, SKOS.note, Literal(f"{note} Please try to select a more specific subject area.")))
def create_identifier(g: Graph, notation: str):
id = BNode()
g.add((id, RDF.type, dlthings.Identifier))
g.add((id, SKOS.notation, Literal(notation)))
g.add((id, DCTERMS.creator, ror["01kratx56"])) # last year, Literal("https://destatis.de/", datatype=XSD.anyURI)))
return id
with Path("derived/personal-stellenstatistik.toml").open("rb") as fp:
data = tomllib.load(fp)
dlthings = Namespace("https://concepts.datalad.org/s/things/v2/")
trr379cps = Namespace("https://concepts.trr379.de/s/dfg-cp-survey/unreleased/")
trr379dfgsurvey = Namespace("https://trr379.de/ns/dfg-cp-survey/") # or sns for survey namespace?
ror = Namespace("https://ror.org/")
g = Graph()
g.bind("dlthings", dlthings)
g.bind("trr379cps", trr379cps)
g.bind("trr379dfgsurvey", trr379dfgsurvey)
g.bind("ror", ror)
for group_id, group in data.items():
group_label, group_desc = get_label_and_desc(group)
group_uri = trr379dfgsurvey[f"discipline/{group_id}"]
add_discipline(g, group_uri, group_label, group_desc, group_id, note="This is an area of study (subject group).")
for field_id, field in group.items():
if field_id == "prefLabel":
# this is not a field, this is a label
# same effect as if not isinstance(area, dict)
continue
field_label, field_desc = get_label_and_desc(field)
field_uri = trr379dfgsurvey[f"discipline/{field_id}"]
add_discipline(g, field_uri, field_label, field_desc, field_id, note="This is a teaching and research field.")
g.add((group_uri, trr379cps.parts, field_uri))
g.add((field_uri, trr379cps.part_of, group_uri))
for area_id, area in field.items():
if area_id == "prefLabel":
continue
area_label, area_desc = get_label_and_desc(area)
area_uri = trr379dfgsurvey[f"discipline/{area_id}"]
add_discipline(g, area_uri, area_label, area_desc, area_id)
g.add((field_uri, trr379cps.parts, area_uri))
g.add((area_uri, trr379cps.part_of, field_uri))
g.serialize(Path("derived/all_records.ttl"))