Welcome to radioSphere’s documentation!
Sphere detection
Library of RadioSphere spheres detection functions.
- detectSpheres.computeFxAndPsiSeries(radioMM, radiusMM, CORxPositions, pixelSizeMM=0.1, sourceDetectorDistMM=100, blur=0.0, maxIterations=50, l=0.5, epsilon='iterative', kTrustRatio=0.75, nProcesses=8)[source]
This function takes in a single divergent projection and positions along the ray direction, and returns the corresponding indicator function (fx) and structuring element (psi) series by running (in parallel) a series of tomopack
- Parameters:
radioMM (2D numpy array of floats) – Radiography containing “distance” projections in mm This is typically the result of mu*log(I/I_0)
radiusMM (float) – Particle radius in mm
CORxPositions (1D numpy array of floats) – Positions in the x-ray direction on which a series of tomopack will be run
pixelSizeMM (float, optional) – Pixel size on detector in mm Default = 0.1
sourceDetectorDistMM (float, optional) – Distance between x-ray source and middle of detector. Set as numpy.inf for parallel projection Default = 100
blur (float, optional) – Sigma of blur to pass to scipy.ndimage.gaussian_filter to blur the synthetic psi Default = 0
maxIterations (int, optional) – Number of iterations to run tomopack Default = 50
l (float, optional) – “Lambda” parameter which controls relaxation in tomopack iterations Default = 0.5
epsilon (float, optional, or 'iterative') – Trust cutoff wavelengths in psi If the radiograph is in mm so is this parameter Default = ‘iterative’ – updating until kTrustRatio (below) is reached
kTrustRatio (float, optional) – Ratio of cutoff psi wavelengths Default = 0.75
nProcesses (integer, optional) – Number of processes for multiprocessing Default = number of CPUs in the system
- Returns:
fXseries (3D numpy array of floats) – Indicator function series along the x-ray direction Its shape is (len(CORxPositions), radioMM.shape[0], radioMM.shape[1])
psiXseries (3D numpy array of floats) – Structuring element series along the x-ray direction Its shape is (len(CORxPositions), radioMM.shape[0], radioMM.shape[1])
- detectSpheres.detectorPeaksTo3DCoordinates(peaksJI, CORxPos, detectorResolution=[512, 512], pixelSizeMM=0.1, sourceDetectorDistMM=100)[source]
This function takes positions on the detector (identified peaks of the indicator function) and a set of positions in the x-ray direction (where a series of tomopack was run) and returns the corresponding XYZ coordinates
- Parameters:
peaksJI (2D numpy array of int) – Positions of spheres centres on the detector (rows, coloumns (JI))
CORxPos (1D numpy array of floats) – Positions in the x-ray direction on which a series of tomopack was run If not a divergent beam, this should be an array full of the same number – COR
pixelSizeMM (float, optional) – Pixel size on detector in mm Default = 0.1
detectorResolution (2-component list of ints, optional) – Number of pixels rows, columns of detector Default = [512,512]
sourceDetectorDistMM (float, optional) – Distance between x-ray source and middle of detector. Set as numpy.inf for parallel projection Default = 100
- Returns:
posXYZmm – Positions of spheres centres (N) in 3D (XYZ) in mm If not a divergent beam, posX is the input COR
- Return type:
(N x 3) 2D numpy array
- detectSpheres.indicatorFunctionToDetectorPositions(fx, scanFixedNumber=None, massThreshold=0.5, debug=False)[source]
This function takes an indicator function fx and returns peaks on the detector. fx can be a 2D array, which is directly the raw output from tomopack, or a 3D array, if a series of tomopack was run.
In both cases, the peaks returned as a (n x 3) 2D array, where the first column corresponds to the slice of the fx series that peaks were found. If a 2D input fx is passed, the first column is always 0 (zero slice in 3D).
- Parameters:
fx (2D or 3D numpy array of floats) – Approximation of indicator function For a divergent beam this should be a 3D array
scanFixedNumber (int, optional) – The number of spheres scanned If None, peaks will be thresholded based on massThreshold (below) Default = None
massThreshold (float, optional) – Threshold for accepting the result of the filtered indicator function Activated if scanFixedNumber (above) is None Default = 0.5
debug (bool, optional) – Show debug graphs (especially in the maximum filtering) Default = False
- Returns:
peaksPOSnJI – Positions of spheres centres (N) on the detector (slice, rows, coloumns (JI)) Where slice is the CORx slice the resonance peak falls in (only makes sense for a 3D fx)
- Return type:
(N x 3) 2D numpy array
- detectSpheres.tomopack(radioMM, psiMM, maxIterations=50, l=0.5, epsilon='iterative', kTrustRatio=0.75, verbose=False, graphShow=False)[source]
‘tomopack’ FFT-based algorithm for sphere identification by Stéphane Roux. the FFT of psiMM as a structuring element to pick up projected spheres in radioMM using a parallel projection hypothesis.
- Parameters:
radioMM (2D numpy array of floats) – Radiography containing “distance” projections in mm This is typically the result of mu*log(I/I_0)
psiMM (2D numpy array of floats) – A (synthetic) projection in mm of a single sphere in the centre of the detector This is the structuring element used for FFT recognition. Should be same size as radioMM
maxIterations (int, optional) – Number of iterations to run the detection for Default = 50
l (float, ptional) – “Lambda” parameter which controls relaxation in the iterations Default = 0.5
epsilon (float, optional, or 'iterative') – Trust cutoff wavelengths in psi. If the radiograph is in mm so is this parameter Default = ‘iterative’ – updating until kTrustRatio (below) is reached
kTrustRatio (float, optional) – Ratio of cutoff psi wavelengths Default = 0.75
verbose (bool, optional) – Get to know what the function is really thinking Default = False
graphShow (bool, optional) – Show evolution of fx during iterations, and final one together with radio and psi Default = False
- Returns:
fx – The approximation of the indicator function Same size as radioMM, with high values where we think spheres centres are Consider using indicatorFunctionToDetectorPositions() to get the IJ detector coordinates of the centres
- Return type:
2D numpy array
- detectSpheres.tomopackDivergentScanTo3DPositions(radioMM, radiusMM, CORxRef=None, CORxMin=None, CORxMax=None, CORxNumber=100, fXseries=None, psiXseries=None, pixelSizeMM=0.1, sourceDetectorDistMM=100, blur=0.0, maxIterations=50, l=0.5, epsilon='iterative', kTrustRatio=0.75, scanFixedNumber=None, massThreshold=0.5, saveSeries=True, saveSeriesDirectory=None, nProcesses=8, verbose=True)[source]
This function takes in a single divergent projection, and will run tomopack generating different psis by varying their position as Centre Of Rotation (COR) in the x-direction, from CORxMin to CORxMax in CORxNumber steps.
The resulting series of indicator functions is analysed and a 3D position guess for all identified spheres is returned.
- Parameters:
radioMM (2D numpy array of floats) – Radiography containing “distance” projections in mm This is typically the result of mu*log(I/I_0)
radiusMM (float) – Particle radius in mm
fXseries (3D numpy array of floats, optional) – Indicator function series along the x-ray direction Default = None
psiXseries (3D numpy array of floats, optional) – Structuring element series along the x-ray direction Default = None
pixelSizeMM (float, optional) – Pixel size on detector in mm Default = 0.1
sourceDetectorDistMM (float, optional) – Distance between x-ray source and middle of detector Default = 100
blur (float, optional) – Sigma of blur to pass to scipy.ndimage.gaussian_filter to blur the synthetic psi Default = 0
maxIterations (int, optional) – Number of iterations to run tomopack Default = 50
l (float, optional) – “Lambda” parameter which controls relaxation in tomopack iterations Default = 0.5
epsilon (float, optional, or 'iterative') – Trust cutoff wavelengths in psi for tomopack If the radiograph is in mm so is this parameter Default = ‘iterative’ – updating until kTrustRatio (below) is reached
kTrustRatio (float, optional) – Ratio of cutoff psi wavelengths for tomopack Default = 0.75
scanFixedNumber (int, optional) – The number of spheres scanned If None peaks will be thresholded based on massThreshold (below) Default = None
massThreshold (float, optional) – Threshold for accepting the result of the filtered indicator function Activated if scanFixedNumber (above) is None Default = 0.5
saveSeries (boolean, optional) – Save indicator function, psi and filtered series as tif files Default = True
saveSeriesDirectory (str, optional) – Directory to save the computed series Default = None
nProcesses (integer, optional) – Number of processes for multiprocessing Default = number of CPUs in the system
verbose (boolean, optional) – Print what the function is doing? Default = True
- Returns:
positionsXYZmm – Positions of spheres centres in 3D (in mm)
- Return type:
2D numpy array
Sphere projection
- projectSphere.computeLinearBackground(radioMM, mask=None)[source]
This function computes a plane-fit for background greylevels to help with the correction of the background
- Parameters:
radioMM (2D numpy array of floats) – The image
mask (2D numpy array of bools, optional) – Masked zone to fit?
- Returns:
background – Same size as radioMM
- Return type:
2D numpy array of floats
- projectSphere.computeMotionKernel(posPrev, posPost, displacementThreshold=1)[source]
Helper function that calculates unique motion kernel in 2D (detector plane) based on two given positions. Its size is given by the maximum displacement and its direction corresponds to the direction of the displacement vector
Parameters
- posPost2D numpy array of floats
Nx3 positions of the particles in MM (step i+1)
- displacementThresholdfloat
Threshold displacement in MM Only if displacement is bigger than this value, a kernel is calculated
- Returns:
kernel – Motion kernel
- Return type:
2D numpy array of floats
- projectSphere.gl2mm(radio, calib=None)[source]
This function takes a greylevel radiograph (I/I0) and returns a radiograph in mm (L), representing the path length encountered.
- Parameters:
radio (a 2D numpy array of floats) –
calib (dictionary (optional)) – This contains a calibration of greylevels to mm If not passed mu is assumed to be 1.
- projectSphere.mm2gl(radioMM, calib=None)[source]
This function takes a radiograph in mm (L) and returns a radiograph in greylevels (I/I0)
- Parameters:
radioMM (a 2D numpy array of floats) –
calib (dictionary (optional)) – This contains a calibration of greylevels to mm If not passed mu is assumed to be 1.
- projectSphere.pointToDetectorPixelRange(posMM, sourceDetectorDistMM=100, pixelSizeMM=0.1, detectorResolution=[512, 512])[source]
This function gives the detector pixel that a single point will affect. The main idea is that it will be used with ROIaroundSphere option for projectSphereMM() and in turn singleSphereToDetectorPixelRange() in order to only project the needed pixels.
- Parameters:
posMM (1x3 2D numpy array of floats) – xyz position of sphere in mm, with the origin being the middle of the detector
sourceDetectorDistMM (float, optional) – Distance between x-ray source and middle of detector Set as numpy.inf for parallel projection Default = 100
pixelSizeMM (float, optional) – Pixel size on detector in mm Default = 0.1
detectorResolution (2-component list of ints, optional) – Number of pixels rows, columns of detector Default = [512,512]
- Returns:
detectorPixel – row, column (j,i) coordinate on detector as per figures/projectedCoords_v2.pdf
- Return type:
tuple
- projectSphere.projectSphereMM(spheresPositionMM, radiiMM, ROIcentreMM=None, ROIradiusMM=None, sourceDetectorDistMM=100, pixelSizeMM=0.1, detectorResolution=[512, 512], projector='C', transformationCentreMM=None, transformationMatrix=None, blur=None, displacementsMM=None)[source]
This is the python wrapping function for the C++ projector, it gets projection geometry, list of particle positions and radii, projected in the X direction. The output is the crossed distance for each sphere in mm.
Please refer to the figures/projectedCoords_v2 for geometry
In order to allow projections from diffferent angles, an XYZ centre and a transformation matrix can be provided, which will be applied to the particle positions.
- Parameters:
spheresPositionMM (Nx3 2D numpy array of floats) – xyz positions of spheres in mm, with the origin being the middle of the detector
radiiMM (1D numpy array of floats) – Particle radii for projection
ROIcentreMM (3-component vector of floats, optional) – Particle position for ROI Default = Disactivated (None)
ROIradiusMM (float, optional) – Particle radius for ROI Default = Disactivated (None)
sourceDetectorDistMM (float, optional) – Distance between x-ray source and middle of detector. Set as numpy.inf for parallel projection Default = 100
pixelSizeMM (float, optional) – Pixel size on detector in mm Default = 0.1
detectorResolution (2-component list of ints, optional) – Number of pixels rows, columns of detector Default = [512,512]
projector (string, optional) – Algorithm for the projector (leave this alone for now) Default = ‘C’
transformationCentreMM (3-component vector) – XYZ centre for a transformation Default = None
transformationMatrix (3x3 numpy array) – XYZ transformation matrix to apply to coordinates Default = None
blur (float, optional) – sigma of blur to pass to scipy.ndimage.gaussian_filter to blur the radiograph at the end of everything
- Returns:
projectionMM – Radiography containing the total crossed distance through the spheres distance in mm for each beam path. To turn this into a radiography, the distances should be put into a calibrated Beer-Lambert law
- Return type:
2D numpy array of floats
- projectSphere.singleSphereToDetectorPixelRange(spherePositionMM, radiusMM, radiusMargin=0.1, sourceDetectorDistMM=100, pixelSizeMM=0.1, detectorResolution=[512, 512], transformationCentreMM=None, transformationMatrix=None)[source]
This function gives the detector pixel range that a single sphere will affect. The main idea is that it will be used with ROIaroundSphere option for projectSphereMM() in order to only project the needed pixels.
- Parameters:
spherePositionMM (1x3 2D numpy array of floats) – xyz position of sphere in mm, with the origin being the middle of the detector
radiusMM (float) – Particle radius for projection
radiusMargin (float) – Multiplicative margin on radius Default = 0.1
ROIaroundSphere (bool, optional) – If there is only one sphere, only compute a region-of-interest radiography? Default = False
sourceDetectorDistMM (float, optional) – Distance between x-ray source and middle of detector Set as numpy.inf for parallel projection Default = 100
pixelSizeMM (float, optional) – Pixel size on detector in mm Default = 0.1
detectorResolution (2-component list of ints, optional) – Number of pixels rows, columns of detector Default = [512,512]
transformationCentreMM (3-component vector) – XYZ centre for a transformation Default = None
transformationMatrix (3x3 numpy array) – XYZ transformation matrix to apply to coordinates Default = None
- Returns:
JIrange
- Return type:
range in rows, colums of detector concerned by this grain
Position optimisation
- optimisePositions.optimiseSensitivityFields(radioMM, xyzGuessesMM, radiiMM, iterationsMax=20, minDeltaMM=0.01, perturbationMM=None, displacementsMM=None, sourceDetectorDistMM=100, pixelSizeMM=0.1, detectorResolution=[512, 512], verbose=0, DEMcorr=False, DEMparameter=0.01, limitsX=None, regularisation=False, regularisationThreshold=inf, weightX=1.0, GRAPH=False, NDDEM_output=False, blur=None, motionKernel=None, showConvergence=False, optimiseGL=False, optimiseGLcalib=None, outDir=None)[source]
This function takes in a reference projection (radioMM) in mm and sphere positions and moves them around to minimise the residual as far as possible. The technique used is the calculation of a sensitivity field in x, y, z with a perturbation of the synthetic radiograph. This is done locally in a ROI around each particle, which avoids doing the projection for all pixels.
- Parameters:
radioMM (2D numpy array of floats) – Projection of distance crossed in spheres in MM
xyzGuessesMM (2D numpy array of floats) – Nx3 guesses for the positions of the particles in MM
radiiMM (1D numpy array of floats) – Particle radii for projection
iterationsMax (int, optional) – Number of iterations to perform Default = 20
minDeltaMM (float, optional) – If step size gets below this value, stop Default = 0.01
perturbationMM (either a single float or a 3-component list of floats, optional) – Size of the perturbation step to compute the sensitivity field Default = mean particle radius * numpy.array([SOD^2/(2*SDD), 0.5, 0.5])
displacementsMM (2D numpy array of floats, optional) – Nx3 displacement vectors to account for blur Default = None
sourceDetectorDistMM (float, optional) – Distance between x-ray source and middle of detector Default = 100
pixelSizeMM (float, optional) – Pixel size on detector in mm Default = 0.1
detectorResolution (2-component list of ints, optional) – Number of pixels height, width of detector Default = [512,512]
verbose (int, optional) – Print noisly? 0 = quiet except warning, 1=iterations, 2=everything Default = 1
DEMcorr (bool, optional) – Perform a soft DEM correction between all iterations? Default = False
DEMparameter (float, optional) – If DEMcorr is activated Stiffness and timestep wrapped into one Default = 0.01
limitsX (two-component list of floats, optional) – Minimum and maximum zoom position in the direction of the X-ray beam Default = None, no limits
regularisation (bool, optional) – Perform a harsh “regularisation” in time in the direction of the X-ray beam Default = False
regularisationThreshold (float, optional) – Threshold (MM) in distance between current X-position and input guess If this is exceeded, the X-position is forced back to the input one Default = numpy.inf
weightX (float, optional) – Extra weighting factor applied in the direction of the X-ray beam It is applied inside the least_squares minimisation damping down X oscillations Default = 1.
NDDEM_output (bool, optional) – Save every iteration so that it can be viewed using NDDEM - sorry Eddy
blur (dictionary of floats, optional) – Dictionary containing a unique sigma for each sphere to pass to scipy.ndimage.gaussian_filter() to blur the synthetic radiographs Default = None
motionKernel (dictionary of floats,, optional) – Dictionary containing a unique motion kernel (2d array of floats) for each sphere to convolve the synthetic radiographs Default = None
showConvergence (bool, optional) – show a graph of the system converging with iterations Default = False
optimiseGL (bool, optional) – Perform optimisation on image in greylevels rather than mm? Default = False
optimiseGLcalib (dictionary, optional) – Calibration to apply for converting mm to greylevels and back Default = None
- Returns:
xzyMM
- Return type:
Corrected positions array
Attenuation calibration
- calibrateAttenuation.generateFitParameters(calibSphereLog, pixelSizeMM, sourceDetectorDistMM, sourceObjectDistanceMM, radiusMM, centreYXpx, fitFunction=<function linearFit>, outputPath=False, verbose=False)[source]
Fit an attenuation law to a logged normalised radiograph of a single particle.
- Parameters:
calibSphereLog (2D numpy array of floats) – A radiograph of a single particle divided by the background intensity and then logged.
pixelSizeMM (float) – The size of a single pixel in mm on the detector panel.
sourceDetectorDistMM (float) – The source-detector distance in mm.
sourceObjectDistanceMM (float) – The source-object distance in mm.
radiusMM (float) – The particle radius in mm.
centreYXpx (1D numpy array of floats) – The y and x location of the centre of the particle in pixels.
fitFunction (function handle (optional)) – The fitting function to use. By default fit a linear fitting law. Options are cubicFit, quadraticFit, linearFit and linearFitNoIntercept
outputPath (string (optional)) – A path to save the fit as an npy file.
verbose (bool (optional)) – Show the fit on a graph. Default is False.
- Returns:
L – The path length through the sphere in mm. If the path lies outside the sphere, returns 0.
- Return type:
float
- calibrateAttenuation.getPathLengthThroughSphere(p, r, sdd, sod)[source]
Get the path length of a ray passing through a sphere. Schematic diagram is provided in the supplementary methods section of the first (only?) radiosphere paper.
- Parameters:
p (float) – The distance in mm along the detector panel from the centre.
r (float) – The particle radius in mm.
sdd (float) – The source-detector distance in mm.
sod (float) – The source-object distance in mm.
- Returns:
L – The path length through the sphere in mm. If the path lies outside the sphere, returns 0.
- Return type:
float
DEM optimisation correction
- DEM.DEM.DEM_step(posMMin, radiiMM, k=0.01)[source]
Lightweight DEM with assumption of same size spheres as mechanical regularisation
- Parameters:
posMMin (Nx3 2D numpy array of floats) – xyz positions of spheres in mm, with the origin being the middle of the detector
radiiMM (1D numpy array of floats) – Particle radii for projection
k (float, optional) – Stiffness and timestep wrapped into one Default = 0.01
- Returns:
posMM
- Return type:
output positions