#!/usr/bin/env python3
"""
Use ``warp_ccf30_to_merfish`` or ``c2m`` from UNRAVEL to warp an image from Allen CCFv3 30 um space to MERFISH-CCF space (10 x 10 x 200 µm).
Prereqs:
- Download files for warping (CCF30_to_MERFISH.tar.gz) from:
- https://stanfordmedicine.box.com/s/u9vg2wdmrx1t4bvqu321vmggg793kvuo (This is 1.4 GB)
- Extract it (double click or use tar -xvzf CCF30_to_MERFISH.tar.gz) to a folder (e.g., /path/CCF30_to_MERFISH; this is the warp root).
- This folder should contain:
- MERFISH_resampled_average_template.nii.gz
- reg_outputs/MERFISH_resampled_average_template_fixed_reg_input.nii.gz
- reg_outputs/ANTsPy_`*`
Usage:
------
warp_ccf30_to_merfish -i path/image.nii.gz -w path/to/warp_root [-o MERFISH] [-inp nearestNeighbor] [-v]
"""
from pathlib import Path
from rich import print
from rich.live import Live
from rich.traceback import install
from unravel.core.help_formatter import RichArgumentParser, SuppressMetavar, SM
from unravel.core.config import Configuration
from unravel.core.utils import get_stem, log_command, match_files, verbose_start_msg, verbose_end_msg, initialize_progress_bar
from unravel.warp.to_fixed import forward_warp
[docs]
def parse_args():
parser = RichArgumentParser(formatter_class=SuppressMetavar, add_help=False, docstring=__doc__)
reqs = parser.add_argument_group('Required arguments')
reqs.add_argument('-i', '--input', help='One or more .nii.gz files or glob patterns to warp from CCFv3 30 µm atlas space (e.g., *.nii.gz subdir/*.nii.gz)', nargs='*', required=True, action=SM)
reqs.add_argument('-w', '--warp_root', help='Path to the root directory containing the warp files.', required=True, action=SM)
opts = parser.add_argument_group('Optional arguments')
opts.add_argument('-o', '--output', help='Output directory to save warped images. Each output will be named like inputname_MERFISH.nii.gz. Default: MERFISH/', default="MERFISH", action=SM)
opts.add_argument('-inp', '--interpol', help='Interpolator for ants.apply_transforms (nearestNeighbor \[default], multiLabel, linear, bSpline)', default="nearestNeighbor", action=SM)
opts.add_argument('-n', '--workers', help='Number of parallel workers to use. Default: 10', default=10, type=int, action=SM)
general = parser.add_argument_group('General arguments')
general.add_argument('-v', '--verbose', help='Increase verbosity. Default: False', action='store_true', default=False)
return parser.parse_args()
[docs]
def ccf30_to_merfish(input_img_path, warp_root, output_img_path, interpol="nearestNeighbor"):
root = Path(warp_root)
fixed_img_path = root / "MERFISH_resampled_average_template.nii.gz"
fixed_reg_in = "MERFISH_resampled_average_template_fixed_reg_input.nii.gz"
reg_outputs_path = root / "reg_outputs"
forward_warp(fixed_img_path, reg_outputs_path, fixed_reg_in, input_img_path, interpol, output=output_img_path, pad_percent=0.15)
# Delete the intermediate warped image
warp_outputs_dir = reg_outputs_path / "warp_outputs"
warped_nii_path = Path(str(warp_outputs_dir / str(Path(input_img_path).name).replace(".nii.gz", "_in_fixed_img_space.nii.gz")))
if warped_nii_path.exists():
warped_nii_path.unlink()
# Delete the warp_outputs directory if empty
if warp_outputs_dir.exists() and not any(warp_outputs_dir.iterdir()):
warp_outputs_dir.rmdir()
[docs]
@log_command
def main():
install()
args = parse_args()
Configuration.verbose = args.verbose
verbose_start_msg()
input_img_paths = match_files(args.input)
input_img_paths = [str(p) for p in input_img_paths]
output_dir = Path(args.output)
output_dir.mkdir(parents=True, exist_ok=True)
progress, task_id = initialize_progress_bar(len(input_img_paths), task_message="[bold green]Warping images...")
with Live(progress):
for input_img_path in input_img_paths:
img_stem = get_stem(input_img_path)
output_img_path = output_dir / f"{img_stem}_MERFISH.nii.gz"
ccf30_to_merfish(input_img_path, args.warp_root, output_img_path, args.interpol)
progress.update(task_id, advance=1)
verbose_end_msg()
if __name__ == '__main__':
main()