Utilities#

Labels#

platipy.imaging.label.utils.binary_decode_image(binary_encoded_img)#

Decode a binary label map to a list of structures.

Parameters:

binary_encoded_img (SimpleITK.Image) – The encoded image.

Returns:

The list of images.

Return type:

list (SimpleITK.Image)

platipy.imaging.label.utils.binary_encode_structure_list(structure_list)#

Encode a list of binary labels using binary encoding

Parameters:

structure_list (list (SimpleITK.Image)) – The list of binary label maps.

Raises:

ValueError – A maximum of 32 structures can be encoded!

Returns:

The encoded image, can be saved etc. as usual.

Return type:

SimpleITK.Image

platipy.imaging.label.utils.correct_volume_overlap(binary_label_dict, assign_overlap_to_largest=True)#

Label structures by primes Smallest prime = largest volume

platipy.imaging.label.utils.generate_primes()#

Generate an infinite sequence of prime numbers.

platipy.imaging.label.utils.get_com(label, as_int=True, real_coords=False)#

Get centre of mass of a SimpleITK.Image

Parameters:
  • label (sitk.Image) – Label mask image.

  • as_int (bool, optional) – Returns each components as int if true. Defaults to True.

  • real_coords (bool, optional) – Return coordinates in physical space if true. Defaults to False.

Returns:

List of coordinates

Return type:

list

platipy.imaging.label.utils.prime_decode_image(prime_encoded_image)#

Decode a prime-encoded image

Parameters:

prime_encoded_image (SimpleITK.Image) – A prime-encoded image.

Returns:

A list of binary masks.

Return type:

list [SimpleITK.Image]

platipy.imaging.label.utils.prime_encode_structure_list(structure_list)#

Encode a list of structures using prime labels

Parameters:

structure_list (list [SimpleITK.Image]) – A list of binary masks.

Returns:

The prime-encoded structure

Return type:

SimpleITK.Image

platipy.imaging.label.utils.vectorised_transform_index_to_physical_point(image, point_array, rotate=True)#

Transforms a set of points from array indices to real-space

platipy.imaging.label.utils.vectorised_transform_physical_point_to_index(image, point_array, rotate=True)#

Transforms a set of points from real-space to array indices

Comparison#

platipy.imaging.label.comparison.compute_apl(label_ref, label_test, distance_threshold_mm=3)#

helper function for computing the added path length

Parameters:
  • label_ref (sitk.Image) – The reference (ground-truth) label

  • label_test (sitk.Image) – The test label

  • distance_threshold_mm (float) – Distances under this threshold will not contribute to the added path length

Returns:

The total (slice-wise) added path length in mm

Return type:

float

platipy.imaging.label.comparison.compute_metric_dsc(label_a, label_b, auto_crop=True)#

Compute the Dice Similarity Coefficient between two labels

Parameters:
  • label_a (sitk.Image) – A mask to compare

  • label_b (sitk.Image) – Another mask to compare

Returns:

The Dice Similarity Coefficient

Return type:

float

platipy.imaging.label.comparison.compute_metric_hd(label_a, label_b, auto_crop=True)#

Compute the Hausdorff distance between two labels

Parameters:
  • label_a (sitk.Image) – A mask to compare

  • label_b (sitk.Image) – Another mask to compare

Returns:

The maximum Hausdorff distance

Return type:

float

platipy.imaging.label.comparison.compute_metric_masd(label_a, label_b, auto_crop=True)#

Compute the mean absolute distance between two labels

Parameters:
  • label_a (sitk.Image) – A mask to compare

  • label_b (sitk.Image) – Another mask to compare

Returns:

The mean absolute surface distance

Return type:

float

platipy.imaging.label.comparison.compute_metric_mean_apl(label_ref, label_test, distance_threshold_mm=3)#

Compute the mean (slice-wise) added path length in mm

This operates on transaxial slices, which are assumed to be in the z-dimension (axis=2).

Parameters:
  • label_ref (sitk.Image) – The reference (ground-truth) label

  • label_test (sitk.Image) – The test label

  • distance_threshold_mm (float) – Distances under this threshold will not contribute to the added path length

Returns:

The mean (slice-wise) added path length in mm

Return type:

float

platipy.imaging.label.comparison.compute_metric_sensitivity(label_a, label_b, auto_crop=True)#

Compute the sensitivity between two labels

Parameters:
  • label_a (sitk.Image) – A mask to compare

  • label_b (sitk.Image) – Another mask to compare

Returns:

The sensitivity between the two labels

Return type:

float

platipy.imaging.label.comparison.compute_metric_specificity(label_a, label_b, auto_crop=True)#

Compute the specificity between two labels

Parameters:
  • label_a (sitk.Image) – A mask to compare

  • label_b (sitk.Image) – Another mask to compare

Returns:

The specificity between the two labels

Return type:

float

platipy.imaging.label.comparison.compute_metric_total_apl(label_ref, label_test, distance_threshold_mm=3)#

Compute the total (slice-wise) added path length in mm

This operates on transaxial slices, which are assumed to be in the z-dimension (axis=2).

Parameters:
  • label_ref (sitk.Image) – The reference (ground-truth) label

  • label_test (sitk.Image) – The test label

  • distance_threshold_mm (float) – Distances under this threshold will not contribute to the added path length

Returns:

The total (slice-wise) added path length in mm

Return type:

float

platipy.imaging.label.comparison.compute_surface_dsc(label_a, label_b, tau=3.0)#

Compute Surface Dice

From: Nikolov S et al. Clinically Applicable Segmentation of Head and Neck Anatomy for Radiotherapy: Deep Learning Algorithm Development and Validation Study J Med Internet Res 2021;23(7):e26151, DOI: 10.2196/26151

Parameters:
  • label_a (sitk.Image) – A mask to compare

  • label_b (sitk.Image) – Another mask to compare

  • tau (float) – Accepted deviation between contours (in mm)

Returns:

The Surface DSC between the two labels

Return type:

float

platipy.imaging.label.comparison.compute_surface_metrics(label_a, label_b, verbose=False)#

Compute surface distance metrics between two labels. Surface metrics computed are: hausdorffDistance, meanSurfaceDistance, medianSurfaceDistance, maximumSurfaceDistance, sigmaSurfaceDistance, surfaceDSC

Parameters:
  • label_a (sitk.Image) – A mask to compare

  • label_b (sitk.Image) – Another mask to compare

  • verbose (bool, optional) – Whether to print verbose output. Defaults to False.

Returns:

Dictionary object containing surface distance metrics

Return type:

dict

platipy.imaging.label.comparison.compute_volume(label)#

Computes the volume in cubic centimetres

Parameters:

label (SimpleITK.Image) – A binary mask.

Returns:

The volume (in cubic centimetres)

Return type:

float

platipy.imaging.label.comparison.compute_volume_metrics(label_a, label_b)#

Compute volume metrics between two labels. Volume metrics computed are: DSC, volumeOverlap fractionOverlap truePositiveFraction trueNegativeFraction falsePositiveFraction falseNegativeFraction

Parameters:
  • label_a (sitk.Image) – A mask to compare

  • label_b (sitk.Image) – Another mask to compare

Returns:

Dictionary object containing volume metrics

Return type:

dict

Cropping#

Various useful utility functions for atlas based segmentation algorithms.

platipy.imaging.utils.crop.crop_to_label_extent(image, label, expansion_mm=0)#

Crop an image to the 3D extent defined by a binary mask (label).

Parameters:
  • image (SimpleITK.Image) – The image to crop.

  • label (SimpleITK.Image) – The binary mask (label) defining the region to crop to.

  • expansion_mm (float | tuple | list, optional) – An optional expansion in physical units. Can be defined as a single number or iterable: (axial, coronal, sagittal) expansion. Defaults to 0.

Returns:

The cropped image.

Return type:

SimpleITK.Image

platipy.imaging.utils.crop.crop_to_roi(image, size, index)#

Utility function for cropping images

platipy.imaging.utils.crop.label_to_roi(label, expansion_mm=[0, 0, 0], return_as_list=False)#

Generates a region of interest (ROI), defined by a starting index (z,y,x) and size (s_z, s_y, s_x). This can be used to crop images/labels.

Parameters:
  • label (sitk.Image | list) – Binary label image/mask/structure to define to ROI

  • expansion_mm (list, optional) – An optional expansion of the box (in each direciton). Defaults to [0, 0, 0].

Returns:

crop_box_size, crop_box_starting_index

Return type:

tuple

Geometry#

platipy.imaging.utils.geometry.rotate_image(img, rotation_centre=(0, 0, 0), rotation_axis=(1, 0, 0), rotation_angle_radians=0, interpolation=1, default_value=0)#

Rotates an image

Parameters:
  • img (SimpleITK.Image) – The image to rotate

  • rotation_centre (tuple, optional) – The centre of rotation (in physical coordinates). Defaults to (0, 0, 0).

  • rotation_axis (tuple, optional) – The axis of rotation. Defaults to (1, 0, 0).

  • rotation_angle_radians (float, optional) – The angle of rotation. Defaults to 0.

  • interpolation (int, optional) – Final interpolation. Defaults to sitk.sitkNearestNeighbor.

  • default_value (int, optional) – Default value. Defaults to 0.

Returns:

The rotated image, resampled into the original space.

Return type:

SimpleITK.Image

platipy.imaging.utils.geometry.vector_angle(v1, v2, smallest=True)#

Return the angle between two vectors

Parameters:
  • v1 (np.array) – A three-dimensional vector

  • v2 (np.array) – A three-dimensional vector

  • smallest (bool, optional) – If True, the angle is the smallest (i.e. ignoring direction). If False, direction is taken into account, so angle can be obtuse. Defaults to True.

Returns:

The angle in radians

Return type:

float

Left Ventricle#

platipy.imaging.utils.ventricle.extract(template_img, angles, radii, angle_min, angle_max, loc_x, loc_y, cw=False, radius_min=0, min_area_mm2=25)#

Utility function to extract relevant voxels from a mask based on polar coordinates

platipy.imaging.utils.ventricle.generate_left_ventricle_segments(contours, label_left_ventricle='Ventricle_L', label_left_atrium='Atrium_L', label_right_ventricle='Ventricle_R', label_heart='Heart', myocardium_thickness_mm=10, hole_fill_mm=3, optimiser_tol_degrees=1, optimiser_max_iter=10, min_area_mm2=50, verbose=False)#

Generates the 17 segments of the left vetricle

This functions works as follows:
  1. Heart volume is rotated to align the long axis to the z Cartesian (physical) space. Usually means it aligns with the axial axis (for normal simulation CT)

  2. An optimiser adjusts the orientation to refine this alignment to the vector defined by MV COM - LV apex axis (long axis)

  3. Left ventricle is divided into thirds along the long axis

  4. Myocardium is defined as the outer 10mm

  5. Geometric operations are used to define the segments

  6. Everything is rotated back to the normal orientation

  7. Some post-processing magic

Parameters:
  • contours (dict) – A dictionary containing strings (label names) as keys and SimpleITK.Image (masks) as values. Must contain at least the LV, RV, MV, and whole heart.

  • label_left_ventricle (str, optional) – The name for the left ventricle mask (contour). Defaults to Ventricle_L.

  • label_left_atrium (str, optional) – The name for the left atrium mask (contour). Defaults to Atrium_L.

  • label_right_ventricle (str, optional) – The name for the right ventricle mask (contour). Defaults to Ventricle_R.

  • label_heart (str, optional) – The name for the heart mask (contour). Defaults to Heart.

  • myocardium_thickness_mm (float, optional) – Moycardial thickness, in millimetres. Defaults to 10.

  • hole_fill_mm (float, optional) – Holes smaller than this get filled in. Defaults to 3.

  • optimiser_tol_degrees (float, optional) – Optimiser tolerance (change in angle per iter). Defaults to 1, which typically requires 3-4 iterations.

  • optimiser_max_iter (int, optional) – Maximum optimiser iterations. Defaults to 10

  • verbose (bool, optional) – Print of information for debugging. Defaults to False.

Returns:

The left ventricle segment dictionary, with labels (int) as keys and the binary label defining the segment (SimpleITK.Image) as values.

Return type:

dict

IO#

platipy.imaging.utils.io.write_nrrd_structure_set(masks, output_file='structure_set.nrrd', colormap=<matplotlib.colors.LinearSegmentedColormap object>, use_compression=True, compression_level=9)#

Write an nrrd structure given a set of masks. Useful for reading in Slicer.

Parameters:
  • masks (dict) – Key is structure name, value is SimpleITK.Image

  • output_file (str, optional) – The path to write the nrrd file. Defaults to “structure_set.nrrd”.

  • colormap (matplotlib.colors.Colormap | dict, optional) – Colormap to use for output. Can also use a dictionary with keys as structure names and values as colors. Defaults to matplotlib.colormaps.get_cmap(“rainbow”).

  • use_compression (bool, optional) – Used by SimpleITK’s WriteImage function to enable compression when writing output file. Defaults to True.

  • compression_level (int, optional) – Used by SimpleITK’s WriteImage function to specify how much compression to use. Should be an integer between 0-9. Defaults to 9.

Raises:
  • AttributeError – masks must be a dict

  • ValueError – colormap must be a matplotlib colormap or a dictionary