Skip to content

Conversation

@ngholiza
Copy link
Collaborator

What

Equipment registered through the web form stores plain unit strings ("sccm", "mTorr", "°C/min") and a free-text equipment type. The FAIR exporter could emit QUDT / SOSA / PROV-O terms, but only when the config already carried them, so most registered equipment was exported without them.

api/fair_ontology.py infers those terms from what the owner entered:

  • QUDT unit + quantity kind. Includes the registration form's units (h, °C/min, °). Case is significant except for a fixed list of spellings, so mbar/Mbar and nm/s vs Nm/s are never confused.
  • SOSA type (Actuator/Sensor) from the equipment type, falling back to the equipment name when the type is generic.
  • PROV direction (input/output) for features.

Rules: never overwrite an existing value; never guess an ambiguous unit ("A"), report it instead.

Where it applies

At export time only (fair_archiver._prepare_domain_config), because PATCH /equipment rebuilds config_json and would drop stored values. If inference fails, the export falls back to the normalized config unchanged.

Inferred terms are marked in both the per-run JSON-LD and the RO-Crate manifest with a schema.org additionalProperty named ontologyInferred, so consumers can tell them apart from owner-entered terms.

api/scripts/fair_ontology_dry_run.py reports, per equipment, what would be filled in and what still needs the owner. It is read-only.

Also handles production config shapes: workflow-example equipment store domain as a bare id and list features/targets by name.

Tests

  • api/tests/test_fair_ontology.py: 26 tests, including the RO-Crate manifest.
  • Full API suite: 181 passed, 59 skipped. test_e2e_platform needs a live database and was not run.

Reviewed by Codex over three rounds, ending in APPROVE.

No schema change and no migration. Only the FAIR export output changes.

🤖 Generated with Claude Code

Equipment registered through the wizard stores plain unit strings and a
free-text equipment type, so FAIR exports for it lack QUDT, SOSA and
PROV-O terms. Add fair_ontology.infer_ontology_annotations(), which
derives them from what the owner already entered without overwriting
existing values and marks each inferred value under ontology_inferred.
Ambiguous or unknown units (A, a.u., blank) are reported, not guessed.

Add a read-only report script (api/scripts/fair_ontology_dry_run.py)
that lists, per equipment, what would be filled and what still needs an
owner, from domains/configs or equipment_metadata.config_json. It also
flags NanoM-PER-MIN in etcher.json, which does not exist on qudt.org.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Equipment edits rebuild config_json from the form, so ontology values
written back to the database would be lost on the next edit. Infer them
at export time instead: _load_domain_config now normalizes and then runs
infer_ontology_annotations, so run JSON-LD and RO-Crate bundles for
registered equipment carry QUDT units/quantity kinds, a SOSA type and
feature PROV direction. Existing values still win; if inference raises,
the export proceeds without it.

Drop the etcher's qudt_unit NanoM-PER-MIN, which does not exist on
qudt.org; the target keeps its LinearVelocity quantity kind and its
nm/min unitText. Units QUDT has no individual for are no longer reported
as owner work, and the schema example now uses a real unit URI.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A read-only dry run against the 13 registered equipment showed:

- Workflow-example equipment store domain as a string and features and
  targets as name lists. Both the inference and fair_archiver's
  _get_feature_ontology_map / _normalize_pg_domain_config assumed dicts
  and raised, so FAIR export for those runs was already failing.
- Most unresolved items were not owner work: text/date/flag fields
  (skipped when their declared type is not numeric), the
  primary_metric/secondary_metric placeholder targets, percent
  positions (now DimensionlessRatio), count/unitless/ratio and sub-second
  times (NUM, UNITLESS, MicroSEC/NanoSEC/PicoSEC; URIs checked).
- Equipment typed "other" now get a SOSA type from the equipment name.
- Corrupted units (U+FFFD) are reported as such.

Unresolved items drop from 322 to 28. The dry-run script also gains
--output and keeps going when one config fails.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Add QUDT DEG_C-PER-MIN (TemperaturePerTime) for the registration form's
  °C/min option.
- Match units case-insensitively only for an explicit list of spellings,
  so "Mbar" (megabar) is no longer read as millibar.
- Carry ontology_inferred into the JSON-LD and RO-Crate exports as a
  schema.org additionalProperty, so inferred terms can be told apart from
  owner-entered ones.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign in to join this conversation on GitHub.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant