Skip to main content

Crate imodfile

Crate imodfile 

Source
Expand description

§imodfile

Decode, encode, and inspect IMOD model files — from Rust and Python. Read and write .mod files used by the IMOD electron microscopy toolkit, in both binary and ASCII formats.

Crates.io Documentation MIT licensed CI


§Install

§Rust crate

cargo add imodfile

§Python package

pip install git+https://github.com/elemeng/imodfile.git

# Or build from source:
pip install maturin
maturin build --features python
pip install target/wheels/imodfile-*.whl

§CLI tool

cargo install imodfile

§Quick start (Rust)

use imodfile::Imod;

let model = Imod::load("cells.mod").unwrap();
println!("{} objects, {} views", model.obj.len(), model.view.len());

// Iterate over every point with indices
for (oi, ci, pi, pt) in model.points() {
    println!("[obj {oi}][cont {ci}][pt {pi}]  {} {} {}", pt.x, pt.y, pt.z);
}

// Dump all points as text
model.save_points("points.txt").unwrap();

// Save back as binary or ASCII (chosen by extension)
model.save("output.mod").unwrap();
model.save("output.txt").unwrap();

§Quick start (Python)

import imodfile
import numpy as np

model = imodfile.load("cells.mod")
print(model.name, model.image_size)

for obj in model.objects:
    for cont in obj.contours:
        pts = cont.points                 # (N, 3) float32 array
        xs, ys, zs = pts[:, 0], pts[:, 1], pts[:, 2]

# Create new objects and contours
obj = model.add_object()
obj.name = "mitochondria"
obj.color = (1.0, 0.0, 0.0)

cont = obj.add_contour()
cont.points = np.array([[0,0,0],[1,0,0],[0,1,0]], dtype=np.float32)

model.save("output.mod")
model.save("output.txt")          # ASCII format
model.save_points("points.txt")   # point dump

§Testing

# Full test suite (Rust + Python)
bash tests/test.sh

# Rust tests only
cargo test

# Python tests only (requires built wheel)
python -m pytest tests/test_python.py -v

# Property-based tests (randomized model generation)
cargo test --test proptests

# Fuzz the binary parser (runs indefinitely)
cargo fuzz run fuzz_binary

The test suite covers:

SuiteTests
Rust integration13 tests — binary/ASCII round-trip, labels, point sizes, clip planes, views, edge cases, real-file round-trip
Property-based2 tests — randomized model generation verifies write→read consistency and field invariants
Doc-tests9 tests — API documentation examples that compile and run
Raw byte verificationBinary writer magic, tags, field layout, IEOF marker
Python bindings15 tests — load, read, create, modify, save, error handling, round-trip
Fuzz testingcargo-fuzz target for the binary parser (crash-resistant input handling)

The CI pipeline (GitHub Actions) runs all Rust tests, clippy (zero-warnings enforced), Python bindings build + pytest, and documentation build on every push and pull request.

§Data model

Imod  (top-level model)
 ├── name, flags, pixsize, units
 ├── obj: Vec<Iobj>
 │    ├── Iobj  (object)
 │    │   ├── name, color, flags, drawmode
 │    │   ├── cont: Vec<Icont>
 │    │   │   └── Icont  (contour)
 │    │   │       ├── pts: Vec<Ipoint>  ← 3-D coordinates
 │    │   │       ├── sizes, flags, time, surf
 │    │   │       └── label, store
 │    │   ├── mesh: Vec<Imesh>
 │    │   │   └── Imesh  (mesh)
 │    │   │       ├── vert: Vec<Ipoint>
 │    │   │       ├── list: Vec<i32>  (indices + sentinels)
 │    │   │       └── flag, time, surf
 │    │   ├── clips: IclipPlanes
 │    │   ├── label, mesh_param
 │    │   └── store: Istore
 │    └── ...
 ├── view: Vec<Iview>     (camera positions)
 ├── slicer_angles: Vec<SlicerAngles>
 ├── ref_image: Option<IrefImage>
 └── store: Istore

Ipoint { x: f32, y: f32, z: f32 }

§Key types

Most users primarily work with Imod (model), Iobj (object), Icont (contour), and Ipoint (3-D coordinate). All types, flag constants, and reader/writer functions are re-exported at the crate root for convenience, and also available under their respective modules for qualified access.

TypeDescription
Imod / ModelTop-level model — image dimensions, transforms, views, objects
Iobj / ObjectA named object with colour, material, contours, and meshes
Icont / ContourA contour — open or closed series of Ipoints
Imesh / MeshTriangle/quad mesh with vertex and index lists
IpointSingle 3-D coordinate { x, y, z }

For secondary types (Iview, IclipPlanes, Ilabel, Istore, ImeshParams, IrefImage, SlicerAngles, flag constants, and the low-level read_binary / write_binary / read_ascii / write_ascii functions), import from imodfile::model or imodfile::binary / imodfile::ascii as needed.

§Rust API

Use caseAPI
Load a fileImod::load(path) — auto-detects binary vs ASCII
Save a filemodel.save(path) — binary, or ASCII if path ends with .txt
Iterate pointsmodel.points()(obj, cont, pt, &Ipoint)
Format as textmodel.to_points()String
Write to writermodel.write_points(&mut writer)
Low-level readread_binary(&mut reader) / read_ascii(&mut reader)
Low-level writewrite_binary(&mut writer, &model) / write_ascii(...)

§Python API

PythonWhat it does
imodfile.load(path)ModelLoad a file (auto-detect format)
model.save(path)Save (binary, or ASCII if .txt)
model.objectslist[Object]All objects
obj.contourslist[Contour]All contours in an object
cont.pointsndarray(N, 3)Point coordinates (read/write)
cont.surface, cont.time, cont.flagsContour metadata (read/write)
obj.add_contour()ContourCreate a new contour
model.add_object()ObjectCreate a new object

The .pyi stub is bundled in the wheel for IDE autocomplete.

§CLI

imodfile <input.mod>                     # dump model info
imodfile <input.mod> <output.mod>        # copy / convert
imodfile <input.mod> output.txt          # convert to ASCII
imodfile <input.mod> output.txt --points # extract point coordinates
imodfile <input.mod> --points            # print points to stdout

§Format support

FormatReadWrite
Binary (big-endian)
ASCII text
Legacy V0.1

All chunk types are supported: objects, contours, meshes, materials, clip planes, labels, point sizes, views, slicer angles, reference transforms, meshing parameters, and general-purpose storage.

The binary parser is fuzz-tested via cargo-fuzz for crash-resistant handling of arbitrary or corrupted input. Property-based tests with proptest verify write→read round-trip correctness across randomly generated models.

§Read/write flow

                ┌──────────────────┐
                │  imodfile crate  │
                └─────────┬────────┘
                          │
            ┌─────────────┴─────────────┐
            ▼                           ▼
    ┌───────────────┐           ┌───────────────┐
    │  Imod::load() │           │  Imod::save() │
    │    / read()   │           │    / write()  │
    └───────┬───────┘           └───────┬───────┘
            │                           │
    ┌───────┴───────┐           ┌───────┴───────┐
    │  detect       │           │  path ends    │
    │  format       │           │  with .txt?   │
    └───────┬───────┘           └───────┬───────┘
            │                           │
    ┌───────┴───────┐           ┌───────┴───────┐
    ▼               ▼           ▼               ▼
 ┌──────┐    ┌──────────┐  ┌──────────┐      ┌──────┐
 │binary│    │  ASCII   │  │  ASCII   │      │binary│
 │reader│    │  reader  │  │  writer  │      │writer│
 └──────┘    └──────────┘  └──────────┘      └──────┘
      │            │             │               │
      ▼            ▼             ▼               ▼
  .mod file   .txt file      .txt file       .mod file
   (binary)    (ASCII)       (ASCII)          (binary)

§Modules

Crate moduleContents
modelData types — Imod, Iobj, Icont, Imesh, Ipoint, …
binaryBinary format reader and writer
asciiASCII format reader and writer
chunk_ids4-byte magic constants
errorImodError / ImodResult
storeGeneral-purpose storage helpers

§License

MIT — see LICENSE for the full text.

Re-exports§

pub use ascii::read_ascii;
pub use ascii::write_ascii;
pub use binary::read_binary;
pub use binary::write_binary;
pub use error::ImodError;
pub use error::ImodResult;
pub use model::IclipPlanes;
pub use model::Icont;
pub use model::Iindex;
pub use model::Imesh;
pub use model::ImeshParams;
pub use model::Imod;
pub use model::Iobj;
pub use model::IobjPointsIter;
pub use model::ImodPointsIter;
pub use model::Iplane;
pub use model::Ipoint;
pub use model::IrefImage;
pub use model::Istore;
pub use model::IstoreItem;
pub use model::Iview;
pub use model::Ilabel;
pub use model::IlabelItem;
pub use model::SlicerAngles;
pub use model::IMODF_FLIPYZ;
pub use model::IMODF_HAS_MESH_THICK;
pub use model::IMODF_MAT1_IS_BYTES;
pub use model::IMODF_MULTIPLE_CLIP;
pub use model::IMODF_NEW_TO_3DMOD;
pub use model::IMODF_OTRANS_ORIGIN;
pub use model::IMODF_ROT90X;
pub use model::IMODF_TILTOK;
pub use model::IMODF_Z_FROM_MINUSPT5;
pub use model::IMOD_OBJFLAG_ANTI_ALIAS;
pub use model::IMOD_OBJFLAG_DRAW_LABEL;
pub use model::IMOD_OBJFLAG_FCOLOR;
pub use model::IMOD_OBJFLAG_FCOLOR_PNT;
pub use model::IMOD_OBJFLAG_FILL;
pub use model::IMOD_OBJFLAG_MCOLOR;
pub use model::IMOD_OBJFLAG_MESH;
pub use model::IMOD_OBJFLAG_NOLINE;
pub use model::IMOD_OBJFLAG_OFF;
pub use model::IMOD_OBJFLAG_OPEN;
pub use model::IMOD_OBJFLAG_OUT;
pub use model::IMOD_OBJFLAG_PNT_ON_SEC;
pub use model::IMOD_OBJFLAG_SCAT;
pub use model::IMOD_OBJFLAG_SCALE_WDTH;
pub use model::IMOD_OBJFLAG_TIME;
pub use model::IMOD_OBJFLAG_TWO_SIDE;
pub use model::IMOD_OBJFLAG_USE_VALUE;

Modules§

ascii
ASCII IMOD format reader and writer.
binary
chunk_ids
Four-byte chunk IDs used in the IMOD binary format — all UPPERCASE.
error
model
Data model types mirroring the IMOD C structures.
python
Python bindings (requires feature python). PyO3 bindings for the imodfile library.
store
General-purpose storage (Istore).

Functions§

read
Read an IMOD model from a file path, auto-detecting binary vs ASCII.
write
Write an IMOD model to a file path. Uses binary format unless the path ends with .txt or .ascii (then ASCII).