Vous avez reçu un message "Your GitLab account has been locked ..." ? Pas d'inquiétude : lisez cet article https://docs.gricad-pages.univ-grenoble-alpes.fr/help/unlock/

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

Merge branch 'moveGrainsFunction'

parents c0206920 9e4c9150
Pipeline #50554 passed with stages
in 23 minutes and 34 seconds
This diff is collapsed.
#!/usr/bin/env python
"""
This python script deforms a labelled image based on a deformation field using SPAM functions
Copyright (C) 2020 SPAM Contributors
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option)
any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>.
"""
from __future__ import print_function
import spam.helpers
import spam.label as ltk
import spam.DIC
import spam.deformation
import numpy
import sys, os
import tifffile
#import matplotlib.pyplot as plt
# Added from rotation_correlation-style parallelisation
import multiprocessing
import argparse
import progressbar
# Define argument parser object
parser = argparse.ArgumentParser(description="spam-moveLabels "+spam.helpers.optionsParser.GLPv3descriptionHeader +\
"This script applies discretely measured deformation functions (Phi) coming from 'spam-ddic' to a labelled image, "+\
"thus generating the deformed labelled image.\n\nWarning: since we're moving labels, "+\
"nearest neighbour interpolation must be used, and thus the shapes of the labels will be slightly damaged",
formatter_class=argparse.RawTextHelpFormatter)
# Parse arguments with external helper function
args = spam.helpers.optionsParser.moveLabelsParser(parser)
print("+-----------------------------+")
print("| SPAM - Labelled mover |")
print("+-----------------------------+")
print("\nCurrent Settings:")
argsDict = vars(args)
for key in sorted(argsDict):
print("\t{}: {}".format(key, argsDict[key]))
if args.RETURN_STATUS_THRESHOLD is None:
DVC = spam.helpers.readCorrelationTSV(args.TSVFile.name, readConvergence=False)
else:
DVC = spam.helpers.readCorrelationTSV(args.TSVFile.name, readConvergence=True)
# Read labelled image
lab = tifffile.imread( args.LabFile.name )
#if args.GREY_FILE is not None:
#greyTmp = tifffile.imread(args.GREY_FILE)
#grey = numpy.zeros((labShapeOrig[0]+2*args.OVERALL_MARGIN,
#labShapeOrig[1]+2*args.OVERALL_MARGIN,
#labShapeOrig[2]+2*args.OVERALL_MARGIN), dtype=greyTmp.dtype)
#grey[slicePadToNonPad] = greyTmp
labOut = spam.label.moveLabels(lab,
DVC['PhiField'],
margin=args.MARGIN,
PhiCOM=args.PHICOM,
threshold=args.THRESH,
labelDilate=args.LABEL_DILATE,
numberOfThreads=args.NUMBER_OF_PROCESSES)
#if args.GREY_FILE is None:
print("\nSaving labelled image with displaced grains...", end='')
tifffile.imsave( args.OUT_DIR+"/"+args.PREFIX+".tif", labOut.astype(lab.dtype) )
#else:
#print("\nSaving binary image with displaced grains...", end='')
#tifffile.imsave( args.OUT_DIR+"/"+args.PREFIX+".tif", labOut[slicePadToNonPad].astype('<u1')*255 )
print("done.")
......@@ -138,6 +138,7 @@ scripts = ['scripts/spam-mmr',
"scripts/spam-deformImageFromField",
"scripts/spam-mmr-graphical",
"scripts/spam-moveGrains",
"scripts/spam-moveLabels",
"scripts/spam-discreteStrain",
"scripts/spam-regularStrain",
"scripts/spam-ITKwatershed",
......
......@@ -11,6 +11,7 @@ import spam.label
import spam.kalisphera
import spam.label.contacts as con
import spam.plotting
import skimage.morphology
VERBOSE = True
# small labelled volume is a 3x3x3 with a single 1 in the middle
......@@ -410,10 +411,10 @@ class TestFunctionLabel(unittest.TestCase):
# #print numpy.where( returns['subvol'] == label )
def test_meanOrientation(self):
#Generate random main direction
# Generate random main direction
theta = numpy.radians(random.randrange(0, 360, 1))
phi = numpy.radians(random.randrange(0, 90, 1))
#Generate n random vector near the main direction
# Generate n random vector near the main direction
n = 1000 #number of vectors
R = 10 #Radius of vectors
vect = numpy.zeros((n, 3))
......@@ -428,129 +429,129 @@ class TestFunctionLabel(unittest.TestCase):
phiPCA = numpy.degrees(numpy.arctan(numpy.sqrt(mainAxis[1]**2 + mainAxis[2]**2) / mainAxis[0]))
thetaPCA = numpy.degrees(numpy.arctan2(mainAxis[1], mainAxis[2]))
if thetaPCA<0: thetaPCA = 360 + thetaPCA
#Check if the difference between the angles is less than 5 degree
# Check if the difference between the angles is less than 5 degree
self.assertLess(numpy.abs(phiPCA - numpy.degrees(phi)), 5)
self.assertLess(numpy.abs(thetaPCA - numpy.degrees(theta)), 5)
#Check if the vector are normalized
# Check if the vector are normalized
normVectors = numpy.sum(numpy.linalg.norm(projectedVectors, axis = 1)) / len(projectedVectors)
self.assertAlmostEqual(normVectors, 1, places = 3)
def test_Spheroid(self):
#Test for Oblate (Lentil-shaped)
# Test for Oblate (Lentil-shaped)
#Generate random direction
# Generate random direction
theta = numpy.radians(random.randrange(0,360,1))
phi = numpy.radians(random.randrange(0,90,1))
vect = numpy.array([numpy.cos(phi), numpy.sin(phi)*numpy.sin(theta), numpy.sin(phi)*numpy.cos(theta)])
if vect[0]<0: vect[:]=-1*vect[:]
#Generate two random semi-axis values
# Generate two random semi-axis values
a = random.randrange(20,40,1)
c = random.randrange(10,20,1)
#Generate the spheroid
spheroid = spam.label.label.Spheroid(a, c, numpy.asarray(vect)).digitize()
#Compute its semi-axis
# Compute its semi-axis
semiAxis = spam.label.ellipseAxes(spheroid)
#Compare the semi-axis
# Compare the semi-axis
self.assertLess(numpy.abs(numpy.max(semiAxis[1])-numpy.maximum(a,c)),2)
self.assertLess(numpy.abs(numpy.min(semiAxis[1])-numpy.minimum(a,c)),2)
#Compute the orientation
# Compute the orientation
eigenVal, eigenVect = spam.label.momentOfInertia(spheroid)
eigenVal = eigenVal / numpy.max(eigenVal)
#Get main orientation
# Get main orientation
mainVect = eigenVect[1][0:3]
if mainVect[0]<0: mainVect[:]=-1*mainVect[:]
#Compute the angle between them
# Compute the angle between them
c = numpy.dot(vect,mainVect)/numpy.linalg.norm(vect)/numpy.linalg.norm(mainVect)
angle = numpy.degrees(numpy.arccos(numpy.clip(c, -1, 1)))
#Check angle less than 2 degree
# Check angle less than 2 degree
self.assertLess(angle,2)
#Test for Prolate (Rice-shaped)
# Test for Prolate (Rice-shaped)
#Generate random direction
# Generate random direction
theta = numpy.radians(random.randrange(0,360,1))
phi = numpy.radians(random.randrange(0,90,1))
vect = numpy.array([numpy.cos(phi), numpy.sin(phi)*numpy.sin(theta), numpy.sin(phi)*numpy.cos(theta)])
if vect[0]<0: vect[:]=-1*vect[:]
#Generate two random semi-axis values
# Generate two random semi-axis values
a = random.randrange(10,20,1)
b = random.randrange(20,40,1)
#Generate the spheroid
# Generate the spheroid
spheroid = spam.label.label.Spheroid(a, b, numpy.asarray(vect)).digitize()
#Compute its semi-axis
# Compute its semi-axis
semiAxis = spam.label.ellipseAxes(spheroid)
#Compare the semi-axis
# Compare the semi-axis
self.assertLess(numpy.abs(numpy.max(semiAxis[1])-numpy.maximum(a,b)),2)
self.assertLess(numpy.abs(numpy.min(semiAxis[1])-numpy.minimum(a,b)),2)
#Compute the orientation
# Compute the orientation
eigenVal, eigenVect = spam.label.momentOfInertia(spheroid)
eigenVal = eigenVal / numpy.max(eigenVal)
#Get main orientation
# Get main orientation
mainVect = eigenVect[1][6:9]
if mainVect[0]<0: mainVect[:]=-1*mainVect[:]
#Compute the angle between them
# Compute the angle between them
c = numpy.dot(vect,mainVect)/numpy.linalg.norm(vect)/numpy.linalg.norm(mainVect)
angle = numpy.degrees(numpy.arccos(numpy.clip(c, -1, 1)))
#Check angle less than 2 degree
# Check angle less than 2 degree
self.assertLess(angle,2)
#Check that raises an error when the vector and dim are passed along
# Check that raises an error when the vector and dim are passed along
with self.assertRaises(ValueError): spam.label.label.Spheroid(10, 20, numpy.asarray([0,1,0]), dim = 1).digitize()
#Check that it runs even without a vector
# Check that it runs even without a vector
res = spam.label.label.Spheroid(10, 20, dim = 3).digitize()
self.assertIsNotNone(res)
def test_FixUnderSegmentation(self):
#Generate two prolate grains (rice-like)
def _test_FixUnderSegmentation(self):
# Generate two prolate grains (rice-like)
grain1 = spam.label.label.Spheroid(10, 20, numpy.asarray([0,1,0])).digitize()
grain2 = spam.label.label.Spheroid(10, 20, numpy.asarray([0,1,0])).digitize()
#Create the bigger labelled image
# Create the bigger labelled image
grainIm = numpy.concatenate((grain1,grain2))
grainIm = numpy.zeros(grainIm.shape)
#Add the grains to the bigger image
# Add the grains to the bigger image
grainIm[:grain1.shape[0]-1,:,:] = grain1[:grain1.shape[0]-1,:,:]
grainIm[grain2.shape[0]-5:-5,:,:] = grainIm[grain2.shape[0]-5:-5,:,:] + grain1[:,:,:]
#Set all the labels to 1
# Set all the labels to 1
grainIm = numpy.where(grainIm >= 1, 3, grainIm)
#Pad a border
# Pad a border
grainIm = numpy.pad(grainIm, pad_width=10, mode='constant', constant_values = 0)
#Create the 'greyScale' image
# Create the 'greyScale' image
greyIm = numpy.where(grainIm == 3, 30000, 10000)
#Check that the greyscale image is normalized
# Check that the greyscale image is normalized
res1 = spam.label.label.fixUndersegmentation(grainIm, greyIm, [3], 10*0.5, 20*0.5)
self.assertEqual(res1, None)
#Check that a or c is valid
# Check that a or c is valid
res2 = spam.label.label.fixUndersegmentation(grainIm, greyIm, [3], numpy.nan, numpy.nan)
self.assertEqual(res2, None)
#Check that a or c are positive
# Check that a or c are positive
res3 = spam.label.label.fixUndersegmentation(grainIm, greyIm, [3], -1, 10)
self.assertEqual(res3, None)
#Run fixUnderSegmentation
# Run fixUnderSegmentation
greyIm = numpy.where(grainIm == 3, 0.75, 0.25)
res4 = spam.label.label.fixUndersegmentation(grainIm, greyIm, [3], 10*0.8, 20*0.8, vect = [[0,1,0]])
#Check that there are two grains
# Check that there are two grains
self.assertEqual(numpy.max(numpy.unique(res4)), 2)
#Check that it runs even if the label does not exist
# Check that it runs even if the label does not exist
res5 = spam.label.label.fixUndersegmentation(grainIm, greyIm, [3], 10*0.8, 20*0.8, vect = [[0,1,0]])
self.assertIsNotNone(res5)
#Check for a vect that is not a list
# Check for a vect that is not a list
res6 = spam.label.label.fixUndersegmentation(grainIm, greyIm, [3], 10*0.8, 20*0.8, vect = (0,1,0))
self.assertIsNone(res6)
#Check that it works without the input vect
# Check that it works without the input vect
res7 = spam.label.label.fixUndersegmentation(grainIm, greyIm, [3], 10*0.8, 20*0.8, numVect = 1)
self.assertIsNotNone(res7)
#Check that it works with verbose = True
# Check that it works with verbose = True
res8 = spam.label.label.fixUndersegmentation(grainIm, greyIm, [3], 10*0.8, 20*0.8, numVect = 1, verbose = True)
self.assertIsNotNone(res8)
#Check that it works even for a non-existing label
# Check that it works even for a non-existing label
res9 = spam.label.label.fixUndersegmentation(grainIm, greyIm, [5], 10*0.8, 20*0.8, numVect = 1)
self.assertIsNotNone(res9)
def test_contactOrientations(self):
#Generate two oblate grains
# Generate two oblate grains
grain1 = spam.label.label.Spheroid(7, 15, numpy.asarray([0,1,0])).digitize()
grain2 = spam.label.label.Spheroid(7, 15, numpy.asarray([0,1,0])).digitize()
grainIm = numpy.concatenate((grain1,grain2))
......@@ -558,23 +559,23 @@ class TestFunctionLabel(unittest.TestCase):
grainIm[:grain1.shape[0]-1,:,:] = grain1[:grain1.shape[0]-1,:,:]
grainIm[grain2.shape[0]-5:-5,:,:] = grainIm[grain2.shape[0]-5:-5,:,:] + grain2[:,:,:]
grainIm = numpy.where(grainIm >1,1,grainIm)
#Generate a new grain and create contact
# Generate a new grain and create contact
grain3 = 2*spam.label.label.Spheroid(7, 15, numpy.asarray([0,1,0])).digitize()
imLab = numpy.concatenate((grain3,grainIm))
imLab = numpy.zeros(imLab.shape)
imLab[:grain3.shape[0]-1,:,:] = grain3[:grain3.shape[0]-1,:,:]
imLab[grain3.shape[0]-3:-3,:,:] = imLab[grain3.shape[0]-3:-3,:,:] + grainIm[:,:,:]
imLab = numpy.where(imLab >2, 2, imLab)
#Create bin image
# Create bin image
imBin = numpy.where(imLab >0, 1, 0)
#Run ITK and check angle of contact
# Run ITK and check angle of contact
contactNormal, intervox, NotTreatedContact = con.contactOrientations(imBin, imLab, watershed="ITK")
if contactNormal[0]<0: contactNormal = contactNormal*-1
c = numpy.dot(contactNormal, [1, 0, 0])/numpy.linalg.norm(contactNormal)/numpy.linalg.norm([1, 0, 0])
angle = numpy.degrees(numpy.arccos(numpy.clip(c, -1, 1)))
self.assertFalse(NotTreatedContact)
self.assertLess(angle, 1.)
#Run RW and check angle of contact
# Run RW and check angle of contact
contactNormal, intervox, NotTreatedContact = con.contactOrientations(imBin, imLab, watershed="RW")
if contactNormal[0]<0: contactNormal = contactNormal*-1
c = numpy.dot(contactNormal, [1, 0, 0])/numpy.linalg.norm(contactNormal)/numpy.linalg.norm([1, 0, 0])
......@@ -583,13 +584,13 @@ class TestFunctionLabel(unittest.TestCase):
self.assertLess(angle, 1.)
def test_fabricTensor(self):
#Define number of vector
# Define number of vector
n = 1000
#Create equally-spaced vector
# Create equally-spaced vector
vectEq = spam.plotting.orientationPlotter.SaffAndKuijlaarsSpiral(n)
#Compute fabric
# Compute fabric
NEq,FEq,aEq = spam.label.label.fabricTensor(vectEq)
#Create a set of vectors using a normal distribution centered on a random orientation
# Create a set of vectors using a normal distribution centered on a random orientation
theta = numpy.radians(random.randrange(0, 360, 1))
phi = numpy.radians(random.randrange(0, 90, 1))
vectRand = numpy.zeros((n, 3))
......@@ -599,9 +600,9 @@ class TestFunctionLabel(unittest.TestCase):
vectRand[x,0] = numpy.cos(phiI)
vectRand[x,1] = numpy.sin(phiI)*numpy.sin(thetaI)
vectRand[x,2] = numpy.sin(phiI)*numpy.cos(thetaI)
#Compute fabric
# Compute fabric
NRand, FRand, aRand = spam.label.label.fabricTensor(vectRand)
#Test the results
# Test the results
self.assertGreater(aRand, aEq)
def test_setVoronoi(self):
......@@ -617,27 +618,119 @@ class TestFunctionLabel(unittest.TestCase):
self.assertEqual(setVoronoiVolumes[2]>labVolumes[2], True)
def test_convexVolume(self):
#Get a random separation between 1 and 10
# Get a random separation between 1 and 10
dist = int(10*numpy.random.rand())
#Create a rectangular image
# Create a rectangular image
im = numpy.zeros((15,15,30))
#Create a first block of 5x5x5
# Create a first block of 5x5x5
im[5:10,5:10,5:10] = 1
#Create second block of 5x5x5 located at dist
# Create second block of 5x5x5 located at dist
im[5:10,5:10,10+dist:15+dist] = 1
#Compute convex volume
# Compute convex volume
im = im.astype('<u4')
convexVol = spam.label.convexVolume(im)
#Compute theoretical volume
# Compute theoretical volume
volOr = numpy.sum(im) + 5*5*dist
self.assertEqual(volOr, convexVol[-1])
#Check that it shows the error for particles smaller than 3 voxels
# Check that it shows the error for particles smaller than 3 voxels
im = numpy.zeros((15,15,30))
im[10,10,10] = 1
#Compute convex volume
# Compute convex volume
im = im.astype('<u4')
convexVol = spam.label.convexVolume(im)
self.assertEqual(0, convexVol[-1])
def test_moveLabels(self):
# Create the sphere
imLab = skimage.morphology.ball(20)
# Pad with zero at each boundaries
imLab = numpy.pad(imLab, (10), 'constant', constant_values=(0))
# Compute initial volume
iniVol = spam.label.volumes(imLab)[-1]
# Compute initial COM
iniCOM = spam.label.centresOfMass(imLab)[-1]
# Compute boundingBoxes
boundingBoxes = spam.label.boundingBoxes(imLab)
# Compute centre of Mass
centresOfMass = spam.label.centresOfMass(imLab)
# Create empty PhiField
PhiField = numpy.zeros((2, 4, 4))
# Test #1 -> COM=iniCOM, vol = iniVol for no dilate and Phi = I
transformation = {'t': [0, 0, 0]}
PhiField[1] = spam.deformation.computePhi(transformation)
imLab2 = spam.label.moveLabels(imLab, PhiField, boundingBoxes = boundingBoxes, centresOfMass = centresOfMass)
# Compute Volume and COM
newVol = spam.label.volumes(imLab2)[-1]
newCOM = spam.label.centresOfMass(imLab2)[-1]
self.assertEqual(0, numpy.sum(iniVol - newVol))
self.assertEqual(0, numpy.sum(iniCOM - newCOM))
# Test #2 -> COM=iniCOM, vol = +10% volIni for a dilation of 10%
transformation = {'z': [1.1, 1, 1]}
PhiField[1] = spam.deformation.computePhi(transformation)
imLab2 = spam.label.moveLabels(imLab, PhiField, boundingBoxes = boundingBoxes, centresOfMass = centresOfMass)
# Compute Volume and COM
newVol = spam.label.volumes(imLab2)[-1]
newCOM = spam.label.centresOfMass(imLab2)[-1]
self.assertEqual(0, numpy.sum(iniCOM - newCOM))
self.assertAlmostEqual(1.1, newVol/iniVol, places = 1)
# Test #3 -> COM=iniCOM and vol/ iniVol > 1 for dilate = 1 and Phi = I
transformation = {'t': [0, 0, 0]}
PhiField[1] = spam.deformation.computePhi(transformation)
imLab2 = spam.label.moveLabels(imLab, PhiField, boundingBoxes = boundingBoxes, centresOfMass = centresOfMass, labelDilate=1)
# Compute Volume and COM
newVol = spam.label.volumes(imLab2)[-1]
newCOM = spam.label.centresOfMass(imLab2)[-1]
self.assertEqual(0, numpy.sum(iniCOM - newCOM))
self.assertGreater(newVol/iniVol, 1.0)
# Test#4 -> vol=iniVol and COM follows the 5vox displacement
transformation = {'t': [5, 5, 5]}
PhiField[1] = spam.deformation.computePhi(transformation)
imLab2 = spam.label.moveLabels(imLab, PhiField, boundingBoxes = boundingBoxes, centresOfMass = centresOfMass)
# Compute Volume and COM
newVol = spam.label.volumes(imLab2)[-1]
newCOM = spam.label.centresOfMass(imLab2)[-1]
self.assertEqual(0, numpy.sum(iniVol - newVol))
self.assertTrue(((newCOM - iniCOM) == 5).all())
# Test 5 -> move grain half out and check volume is near 0.5
transformation = {'t': [30, 0, 0,]}
PhiField[1] = spam.deformation.computePhi(transformation)
imLab2 = spam.label.moveLabels(imLab, PhiField, boundingBoxes = boundingBoxes, centresOfMass = centresOfMass)
# Compute Volume and COM
newVol = spam.label.volumes(imLab2)[-1]
newCOM = spam.label.centresOfMass(imLab2)[-1]
self.assertAlmostEqual(0.5, newVol/iniVol, places = 1)
# Test 6A -> Check that it runs when the PhiField has less labels than the labelled image
PhiField = numpy.zeros((1, 4, 4))
imLab2 = spam.label.moveLabels(imLab, PhiField, boundingBoxes = boundingBoxes, centresOfMass = centresOfMass)
self.assertIsNotNone(imLab2)
# Test 6B -> Check that it runs when the PhiField has more labels than the labelled image
PhiField = numpy.zeros((3, 4, 4))
imLab2 = spam.label.moveLabels(imLab, PhiField, boundingBoxes = boundingBoxes, centresOfMass = centresOfMass)
self.assertIsNotNone(imLab2)
def test_erodeLabels(self):
# Create the sphere
imLab = skimage.morphology.ball(20)
# Pad with zero at each boundaries
imLab = numpy.pad(imLab, (10), 'constant', constant_values=(0))
# Compute initial volume
iniVol = spam.label.volumes(imLab)[-1]
# Compute initial COM
iniCOM = spam.label.centresOfMass(imLab)[-1]
# Test #1 -> COM=iniCOM, vol = iniVol for no dilate and Phi = I
imLab2 = spam.label.erodeLabels(imLab, erosion=0)
# Compute Volume and COM
newVol = spam.label.volumes(imLab2)[-1]
newCOM = spam.label.centresOfMass(imLab2)[-1]
self.assertEqual(0, numpy.sum(iniVol - newVol))
self.assertEqual(0, numpy.sum(iniCOM - newCOM))
# Test #2 -> COM=iniCOM and vol/ iniVol < 1 for dilate = 1 and Phi = I
imLab2 = spam.label.erodeLabels(imLab, erosion=1)
# Compute Volume and COM
newVol = spam.label.volumes(imLab2)[-1]
newCOM = spam.label.centresOfMass(imLab2)[-1]
self.assertEqual(0, numpy.sum(iniCOM - newCOM))
self.assertGreater(1.0, newVol/iniVol)
if __name__ == '__main__':
unittest.main()
......@@ -517,7 +517,7 @@ class testAll(unittest.TestCase):
#######################################################
# Now check with label mover -- easier if there are no rotations
#######################################################
exitCode = subprocess.call(["spam-moveGrains",
exitCode = subprocess.call(["spam-moveLabels",
testFolder + "Lab0.tif",
testFolder + "Step0-Step1-discreteDVC.tsv"])
self.assertEqual(exitCode, 0)
......
......@@ -308,7 +308,7 @@ def reconstructionFromOppositeFaces(im, dmax=None, verbose=False):
return rec1 # send the reconstructed image
def directionalErosion(bwIm, vect, a, c, NumberOfThreads=1, verbose = False):
def directionalErosion(bwIm, vect, a, c, numberOfThreads=1, verbose = False):
"""
This functions performs direction erosion over the binarized image using
an ellipsoidal structuring element over a range of directions. It is highly
......@@ -329,7 +329,7 @@ def directionalErosion(bwIm, vect, a, c, NumberOfThreads=1, verbose = False):
c : int or float
Lenght of the principal semi-axis of the structuring element in px
NumberOfThreads : integer, optional
numberOfThreads : integer, optional
Number of Threads for multiprocessing.
Default = 1
......@@ -379,11 +379,11 @@ def directionalErosion(bwIm, vect, a, c, NumberOfThreads=1, verbose = False):
# qJobs.put( contactList[x,0] )
qJobs.put(x)
for i in range(NumberOfThreads):
for i in range(numberOfThreads):
qJobs.put("STOP")
# print "Master: Launching workers"
for i in range(NumberOfThreads):
for i in range(numberOfThreads):
p = multiprocessing.Process(target=worker, args=(i, qJobs, qResults, ))
p.start()
......@@ -392,7 +392,7 @@ def directionalErosion(bwIm, vect, a, c, NumberOfThreads=1, verbose = False):
finishedThreads = 0
finishedJobs = 0
# print "Master: Waiting for results"
while finishedThreads < NumberOfThreads:
while finishedThreads < numberOfThreads:
result = qResults.get()
if result == "STOP":
......
......@@ -1514,7 +1514,7 @@ def eregDiscreteParser(parser):
def moveGrainsParser(parser):
def moveLabelsParser(parser):
parser.add_argument('LabFile',
metavar='LabFile',
type=argparse.FileType('r'),
......@@ -1559,25 +1559,18 @@ def moveGrainsParser(parser):
dest='RETURN_STATUS_THRESHOLD',
help='Return status in spam-ddic to consider the grain. Default = None, but 2 (i.e., converged) is recommended')
parser.add_argument('-gf',
'--grey-file',
type=str,
default=None,
dest='GREY_FILE',
help='Input greylevel tiff file corresponding to the input labelled file. This option requires a threshold to be set with -thr')
parser.add_argument('-om',
'--overall-margin',
type=int,
default=10,
dest='OVERALL_MARGIN',
help="Overall image padding for label movement near edges, this is how much the labelled image is increased before starting to place label. Default = 10")
#parser.add_argument('-gf',
#'--grey-file',
#type=str,
#default=None,
#dest='GREY_FILE',
#help='Input greylevel tiff file corresponding to the input labelled file. This option requires a threshold to be set with -thr')
parser.add_argument('-lm',
'--label-margin',
type=int,
default=3,
dest='LABEL_MARGIN',
dest='MARGIN',
help="Bounding box margin for each label to allow for rotation/strain of the label. Default = 3")
parser.add_argument('-ld',
......@@ -1624,8 +1617,8 @@ def moveGrainsParser(parser):
if args.PREFIX is None:
args.PREFIX = os.path.splitext(os.path.basename(args.LabFile.name))[0] + "-displaced"
if args.GREY_FILE is not None and args.THRESH == 0.5:
print("\n\nWARNING: You set a greyfile and your threshold is 0.5 -- I hope this is the right threshold for the greylevel image!\n\n")
#if args.GREY_FILE is not None and args.THRESH == 0.5:
#print("\n\nWARNING: You set a greyfile and your threshold is 0.5 -- I hope this is the right threshold for the greylevel image!\n\n")
if args.LABEL_DILATE > 0 and args.GREY_FILE is None:
print("\n\nWARNING: You are dilating labels but haven't loaded a grey image, everything's going to expand a lot!\n\n")
......
......@@ -859,7 +859,7 @@ def _markerCorrection(markers, numMarkers, distanceMap, volBin, peakDistance=5,
return markers
def localDetectionAssembly(volLab, volGrey, contactList, localThreshold, boundingBoxes=None, NumberOfThreads=1, radiusThresh=4):
def localDetectionAssembly(volLab, volGrey, contactList, localThreshold, boundingBoxes=None, numberOfThreads=1, radiusThresh=4):
"""
Local contact refinement of a set of contacts
checks whether two particles are in contact with a local threshold using ``localDetection()``
......@@ -883,7 +883,7 @@ def localDetectionAssembly(volLab, volGrey, contactList, localThreshold, boundin