Getting started¶
Installation¶
PyTorch: Before installing the package, PyTorch needs to be installed which can be done using the instructions on PyTorch.
FetalBrain package: The fetalbrain package will be hosted on pip, but can currently be used by cloning the repository locally with:
$ git clone git@github.com:oxford-omni-lab-org/OMNI_ultrasound.git
User installation¶
The package can then be installed from the root of the repository with (This will install the package and all required dependencies):
$ pip install .
Then download the model weights using the provided command line downloader (this only downloads the model weights if that folder does not exists yet):
$ ftlbr_download_modelweights
To overwrite any existing downloads use:
$ ftlbr_download_modelweights --force
After installation and download of the model weights, the package can simply be used in Python with:
import fetalbrain
Development installation¶
To install the package for development, use:
$ pip install -e ".[all]"
This will install the package as editable, meaning that any changes to the package are immediately available without having to reinstall the package. The [all] option installs all dependencies needed for development, testing and documentation (as specified in the setup.cfg file). Also rerun the downlaoder to load the model weights in the correct location.
To perform testing, run the downloader with the additional argument –testdata to download the test data:
$ ftlbr_download_modelweights --testdata
Minimal Example¶
The following example shows a minimal example of using the whole pipeline to align, and segment a fetal brain scan.
from pathlib import Path
from fetalbrain.utils import read_image, write_image
from fetalbrain.alignment.align import align_scan
from fetalbrain.structural_segmentation.subcortical_segm import segment_scan_subc, compute_volume_segm
from fetalbrain.tedsnet_multi.teds_multi_segm import segment_scan_tedsall
from fetalbrain.brain_extraction.extract import extract_scan_brain
from fetalbrain.model_paths import EXAMPLE_IMAGE_PATH
example_scan, _ = read_image(EXAMPLE_IMAGE_PATH)
# Start with alignment to atlas space
aligned_scan, params = align_scan(example_scan, scale=False, to_atlas=True)
# Perform subcortical segmentation
subc_segm, subc_keys = segment_scan_subc(aligned_scan, connected_component=True)
# Use TEDSnet to do all structure segmentations
allstructure_segm, multi_keys = segment_scan_tedsall(aligned_scan)
# Extract the brain
brain_mask, brain_key = extract_scan_brain(aligned_scan)
# Write out the results in the aligned orientation
write_image(Path("aligned_scan.nii.gz"), aligned_scan.squeeze().numpy())
write_image(Path("subcortical_segm.nii.gz"), subc_segm.squeeze(), segm=True)
write_image(Path("allstructure_segm.nii.gz"), allstructure_segm.squeeze(), segm=True)
write_image(Path("brain_mask.nii.gz"), brain_mask.squeeze(), segm=True)
# compute volumes of the segmentation masks
volume_dict = compute_volume_segm(subc_segm, subc_keys, spacing=(0.6, 0.6, 0.6))
print(volume_dict)
Advanced Example¶
To run the pipeline for multiple scans and with more flexibility, it is recommended to use the individual pipeline functions rather than the wrapper functions. This ensures that the models are not reloaded for each scan. The following example demonstrates this for a single example.
from pathlib import Path
import torch
from fetalbrain.utils import read_image, write_image
from fetalbrain.alignment.align import load_alignment_model, align_to_atlas, prepare_scan
from fetalbrain.structural_segmentation.subcortical_segm import load_segmentation_model, segment_subcortical
from fetalbrain.tedsnet_multi.teds_multi_segm import (
load_tedsmulti_model,
segment_tedsall,
load_sidedetector_model,
detect_side,
)
from fetalbrain.brain_extraction.extract import extract_brain, load_brainextraction_model
from fetalbrain.alignment.kelluwen_transforms import apply_affine
from fetalbrain.model_paths import EXAMPLE_IMAGE_PATH
# Load the models once
align_model = load_alignment_model()
subc_segmmodel = load_segmentation_model()
teds_multimodel = load_tedsmulti_model()
side_detectormodel = load_sidedetector_model()
brainextraction_model = load_brainextraction_model()
# whether to do connected component analysis for subcortical segm
connected_component = True
# Loop over all scans (just one here as example)
example_scan, _ = read_image(EXAMPLE_IMAGE_PATH)
torch_scan = prepare_scan(example_scan)
# Start with alignment to atlas space
aligned_scan, params = align_to_atlas(torch_scan, align_model, scale=False)
# Perform subcortical segmentation
subc_segm, subc_keys = segment_subcortical(aligned_scan, subc_segmmodel, connected_component=True)
# Perform segmentation with multi structure tedsnet
side, prob_side = detect_side(aligned_scan, side_detectormodel)
allstructure_segm, multi_keys = segment_tedsall(aligned_scan, teds_multimodel, side=side)
# perform whole brian extraction (i.e. brain masking)
brain_mask, brain_key = extract_brain(aligned_scan, brainextraction_model)
# Write out the results in the aligned orientation
savefolder = Path("results")
savefolder.mkdir(exist_ok=True)
write_image(savefolder / "aligned_scan.nii.gz", aligned_scan.squeeze().numpy())
write_image(savefolder / "subcortical_segm.nii.gz", subc_segm.squeeze(), segm=True)
write_image(savefolder / "allstructure_segm.nii.gz", allstructure_segm.squeeze(), segm=True)
write_image(savefolder / "brain_mask.nii.gz", brain_mask.squeeze().numpy(), segm=True)
# to create segmentations in the original orientation
aligned_scan, params, affine = align_to_atlas(torch_scan, align_model, scale=False, return_affine=True)
subc_segm_original = apply_affine(torch.from_numpy(subc_segm).unsqueeze(0), affine.inverse(), type_resampling="nearest")
# Write out the results in the original orientation
write_image(savefolder / "original_scan.nii.gz", example_scan)
write_image(savefolder / "subcortical_segm_original.nii.gz", subc_segm_original.squeeze().numpy(), # type: ignore
segm=True)