SKOS & the ATRIUM vocabulary¶
How ATRIUM names its controlled labels with stable identifiers, what the page-category
vocabulary contains in full, and how page-classification and the translator use it.
Scope
The registry holds six vocabularies; one of them belongs to page-classification, and the
translator uses none. The other five belong to alto-postprocess and nlp-enrich.
docs/skos_strategy.md
is the normative text.
What SKOS is doing here¶
SKOS — the W3C's Simple Knowledge Organization System — is a small RDF vocabulary for writing
down a controlled list: each term is a skos:Concept with a stable URI, a label, and a place in a
skos:ConceptScheme. ATRIUM uses it for one purpose: so that a bare string in a record — TEXT_HW
in page_categories — can be resolved to one unambiguous, documented concept.
It is an internal alignment framework, and deliberately modest:
- Nothing is published. No external service is contacted, and no vocabulary registration is a prerequisite for any of it.
- No namespace was requested. A request for a DARIAH vocabulary namespace was set aside as a long-horizon item; using SKOS to align the data internally was judged worth doing without it.
- Source vocabularies keep their own URIs. AMCR and TEATER already mint resolvable identifiers, and ATRIUM does not re-mint them.
- ATRIUM mints URIs only for what it authors — and roots them all in one constant, so the day a real namespace exists, one line changes.
The registry is atrium_vocab.py, one of the 17 shared files,
vendored byte-identically into both documented tools.
How a URI is minted¶
SKOS_BASE = https://w3id.org/atrium/
scheme https://w3id.org/atrium/scheme/<scheme>
concept https://w3id.org/atrium/<scheme>/<notation>
collection https://w3id.org/atrium/<scheme>/collection/<name>
The notation is kept case-preserving — letters, digits, _ and . survive; any other run of
characters becomes one -. So:
| URI | |
|---|---|
| the scheme | https://w3id.org/atrium/scheme/page-category |
| one concept | https://w3id.org/atrium/page-category/TEXT_HW |
| one collection | https://w3id.org/atrium/page-category/collection/tabular |
Identifiers first, locators second
An ATRIUM URI is a stable identifier: records and crates can use it whether or not
anything answers at that address. Making it a resolvable locator is a matter of a
w3id.org redirect to a published copy of the registry, which changes no data and no
code.
In Turtle, as python atrium_vocab.py --turtle writes it, one concept reads:
a-page-category:TEXT_HW rdf:type skos:Concept ;
skos:definition "only handwritten text in paragraph or block form (non-tabular)"@en ;
skos:inScheme atrium-scheme:page-category ;
skos:notation "TEXT_HW" ;
skos:prefLabel "TEXT_HW"@en .
The six vocabularies at a glance¶
| Scheme | Concepts | Authority | Record field |
|---|---|---|---|
page-category |
11 | page-classification — model_registry.py CATEGORIES |
page_categories, pages[].category |
line-category |
7 | alto-postprocess and digital-convert | lines[].categ |
quality-band |
3 | alto-postprocess | pages[].quality_band |
entity-type |
4 | nlp-enrich | entities[].type_teitok |
cnec |
28 | nlp-enrich (CNEC 2.0) | entities[].type_cnec |
theme |
11 | nlp-enrich's taxonomy | enrichment.items[].teater_category, via the facet |
The translator appears in none of them — see below.
page-category, in full¶
The eleven concepts, in the order model_registry.CATEGORIES declares them. The order is
load-bearing: it is the label-to-index binding the models were trained with, and the registry's
PAGE_CATEGORIES must match it exactly.
| Notation | URI | Definition |
|---|---|---|
DRAW |
…/page-category/DRAW |
drawings, maps, paintings, schematics, or graphics, potentially containing some text labels or captions |
DRAW_L |
…/page-category/DRAW_L |
drawings, etc but presented within a table-like layout or includes a legend formatted as a table |
LINE_HW |
…/page-category/LINE_HW |
handwritten text organized in a tabular or form-like structure |
LINE_P |
…/page-category/LINE_P |
printed text organized in a tabular or form-like structure |
LINE_T |
…/page-category/LINE_T |
machine-typed text organized in a tabular or form-like structure |
PHOTO |
…/page-category/PHOTO |
photographs or photographic cutouts, potentially with text captions |
PHOTO_L |
…/page-category/PHOTO_L |
photos presented within a table-like layout or accompanied by tabular annotations |
TEXT |
…/page-category/TEXT |
mixtures of printed, handwritten, and/or typed text, potentially with minor graphical elements |
TEXT_HW |
…/page-category/TEXT_HW |
only handwritten text in paragraph or block form (non-tabular) |
TEXT_P |
…/page-category/TEXT_P |
only printed text in paragraph or block form (non-tabular) |
TEXT_T |
…/page-category/TEXT_T |
only machine-typed text in paragraph or block form (non-tabular) |
Each concept's prefLabel is its notation.
Facets are collections, not a hierarchy¶
The categories cut across three independent criteria — graphical content, kind of text, tabular
layout — so they do not form a tree. The registry says so by modelling each criterion as a
skos:Collection, which states membership without implying that one concept is narrower than
another:
| Collection | Label | Members |
|---|---|---|
graphical |
carries graphical elements | DRAW · DRAW_L · PHOTO · PHOTO_L · TEXT |
tabular |
laid out as a table, form or legend | DRAW_L · LINE_HW · LINE_P · LINE_T · PHOTO_L |
handwritten |
contains handwritten text | LINE_HW · TEXT · TEXT_HW |
printed |
contains printed text | LINE_P · TEXT · TEXT_P |
typed |
contains machine-typed text | LINE_T · TEXT · TEXT_T |
There is no skos:broader anywhere in the scheme and no top concept. TEXT belongs to four
collections — it is the one mixed category — and PHOTO and DRAW belong to graphical only.
How page-classification uses it¶
model_registry.CATEGORIES is the authority: the tool writes exactly those eleven strings.
When model_registry.py is imported, it compares CATEGORIES with the registry's
page-category labels and prints a note if the two sets ever differ; it never changes
CATEGORIES and never stops a run. Training and evaluation, which read the category list from
the folder names of the training tree, do the same comparison for that tree.
Records carry the bare label. To get from a label to its concept:
from atrium_vocab import concept_uri, validate_labels
concept_uri("page-category", "TEXT_HW")
# 'https://w3id.org/atrium/page-category/TEXT_HW'
validate_labels("page-category", ["TEXT", "Text", "Plate"])
# reports that "Text" differs from TEXT only in case, and that "Plate" is not in the scheme
validate_labels() reports rather than raises — the same advisory stance as the missing
enum in the schema.
model_registry.category_uri(label) is the tool's own shortcut for concept_uri.
The translator and its glossary¶
The translator does not import atrium_vocab and writes no field that carries a scheme. Its
controlled vocabulary is something else: a translation glossary,
data_samples/vocabulary.csv, with five columns — source_lemma,target_translation,source,source_id,uri
— harvested by load_vocab.py from AMCR (over OAI-PMH) and TEATER (over GraphQL). The
source_id and uri columns point back at the source vocabulary's own concept — for example
https://api.aiscr.cz/id/HES-000497 for AMCR's (polo)zemnice, "pit house" — so a protected
term stays traceable without ATRIUM minting a URI for it. The glossary protects terms during
translation; it does not label anything in the record. See
translator → Guide.
"broader means two things"¶
skos_strategy.md §5.2 records a modelling decision about the source vocabularies: AMCR's
hierarchie_vyse edges all cross from one scheme to another and so become skos:related, while
TEATER's broader edges stay within one scheme and become real skos:broader. That concerns the
vocabularies nlp-enrich builds from AMCR and TEATER. It does not touch page-category, which
asserts no broader at all.
Getting the vocabulary¶
python atrium_vocab.py --jsonld # the whole registry as JSON-LD
python atrium_vocab.py --turtle # … or as Turtle
python atrium_vocab.py --labels page-category
python atrium_vocab.py --selftest
Run from either tool's checkout, where the file sits at the repository root. The JSON-LD output is
what atrium_vocab.schema.json describes.
Sources¶
This table records provenance: what this page was written from, not a build instruction.
| Source | What was taken from it |
|---|---|
atrium-project/docs/templates/shared/atrium_vocab.py — run, not only read |
SKOS_BASE, the minting rules, the six schemes, the concepts and collections, the Turtle excerpt, validate_labels() output |
atrium-project/docs/skos_strategy.md §§0, 5.2, 6, 7 |
the design decisions |
atrium-page-classification@vit adee922 — model_registry.py, utils.py |
the authority list, the advisory comparison, category_uri |
atrium-translator@master 71feaef — load_vocab.py, data_samples/vocabulary.csv, processors/vocab.py |
the glossary, its columns and its harvester |