Skip to main content

Python version PyPI version License

medio

Medical image I/O for Python — read and write NIfTI, DICOM, MetaImage, and more in one consistent API.

  • One function reads any format; format auto-detected from path
  • Returns a NumPy array + rich MetaData (affine, orientation, spacing) — no format-specific objects to unwrap
  • Transparent coordinate system normalization between ITK and NiBabel conventions
  • Metadata-only reads (read_meta) for large files when you only need spatial info

Installation

pip install medio

Usage

Read and save any format

import medio

arr, meta = medio.read_img('scan.nii.gz')
print(meta.ornt, meta.spacing)   # e.g. 'LPI', [0.5, 0.5, 1.0]

medio.save_img('out.mhd', arr, meta)

Read metadata only — no pixel data loaded

meta = medio.read_meta('large_scan.nii.gz')
print(meta.spatial_shape)    # (256, 256, 128)
print(meta.affine.spacing)   # [0.98, 0.98, 1.5]

Reorient to a standard orientation

arr, meta = medio.read_img('scan.nii.gz', desired_ornt='RAS')
# arr axes are reordered; meta.affine updated to match

Write a DICOM series from a 3D array

arr, meta = medio.read_img('scan.mhd')
medio.save_dir('dicom_out/', arr, meta)

DICOM series geometry is validated

A DICOM directory is only a valid 3D volume if its slices agree geometrically. Series Instance UID does not guarantee that: scanners emit a localizer/scout under the same Series Instance UID as the acquisition, and reading it as part of the volume silently corrupts the derived slice spacing. read_img and read_meta therefore refuse an inconsistent series instead of returning a wrong image:

medio.read_img('dicom_dir/')
# InconsistentSeriesError: DICOM series mixes slice orientations: 1 of 325 slice(s) are not
# parallel to the first ... typically a localizer/scout slice sharing the Series Instance UID.

# read only the slices that share the dominant geometry (drops the localizer):
arr, meta = medio.read_img('dicom_dir/', keep_dominant_geometry=True)

# opt out entirely and get the previous, unchecked behaviour:
arr, meta = medio.read_img('dicom_dir/', validate_series=False)

The checks are the invariants any single volume must satisfy — one orientation, one in-plane geometry, uniformly spaced slice positions — and they catch missing or duplicated slices as well as localizers. SliceThickness is deliberately not required to equal the slice spacing: gapped and overlapping reconstructions are legitimate.

keep_dominant_geometry filters first and then still validates what remains, so it discards off-geometry slices without hiding a genuine gap in the rest.

Spatial slicing with automatic affine update

from medio.medimg import MedImg

mimg = MedImg(arr, meta)
cropped      = mimg[2:8, 3:7, :]    # origin updated
downsampled  = mimg[::2, ::2, ::1]  # spacing updated

Supported Formats

Format Extensions Default backend
NIfTI .nii, .nii.gz ITK
DICOM directory or .dcm ITK
MetaImage .mhd, .mha ITK
NIfTI (NiBabel) .nii, .nii.gz backend='nib'
DICOM (pydicom) .dcm backend='pdcm'
Other ITK formats .png, .jpg, … ITK

API Reference

read_img

medio.read_img(input_path, desired_ornt=None, backend=None, dtype=None,
               header=False, channels_axis=-1, coord_sys='itk', **kwargs)
→ tuple[np.ndarray, MetaData]
Parameter Type Default Description
input_path path-like — File or DICOM directory
desired_ornt str | None None Reorient to this axis code (e.g. 'RAS')
backend str | None None Force backend: 'itk', 'nib', 'pdcm'
dtype dtype | None None Cast array to this dtype
header bool False Include raw format header in MetaData.header
channels_axis int | None -1 Axis for multi-channel (e.g. RGB) images
coord_sys 'itk' | 'nib' | None 'itk' Coordinate convention for orientation and metadata

**kwargs are passed to the backend. DICOM directories (both backends): series, validate_series, keep_dominant_geometry. ITK-specific: pixel_type, fallback_only. pydicom-specific: globber, allow_default_affine.

DICOM-directory parameter Type Default Description
validate_series bool True Raise InconsistentSeriesError unless the slices form one consistent 3D volume. False restores the previous, unchecked behaviour
keep_dominant_geometry bool False Read only the slices sharing the dominant geometry, discarding e.g. a localizer that shares the Series Instance UID

read_meta

medio.read_meta(input_path, desired_ornt=None, backend=None,
                header=False, coord_sys='itk', **kwargs)
→ MetaData

See read_img for parameters. Reads only spatial metadata without loading pixel data.


save_img

medio.save_img(filename, np_image, metadata, use_original_ornt=True,
               backend=None, dtype=None, channels_axis=None,
               mkdir=False, parents=False, **kwargs)
Parameter Type Default Description
filename path-like — Output file path (format inferred from suffix)
np_image ndarray — Image array
metadata MetaData — Spatial metadata
use_original_ornt bool True Reorient to metadata.orig_ornt before saving
backend str | None None Force backend: 'itk' or 'nib'
dtype dtype | None None Cast before saving
channels_axis int | None None Axis of channel dimension in np_image
mkdir bool False Create the output directory if it doesn't exist
parents bool False Create all missing parent directories

save_dir

medio.save_dir(dirname, np_image, metadata, use_original_ornt=True,
               dtype=None, channels_axis=None, parents=False,
               exist_ok=False, allow_dcm_reorient=False, **kwargs)

Saves a 3D array as a DICOM series of 2D slices.

Parameter Default Description
dirname — Output directory
exist_ok False Allow writing into an existing non-empty directory
allow_dcm_reorient False Reorient to nearest right-handed orientation if needed
pattern 'IM{}.dcm' Filename pattern; {} is replaced with the slice number
metadata_dict None Override or add DICOM tags, e.g. {'0008|0060': 'US'}

MetaData

medio.MetaData(affine, coord_sys='itk', orig_ornt=None, header=None, spatial_shape=None)
Property Type Description
affine Affine 4×4 spatial transform (index space → physical space)
coord_sys str 'itk' or 'nib'
ornt str Current orientation code (e.g. 'LPI'), derived from affine
orig_ornt str Orientation before any reorientation
spacing ndarray Voxel spacing — alias for affine.spacing
header dict | None Raw format header (populated when header=True in read_img)
spatial_shape tuple | None Image dimensions (populated by read_meta)

Methods: .convert(dest_coord_sys) — in-place convention switch; .clone() — deep copy.


Affine

A 4×4 NumPy array subclass with named spatial accessors.

from medio import Affine
import numpy as np

aff = Affine(np.eye(4))
aff = Affine(direction=np.eye(3), spacing=[0.5, 0.5, 1.0], origin=[0., 0., 0.])
coord = aff.index2coord([4, 0, 9])   # map voxel index → physical coordinate

Properties: .spacing, .origin, .direction (all gettable and settable). Method: .clone().

For a mathematical background see NiBabel's affine documentation.


MedImg

Container for an image array + metadata with spatially-aware indexing.

from medio.medimg.medimg import MedImg

mimg = MedImg(arr, meta)                         # from array + metadata
mimg = MedImg.from_file('scan.mhd')   # load from file

Indexing crops or downsamples the array and updates the affine automatically:

Indexing Effect on metadata
mimg[2:8, 3:7, :] origin updated to new start voxel
mimg[::2, ::2, ::1] spacing scaled by step sizes
mimg[..., 5:15] ellipsis supported

Properties: .np_image, .metadata. Method: .save(filename).


Orientation conventions

medio uses ITK convention by default (coord_sys='itk'). Pass coord_sys='nib' to read_img / read_meta to work in NiBabel convention throughout.


License

Apache 2.0 — see LICENSE.

Issues and contributions: github.com/RSIP-Vision/medio/issues

Metadata

Release files for medio 0.7.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 medio 0.7.0
File Size Uploaded
medio-0.7.0.tar.gz 33.2 kB Details

Built distribution (wheel)

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

Total release size: 74.9 kB

Release files / medio-0.7.0.tar.gz

Download URL medio-0.7.0.tar.gz
Size 33.2 kB
Tags Source
SHA-256 checksum
How to use checksums
231ce401007ba8c12d26e4b4648d03053564b7e9c6bfcfe4be573fdc68ed7865
BLAKE2b-256 checksum
How to use checksums
9ebdaebd3ecbccd125a1e3aedd713f4ca7200a85a59e6f52f3f64b3edd7c02c1
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 Aug 17, 2026.

Transparency log

Release files / medio-0.7.0-py3-none-any.whl

Download URL medio-0.7.0-py3-none-any.whl
Size 41.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e0b2149d7f92e4b7b327f770b2a9dd9d06142ed83380772b56efaf929c0b13df
BLAKE2b-256 checksum
How to use checksums
f976fd2e098c54bf024de8a1959ebf136d72b0f701ac562e3aca1a451c475ae9
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 Aug 17, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.7.0 This release

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.3

1 release file

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.0

2 release files

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