hazenlib package

Core functions

Welcome to the hazen Command Line Interface

The following Tasks are available: - ACR phantom: acr_snr | acr_slice_position | acr_slice_thickness | acr_spatial_resolution | acr_uniformity | acr_ghosting | acr_geometric_accuracy - MagNET Test Objects: snr | snr_map | slice_position | slice_width | spatial_resolution | uniformity | ghosting - Caliber phantom: relaxometry

All tasks can be run by executing ‘hazen <task> <folder>’. Optional flags are available for the Tasks; see the General Options section below. The ‘acr_snr’ and ‘snr’ Tasks have additional optional flags, also detailed below.

Usage:

hazen <task> <folder> [options] hazen snr <folder> [–measured_slice_width=<mm>] [–coil=<head or body>] [options] hazen acr_snr <folder> [–measured_slice_width=<mm>] [–subtract=<folder2>] [options] hazen relaxometry <folder> –calc=<T1> –plate_number=<4> [options]

hazen -h | –help hazen –version

General Options: available for all Tasks
--report

Whether to generate visualisation of the measurement steps.

--output=<path>

Provide a folder where report images are to be saved.

--verbose

Whether to provide additional metadata about the calculation in the result (slice position and relaxometry tasks)

--log=<level>

Set the level of logging based on severity. Available levels are “debug”, “warning”, “error”, “critical”, with “info” as default.

acr_snr & snr Task options:
--measured_slice_width=<mm>

Provide a slice width to be used for SNR measurement, by default it is parsed from the DICOM (optional for acr_snr and snr)

--subtract=<folder2>

Provide a second folder path to calculate SNR by subtraction for the ACR phantom (optional for acr_snr)

relaxometry Task options:
--calc=<n>

Choose ‘T1’ or ‘T2’ for relaxometry measurement (required)

--plate_number=<n>

Which plate to use for measurement: 4 or 5 (required)

hazenlib.init_task(selected_task, files, report, report_dir, **kwargs)[source]

Initialise object of the correct HazenTask class

Parameters
  • selected_task (string) – name of task script/module to load

  • files (list) – list of filepaths to DICOM images

  • report (bool) – whether to generate report images

  • report_dir (string) – path to folder to save report images to

  • kwargs – any other key word arguments

Returns

an object of the specified HazenTask class

hazenlib.main()[source]

Main entrypoint to hazen

Task-specific functions

Utility functions:

hazenlib.ACRObject

class hazenlib.ACRObject.ACRObject(dcm_list)[source]

Bases: object

Base class for performing tasks on image sets of the ACR phantom.

acquired following the ACR Large phantom guidelines

sort_dcms(dcm_list)[source]

Sort a stack of DICOM images based on slice position.

Parameters

dcm_list (list) – list of pyDICOM image objects

Returns

sorted list of pydicom.Dataset objects

Return type

list

order_phantom_slices(dcm_list)[source]

Determine slice order based on the detection of the small circle in the first slice # or an LR orientation swap is required.

# This function analyzes the given set of images and their associated DICOM objects to determine if any # adjustments are needed to restore the correct slice order and view orientation.

Parameters

dcm_list (list) – list of pyDICOM image objects

Returns

sorted list of pydicom.Dataset objects corresponding to ordered phantom slices

Return type

list

static determine_rotation(img)[source]

Determine the rotation angle of the phantom using edge detection and the Hough transform.

Parameters

img (np.ndarray) – pixel array of a DICOM object

Returns

The rotation angle in degrees.

Return type

float

rotate_images(dcm_list, rot_angle)[source]

Rotate the images by a specified angle. The value range and dimensions of the image are preserved.

Parameters
  • dcm_list (list) – list of pyDICOM image objects

  • rot_angle (float) – angle in degrees that image (pixel array) should be rotated by

Returns

The rotated images.

Return type

list of np.ndarray

static find_phantom_center(img, dx, dy)[source]

Find the center of the ACR phantom in a given slice (pixel array)

using the Hough circle detector on a blurred image.

Parameters

img (np.ndarray) – pixel array of the DICOM image.

Returns

(x, y) coordinates of the center of the image

Return type

tuple of ints

get_mask_image(image, mag_threshold=0.07, open_threshold=500)[source]

Create a masked pixel array.

Mask an image by magnitude threshold before applying morphological opening to remove small unconnected features. The convex hull is calculated in order to accommodate for potential air bubbles.

Parameters
  • image (np.ndarray) – pixel array of the dicom

  • mag_threshold (float, optional) – magnitude threshold. Defaults to 0.07.

  • open_threshold (int, optional) – open threshold. Defaults to 500.

Returns

the masked image

Return type

np.ndarray

static circular_mask(centre, radius, dims)[source]

Generates a circular mask using given centre coordinates and a given radius. Generates a linspace grid the size of the given dimensions and checks whether each point on the linspace grid is within the desired radius from the given centre coordinates. Each linspace value within the chosen radius then becomes part of the mask.

Parameters
  • centre (tuple) – centre coordinates of the circular mask.

  • radius (int) – radius of the circular mask.

  • dims (tuple) – dimensions to create the base linspace grid from.

Returns

A sorted stack of images, where each image is represented as a 2D numpy array.

Return type

np.ndarray

measure_orthogonal_lengths(mask, slice_index)[source]

Compute the horizontal and vertical lengths of a mask, based on the centroid.

Parameters

mask (np.ndarray) – Boolean array of the image where pixel values meet threshold

Returns

a dictionary with the following:
’Horizontal Start’ | ‘Vertical Start’tuple of int

Horizontal/vertical starting point of the object.

’Horizontal End’ | ‘Vertical End’tuple of int

Horizontal/vertical ending point of the object.

’Horizontal Extent’ | ‘Vertical Extent’np.ndarray of int

Indices of the non-zero elements of the horizontal/vertical line profile.

’Horizontal Distance’ | ‘Vertical Distance’float

The horizontal/vertical length of the object.

Return type

dict

static rotate_point(origin, point, angle)[source]

Compute the horizontal and vertical lengths of a mask, based on the centroid.

Parameters
  • origin (tuple) – The coordinates of the point around which the rotation is performed.

  • point (tuple) – The coordinates of the point to rotate.

  • angle (int) – Angle in degrees.

Returns

Floats representing the x and y coordinates of the input point after being rotated around an origin.

Return type

tuple of float

static find_n_highest_peaks(data, n, height=1)[source]

Find the indices and amplitudes of the N highest peaks within a 1D array.

Parameters
  • data (np.ndarray) – pixel array containing the data to perform peak extraction on

  • n (int) – The coordinates of the point to rotate

  • height (int, optional) – The amplitude threshold for peak identification. Defaults to 1.

Returns

peak_locs: A numpy array containing the indices of the N highest peaks identified.

peak_heights: A numpy array containing the amplitudes of the N highest peaks identified.

Return type

tuple of np.ndarray

hazenlib.HazenTask

HazenTask.py

class hazenlib.HazenTask.HazenTask(input_data: list, report: bool = False, report_dir=None, **kwargs)[source]

Bases: object

Base class for performing tasks on image sets

init_result_dict() dict[source]

Initialise the dictionary that holds measurement results and input description

Returns

holds measurement results and task input description

Return type

dict

img_desc(dcm, properties=None) str[source]

Obtain values from the DICOM header to identify input series

Parameters
  • dcm (pydicom.Dataset) – DICOM image object

  • properties (list, optional) – list of DICOM header field names supported by pydicom that shuld be used to generate sereis identifier. Defaults to None.

Returns

contatenation of the specified DICOM header property values

Return type

str

hazenlib.exceptions

Application-specific errors

exception hazenlib.exceptions.ShapeError(shape, msg=None)[source]

Bases: Exception

Base exception for shapes.

exception hazenlib.exceptions.ShapeDetectionError(shape, msg=None)[source]

Bases: ShapeError

Shape not found

exception hazenlib.exceptions.MultipleShapesError(shape, msg=None)[source]

Bases: ShapeDetectionError

Shape not found

exception hazenlib.exceptions.ArgumentCombinationError(msg='Invalid combination of arguments.')[source]

Bases: Exception

Argument combination not valid.

hazenlib.logger

hazenlib.logger.configure_logger()[source]

Configure logger for the standard out (command line) stream and save logs to file

hazenlib.utils

hazenlib.utils.get_dicom_files(folder: str, sort=False) list[source]

Collect files in the folder into a list if they are parsable DICOMs

Parameters
  • folder (str) – path to folder

  • sort (bool, optional) – whether to sort file list based on InstanceNumber. Defaults to False.

Returns

full path to DICOM files found within a folder

Return type

list

hazenlib.utils.is_dicom_file(filename)[source]

Check if file is a DICOM file, using the the first 128 bytes are preamble the next 4 bytes should contain DICM otherwise it is not a dicom

Parameters

filename (str) – path to file to be checked for the DICM header block

Returns

True or False whether file is a DICOM

Return type

bool

hazenlib.utils.is_enhanced_dicom(dcm: Dataset) bool[source]

Check if file is an enhanced DICOM file

Parameters

dcm (pydicom.Dataset) – DICOM image object

Raises

Exception – Unrecognised_SOPClassUID

Returns

True or False whether file is an enhanced DICOM

Return type

bool

hazenlib.utils.get_manufacturer(dcm: Dataset) str[source]

Get the manufacturer field from the DICOM header

Parameters

dcm (pydicom.Dataset) – DICOM image object

Raises

Exception – _description_

Returns

manufacturer of the scanner used to obtain the DICOM image

Return type

str

hazenlib.utils.get_average(dcm: Dataset) float[source]

Get the NumberOfAverages field from the DICOM header

Parameters

dcm (pydicom.Dataset) – DICOM image object

Returns

value of the NumberOfAverages field from the DICOM header

Return type

float

hazenlib.utils.get_bandwidth(dcm: Dataset) float[source]

Get the PixelBandwidth field from the DICOM header

Parameters

dcm (pydicom.Dataset) – DICOM image object

Returns

value of the PixelBandwidth field from the DICOM header

Return type

float

hazenlib.utils.get_num_of_frames(dcm: Dataset) int[source]

Get the number of frames from the DICOM pixel_array

Parameters

dcm (pydicom.Dataset) – DICOM image object

Returns

value of the PixelBandwidth field from the DICOM header

Return type

float

hazenlib.utils.get_slice_thickness(dcm: Dataset) float[source]

Get the SliceThickness field from the DICOM header

Parameters

dcm (pydicom.Dataset) – DICOM image object

Returns

value of the SliceThickness field from the DICOM header

Return type

float

hazenlib.utils.get_pixel_size(dcm: ~pydicom.dataset.Dataset) -> (<class 'float'>, <class 'float'>)[source]

Get the PixelSpacing field from the DICOM header

Parameters

dcm (pydicom.Dataset) – DICOM image object

Returns

x and y values of the PixelSpacing field from the DICOM header

Return type

tuple of float

hazenlib.utils.get_TR(dcm: Dataset) float[source]

Get the RepetitionTime field from the DICOM header

Parameters

dcm (pydicom.Dataset) – DICOM image object

Returns

value of the RepetitionTime field from the DICOM header, or defaults to 1000

Return type

float

hazenlib.utils.get_rows(dcm: Dataset) float[source]

Get the Rows field from the DICOM header

Parameters

dcm (pydicom.Dataset) – DICOM image object

Returns

value of the Rows field from the DICOM header, or defaults to 256

Return type

float

hazenlib.utils.get_columns(dcm: Dataset) float[source]

Get the Columns field from the DICOM header

Parameters

dcm (pydicom.Dataset) – DICOM image object

Returns

value of the Columns field from the DICOM header, or defaults to 256

Return type

float

hazenlib.utils.get_field_of_view(dcm: Dataset)[source]

Get Field of View value from DICOM header depending on manufacturer encoding

Parameters

dcm (pydicom.Dataset) – DICOM image object

Raises

NotImplementedError – Manufacturer not GE, Siemens, Toshiba or Philips so FOV cannot be calculated.

Returns

value of the Field of View (calculated as Columns * PixelSpacing[0])

Return type

float

hazenlib.utils.get_image_orientation(iop)[source]

From http://dicomiseasy.blogspot.com/2013/06/getting-oriented-using-image-plane.html

Parameters

iop (list) – values of dcm.ImageOrientationPatient - list of float

Returns

Sagittal, Coronal or Transverse

Return type

str

hazenlib.utils.determine_orientation(dcm_list)[source]

Determine the phantom orientation based on DICOM metadata from a list of DICOM images.

Note

The ImageOrientationPatient tag is a record of the orientation of the imaging volume which contains the phantom. The orientation of the imaging volume MAY NOT align with the true phantom orientation.

Parameters

dcm_list (list) – list of pyDICOM image objects.

Returns

“saggital”, “coronal”, “axial”, or “unexpected” orientation.

list of the changing ImagePositionPatient values.

Return type

tuple (string, list)

hazenlib.utils.rescale_to_byte(array)[source]

WARNING: This function normalises/equalises the histogram. This might have unintended consequences.

Parameters

array (np.array) – dcm.pixel_array

Returns

normalised pixel values as 8-bit (byte) integer

Return type

np.array

hazenlib.utils.detect_circle(img, dx)[source]
class hazenlib.utils.Rod(x, y)[source]

Bases: object

Class for rods detected in the image

property centroid
class hazenlib.utils.ShapeDetector(arr)[source]

Bases: object

Class for the detection of shapes in pixel arrays This class is largely adapted from https://www.pyimagesearch.com/2016/02/08/opencv-shape-detection/

find_contours()[source]

Find contours in pixel array

detect()[source]

Detect specified shapes in pixel array

Currently supported shapes:
  • circle

  • triangle

  • rectangle

  • pentagon

get_shape(shape)[source]

Identify shapes in pixel array

Parameters

shape (_type_) – _description_

Raises
  • exc.ShapeDetectionError – ensure that only expected shapes are detected

  • exc.MultipleShapesError – ensure that only 1 shape is detected

Returns

varies depending on shape detected
  • circle: x, y, r - corresponding to x,y coords of centre and radius

  • rectangle/square: (x, y), size, angle - corresponding to x,y coords of centre, size (tuple) and angle in degrees

Return type

tuple