bioio-imzml
A basic BioIO reader plugin for imzML mass spectrometry imaging (MSI) data, read with pyimzML.
Installation
pip install bioio-imzml
Requires a sibling .imzML + .ibd file pair (the standard imzML layout).
Usage
from bioio import BioImage
img = BioImage("sample.imzML")
img.dims.order # "TCZYX" -- C is the m/z axis
img.channel_names # "<m/z>±<tolerance>" strings, e.g. "798.5400±0.0000"
img.data # (T, C, Z, Y, X) numpy array
imzML-specific options (mz, mz_step, n_bins, mz_tolerance_absolute,
mz_tolerance_relative, mz_agg) work the same way through BioImage,
since it forwards unrecognized keyword arguments straight to the reader.
Pass reader=bioio_imzml.Reader to skip plugin auto-detection (useful when
more than one installed plugin could claim the file):
import bioio_imzml
from bioio import BioImage
# "processed" mode files (one m/z axis per pixel) need target channels:
img = BioImage("sample.imzML", reader=bioio_imzml.Reader, mz=[798.54, 826.57, 885.55])
# reject a target with no real peak nearby instead of returning whatever
# peak happens to be closest, however far away. mz_tolerance_absolute and
# mz_tolerance_relative are both in the same units as mz (m/z) -- relative
# is a plain fraction, not a ppm count, so convert yourself (3 ppm = 3e-6).
# They combine per channel as: tolerance = absolute + m/z * relative
img = BioImage(
"sample.imzML",
reader=bioio_imzml.Reader,
mz=[798.54, 826.57],
mz_tolerance_absolute=0.005,
mz_tolerance_relative=3e-6, # 3 ppm
)
img.reader.mz_tolerance # the resulting per-channel tolerance, e.g. [0.0074, 0.0075]
img.channel_names # ["798.5400±0.0074", "826.5700±0.0075"]
# leave both unset and "processed" mode files get a tolerance for free:
# half the distance to each target's nearest neighboring target, so windows
# never overlap (a lone target with no neighbor is left unbounded).
img = BioImage("sample.imzML", reader=bioio_imzml.Reader, mz=[798.54, 826.57, 885.55])
img.reader.mz_tolerance # e.g. [14.015, 14.015, 29.49] (half the gaps above/below)
# or let the reader pick evenly spaced channels across the file's m/z range,
# either a fixed count (n_bins) or a fixed step (mz_step) in m/z units:
img = BioImage("sample.imzML", reader=bioio_imzml.Reader, n_bins=512)
img = BioImage("sample.imzML", reader=bioio_imzml.Reader, mz_step=0.1)
# mz_agg controls how peaks within a channel's tolerance window combine.
# Default is "sum" -- every measured peak in the window is added up, matching
# how tools like Lipostar/MetaboScape aggregate signal in a window. Pass
# "nearest" instead to take only the single closest measured peak per
# channel (dropping the rest):
img = BioImage(
"sample.imzML", reader=bioio_imzml.Reader, mz=[798.54, 826.57], mz_agg="nearest"
)
Auto peak-picking
Don't know which m/z channels a file actually has signal at? auto_pick_peaks
finds candidate peaks on the file's mean spectrum, then drops candidates that
are too rare across pixels or spatially unstructured (noise/matrix artifacts
rather than real signal):
import bioio_imzml
from bioio import BioImage
# pin a tolerance and reuse it for picking and extraction, so extraction
# matches what pixel_frequency/spatial_chaos actually scored. Size it to
# bin_width, not to ppm mass-accuracy precision: candidates come from a
# bin_width-binned mean spectrum, so a candidate's reported m/z can be off
# from the true peak by up to ~bin_width/2.
bin_width = 0.05
tol_abs = bin_width
result = bioio_imzml.auto_pick_peaks(
"sample.imzML",
min_mz=650,
max_mz=850,
bin_width=bin_width,
mz_tolerance_absolute=tol_abs,
)
result.mzs # candidate m/z values, sorted by descending intensity
result.pixel_frequency # fraction of pixels with signal, one per mz
result.spatial_chaos # 0 (structured) .. 1 (spatially random), one per mz
if len(result.mzs) == 0:
# min_pixel_frequency/max_spatial_chaos defaults can reject every
# candidate on data with sparse per-pixel peak-picking (e.g.
# single-cell-resolution processed-mode files) -- loosen or disable a
# filter rather than pass an empty mz list on to Reader/BioImage:
result = bioio_imzml.auto_pick_peaks(
"sample.imzML",
min_mz=650,
max_mz=850,
bin_width=bin_width,
mz_tolerance_absolute=tol_abs,
max_spatial_chaos=None,
)
img = BioImage(
"sample.imzML",
reader=bioio_imzml.Reader,
mz=result.mzs,
mz_tolerance_absolute=tol_abs,
)
Tune detection sensitivity (snr_threshold, min_relative_intensity) and the
quality filters (min_pixel_frequency, max_spatial_chaos) as keyword
arguments; see the docstring for defaults. The minimum gap between detected
candidates reuses mz_tolerance_absolute/mz_tolerance_relative (the same
matching window used for extraction), so on high-resolution data it tracks
instrument resolution (and grows with m/z) instead of a fixed Da value -- a
fixed gap either merges genuinely distinct high-m/z peaks or over-splits one
peak into several. For a separation independent of the matching tolerance, call
find_peaks_in_spectrum directly (its min_separation_mz/
min_separation_relative args).
snr_threshold, min_pixel_frequency, and max_spatial_chaos each accept
None to disable that filter -- passing None for both quality filters
also skips the per-pixel pass over the file entirely (the slow part),
leaving result.pixel_frequency/result.spatial_chaos as NaN.
bioio_imzml.peak_picking also exposes the individual steps --
mean_spectrum, find_peaks_in_spectrum, and
pixel_frequency_and_spatial_chaos -- to inspect intermediate results or why
a candidate was dropped before committing to thresholds.
auto_pick_peaks parameters
| Parameter | Default | Description |
|---|---|---|
image |
(required) | Path to the imzML file. |
min_mz |
None |
Lower bound of the m/z range to scan (whole range if None). |
max_mz |
None |
Upper bound of the m/z range to scan (whole range if None). |
bin_width |
0.05 |
Bin width (m/z) of the mean spectrum candidates are detected on. |
smooth |
True |
Apply Savitzky-Golay smoothing before detection (detection only; not applied to the returned raw spectrum). |
savgol_window |
7 |
Savitzky-Golay window length; widen to suppress jagged/spurious candidates. |
savgol_polyorder |
2 |
Savitzky-Golay polynomial order. |
snr_threshold |
None |
Minimum signal-to-noise ratio; None disables the SNR filter. |
min_relative_intensity |
0.0 |
Minimum intensity relative to the tallest peak. |
min_pixel_frequency |
0.01 |
Minimum fraction of pixels with signal; None disables it. |
max_spatial_chaos |
0.4 |
Maximum spatial chaos (0 structured .. 1 random); None disables it. Both quality filters None skips the slow per-pixel pass. |
top_n_peaks |
None |
Cap on channels returned after filtering (all if None). |
mz_tolerance_absolute |
None |
Absolute tolerance (m/z). Sets both the per-pixel frequency/chaos scoring window and the minimum gap between detected candidates. |
mz_tolerance_relative |
None |
Relative tolerance (fraction) for the same, combining as absolute + m/z * relative; makes the gap scale with m/z. Both None = no separation enforced during detection. |
fs_kwargs |
{} |
Extra kwargs forwarded to the underlying file reader. |
PeakPickingResult attributes
| Attribute | Description |
|---|---|
mzs |
Candidate m/z values, sorted by descending mean-spectrum intensity. |
pixel_frequency |
Fraction of pixels with signal, one per mzs (NaN if both quality filters disabled). |
spatial_chaos |
Spatial chaos 0 (structured) .. 1 (random), one per mzs (NaN if both quality filters disabled). |
mean_spectrum_mz |
m/z axis of the full (raw) mean spectrum candidates were detected from. |
mean_spectrum_intensity |
Raw intensities of that mean spectrum. |
Continuous vs. processed mode
imzML stores spectra in one of two ways:
- continuous: every pixel shares one m/z axis, so intensities already line up across pixels. Detected automatically (identical m/z byte offset and length for every spectrum) and read directly -- no resampling, no channel arguments needed.
- processed: each pixel has its own m/z axis (typical for high-resolution
profile data). There's no single true channel set, so this reader resamples
every spectrum onto shared target m/z values, given via
mz=or auto-generated withn_bins=, summing peaks within each channel's tolerance window by default (mz_agg="sum";mz_agg="nearest"takes the single closest peak instead).
reader.is_continuous reports which case applies to a given file.
Development
uv sync
uv run pytest
uv run ruff check .
uv run ruff format .
uv run ty check
Bump the version (updates pyproject.toml) and tag a release to publish to
PyPI via CI:
uv version --bump patch # or minor / major
git commit -am "Bump version"
git tag "v$(uv version --short)"
git push --tags
License
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file bioio_imzml-0.5.0.tar.gz.
File metadata
- Download URL: bioio_imzml-0.5.0.tar.gz
- Upload date:
- Size: 121.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a0caa33cd3fe3f793eabfe61ad3c2783a1308054b6d3c88ad2882cbb499873ab
|
|
| MD5 |
a1118c113e4de8fc4977587e8e4854ee
|
|
| BLAKE2b-256 |
69231ec8c146301d04a9c867c0a95f03d7977a0e5ca0b6c56767933c3413b000
|
Provenance
The following attestation bundles were made for bioio_imzml-0.5.0.tar.gz:
Publisher:
ci.yml on DBP008/bioio-imzml
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bioio_imzml-0.5.0.tar.gz -
Subject digest:
a0caa33cd3fe3f793eabfe61ad3c2783a1308054b6d3c88ad2882cbb499873ab - Sigstore transparency entry: 2583341739
- Sigstore integration time:
-
Permalink:
DBP008/bioio-imzml@5e087a9bc638014f243fde987ccfb18b55676632 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/DBP008
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@5e087a9bc638014f243fde987ccfb18b55676632 -
Trigger Event:
push
-
Statement type:
File details
Details for the file bioio_imzml-0.5.0-py3-none-any.whl.
File metadata
- Download URL: bioio_imzml-0.5.0-py3-none-any.whl
- Upload date:
- Size: 26.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a26c530475979f6da366a133d847c4c37959de0a0c847f4ce43f050eee21e9c3
|
|
| MD5 |
32f9e7c152aac74b41999edf17f75557
|
|
| BLAKE2b-256 |
47e2c7fea4f20de71d349e2f15ace5dce3892a100025f46b3b85bf6c5e67c5b0
|
Provenance
The following attestation bundles were made for bioio_imzml-0.5.0-py3-none-any.whl:
Publisher:
ci.yml on DBP008/bioio-imzml
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bioio_imzml-0.5.0-py3-none-any.whl -
Subject digest:
a26c530475979f6da366a133d847c4c37959de0a0c847f4ce43f050eee21e9c3 - Sigstore transparency entry: 2583341788
- Sigstore integration time:
-
Permalink:
DBP008/bioio-imzml@5e087a9bc638014f243fde987ccfb18b55676632 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/DBP008
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@5e087a9bc638014f243fde987ccfb18b55676632 -
Trigger Event:
push
-
Statement type: