Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added antspynet/cli/__init__.py
Empty file.
82 changes: 82 additions & 0 deletions antspynet/cli/mouse_brain_extraction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#!/usr/bin/env python

import argparse

import ants
import antspynet


def build_parser():
parser = argparse.ArgumentParser(
description="Run mouse brain extraction with ANTsPyNet."
)
parser.add_argument(
"input_image",
type=str,
help="Path to the input mouse image.",
)
parser.add_argument(
"output_image",
type=str,
help="Path to write the extracted probability image.",
)
parser.add_argument(
"--modality",
default="t2",
choices=["t2", "ex5coronal", "ex5sagittal"],
help='Mouse image modality passed to mouse_brain_extraction (default: "t2").',
)
parser.add_argument(
"--isotropic-output",
action="store_true",
help="Return the probability image in isotropic space before writing it.",
)
parser.add_argument(
"--axis",
type=int,
default=2,
choices=[0, 1, 2],
help="Axis index used for ex5 modalities (default: 2).",
)
Comment on lines +23 to +40
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is important. The documentation needs to be complete and explanatory, which does introduce some duplication with function documentation, but I don't see how it can be avoided.

parser.add_argument(
"--verbose",
action="store_true",
help="Print progress while running the model.",
)
return parser


def run(input_image, output_image, modality="t2", isotropic_output=False, axis=2, verbose=False):
image = ants.image_read(input_image)
probability_image = antspynet.mouse_brain_extraction(
image,
modality=modality,
return_isotropic_output=isotropic_output,
which_axis=axis,
verbose=verbose,
)
ants.image_write(probability_image, output_image)
return output_image


def main(argv=None):
parser = build_parser()
args = parser.parse_args(argv)

try:
run(
args.input_image,
args.output_image,
modality=args.modality,
isotropic_output=args.isotropic_output,
axis=args.axis,
verbose=args.verbose,
)
except Exception as error:
parser.exit(1, f"Error: {error}\n")

Comment on lines +62 to +77
return 0


if __name__ == "__main__":
raise SystemExit(main())
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,6 @@ find = { include = ["antspynet","antspynet.*"] }
[tool.setuptools]
license-files = []

[project.scripts]
antsMouseBrainExtraction = "antspynet.cli.mouse_brain_extraction:main"

69 changes: 69 additions & 0 deletions tests/test_mouse_cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import os
import tempfile
import unittest
from unittest.mock import patch

import ants
import numpy as np

from antspynet.cli.mouse_brain_extraction import main


class TestMouseBrainExtractionCli(unittest.TestCase):
def test_main_routes_to_mouse_brain_extraction(self):
input_image = ants.from_numpy(np.ones((4, 4, 4)))
output_image = ants.from_numpy(np.full((4, 4, 4), 0.25))

with tempfile.TemporaryDirectory() as tmpdir:
input_path = os.path.join(tmpdir, "input.nii.gz")
output_path = os.path.join(tmpdir, "output.nii.gz")

calls = {}

def fake_image_read(path):
calls["image_read"] = path
return input_image

def fake_mouse_brain_extraction(
image,
modality,
return_isotropic_output,
which_axis,
verbose,
):
calls["mouse_brain_extraction"] = {
"image": image,
"modality": modality,
"return_isotropic_output": return_isotropic_output,
"which_axis": which_axis,
"verbose": verbose,
}
return output_image

def fake_image_write(image, path):
calls["image_write"] = {"image": image, "path": path}

with patch("antspynet.cli.mouse_brain_extraction.ants.image_read", side_effect=fake_image_read), \
patch("antspynet.cli.mouse_brain_extraction.antspynet.mouse_brain_extraction", side_effect=fake_mouse_brain_extraction), \
patch("antspynet.cli.mouse_brain_extraction.ants.image_write", side_effect=fake_image_write):
exit_code = main([
input_path,
output_path,
"--modality", "t2",
"--isotropic-output",
"--axis", "1",
"--verbose",
])

self.assertEqual(exit_code, 0)
self.assertEqual(calls["image_read"], input_path)
self.assertEqual(calls["image_write"]["path"], output_path)
self.assertIs(calls["image_write"]["image"], output_image)
self.assertEqual(calls["mouse_brain_extraction"]["modality"], "t2")
self.assertTrue(calls["mouse_brain_extraction"]["return_isotropic_output"])
self.assertEqual(calls["mouse_brain_extraction"]["which_axis"], 1)
self.assertTrue(calls["mouse_brain_extraction"]["verbose"])


if __name__ == "__main__":
unittest.main()
Loading