Utilities#
Test datasets#
A range of small test datasets to generate and use
A set of simulated volumes and CT data#
- class cil.utilities.dataexample.SIMULATED_CONE_BEAM_DATA[source]#
- class cil.utilities.dataexample.SIMULATED_PARALLEL_BEAM_DATA[source]#
A CT dataset from the Diamond Light Source#
Simulated image data#
- class cil.utilities.dataexample.TestData(data_dir)[source]#
Class to return test data
provides 6 dataset: BOAT = ‘boat.tiff’ CAMERA = ‘camera.png’ PEPPERS = ‘peppers.tiff’ RESOLUTION_CHART = ‘resolution_chart.tiff’ SIMPLE_PHANTOM_2D = ‘hotdog’ SHAPES = ‘shapes.png’ RAINBOW = ‘rainbow.png’
- load(which, size=None, scale=(0, 1), **kwargs)[source]#
Return a test data of the requested image
- Parameters:
which (str) – Image selector: BOAT, CAMERA, PEPPERS, RESOLUTION_CHART, SIMPLE_PHANTOM_2D, SHAPES, RAINBOW
size (tuple, optional) – The size of the returned ImageData. If None default will be used for each image type
scale (tuple, optional) – The scale of the data values
- Returns:
The simulated spheres volume
- Return type:
- static random_noise(image, mode='gaussian', seed=None, clip=True, **kwargs)[source]#
Function to add noise to input image
- Parameters:
image – input dataset, DataContainer of numpy.ndarray
mode – type of noise
seed – seed for random number generator
clip – should clip the data.
- static scikit_random_noise(image, mode='gaussian', seed=None, clip=True, **kwargs)[source]#
Function to add random noise of various types to a floating-point image. :param image: Input image data. Will be converted to float. :type image: ndarray :param mode: One of the following strings, selecting the type of noise to add:
‘gaussian’ Gaussian-distributed additive noise.
- ‘localvar’ Gaussian-distributed additive noise, with specified
local variance at each point of image.
‘poisson’ Poisson-distributed noise generated from the data.
‘salt’ Replaces random pixels with 1.
- ‘pepper’ Replaces random pixels with 0 (for unsigned images) or
-1 (for signed images).
- ‘s&p’ Replaces random pixels with either 1 or low_val, where
low_val is 0 for unsigned images or -1 for signed images.
- ‘speckle’ Multiplicative noise using out = image + n*image, where
n is uniform noise with specified mean & variance.
- Parameters:
seed (int, optional) – If provided, this will set the random seed before generating noise, for valid pseudo-random comparisons.
clip (bool, optional) – If True (default), the output will be clipped after noise applied for modes ‘speckle’, ‘poisson’, and ‘gaussian’. This is needed to maintain the proper image data range. If False, clipping is not applied, and the output may extend beyond the range [-1, 1].
mean (float, optional) – Mean of random distribution. Used in ‘gaussian’ and ‘speckle’. Default : 0.
var (float, optional) – Variance of random distribution. Used in ‘gaussian’ and ‘speckle’. Note: variance = (standard deviation) ** 2. Default : 0.01
local_vars (ndarray, optional) – Array of positive floats, same shape as image, defining the local variance at every image point. Used in ‘localvar’.
amount (float, optional) – Proportion of image pixels to replace with noise on range [0, 1]. Used in ‘salt’, ‘pepper’, and ‘salt & pepper’. Default : 0.05
salt_vs_pepper (float, optional) – Proportion of salt vs. pepper noise for ‘s&p’ on range [0, 1]. Higher values represent more salt. Default : 0.5 (equal amounts)
- Returns:
out – Output floating-point image data on range [0, 1] or [-1, 1] if the input image was unsigned or signed, respectively.
- Return type:
ndarray
Notes
Speckle, Poisson, Localvar, and Gaussian noise may generate noise outside the valid image range. The default is to clip (not alias) these values, but they may be preserved by setting clip=False. Note that in this case the output may contain values outside the ranges [0, 1] or [-1, 1]. Use this option with care. Because of the prevalence of exclusively positive floating-point images in intermediate calculations, it is not possible to intuit if an input is signed based on dtype alone. Instead, negative values are explicitly searched for. Only if found does this function assume signed input. Unexpected results only occur in rare, poorly exposes cases (e.g. if all values are above 50 percent gray in a signed image). In this event, manually scaling the input to the positive domain will solve the problem. The Poisson distribution is only defined for positive integers. To apply this noise type, the number of unique values in the image is found and the next round power of two is used to scale up the floating-point result, after which it is scaled back down to the floating-point image range. To generate Poisson noise against a signed image, the signed image is temporarily converted to an unsigned image in the floating point domain, Poisson noise is generated, then it is returned to the original range.
This function is adapted from scikit-image. scikit-image/scikit-image
Copyright (C) 2019, the scikit-image team All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
- Neither the name of skimage nor the names of its contributors may be
used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS’’ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Remote data#
Remote data classes can be used to access specific datasets from zenodo. These datasets are not packaged as part of CIL, instead the download_data(data_dir) method can be used to download the dataset to a chosen data directory then loaded from that data directory using get(data_dir).
Walnut#
- class cil.utilities.dataexample.WALNUT[source]#
A microcomputed tomography dataset of a walnut from https://zenodo.org/records/4822516
Example
>>> data_dir = 'my_PC/data_folder' >>> dataexample.WALNUT.download_data(data_dir) # download the data >>> dataexample.WALNUT.get(data_dir) # load the data
- classmethod get(data_dir)[source]#
Get the microcomputed tomography dataset of a walnut from https://zenodo.org/records/4822516 This function returns the raw projection data from the .txrm file
- Parameters:
data_dir (str) – The path to the directory where the dataset is stored. Data can be downloaded with dataexample.WALNUT.download_data(data_dir)
- Returns:
The walnut dataset
- Return type:
- classmethod download_data(data_dir, prompt=True)#
Download a dataset from a remote repository
- Parameters:
data_dir (str, optional) – The path to the data directory where the downloaded data should be stored
USB#
- class cil.utilities.dataexample.USB[source]#
A microcomputed tomography dataset of a usb memory stick from https://zenodo.org/records/4822516
Example
>>> data_dir = 'my_PC/data_folder' >>> dataexample.USB.download_data(data_dir) # download the data >>> dataexample.USB.get(data_dir) # load the data
- classmethod get(data_dir)[source]#
Get the microcomputed tomography dataset of a usb memory stick from https://zenodo.org/records/4822516 This function returns the raw projection data from the .txrm file
- Parameters:
data_dir (str) – The path to the directory where the dataset is stored. Data can be downloaded with dataexample.WALNUT.download_data(data_dir)
- Returns:
The usb dataset
- Return type:
- classmethod download_data(data_dir, prompt=True)#
Download a dataset from a remote repository
- Parameters:
data_dir (str, optional) – The path to the data directory where the downloaded data should be stored
KORN#
- class cil.utilities.dataexample.KORN[source]#
A microcomputed tomography dataset of a sunflower seeds in a box from https://zenodo.org/records/6874123
Example
>>> data_dir = 'my_PC/data_folder' >>> dataexample.KORN.download_data(data_dir) # download the data >>> dataexample.KORN.get(data_dir) # load the data
- classmethod get(data_dir)[source]#
Get the microcomputed tomography dataset of a sunflower seeds in a box from https://zenodo.org/records/6874123 This function returns the raw projection data from the .xtekct file
- Parameters:
data_dir (str) – The path to the directory where the dataset is stored. Data can be downloaded with dataexample.KORN.download_data(data_dir)
- Returns:
The korn dataset
- Return type:
- classmethod download_data(data_dir, prompt=True)#
Download a dataset from a remote repository
- Parameters:
data_dir (str, optional) – The path to the data directory where the downloaded data should be stored
SANDSTONE#
- class cil.utilities.dataexample.SANDSTONE[source]#
A synchrotron x-ray tomography dataset of sandstone from https://zenodo.org/records/4912435 A small subset of the data containing selected projections and 4 slices of the reconstruction
Example
>>> data_dir = 'my_PC/data_folder' >>> dataexample.SANDSTONE.download_data(data_dir) # download the data >>> dataexample.SANDSTONE.get(data_dir) # load the data
- classmethod get(data_dir, filename)[source]#
Get the synchrotron x-ray tomography dataset of sandstone from https://zenodo.org/records/4912435 A small subset of the data containing selected projections and 4 slices of the reconstruction :param data_dir: The path to the directory where the dataset is stored. Data can be downloaded with dataexample.SANDSTONE.download_data(data_dir) :type data_dir: str :param file: The slices or projections to return, specify the path to the file within the data_dir :type file: str
- Returns:
The selected sandstone dataset
- Return type:
- classmethod download_data(data_dir, prompt=True)#
Download a dataset from a remote repository
- Parameters:
data_dir (str, optional) – The path to the data directory where the downloaded data should be stored
Image Quality metrics#
- cil.utilities.quality_measures.mse(dc1, dc2, mask=None)[source]#
Calculates the mean squared error of two images
- Parameters:
dc1 (DataContainer) – One image to be compared
dc2 (DataContainer) – Second image to be compared
mask (array or DataContainer with the same dimensions as the dc1 and dc2) – The pixelwise operation only considers values where the mask is True or NonZero.
- Return type:
A number, the mean squared error of the two images
- cil.utilities.quality_measures.mae(dc1, dc2, mask=None)[source]#
Calculates the Mean Absolute error of two images.
- Parameters:
dc1 (DataContainer) – One image to be compared
dc2 (DataContainer) – Second image to be compared
mask (array or DataContainer with the same dimensions as the dc1 and dc2) – The pixelwise operation only considers values where the mask is True or NonZero.
- Return type:
A number with the mean absolute error between the two images.
- cil.utilities.quality_measures.psnr(ground_truth, corrupted, data_range=None, mask=None)[source]#
Calculates the Peak signal to noise ratio (PSNR) between the two images.
- Parameters:
ground_truth (DataContainer) – The reference image
corrupted (DataContainer) – The image to be evaluated
data_range (scalar value, default=None) – PSNR scaling factor, the dynamic range of the images (i.e., the difference between the maximum the and minimum allowed values). We take the maximum value in the ground truth array.
mask (array or DataContainer with the same dimensions as the dc1 and dc2) – The pixelwise operation only considers values where the mask is True or NonZero..
- Return type:
A number, the peak signal to noise ration between the two images.
Visualisation#
show2D - Display 2D slices#
- class cil.utilities.display.show2D(datacontainers, title=None, slice_list=None, fix_range=False, axis_labels=None, origin='lower-left', cmap='gray', num_cols=2, size=(15, 15))[source]#
This plots 2D slices from cil DataContainer types.
Plots 1 or more 2D plots in an (n x num_cols) matrix. Can plot multiple slices from one 3D dataset, or compare multiple datasets Inputs can be single arguments or list of arguments that will be sequentially applied to subplots If no slice_list is passed a 3D dataset will display the centre slice of the outer dimension, a 4D dataset will show the centre slices of the two outer dimension.
- Parameters:
datacontainers (ImageData, AcquisitionData, list of ImageData / AcquisitionData, BlockDataContainer) – The DataContainers to be displayed
title (string, list of strings, optional) – The title for each figure
slice_list (tuple, int, list of tuples, list of ints, optional) – The slices to show. A list of integers will show slices for the outer dimension. For 3D datacontainers single slice: (direction, index). For 4D datacontainers two slices: [(direction0, index),(direction1, index)].
fix_range (boolean, tuple, list of tuples) – Sets the display range of the data. True sets all plots to the global (min, max).
axis_labels (tuple, list of tuples, optional) – The axis labels for each figure e.g. (‘x’,’y’)
origin (string, list of strings) – Sets the display origin. ‘lower/upper-left/right’
cmap (str, list or tuple of strings) – Sets the colour map of the plot (see matplotlib.pyplot). If passed a list or tuple of the length of datacontainers, allows to set a different color map for each datacontainer.
num_cols (int) – Sets the number of columns of subplots to display
size (tuple) – Figure size in inches
- Returns:
returns a matplotlib.pyplot figure object
- Return type:
matplotlib.figure.Figure
- save(filename, **kwargs)#
Saves the image as a .png using matplotlib.figure.savefig()
matplotlib kwargs can be passed, refer to documentation https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.savefig.html
show1D - Display 1D slices#
- class cil.utilities.display.show1D(data, slice_list=None, label='default', title=None, line_colours=None, line_styles=None, axis_labels=('Index', 'Value'), size=(8, 6))[source]#
This creates and displays 1D plots of pixel values by slicing multi-dimensional data.
The behaviour is as follows: if provided multiple datasets and a single slice set (see first example below), one line plot will be generated per dataset; if provided a single dataset and multiple sets of slices (see second example below), one line plot will be generated per slice set; if provided multiple datasets and multiple slice sets, the \(i\)-th set of slices will apply to the \(i\)-th dataset, with a line plot generated in each case.
- Parameters:
data (DataContainer, list of DataContainer, tuple of DataContainer) – Multi-dimensional data to be reduced to 1D.
slice_list (tuple, list of tuple or list of list of tuple, default=None) – A tuple of (dimension, coordinate) pair, or a list, or nested list, of such pairs for slicing data (default is None, which is only valid when 1D data is passed)
label ('default', str, list of str, None, default='default') – Label(s) to use in the plot’s legend. Use None to suppress legend.
title (str, default None) – A title for the plot
line_colours (str, list of str, default=None) – Colour(s) for each line plot
line_styles ({"-","--","-.",":"}, list of {"-","--","-.",":"}, default=None) – Linestyle(s) for each line plot
axis_labels (tuple of str, list of str, default=('Index','Value')) – Axis labels in the form (x_axis_label,y_axis_label)
size (tuple, default=(8,6)) – The size of the figure
- figure#
- Type:
matplotlib.figure.Figure
Examples
This example creates two 2D datasets (images), and uses the provided slicing information to generate two plots on the same axis, corresponding to the two datasets.
>>> from cil.utilities.display import show1D >>> from cil.utilities.dataexample import PEPPERS >>> data = PEPPERS.get() >>> data_channel0 = data.get_slice(channel=0) >>> data_channel1 = data.get_slice(channel=1) >>> show1D([data_channel0, data_channel1], slice_list=[('horizontal_x', 256)], ... label=['Channel 0', 'Channel 1'], line_styles=["--", "-"])
The following example uses two sets of slicing information applied to a single dataset, resulting in two separate plots.
>>> from cil.utilities.display import show1D >>> from cil.utilities.dataexample import PEPPERS >>> data = PEPPERS.get() >>> slices = [[('channel', 0), ('horizontal_x', 256)], [('channel', 1), ('horizontal_y', 256)]] >>> show1D(data, slice_list=slices, title=['Channel 0', 'Channel 1'])
- save(filename, **kwargs)#
Saves the image as a .png using matplotlib.figure.savefig()
matplotlib kwargs can be passed, refer to documentation https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.savefig.html
show_geometry - Display system geometry#
- class cil.utilities.display.show_geometry(acquisition_geometry, image_geometry=None, elevation=20, azimuthal=-35, view_distance=10, grid=False, figsize=(10, 10), fontsize=10)[source]#
Displays a schematic of the acquisition geometry for 2D geometries elevation and azimuthal cannot be changed
- Parameters:
acquisition_geometry (AcquisitionGeometry) – CIL acquisition geometry
image_geometry (ImageGeometry, optional) – CIL image geometry
elevation (float) – Camera elevation in degrees, 3D geometries only, default=20
azimuthal (float) – Camera azimuthal in degrees, 3D geometries only, default=-35
view_distance (float) – Camera view distance, default=10
grid (boolean) – Show figure axis, default=False
figsize (tuple (x, y)) – Set figure size (inches), default (10,10)
fontsize (int) – Set fontsize, default 10
- Returns:
returns a matplotlib.pyplot figure object
- Return type:
matplotlib.figure.Figure
- save(filename, **kwargs)#
Saves the image as a .png using matplotlib.figure.savefig()
matplotlib kwargs can be passed, refer to documentation https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.savefig.html
islicer - interactive display of 2D slices#
- class cil.utilities.jupyter.islicer(data, direction=0, title=None, slice_number=None, cmap='gray', minmax=None, size=None, axis_labels=None, origin='lower-left', play_interval=500)[source]#
Creates an interactive slider that slices a 3D volume along an axis.
- Parameters:
data (DataContainer or numpy.ndarray) – A 3-dimensional dataset from which 2-dimensional slices will be shown
direction (int) – Axis to slice on. Can be 0,1,2 or the axis label, default 0
title (str, list of str or tuple of str, default='') – Title for the display
slice_number (int, optional) – Start slice number (default is None, which results in the center slice being shown initially)
cmap (str or matplotlib.colors.Colormap, default='gray') – Set the colour map
minmax (tuple) – Colorbar (min, max) values, default None (uses the min, max of values in data)
size (int or tuple, optional) – Specify the figure size in inches. If int this specifies the width, and scales the height in order to keep the standard matplotlib aspect ratio, default None (use the default matplotlib figure size)
axis_labels (list of str, optional) – The axis labels to use for each of the 3 dimensions in the data (default is None, resulting in labels extracted from the data, or [‘X’,’Y’,’Z’] if no labels are present)
origin ({'lower-left', 'upper-left', 'lower-right', 'upper-right'}) – Sets the display origin
play_interval (int, default=500) – The interval of time (in ms) a slice is selected for when iterating through a set of them
- Returns:
box – The top-level widget container.
- Return type:
ipywidgets.Box