hazenlib ACR tasks

hazenlib.tasks.acr_geometric_accuracy task

ACR Geometric Accuracy

https://www.acraccreditation.org/-/media/acraccreditation/documents/mri/largephantomguidance.pdf

Calculates geometric accuracy for slices 1 and 5 of the ACR phantom.

This script calculates the horizontal and vertical lengths of the ACR phantom in Slice 1 in accordance with the ACR Guidance. This script calculates the horizontal, vertical and diagonal lengths of the ACR phantom in Slice 5 in accordance with the ACR Guidance. The average distance measurement error, maximum distance measurement error and coefficient of variation of all distance measurements is reported as recommended by IPEM Report 112, “Quality Control and Artefacts in Magnetic Resonance Imaging”.

This is done by first producing a binary mask for each respective slice. Line profiles are drawn with aid of rotation matrices around the centre of the test object to determine each respective length. The results are also visualised.

Created by Yassine Azma yassine.azma@rmh.nhs.uk

18/11/2022

class hazenlib.tasks.acr_geometric_accuracy.ACRGeometricAccuracy(**kwargs)[source]

Bases: HazenTask

Geometric accuracy measurement class for DICOM images of the ACR phantom.

run() dict[source]

Main function for performing geometric accuracy measurement using the first and fifth slices from the ACR phantom image set.

Returns

results are returned in a standardised dictionary structure specifying the task name, input DICOM Series Description + SeriesNumber + InstanceNumber, task measurement key-value pairs, optionally path to the generated images for visualisation.

Return type

dict

get_geometric_accuracy(slice_index)[source]

Measure geometric accuracy for input slice.

Creates a mask over the phantom from the pixel array of the DICOM image. Uses the centre and shape of the mask to determine horizontal and vertical lengths, and also diagonal lengths in slice 5.

Parameters

slice_index (int) – the index of the slice position, for example slice 5 is at index 4.

Returns

horizontal and vertical distances.

Return type

tuple of float

diagonal_lengths(img, cxy, slice_index)[source]

Measure diagonal lengths.

Rotates the pixel array by 45° and measures the horizontal and vertical distances.

Parameters
  • img (np.ndarray) – pixel array of the slice (dcm.pixel_array).

  • cxy (tuple) – x,y coordinates of the circle centre.

  • slice_index (int) – index of the slice number.

Returns

for both the south-east (SE) diagonal length and the south-west (SW) diagonal length:

”start” and “end” indicate the start and end x and y positions of the lengths; “Extent” is the distance (in pixels) of the lengths; “Distance” is “Extent” with factors applied to convert from pixels to mm.

Return type

tuple of dictionaries

static get_distortion_metrics(L)[source]

Calculates the mean error, the maximum error and the coefficient of variation between the horizontal and vertical distances measured on slices 1 and 5.

Parameters

L (tuple) – horizontal and vertical distances from slices 1 and 5.

Returns

mean_err, max_err, cov_l

Return type

tuple of floats

hazenlib.tasks.acr_ghosting task

ACR Ghosting

https://www.acraccreditation.org/-/media/acraccreditation/documents/mri/largephantomguidance.pdf

Calculates the percent-signal ghosting for slice 7 of the ACR phantom.

This script calculates the percentage signal ghosting in accordance with the ACR Guidance. This is done by first defining a large 200cm2 ROI before placing 10cm2 elliptical ROIs outside the phantom along the cardinal directions. The results are also visualised.

Created by Yassine Azma yassine.azma@rmh.nhs.uk

14/11/2022

class hazenlib.tasks.acr_ghosting.ACRGhosting(**kwargs)[source]

Bases: HazenTask

Ghosting measurement class for DICOM images of the ACR phantom.

run() dict[source]

Main function for performing ghosting measurement using slice 7 from the ACR phantom image set.

Returns

results are returned in a standardised dictionary structure specifying the task name, input DICOM Series Description + SeriesNumber + InstanceNumber, task measurement key-value pairs, optionally path to the generated images for visualisation.

Return type

dict

get_signal_ghosting(dcm)[source]

Calculate the percentage signal ghosting (PSG).

Sample signal intensity from ellipses outside the phantom in four directions and calculate the mean signal value within each. Percentage signal ghosting (PSG) is then expressed as the mean signal in these four ROIs as a percentage of the mean signal in a ROI in the centre of the phantom.

Parameters

dcm (pydicom.Dataset) – DICOM image object.

Returns

percentage ghosting value.

Return type

float

hazenlib.tasks.acr_slice_position task

ACR Slice Position

https://www.acraccreditation.org/-/media/acraccreditation/documents/mri/largephantomguidance.pdf

Calculates the bar length difference for slices 1 and 11 of the ACR phantom.

This script calculates the bar length difference in accordance with the ACR Guidance. Line profiles are drawn vertically through the left and right wedges. The right wedge’s line profile is shifted and wrapped round before being subtracted from the left wedge’s line profile, e.g.:

Right line profile: [1, 2, 3, 4, 5]

Right line profile wrapped round by 1: [2, 3, 4, 5, 1]

This wrapping process, from hereon referred to as ‘circular shifting’, is then used for subtractions.

The shift used to produce the minimum difference between the circularly shifted right line profile and the static left one is used to determine the bar length difference, which is twice the slice position displacement.

The results are also visualised.

Created by Yassine Azma yassine.azma@rmh.nhs.uk

28/12/2022

class hazenlib.tasks.acr_slice_position.ACRSlicePosition(**kwargs)[source]

Bases: HazenTask

Slice position measurement class for DICOM images of the ACR phantom.

run() dict[source]

Main function for performing slice position measurement using the first and last slices from the ACR phantom image set.

Returns

results are returned in a standardised dictionary structure specifying the task name, input DICOM Series Description + SeriesNumber + InstanceNumber, task measurement key-value pairs, optionally path to the generated images for visualisation

Return type

dict

find_wedges(img, mask)[source]

Find wedges in the pixel array.

Investigates the top half of the phantom to locate where the wedges pass through the slice, and calculates the co-ordinates of these locations.

Parameters
  • img (np.ndarray) – dcm.pixel_array

  • mask (np.ndarray) – dcm.pixel_array of the image mask

Returns

of x and y coordinates of wedges.

Return type

tuple of tuples

get_slice_position(dcm)[source]

Measure slice position.

Locates the two opposing wedges and calculates the height difference.

Parameters

dcm (pydicom.Dataset) – DICOM image object.

Returns

bar length difference.

Return type

float

hazenlib.tasks.acr_slice_thickness task

ACR Slice Thickness

Calculates the slice thickness for slice 1 of the ACR phantom.

The ramps located in the middle of the phantom are located and line profiles are drawn through them. The full-width half-maximum (FWHM) of each ramp is determined to be their length. Using the formula described in the ACR guidance, the slice thickness is then calculated.

Created by Yassine Azma yassine.azma@rmh.nhs.uk

31/01/2022

class hazenlib.tasks.acr_slice_thickness.ACRSliceThickness(**kwargs)[source]

Bases: HazenTask

Slice width measurement class for DICOM images of the ACR phantom.

run() dict[source]

Main function for performing slice width measurement using slice 1 from the ACR phantom image set.

Returns

results are returned in a standardised dictionary structure specifying the task name, input DICOM Series Description + SeriesNumber + InstanceNumber, task measurement key-value pairs, optionally path to the generated images for visualisation.

Return type

dict

find_ramps(img, centre)[source]

Find ramps in the pixel array and return the co-ordinates of their location.

Parameters
  • img (np.ndarray) – dcm.pixel_array

  • centre (list) – x,y coordinates of the phantom centre

Returns

x and y coordinates of ramp.

Return type

tuple

FWHM(data)[source]

Calculate full width at half maximum of the line profile.

Parameters

data (np.ndarray) – slice profile curve.

Returns

co-ordinates of the half-maximum points on the line profile.

Return type

tuple

get_slice_thickness(dcm)[source]

Measure slice thickness.

Identify the ramps, measure the line profile, measure the FWHM, and use this to calculate the slice thickness.

Parameters

dcm (pydicom.Dataset) – DICOM image object.

Returns

measured slice thickness.

Return type

float

hazenlib.tasks.acr_snr task

ACR SNR

Calculates the SNR for slice 7 (the uniformity slice) of the ACR phantom.

This script utilises the smoothed subtraction method described in McCann 2013 [1], and a standard subtraction SNR.

Created by Neil Heraghty (Adapted by Yassine Azma, yassine.azma@rmh.nhs.uk)

09/01/2023

[1] McCann, A. J., Workman, A., & McGrath, C. (2013). A quick and robust method for measurement of signal-to-noise ratio in MRI. Physics in Medicine & Biology, 58(11), 3775.

class hazenlib.tasks.acr_snr.ACRSNR(**kwargs)[source]

Bases: HazenTask

Signal-to-noise ratio measurement class for DICOM images of the ACR phantom.

run() dict[source]

Main function for performing SNR measurement using slice 7 from the ACR phantom image set. Performs either smoothing or subtraction method depending on user-provided input.

Notes

Uses the smoothing method by default or the subtraction method if a second set of images are provided (using the –subtract option with dataset in a separate folder).

Returns

results are returned in a standardised dictionary structure specifying the task name, input DICOM Series Description + SeriesNumber + InstanceNumber, task measurement key-value pairs, optionally path to the generated images for visualisation.

Return type

dict

get_normalised_snr_factor(dcm, measured_slice_width=None) float[source]

Calculates the normalisation factor to be applied to the SNR in order to obtain the absolute SNR (ASNR). The normalisation factor depends on voxel size, bandwidth, number of averages and number of phase encoding steps.

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

  • measured_slice_width (float, optional) – Provide the true slice width for the set of images. Defaults to None.

Returns

normalisation factor.

Return type

float

filtered_image(dcm: Dataset) array[source]

Apply filtering to a pixel array (image), as per the single image SNR method outlined in McCann et al, 2013.

Notes

Performs a 2D convolution (for filtering images), using uniform_filter (SciPy function).

Parameters

dcm (pydicom.Dataset) – DICOM image object.

Returns

pixel array of the filtered image.

Return type

np.array

get_noise_image(dcm: Dataset) array[source]

Get a noise image when only one set of DICOM data is available.

Notes

Separates the image noise by smoothing the pixel array and subtracting the smoothed pixel array from the original, leaving only the noise.

Parameters

dcm (pydicom.Dataset) – DICOM image object

Returns

pixel array representing the image noise.

Return type

np.array

get_roi_samples(ax, dcm: Dataset, centre_col: int, centre_row: int) list[source]

Takes the pixel array and divides it into several rectangular regions of interest (ROIs). If ‘ax’ is provided, then a plot of the ROIs is generated.

Parameters
  • ax (matplotlib.pyplot.subplots) – matplotlib axis for visualisation.

  • dcm (pydicom.Dataset or np.ndarray) – DICOM image object, or its pixel array.

  • centre_col (int) – x coordinate of the centre.

  • centre_row (int) – y coordinate of the centre.

Returns

subsets of the original pixel array.

Return type

list of np.array

snr_by_smoothing(dcm: Dataset, measured_slice_width=None) float[source]

Obtains a noise image using the single-image smoothing technique. Generates a ROI within the phantom region of the pixel array. Then measures the mean signal within the ROI on the original pixel array, and the standard deviation within the ROI on the noise image. Calculates SNR using these values and multiplies the SNR by the normalisation factor.

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

  • measured_slice_width (float, optional) – Provide the true slice width for the set of images. Defaults to None.

Returns

normalised_snr.

Return type

float

snr_by_subtraction(dcm1: Dataset, dcm2: Dataset, measured_slice_width=None) float[source]

Calculates signal to noise ratio using the two image subtraction method. Obtains a noise image by subtracting the two pixel arrays. Obtains ROIs within the phantom region of the pixel arrays. Calculates the mean within the ROI on one of the pixel arrays, and the standard deviation within the ROIs on the noise image. Calculates the SNR with these measurements and multiplies by the normalisation factor.

Parameters
  • dcm1 (pydicom.Dataset) – DICOM image object to calculate signal.

  • dcm2 (pydicom.Dataset) – DICOM image object to calculate noise.

  • measured_slice_width (float, optional) – Provide the true slice width for the set of images. Defaults to None.

Returns

normalised_snr.

Return type

float

hazenlib.tasks.acr_spatial_resolution task

ACR Spatial Resolution (MTF)

https://www.acraccreditation.org/-/media/acraccreditation/documents/mri/largephantomguidance.pdf

Calculates the effective resolution (MTF50) for slice 1 for the ACR phantom. This is done in accordance with the methodology described in Section 3 of the following paper:

https://opg.optica.org/oe/fulltext.cfm?uri=oe-22-5-6040&id=281325

WARNING: The phantom must be slanted for valid results to be produced. This test is not within the scope of ACR guidance.

This script first identifies the rotation angle of the ACR phantom using slice 1. It provides a warning if the slanted angle is less than 3 degrees.

The location of the ramps within the slice thickness are identified and a square ROI is selected around the anterior edge of the slice thickness insert.

A rudimentary edge response function is generated based on the edge within the ROI to provide initialisation values for the 2D normal cumulative distribution fit of the ROI.

The edge is then super-sampled in the direction of the bright-dark transition of the edge and binned at right angles based on the edge slope determined from the 2D Normal CDF fit of the ROI to obtain the edge response function.

This super-sampled ERF is then fitted using a weighted sigmoid function. The raw data and this fit are then used to determine the LSF and the subsequent MTF. The MTF50 for both raw and fitted data are reported.

The results are also visualised.

Created by Yassine Azma yassine.azma@rmh.nhs.uk

22/02/2023

class hazenlib.tasks.acr_spatial_resolution.ACRSpatialResolution(**kwargs)[source]

Bases: HazenTask

Spatial resolution measurement class for DICOM images of the ACR phantom

Inherits from HazenTask class

run() dict[source]

Main function for performing spatial resolution measurement using slice 1 from the ACR phantom image set

Returns

results are returned in a standardised dictionary structure specifying the task name, input DICOM Series Description + SeriesNumber + InstanceNumber, task measurement key-value pairs, optionally path to the generated images for visualisation

Return type

dict

y_position_for_ramp(img, cxy)[source]

Identify the y coordinate of the ramp

Parameters
  • img (np.ndarray) – dcm.pixelarray

  • cxy (tuple) – x,y coordinates of the object centre

Returns

y coordinate of the ramp min

Return type

float

crop_image(img, x, y, width)[source]

Return a rectangular subset of a pixel array

Parameters
  • img (np.ndarray) – dcm.pixelarray

  • x (int) – x coordinate of centre

  • y (int) – y coordinate of centre

  • width (int) – size of the array top subset

Returns

subset of a pixel array with given width

Return type

np.ndarray

get_edge_type(crop_img)[source]

Determine direction of ramp edge

Parameters

crop_img (np.ndarray) – cropped pixel array ~ subset of the image

Returns

vertical/horizontal and up/down or left/rigtward

Return type

tuple of string

edge_location_for_plot(crop_img, edge_type)[source]

Determine the location of the edge so it can be visualised

Parameters
  • crop_img (np.array) – cropped pixel array ~ subset of the image

  • edge_type (tuple) – vertical/horizontal and up/down or left/rigtward

Returns

mask array for edge location

Return type

np.array

fit_normcdf_surface(crop_img, edge_type, direction)[source]

Fit normalised CDF? to surface

Parameters
  • crop_img (np.array) – cropped pixel array ~ subset of the image

  • edge_type (string) – vertical/horizontal

  • direction (string) – up/down or left/rigtward

Returns

slope, surface

Return type

tuple of floats

sample_erf(crop_img, slope, edge_type)[source]

_summary_

Parameters
  • crop_img (np.array) – cropped pixel array ~ subset of the image

  • slope (float) – value of slope of edge

  • edge_type (string) – vertical/horizontal

Returns

_description_

Return type

np.array

fit_erf(erf)[source]

Fit ERF

Parameters

erf (np.array) – _description_

Returns

_description_

Return type

_type_

calculate_MTF(erf)[source]

Calculate MTF

Parameters

erf (np.array) – array of ?

Returns

freq, lsf, MTF

Return type

tuple

identify_MTF50(freq, MTF)[source]

Calculate effective resolution

Parameters
  • freq (float or int) – _description_

  • MTF (float or int) – _description_

Returns

_description_

Return type

float

get_mtf50(dcm)[source]

_summary_

Parameters

dcm (pydicom.Dataset) – DICOM image object

Returns

_description_

Return type

tuple

hazenlib.tasks.acr_uniformity task

ACR Uniformity

https://www.acraccreditation.org/-/media/acraccreditation/documents/mri/largephantomguidance.pdf

Calculates the percentage integral uniformity for slice 7 of the ACR phantom.

This script calculates the percentage integral uniformity in accordance with the ACR Guidance. This is done by first defining a large 200cm2 ROI before placing 1cm2 ROIs at every pixel within the large ROI. At each point, the mean of the 1cm2 ROI is calculated. The ROIs with the maximum and minimum mean value are used to calculate the integral uniformity. The results are also visualised.

Created by Yassine Azma yassine.azma@rmh.nhs.uk

13/01/2022

class hazenlib.tasks.acr_uniformity.ACRUniformity(**kwargs)[source]

Bases: HazenTask

Uniformity measurement class for DICOM images of the ACR phantom.

run() dict[source]

Main function for performing uniformity measurement using slice 7 from the ACR phantom image set.

Returns

results are returned in a standardised dictionary structure specifying the task name, input DICOM Series Description + SeriesNumber + InstanceNumber, task measurement key-value pairs, optionally path to the generated images for visualisation

Return type

dict

get_integral_uniformity(dcm)[source]

Calculates the percent integral uniformity (PIU) of a DICOM pixel array.

Iterates with a ~1 cm^2 ROI through a ~200 cm^2 ROI inside the phantom region, and calculates the mean non-zero pixel value inside each ~1 cm^2 ROI.

The PIU is defined as: PIU = 100 * (1 - (max - min) / (max + min)), where

‘max’ and ‘min’ represent the maximum and minimum of the mean non-zero pixel values of each ~1 cm^2 ROI.

Parameters

dcm (pydicom.Dataset) – DICOM image object to calculate uniformity from.

Returns

value of integral uniformity.

Return type

float