Analyze mitochondrial networks and protein distribution in fluorescence microscopy images. This unified tool provides multiple workflows to process multi-channel TIFF images, identify mitochondrial structures, and quantify protein localization along the mitochondrial network.
- Multiple Analysis Workflows: Five specialized workflows for different analysis needs
- Network Skeletonization: Automatically extracts the mitochondrial network structure from binary images
- Interactive Mask Drawing: GUI-based tool for manually creating mitochondrial masks
- Mask Refinement: Refine mask edges using intensity information for improved accuracy
- Outer Mitochondrial Membrane (OMM) Scanning: Specialized scanning along the outer membrane using surface normals
- Network Line Scanning: Protein intensity profiling along mitochondrial network paths, built on a ridge-filter mask pipeline with an interactive tuning GUI and an optional local-thickness post-skeletonization filter
- Peak Detection & Analysis: Identifies and analyzes peaks in protein distribution
- Configuration-Driven: Use YAML config files for reproducible, batch processing workflows
- Batch Processing: Process multiple TIFF images with consistent parameters
- CSV Export: Saves intensity profiles, visualizations, and analysis results
- Python 3.10 or later
- Conda (Miniconda or Anaconda, or micromamba)
- Multi-channel TIFF image files
- 2-4 channels typical (mitochondria, scan signal, optional mask, etc.)
git clone https://github.com/GrotjahnLab/mito_linescan.git
cd mito_linescanconda env create -f environment.ymlOr with micromamba:
micromamba env create -f environment.ymlThis creates a conda environment named mito_protein_scanner with all required dependencies:
- numpy, scipy, matplotlib, pandas, scikit-image, networkx
- click (for CLI), tifffile (TIFF I/O), sknw (skeleton network building), tqdm (progress bars)
- localthickness (optional local-thickness filter in
network_line_scan)
conda activate mito_protein_scannerThe recommended way to use this tool is through the YAML configuration file, which enables reproducible analysis with all parameters in one place.
Generate a default config.yaml with the bundled create-config command:
mito_protein_localization create-config # writes ./config.yaml
mito_protein_localization create-config --output ./my_config.yaml
mito_protein_localization create-config --force # overwrite an existing filecreate-config copies config.yaml.template byte-for-byte and refuses to
clobber an existing file unless --force is passed. If you prefer to do it
by hand, you can still:
cp config.yaml.template config.yamlEither way, edit config.yaml and configure the workflows you want to use.
Each workflow section contains the parameters for that analysis.
Manually draw masks for mitochondrial structures with interactive GUI.
draw_mask:
input_directory: '/path/to/input/directory'
manual_mask_directory: '/path/to/output/directory'
mito_channel: 0 # Channel index for mitochondria (0-based)
target_channel: 1 # Channel index for target/scan signal
scan_width: 7 # Width of scan lines in pixels
sampling_radius: 3 # Radius for weighted average samplingRefine mask edges using intensity information for improved accuracy.
refine_mask:
input_directory: '/path/to/input/directory'
refined_mask_directory: '/path/to/output/directory'
mask_channel: 0 # Channel index for mask
mito_channel: 1 # Channel index for mitochondria
target_channel: 2 # Channel index for target/scan signalScan protein distribution on the outer mitochondrial membrane using surface normals.
omm_normal_scan:
input_directory: '/path/to/images/'
output_directory: '/path/to/output/'
mito_channel: 1 # Mitochondria channel
scan_channel: 0 # Scan/protein channel
mask_channel: 2 # Mask channel
scan_width: 7 # Width of scan lines
sampling_radius: 3 # Radius for weighted sampling
mito_thickness_threshold: 1 # Initial erosion value (1-20)Scan protein distribution along the mitochondrial network. The binary mask is built by a multi-scale ridge-filter pipeline (white top-hat → Meijering ridge filter → Otsu) and can be tuned either through an interactive GUI or via config/CLI parameters for batch processing. An optional local-thickness filter prunes the skeleton after skeletonization so it does not perturb the network topology.
network_line_scan:
input_dir: '/path/to/input'
input_pattern: 'snap*.tiff' # Pattern to match files
mask_dir_output: '/path/to/masks' # Output mask directory
mask_dir_input: '/path/to/masks/' # Input mask directory
run_name: 'run1' # Run name suffix for outputs
mito_channel: 0 # Mitochondria channel
protein_channel: 2 # Protein channel
use_gui: true # Interactive mask GUI on/off
scan_width: 4 # Pixels on each side of path
path_sampling: 5 # Subpixel samples along normal
min_path_length: 30 # Minimum path length to process
# --- Ridge-filter mask pipeline (also live-tunable in the GUI) ---
tubule_radius: 2.0 # Tubule radius (px); drives
# top-hat disk + ridge sigmas
sensitivity: 1.0 # Multiplier on Otsu cut of ridge
# response (1.0=Otsu, <1=more
# permissive, >1=stricter)
min_object_size: 30 # Drop small CCs (px)
gap_closing: 1 # Binary-closing disk radius (px)
# to bridge 1-2 px breaks
# --- Local-thickness filter (applied AFTER skeletonization) ---
use_thickness_filter: false # Toggle local-thickness filtering
min_thickness: 1.0 # Keep skeleton px with thickness >=
max_thickness: 20.0 # Keep skeleton px with thickness <=
# --- Final binary mask export (reusable downstream) ---
binary_mask_dir_output: '' # If set, save the final (post-
# thickness-filter) mito binary as
# {basename}_mito_binary.tif
# (uint8 0/255). Empty = skip.When use_gui: true, an interactive figure opens with live overlays and
controls:
- Tubule radius (px) — sets the structural scale of the ridge filter (top-hat disk and Meijering sigmas). Recomputation is slow, so it updates only when you press the Recompute ridge button. For ~0.17 µm/px decon data with ~0.3–0.6 µm mito tubules, ~2 px is a good starting point.
- Sensitivity — multiplier on the Otsu cut of the ridge response.
1.0= pure Otsu;<1catches dim tubules;>1is stricter. - Min size (px) — drops binary connected components smaller than this.
- Gap closing (px) — binary-closing disk radius to bridge small breaks before skeletonization.
- Min / Max thickness (px) — together define the allowed local-thickness
range. When
Filter ONis checked, skeleton pixels whose underlying local thickness is outside[min, max]are dropped from the returned skeleton. Crucially, this exclusion is applied afterskeletonize, so the topology of the network is determined by the full binary; thickness only removes pixels from the final skeleton and rebuilds the network graph.
The view toggles (Binary / Skeleton / Nodes / Ridge / Excluded / Filter ON) let you overlay any combination of intermediates, and a stats line below the figure reports binary %, skeleton pixels (filtered), nodes/edges, paths ≥ min_path_length, current threshold, and thickness distribution.
The optional thickness filter uses the
localthickness package, which is
installed as part of environment.yml. If the package is missing for any
reason, the filter is silently disabled (a warning is printed) and the
pipeline falls back to the un-filtered skeleton.
Analyze intensity profiles and detect peaks from OMM scanning results.
analyze_omm_scans:
input_directory: '/path/to/pickle/files/'
output_directory: '/path/to/output/' # Optional, defaults to input
peak_threshold: 0.3 # Peak threshold (0.0-1.0)
peak_prominence: 0.1 # Peak prominence threshold (0.0-1.0)Pool every per-mito CSV produced by network_line_scan, detect peaks on the
Scan_Intensity column (the protein / target channel) with intensity +
prominence thresholds, and write a histogram of the consecutive
peak-to-peak distances. Outputs go into output_directory (defaults to
csv_directory):
peak_distance_histogram.png— pooled histogram with median + mean overlayspeak_distances.csv— one row per consecutive pair:image_name,mito_id,distancepeak_distance_per_track.csv— per-track summary (n_peaks, path_length, mean/median distance)peak_distance_summary.txt— global stats
plot_peak_distance_analysis:
csv_directory: '/path/to/line_scan/output_dir/' # Where the per-mito CSVs live
input_pattern: '*_mito_*.csv' # Glob for the CSV files
output_directory: '' # Default: same as csv_directory
peak_min_intensity: 0.3 # Min Scan_Intensity (0-1)
peak_min_prominence: 0.1 # Min prominence (0-1)
peak_prominence_wlen: 10 # peak_prominences wlen
bin_width: 5.0 # Histogram bin width (px)
max_distance: 0.0 # X-axis cap; 0 = auto (data p99)
recursive: false # Recurse into subdirectoriesDistances are reported in whatever units the CSV's Distance column is in
(pixels, by default).
Execute any workflow using the unified command with the config file:
mito_protein_localization --config config.yaml draw_mask
mito_protein_localization --config config.yaml refine_mask
mito_protein_localization --config config.yaml omm_normal_scan
mito_protein_localization --config config.yaml network_line_scan
mito_protein_localization --config config.yaml analyze_omm_scans
mito_protein_localization --config config.yaml plot_peak_distance_analysisOr run all workflows in sequence:
mito_protein_localization --config config.yaml draw_mask && \
mito_protein_localization --config config.yaml refine_mask && \
mito_protein_localization --config config.yaml omm_normal_scan && \
mito_protein_localization --config config.yaml analyze_omm_scansSet up your config.yaml:
network_line_scan:
input_dir: './my_data/tiff'
input_pattern: '*.tiff'
mask_dir_output: './my_data/masks'
mito_channel: 0
protein_channel: 2
use_gui: true
scan_width: 4Then run:
mito_protein_localization --config config.yaml network_line_scanomm_normal_scan:
input_directory: '/data/2024_experiments/'
output_directory: '/data/2024_experiments/omm_results/'
mito_channel: 0
scan_channel: 1
mask_channel: 2
mito_thickness_threshold: 2Run the analysis:
mito_protein_localization --config config.yaml omm_normal_scanCreate a comprehensive config.yaml with all workflows and run them in sequence:
mito_protein_localization --config config.yaml draw_mask && \
mito_protein_localization --config config.yaml omm_normal_scan && \
mito_protein_localization --config config.yaml analyze_omm_scansFor advanced use cases, you can still call individual scripts directly:
python bin/mito_mask.py --i /path/to/input --o /path/to/output
python bin/mito_mask_refine.py --i /path/to/input --o /path/to/output
python bin/mito_protein_omm_normal_scanner.py --i /path/to/input --o /path/to/output
python bin/mito_protein_line_scanner.py --input-dir /path/to/inputView help for individual scripts:
python bin/mito_protein_line_scanner.py --help
python bin/mito_protein_omm_normal_scanner.py --helpThe config.yaml file uses YAML syntax. Key points:
- Indentation: Use 2 spaces (not tabs)
- Channel indices: 0-based (0, 1, 2, ...)
- Boolean values: Use
trueorfalse(lowercase) - Paths: Use absolute paths or relative paths from where you run the command
- Underscores: Use underscores in parameter names (not hyphens) in config files
- Multiple workflows in one file: You can define all five workflows in a single config.yaml
- Selective execution: Only the workflow you specify on the command line will run
- Template: Always start with
config.yaml.templateas your reference - Paths: Ensure all input directories exist and contain valid TIFF files
- Channel order: Verify your TIFF file channel order before setting indices
Output structure depends on which workflow you run:
{run_name}_output/
├── {image_name}_mito_1.csv # Intensity profile along mitochondrial path
├── {image_name}_mito_1_intensities.png # Visualization with path overlay
├── {image_name}_mito_2.csv
├── {image_name}_mito_2_intensities.png
└── ...
binary_mask_dir_output/ # (optional, only if configured)
├── {image_name}_mito_binary.tif # Final mito binary mask (uint8, 0/255),
│ # post-thickness-filter; ready to be reused
│ # as input to other workflows.
└── ...
CSV file columns:
Distance: Position along mitochondrial pathMito_Intensity: Mitochondria channel intensity (normalized 0-1)Scan_Intensity: Protein channel intensity (normalized 0-1)
output_directory/
├── pickle_files/
│ ├── {image_name}_profile.pkl # Serialized intensity profiles
│ └── ...
└── visualizations/
├── {image_name}_profile.png
└── ...
manual_mask_directory/ or refined_mask_directory/
├── mask_{image_name}.tiff
├── mask_{image_name}.png
└── ...
output_directory/
├── peaks_summary.csv # Summary of detected peaks
├── peak_plots/ # Peak visualization plots
│ ├── {image_name}_peaks.png
│ └── ...
└── intensity_analysis/
└── ...
- Multi-channel stacked TIFF files with intensity data as 16-bit or 8-bit
- Channels should be ordered consistently across all images
- Example: Channel 0 = mitochondria (MitoTracker), Channel 1 = protein signal
- Channel 0: Mitochondria marker (MitoTracker, TOM20 staining, etc.)
- Channel 1: Optional intermediate channel
- Channel 2: Protein of interest (your scan signal)
- Additional channels: Optional additional markers
data/
├── image_001.tiff
├── image_002.tiff
├── image_003.tiff
└── ...
- Ensure the environment is activated:
conda activate mito_protein_scanner - Verify installation completed successfully
- Try:
python -m bin.mito_protein_localization --help
- Verify YAML indentation uses 2 spaces (not tabs)
- Check that paths in config are valid
- Boolean values should be
trueorfalse(lowercase)
- Verify
input_directoryexists and is spelled correctly - Check that TIFF files match the
input_pattern - Example: For pattern
snap*.tiff, files should be namedsnap0001.tiff, etc.
- For network_line_scan: Set
use_gui: falsefor batch processing - Reduce
scan_widthandpath_samplingvalues - Process fewer files at a time
- Ensure X11 forwarding is enabled:
ssh -X user@host - For headless systems, set
use_gui: falsein config - Try:
mito_protein_localization --config config.yaml network_line_scan
- Verify channel indices match your TIFF file structure
- Use 0-based indexing (first channel = 0, second = 1, etc.)
- Check TIFF metadata with:
python -c "from tifffile import TiffFile; t = TiffFile('yourfile.tiff'); print(len(t.series[0].pages))"
- scan_width: Larger values = more computation. Start with 4, increase if needed
- path_sampling: Controls subpixel accuracy. Use 5 for speed, 10+ for precision
- min_path_length: Filters out small/noise segments. Increase to skip isolated structures
- Peak detection: Adjust
peak_thresholdandpeak_prominenceto filter false positives
- Input: TIFF files (
.tiff,.tif) - Output: CSV, PNG, pickle
- Config: YAML (
.yaml,.yml)
- CLI_USAGE.md - Direct command-line script usage
- MITO_LOCATION_USAGE.md - Config-based workflow documentation
config.yaml.template- Complete configuration file template with explanations