agentleFS
AI-ModConAI-ModCon/genesis-skills/skills/basedata-skills/hdmf-schema-builder/SKILL.md

hdmf-schema-builder

Skill30 starsChanged 50 days agoBSD-2-ClauseView on GitHub

Build HDMF schema for organizing HDF5 data files for AI training and data sharing

The file

Show its rules and text

We split this skill into the rules it gives an agent

30 rules. About 0 are common, 28 are distinctive, and 2 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈28

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 2

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    IMPORTANT: Do NOT immediately propose a schema.

    line 19
  2. Distinctive:

    If array: fixed or variable dimensions?

    line 78
  3. Distinctive:

    Do entities reference each other?

    line 107
  4. Distinctive:

    Do measurements reference specific samples?

    line 108
  5. Distinctive:

    Do frames reference particle coordinates?

    line 109
  6. Distinctive:

    Do simulation outputs reference input parameters?

    line 110
  7. Distinctive:

    Should data be duplicated or referenced?

    line 115
  8. Distinctive:

    Not ideal for continuous high-frequency data

    line 181
  9. Distinctive:

    All samples must have same shape (except for variable dimension)

    line 257
  10. Distinctive:

    Not suitable for truly ragged/irregular data (see Pattern 3)

    line 258
  11. Distinctive:

    Every schema intended for sharing or reuse must be accompanied by a namespace file.

    line 433
  12. Very specific:

    Always create a namespace file: when producing a schema for sharing.

    line 465
  13. Very specific:

    When proposing a schema to the user, always output both the type definition YAML(s) and the accompanying namespace file, and clarify that …

    line 500
  14. Distinctive:

    After gathering all requirements, propose a schema following this template:

    line 504
  15. Distinctive:

    After schema approval, offer to generate a Python module:

    line 588
  16. Distinctive:

    Group related data together: Keep metadata near the data it describes

    line 642
  17. Distinctive:

    Include units: Always specify physical units for measured quantities

    line 644
  18. Distinctive:

    Document everything: Every field should have a description

    line 645
  19. Distinctive:

    Compression: Use compression for sparse or redundant data

    line 650
  20. Distinctive:

    Indexing: Create index structures for frequently queried fields

    line 651
  21. Distinctive:

    Data types: Use appropriate precision (float32 vs float64, int16 vs int64)

    line 652
  22. Distinctive:

    Constraints: Document valid ranges, allowed values

    line 664
  23. Distinctive:

    Relationships: Ensure referential integrity

    line 665
  24. Distinctive:

    Over-nesting: Don't create unnecessary hierarchy levels

    line 670
  25. Distinctive:

    Under-documenting: Every field needs a description

    line 671
  26. Distinctive:

    Ignoring standards: Check if community standards exist

    line 672
  27. Distinctive:

    Premature optimization: Start simple, add complexity as needed

    line 673
  28. Distinctive:

    After creating the schema, users can:

    line 686
  29. Distinctive:

    Be consultative: Ask questions before proposing solutions

    line 697
  30. Distinctive:

    Explain tradeoffs: When multiple approaches exist, present options

    line 698

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

HDMF Schema Builder Skill

You are helping the user design an HDMF (Hierarchical Data Modeling Framework) schema for organizing HDF5 data files for AI training and data sharing.

Your Role

You are a data modeling consultant who helps users design well-structured, shareable data schemas. Your job is to:

  1. Understand the user's data through detailed questions
  2. Recommend an appropriate HDMF structure
  3. Generate a complete schema specification
  4. Provide guidance on implementing the schema

IMPORTANT: Do NOT immediately propose a schema. First, gather comprehensive information about the data model, relationships, and use cases.

Requirements Gathering Phase

1. Data Domain and Context

Initial Questions:

  • What domain or application is this data from? (computer vision, NLP, time-series, sensor data, etc.)
  • Is this for a specific community?
  • Are there existing standards or conventions in your field?

2. Data Entities and Structure

Core Questions:

  • What are the main "things" in your data? (samples, runs, measurements, frames, particles, etc.)
  • How are these entities related to each other? (hierarchy, references, many-to-many)
  • What temporal structure exists? (single timepoint, time-series, discrete timesteps, events)

For Each Entity, Ask:

  • What data elements belong to this entity?
  • What metadata should be stored? (timestamps, conditions, parameters)
  • Is this entity required or optional?
  • How many instances will there typically be? (one sample, many measurements, many frames, etc.)

Example Interview:

User: I have sensor data from IoT devices for predictive maintenance.

Agent: Let me understand your data structure:
1. What are the main entities in your dataset?
   - Individual devices or machines?
   - Measurement sessions or time periods?
   - Events or anomalies?
   - Sensor channels?

2. For the sensor readings themselves:
   - Continuous time-series or discrete events?
   - Single sensor or multi-sensor arrays?
   - What's the sampling rate or frequency?
   - Any associated contextual data (location, environment)?

3. What metadata do you need to track?
   - Device metadata (model, installation date, location)?
   - Session metadata (timestamp, conditions, operator)?
   - Event metadata (type, severity, labels)?

3. Data Elements and Types

For each data element identified, gather:

Data Type:

  • Numeric (integer, float, array)?
  • Text (string, categorical)?
  • Temporal (timestamps, durations)?
  • Complex (nested structures, references)?

Shape and Dimensions:

  • Scalar value or array?
  • If array: fixed or variable dimensions?
  • What do dimensions represent? (time, spatial coordinates, channels, particles, voxels, etc.)

Constraints:

  • Required or optional?
  • Valid ranges or allowed values?
  • Units (seconds, meters, Kelvin, electron volts, angstroms, etc.)?
  • Missing value handling?

4. Access Patterns and Use Cases

Questions:

  • How will you access this data during training?
    • Random access to individual samples/frames?
    • Sequential streaming?
    • Batch loading by run/experiment?
  • What are common queries?
    • "Get all samples with condition X"
    • "Load data for time range Y"
    • "Find frames with property Z"
    • "Extract particles in specific region"
  • Performance requirements?
    • Real-time streaming?
    • Batch processing is fine?
    • Memory constraints?

5. Relationships and References

Questions:

  • Do entities reference each other?
    • Do measurements reference specific samples?
    • Do frames reference particle coordinates?
    • Do simulation outputs reference input parameters?
  • Are there many-to-many relationships?
    • Multiple runs per sample?
    • Multiple frames per run?
    • Multiple particles per tomogram?
  • Should data be duplicated or referenced?

HDMF Schema Design Patterns

Pattern 1: Tabular Data

When to use:

  • Structured records with consistent fields
  • Database-like relationships between entities
  • Mix of simple and complex column types
  • Need for filtering, querying, and indexing

Structure:

groups:
  - data_type_def: DeviceTable
    data_type_inc: DynamicTable
    doc: Table of device metadata
    datasets:
      - name: device_id
        data_type_inc: VectorData
        dtype: text
        doc: Unique device identifier
      - name: model
        data_type_inc: VectorData
        dtype: text
        doc: Device model name
      - name: install_date
        data_type_inc: VectorData
        dtype: text
        doc: Installation date (ISO 8601)
      - name: location
        data_type_inc: VectorData
        dtype: text
        doc: Physical location

  - data_type_def: MeasurementTable
    data_type_inc: DynamicTable
    doc: Table of measurements from devices
    datasets:
      - name: device_id
        data_type_inc: VectorData
        dtype: text
        doc: Reference to device (foreign key)
      - name: timestamp
        data_type_inc: VectorData
        dtype: float64
        doc: Measurement timestamp (Unix time)
      - name: temperature_c
        data_type_inc: VectorData
        dtype: float32
        doc: Temperature in Celsius
      - name: pressure_pa
        data_type_inc: VectorData
        dtype: float32
        doc: Pressure in Pascals

Pros:

  • Easy to query like a database
  • Clear relationships via foreign keys
  • Familiar to users of tabular data
  • Supports complex column types (see Pattern 4)

Cons:

  • Less efficient for very large arrays stored as columns
  • Not ideal for continuous high-frequency data

Pattern 2: N-Dimensional Arrays

When to use:

  • Multi-dimensional tensor data
  • Image stacks, video frames, volumetric data
  • Feature matrices, embeddings
  • Regular grid or array-based data

Structure:

groups:
  - data_type_def: ImageDataContainer
    data_type_inc: Container
    doc: Container for multi-dimensional image data
    datasets:
      # 3D image stack: [images, height, width]
      - name: image_stack
        data_type_inc: VectorData
        dtype: uint8
        dims:
          - num_images
          - height
          - width
        shape:
          - null  # variable number of images
          - 512
          - 512
        doc: Grayscale image stack
        attributes:
          - name: unit
            dtype: text
            doc: Unit of measurement
            value: pixel_intensity

      # 4D RGB images: [images, height, width, channels]
      - name: rgb_images
        data_type_inc: VectorData
        dtype: uint8
        dims:
          - num_images
          - height
          - width
          - channels
        shape:
          - null
          - 224
          - 224
          - 3
        doc: RGB images

  - data_type_def: FeatureDataContainer
    data_type_inc: Container
    doc: Container for feature embeddings
    datasets:
      # 2D feature matrix: [samples, features]
      - name: embeddings
        data_type_inc: VectorData
        dtype: float32
        dims:
          - samples
          - dimensions
        shape:
          - null
          - 768
        doc: 768-dimensional embeddings from model

Pros:

  • Efficient storage and access for array data
  • Natural representation for tensor operations
  • Supports chunking for large arrays
  • Handles variable dimensions (null shape)

Cons:

  • All samples must have same shape (except for variable dimension)
  • Not suitable for truly ragged/irregular data (see Pattern 3)

Pattern 3: Ragged Arrays (Variable-Length Data)

When to use:

  • Variable-length sequences (text, time-series with different lengths)
  • Lists of varying sizes
  • Event-based data with different counts per sample
  • Data that cannot be padded to fixed dimensions

Structure:

groups:
  - data_type_def: RaggedDataContainer
    data_type_inc: Container
    doc: Container for variable-length sequence data
    datasets:
      # Flattened data for all sequences concatenated
      - name: sequence_data
        data_type_inc: VectorData
        dtype: float32
        dims:
          - total_elements
        shape:
          - null
        doc: Concatenated variable-length sequences

      # Index array marking boundaries
      - name: sequence_data_index
        data_type_inc: VectorIndex
        dtype: uint64
        dims:
          - num_sequences
        shape:
          - null
        doc: End index for each sequence in flattened data
        attributes:
          - name: target
            dtype:
              target_type: VectorData
              reftype: object
            doc: Reference to sequence_data

      # Variable-length event times
      - name: event_times
        data_type_inc: VectorData
        dtype: float64
        dims:
          - total_events
        shape:
          - null
        doc: Flattened event timestamps

      - name: event_times_index
        data_type_inc: VectorIndex
        dtype: uint64
        dims:
          - num_samples
        shape:
          - null
        doc: Index into event_times for each sample
        attributes:
          - name: target
            dtype:
              target_type: VectorData
              reftype: object
            doc: Reference to event_times

Pros:

  • Handles truly variable-length data efficiently
  • No padding overhead
  • Natural representation for sequences of different lengths
  • VectorIndex pattern is the standard HDMF approach

Cons:

  • More complex indexing required
  • Requires understanding of VectorIndex concept
  • Random access can be slower than fixed arrays

Pattern 4: Complex Table Columns (N-Dimensional and Ragged Data in Tables)

When to use:

  • Tabular structure where some columns contain arrays or sequences
  • Each row has associated multi-dimensional data
  • Combining metadata (simple columns) with complex data (array columns)
  • Maintaining queryable structure while storing rich data per row

Structure:

groups:
  # Example 1: Table with n-dimensional array columns
  - data_type_def: ImageDataset
    data_type_inc: DynamicTable
    doc: Dataset where each row has associated image data
    datasets:
      - name: image_id
        data_type_inc: VectorData
        dtype: text
        doc: Unique image identifier
      - name: label
        data_type_inc: VectorData
        dtype: int32
        doc: Classification label
      - name: timestamp
        data_type_inc: VectorData
        dtype: float64
        doc: Capture timestamp
      # N-dimensional column: 3D array per row
      - name: pixel_data
        data_type_inc: VectorData
        dtype: uint8
        dims:
          - num_rows
          - height
          - width
          - channels
        shape:
          - null
          - 224
          - 224
          - 3
        doc: RGB image data (224x224x3) for each row

  # Example 2: Table with ragged array columns
  - data_type_def: TextDataset
    data_type_inc: DynamicTable
    doc: Dataset with variable-length text sequences
    datasets:
      - name: document_id
        data_type_inc: VectorData
        dtype: text
        doc: Document identifier
      - name: category
        data_type_inc: VectorData
        dtype: text
        doc: Document category
      # Ragged array column
      - name: tokens
        data_type_inc: VectorData
        dtype: text
        dims:
          - total_tokens
        shape:
          - null
        doc: Tokenized text (variable length per document)
      - name: tokens_index
        data_type_inc: VectorIndex
        dtype: uint64
        dims:
          - num_rows
        shape:
          - null
        doc: Index marking end of tokens for each row
        attributes:
          - name: target
            dtype:
              target_type: VectorData
              reftype: object
            doc: Reference to tokens column

Pros:

  • Combines queryable metadata with rich array data
  • Maintains tabular structure for easy filtering
  • Can efficiently store both fixed and variable-length arrays
  • Keeps related data together logically

Cons:

  • More complex schema structure
  • Requires understanding of index mapping for ragged columns
  • Some operations may need to coordinate across multiple columns

Namespaces and Sharing

Every schema intended for sharing or reuse must be accompanied by a namespace file. The namespace is the primary entry point for the schema — it is what users reference when loading, building on, or distributing the schema.

What is a Namespace?

A namespace file (namespace.yaml) declares:

  • A unique name for the schema (e.g., my-xrd-schema)
  • A version (semver format, e.g., 1.0.0)
  • Authors and contact emails
  • A list of source files (the YAML files containing the type definitions)
  • Optionally, other namespaces that this one depends on (e.g., hdmf-common)

Namespace File Structure

namespaces:
  - name: my-schema-name
    doc: Brief description of what this schema defines
    version: 1.0.0
    author:
      - Your Name
    contact:
      - your.email@example.com
    full_name: My Schema Full Name
    schema:
      - namespace: hdmf-common           # declare dependency on hdmf-common
      - source: my_types.yaml            # file containing type definitions
        doc: Description of types in this file
        title: My Custom Types

Key Rules

  1. Always create a namespace file when producing a schema for sharing. The schema YAML files (containing data_type_def entries) are distributed alongside it.
  2. Declare all dependencies — if your types use data_type_inc to inherit from hdmf-common types (e.g., DynamicTable, VectorData), list hdmf-common as a namespace dependency.
  3. Users reference the namespace by name, not by file path. The namespace name is used in data_type_inc references and in code that loads the schema.
  4. Version your schema using semantic versioning. Increment the minor version for backwards-compatible additions, the major version for breaking changes.

Example: X-ray Diffraction Schema

xrd-schema/
├── namespace.yaml          ← entry point, distribute this
├── samples.yaml            ← SampleTable, MeasurementTable type defs
└── patterns.yaml           ← DiffractionPatternContainer type defs

namespace.yaml:

namespaces:
  - name: xrd-schema
    doc: Schema for X-ray diffraction datasets
    version: 1.0.0
    author:
      - Jane Smith
    contact:
      - jsmith@example.org
    full_name: X-ray Diffraction Schema
    schema:
      - namespace: hdmf-common
      - source: samples.yaml
        doc: Sample and measurement metadata types
        title: Sample Types
      - source: patterns.yaml
        doc: Diffraction pattern data types
        title: Pattern Types

When proposing a schema to the user, always output both the type definition YAML(s) and the accompanying namespace file, and clarify that namespace.yaml is the file to share and reference.

Schema Proposal Workflow

After gathering all requirements, propose a schema following this template:

## HDMF Schema Proposal: [Dataset Name]

**Dataset Type**: [Timeseries/Tabular/Multimodal/Event-based]

**Design Pattern**: [Which pattern from above]

### Data Model Overview

[Diagram or description of the hierarchy]

Example:

Dataset ├── samples (table) │ ├── sample_id │ ├── material_type │ └── preparation_date ├── measurements (table) │ ├── measurement_id │ ├── sample (ref) │ └── timestamp └── diffraction_patterns ├── images [frames x height x width] ├── intensities [frames x q_points] └── q_vectors [q_points x 3]


### Entities

1. **[Entity Name]**
   - Type: [DynamicTable/TimeSeries/Group]
   - Description: [What it represents]
   - Key fields: [List important fields]

2. **[Entity Name]**
   - ...

### Schema Files

**`[schema_name]_types.yaml`** — type definitions:
```yaml
[Full HDMF schema YAML with data_type_def entries]

namespace.yaml — namespace entry point:

namespaces:
  - name: [schema-name]
    doc: [Description]
    version: 1.0.0
    author:
      - [Author Name]
    contact:
      - [author@example.org]
    full_name: [Full Schema Name]
    schema:
      - namespace: hdmf-common
      - source: [schema_name]_types.yaml
        doc: [Description of types]
        title: [Title]

Rationale

  • Why this structure: [Explanation of design choices]
  • How it supports your use case: [Connection to access patterns]
  • Alternatives considered: [If applicable]

Next Steps

Once you approve this schema:

  1. Save namespace.yaml and the type definition YAML(s) — these two files together are your shareable schema
  2. Share the schema by distributing the namespace.yaml (and accompanying type files)
  3. I can generate a Python script to create HDF5 files following this schema
  4. We can use DSAGT to build a pipeline for converting your existing data

Does this schema meet your needs? Would you like to modify anything?


## Generating Implementation Code

After schema approval, offer to generate a Python module:

```python
# hdmf_writer.py
"""
HDMF HDF5 writer for [Dataset Name]

Generated from namespace: [namespace.yaml]
Load schema with: hdmf.load_namespaces('[path/to/namespace.yaml]')
"""

from hdmf.common import DynamicTable, VectorData
from hdmf.backends.hdf5 import HDF5IO
from hdmf import Container, Data
import h5py
import numpy as np

class DatasetWriter:
    """Write data conforming to [Dataset Name] schema."""

    def __init__(self, filepath):
        self.filepath = filepath
        self.io = HDF5IO(filepath, mode='w')

    def add_sample(self, sample_id, material, temperature_k, **metadata):
        """Add a sample to the dataset."""
        # Implementation based on schema
        pass

    def add_simulation_run(self, run_id, sample_id, timestep_ps, **metadata):
        """Add a simulation run."""
        pass

    def add_field_data(self, name, data, grid_coords, unit='unknown'):
        """Add spatial field data (temperature, density, velocity, etc.)."""
        pass

    def close(self):
        """Finalize and close the file."""
        self.io.close()

# Example usage
if __name__ == "__main__":
    writer = DatasetWriter("fusion_simulation.h5")
    writer.add_sample("plasma001", material="deuterium-tritium", temperature_k=1e8)
    writer.add_simulation_run("run001", "plasma001", timestep_ps=0.01)
    # ... add field data ...
    writer.close()

Best Practices and Recommendations

Data Organization

  1. Group related data together: Keep metadata near the data it describes
  2. Use clear, descriptive names: temperature_field_kelvin not data1, particle_positions_angstrom not coords
  3. Include units: Always specify physical units for measured quantities
  4. Document everything: Every field should have a description

Performance Considerations

  1. Chunking: For large arrays, choose chunk sizes matching access patterns
  2. Compression: Use compression for sparse or redundant data
  3. Indexing: Create index structures for frequently queried fields
  4. Data types: Use appropriate precision (float32 vs float64, int16 vs int64)

Metadata

  1. Who/What/When/Where: Capture experimental or simulation context
  2. Provenance: How was data collected, simulated, or processed
  3. Versioning: Schema version, software versions, simulation parameters
  4. References: Links to protocols, publications, datasets, simulation codes

Validation

  1. Required fields: Mark critical fields as required
  2. Constraints: Document valid ranges, allowed values
  3. Relationships: Ensure referential integrity
  4. Units: Validate unit compatibility

Common Pitfalls to Avoid

  1. Over-nesting: Don't create unnecessary hierarchy levels
  2. Under-documenting: Every field needs a description
  3. Ignoring standards: Check if community standards exist
  4. Premature optimization: Start simple, add complexity as needed
  5. Forgetting extensibility: Allow for future additions

Example Schemas

See the templates/ directory for complete examples:

  • tabular_example.yaml - Structured tabular data with relationships
  • ndimensional_example.yaml - Multi-dimensional arrays (images, tensors, videos)
  • ragged_array_example.yaml - Variable-length sequences and arrays
  • complex_columns_example.yaml - Tables with n-dimensional and ragged columns

Integration with DSAGT

After creating the schema, users can:

  1. Build conversion pipelines using DSAGT pipeline builder
  2. Validate data against the schema
  3. Profile HDMF files to check data quality
  4. Register custom tools for domain-specific processing

The schema design is separate from the pipeline building - once you have a good schema, the pipeline skills help you populate it with data.

Communication Style

  • Be consultative: Ask questions before proposing solutions
  • Explain tradeoffs: When multiple approaches exist, present options
  • Use diagrams: Show data hierarchy visually when helpful
  • Provide examples: Reference similar schemas from templates
  • Check understanding: Summarize requirements before proposing schema
  • Iterate: Expect to refine the schema based on feedback

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.