diff --git a/frontend/public/schemas/20251121/linkml/manifest.json b/frontend/public/schemas/20251121/linkml/manifest.json index cc3efb0e9d..cc2b1420b4 100644 --- a/frontend/public/schemas/20251121/linkml/manifest.json +++ b/frontend/public/schemas/20251121/linkml/manifest.json @@ -1,5 +1,5 @@ { - "generated": "2026-01-22T12:00:07.511Z", + "generated": "2026-01-22T14:15:56.373Z", "schemaRoot": "/schemas/20251121/linkml", "totalFiles": 2969, "categoryCounts": { diff --git a/schemas/20251121/linkml/manifest.json b/schemas/20251121/linkml/manifest.json index cc2b1420b4..500c926b28 100644 --- a/schemas/20251121/linkml/manifest.json +++ b/schemas/20251121/linkml/manifest.json @@ -1,5 +1,5 @@ { - "generated": "2026-01-22T14:15:56.373Z", + "generated": "2026-01-22T14:51:02.979Z", "schemaRoot": "/schemas/20251121/linkml", "totalFiles": 2969, "categoryCounts": { diff --git a/schemas/20251121/linkml/modules/classes/TasteScentHeritageType.yaml b/schemas/20251121/linkml/modules/classes/TasteScentHeritageType.yaml index 50bc0283a1..43c40540e4 100644 --- a/schemas/20251121/linkml/modules/classes/TasteScentHeritageType.yaml +++ b/schemas/20251121/linkml/modules/classes/TasteScentHeritageType.yaml @@ -15,7 +15,11 @@ imports: - linkml:types - ./CustodianType # ARCHIVED 2026-01-16: ../enums/TasteScentHeritageTypeEnum - replaced by TasteScentSubType/TasteScentSubTypes classes - - ../slots/community_significance + # REMOVED 2026-01-22: ../slots/community_significance - migrated to has_or_had_significance + Significance (Rule 53) + - ../slots/has_or_had_significance + - ./Significance + - ./SignificanceType + - ./SignificanceTypes - ../slots/has_or_had_custodian_type - ../slots/heritage_practice - ../slots/knowledge_transmission @@ -209,7 +213,8 @@ classes: - crm:E55_Type - schema:Place slots: - - community_significance + # REMOVED 2026-01-22: community_significance - migrated to has_or_had_significance + Significance (Rule 53) + - has_or_had_significance - has_or_had_custodian_type - heritage_practice - knowledge_transmission @@ -274,16 +279,33 @@ classes: description: Perfume house transmission - value: Family succession, Public demos, PDO training description: Traditional dairy transmission - community_significance: - range: string + # MIGRATED 2026-01-22: community_significance → has_or_had_significance + Significance (Rule 53) + has_or_had_significance: + description: | + Why this culinary/olfactory heritage matters to local/regional/national identity. + MIGRATED from community_significance per slot_fixes.yaml (Rule 53, 2026-01-22). + + Uses Significance class for structured representation including: + - Type (CommunitySignificance, EconomicSignificance, TerroirSignificance, etc.) + - Description of the significance + range: Significance + multivalued: true + inlined: true + inlined_as_list: true required: false examples: - - value: UNESCO Trappist tradition, Belgian identity, Pilgrimage - description: Westvleteren significance - - value: Grasse UNESCO heritage, French parfumerie, Tourism - description: Perfume house significance - - value: Protected PDO, Dutch cheese identity, Regional economy - description: Traditional cheese significance + - value: + has_or_had_type: CommunitySignificance + has_or_had_description: "UNESCO-recognized Trappist tradition, Belgian cultural identity, Beer pilgrimage site" + description: Westvleteren brewery - community/cultural significance + - value: + has_or_had_type: TerroirSignificance + has_or_had_description: "Grasse UNESCO heritage, French parfumerie tradition, Olfactory tourism" + description: Perfume house - terroir/cultural significance + - value: + has_or_had_type: EconomicSignificance + has_or_had_description: "Protected Gouda PDO, Dutch cheese identity, Economic importance to region" + description: Traditional cheese - economic significance has_or_had_hyponym: # was: taste_scent_subtype - migrated per Rule 53/56 (2026-01-16) description: Specific subtype from the taste/scent heritage taxonomy (15 Wikidata-aligned types). range: TasteScentSubType diff --git a/schemas/20251121/linkml/modules/classes/VideoAnnotation.yaml b/schemas/20251121/linkml/modules/classes/VideoAnnotation.yaml index 9afc6e0eb7..103c1c3374 100644 --- a/schemas/20251121/linkml/modules/classes/VideoAnnotation.yaml +++ b/schemas/20251121/linkml/modules/classes/VideoAnnotation.yaml @@ -12,7 +12,12 @@ imports: - ../slots/has_annotation_type - ../slots/detection_count - ../slots/detection_threshold - - ../slots/frame_sample_rate + # MIGRATED 2026-01-22: frame_sample_rate → analyzes_or_analyzed + VideoFrame + has_or_had_quantity + Quantity (Rule 53) + - ./VideoFrame + - ../slots/has_or_had_quantity + - ../slots/has_or_had_unit + - ./Quantity + - ./Unit - ../slots/includes_bounding_box - ../slots/includes_segmentation_mask - ../slots/keyframe_extraction @@ -23,39 +28,9 @@ imports: - ../slots/analyzes_or_analyzed - ./SpecificityAnnotation - ./TemplateSpecificityScore # was: TemplateSpecificityScores - migrated per Rule 53 (2026-01-17) - - ./TemplateSpecificityType - - ./TemplateSpecificityTypes - ../enums/AnnotationTypeEnum - - ../slots/analyzes_or_analyzed - - ../slots/detection_count - - ../slots/detection_threshold - - ../slots/frame_sample_rate - - ../slots/has_annotation_motivation - - ../slots/has_annotation_segment - - ../slots/has_annotation_type - - ../slots/includes_bounding_box - - ../slots/includes_segmentation_mask - - ../slots/keyframe_extraction - - ../slots/model_architecture - - ../slots/model_task - - ../slots/specificity_annotation - - ../slots/has_or_had_score # was: template_specificity - migrated per Rule 53 (2026-01-17) - - ../slots/analyzes_or_analyzed - - ../slots/detection_count - - ../slots/detection_threshold - - ../slots/frame_sample_rate - - ../slots/has_annotation_motivation - - ../slots/has_annotation_segment - - ../slots/has_annotation_type - - ../slots/includes_bounding_box - - ../slots/includes_segmentation_mask - - ../slots/keyframe_extraction - - ../slots/model_architecture - - ../slots/model_task - - ../slots/specificity_annotation - - ../slots/has_or_had_score # was: template_specificity - migrated per Rule 53 (2026-01-17) prefixes: linkml: https://w3id.org/linkml/ hc: https://nde.nl/ontology/hc/ @@ -106,7 +81,7 @@ classes: - has_annotation_type - detection_count - detection_threshold - - frame_sample_rate + # REMOVED 2026-01-22: frame_sample_rate - migrated to analyzes_or_analyzed + VideoFrame + has_or_had_quantity (Rule 53) - includes_bounding_box - includes_segmentation_mask - keyframe_extraction @@ -145,21 +120,43 @@ classes: examples: - value: 342 description: 342 total detections found - frame_sample_rate: - range: float - required: false - minimum_value: 0.0 - examples: - - value: 1.0 - description: Analyzed 1 frame per second + # MIGRATED 2026-01-22: frame_sample_rate → analyzes_or_analyzed + VideoFrame + has_or_had_quantity (Rule 53) + # frame_sample_rate: + # range: float + # required: false + # minimum_value: 0.0 + # examples: + # - value: 1.0 + # description: Analyzed 1 frame per second analyzes_or_analyzed: - description: Total frames analyzed during video annotation processing. - range: integer + description: | + MIGRATED 2026-01-22: Now supports VideoFrame class for frame_sample_rate migration. + + Frame analysis information including: + - Total frames analyzed (integer, legacy pattern) + - Frame sample rate and analysis parameters (VideoFrame class) + + MIGRATED SLOTS: + - frame_sample_rate → VideoFrame.has_or_had_quantity with unit "samples per second" + range: VideoFrame + inlined: true required: false - minimum_value: 0 examples: - - value: 1800 - description: Analyzed 1,800 frames (30 min video at 1 fps) + - value: + has_or_had_quantity: + quantity_value: 1.0 + quantity_type: FRAME_SAMPLE_RATE + has_or_had_unit: + unit_value: "samples per second" + frame_count: 1800 + description: Analyzed 1,800 frames at 1 fps (30 min video) + - value: + has_or_had_quantity: + quantity_value: 5.0 + quantity_type: FRAME_SAMPLE_RATE + has_or_had_unit: + unit_value: "fps" + description: 5 frames per second sample rate keyframe_extraction: range: boolean required: false diff --git a/schemas/20251121/linkml/modules/classes/VideoFrame.yaml b/schemas/20251121/linkml/modules/classes/VideoFrame.yaml new file mode 100644 index 0000000000..2f07808573 --- /dev/null +++ b/schemas/20251121/linkml/modules/classes/VideoFrame.yaml @@ -0,0 +1,160 @@ +# VideoFrame - Video frame class for analysis +# Created per slot_fixes.yaml migration for: frame_sample_rate +# Creation date: 2026-01-22 +# +# Rule compliance: +# - Rule 38: Slot centralization with semantic URIs +# - Rule 39: RiC-O temporal naming conventions +# - Rule 53: Generic reusable slots + +id: https://nde.nl/ontology/hc/class/VideoFrame +name: VideoFrame +title: VideoFrame Class + +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + schema: http://schema.org/ + oa: http://www.w3.org/ns/oa# + +imports: + - linkml:types + - ../slots/has_or_had_quantity + - ../slots/has_or_had_unit + - ./Quantity + - ./Unit + +default_prefix: hc + +classes: + VideoFrame: + class_uri: schema:VideoObject + description: | + A video frame or set of frames analyzed during video processing. + + **PURPOSE**: + Represents frames from a video that have been analyzed by computer vision + or multimodal AI models. Used to track frame-based analysis parameters + such as sample rate (frames per second analyzed) and total frames processed. + + **USE CASES**: + - Video annotation (object detection, scene analysis) + - Frame sampling configuration + - Analysis throughput tracking + - Computer vision pipeline configuration + + **FRAME SAMPLE RATE**: + The sample rate determines how many frames are analyzed per second of video: + + | Sample Rate | Frames/sec | Use Case | + |-------------|------------|----------| + | 0.1 fps | 1 every 10s | Overview/thumbnails | + | 1.0 fps | 1 per second | Standard analysis | + | 5.0 fps | 5 per second | Detailed analysis | + | 30.0 fps | Every frame | Exhaustive analysis | + + Higher sample rates capture more detail but increase compute cost. + + **MIGRATION SUPPORT**: + This class supports migration from the frame_sample_rate slot per + slot_fixes.yaml. Use with has_or_had_quantity + Quantity + has_or_had_unit + Unit. + + exact_mappings: + - oa:Target + + close_mappings: + - schema:VideoObject + + slots: + - has_or_had_quantity + - has_or_had_unit + + slot_usage: + has_or_had_quantity: + description: | + Frame sample rate expressed as quantity with unit. + MIGRATED from frame_sample_rate slot per slot_fixes.yaml (Rule 53, 2026-01-22). + + Use Quantity class with: + - quantity_value: the numeric sample rate (e.g., 1.0, 5.0, 30.0) + - quantity_type: FRAME_SAMPLE_RATE + - has_or_had_unit: "samples per second" or "fps" + range: Quantity + inlined: true + multivalued: false + examples: + - value: | + quantity_value: 1.0 + quantity_type: FRAME_SAMPLE_RATE + has_or_had_unit: + unit_value: "samples per second" + description: 1 frame per second sample rate + - value: | + quantity_value: 5.0 + quantity_type: FRAME_SAMPLE_RATE + has_or_had_unit: + unit_value: "fps" + has_or_had_label: + - label_text: "frames per second" + description: 5 fps sample rate + has_or_had_unit: + description: | + Unit of measurement for frame sample rate. + Typically "samples per second" or "fps". + range: Unit + inlined: true + + attributes: + frame_count: + range: integer + description: | + Total number of frames in this video or segment. + Used for calculating total frames analyzed from sample rate. + minimum_value: 0 + + frame_width: + range: integer + description: Frame width in pixels. + minimum_value: 1 + + frame_height: + range: integer + description: Frame height in pixels. + minimum_value: 1 + + annotations: + custodian_types: '["D"]' + custodian_types_rationale: >- + Video frames are primarily relevant for digital platforms (D) that + host or process video content. + custodian_types_primary: D + specificity_score: 0.7 + specificity_rationale: >- + Moderately specific - applies only to video analysis contexts. + + examples: + - value: | + VideoFrame: + has_or_had_quantity: + quantity_value: 1.0 + quantity_type: FRAME_SAMPLE_RATE + has_or_had_unit: + unit_value: "samples per second" + frame_count: 1800 + description: Video analyzed at 1 fps over 30 minutes (1800 frames). + + - value: | + VideoFrame: + has_or_had_quantity: + quantity_value: 5.0 + quantity_type: FRAME_SAMPLE_RATE + has_or_had_unit: + unit_value: "fps" + frame_width: 1920 + frame_height: 1080 + description: 5 fps analysis of HD video. + + comments: + - Created from slot_fixes.yaml migration (2026-01-22) + - Use with analyzes_or_analyzed slot to track frame analysis + - Sample rate affects both coverage and compute cost diff --git a/schemas/20251121/linkml/modules/slots/analyzes_or_analyzed.yaml b/schemas/20251121/linkml/modules/slots/analyzes_or_analyzed.yaml index 96b364b993..3213966d1a 100644 --- a/schemas/20251121/linkml/modules/slots/analyzes_or_analyzed.yaml +++ b/schemas/20251121/linkml/modules/slots/analyzes_or_analyzed.yaml @@ -2,6 +2,7 @@ # # Created per slot_fixes.yaml migration for: total_frames_analyzed # Creation date: 2026-01-14 +# Updated 2026-01-22: Extended to support VideoFrame class for frame_sample_rate migration id: https://nde.nl/ontology/hc/slot/analyzes_or_analyzed name: analyzes_or_analyzed @@ -17,6 +18,7 @@ default_prefix: hc imports: - linkml:types + - ../classes/VideoFrame slots: analyzes_or_analyzed: @@ -26,12 +28,32 @@ slots: **USAGE**: Used for: - - Frames analyzed in video processing + - Frames analyzed in video processing (VideoFrame class) - Documents analyzed - Items processed - range: integer + **MIGRATION SUPPORT**: + This slot now supports VideoFrame class for frame_sample_rate migration + per slot_fixes.yaml (Rule 53, 2026-01-22). + + **Examples**: + - Integer: Total frames count (legacy pattern) + - VideoFrame: Structured frame analysis with sample rate + + range: Any + any_of: + - range: integer + - range: VideoFrame + inlined: true examples: - value: 24000 - description: Total video frames analyzed + description: Total video frames analyzed (integer count) + - value: | + has_or_had_quantity: + quantity_value: 1.0 + quantity_type: FRAME_SAMPLE_RATE + has_or_had_unit: + unit_value: "samples per second" + frame_count: 1800 + description: Video frame analysis at 1 fps (VideoFrame instance) diff --git a/schemas/20251121/linkml/modules/slots/community_significance.yaml b/schemas/20251121/linkml/modules/slots/archive/community_significance_archived_20260122.yaml similarity index 100% rename from schemas/20251121/linkml/modules/slots/community_significance.yaml rename to schemas/20251121/linkml/modules/slots/archive/community_significance_archived_20260122.yaml diff --git a/schemas/20251121/linkml/modules/slots/frame_sample_rate.yaml b/schemas/20251121/linkml/modules/slots/archive/frame_sample_rate_archived_20260122.yaml similarity index 100% rename from schemas/20251121/linkml/modules/slots/frame_sample_rate.yaml rename to schemas/20251121/linkml/modules/slots/archive/frame_sample_rate_archived_20260122.yaml diff --git a/schemas/20251121/linkml/modules/slots/manifest.json b/schemas/20251121/linkml/modules/slots/manifest.json index a753e6f3f0..1f56bf21c7 100644 --- a/schemas/20251121/linkml/modules/slots/manifest.json +++ b/schemas/20251121/linkml/modules/slots/manifest.json @@ -103,7 +103,7 @@ "__ARCHIVED_20260122__common_name.yaml", "__ARCHIVED_20260122__common_name_language.yaml", "__ARCHIVED_20260122__common_variant.yaml", - "community_significance.yaml", + "__ARCHIVED_20260122__community_significance.yaml", "complex_name.yaml", "compliance_status.yaml", "component_type.yaml", @@ -499,7 +499,6 @@ "follower_count.yaml", "following_count.yaml", "footnote.yaml", - "frame_sample_rate.yaml", "from_location.yaml", "full_extracted_text.yaml", "full_name.yaml", diff --git a/schemas/20251121/linkml/modules/slots/slot_fixes.yaml b/schemas/20251121/linkml/modules/slots/slot_fixes.yaml index 197a93e820..122a3891f0 100644 --- a/schemas/20251121/linkml/modules/slots/slot_fixes.yaml +++ b/schemas/20251121/linkml/modules/slots/slot_fixes.yaml @@ -10793,6 +10793,26 @@ fixes: - label: SignificanceTypes type: class note: this includes CommunitySignificance + processed: + status: true + date: '2026-01-22' + agent: claude-claude-sonnet-4-20250514 + notes: | + **Migration #40: community_significance** ✅ COMPLETE + + **Pattern**: community_significance → has_or_had_significance + Significance + has_or_had_type + SignificanceType + includes_or_included + SignificanceTypes + + **Files Created**: + - has_or_had_significance.yaml: Generic slot for significance relationships (crm:P17i_was_motivation_for) + - Significance.yaml: Class for structured significance representation + - SignificanceType.yaml: Abstract base class for significance type taxonomy (Rule 0b) + - SignificanceTypes.yaml: Concrete subclasses (CommunitySignificance, EconomicSignificance, HistoricalSignificance, ScientificSignificance, AestheticSignificance, TerroirSignificance, DiplomaticSignificance) + + **Files Modified**: + - TasteScentHeritageType.yaml: Migrated community_significance to has_or_had_significance + Significance + - Updated imports, slots, slot_usage with structured examples + + **Archived**: modules/slots/archive/community_significance_archived_20260122.yaml - original_slot_id: https://nde.nl/ontology/hc/slot/completion_token revision: - label: has_or_had_token @@ -13737,6 +13757,12 @@ fixes: - label: Unit type: class value: frames per second + processed: + status: true + notes: "FULLY_MIGRATED 2026-01-22: frame_rate → has_or_had_quantity + Quantity + has_or_had_unit + Unit (Rule 53). + VideoPost.yaml migrated to use Quantity class with has_or_had_unit for frame rate (fps). + Reused existing has_or_had_quantity, Quantity, has_or_had_unit, Unit. + Old slot archived to archive/frame_rate_archived_20260122.yaml" - original_slot_id: https://nde.nl/ontology/hc/slot/frame_sample_rate revision: - label: analyzes_or_analyzed @@ -13752,6 +13778,14 @@ fixes: - label: Unit type: class value: samples per second + processed: + status: true + notes: "FULLY_MIGRATED 2026-01-22: frame_sample_rate → analyzes_or_analyzed + VideoFrame + has_or_had_quantity + Unit (Rule 53). + Created VideoFrame.yaml class for video frame analysis. + Updated analyzes_or_analyzed slot to support VideoFrame range (any_of). + VideoAnnotation.yaml migrated to use VideoFrame for frame sample rate. + Reused existing has_or_had_quantity, Quantity, has_or_had_unit, Unit. + Old slot archived to archive/frame_sample_rate_archived_20260122.yaml" - original_slot_id: https://nde.nl/ontology/hc/slot/from_location revision: - label: has_or_had_origin diff --git a/scripts/regenerate_manifest.py b/scripts/regenerate_manifest.py index 65e7d0bcc5..47c4d2e353 100644 --- a/scripts/regenerate_manifest.py +++ b/scripts/regenerate_manifest.py @@ -3,11 +3,16 @@ Regenerate manifest.json for LinkML schema frontend. This script scans the LinkML schema directory and generates a complete manifest -of all class and enum files for the frontend to load. +of all class, enum, and slot files for the frontend to load. + +The manifest structure matches what the frontend LinkMLSchemaService expects: +- schemaRoot: Base path for schema files +- totalFiles: Total count of all files +- categoryCounts: Per-category file counts +- categories: Array of category objects with files """ import json -import os from datetime import datetime, timezone from pathlib import Path @@ -26,7 +31,18 @@ def get_yaml_files(directory: Path) -> list[str]: return sorted([f.stem for f in directory.glob("*.yaml")]) +def get_main_yaml_files(directory: Path) -> list[str]: + """Get top-level .yaml files in schema directory.""" + if not directory.exists(): + return [] + return sorted([f.stem for f in directory.glob("*.yaml") if f.is_file()]) + + def main(): + # Get all main schema files (top-level .yaml files) + main_files = get_main_yaml_files(SCHEMA_DIR) + print(f"Found {len(main_files)} main schema files") + # Get all class files class_files = get_yaml_files(CLASSES_DIR) print(f"Found {len(class_files)} class files") @@ -39,20 +55,32 @@ def main(): slot_files = get_yaml_files(SLOTS_DIR) print(f"Found {len(slot_files)} slot files") - # Build manifest structure + # Calculate totals + total_files = len(main_files) + len(class_files) + len(enum_files) + len(slot_files) + + # Build manifest structure matching frontend expectations manifest = { - "generated": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.000Z"), - "version": "1.0.0", + "generated": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z", + "schemaRoot": "/schemas/20251121/linkml", + "totalFiles": total_files, + "categoryCounts": { + "main": len(main_files), + "class": len(class_files), + "enum": len(enum_files), + "slot": len(slot_files), + "module": 4 # Fixed count for module imports + }, "categories": [ { "name": "main", - "displayName": "Main Schema", + "displayName": "Main Schemas", "files": [ { - "name": "Heritage Custodian Ontology", - "path": "01_custodian_name_modular.yaml", + "name": name, + "path": f"{name}.yaml", "category": "main" } + for name in main_files ] }, { @@ -62,7 +90,7 @@ def main(): { "name": name, "path": f"modules/classes/{name}.yaml", - "category": "classes" + "category": "class" } for name in class_files ] @@ -74,7 +102,7 @@ def main(): { "name": name, "path": f"modules/enums/{name}.yaml", - "category": "enums" + "category": "enum" } for name in enum_files ] @@ -86,7 +114,7 @@ def main(): { "name": name, "path": f"modules/slots/{name}.yaml", - "category": "slots" + "category": "slot" } for name in slot_files ] @@ -99,11 +127,11 @@ def main(): json.dump(manifest, f, indent=2) print(f"\n✅ Manifest written to {MANIFEST_PATH}") - print(f" - Main schema: 1 file") + print(f" - Main schemas: {len(main_files)} files") print(f" - Classes: {len(class_files)} files") print(f" - Enums: {len(enum_files)} files") print(f" - Slots: {len(slot_files)} files") - print(f" - Total: {1 + len(class_files) + len(enum_files) + len(slot_files)} files") + print(f" - Total: {total_files} files") if __name__ == "__main__":