nifti-lite
A small NIfTI reader I wrote from scratch, mainly to understand how MRI files are actually stored.
While working on brain tumor segmentation, I kept hitting the same problem: one scan in a dataset with a different shape or voxel spacing would quietly break preprocessing. Loading every full volume just to check its size is slow, so nifti-lite reads only the 348-byte header of each file and checks the whole dataset in seconds.
Install
pip install nifti-lite
Usage
Scan a folder of scans:
nifti-lite scan data/
nifti-lite scan data/ --csv results.csv
file shape spacing (mm) dtype
------------------------------------------------------------------------------
broken.nii.gz ERROR: Not a gzipped file
odd_shape.nii.gz (64, 64, 32) (1.0, 1.0, 1.0) float32
patient_0.nii.gz (64, 64, 40) (1.0, 1.0, 1.0) float32
...
WARNING: 2 different shapes found: [(64, 64, 32), (64, 64, 40)]
Look at one file in detail, including image statistics:
nifti-lite info scan.nii.gz
Or use it from Python:
from nifti_lite import read_header, load_data
hdr = read_header("scan.nii.gz") # header only, fast
data = load_data("scan.nii.gz") # full volume as a numpy array
How it works
A NIfTI-1 file starts with a fixed 348-byte header. nifti-lite unpacks it with Python's struct module: dimensions at byte 40, data type at byte 70, voxel spacing at byte 76, and so on.
The byte order isn't stored as a flag, so it's detected by trick: the first 4 bytes always hold the number 348, and whichever byte order reads them as 348 is the right one.
To load the image, it reads the raw bytes after the header, decodes them with the correct data type and byte order, and reshapes them in column-major order, since NIfTI stores the x axis fastest. Intensity scaling (slope/intercept) is applied if the file uses it.
For .nii.gz files, scanning only decompresses the first few hundred bytes, which is why it's fast even on big datasets.
Tests
pip install pytest
pytest -v
The tests write files and read them back for 5 data types in both .nii and .nii.gz, check that axis order is preserved, and include a hand-built big-endian file.
Limitations
Supports NIfTI-1 only (not NIfTI-2), and doesn't apply the orientation matrix. For full-featured work, use nibabel. This project is about understanding the format and fast dataset checks.
License
MITp
Metadata
Release files for nifti-lite 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| nifti_lite-0.1.0.tar.gz | 4.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| nifti_lite-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 9.6 kB
Release files / nifti_lite-0.1.0.tar.gz
| Download URL | nifti_lite-0.1.0.tar.gz |
|---|---|
| Size | 4.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4778179ec22519b2ee1d080eba83cbb897a8ede6a647ea586c111fc7158576cd
|
|
BLAKE2b-256 checksum How to use checksums |
f7d85e0dfbd847b564b9d9bf7a5339e151ef65a2fdd1993a0f14d63a869fb060
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.9
|
Release files / nifti_lite-0.1.0-py3-none-any.whl
| Download URL | nifti_lite-0.1.0-py3-none-any.whl |
|---|---|
| Size | 5.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
35435df63c9648597ec33771907760de70a697f4a29d026fbfddb89a2e5fad36
|
|
BLAKE2b-256 checksum How to use checksums |
c33323a45ce0f5bb64b43382f5b2e97ce036cc90ac37d3e9e87791413ea060cf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.9
|