Skip to content

BioimageAnalysisCoreWEHI/uncertainty_aware_brain_analysis

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Uncertainty-aware atlas registration workflow for whole-brain LSFM analysis

This repository contains analysis scripts for an uncertainty-aware atlas registration and quantification workflow for whole-brain light-sheet fluorescence microscopy (LSFM) datasets, using brainreg, link to GitHub.

The workflow was developed to assess how registration parameter choices influence propagated atlas regions and downstream TH+ cell counts in anatomically ambiguous brain regions such as the substantia nigra pars compacta (SNpc).


Overview

The pipeline:

  1. Generates a brainreg parameter-sweep job table.
  2. Runs brainreg registrations as independent SLURM array jobs.
  3. Computes global and local registration QC metrics.
  4. Builds SNpc probability maps and consensus masks.
  5. Extracts full-resolution TH and AF crops around the SNpc region.
  6. Runs Cellpose on each TH crop.
  7. Counts detected cells within each parameter-specific and consensus SNpc mask.
  8. Computes cell-level regional assignment probabilities across registrations.

Repository structure

.
├── config/
│   ├── config.yaml
│   ├── samples.csv
|   |── ARA2_annotation_info_avail_regions.csv
│   └── midbrain_bbox.json
│
├── scripts/
│   ├── 01_make_brainreg_jobs.py
│   ├── 02_submit_brainreg_sweep.sh
│   ├── run_brainreg_array.sh
│   │
│   ├── 03_compute_qc_metrics.py
│   ├── 04_build_consensus_maps.py
│   │
│   ├── 05_cellpose_local.py
│   ├── 05_make_cellpose_jobs.py
│   ├── run_cellpose_one_crop.py
│   ├── run_cellpose_array.sh
│   ├── 06_submit_cellpose_jobs.sh
│   │
│   ├── 07_count_cells_in_masks.py
│   └── 08_compute_cell_region_probabilities.py

Pipeline summary

1. Brainreg parameter sweep generation

01_make_brainreg_jobs.py generates a parameter sweep table from:

  • config/config.yaml
  • config/samples.csv

Each row corresponds to a single registration job.

Generates

results/job_tables/brainreg_jobs.csv
results/job_tables/brainreg_jobs.metadata.json

Example

python scripts/01_make_brainreg_jobs.py \
    --config config/config.yaml \
    --samples config/samples.csv \
    --out results/job_tables/brainreg_jobs.csv

2. SLURM brainreg registration sweep

02_submit_brainreg_sweep.sh automatically:

  • reads the generated job table
  • calculates the required SLURM array size
  • submits all registrations

Each registration is executed independently through:

run_brainreg_array.sh

Example

sbatch scripts/02_submit_brainreg_sweep.sh

brainreg command

Each registration executes a command of the form:

brainreg "$AF_DIR" "$SAVE_DIR" \
  -v "$vx" "$vy" "$vz" \
  --orientation "$orientation" \
  --atlas "$atlas" \
  --debug \
  --save-original-orientation \
  -a "$TH_DIR" "$UNPROCESSED_DIR" \
  --n-free-cpus 0 \
  --bending-energy-weight "$bending" \
  --grid-spacing "$grid" \
  --smoothing-sigma-floating "$smoothing"

Input configuration

config/config.yaml

Controls:

  • atlas settings, the region_label is found from the ontology file, this can be changed according to the region of interest

  • brainreg sweep parameters

  • QC thresholds

  • consensus thresholds

  • Cellpose settings

  • NOTE: If you are interested in a different region, the midbrain_bbox.json (bounding box) used during the local QC will have to be recalculated and extracted

Example

atlas:
  name: "perens_lsfm_mouse_20um"
  reference_image: "/path/to/reference_atlas_image.tif"
  resolution_um: 20
  region_label: 374

brainreg:
  grid_spacing: [-2, -3, -5, -10, -30, -50]
  bending_energy_weight: [0.0, 0.1, 0.3, 0.5, 0.7, 0.9, 0.95, 1.0]
  smoothing_sigma_floating: [-1.0]
  orientation: sal
  voxel_size: [20, 20, 20]

qc:
  iou_threshold: 0.9
  grad_p95_threshold: 0.045
  ssim_top_fraction: 0.5

consensus:
  thresholds: [0.05, 0.1, 0.25, 0.5, 0.75, 1.0]

cellpose:
  custom_weights: "/path/to/custom/model"
  diameter: 9
  channels: [0, 0]
  flow_threshold: 0.8
  cellprob_threshold: -3.0
  stitch_threshold: 0.3
  do_3D: false
  use_gpu: true

config/samples.csv

Expected columns:

sample_id,input_type,output_group,af_image,th_image,unprocessed_image,tissue_mask,af_full_res,th_full_res,pixel_size_z,pixel_size_y,pixel_size_x

Description

Column Description
af_image Downsampled autofluorescence image used for brainreg
th_image Downsampled TH image passed to brainreg
unprocessed_image Additional image passed to brainreg
tissue_mask Binary tissue mask used for overlap QC
af_full_res Full-resolution autofluorescence stack
th_full_res Full-resolution TH stack
pixel_size_z/y/x Full-resolution voxel size

3. Registration QC metrics

03_compute_qc_metrics.py computes:

Global QC

  • tissue-atlas IoU
  • atlas overlap fractions
  • tissue overlap fractions

Deformation QC

  • deformation gradient statistics
  • Jacobian determinant statistics

Local QC

  • local SSIM within a fixed midbrain bounding box

Generates

results/qc_tables/qc_results.csv

Example

python scripts/03_compute_qc_metrics.py \
    --config config/config.yaml \
    --samples config/samples.csv \
    --jobs results/job_tables/brainreg_jobs.csv \
    --out results/qc_tables/qc_results.csv

4. Consensus maps and region assets

04_build_consensus_maps.py:

  • extracts SNpc masks from registered atlases
  • generates voxel-wise probability maps
  • computes consensus regions
  • extracts full-resolution TH/AF crops
  • converts between coronal and axial orientations
  • rescales atlas-space masks into full-resolution image space

Outputs

results/region_assets/
└── sample_id/
    └── input_type/
        ├── probability_maps_downsampled/
        ├── bbox/
        ├── fullres_crops/
        ├── parameter_masks_fullres_crop/
        ├── registered_atlas_fullres_crop/
        └── consensus_masks_fullres_crop/

Example

python scripts/04_build_consensus_maps.py \
    --config config/config.yaml \
    --samples config/samples.csv \
    --qc-table results/qc_tables/qc_results.csv \
    --out-dir results/region_assets \
    --consensus-qc-column passes_final_qc

5A. Local Cellpose segmentation

05_cellpose_local.py runs Cellpose on each extracted TH crop.

Example

python scripts/05_cellpose_local.py \
    --config config/config.yaml \
    --region-assets results/region_assets

Output

results/region_assets/sample_id/input_type/cellpose_outputs/

Containing:

cellpose_labels.tif
cellpose_run_metadata.json

5B. HPC Cellpose segmentation

Generate Cellpose job table:

python scripts/05_make_cellpose_jobs.py \
    --config config/config.yaml \
    --region-assets results/region_assets

Submit jobs:

bash scripts/06_submit_cellpose_jobs.sh

Each array task executes:

run_cellpose_array.sh

which runs:

run_cellpose_one_crop.py

6. Cell counting within parameter and consensus masks

07_count_cells_in_masks.py:

  • masks Cellpose labels using SNpc masks
  • counts overlapping labels
  • saves masked label images
  • computes counts for:
    • parameter-specific masks
    • consensus masks

Example

python scripts/07_count_cells_in_masks.py \
    --region-root results/region_assets \
    --out-dir results/cell_counts

Outputs

results/cell_counts/
├── cell_counts_by_parameter_mask.csv
└── cell_counts_by_consensus_mask.csv

Masked labels are additionally saved under:

parameter_masked_cell_labels/
consensus_masked_cell_labels/

7. Cell-level regional assignment probabilities

08_compute_cell_region_probabilities.py computes probabilistic atlas assignments for each detected cell across all registrations.

Each cell is assigned a probability of belonging to each atlas region based on its centroid location across registered atlas crops.

Example

python scripts/08_compute_cell_region_probabilities.py \
    --region-root results/region_assets \
    --ontology-csv /path/to/ontology.csv \
    --out-dir results/cell_region_probabilities

Outputs

ALL_cell_region_probabilities_long.csv
ALL_cell_region_probabilities_wide.csv
ALL_cell_region_grouped_probabilities_long.csv
ALL_cell_region_grouped_probabilities_wide.csv
run_manifest.csv

Orientation handling

brainreg outputs are generated in coronal orientation, while the original full-resolution LSFM stacks are axial.

Current conversion logic:

def coronal_to_axial(arr):
    return np.flip(np.transpose(arr, (1, 0, 2)), axis=2)

This transform should be visually verified for new datasets.


Path handling

Some scripts automatically convert Linux cluster paths to Windows mapped drives when running locally:

/vast/scratch -> U:\
/vast/imaging -> V:\

Adjust these mappings if required for your local environment.


Software requirements

Python packages

Core dependencies include:

brainreg
cellpose
numpy
pandas
tifffile
scikit-image
scipy
dask-image
pyyaml

Notes

This repository is intended as a reproducibility workflow accompanying the associated manuscript, rather than a fully packaged general-purpose software tool.


About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors