Skip to content

CeMOS-Mannheim/shape2instrument

Repository files navigation

Shape2Instrument

Converts segmented shape definitions (multi-label NRRD mask) and point sets (MPS) into physical vector polygons formatted for specific mass spectrometry imaging (MSI) instrument interfaces.

Supported formats:

Format Instrument Use case
xml Leica LMD Laser microdissection
csv MMI (Molecular Machines & Industries) Laser microdissection
mis Bruker flexImaging MALDI imaging

Prerequisites

  • Docker (recommended) — must be installed and running.
  • Python 3.11+ (optional, for local use) — install dependencies via pip install -r requirements.txt.

🏗️ 1. Building the Image

docker build -t shape2instrument:latest .

The image is ~370 MB (slim Debian base, no OpenGL dependencies).


🚀 2. Running the Container

Mount your data directory so the container can read inputs and write results:

docker run --rm -v "${PWD}:/data" shape2instrument:latest [arguments]

Required Arguments

Argument Description
--mask Path to the input multi-label .nrrd image mask
--output Output directory inside the mounted volume
--format Target format: xml, csv, or mis

Conditionally Required Arguments

Argument Required for Description
--mps csv, xml Path to the .mps calibration points file (3-point set)
--mis_template mis Path to a template .mis file (Bruker slide optical mappings)

Optional Arguments

Argument Default Description
--cap_ids auto-generated Comma-separated capture IDs, one per unique label in the mask
--mis_image mask.tif Image filename for flexImaging (mis format only)
--mis_raster 20,20 Raster spacing in µm for flexImaging (mis format only)
--offset_x 0.0 X offset
--offset_y 0.0 Y offset
--scale 1.0 Global scaling factor
--invert_x 1.0 X invert factor (-1.0 to mirror)
--invert_y 1.0 Y invert factor (-1.0 to mirror)

🏷️ Capture IDs

Capture IDs label each segment group in the output. They work identically for both xml and csv formats.

How it works

  • One ID per unique label — the NRRD mask contains labeled regions (e.g., label 2 = tumor, label 3 = stroma). You supply one capture ID per unique label.
  • Auto-expansion — if a single label produces multiple disconnected contours, all of them get the same capture ID.
  • Auto-generation — if --cap_ids is omitted, IDs are generated automatically using the 96-well-plate naming convention: A1, B1, C1, ..., H1, A2, B2, ...

Examples

Unique labels --cap_ids Result
1 (omitted) A1 → all segments
2 (omitted) A1, B1 → one per label
2 TUMOR,STROMA Custom names, one per label
46 (omitted) A1 through H6 (wraps columns)

Output appearance

XML — each <Shape_N> contains a <CapID> element.

CSV — each segment group is labelled with # Group: <cap_id>:

# reference 0
1.1203,1.2922

# reference 1
43.7406,1.3146

# reference 2
43.6189,15.1379

# Group: A1
18.24,5.92
18.28,5.92
18.28,5.98
18.24,5.98

# Group: A1
18.20,5.00
18.24,5.00

📋 Examples

A: Leica XML (with custom capture IDs)

docker run --rm \
  -v "${PWD}:/data" \
  shape2instrument:latest \
  --mask /data/01-labels.nrrd \
  --mps /data/pointset.mps \
  --output /data/results \
  --format xml \
  --cap_ids TUMOR,STROMA

B: Leica XML (auto-generated IDs)

docker run --rm \
  -v "${PWD}:/data" \
  shape2instrument:latest \
  --mask /data/01-labels.nrrd \
  --mps /data/pointset.mps \
  --output /data/results \
  --format xml

C: MMI CSV (with custom capture IDs)

docker run --rm \
  -v "${PWD}:/data" \
  shape2instrument:latest \
  --mask /data/01-labels.nrrd \
  --mps /data/pointset.mps \
  --output /data/results \
  --format csv \
  --cap_ids TUMOR,STROMA

D: MMI CSV (auto-generated IDs)

docker run --rm \
  -v "${PWD}:/data" \
  shape2instrument:latest \
  --mask /data/01-labels.nrrd \
  --mps /data/pointset.mps \
  --output /data/results \
  --format csv

E: Bruker flexImaging MIS

docker run --rm \
  -v "${PWD}:/data" \
  shape2instrument:latest \
  --mask /data/01-labels.nrrd \
  --mis_template "/data/Bruker_Slide_Template.mis" \
  --output /data/results \
  --format mis \
  --mis_image "mask.tif" \
  --mis_raster 20,20

🐍 Local Python Usage

from main import extract_segments_from_nrrd, parse_mps_calibration
from shape2xml_v2 import shape2xml
from shape2csv_v2 import shape2csv

# 1. Extract segments from NRRD
segments, segment_labels, valid_labels = extract_segments_from_nrrd(
    "examples/01_tic_tenzl-labels.nrrd", physical_space=True
)

# 2. Parse calibration points
calib = parse_mps_calibration("examples/PointSet.mps")

# 3. Generate XML (auto-generated well-plate IDs)
shape2xml(segments, calibration_points=calib, folder_name="example_results")

# 4. Generate CSV (custom capture IDs)
shape2csv(segments, calib, capture_ids=["TUMOR", "STROMA"], folder_name="example_results")

📂 Project Structure

File Purpose
main.py CLI entry point, argument parsing, segment extraction
shape2xml_v2.py Leica XML export
shape2csv_v2.py MMI CSV export
mis_maker_class.py Bruker MIS export
utils.py Shared utilities (e.g., well-plate ID generation)
Dockerfile Container definition
examples/ Sample NRRD mask and MPS calibration
example_results/ Generated output files

About

Docker container to convert masks and point sets into xml (Leica) or csv (MMI) to perform LMD

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors