Skip to main content
Adding a format is one module + one test + one registry row. See sdk/python/dataerai/metaextract/CONTRIBUTING_EXTRACTORS.md for the full contract. Source lives under sdk/python/dataerai/metaextract/ in the monorepo.

1. Write an extractor

Subclass MetadataExtractor and implement _do_extract(), or reuse a structural base from bases.pyHdf5Extractor, XmlMetadataExtractor, or TextHeaderExtractor. Place it under the matching domain package (containers/, microscopy/, medical/, bio/, compchem/, …, or an instruments/<Category>/<vendor>/). The base class filters out blank-string values automatically. Read headers/attributes only — never load full arrays — and unit-tag every physical quantity with units.tag() so it is searchable in the units engine:
tag() returns the {"value", "unit"} override the console’s unit-aware search consumes when the unit maps to the catalog, or the bare value otherwise — so it is always safe to call. Calling .extract() (not _do_extract()) runs the extraction and applies filtering:

2. (Optional) write a converter

Subclass Converter (from core.py) and implement _do_convert(), which returns an xarray.Dataset. The public convert(output_path=...) wrapper runs it and optionally writes netCDF. Converters typically reuse the matching extractor for the metadata and add the array data on top. Put it under converters/<Category>/<vendor>/<format>.py. Only formats with a converter row appear with convert: true in get_supported_formats().

3. Register the format

Add one FormatSpec row to the declarative SPECS table in registry.py. extract_metadata() / convert_file() / get_supported_formats() pick it up by extension automatically — no edits to api.py.
The registry resolves the class lazily: if your extractor’s heavy parser library isn’t installed, the row resolves to None and the format is simply absent in that environment — so import your parser at the top of the module (let it raise ImportError) rather than guarding it yourself. Pure-stdlib/numpy extractors always register. Don’t claim a generic extension (.xml, .out, .raw) that would hijack unrelated files — add a content sniff and lean on the format= alias instead.

4. (Optional) add a data type + visualization

Define a DataType so the format is classified, and register a visualizer so visualize_data() can route to it. register_visualization() is a plain function — pass the data-type name and your plotting function (it is not a decorator):
visualize_data(dataset) then detects the data type from the dataset’s metadata and dispatches to your function via the visualization registry.

5. Test it on a real file

Add a test under sdk/python/tests/metaextract/. Test on a real file — generate a genuine, valid file with the format’s own writer (or build a minimal one by hand from the documented layout), then extract and assert known fields, including at least one unit-tagged value. Skip cleanly when the writer/reader library is absent. Run the suite with the full extras installed:
Once the format is supported in dataerai.metaextract, DataErai’s server-side automatic extraction picks it up too — the console calls the exact same library.