NeuroRuler.utils package

Submodules

NeuroRuler.utils.cli_settings module

CLI settings set through command-line arguments and cli_config.json.

Command-line arguments override the values in the JSON.

NeuroRuler.utils.cli_settings.CONDUCTANCE_PARAMETER: float = 3.0

Smoothing option. See global_vars.CONDUCTANCE_PARAMETER.

NeuroRuler.utils.cli_settings.DEBUG: bool = False

Whether or not to print debugging information throughout execution.

NeuroRuler.utils.cli_settings.FILE: str = ''

The file path.

NeuroRuler.utils.cli_settings.LOWER_BINARY_THRESHOLD: float = 0.0

Required threshold option for binary threshold.

If THRESHOLD_FILTER is ThresholdFilter.Otsu, then this field will not be updated by CLI args or by cli_config.json.

NeuroRuler.utils.cli_settings.RAW: bool = False

Whether to print the “raw” circumference.

If false, it prints a “pretty”, rounded output with units included.

NeuroRuler.utils.cli_settings.SLICE: int = -1

0-indexed. Overwritten later.

NeuroRuler.utils.cli_settings.SMOOTHING_ITERATIONS: int = 5

Smoothing option. See global_vars.SMOOTHING_ITERATIONS.

NeuroRuler.utils.cli_settings.THETA_X: int = 0

In degrees

NeuroRuler.utils.cli_settings.THETA_Y: int = 0

In degrees

NeuroRuler.utils.cli_settings.THETA_Z: int = 0

In degrees

NeuroRuler.utils.cli_settings.THRESHOLD_FILTER: ThresholdFilter = ThresholdFilter.Otsu

Which threshold filter to use. Default is Otsu.

NeuroRuler.utils.cli_settings.TIME_STEP: float = 0.0625

Smoothing option. See global_vars.TIME_STEP.

NeuroRuler.utils.cli_settings.UPPER_BINARY_THRESHOLD: float = 200.0

Required threshold option for binary threshold.

If THRESHOLD_FILTER is ThresholdFilter.Otsu, then this field will not be updated by CLI args or by cli_config.json.

NeuroRuler.utils.cli_settings.get_settings() dict[str, Any][source]

Returns dict containing values of all variables in this file, used for debugging

Returns:

dict of all CLI settings

Return type:

dict[str, Any]

NeuroRuler.utils.constants module

Constant values and functions. DO NOT MUTATE ANY VARIABLE IN THIS FILE FROM OUTSIDE OF THIS FILE!

This file should not import any module in this repo to avoid circular imports.

class NeuroRuler.utils.constants.BinaryColor(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]

Bases: Enum

Self-explanatory

Black = 0
White = 1
NeuroRuler.utils.constants.JSON_CLI_CONFIG_PATH: Path = PosixPath('cli_config.json')

Settings that configure cli_settings.py.

In CLI.__init__.py cli(), will be created using package’s cli_config.json if it doesn’t already exist.

NeuroRuler.utils.constants.JSON_GUI_CONFIG_PATH: Path = PosixPath('gui_config.json')

Settings that configure gui_settings.py.

In GUI.__init__.py gui(), will be created using package’s cli_config.json if it doesn’t already exist.

NeuroRuler.utils.constants.MESSAGE_TO_SHOW_IF_UNITS_NOT_FOUND: str = 'millimeters (mm)'

We assume units are millimeters if we can’t find units in metadata

NeuroRuler.utils.constants.NIFTI_METADATA_UNITS_KEY: str = 'xyzt_units'

In the NIfTI metadata dictionary, the numerical str value attached to this key represents units of the file.

NeuroRuler.utils.constants.NIFTI_METADATA_UNITS_VALUE_TO_PHYSICAL_UNITS: dict[str, str] = {'0': 'unknown', '1': 'meters (m)', '16': 'milliseconds (ms)', '2': 'millimeters (mm)', '24': 'microseconds (μs)', '3': 'microns (μm)', '32': 'Hertz (Hz)', '40': 'parts-per-million (ppm)', '48': 'radians per second (rad/s)', '8': 'seconds (s)'}

Maps the value of xyzt_units of the metadata of a NIfTI file to physical meaning.

Based on https://brainder.org/2012/09/23/the-nifti-file-format/.

See img_helpers.py MRIImage for code to get metadata using sitk.

NeuroRuler.utils.constants.NUM_CONTOURS_IN_INVALID_SLICE: int = 10

If this number of contours or more is detected in a slice after processing by contour() (Otsu, largest component, etc.), then the slice is considered invalid.

NeuroRuler.utils.constants.NUM_DIGITS_TO_ROUND_TO: int = 3

For floats, number of digits to round to, i.e. round(float, n).

NeuroRuler.utils.constants.ORIENTATION_STRINGS: tuple[str, str, str] = ('RPI', 'LPI', 'LPS')

(X_ORIENTATION_STR, Y_ORIENTATION_STR, Z_ORIENTATION_STR)

Intended to be indexed using View.X.value, View.Y.value, and View.Z.value.

NeuroRuler.utils.constants.OUTPUT_DIR: Path = PosixPath('output')

Directory for storing output.

NeuroRuler.utils.constants.PRIMARY_MONITOR_DIMENSIONS: tuple[int, int] = (500, 500)

Set to user’s primary monitor’s dimensions. 500, 500 are dummy values

NeuroRuler.utils.constants.ROTATION_MAX: int = 90

In degrees

NeuroRuler.utils.constants.ROTATION_MIN: int = -90

In degrees

NeuroRuler.utils.constants.SUPPORTED_IMAGE_EXTENSIONS: tuple = ('*.nii.gz', '*.nii', '*.nrrd')

Image file formats supported. Must be a subset of the file formats supported by SimpleITK.

NeuroRuler.utils.constants.SUPPORTED_IMAGE_EXTENSIONS_REGEX: tuple[re.Pattern, ...] = (re.compile('^.*\\.nii\\.gz$'), re.compile('^.*\\.nii$'), re.compile('^.*\\.nrrd$'))

Tuple of re.Pattern for supported image extensions.

NeuroRuler.utils.constants.THEMES: list[str] = []

List of themes, i.e. the names of the directories in THEME_DIR.

NeuroRuler.utils.constants.THEME_DIR: Path = PosixPath('NeuroRuler/GUI/themes')

themes/ directory where .qss stylesheets and resources.py files are stored.

class NeuroRuler.utils.constants.ThresholdFilter(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]

Bases: Enum

Determines the threshold filter (Otsu or binary) used in imgproc.contour().

Binary = 1
Otsu = 0
class NeuroRuler.utils.constants.View(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]

Bases: Enum

X, Y, or Z view.

The letters are assigned indices 0-2 to be used for indexing operations.

X = 0
Y = 1
Z = 2
NeuroRuler.utils.constants.X_ORIENTATION_STR: str = 'RPI'

Orientation string to pass into sitk.DICOMOrientImageFilter to orient X view correctly.

NeuroRuler.utils.constants.Y_ORIENTATION_STR: str = 'LPI'

Orientation string to pass into sitk.DICOMOrientImageFilter to orient Y view correctly.

NeuroRuler.utils.constants.Z_ORIENTATION_STR: str = 'LPS'

Orientation string to pass into sitk.DICOMOrientImageFilter to orient Z view correctly.

NeuroRuler.utils.constants.degrees_to_radians(angle: int | float) float[source]

It’s quite simple.

Parameters:

num (int or float) – A degree measure

Returns:

Equivalent radian measure

Return type:

float

NeuroRuler.utils.constants.deprecated(func)[source]

This is a decorator which can be used to mark functions as deprecated. It will result in a warning being emitted when the function is used.

NeuroRuler.utils.constants.get_path_stem(path: Path) str[source]

Get true stem of path.

E.g., stem of a.nii is a, and stem of a.nii.gz is also a.

Note that Path('a.nii.gz').stem is 'a.nii', not expected in this project.

Parameters:

path (Path) –

Returns:

True stem of path

Return type:

str

NeuroRuler.utils.exceptions module

Custom exceptions.

exception NeuroRuler.utils.exceptions.ArraysDifferentShape[source]

Bases: Exception

__init__()[source]
exception NeuroRuler.utils.exceptions.ComputeCircumferenceOfInvalidSlice(num_contours)[source]

Bases: Exception

User attempted to compute circumference of an invalid slice.

We detect this by noticing that the number of contours in the slice >= global_vars.NUM_CONTOURS_IN_INVALID_SLICE AFTER processing (threshold, select largest component, etc.) in NeuroRuler.utils.imgproc.contour().

Most valid brain slices have only 2 or 3 detectable contours.

Change the number in global_vars.py, then run pytest and examine slices given by settings in tests/noise_vals.txt. Some valid slices have 6 or 7 contours.

See NIFTI file (0, 0, 0, 151) for a valid slice with 9 contours. 9 seems like a good limit.

__init__(num_contours)[source]
exception NeuroRuler.utils.exceptions.InvalidColor(color: str)[source]

Bases: Exception

__init__(color: str)[source]
exception NeuroRuler.utils.exceptions.InvalidJSONField(field: str, expected: str)[source]

Bases: Exception

__init__(field: str, expected: str)[source]

field is the name of the invalid field

expected is some information about what the expected value should be

exception NeuroRuler.utils.exceptions.RotationOutOfBounds(theta: int, axis: str)[source]

Bases: Exception

Should never be encountered in the GUI because our sliders have min and max. This will be for CLI arguments.

__init__(theta: int, axis: str)[source]

NeuroRuler.utils.global_vars module

Global variables that change throughout program execution.

NeuroRuler.utils.global_vars.BINARY_THRESHOLD_FILTER: BinaryThresholdImageFilter = <SimpleITK.SimpleITK.BinaryThresholdImageFilter; proxy of <Swig Object of type 'itk::simple::BinaryThresholdImageFilter *'> >

Global binary threshold filter.

NeuroRuler.utils.global_vars.CONDUCTANCE_PARAMETER: float = 3.0

Smoothing option.

Conductance controls the sensitivity of the conductance term. As a general rule, the lower the value, the more strongly the filter preserves edges. A high value will cause diffusion (smoothing) across edges. Note that the number of iterations controls how much smoothing is done within regions bounded by edges.

NeuroRuler.utils.global_vars.CURR_IMAGE_INDEX: int = 0

Image of the current image in the loaded batch of images, which is a dict[Path, sitk.Image].

You should probably use the helper functions in img_helpers instead of this (unless you’re writing helper functions).

NeuroRuler.utils.global_vars.EULER_3D_TRANSFORM: Euler3DTransform = <SimpleITK.SimpleITK.Euler3DTransform; proxy of <Swig Object of type 'itk::simple::Euler3DTransform *'> >

Global sitk.Euler3DTransform for 3D rotations.

NeuroRuler.utils.global_vars.IMAGE_DICT: dict[pathlib.Path, SimpleITK.SimpleITK.Image] = {}

The group of images that have been loaded.

Since Python 3.7+, dicts maintain insertion order. Therefore, we can use CURR_IMAGE_INDEX for retrieval and deletion.

Use list(IMAGE_DICT.keys())[i] to return the i’th key in the dict, which can also index into the dict. Not sure about this operation’s speed, but it’s used only in the GUI for insertion and deletion operations, should be fine.

All images in the dictionary have matching properties, as defined by mri_image.get_properties.

NeuroRuler.utils.global_vars.LOWER_BINARY_THRESHOLD: float = 0.0

Threshold option for binary threshold.

NeuroRuler.utils.global_vars.ORIENT_FILTER: DICOMOrientImageFilter = <SimpleITK.SimpleITK.DICOMOrientImageFilter; proxy of <Swig Object of type 'itk::simple::DICOMOrientImageFilter *'> >

Global sitk.DICOMOrientImageFilter for orienting images.

See https://simpleitk.org/doxygen/latest/html/classitk_1_1simple_1_1DICOMOrientImageFilter.html#details and the orientation strings in constants.py. Use ITK-SNAP for the orientations that we copy.

NeuroRuler.utils.global_vars.OTSU_THRESHOLD_FILTER: OtsuThresholdImageFilter = <SimpleITK.SimpleITK.OtsuThresholdImageFilter; proxy of <Swig Object of type 'itk::simple::OtsuThresholdImageFilter *'> >

Global Otsu threshold filter.

NeuroRuler.utils.global_vars.READER: ImageFileReader = <SimpleITK.SimpleITK.ImageFileReader; proxy of <Swig Object of type 'itk::simple::ImageFileReader *'> >

Global sitk.ImageFileReader.

NeuroRuler.utils.global_vars.SLICE: int = 0

0-indexed

NeuroRuler.utils.global_vars.SMOOTHING_FILTER: GradientAnisotropicDiffusionImageFilter = <SimpleITK.SimpleITK.GradientAnisotropicDiffusionImageFilter; proxy of <Swig Object of type 'itk::simple::GradientAnisotropicDiffusionImageFilter *'> >

Global sitk.GradientAnisotropicDiffusionImageFilter for image smoothing.

See https://slicer.readthedocs.io/en/latest/user_guide/modules/gradientanisotropicdiffusion.html for more information.

NeuroRuler.utils.global_vars.SMOOTHING_ITERATIONS: int = 5

Smoothing option.

The more iterations, the more smoothing. Each iteration takes the same amount of time. If it takes 10 seconds for one iteration, then it will take 100 seconds for 10 iterations. Note that the conductance controls how much each iteration smooths across edges.

NeuroRuler.utils.global_vars.THETA_X: int = 0

In degrees

NeuroRuler.utils.global_vars.THETA_Y: int = 0

In degrees

NeuroRuler.utils.global_vars.THETA_Z: int = 0

In degrees

NeuroRuler.utils.global_vars.TIME_STEP: float = 0.0625

Smoothing option.

The time step depends on the dimensionality of the image. In Slicer, the images are 3D and the default (.0625) time step will provide a stable solution.

NeuroRuler.utils.global_vars.UPPER_BINARY_THRESHOLD: float = 200.0

Threshold option for binary threshold.

NeuroRuler.utils.global_vars.VIEW: View = View.Z

Current view in the GUI.

NeuroRuler.utils.global_vars.X_CENTER: int = 0

Used for changing views.

NeuroRuler.utils.global_vars.Y_CENTER: int = 0

Used for changing views.

NeuroRuler.utils.gui_settings module

GUI settings set through command-line arguments and gui_config.json.

Command-line arguments override the values in the JSON.

There shouldn’t be any blank (empty string) values here (like the blank values in gui_config.json that are set to default values by parser.py) because if parsing the GUI json fails (e.g., doesn’t exist), then we need an actual working value here.

NeuroRuler.utils.gui_settings.CONTOUR_COLOR: str = 'b55162'

Color of the contour.

This can be a 6-hexit string rrggbb (don’t prepend 0x) or a name (e.g. red, blue, etc.).

Internally, this is converted to a QColor using imgproc.string_to_QColor(). QColor supports 8-hexit rrggbbaa but doesn’t work in our GUI, i.e. aa=00 appears fully bright in the GUI.

NeuroRuler.utils.gui_settings.DEBUG: bool = False

Whether or not to print debugging information throughout execution.

NeuroRuler.utils.gui_settings.DISPLAY_ADVANCED_MENU_MESSAGES_IN_TERMINAL: bool = False

Whether the advanced menu messages display in terminal or new window

NeuroRuler.utils.gui_settings.FILE_BROWSER_START_DIR: Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/neuroruler/checkouts/stable/docs')

The starting directory that is opened in the file browser.

Defaults to cwd.

NeuroRuler.utils.gui_settings.STARTUP_HEIGHT_RATIO: float = 0.6

Max GUI height as fraction of primary monitor height. Configurable in JSON

NeuroRuler.utils.gui_settings.STARTUP_WIDTH_RATIO: float = 0.65

Max GUI width as fraction of primary monitor width. Configurable in JSON

NeuroRuler.utils.gui_settings.THEME_NAME: str = 'dark-nr'

Name of theme in NeuroRuler/GUI/themes.

The full path to the .qss file is {constants.THEME_DIR}/{THEME_NAME}/stylesheet.qss.

NeuroRuler.utils.img_helpers module

Image helper functions that aren’t quite part of the main algorithm, unlike imgproc.py.

Mostly holds helper functions for working with IMAGE_DICT in global_vars.py.

NeuroRuler.utils.img_helpers.clear_globals() None[source]

Clear global variables for unit testing in test_img_helpers.

Don’t need to reset Euler3DTransform since that’s not used in the tests there.

Returns:

None

Return type:

None

NeuroRuler.utils.img_helpers.del_curr_img() None[source]

Remove currently displayed image from IMAGE_DICT.

Decrements CURR_IMAGE_INDEX if removing the last element.

Will not check for IMAGE_DICT being empty after the deletion (GUI should be disabled). This happens in the GUI.

Returns:

None

Return type:

None

NeuroRuler.utils.img_helpers.get_all_paths() list[pathlib.Path][source]

Return all Paths in IMAGE_DICT.

Returns:

All paths in IMAGE_DICT

Return type:

list[Path]

NeuroRuler.utils.img_helpers.get_center_of_rotation(img: Image) tuple[source]

img.TransformContinuousIndexToPhysicalPoint([ (dimension - 1) / 2.0 for dimension in img.GetSize()])

Param:

img

Returns:

img.TransformContinuousIndexToPhysicalPoint([

(dimension - 1) / 2.0 for dimension in img.GetSize()]

NeuroRuler.utils.img_helpers.get_curr_binary_thresholded_slice() Image[source]

Return binary thresholded slice of the current image based on binary filter determined by global threshold settings.

Returns:

binary thresholded 2D rotated slice using global binary threshold settings

Return type:

sitk.Image

NeuroRuler.utils.img_helpers.get_curr_image() Image[source]

Return the sitk.Image at the current index in global_vars.IMAGE_DICT.

Returns:

current image

Return type:

sitk.Image

NeuroRuler.utils.img_helpers.get_curr_image_size() tuple[source]

Return dimensions of current image.

Returns:

dimensions

Return type:

tuple

NeuroRuler.utils.img_helpers.get_curr_metadata() dict[str, str][source]

Computes and returns currently displayed image’s metadata.

Note: Does not return all metadata stored in the file, just the metadata stored in sitk.Image.GetMetaDataKeys() For example, it’s possible to get a sitk.Image’s spacing using GetSpacing(), but the same spacing values won’t be returned by this function.

Returns:

metadata

Return type:

dict[str, str]

NeuroRuler.utils.img_helpers.get_curr_otsu_slice() Image[source]

Return Otsu filtered slice of the current image.

Returns:

Otsu filtered 2D rotated slice

Return type:

sitk.Image

NeuroRuler.utils.img_helpers.get_curr_path() Path[source]

Return the current Path in IMAGE_DICT. That is, the key at index CURR_IMAGE_INDEX.

Returns:

Path of current image

Return type:

Path

NeuroRuler.utils.img_helpers.get_curr_physical_units() str | None[source]

Return currently displayed image’s physical units from sitk.GetMetaData if it exists, else None.

TODO works only for NIFTI, not NRRD.

Returns:

units or None

Return type:

str or None

NeuroRuler.utils.img_helpers.get_curr_properties_tuple() tuple[source]

Return properties tuple for the currently loaded batch of images.

Returns:

current properties tuple

Return type:

tuple

NeuroRuler.utils.img_helpers.get_curr_rotated_slice() Image[source]

Return 2D rotated slice of the current image determined by global rotation and slice settings.

Sets global_vars.EULER_3D_TRANSFORM’s rotation values but not its center since all loaded images should have the same center.

Returns:

2D rotated slice

Return type:

sitk.Image

NeuroRuler.utils.img_helpers.get_curr_smooth_slice() Image[source]

Return smoothed 2D rotated slice of the current image determined by global smoothing settings.

Returns:

smooth 2D rotated slice

Return type:

sitk.Image

NeuroRuler.utils.img_helpers.get_middle_dimension(img: Image, axis: View) int[source]

int((img.GetSize()[axis.value] - 1) / 2)

Parameters:
  • img (sitk.Image) –

  • axis – int (0-2)

Returns:

int((img.GetSize()[axis.value] - 1) / 2)

Return type:

int

NeuroRuler.utils.img_helpers.get_properties_from_path(path: Path) tuple[source]

Tuple of properties of the sitk.Image we get from path. Uses global_vars.READER.

Parameters:

path (Path) – Path from which we can get a sitk.Image

Returns:

(dimensions, center of rotation used in EULER_3D_TRANSFORM, spacing)

Return type:

tuple

NeuroRuler.utils.img_helpers.get_properties_from_sitk_image(img: Image) tuple[source]

Tuple of properties of a sitk.Image.

TODO: Add more properties

If modifying this, NeuroRuler/GUI/main.py print_properties also has to be modified slightly.

Parameters:

img (sitk.Image) –

Returns:

(center of rotation used in EULER_3D_TRANSFORM, dimensions, spacing)

Return type:

tuple

NeuroRuler.utils.img_helpers.get_rotated_slice_hardcoded(mri_img_3d: Image, theta_x: int = 0, theta_y: int = 0, theta_z: int = 0, slice_num: int = 0) Image[source]

Get 2D rotated slice of mri_img_3d from hardcoded values. Rotation values are in degrees, slice_num is an int.

For unit testing. Sets center of global EULER_3D_TRANSFORM to center of rotation of mri_img_3d.

Parameters:
  • mri_img_3d (sitk.Image) –

  • theta_x (int) –

  • theta_y (int) –

  • theta_z (int) –

  • slice_num (int) –

Returns:

2D rotated slice using hardcoded settings

Return type:

sitk.Image

NeuroRuler.utils.img_helpers.image_dict_is_empty() bool[source]
Returns:

True if IMAGE_DICT is empty, else False

Return type:

bool

NeuroRuler.utils.img_helpers.initialize_globals(path_list: list[pathlib.Path]) list[pathlib.Path][source]

After pressing File > Open, the global variables need to be cleared and (re)initialized.

If loading images with different properties, then this method returns False, and IMAGE_DICT isn’t updated with the differing images.

Mutated global variables: IMAGE_DICT, CURR_IMAGE_INDEX, READER, THETA_X, THETA_Y, THETA_Z, SLICE, EULER_3D_TRANSFORM.

Specifically, clears IMAGE_DICT and then populates it.

Parameters:

path_list (list[Path]) –

Returns:

List of paths of images with properties that differ from those of the images currently in IMAGE_DICT

Return type:

list[Path]

NeuroRuler.utils.img_helpers.next_img() None[source]

Increment CURR_IMAGE_INDEX, wrapping if necessary.

Returns:

None

Return type:

None

NeuroRuler.utils.img_helpers.orient_curr_image(view: View) None[source]

Given a view enum, set the current image to the oriented version for that view.

Parameters:

view (View.X, View.Y, or View.Z) –

Returns:

None

Return type:

None

NeuroRuler.utils.img_helpers.previous_img() None[source]

Decrement CURR_IMAGE_INDEX, wrapping if necessary.

Returns:

None

Return type:

None

NeuroRuler.utils.img_helpers.set_curr_image(image: Image) None[source]

Set the sitk.Image at the current index in global_vars.IMAGE_DICT.

Parameters:

image (sitk.Image) –

Returns:

None

Return type:

None

NeuroRuler.utils.img_helpers.update_images(path_list: list[pathlib.Path]) list[pathlib.Path][source]

Initialize IMAGE_DICT. See the docstring for IMAGE_DICT in global_vars.py for more info.

All images are oriented for the axial view when loaded. When calling this, make sure global_vars.VIEW = Z.

If the images at path(s) in path_list don’t match the properties of previously saved images, then this method returns the paths of the images that don’t match, and IMAGE_DICT is updated only with the non-differing images.

Parameters:

path_list (list[Path]) –

Raise:

Exception if path_list is empty (disallow this in GUI)

Returns:

List of paths of images with properties that differ from those of the images currently in IMAGE_DICT

Return type:

list[Path]

NeuroRuler.utils.imgproc module

Helper functions for image processing. Main algorithm.

NeuroRuler.utils.imgproc.MAX_NUM_MISMATCHED_PIXELS_FOR_BACKGROUND_COLOR_DETECTION: int = 3

At most this many edge pixels can be different from the pixel at (0, 0).

NeuroRuler.utils.imgproc.NUM_PIXELS_TO_CHECK_ON_EACH_EDGE_FOR_BACKGROUND_COLOR_DETECTION: int = 25

Roughly this many pixels are checked along the top, bottom, left, and right edges of the image.

NeuroRuler.utils.imgproc.background_color_of_binary_thresholded_slice(img_2d: Image) BinaryColor[source]

Checks the background color of the slice returning from binary threshold filter since some settings result in fg 0, bg 1, and other settings result in fg 1, bg 0.

Internally, compares the pixel value at (0, 0) to pixel values at the top, bottom, left, and right edges. Very naive approach that assumes there won’t be noise or islands at the edges.

Parameters:

img_2d (sitk.Image) –

Returns:

BinaryColor.Black or BinaryColor.White

Return type:

BinaryColor

NeuroRuler.utils.imgproc.contour(img_2d: Image, threshold_filter: ThresholdFilter = ThresholdFilter.Otsu) ndarray[source]

Generate the contour of a 2D slice by applying smoothing, Otsu threshold or binary threshold, hole filling, and island removal (select largest component). Return a binary (0|1) numpy array with only the points within the contour=1.

Calls sitk.GetArrayFromImage() at the end, which will return the transpose of the sitk.Image. Consider whether to re-transpose the result or not.

Parameters:
  • img_2d (sitk.Image) –

  • threshold_filter (ThresholdFilter) – ThresholdFilter.Otsu or ThresholdFilter.Binary. Defaults to ThresholdFilter.Otsu

Returns:

binary (0|1) numpy array with only the points on the contour = 1

Return type:

np.ndarray

NeuroRuler.utils.imgproc.distance_2d_with_spacing(p1, p2, x_spacing: float, y_spacing: float) float[source]

Return the distance between two 2D iterables (list or tuple) given x and y spacing values. :param p1: 2D point :type p1: iterable :param p2: 2D point :type p2: iterable :param x_spacing: :type x_spacing: float :param y_spacing: :type y_spacing: float

NeuroRuler.utils.imgproc.length_of_contour(binary_contour_slice: ndarray, raise_exception: bool = True) float[source]

Given a 2D binary slice, return the arc length of the parent contour.

cv2.findContours will find all contours if there is more than one. Most valid brain slices have 2 or 3.

The binary slice passed into this function should be processed by contour() (i.e., hole-filling, island removal, threshold, etc.) to contain just one contour (except in edge cases that we don’t need to worry about) to guarantee an accurate result.

This function assumes the contour is a closed curve.

Parameters:
  • binary_contour_slice (np.ndarray) – 2D binary (0|1) slice that should be pre-processed by contour() to contain just a single contour.

  • raise_exception (bool) – Whether or not to raise ComputeCircumferenceOfInvalidSlice. Defaults to True and should be False only for unit testing purposes.

Raises:

exceptions.ComputeCircumferenceOfInvalidSlice – If >= constants.NUM_CONTOURS_IN_INVALID_SLICE contours are detected.

Returns:

Arc length of parent contour

Return type:

float

NeuroRuler.utils.imgproc.length_of_contour_with_spacing(binary_contour_slice: ndarray, x_spacing: float, y_spacing: float) float[source]

Given a 2D binary slice (i.e., RV of contour()), return arc length of parent contour, accounting for x_spacing and y_spacing values. MAKE SURE x_spacing and y_spacing values are passed in the correct order! The binary slice passed into this function should be processed by contour() to guarantee an accurate result. Slices for which circumference is calculated are always parallel to z, so the z spacing value is always ignored. This function assumes the contour is a closed curve.

Parameters:
  • binary_contour_slice (np.ndarray) –

  • x_spacing (float) –

  • y_spacing (float) –

Raise:

exceptions.ComputeCircumferenceOfInvalidSlice if contours detected >= constants.NUM_CONTOURS_IN_INVALID_SLICE

Returns:

arc length of parent contour

Return type:

float

NeuroRuler.utils.imgproc.select_largest_component(binary_slice: Image) Image[source]

Remove islands from a binary (0|1) 2D slice. Return a binary slice containing only the largest connected component.

Parameters:

binary_slice (sitk.Image) – Binary (0|1) 2D slice

Returns:

Binary (0|1) slice with only the largest connected component

Return type:

sitk.Image

NeuroRuler.utils.parser module

Parse config JSON and CLI arguments to set global settings in gui_settings.py and cli_settings.py.

NeuroRuler.utils.parser.JSON_SETTINGS: dict = {}

Dict of settings resulting from JSON file parsing. Global within this file.

NeuroRuler.utils.parser.iterable_of_str_to_str(iterable: list[str] | tuple[str], use_or: bool = True) str[source]

Convert iterable of str to str, with some formatting.

For example, (‘.nii.gz’, ‘.nii’, ‘.nrrd’) becomes ‘.nii.gz, .nii, [or] .nrrd’.

Parameters:
  • iterable (Union[list[str], tuple[str]]) –

  • use_or (bool) – Whether to use ‘or’ in the string

Returns:

String representation of tuple

Return type:

str

NeuroRuler.utils.parser.load_json(path: Path) dict[source]

Load config.json file, ignoring comments //.

Source: https://github.com/Alexhuszagh/BreezeStyleSheets/blob/main/configure.py#L82

Parameters:

path (Path) – path to JSON configuration file

Returns:

JSON represented as dict

Return type:

dict

NeuroRuler.utils.parser.parse_bool(field: str) bool[source]

For bool field “True” or “False”, return the bool.

Parameters:

field (str) – JSON field

Raise:

exceptions.InvalidJSONField if s is not “True” or “False”

Returns:

True or False

Return type:

bool

NeuroRuler.utils.parser.parse_cli() None[source]

Parse CLI (non-GUI) args and set settings in cli_settings.py.

Returns:

None

NeuroRuler.utils.parser.parse_cli_config() None[source]

Parse CLI JSON config and set user settings in gui_settings.py.

load_json will load constants.JSON_CLI_CONFIG_PATH.

NeuroRuler.utils.parser.parse_float(field: str) float[source]

For float field, return float.

Parameters:

field (str) – JSON field

Raise:

exceptions.InvalidJSONField

Returns:

Return type:

float

NeuroRuler.utils.parser.parse_gui_cli() None[source]

Parse GUI CLI args and set settings in gui_settings.py.

Returns:

None

NeuroRuler.utils.parser.parse_gui_config() None[source]

Parse GUI JSON config and set user settings in gui_settings.py.

load_json will load constants.JSON_GUI_CONFIG_PATH.

NeuroRuler.utils.parser.parse_int(field: str) int[source]

For int field, return int.

Parameters:

field (str) – JSON field

Raise:

exceptions.InvalidJSONField

Returns:

Return type:

int

NeuroRuler.utils.parser.parse_main_color_from_theme_json() str[source]

Parse the main color from the theme JSON file (user_settings.THEME_NAME) in the highlight field.

Uses user_settings.THEME_NAME so must be called after parse_gui_config sets user_settings.THEME_NAME (i.e. can be called within parse_gui_config).

Returns:

main color rrggbb (hexits)

Return type:

str

NeuroRuler.utils.parser.parse_path(field: str) Path[source]

For path field, return a Path.

Parameters:

field (str) – JSON field

Raise:

exceptions.InvalidJSONField

Returns:

Return type:

Path

NeuroRuler.utils.parser.parse_str(field: str) str[source]

For str field, return the str.

Parameters:

field (``str``) – JSON field

Returns:

string

Return type:

``str``

Module contents