Commit b5c24047 authored by Gustavo Pinzon's avatar Gustavo Pinzon
Browse files

New function spam.label.getNeighbours() with test

parent a20f3f85
Pipeline #51193 passed with stages
in 12 minutes and 49 seconds
......@@ -31,6 +31,7 @@ import matplotlib
import math
import progressbar
import spam.filters
import spam.mesh
import multiprocessing
import spam.DIC
......@@ -1945,3 +1946,93 @@ def convexFillHoles(lab, boundingBoxes=None, centresOfMass=None):
return labOut
def getNeighbours(lab, listOfLabels, method = 'getLabel', parameter = None, centresOfMass = None, boundingBoxes = None):
"""
This function computes the neighbours for a list of labels.
Parameters
-----------
lab : 3D numpy array
Labelled image
listOfLabels : list of ints
List of labels to which the neighbours will be computed
method : string
Method to compute the neighbours.
'getLabel' : The neighbours are the labels inside the subset obtained through spam.getLabel()
'mesh' : The neighbours are computed using a tetrahedral connectivity matrix
Default = 'getLabel'
parameter : int
Parameter controlling each method.
For 'getLabel', it correspond to the size of the subset. Default = 3
For 'mesh', it correspond to the size of the alpha shape used for carving the mesh. Default = 5*meanDiameter.
boundingBoxes : lab.max()x6 array of ints, optional
Bounding boxes in format returned by ``boundingBoxes``.
If not defined (Default = None), it is recomputed by running ``boundingBoxes``
centresOfMass : lab.max()x3 array of floats, optional
Centres of mass in format returned by ``centresOfMass``.
If not defined (Default = None), it is recomputed by running ``centresOfMass``
Returns
--------
neighbours : list
List with the neighbours for each label in listOfLabels.
"""
# Create result list
neighbours = []
# Compute centreOfMass if needed
if centresOfMass == None:
centresOfMass = spam.label.centresOfMass(lab)
# Compute boundingBoxes if needed
if boundingBoxes == None:
boundingBoxes = spam.label.boundingBoxes(lab)
if method == 'getLabel':
# Compute parameter if needed
if parameter == None:
parameter = 3
# Compute for each label in the list of labels
for label in listOfLabels:
getLabelReturn = spam.label.getLabel(lab,
label,
labelDilate=parameter,
margin=parameter,
boundingBoxes=boundingBoxes,
centresOfMass=centresOfMass,
maskOtherLabels=False)
# Get subvolume
subVol = getLabelReturn['subvol']
# Get neighbours
neighboursLabel = numpy.unique(subVol)
# Remove label and 0 from the list of neighbours
neighboursLabel = neighboursLabel[~numpy.in1d(neighboursLabel, label)]
neighboursLabel = neighboursLabel[~numpy.in1d(neighboursLabel, 0)]
# Add the neighbours to the list
neighbours.append(neighboursLabel)
elif method == 'mesh':
# Compute Radii
radii = spam.label.equivalentRadii(lab)
# Compute parameter if needed
if parameter == None:
parameter = 5*2*numpy.mean(radii)
# Get connectivity matrix
conn = spam.mesh.triangulate(centresOfMass, weights=radii*2, alpha=parameter)
Please register or sign in to reply
# Compute for each label in the list of labels
for label in listOfLabels:
neighboursLabel = numpy.unique(conn[numpy.where(numpy.sum(conn == label, axis=1))])
# Remove label from the list of neighbours
neighboursLabel = neighboursLabel[~numpy.in1d(neighboursLabel, label)]
# Add the neighbours to the list
neighbours.append(neighboursLabel)
else:
print('spam.label.getNeighbours(): Wrong method, aborting')
return neighbours
......@@ -5,13 +5,16 @@ import os
import tifffile
import numpy
import random
import math
import spam.label
import spam.kalisphera
import spam.label.contacts as con
import spam.plotting
import skimage.morphology
import scipy.ndimage
import spam.datasets
VERBOSE = True
# small labelled volume is a 3x3x3 with a single 1 in the middle
......@@ -782,5 +785,36 @@ class TestFunctionLabel(unittest.TestCase):
# Test#2 -> Check that Vol1 is the same and Vol2 increased
self.assertAlmostEqual(normVol1, 0, places = 3)
self.assertGreater(normVol2, 0)
def test_getNeighbours(self):
# Create a sample with kalisphera
pixelSize = 30.e-6
blurSTD = 0.8
noiseSTD = 0.03
boxSizeDEM, centres, radii = spam.datasets.loadDEMboxsizeCentreRadius()
rMax = numpy.amax(radii)
boxSize = boxSizeDEM + 3 * rMax
centres[:, :] = centres[:, :] + 1.5 * rMax
boxSize = int(math.ceil(numpy.max(boxSize[:]) / pixelSize))
centres = centres / pixelSize
radii = radii / pixelSize
Box = numpy.zeros((boxSize, boxSize, boxSize), dtype="<f8")
spam.kalisphera.makeSphere(Box, centres, radii)
Box[numpy.where(Box > 1.0)] = 1.0
Box[numpy.where(Box < 0.0)] = 0.0
Box = Box * 0.5
Box = Box + 0.25
Box = scipy.ndimage.filters.gaussian_filter(Box, sigma=blurSTD)
Box = numpy.random.normal(Box, scale=noiseSTD)
BoxLab = spam.label.watershed((Box > 0.5).astype(bool))
# Set a list of labels
labels = [100, 150, 200]
# Get the neighbours with bot methods
res1 = spam.label.getNeighbours(BoxLab, labels, method = 'mesh')
res2 = spam.label.getNeighbours(BoxLab, labels, method = 'getLabel')
# Check that they are not none
self.assertIsNotNone(res1)
self.assertIsNotNone(res2)
if __name__ == '__main__':
unittest.main()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment