MR data tends to arrive as a bare array plus a pile of numbers you have to keep in your head:
which axis is time, how wide the sweep was, what zero means. xmris keeps all of that on the
data itself. Your FID stays a plain xarray DataArray — axes named, time
in seconds, metadata riding along — and the physics is one accessor away.
spectrum = fid.xmr.to_spectrum().xmr.autophase().xmr.to_ppm()
There is no custom class to learn. Every xarray habit you have keeps working, a whole grid of
voxels goes through the same call as a single one, and the spectrum that comes out still knows its
ppm axis.
Start with the documentation
→ andrewendlinger.github.io/xmris
That is where the package really lives. Every tutorial page is a live notebook: the plots and
numbers you see come from the code right above them, re-run on every pull request. New here?
Basics walks the FID → spectrum → ppm round trip
from scratch; Concepts explains why xmris is
fussy about names and metadata.
Quick start
The shortest path to something you can look at: simulate_fid hands you a signal that already
carries the metadata the physics needs.
import xmris # importing registers the .xmr accessor on every xarray object
fid = xmris.simulate_fid(
amplitudes=[1.0, 0.4],
chemical_shifts=[0.0, 5.2], # ppm
reference_frequency=120.66, # MHz, the Larmor frequency of your nucleus
n_points=1024,
)
spectrum = (
fid
.xmr.apodize_exp(lb=5.0)
.xmr.zero_fill(target_points=2048)
.xmr.to_spectrum()
.xmr.autophase()
.xmr.to_ppm()
)
print(spectrum.dims) # ('chemical_shift',)
print(round(spectrum.attrs["phase_p0"], 2)) # 2.17 — autophase wrote down what it applied
Got your own data? Then you build the DataArray yourself. Four steps, no magic:
import numpy as np
import xarray as xr
import xmris
# Step 1 — the time axis. Space it by your dwell time (here: a 4000 Hz sweep,
# so 1/4000 s per point). This axis alone sets the frequency axis later on —
# there is no separate sweep-width setting to keep in sync.
time = np.arange(1024) / 4000.0 # seconds
# Step 2 — your samples. Any complex array works; here, one fake peak
# 250 Hz off centre, decaying. Stack three copies to play three voxels.
signal = np.exp(2j * np.pi * 250.0 * time - time / 0.05)
data = np.stack([signal, 0.5 * signal, 0.25 * signal]) # (voxel, time)
# Step 3 — wrap it up. Name the dims, attach the time axis, and add the
# two facts only you can know:
fid = xr.DataArray(
data,
dims=["voxel", "time"],
coords={"time": time},
attrs={
"reference_frequency": 120.66, # MHz — your Larmor frequency
"carrier_ppm": 0.0, # which ppm sits at 0 Hz (1H water: 4.7)
},
)
# Step 4 — done. The whole toolbox now works, all voxels at once:
spectrum = fid.xmr.to_spectrum()
print(spectrum.coords["frequency"].values[[0, -1]].tolist()) # [-2000.0, 1996.09375]
ppm = spectrum.xmr.to_ppm()
print(ppm.dims) # ('voxel', 'chemical_shift')
The 4000 Hz you put into the time axis is the 4000 Hz you get back. Forget
reference_frequency or carrier_ppm and to_ppm tells you, by name, before it does any maths —
Hz and ppm takes it from here.
What is in the box
- Processing — zero filling, exponential and Lorentz-to-Gauss apodization, manual and automatic phasing, asymmetric-least-squares baseline correction, FID ↔ spectrum, Hz ↔ ppm.
- Vendor data — Bruker ParaVision arrays and their parameter dicts become a fully labelled FID, digital-filter group delay included: the one that puts a phase roll through everything if you forget it.
- Fitting — AMARES quantification via pyAMARES, returning
a
Datasetwith your signal, the fit and the residual aligned. - Plots and widgets — matplotlib helpers, plus sliders you can drag to phase, apodize, or scroll through a stack of spectra.
And what is not: xmris is a 0.x package, the MRS side is ahead of the imaging side, Bruker is
the only vendor loader so far, and full MRSI grids — lazy, chunked, sitting on an anatomical
image — are still to come. Core xmris will not do image reconstruction. The
roadmap says what is shipped, what is moving,
and what is still being argued about.
Install
pip install xmris # or: uv add xmris
pip install "xmris[fitting]" # adds AMARES quantification
Fitting is an extra because deep in its dependencies sits hlsvdpro, which ships no arm64 wheel;
the pyamares-xmris repackage on PyPI adds the marker that skips it on Apple Silicon, so the
install works there too. All else is in the bare install. Python 3.10 – 3.13.
Contributing
Issues and pull requests are welcome. uv sync --all-extras --dev then uv run test gets you a
working checkout; the setup steps, the architecture contract and one page per kind of change are in
the contributor guide.
Changelog
Upgrading? The changelog records what
changed in each release. There is no CHANGELOG.md here — it is a rendered page, so every entry can
link the issue, the pull request, and the docs behind it.
License
xmris is BSD 3-Clause — see
LICENSE. Use it, build on it, ship
it, paid work or not; just keep the notice.
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 xmris-0.7.0.tar.gz.
File metadata
- Download URL: xmris-0.7.0.tar.gz
- Upload date:
- Size: 109.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f62dd5ce3beef4c4ef09488975ee88ae1cf4cb7a34544da36f745b4c73fcc239
|
|
| MD5 |
7b19b493990b2decfc8b63bc4ffef3ec
|
|
| BLAKE2b-256 |
a5b3016f27e7c7ceb20302e1e7a5bcc662af5267533cb41e177d43cd556a80d4
|
File details
Details for the file xmris-0.7.0-py3-none-any.whl.
File metadata
- Download URL: xmris-0.7.0-py3-none-any.whl
- Upload date:
- Size: 134.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
32185f99a12269df24147b8e998508521ab6d7a4c7c52abffc27a6c25f092fba
|
|
| MD5 |
22f81c0218dc36604c11b7f106522ca1
|
|
| BLAKE2b-256 |
c5e666abb9f962c06b4eff4a40e9c0bddd459ddd7c499bf477def6e9128c4940
|