Commit a2618016 authored by Edward Andò's avatar Edward Andò
Browse files

small fixes to strains + beginning of GPLv3 headers

parent f7b86bf7
This diff is collapsed.
......@@ -102,7 +102,7 @@ The decomposition of this tensor into strains and rotations is explained in deta
Strain invariants
-----------------
Having done a polar decomposition of **F** to end up with a strain tensor, it is useful now to decompose the strain tensor in an **isotropic** (*i.e.,* spherical) and **deviatoric** part and extract scalars representative of the volume and shear distortion of the material at that point, respectively.
For more details, please have a look at `these`_ (code: spamTheory) very helpful notes by Denis Caillerie.
For more details, please have a look at `these`_ (password: spamTheory) very helpful notes by Denis Caillerie.
.. _these: https://mycore.core-cloud.net/index.php/s/AobNABImYaKDlbi
......
#!/usr/bin/env python
"""
This python script is a wrapper for Simple ITK's watershed
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 tifffile
......
#!/usr/bin/env python
"""
This python script performs Discrete Digital Image Correlation 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
......
#!/usr/bin/env python
"""
This script deforms an image according to an input deformation field.
This can be very useful for generating deformed images to calculate a residual field
This script deforms an image according to an input 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/>.
"""
"""
This script can be very useful for generating deformed images to calculate a residual field
The current implementation will mesh correlation points with tetrahedra and deform them with displacements,
this has the advantage of speed, but the interpolation of displacements is approximative.
We don't use the more accurate `spam.DIC.deformationFunction.applyPhiField` which is slow for large images
"""
from __future__ import print_function
......
#!/usr/bin/env python
"""
This python computes strains from particle displacements 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/>.
"""
"""
This script calculates strains in a granular assembly using Bagi's strain tesselation technique.
This means that at the fundamental level, strains are calculated on space-filling tetrahedra that
connectivityect four grain centres.
connect four grain centres.
Tesselations can either be provided or calculated within the script.
The strains defined on tetrahedra can either be output as-are, or processed further,
......
#!/usr/bin/env python
# imports
"""
This python script is a graphical tool for aligning 3D images by eye using QT5 and 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/>.
"""
import sys
import os
......
#!/usr/bin/env python
"""
This python script (under development) performs Global Digital Image Correlation 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 tifffile
import numpy
......
#!/usr/bin/env python
"""
This python script performs Local Digital Image Correlation 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 os
import argparse
......
#!/usr/bin/env python
"""
This python script performs Multi-Modal Image Registration 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.DIC
import pickle
......
#!/usr/bin/env python
"""
This python script computes a strain field from a displacement field defined on a regular grid (e.g., from spam-ldic) 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 tifffile
import numpy
......@@ -7,7 +26,7 @@ import numpy
import argparse
import spam.helpers
import spam.DIC
import spam.mesh.structured as smesh
import spam.mesh
# Define argument parser object
parser = argparse.ArgumentParser()
......@@ -15,9 +34,9 @@ parser = argparse.ArgumentParser()
# Parse arguments with external helper function
args = spam.helpers.optionsParser.regularStrainsCalcParser(parser)
print(" --------------------------- ")
print("------------------------------")
print("| Regular Strain Calculation |")
print(" --------------------------- \n")
print("------------------------------\n")
print("\nCurrent Settings:")
argsDict = vars(args)
......@@ -52,14 +71,14 @@ else:
# Check if the correction of the input field is asked
if args.CORRECT_FIELD or args.CORRECT_MEDIAN_FILTER:
print("\nCorrecting/filtering field...")
fieldValues = spam.DIC.correctPhiField( fileName=args.inFile.name,
correctBadPoints = args.CORRECT_FIELD,
ignoreBackGround = ignoreBackGround,
deltaPhiNormMin=args.CORRECT_DELTA_PHI_NORM,
pixelSearchCCmin=args.CORRECT_PIXEL_SEARCH_CC,
neighbours=args.CORRECT_NEIGHBOURS,
filterPoints=args.CORRECT_MEDIAN_FILTER,
filterPointsRadius=args.CORRECT_MEDIAN_FILTER_RADIUS)
fieldValues = spam.DIC.correctPhiField(fileName=args.inFile.name,
correctBadPoints = args.CORRECT_FIELD,
ignoreBackGround = ignoreBackGround,
deltaPhiNormMin=args.CORRECT_DELTA_PHI_NORM,
pixelSearchCCmin=args.CORRECT_PIXEL_SEARCH_CC,
neighbours=args.CORRECT_NEIGHBOURS,
filterPoints=args.CORRECT_MEDIAN_FILTER,
filterPointsRadius=args.CORRECT_MEDIAN_FILTER_RADIUS)
# Extract the corrected displacement field and reshape it
disp = fieldValues[:,:3,-1].reshape(dims[0], dims[1], dims[2], 3)
else:
......@@ -84,32 +103,27 @@ if args.NOT_ONLY_STRAIN:
print("\nStart strain calculation...")
if largeStrains:
if onlyStrain:
strainMatrix, volStrain, devStrain = smesh.regularStrain(disp, nodeSpacing = [spaceZ, spaceY, spaceX], largeStrains=largeStrains, onlyStrain=onlyStrain)
else:
strainMatrix, F, r, volStrain, devStrain = smesh.regularStrain(disp, nodeSpacing = [spaceZ, spaceY, spaceX], largeStrains=largeStrains, onlyStrain=onlyStrain)
# for readability compute "onlyStrain" anyway
strainMatrix, F, r, volStrain, devStrain = spam.mesh.regularStrain(disp, nodeSpacing = [spaceZ, spaceY, spaceX], largeStrains=largeStrains, onlyStrain=True)
else:
if onlyStrain:
strainMatrix, volStrain, devStrain = smesh.regularStrain(disp, nodeSpacing = [spaceZ, spaceY, spaceX], largeStrains=largeStrains, onlyStrain=onlyStrain)
else:
strainMatrix, F, volStrain, devStrain = smesh.regularStrain(disp, nodeSpacing = [spaceZ, spaceY, spaceX], largeStrains=largeStrains, onlyStrain=onlyStrain)
strainMatrix, F, volStrain, devStrain = spam.mesh.regularStrain(disp, nodeSpacing = [spaceZ, spaceY, spaceX], largeStrains=largeStrains, onlyStrain=True)
# Extract strain tensor components
strainComponents = {}
strainComponents['yy'] = numpy.array(strainMatrix[:, :, :, 1, 1 ])
strainComponents['yx'] = numpy.array(strainMatrix[:, :, :, 1, 2 ])
strainComponents['xy'] = numpy.array(strainMatrix[:, :, :, 2, 1 ])
strainComponents['xx'] = numpy.array(strainMatrix[:, :, :, 2, 2 ])
strainComponents['yy'] = numpy.array(strainMatrix[:, :, :, 1, 1])
strainComponents['yx'] = numpy.array(strainMatrix[:, :, :, 1, 2])
strainComponents['xy'] = numpy.array(strainMatrix[:, :, :, 2, 1])
strainComponents['xx'] = numpy.array(strainMatrix[:, :, :, 2, 2])
strainComponents['volumetric'] = volStrain
strainComponents['deviatoric'] = devStrain
if twoD == False:
strainComponents['zz'] = numpy.array(strainMatrix[:, :, :, 0, 0 ])
strainComponents['zy'] = numpy.array(strainMatrix[:, :, :, 0, 1 ])
strainComponents['zx'] = numpy.array(strainMatrix[:, :, :, 0, 2 ])
strainComponents['yz'] = numpy.array(strainMatrix[:, :, :, 1, 0 ])
strainComponents['xz'] = numpy.array(strainMatrix[:, :, :, 2, 0 ])
strainComponents['zz'] = numpy.array(strainMatrix[:, :, :, 0, 0])
strainComponents['zy'] = numpy.array(strainMatrix[:, :, :, 0, 1])
strainComponents['zx'] = numpy.array(strainMatrix[:, :, :, 0, 2])
strainComponents['yz'] = numpy.array(strainMatrix[:, :, :, 1, 0])
strainComponents['xz'] = numpy.array(strainMatrix[:, :, :, 2, 0])
componentsL = ['zz', 'zy', 'zx', 'yz', 'yy', 'yx', 'xz', 'xy', 'xx', 'volumetric', 'deviatoric']
componentsS = ['zz', 'zy', 'zx', 'yy', 'yx', 'xx', 'volumetric', 'deviatoric']
else:
......
......@@ -3,11 +3,14 @@
import numpy
import scipy.ndimage
numpy.set_printoptions(precision=3, suppress=True)
#numpy.set_printoptions(precision=3, suppress=True)
# Point at which to consider no rotation
# Value at which to consider no rotation to avoid numerical issues
rotationAngleDegThreshold = 0.0001
# Value at which to consider no stretch to avoid numerical issues
distanceFromIdentity = 0.00001
###########################################################
# From components (translation, rotation, zoom, shear) compute Phi
###########################################################
......@@ -46,11 +49,11 @@ def computePhi(transformation, PhiCentre=[0.0, 0.0, 0.0], PhiPoint=[0.0, 0.0, 0.
----
Useful reference: Chapter 2 -- Rigid Body Registration -- John Ashburner & Karl J. Friston, although we use a symmetric shear
"""
Phi = numpy.eye(4, dtype='<f4')
Phi = numpy.eye(4)
# Translation:
if 't' in transformation:
tmp = numpy.eye(4, dtype='<f4')
tmp = numpy.eye(4)
tmp[0:3, 3] = transformation['t']
Phi = numpy.dot(Phi, tmp)
......@@ -73,14 +76,14 @@ def computePhi(transformation, PhiCentre=[0.0, 0.0, 0.0], PhiPoint=[0.0, 0.0, 0.
R = numpy.eye(3) + (numpy.sin(numpy.deg2rad(rotationAngleDeg)) * K) + \
((1.0 - numpy.cos(numpy.deg2rad(rotationAngleDeg))) * numpy.dot(K, K))
tmp = numpy.eye(4, dtype='<f4')
tmp = numpy.eye(4)
tmp[0:3, 0:3] = R
Phi = numpy.dot(Phi, tmp)
# Zoom + Shear
if 'z' in transformation or 's' in transformation:
tmp = numpy.eye(4, dtype='<f4')
tmp = numpy.eye(4)
if 'z' in transformation:
# Zoom components
......@@ -99,7 +102,7 @@ def computePhi(transformation, PhiCentre=[0.0, 0.0, 0.0], PhiPoint=[0.0, 0.0, 0.
tmp[2, 1] = transformation['s'][2]
Phi = numpy.dot(Phi, tmp)
elif 'U' in transformation:
tmp = numpy.eye(4, dtype='<f4')
tmp = numpy.eye(4)
tmp[:3, :3] = transformation['U']
Phi = numpy.dot(Phi, tmp)
......@@ -185,6 +188,7 @@ def decomposePhi(Phi, PhiCentre=[0.0, 0.0, 0.0], PhiPoint=[0.0, 0.0, 0.0]):
###########################################################
F = Phi[0:3, 0:3].copy()
###########################################################
# Calculate transformation by undoing F on the PhiPoint
###########################################################
......@@ -205,13 +209,18 @@ def decomposePhi(Phi, PhiCentre=[0.0, 0.0, 0.0], PhiPoint=[0.0, 0.0, 0.0]):
# Compute the Right Cauchy tensor
C = numpy.dot(F.T, F)
# 2020-02-24 EA and OS (day of the fire in 3SR): catch the case when C is practically the identity matrix (i.e., a rigid body motion)
if numpy.abs(numpy.subtract(C, numpy.eye(3))).sum() < distanceFromIdentity:
# This forces the rest of the function to give trivial results
C = numpy.eye(3)
# Solve eigen problem
CeigVal, CeigVec = numpy.linalg.eig(C)
# 2018-06-29 OS & ER check for negative eigenvalues
# test "really" negative eigenvalues
if CeigVal.any() / CeigVal.mean() < -1:
print("deformationFunction.decomposePhi(): negative eigen value in transpose(Phi).Phi which is really wrong. Exiting")
print("deformationFunction.decomposePhi(): negative eigen value in transpose(Phi). Phi which is really wrong. Exiting")
print("Eigenvalues are: {}".format(CeigenVal))
exit()
# for negative eigen values but close to 0 we set it to 0
......
......@@ -1056,6 +1056,19 @@ def regularStrainsCalcParser(parser):
dest='MASK',
help='Mask correlation points according to return status')
parser.add_argument('-n',
'--neighbours-for-strain-calculation',
type=numpy.uint,
default=1,
dest='STRAIN_NEIGHBOURS',
help="Neighbour distance, in units of NODE SPACING for displacement gradient calculation. Ignored if -cub is set. Default = 1")
parser.add_argument('-cub',
'--cubic-element',
action="store_true",
dest='Q8',
help='Use Q8 element interpolation? More noisy and strain values not centred on displacement points')
parser.add_argument('-cif',
'--correct-input-field',
action="store_true",
......
......@@ -252,7 +252,7 @@ def regularStrainCentred(displacementField, nodeSpacing=[1.0, 1.0, 1.0], neighbo
This function computes the strain field from a given displacement field.
This is a 3D implementation of:
"Computing strain felds from discrete displacement fields in 2D-solids", Geers et al., 1996
"Computing strain fields from discrete displacement fields in 2D-solids", Geers et al., 1996
Taken from the implmentation in "TomoWarp2: A local digital volume correlation code", Tudisco et al., 2017
......
Supports Markdown
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