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 1eab193f authored by Edward Andò's avatar Edward Andò
Browse files

Merge branch 'master' into noBorders

parents 4ffdd099 8d3e67ed
......@@ -36,7 +36,7 @@ for speed.
Some user-callable scipts are also provided -- they are more
complex pieces of code that combine a number of functions and
which have a command-line interface.
For the moment the clients are 3 different image correlation
For the moment the scripts are 3 different image correlation
techniques.
Please have a look at our online documentation for:
......
......@@ -53,6 +53,7 @@ Here's a list of existing **spam** scripts organised into categories:
- **spam-ddic** — Discrete image correlation with discrete objects defined with labelled image see: :ref:`discreteDICscript`
- **spam-moveGrains** — Deform a labelled image with displacements defined for each label
- **spam-discreteStrain** — Computes strains on a tetrahedral mesh linking grain centres
- **spam-ereg-discrete** — A graphical tool to pre-align grains for correlation
Description of image correlation scripts
#########################################
......@@ -90,8 +91,7 @@ This script can **run in parallel** using the MPI multiprocessing library by put
Other key input options are (check figure below for illustration):
- *-ns* and *-hws* set the spacing between the grid points in pixels and the "half window size" in pixels. Since measurements are defined as centred on a point, the subvolume which is extracted from around the point is "half window size" pixels on each size of the central point, yielding a volume 1+2*hws in each direction.
- *-reg* performs an initial registration of the two provided images -- **this is highly recommended**. In many cases (without too complicated and large displacement fields), this step can avoid the need to perform a computationally expensive pixel search. The option *-regb* bins (downscales by a given factor) the entire input images to save time.
- *-glt* and *-ght* **prevent** a correlation from occurring if the mean greyvalue of the extracted subvolume is less than *glt* or higher than *ght*.
- *-regbb* and *-regbe* to perform an *initial multiscale registration* of the two provided images -- **this is highly recommended**. In many cases (without too complicated and large displacement fields), this step can avoid the need to perform a computationally expensive pixel search. *-regbb* defines the initial binning level *-regbe* defines the final binning level. - *-glt* and *-ght* **prevent** a correlation from occurring if the mean greyvalue of the extracted subvolume is less than *glt* or higher than *ght*.
- *-gpi* and *-gpp* regulate convergence options for each grid point `spam.DIC.register` run in a subvolume: the number of maximum iterations and the smallest change in the norm of Φ (:math:`\delta\Phi_{min}`) respectively.
- *-od* and *-pre* set the output directory and the prefix for the output files respectively.
......@@ -145,9 +145,9 @@ The code will return, for each measurement point/node (thus the centre of correl
- The point's number
- The point's Z,Y,X position
- The point's Z,Y,X displacement
- The subvolume's components of Φ matrix
- The error for this subvolume: final difference in greylevels between im1 and im2(:math:`\Phi`.x) subvolumes with a normalisation applied.
- The measured point's Z,Y,X displacement
- The measured subvolume's components of F matrix
- The correlation error for this subvolume: final difference in greylevels between im1 and im2(:math:`\Phi`.x) subvolumes with a normalisation applied.
- The number of iterations until convergence (equal to *-gpi* if convergence was not reached)
- The return status (**this is important!**):
......@@ -216,9 +216,9 @@ Here is an example of the vertical slices through the "Martian Simulant" M2EA05
Other key input options are:
- *-ld* sets how many iterations of dilation will be applied to each object to extract the greylevels to correlate
- *-reg* performs an initial registration of the two provided images -- **this is highly recommended**. In many cases (without too complicated and large displacement fields), this step can avoid the need to perform a computationally expensive pixel search. The option *-regb* bins (downscales by a given factor) the entire input images to save time.
- *-regbb* and *-regbe* to perform an *initial multiscale registration* of the two provided images -- **this is highly recommended**. In many cases (without too complicated and large displacement fields), this step can avoid the need to perform a computationally expensive pixel search. *-regbb* defines the initial binning level *-regbe* defines the final binning level.
- *-vt* the volume (in voxels) of the smallest object to correlate.
- *-gpi* and *-gpp* regulate convergence options for each grid point `spam.DIC.correlate.register` run in an object: the number of maximum iterations and the smallest change in the norm of Φ (:math:`\delta\Phi_{min}`) respectively.
- *-lci* and *-lcp* regulate convergence options for each grid point `spam.DIC.correlate.register` run in an object: the number of maximum iterations and the smallest change in the norm of Φ (:math:`\delta\Phi_{min}`) respectively.
- *-od* and *-pre* set the output directory and the prefix for the output files respectively.
As per the ``spam-ldic`` script, a large number of other options exist and can be seen with **- -help**.
......@@ -234,6 +234,27 @@ By default the outputs of a discrete correlation are:
- a TSV file with the transformation and correlation status for each object
- a VTK file with the displacement vectors of each object
The code will return, for each label, the following information:
- The label number
- The label's Z,Y,X position (centre of mass)
- The measured label's Z,Y,X displacement
- The measured label's components of F matrix
- The correlation error for this label: final difference in greylevels between im1 and im2(:math:`\Phi`.x) subvolumes with a normalisation applied.
- The number of iterations until convergence (equal to *-lci* if convergence was not reached)
- The return status (**this is important!**):
- 2 = **Convergence**: reached desired :math:`\delta\Phi_{min}` (*-lcp* input)
- 1 = **Not Convergence**: stopped by hitting the maximum number of iterations (*-lci* input) without diverging
- -1 = **Divergence**: error is more than 80% of previous iteration error (see `spam.DIC.correlate.register`)
- -2 = Iterative procedure stopped: singular matrix M cannot be inverted (see `spam.DIC.correlate.register`)
- -3 = Divergence: diverged on displacement or volumetric change condition (see `spam.DIC.correlate.register`)
- -4 = Margin alignment for im1 and im2 subvolumes failed (the iterative procedure never started)
- -5 = Failed margin alignment (too close to edge?) or failed volume condition
- -6 = Not used right now
- -7 = Label missing or NaNs/infinite in Phi
As per ``spam-ldic`` script, to perform a discrete correlation between these two M2EA05 states, again only very simple lines are needed:
.. code-block:: console
......
......@@ -105,8 +105,8 @@ class testAll(unittest.TestCase):
#spam.helpers.binarisation(im, threshold=0.5, mask=im > 0.2)
def test_slicePadded(self):
# case 1: inside
im = numpy.random.rand(100, 100, 100)
# case 1: inside
startStop = numpy.array([70, 90, 70, 90, 70, 90])
imSliced = spam.helpers.slicePadded(im, startStop)
self.assertEqual(numpy.subtract(im[startStop[0]:startStop[1], startStop[2]:startStop[3], startStop[4]:startStop[5]], imSliced).sum(), 0)
......@@ -143,6 +143,13 @@ class testAll(unittest.TestCase):
self.assertEqual(imSliced[110:, 110:, 110:].sum(), 0)
self.assertEqual(numpy.subtract(im, imSliced[10:110, 10:110, 10:110]).sum(), 0)
self.assertEqual(mask[10:110, 10:110, 10:110].sum(), 100**3)
## case 6: not touching im
startStop = numpy.array([100, 120, 100, 120, 100, 120])
imSliced, mask = spam.helpers.slicePadded(im, startStop, createMask = True)
self.assertEqual(list(imSliced.shape), [20, 20, 20])
self.assertEqual(numpy.isfinite(imSliced).sum(), 0)
self.assertEqual(mask.sum(), 0)
if __name__ == '__main__':
unittest.main()
......@@ -458,7 +458,7 @@ def _binarisation(im, threshold=0.0, boolean=False, op='>', mask=None):
def slicePadded(im, startStop, createMask = False):
"""
Extract padded slice from im, which is always of the dimensions asked (given from startStop)
Extract slice from im, padded with zeros, which is always of the dimensions asked (given from startStop)
Parameters
----------
......@@ -470,7 +470,7 @@ def slicePadded(im, startStop, createMask = False):
[Zmin, Zmax, Ymin, Ymax, Xmin, Xmax]
createMask : bool, optional
If True, return a of the padded slice, which is False when the slice falls outside im
If True, return a padded slice, which is False when the slice falls outside im
Default = False
Returns
......@@ -481,20 +481,35 @@ def slicePadded(im, startStop, createMask = False):
mask : 3D numpy array of bools
The 3D mask, only returned if createMask is True
"""
imSliced = numpy.zeros((startStop[1]-startStop[0], startStop[3]-startStop[2], startStop[5]-startStop[4]), dtype=im.dtype)
start = numpy.array([startStop[0], startStop[2], startStop[4]])
stop = numpy.array([startStop[1], startStop[3], startStop[5]])
imSliced = numpy.zeros((startStop[1]-startStop[0],
startStop[3]-startStop[2],
startStop[5]-startStop[4]), dtype=im.dtype)
start = numpy.array([startStop[0], startStop[2], startStop[4]])
stop = numpy.array([startStop[1], startStop[3], startStop[5]])
startOffset = numpy.array([max(0, start[0]), max(0, start[1]), max(0, start[2])])
stopOffset = numpy.array([min(im.shape[0], stop[0]), min(im.shape[1], stop[1]), min(im.shape[2], stop[2])])
startLocal = startOffset - start
stopLocal = startLocal + stopOffset - startOffset
imSliced[startLocal[0]:stopLocal[0], startLocal[1]:stopLocal[1], startLocal[2]:stopLocal[2]] = im[startOffset[0]:stopOffset[0], startOffset[1]:stopOffset[1], startOffset[2]:stopOffset[2]]
if createMask:
mask = numpy.zeros_like(imSliced, dtype=bool)
mask[startLocal[0]:stopLocal[0], startLocal[1]:stopLocal[1], startLocal[2]:stopLocal[2]] = 1
return imSliced, mask
startLocal = startOffset - start
stopLocal = startLocal + stopOffset - startOffset
# Check condition that we're asking for a slice of data wholly outside im
# This means either that the stop values are all smaller than 0
# OR the start are all bigger than im.shape
if numpy.all(stop < numpy.array([0, 0, 0])) or numpy.all(start >= numpy.array(im.shape)):
print("spam.helpers.slicePadded(): The extracted padded slice doesn't not touch the image!")
imSliced *= numpy.nan
if createMask:
return imSliced, numpy.zeros_like(imSliced, dtype=bool)
else:
imSliced[startLocal[0]:stopLocal[0],
startLocal[1]:stopLocal[1],
startLocal[2]:stopLocal[2]] = im[startOffset[0]:stopOffset[0],
startOffset[1]:stopOffset[1],
startOffset[2]:stopOffset[2]]
if createMask:
mask = numpy.zeros_like(imSliced, dtype=bool)
mask[startLocal[0]:stopLocal[0], startLocal[1]:stopLocal[1], startLocal[2]:stopLocal[2]] = 1
return imSliced, mask
return imSliced
......
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