Skip to content

CLI Reference

thyra [OPTIONS] INPUT OUTPUT

INPUT -- Path to input MSI file or directory (.imzML, .d, .raw)

OUTPUT -- Path for output .zarr directory

thyra also has two metadata subcommands, thyra validate and thyra export-metaspace -- see Metadata subcommands.

Grouped help

thyra --help lists every option under a category heading -- Conversion, Logging, Resampling (advanced), Performance, imzML-specific, Bruker-specific, Other, and a General section holding --version and --help -- in the same order as the sections on this page.


Exit status

Code Meaning
0 Conversion completed and the output store was written
1 Conversion failed
2 Invalid command-line arguments (click usage error)

A failed conversion renames any partially written store to <output>.zarr.failed, so the output path stays free for a retry and an incomplete store is never left where a finished one is expected. This makes thyra safe to chain in a shell script or CI job:

thyra input.imzML output.zarr && python analyse.py output.zarr

Conversion

Option Default Description
--format [spatialdata] spatialdata Output format
--pixel-size FLOAT auto-detect Pixel size in micrometers
--region TEXT all Convert one region, by .mis Area Name or by DB RegionNumber
--resample / --no-resample enabled Mass axis resampling
--include-optical / --no-optical enabled Include optical images in output

Examples

# Basic conversion -- format, pixel size, and resampling all auto-detected
thyra input.imzML output.zarr

# Specify pixel size manually (when metadata is unavailable)
thyra input.imzML output.zarr --pixel-size 25

# Convert one region, named the way flexImaging names it
thyra data.d output.zarr --region 03

# Or by the database's own region number
thyra data.d output.zarr --region 0

# Skip optical images
thyra data.d output.zarr --no-optical

Naming a region

--region takes a string, and the value is matched against the .mis Area Names first. Only if nothing matches is it parsed as a DB RegionNumber, which starts at 0. Passing something that is neither is an error that lists the area names it did find.

The two numbering schemes do not have to agree, which is exactly why area '03' need not be RegionNumber 3. For a multi-region dataset Thyra logs the whole mapping at INFO during startup -- a header line Region mapping (DB RegionNumber -> .mis Area Name): followed by one RegionNumber <n> -> Area '<name>' (<n> frames) line per region -- so a plain run already tells you which is which before you pick one.

Use -v DEBUG for the per-region spectrum counts as well.


Logging

Option Default Description
-v, --log-level LEVEL INFO Logging level: DEBUG, INFO, WARNING, ERROR, CRITICAL
--log-file PATH none Write logs to file

Examples

# Verbose output -- shows pixel size detection, resampling config, timing
thyra input.imzML output.zarr -v DEBUG

# Save logs to file for later review
thyra input.imzML output.zarr --log-file conversion.log

Debugging conversions

When something looks wrong in the output, re-run with -v DEBUG --log-file debug.log. The log will contain pixel size detection details, resampling parameters, region info, and timing for each step.


Resampling (Advanced)

These options control how spectra are mapped onto a common mass axis. In most cases the defaults work well -- Thyra auto-detects the instrument type and chooses an appropriate method and bin count.

Option Default Description
--resample-method METHOD auto auto, nearest_neighbor, or tic_preserving
--mass-axis-type TYPE auto auto, constant, linear_tof, reflector_tof, orbitrap, fticr
--resample-bins INTEGER auto Number of bins (mutually exclusive with --resample-width-at-mz)
--resample-min-mz FLOAT auto Minimum m/z value
--resample-max-mz FLOAT auto Maximum m/z value
--resample-width-at-mz FLOAT auto Mass width in Da at reference m/z for physics-based binning
--resample-reference-mz FLOAT 1000.0 Reference m/z for width specification
--resample-gap-tolerance FLOAT none tic_preserving only: discard target bins farther than this many Da from any measured m/z, instead of interpolating across the gap

Choosing a resampling method

  • nearest_neighbor -- Each target bin takes the nearest original m/z value. Correct for centroid data, where peaks are discrete masses.
  • tic_preserving -- Linear interpolation, rescaled so the total ion current is unchanged. Correct for profile data on a target axis whose bin widths scale the same way the source points are spaced -- pair it only with constant unless you know otherwise.
  • auto -- Picks tic_preserving only for Bruker flexImaging / Rapiflex data, whose source grid is uniform in m/z, and nearest_neighbor for everything else -- including profile data from an instrument Thyra cannot identify, because the interpolating method is only exact when the two axis laws match. See Resampling for the full decision table.

Choosing a mass axis type

The axis type determines how bin widths scale with m/z:

  • constant -- Uniform bin width (Da). Suitable for MALDI-TOF in linear mode.
  • linear_tof -- Width scales as sqrt(m/z). Matches TOF resolution.
  • reflector_tof -- Width scales linearly with m/z (constant relative resolution). Matches reflector TOF.
  • orbitrap -- Width scales as m/z^(3/2). Matches Orbitrap resolution.
  • fticr -- Width scales as m/z^2. Matches FTICR resolution.
  • auto -- Detected from instrument metadata.

Examples

# Physics-based resampling for Orbitrap data
thyra input.imzML output.zarr \
    --resample-method tic_preserving \
    --mass-axis-type orbitrap

# Fixed number of bins
thyra input.imzML output.zarr --resample-bins 50000

# Restrict mass range
thyra input.imzML output.zarr --resample-min-mz 100 --resample-max-mz 1000

# Specify bin width at a reference m/z (physics-based)
thyra input.imzML output.zarr \
    --resample-width-at-mz 0.01 \
    --resample-reference-mz 500

Performance

Option Default Description
--streaming [auto\|true\|false] auto Streaming mode for large datasets
--sparse-format [csc\|csr] csc Sparse matrix storage format

Streaming mode

  • auto (default) -- Thyra estimates dataset size and enables streaming for datasets over ~10 GB.
  • true -- Force streaming. Useful if auto-detection underestimates.
  • false -- Force standard (in-memory) conversion.

Streaming processes spectra in chunks and writes incrementally to disk. The output is identical to standard mode.

Examples

# Force streaming for a large dataset
thyra large.d output.zarr --streaming true

# Use CSR format (faster row access, slower column access)
thyra input.imzML output.zarr --sparse-format csr

CSC vs CSR

CSC (default) is optimised for extracting ion images (one m/z across all pixels). CSR is optimised for extracting spectra (one pixel across all m/z values). Choose based on your downstream access pattern.

--optimize-chunks is deprecated

The flag is still accepted, so existing scripts keep running, but it does nothing and now logs a warning. It will be dropped in a future release.

It never did anything: the post-hoc pass it invoked was written for a dense 4-D image layout and could not read the sparse table the converter actually writes, so it failed on every conversion and the CLI still exited 0. Chunk sizes are chosen at write time instead.


imzML-Specific

Option Default Description
--spectrum-type TYPE auto auto, profile, or centroid -- declare the spectrum representation instead of detecting it

By default Thyra reads the representation the file declares (MS:1000127 centroid / MS:1000128 profile), wherever in the document it is written, and only guesses when the file declares neither. --spectrum-type overrides all of that.

SCiLS Lab exposes the same control as --rep_type PROFILE|CENTROID (2026b User Guide, p.81).

This changes stored values

The representation is not just a label: it feeds instrument detection, which picks the mass-axis type, which decides the bin spacing. Overriding it changes the axis a dataset is resampled onto, and therefore the numbers written to the store. It changes nothing for anyone who does not pass it.

Use it when a file declares the wrong thing -- that does happen. When the override contradicts an explicit declaration Thyra logs a warning naming both values; run with -v INFO to see it, and check the result.

Examples

# The file says centroid but it is really profile data
thyra input.imzML output.zarr --spectrum-type profile

# See what detection would have concluded before overriding it
thyra input.imzML output.zarr -v INFO

Bruker-Specific

These options only apply when converting Bruker .d directories.

Option Default Description
--use-recalibrated / --no-recalibrated enabled Use recalibrated m/z state
--interactive-calibration off Display available calibration states
--intensity-threshold FLOAT none Minimum intensity filter

Examples

# Use raw (non-recalibrated) m/z values
thyra data.d output.zarr --no-recalibrated

# Interactively choose calibration state
thyra data.d output.zarr --interactive-calibration

# Filter low-intensity signals (useful for continuous-mode Bruker data)
thyra data.d output.zarr --intensity-threshold 100

Intensity threshold

The --intensity-threshold option drops all peaks below the given value before writing to zarr. This reduces file size but is irreversible. Use with care -- inspect the data with -v DEBUG first to choose an appropriate threshold.


Other

Option Default Description
--dataset-id TEXT msi_dataset Dataset identifier used in element keys
--handle-3d off Process as 3D volume instead of 2D slices
--z-spacing FLOAT in-plane pixel size Distance between consecutive slices, in um. Only used with --handle-3d

Examples

# Custom dataset ID (affects table and image key names)
thyra input.imzML output.zarr --dataset-id hippocampus
# -> table key: hippocampus_z0, TIC key: hippocampus_z0_tic

# Combine z-slices into a single 3D table
thyra volume.imzML output.zarr --handle-3d

# 20 um sections acquired on a 50 um raster
thyra volume.imzML output.zarr --handle-3d --pixel-size 50 --z-spacing 20

Set --z-spacing whenever you know it

--pixel-size is the in-plane raster pitch. It says nothing about how far apart consecutive slices are: that distance is set by the microtome that cut the sections, not by the stage that rastered them, and the two match only by coincidence.

With no --z-spacing, Thyra reuses the in-plane pitch, warns, and records z_spacing_source: "assumed_isotropic" in the store so the guess stays distinguishable from a measurement. The volume's voxel values are unaffected either way — what is wrong is its depth, so a viewer reading it in micrometres renders the stack squashed or stretched along z.

There is no way to detect this from the data. imzML has no term for slice spacing, and 3D MSI acquisitions are frequently non-consecutive sections, so the number has to come from whoever cut them.

It does nothing without --handle-3d

Without 3D handling each slice is written as its own 2D image and there is no z axis to space out. Passing --z-spacing on its own is logged as ignored rather than silently accepted.


Metadata subcommands

Both take either a converted .zarr store or a standalone metadata .json document. Only the metadata block is read, never the intensity data, so both are instant on stores of any size. See Metadata Schema for the schema itself.

thyra validate

thyra validate PATH [OPTIONS]

Validates the uns["msi_metadata"] block (or a JSON document) against the schema: structure, schema version, and ontology terms.

Option Default Description
--merge PATH none JSON file overlaid onto the metadata before validation
--json off Machine-readable report on stdout instead of text

Exit status follows the conversion command's convention: 0 when every document conforms (warnings allowed), 1 otherwise, 2 for usage errors -- so thyra validate can gate a CI pipeline.

thyra validate output.zarr
thyra validate output.zarr --merge sample.json
thyra validate metadata.json --json

thyra export-metaspace

thyra export-metaspace PATH [OPTIONS]

Writes the METASPACE submission metadata JSON for a dataset. Required fields the store cannot know (organism, condition, ...) are emitted empty and reported as warnings on stderr; supply them with --merge or fill them on the submission form.

Option Default Description
--merge PATH none JSON file overlaid onto the metadata before export
--table NAME the only one Table to export when the store has several
-o, --output PATH <input>.metaspace.json Output file; - for stdout
thyra export-metaspace output.zarr --merge sample.json
thyra export-metaspace output.zarr -o -          # print to stdout

The other two commands

Installing Thyra puts three commands on your path, not one.

thyra-example-data

Writes the small synthetic imzML dataset the tutorial uses. No download, no vendor SDK.

thyra-example-data [OUTPUT] [OPTIONS]

OUTPUT -- Path for the .imzML (default: example_data/synthetic_brain.imzML). A non-.imzML suffix is replaced.

Option Default Description
--pixels-x INTEGER 48 Grid width in pixels
--pixels-y INTEGER 36 Grid height in pixels
--pixel-size FLOAT 25.0 Pixel size in micrometers written to the metadata
--mz-bins INTEGER 4000 Number of points on the m/z axis
--seed INTEGER 0 Random seed
--verbose off Verbose output
# The tutorial's dataset: 48 x 36 pixels, 4,000 m/z points, seed 0
thyra-example-data example_data/synthetic_brain.imzML

# A larger phantom on a coarser axis
thyra-example-data big.imzML --pixels-x 200 --pixels-y 150 --mz-bins 2000

--seed is what makes the tutorial reproducible

Generation is deterministic given the seed, so the default --seed 0 produces byte-identical data on every machine -- which is why the tutorial can print exact numbers and expect yours to match. Change the seed and the numbers change with it.

thyra-check-ontology

Validates the CV (controlled vocabulary) terms in an imzML file against Thyra's ontology cache, and reports any it does not recognise.

thyra-check-ontology INPUT [OPTIONS]

INPUT -- An .imzML file, or a directory to check every file in.

Option Default Description
--output PATH none Save results as JSON instead of printing them
--verbose off Verbose output, including the per-file summary
# Check one file
thyra-check-ontology sample.imzML

# Check a whole directory and keep the report
thyra-check-ontology data/ --output ontology_report.json