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 9f964fbe authored by Gustavo Pinzon's avatar Gustavo Pinzon
Browse files

Merge branch 'master' of https://gricad-gitlab.univ-grenoble-alpes.fr/ttk/spam into ddicTools

parents a9c986dc 894bf309
......@@ -35,35 +35,36 @@ def main():
print("usage : spam-ereg BINNING [Im1 Im2 Phi]")
print("binning = 1")
binning = 1
try:
images = [tifffile.imread(sys.argv[2]), tifffile.imread(sys.argv[3])]
fileName1 = sys.argv[2]
fileName2 = sys.argv[3]
images = [tifffile.imread(fileName1), tifffile.imread(fileName2)]
except:
images = []
fileName = QFileDialog.getOpenFileName(
None, 'Open Image 1', os.getcwd())[0]
images.append(tifffile.imread(
fileName))
images.append(tifffile.imread(
QFileDialog.getOpenFileName(None, 'Open Image 2', os.path.dirname(os.path.realpath(fileName)))[0]))
fileName1 = QFileDialog.getOpenFileName(None, 'Open Image 1', os.getcwd())[0]
images.append(tifffile.imread(fileName1))
fileName2 = QFileDialog.getOpenFileName(None, 'Open Image 2', os.path.dirname(os.path.realpath(fileName1)))[0]
images.append(tifffile.imread(fileName2))
try:
f = numpy.genfromtxt(sys.argv[4], delimiter="\t", names=True)
Phi = numpy.array([[float(f["F11"]), float(f["F12"]), float(f["F13"]), float(f['Zdisp'])],
[float(f["F21"]), float(f["F22"]), float(f["F23"]), float(f['Ydisp'])],
[float(f["F31"]), float(f["F32"]), float(f["F33"]), float(f['Xdisp'])],
Phi = numpy.array([[float(f["Fzz"]), float(f["Fzy"] ), float(f["Fzx"]), float(f['Zdisp'])],
[float(f["Fyz"]), float(f["Fyy"]), float(f["Fyx"]), float(f['Ydisp'])],
[float(f["Fxz"]), float(f["Fxy"]), float(f["Fxx"]), float(f['Xdisp'])],
[0, 0, 0, 1]])
except:
try:
f = numpy.genfromtxt(QFileDialog.getOpenFileName(
None, '(optional) Open Phi TSV', os.path.dirname(os.path.realpath(fileName)))[0], delimiter="\t", names=True)
Phi = numpy.array([[float(f["F11"]), float(f["F12"]), float(f["F13"]), float(f['Zdisp'])],
[float(f["F21"]), float(f["F22"]), float(f["F23"]), float(f['Ydisp'])],
[float(f["F31"]), float(f["F32"]), float(f["F33"]), float(f['Xdisp'])],
f = numpy.genfromtxt(QFileDialog.getOpenFileName(None, '(optional) Open Phi TSV', os.path.dirname(os.path.realpath(fileName1)))[0], delimiter="\t", names=True)
Phi = numpy.array([[float(f["Fzz"]), float(f["Fzy"]), float(f["Fzx"]), float(f['Zdisp'])],
[float(f["Fyz"]), float(f["Fyy"]), float(f["Fyx"]), float(f['Ydisp'])],
[float(f["Fxz"]), float(f["Fxy"]), float(f["Fxx"]), float(f['Xdisp'])],
[0, 0, 0, 1]])
except:
Phi = numpy.eye(4, 4)
window = QWidget()
mainWindowGrid = QGridLayout(window)
eregWidget = visual.ereg(images, Phi, binning, ["image1", "image2"])
eregWidget = visual.ereg(images, Phi, binning, [fileName1, fileName2])
mainWindowGrid.addWidget(eregWidget, 1, 1)
window.show()
eregWidget.show()
......
......@@ -19,7 +19,6 @@ 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 os
import sys
import subprocess
......@@ -84,9 +83,15 @@ class MainWindow(QWidget):
self.Phi = numpy.eye(4)
self.mainWindowGrid = QGridLayout(self)
self.nonConvergedGrains = numpy.where(DDIC['returnStatus'] < args.RETURN_STAT_THRESHOLD)[0][1:]
# Issue #192 will be fixed here, by making sure the loew return stat list also has real boundin boxes
# (i.e., grains are really defined)
nonConvergedGrains = DDIC['returnStatus'] < args.RETURN_STAT_THRESHOLD
presentGrains = REFlabBB[:,1]>REFlabBB[:,0]
print(numpy.where(nonConvergedGrains), presentGrains)
self.nonConvergedGrains = numpy.where(numpy.logical_and(nonConvergedGrains, presentGrains))[0][0:]
self.N = 0 # Number of the current nonConvergedGrain that's being studied
print("Going to work on these labels:\n", self.nonConvergedGrains)
print("Going to work on these labels:\n", self.nonConvergedGrains, "(p.s. I removed non-existent labels:", numpy.where(~presentGrains)[0][1:]," )")
if len(self.nonConvergedGrains) > 0:
self.alignOneLabel()
self.labAndPhi = []
......@@ -114,38 +119,44 @@ class MainWindow(QWidget):
labelDilate=args.LABEL_DILATE, margin=args.margin,
maskOtherLabels=args.MASK)
# 2020-10-23: EA on Issue #186: using spam.helpers.slicePadded
REFsubvol = spam.helpers.slicePadded(REFgrey, REFgl['boundingBox']+numpy.array([0,1,0,1,0,1]))
if args.MASK:
# If mask asked, also flatten greylevels
REFsubvol[REFgl['subvol'] == 0] = 0
# 2020-10-23: EA on Issue #186: using spam.helpers.slicePadded
DEFsubvol = spam.helpers.slicePadded(DEFgrey, REFgl['boundingBox']+
numpy.array([0,1,0,1,0,1])+
numpy.array([displacementInt[0], displacementInt[0],
displacementInt[1], displacementInt[1],
displacementInt[2], displacementInt[2]]))
self.eregWidget = visual.ereg( [REFsubvol, DEFsubvol],
Phi, 1,
["{} - label {}".format(REFstr, nonConvergedGrain), "{} - label {}".format(DEFstr, nonConvergedGrain)], 0)
self.mainWindowGrid.addWidget(self.eregWidget, 1, 1)
self.nextLabelButton = QPushButton("Accept and move on to next grain", self)
self.nextLabelButton.clicked.connect(self.nextLabel)
self.mainWindowGrid.addWidget(self.nextLabelButton, 2, 1)
def nextLabel(self):
#print("Phi:", self.eregWidget.output())
self.eregWidget.close()
# Get Phi output from graphical
PhiTmp = self.eregWidget.output()
# Add back in int displacement
PhiTmp[0:3, -1] += self.diplacementInt
# nonConvergedGrain label number, eye-Phi
self.labAndPhi.append([self.nonConvergedGrains[self.N], PhiTmp])
if REFgl is not None:
# 2020-10-23: EA on Issue #186: using spam.helpers.slicePadded
REFsubvol = spam.helpers.slicePadded(REFgrey, REFgl['boundingBox']+numpy.array([0,1,0,1,0,1]))
if args.MASK:
# If mask asked, also flatten greylevels
REFsubvol[REFgl['subvol'] == 0] = 0
# 2020-10-23: EA on Issue #186: using spam.helpers.slicePadded
DEFsubvol = spam.helpers.slicePadded(DEFgrey, REFgl['boundingBox']+
numpy.array([0,1,0,1,0,1])+
numpy.array([displacementInt[0], displacementInt[0],
displacementInt[1], displacementInt[1],
displacementInt[2], displacementInt[2]]))
self.eregWidget = visual.ereg( [REFsubvol, DEFsubvol],
Phi, 1,
["{} - label {}".format(REFstr, nonConvergedGrain), "{} - label {}".format(DEFstr, nonConvergedGrain)], 0)
self.mainWindowGrid.addWidget(self.eregWidget, 1, 1)
self.nextLabelButton = QPushButton("Accept and move on to next grain", self)
self.nextLabelButton.clicked.connect(self.nextLabel)
self.mainWindowGrid.addWidget(self.nextLabelButton, 2, 1)
else:
self.nextLabel(widgetOpen=False)
def nextLabel(self, widgetOpen=True):
if widgetOpen:
self.eregWidget.close()
# Get Phi output from graphical
PhiTmp = self.eregWidget.output()
# Add back in int displacement
PhiTmp[0:3, -1] += self.diplacementInt
# nonConvergedGrain label number, eye-Phi
self.labAndPhi.append([self.nonConvergedGrains[self.N], PhiTmp])
else:
# This grain was skipped, let's add nothing in its place
self.labAndPhi.append([self.nonConvergedGrains[self.N], numpy.eye(4)])
# Move onto next grain, otherwise write and quit
self.N += 1
......
......@@ -330,6 +330,7 @@ if mpiRank == boss or not mpi:
margin=args.GRID_POINT_MARGIN,
maxIterations=args.GRID_POINT_MAX_ITERATIONS,
deltaPhiMin=args.GRID_POINT_MIN_PHI_CHANGE,
updateGradient=args.GRID_POINT_UPDATE_GRADIENT,
im1mask=im1mask,
minMaskCoverage = args.GRID_POINT_MASK_COVERAGE,
interpolationOrder=args.GRID_POINT_INTERPOLATION_ORDER,
......@@ -478,14 +479,15 @@ elif mpi: # We are not the mpi boss, so we are a lukasKanade worker
elif tag == 3:
# print "\n\n\t\tI am worker {} working on node {}".format( mpiRank, m )
lukasKanadeReturns = spam.DIC.correlate.register(m['im1'],
m['im2'],
im1mask=m['im1mask'],
PhiInit=m['PhiInit'],
margin=m['margin'],
maxIterations=m['maxIterations'],
deltaPhiMin=m['deltaPhiMin'],
interpolationOrder=m['interpolationOrder'],
interpolator=m['interpolator'])
m['im2'],
im1mask=m['im1mask'],
PhiInit=m['PhiInit'],
margin=m['margin'],
maxIterations=m['maxIterations'],
deltaPhiMin=m['deltaPhiMin'],
updateGradient=m['updateGradient'],
interpolationOrder=m['interpolationOrder'],
interpolator=m['interpolator'])
# print "\t\tI am worker {} Sending result for node {}".format( mpiRank, node )
mpiComm.send([mpiRank, m['nodeNumber'], lukasKanadeReturns, m['nodeDisplacement']], dest=boss, tag=4)
......
#!/usr/bin/env python
"""
This script performs a registration between two images, aiming to measure a
single Phi (a homogeneous deformation function) to map im1 into im2
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 is a good initial starting point for a the measurement of a displacement
field, if there is a homogeneous background movement to measure
"""
import numpy
import argparse
#import spam.helpers
#import spam.mesh
#import spam.label
import spam.DIC
#import spam.deformation
import tifffile
import os
# Define argument parser object
parser = argparse.ArgumentParser(description="spam-register "+spam.helpers.optionsParser.GLPv3descriptionHeader +\
"This script tries to measure Phi from im1 to im2\n",
formatter_class=argparse.RawTextHelpFormatter)
# Parse arguments with external helper function
args = spam.helpers.optionsParser.register(parser)
print("Current Settings:")
argsDict = vars(args)
for key in sorted(argsDict):
print("\t{}: {}".format(key, argsDict[key]))
# Load reference image
im1 = tifffile.imread(args.im1.name)
if args.MASK1:
im1mask = tifffile.imread(args.MASK1.name) != 0
else:
im1mask = None
im2 = tifffile.imread(args.im2.name)
if args.PHIFILE is not None:
PhiFromFile = spam.helpers.readCorrelationTSV(args.PHIFILE.name, fieldBinRatio=args.PHIFILE_BIN_RATIO)
# If the read Phi-file has only one line -- it's a single point registration!
if PhiFromFile['fieldCoords'].shape[0] == 1:
PhiInit = PhiFromFile['PhiField'][0]
#regCentre = PhiFromFile['fieldCoords'][0]
#print("\tI read a registration from a file in binning {} at centre {} at this scale".format(args.PHIFILE_BIN_RATIO, regCentre) )
print("\tI read a registration from a file in binning {}".format(args.PHIFILE_BIN_RATIO))
print("\tTranslations (px)")
print("\t\t", spam.deformation.decomposePhi(PhiInit)['t'])
print("\tRotations (deg)")
print("\t\t", spam.deformation.decomposePhi(PhiInit)['r'])
# If the read F-file contains multiple lines it's an F field!
else:
print("You can't pass a field to register!!!")
exit()
else:
PhiInit = None
if args.INTERPOLATION_ORDER == 1:
# Override interpolator to save memory
interpolator = 'C'
else:
interpolator = 'python'
regReturns = spam.DIC.correlate.registerMultiscale(im1,
im2,
args.BIN_BEGIN, binStop=args.BIN_END,
margin=args.MARGIN,
PhiRigid=args.RIGID,
im1mask=im1mask,
interpolationOrder=args.INTERPOLATION_ORDER,
maxIterations=args.MAX_ITERATIONS,
deltaPhiMin=args.MIN_DELTA_PHI,
updateGradient=args.UPDATE_GRADIENT,
interpolator=interpolator,
verbose=True,
imShowProgress=args.GRAPH)
if regReturns['returnStatus'] == 2:
print("\n\nRegistration converged, great... saving")
if regReturns['returnStatus'] == 1:
print("\n\nRegistration hit max iterations, OK... saving")
if regReturns['returnStatus'] > 0 and args.DEF:
tifffile.imsave(args.OUT_DIR+"/"+os.path.splitext(os.path.basename(args.im1.name))[0]+'-reg-def.tif', spam.DIC.applyPhi(im1, Phi=regReturns['Phi']))
if regReturns['returnStatus'] < 0:
print("\n\nWe're saving this registration but we don't trust it at all")
spam.helpers.writeRegistrationTSV(args.OUT_DIR+"/"+args.PREFIX+".tsv", (numpy.array(im1.shape )-1)/2.0, regReturns)
......@@ -145,6 +145,7 @@ TTK_modules_pb = ["mesh", "label", "filters", "measurements", "kalisphera", "DIC
### also add it to the list in docs/source/scripts.rst
###############################################################
scripts = ['scripts/spam-mmr',
'scripts/spam-reg',
'scripts/spam-gdic',
"scripts/spam-ddic",
"scripts/spam-ldic",
......
......@@ -349,7 +349,7 @@ def pixelSearchOnGrid(im1, im2, nodePositions, halfWindowSize, searchRange, PhiF
'pixelSearchCC': pixelSearchCC}
def registerOnGrid(im1, im2, nodePositions, halfWindowSize, PhiField=None, margin=None, maxIterations=None, deltaPhiMin=None, interpolationOrder=None, minMaskCoverage=0.5, im1mask=None, greyThreshold=[-numpy.inf, numpy.inf], mpi=False, killWorkersWhenDone=True):
def registerOnGrid(im1, im2, nodePositions, halfWindowSize, PhiField=None, margin=None, maxIterations=None, deltaPhiMin=None, updateGradient=None, interpolationOrder=None, minMaskCoverage=0.5, im1mask=None, greyThreshold=[-numpy.inf, numpy.inf], mpi=False, killWorkersWhenDone=True):
"""
This function handles grid-based local correlation, performing a "register" subpixel refinement.
Here we minimise a residual which is the difference between im1 and im2.
......@@ -384,6 +384,10 @@ def registerOnGrid(im1, im2, nodePositions, halfWindowSize, PhiField=None, margi
deltaPhiMin : float, optional
Stop iterating when norm of F gets below this value
Default = None (use ``register``'s default)
updateGradient : bool, optional
Should the gradient of the image be computed (and updated) on the deforming im2?
Default = None (use ``register``'s default)
interpolationOrder : int, optional
Greyscale interpolation order
......@@ -607,6 +611,7 @@ def registerOnGrid(im1, im2, nodePositions, halfWindowSize, PhiField=None, margi
'margin': 1, # see top of this file for compensation
'maxIterations': maxIterations,
'deltaPhiMin': deltaPhiMin,
'updateGradient': updateGradient,
'interpolationOrder': interpolationOrder,
'interpolator': interpolator,
'nodeDisplacement': imagetteReturns['nodeDisplacement']
......@@ -628,6 +633,7 @@ def registerOnGrid(im1, im2, nodePositions, halfWindowSize, PhiField=None, margi
margin=1, # see top of this file for compensation
maxIterations=maxIterations,
deltaPhiMin=deltaPhiMin,
updateGradient=updateGradient,
interpolationOrder=interpolationOrder,
verbose=False,
imShowProgress=False)
......
......@@ -43,7 +43,7 @@ def ldicParser(parser):
parser.add_argument('inFiles',
nargs='+',
type=argparse.FileType('r'),
help="A space-separated list of two 3D greyscale tiff files to correlate, in order")
help="A space-separated list of two or more 3D greyscale tiff files to correlate, in order")
parser.add_argument('-mf1',
'--maskFile1',
......@@ -215,7 +215,7 @@ def ldicParser(parser):
help="Maximum iterations for grid-point registration. Default = 50")
parser.add_argument('-gpp',
'--grid-point-min-phi-change',
'--grid-point-min-delta-phi',
type=numpy.float,
default=0.001,
dest='GRID_POINT_MIN_PHI_CHANGE',
......@@ -235,6 +235,12 @@ def ldicParser(parser):
dest='GRID_POINT_MASK_COVERAGE',
help="In case a mask is defined, tolerance for a subvolume's pixels to be masked before it is skipped with RS=-5. Default = 0.5")
parser.add_argument('-gpug',
'--grid-point-update-gradient',
action="store_true",
dest='GRID_POINT_UPDATE_GRADIENT',
help='Update gradient in grid-point registration? More computation time but more robust and possibly fewer iterations.')
parser.add_argument('-sef',
'--series-Ffile',
action="store_true",
......@@ -597,8 +603,8 @@ def ddicParser(parser):
dest='LABEL_CORRELATE_MAX_ITERATIONS',
help="Maximum iterations for label correlation. Default = 50")
parser.add_argument('-lcp',
'--label-correlate-min-phi-change',
parser.add_argument('-lcdp',
'--label-correlate-min-delta-phi',
type=numpy.float,
default=0.001,
dest='LABEL_CORRELATE_MIN_PHI_CHANGE',
......@@ -1513,7 +1519,6 @@ def eregDiscreteParser(parser):
return args
def moveLabelsParser(parser):
parser.add_argument('LabFile',
metavar='LabFile',
......@@ -1919,3 +1924,154 @@ def deformImageFromFieldParser(parser):
return args
def register(parser):
parser.add_argument('im1',
metavar='im1',
type=argparse.FileType('r'),
help="Greyscale image of reference state for correlation")
parser.add_argument('im2',
metavar='im2',
type=argparse.FileType('r'),
help="Greyscale image of deformed state for correlation")
parser.add_argument('-mf1',
'--maskFile1',
dest='MASK1',
default=None,
type=argparse.FileType('r'),
help="Path to tiff file containing the mask of image 1 -- masks zones not to correlate, which should be == 0")
parser.add_argument('-pf',
'-phiFile',
dest='PHIFILE',
default=None,
type=argparse.FileType('r'),
help="Path to TSV file containing the deformation function field (required)")
parser.add_argument('-pfb',
'--phiFile-bin-ratio',
type=int,
default=1,
dest='PHIFILE_BIN_RATIO',
help="Ratio of binning level between loaded Phi file and current calculation. If the input Phi file has been obtained on a 500x500x500 image and now the calculation is on 1000x1000x1000, this should be 2. Default = 1")
parser.add_argument('-rig',
'--rigid',
action="store_true",
dest='RIGID',
help='Only do a rigid registration (i.e., displacements and rotations)?')
parser.add_argument('-bb',
'--binning-begin',
type=int,
default=4,
dest='BIN_BEGIN',
help='Initial binning to apply to input images for initial registration. Default = 4')
parser.add_argument('-be',
'--binning-end',
type=int,
default=1,
dest='BIN_END',
help='Binning level to stop at for initial registration. Default = 1')
parser.add_argument('-m',
'-mar',
'--margin',
type=float,
default=0.1,
dest='MARGIN',
help='Interpolation margin in proportions of image size. Default = 0.1, which means 0.1 * image size from both sides in all directions')
parser.add_argument('-m3',
'-mar3',
'--margin3',
nargs=3,
type=int,
default=None,
dest='MARGIN',
help="Interpolation margin in pixels. Default = 0.1 * image size from both sides in all directions")
parser.add_argument('-ug',
'--update-gradient',
action="store_true",
dest='UPDATE_GRADIENT',
help='Update gradient during newton iterations? More computation time but more robust and possibly fewer iterations. Default = False')
parser.add_argument('-it',
'--max-iterations',
type=int,
default=50,
dest='MAX_ITERATIONS',
help="Maximum number of iterations. Default = 50")
parser.add_argument('-dp',
'--min-delta-phi',
type=numpy.float,
default=0.0001,
dest='MIN_DELTA_PHI',
help="Minimum delta Phi for convergence. Default = 0.0001")
parser.add_argument('-o',
'--interpolation-order',
type=int,
default=1,
dest='INTERPOLATION_ORDER',
help="Interpolation order for image interpolation. Default = 1")
parser.add_argument('-g',
'--graph',
action="store_true",
default=False,
dest='GRAPH',
help="Activate graphical mode to look at iterations")
parser.add_argument('-od',
'--out-dir',
type=str,
default=None,
dest='OUT_DIR',
help="Output directory, default is the dirname of gmsh file")
parser.add_argument('-pre',
'--prefix',
type=str,
default=None,
dest='PREFIX',
help='Prefix for output files (without extension). Default is basename of mesh file')
parser.add_argument('-def',
'--save-deformed-image1',
action="store_true",
default=False,
dest='DEF',
help="Activate the saving of a deformed image 1 (as <im1>-reg-def.tif)")
args = parser.parse_args()
# If we have no out dir specified, deliver on our default promise -- this can't be done inline before since parser.parse_args() has not been run at that stage.
if args.OUT_DIR is None:
args.OUT_DIR = os.path.dirname(args.im1.name)
# However if we have no dir, notice this and make it the current directory.
if args.OUT_DIR == "":
args.OUT_DIR = "./"
else:
# Check existence of output directory
try:
if args.OUT_DIR:
os.makedirs(args.OUT_DIR)
else:
args.DIR_out = os.path.dirname(args.im1.name)
except OSError:
if not os.path.isdir(args.OUT_DIR):
raise
# Output file name prefix
if args.PREFIX is None:
args.PREFIX = os.path.splitext(os.path.basename(args.im1.name))[0] + "-" + os.path.splitext(os.path.basename(args.im2.name))[0] + "-registration"
return args
......@@ -954,13 +954,13 @@ class ereg(QWidget):
fileName = tmp if tmp.split(".")[-1] in ["tsv"] else tmp + ".tsv"
# save.writeRegistrationTSV(fileName, (numpy.array(self.images[1].shape) - 1) / 2.0, {
# 'PhiCentre': self.Phis[1], "returnStatus": 2, "iterations": self.iterations, "error": 100, "deltaPhiNorm": 0.1})
TSVheader = "Zpos\tYpos\tXpos\tFzz\tFzy\tFzx\tZdisp\tFyz\tFyy\tFyx\tYdisp\tFxz\tFxy\tFxx\tXdisp\tbin\treturnStatus"
TSVheader = "Zpos\tYpos\tXpos\tFzz\tFzy\tFzx\tZdisp\tFyz\tFyy\tFyx\tYdisp\tFxz\tFxy\tFxx\tXdisp\tbin\treturnStatus\tdeltaPhiNorm\terror\titerations"
centre = (numpy.array(self.images[0].shape)-1)/2.0
output = numpy.array([[centre[0]], [centre[1]], [centre[2]],
[self.Phis[1][0, 0]], [self.Phis[1][0, 1]], [self.Phis[1][0, 2]], [self.Phis[1][0, 3]],
[self.Phis[1][1, 0]], [self.Phis[1][1, 1]], [self.Phis[1][1, 2]], [self.Phis[1][1, 3]],
[self.Phis[1][2, 0]], [self.Phis[1][2, 1]], [self.Phis[1][2, 2]], [self.Phis[1][2, 3]],
[self.binning], [0]])
[self.binning], [0], [1.0], [self.images[0].mean()], [0] ])
numpy.savetxt(fileName, output.T, fmt='%.7f', delimiter='\t', newline='\n', comments='', header=TSVheader)
self.resultLabel.setText("Phi saved in: {}".format(os.path.join(os.getcwd(), fileName)))
self.resultLabel.setStyleSheet("QLabel {font-weight: bold; color: green;}")
......
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