Skip to main content

tomio

I/O utilities for medical images: image volumes (thin wrapper over SimpleITK), interpolation, label files (ITK-SNAP, FreeSurfer, 3D Slicer) and config files (JSON, YAML, TOML).

Installation

pip install tomio
pip install tomio[interp]   # optional: scipy interpolation backend
pip install tomio[nibabel]  # optional: conversion to/from nibabel images

Requires Python >= 3.10. Reading TOML files on Python 3.10 requires tomli.

Conventions

  • Arrays are indexed (x, y, z, ...), in ITK index order (not the (z, y, x) order of sitk.GetArrayFromImage).
  • World coordinates are LPS (ITK, DICOM). Conversion to nibabel (RAS) is done by to_nibabel/from_nibabel.
  • vol.transform is a tuple of axis directions: transform[i] is the world direction of array axis i, i.e. column i of the ITK direction matrix.
  • Orientation codes use the ITK "from" convention by default (identity: RAI); the "to" convention (identity: LPS) is available with convention="to".

Volumes

import numpy as np
from tomio import volume

# read / write (formats: .nii, .nii.gz, .mha, .mhd, .nrrd...)
vol = volume.read("vol.nii.gz")
volume.write("vol2.mha", vol)

# options
vol = volume.read("vol.nii.gz", dtype=np.float32)  # cast
vol = volume.read("complex.mha", as_complex=True)  # complex volume (written by volume.write)
volume.write("vol2.nii.gz", vol, compression_level=9)
header = volume.read_header("vol.nii.gz")  # shape, spacing, origin, transform, metadata (no pixel data)

# Volume is a numpy ndarray
isinstance(vol, np.ndarray)  # True
vol.A  # plain np.ndarray

# header
vol.spacing  # (sx, sy, sz)
vol.origin  # world coordinates of voxel (0, 0, 0)
vol.transform  # axis directions
vol.metadata  # dict[str, str], written to the file
vol.header  # dict of spacing, origin, transform and metadata
vol.affine  # 4x4 affine transform (indices -> LPS coordinates)

# world coordinates <-> indices
coords = vol.get_coords([1, 2, 3])
indices = vol.get_indices(coords)

# create volumes
vol2 = volume.Volume(np.zeros((10, 20, 30)), spacing=(1, 1, 2), origin=(0, 0, 0))
vol2 = volume.asvolume(array, ref=vol)  # copy the header of `vol`
vol2 = volume.tovolume(values, mask=mask, ref=vol)  # fill the voxels of a mask

Volumes with more than 3 dimensions (e.g. time series (x, y, z, t)) and complex volumes can be read and written; the geometry applies to the first 3 axes.

Geometry

geom = vol.geometry  # volume.Geometry: shape, spacing, origin, transform (immutable)
geom.affine, geom.extent, geom.center, geom.voxel_volume
geom.same_as(other_vol, tol=1e-4)
vol2 = volume.Volume(array, geometry=geom)

Slicing and numpy operations

The geometry follows numpy operations when it makes sense:

vol[2:].origin  # world coordinates of the first voxel of the slice
vol[::2].spacing  # spacing x 2 in the first axis
vol[::-1]  # axis direction flipped (also np.flip)
vol.T, np.moveaxis(vol, 0, -1)  # spacing and directions permuted
vol + 1, np.sqrt(vol)  # same geometry

# no geometry: plain np.ndarray
vol[0], vol[mask], vol.sum(axis=0), vol.mean()
# time series: geometry kept
vol4d[..., 0], vol4d.mean(axis=3)

Orientation

vol.anatomical_orientation  # e.g. "RAI" (ITK "from" convention)
vol.get_orientation(convention="to")  # e.g. "LPS"
vol2 = vol.reorient("RAS", convention="to")  # flip/permute the axes

Interoperability

image = vol.to_sitk()  # SimpleITK Image
vol = volume.Volume.from_sitk(image)
nifti = vol.to_nibabel()  # nibabel Nifti1Image (requires nibabel)
vol = volume.Volume.from_nibabel(nifti)

Interpolation

import numpy as np
from tomio import volume

vol2 = volume.resample(vol, like=ref)  # geometry of another volume (or a Geometry)
vol2 = volume.resample(vol, spacing=(1, 1, 1))  # new spacing, same extent
vol2 = volume.resample(vol, geometry={"spacing": (1, 1, 1), "shape": (64, 64, 64)})
vol2 = volume.resample(vol, like=ref, method="linear", fill=np.nan)  # value outside `vol`

# label maps and masks
labels2 = volume.resample(labelmap, like=ref, method="labels")  # label by label (smooth boundaries)
roi2 = volume.resample(roi, like=ref, method="roi")  # no label lost when downsampling
  • Methods: nearest, linear, spline3 (and splineN), labels, roi. Default: nearest for integer and bool data (label maps), spline3 otherwise. The output has the dtype of the input.
  • Backends: SimpleITK (default, multithreaded) or scipy (backend="scipy", requires tomio[interp]). SimpleITK considers voxels inside the source up to half a voxel beyond the border voxel centers.
  • Lower-level functions: interp.interpolate, interpolate_like, interpolate_to, interpolate_roi, interpolate_labels.

Label files

from tomio import labelfile

labels = labelfile.read("labels.txt")  # ITK-SNAP label description file
labels = labelfile.read("FreeSurferColorLUT.txt", format="freesurfer")
labels = labelfile.read("labels.ctbl", format="slicer")  # 3D Slicer color table
labelfile.write("labels.txt", labels)  # or labels.save("labels.txt"), ITK-SNAP format

# Labels: mapping {index: description}, sorted by index
labels = labelfile.Labels({1: "white matter", 2: "grey matter"})  # automatic colors
labels = labelfile.Labels({1: {"LABEL": "white matter", "RGBA": (255, 255, 255, 1.0)}})
labels = labelfile.Labels(["background", "white matter"])  # indices 0, 1

labels[1]  # description
labels[3] = "csf"  # add or rename (keeps the color)
del labels[3]
labels.getindex("grey matter")  # index of a description
labels.indices, labels.descriptions  # lists, sorted by index (can be assigned)
labels.colors  # {index: (R, G, B, A)}, RGB in 0..255, alpha in 0..1 (can be assigned)

# label maps
labels = labelfile.Labels.from_volume(labelmap)  # one label per value
rgba = labels.lut[labelmap]  # RGBA image (uint8)
labels2, mapping = labels.reindex()  # indices 1..N
labelmap2 = labelfile.apply_mapping(labelmap, mapping)

Labels are validated: non-negative integer indices, unique descriptions without " or line breaks (allow_duplicates=True to allow duplicates), RGB in 0..255, alpha in 0..1. Label files are UTF-8.

Config files

from tomio import configfile

cfg = configfile.read("config.yml")  # .json, .yaml, .yml, .toml -> dict
configfile.write("config.yml", cfg)  # .json, .yaml, .yml
  • The format is set by the file extension (no extension: .json). TOML files are read-only.
  • Values are written as standard types: numpy arrays as lists, numpy scalars as numbers, complex numbers as strings "3 + 4i" (read back as complex numbers).
  • YAML files are loaded safely (no Python-specific tags).

Command line

tomio convert vol.mha vol.nii.gz                        # convert (format from the extensions)
tomio convert vol.mha vol.nii.gz --dtype float32 --compression-level 9
tomio resample vol.nii.gz out.nii.gz --spacing 1 1 1    # new spacing
tomio resample labels.nii.gz out.nii.gz --like ref.nii.gz --method labels
tomio info vol.nii.gz --metadata                        # header: shape, pixel type, geometry

Existing output files are not overwritten unless --force is given. See tomio COMMAND --help.

Metadata

Release files for tomio 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tomio 0.1.0
File Size Uploaded Provenance Actions
tomio-0.1.0.tar.gz 46.1 kB With provenance Details for tomio-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for tomio 0.1.0
File Interpreter ABI Platform Actions
tomio-0.1.0-py3-none-any.whl Python 3 none any Details for tomio-0.1.0-py3-none-any.whl

Total release size: 76.0 kB

Release files / tomio-0.1.0.tar.gz

Download URL tomio-0.1.0.tar.gz
Size 46.1 kB
Tags Source
SHA-256 checksum
How to use checksums
58a055ef6bf44a13a84c8a8b6a7517d71c460a27712a969fa504a9147d2b46a3
BLAKE2b-256 checksum
How to use checksums
77c8f8de6522650f3d31b8f7efe7a13a990698a8be2e850ebe537c2c87f4b2c4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Release files / tomio-0.1.0-py3-none-any.whl

Download URL tomio-0.1.0-py3-none-any.whl
Size 29.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
861f13d9dc5df00d40d3f6dc52f2b6163156cc03dd574f0b1f190c03db9a3993
BLAKE2b-256 checksum
How to use checksums
541ac102cc7a789b789c7506f1dbc030e7e01878afd9017591b4dc2f4653bac9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Security for tomio 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for tomio-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page