From fde92112628f76da66bc93792569de46e6da061f Mon Sep 17 00:00:00 2001 From: engrosamaali91 Date: Wed, 21 Feb 2024 14:49:58 +0100 Subject: [PATCH] Implemented requested changes --- CerebNet/apply_warp.py | 14 ++-------- CerebNet/run_prediction.py | 13 +++++++-- doc/conf.py | 6 ---- recon_surf/N4_bias_correct.py | 34 +++++++++++++---------- recon_surf/fs_balabels.py | 4 +-- recon_surf/lta.py | 2 +- recon_surf/map_surf_label.py | 4 +-- recon_surf/paint_cc_into_pred.py | 17 +++++++----- recon_surf/rewrite_mc_surface.py | 4 +-- recon_surf/rotate_sphere.py | 11 ++++---- recon_surf/sample_parc.py | 12 ++++---- recon_surf/smooth_aparc.py | 20 ++++++------- recon_surf/spherically_project_wrapper.py | 6 ++-- 13 files changed, 76 insertions(+), 71 deletions(-) diff --git a/CerebNet/apply_warp.py b/CerebNet/apply_warp.py index 86f1f15d7..9bc2cb0c2 100644 --- a/CerebNet/apply_warp.py +++ b/CerebNet/apply_warp.py @@ -35,11 +35,6 @@ def save_nii_image(img_data, save_path, header, affine): The header information for the NIfTI file. affine : ndarray The affine matrix for the NIfTI file. - - Returns - ------- - None - This function returns nothing. """ img_out = nib.Nifti1Image(img_data, header=header, affine=affine) @@ -47,7 +42,7 @@ def save_nii_image(img_data, save_path, header, affine): nib.save(img_out, save_path) -def store_warped_data(img_path, lbl_path, warp_path, result_path, patch_size): +def main(img_path, lbl_path, warp_path, result_path, patch_size): """ Load, warp, crop, and save both an image and its corresponding label based on a given warp field. @@ -64,11 +59,6 @@ def store_warped_data(img_path, lbl_path, warp_path, result_path, patch_size): Directory path where the warped and cropped images will be saved. patch_size : tuple of int The dimensions (height, width, depth) cropped images after warping. - - Returns - ------- - None - This function returns nothing. """ img, img_file = utils.load_reorient_rescale_image(img_path) @@ -120,7 +110,7 @@ def store_warped_data(img_path, lbl_path, warp_path, result_path, patch_size): args = parser.parse_args() warp_path = join(args.result_path, args.warp_filename) - store_warped_data(args.img_path, + main(args.img_path, args.lbl_path, warp_path=warp_path, result_path=args.result_path, diff --git a/CerebNet/run_prediction.py b/CerebNet/run_prediction.py index 566c9021b..62f6c6a33 100644 --- a/CerebNet/run_prediction.py +++ b/CerebNet/run_prediction.py @@ -104,6 +104,7 @@ def setup_options(): def main(args): """ Main function to run the inference based on the given command line arguments. + This implementation is inspired by methods described in CerebNet for cerebellum sub-segmentation. Parameters ---------- @@ -112,8 +113,16 @@ def main(args): Returns ------- - str or None - A message indicating the failure reason in case of an exception, otherwise `None`. + int + Returns 0 upon successful execution to indicate success. + str + A message indicating the failure reason in case of an exception. + + References + ---------- + Faber J, Kuegler D, Bahrami E, et al. CerebNet: A fast and reliable deep-learning + pipeline for detailed cerebellum sub-segmentation. NeuroImage 264 (2022), 119703. + https://doi.org/10.1016/j.neuroimage.2022.119703 """ cfg = get_config(args) cfg.TEST.ENABLE = True diff --git a/doc/conf.py b/doc/conf.py index 7771edbce..289c92c1e 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -21,12 +21,6 @@ import os sys.path.append(os.path.dirname(__file__) + '/..') sys.path.append(os.path.dirname(__file__) + '/../recon_surf') -# sys.path.append(os.path.dirname(__file__) + '/../CerebNet') - -# sys.path.insert(0, '..') #after - -# autodoc_mock_imports = ["torch", "yacs"] - project = 'FastSurfer' copyright = '2023, Martin Reuter' diff --git a/recon_surf/N4_bias_correct.py b/recon_surf/N4_bias_correct.py index db957ae6e..87e56f96b 100644 --- a/recon_surf/N4_bias_correct.py +++ b/recon_surf/N4_bias_correct.py @@ -15,17 +15,21 @@ # IMPORTS -import image_io as iio +# Group 1: Python native modules import argparse -import sys import logging -import SimpleITK as sitk -import numpy as np - +import sys from pathlib import Path from typing import Optional, cast, Tuple + +# Group 2: External modules +import SimpleITK as sitk +import numpy as np from numpy import typing as npt +# Group 3: Internal modules +import image_io as iio + HELPTEXT = """ Script to call SITK N4 Bias Correction @@ -104,7 +108,7 @@ def options_parse(): Returns ------- options - Object holding options. + Namespace object holding options. """ parser = argparse.ArgumentParser( description=HELPTEXT, @@ -277,7 +281,8 @@ def normalize_wm_aseg( target_bg: float = 3. ) -> sitk.Image: """ - Normalize WM image [MISSING]. + Normalize WM image so the white matter has a mean + intensity of target_wm and the backgroud has intensity target_bg. Parameters ---------- @@ -323,8 +328,8 @@ def normalize_wm_aseg( def normalize_img( itk_image: sitk.Image, itk_mask: Optional[sitk.Image], - source_intensity: Tuple[float, float], - target_intensity: Tuple[float, float] + source_intensity: tuple[float, float], + target_intensity: tuple[float, float] ) -> sitk.Image: """ Normalize image by source and target intensity values. @@ -334,10 +339,11 @@ def normalize_img( itk_image : sitk.Image Input image to be normalized. itk_mask : sitk.Image | None - [MISSING]. - source_intensity : Tuple[float, float] + Brain mask, voxels inside the mask are guaranteed to be > 0, + None is optional. + source_intensity : tuple[float, float] Source intensity range. - target_intensity : Tuple[float, float] + target_intensity : tuple[float, float] Target intensity range. Returns @@ -474,12 +480,12 @@ def get_image_mean(image: sitk.Image, mask: Optional[sitk.Image] = None) -> floa def get_brain_centroid(itk_mask: sitk.Image) -> np.ndarray: """ - Get the brain centroid from the itk_mask + Get the brain centroid from a binary image. Parameters ---------- itk_mask : sitk.Image - [MISSING]. + Binary image to compute the centroid of its labeled region. Returns ------- diff --git a/recon_surf/fs_balabels.py b/recon_surf/fs_balabels.py index 86194f689..816f3eedc 100755 --- a/recon_surf/fs_balabels.py +++ b/recon_surf/fs_balabels.py @@ -75,12 +75,12 @@ def options_parse(): """ - Command line option parser. + Create a command line interface and return command line options. Returns ------- options - Object holding options. + Namespace object holding options. """ parser = optparse.OptionParser( version="$Id:fs_balabels.py,v 1.0 2022/08/24 21:22:08 mreuter Exp $", diff --git a/recon_surf/lta.py b/recon_surf/lta.py index 361182035..c69645df1 100755 --- a/recon_surf/lta.py +++ b/recon_surf/lta.py @@ -29,7 +29,7 @@ def writeLTA( dst_header: Dict ) -> None: """ - Write linear transform array info to a .lta file. + An .lta file. Parameters ---------- diff --git a/recon_surf/map_surf_label.py b/recon_surf/map_surf_label.py index 4e985e424..6e1cc09cb 100755 --- a/recon_surf/map_surf_label.py +++ b/recon_surf/map_surf_label.py @@ -60,12 +60,12 @@ def options_parse(): """ - Command line option parser. + Create a command line interface and return command line options. Returns ------- options - Object holding options. + Namespace object holding options. """ parser = optparse.OptionParser( version="$Id:map_surf_label.py,v 1.0 2022/08/24 21:22:08 mreuter Exp $", diff --git a/recon_surf/paint_cc_into_pred.py b/recon_surf/paint_cc_into_pred.py index 9617e6be3..fc7ac47ec 100644 --- a/recon_surf/paint_cc_into_pred.py +++ b/recon_surf/paint_cc_into_pred.py @@ -14,11 +14,11 @@ # IMPORTS -import numpy as np -import nibabel as nib + import sys import argparse - +import numpy as np +import nibabel as nib from numpy import typing as npt HELPTEXT = """ @@ -44,12 +44,12 @@ def argument_parse(): """ - Command line option parser. + Create a command line interface and return command line options. Returns ------- options - Object holding options. + Namespace object holding options. """ parser = argparse.ArgumentParser(usage=HELPTEXT) parser.add_argument( @@ -87,14 +87,14 @@ def paint_in_cc(pred: npt.ArrayLike, aseg_cc: npt.ArrayLike) -> npt.ArrayLike: Parameters ---------- - pred : npt.ArrayLike + asegdt : npt.ArrayLike Deep-learning prediction. aseg_cc : npt.ArrayLike Aseg segmentation with CC. Returns ------- - pred + asegdt Prediction with added CC. """ cc_mask = (aseg_cc >= 251) & (aseg_cc <= 255) @@ -116,3 +116,6 @@ def paint_in_cc(pred: npt.ArrayLike, aseg_cc: npt.ArrayLike) -> npt.ArrayLike: pred_with_cc_fin.to_filename(options.output) sys.exit(0) + + +# TODO: Rename the file (paint_cc_into_asegdkt or similar) and functions. diff --git a/recon_surf/rewrite_mc_surface.py b/recon_surf/rewrite_mc_surface.py index ee86743a9..bfc0cf93c 100644 --- a/recon_surf/rewrite_mc_surface.py +++ b/recon_surf/rewrite_mc_surface.py @@ -22,12 +22,12 @@ def options_parse(): """ - Command line option parser. + Create a command line interface and return command line options. Returns ------- options - Object holding options. + Namespace object holding options. """ parser = optparse.OptionParser( version="$Id: rewrite_mc_surface,v 1.1 2020/06/23 15:42:08 henschell $", diff --git a/recon_surf/rotate_sphere.py b/recon_surf/rotate_sphere.py index 74ebfc65c..72984e236 100644 --- a/recon_surf/rotate_sphere.py +++ b/recon_surf/rotate_sphere.py @@ -18,11 +18,12 @@ # IMPORTS import optparse -import numpy as np import sys + +import numpy as np import nibabel.freesurfer.io as fs -import align_points as align +import align_points as align from numpy import typing as npt @@ -68,12 +69,12 @@ def options_parse(): """ - Command line option parser. + Create a command line interface and return command line options. Returns ------- options - Object holding options. + Namespace object holding options. """ parser = optparse.OptionParser( version="$Id: rotate_sphere.py,v 1.0 2022/03/18 21:22:08 mreuter Exp $", @@ -125,7 +126,7 @@ def align_aparc_centroids( Returns ------- - R + R : npt.NDArray[float] Rotation Matrix. """ #nferiorparietal, inferiortemporal, lateraloccipital, postcentral, posteriorsingulate diff --git a/recon_surf/sample_parc.py b/recon_surf/sample_parc.py index eaeeb2626..ee1dc8256 100644 --- a/recon_surf/sample_parc.py +++ b/recon_surf/sample_parc.py @@ -19,11 +19,13 @@ # IMPORTS import optparse import sys + import numpy as np import nibabel.freesurfer.io as fs import nibabel as nib from scipy import sparse from scipy.sparse.csgraph import connected_components + from lapy import TriaMesh from smooth_aparc import smooth_aparc from numpy import typing as npt @@ -65,12 +67,12 @@ def options_parse(): """ - Command line option parser. + Create a command line interface and return command line options. Returns ------- options - Object holding options. + Namespace object holding options. """ parser = optparse.OptionParser( version="$Id: smooth_aparc,v 1.0 2018/06/24 11:34:08 mreuter Exp $", @@ -102,7 +104,7 @@ def options_parse(): def construct_adj_cluster(tria, annot): """ - Adjacency matrix of edges from same annotation label only. + Compute adjacency matrix of edges from same annotation label only. Operates only on triangles and removes edges that cross annotation label boundaries. @@ -268,7 +270,7 @@ def sample_img(surf, img, cortex=None, projmm=0.0, radius=None): Filename of cortex label or np.array with cortex indices. projmm : float Sample projmm mm along the surface vertex normals (default=0). - radius : float [optional] | None + radius : float, optional If given and if the sample is equal to zero, then consider all voxels inside this radius to find a non-zero value. @@ -389,7 +391,7 @@ def sample_parc (surf, seg, imglut, surflut, outaparc, cortex=None, projmm=0.0, Filename of cortex label or np.ndarray with cortex indices. projmm : float Sample projmm mm along the surface vertex normals (default=0). - radius : float [optional] | None + radius : float, optional If given and if the sample is equal to zero, then consider all voxels inside this radius to find a non-zero value. """ diff --git a/recon_surf/smooth_aparc.py b/recon_surf/smooth_aparc.py index 0265ca947..6ace3361e 100644 --- a/recon_surf/smooth_aparc.py +++ b/recon_surf/smooth_aparc.py @@ -55,12 +55,12 @@ def options_parse(): """ - Command line option parser. + Create a command line interface and return command line options. Returns ------- options - Object holding options. + Namespace object holding options. """ parser = optparse.OptionParser( version="$Id: smooth_aparc,v 1.0 2018/06/24 11:34:08 mreuter Exp $", @@ -78,14 +78,14 @@ def options_parse(): return options -def get_adjM(trias: npt.NDArray, n: int): +def get_adjM(trias: npt.NDArray[int], n: int): """ Create symmetric sparse adjacency matrix of triangle mesh. Parameters ---------- - trias : np.ndarray shape (m, 3) int - [MISSING]. + trias : npt.NDArray[int](m, 3) + Triangle mesh matrix. n : int Shape of output (n,n) adjaceny matrix, where n>=m. @@ -252,7 +252,7 @@ def mode_filter( def smooth_aparc(surf, labels, cortex = None): """ - Smoothes aparc and fills holes. + Smooth aparc label regions on the surface and fill holes. First all labels with 0 and -1 unside cortex are filled via repeated mode filtering, then all labels are smoothed first with a wider and @@ -364,14 +364,14 @@ def smooth_aparc(surf, labels, cortex = None): return labels -def smooth_aparc_files( +def main( insurfname: str, inaparcname: str, incortexname: str, outaparcname: str ) -> None: """ - Smoothes aparc. + Read files, smooth the aparc labels on the surface and save the smoothed labels. Parameters ---------- @@ -382,7 +382,7 @@ def smooth_aparc_files( incortexname : str Label filepath and name of source. outaparcname : str - Suface filepath and name of destination. + Surface filepath and name of destination. """ # read input files print("Reading in surface: {} ...".format(insurfname)) @@ -402,6 +402,6 @@ def smooth_aparc_files( # Command Line options are error checking done here options = options_parse() - smooth_aparc_files(options.insurf, options.inaparc, options.incort, options.outaparc) + main(options.insurf, options.inaparc, options.incort, options.outaparc) sys.exit(0) diff --git a/recon_surf/spherically_project_wrapper.py b/recon_surf/spherically_project_wrapper.py index be9bd9f11..d253130e9 100644 --- a/recon_surf/spherically_project_wrapper.py +++ b/recon_surf/spherically_project_wrapper.py @@ -22,12 +22,12 @@ def setup_options(): """ - Command line option parser. + Create a command line interface and return command line options. Returns ------- options - Object holding options. + Namespace object holding options. """ # Validation settings parser = argparse.ArgumentParser(description="Wrapper for spherical projection") @@ -80,7 +80,7 @@ def call(command: str, **kwargs: Any) -> int: def spherical_wrapper(command1: str, command2: str, **kwargs: Any) -> int: """ - Run the first command. If it fails the fallback command is run as well. + Run the first command. If it fails the fallback command is run instead. Parameters ----------