Coverage for /usr/local/lib/python3.8/site-packages/spam/helpers/tsvio.py: 97%

352 statements  

« prev     ^ index     » next       coverage.py v7.2.3, created at 2023-11-22 13:26 +0000

1""" 

2Library of SPAM functions for reading and writing TSV files. 

3Copyright (C) 2020 SPAM Contributors 

4 

5This program is free software: you can redistribute it and/or modify it 

6under the terms of the GNU General Public License as published by the Free 

7Software Foundation, either version 3 of the License, or (at your option) 

8any later version. 

9 

10This program is distributed in the hope that it will be useful, but WITHOUT 

11ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 

12FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 

13more details. 

14 

15You should have received a copy of the GNU General Public License along with 

16this program. If not, see <http://www.gnu.org/licenses/>. 

17""" 

18 

19import numpy 

20import os 

21 

22 

23def writeRegistrationTSV(fileName, regCentre, regReturns): 

24 ''' 

25 This function writes a correctly formatted TSV file from the result of a single `register()` call, allowing it to be used as an initial registration. 

26 

27 Parameters 

28 ---------- 

29 fileName : string 

30 The file name for output, suggestion: it should probably end with ".tsv" 

31 

32 regCentre : 3-component list 

33 A list containing the point at which `Phi` has been measured. 

34 This is typically the middle of the image, and can be obtained as follows: 

35 (numpy.array( im.shape )-1)/2.0 

36 The conversion to a numpy array is necessary, since tuples cannot be divided by a number directly. 

37 

38 regReturns : dictionary 

39 This should be the return dictionary from `register`. 

40 From this dictionary will be extracted: 'Phi', 'error', 'iterations', 'returnStatus', 'deltaPhiNorm' 

41 

42 ''' 

43 try: 

44 regPhi = regReturns['Phi'] 

45 except: 

46 print("spam.helpers.tsvio.writeRegistrationTSV(): Attempting to read old format") 

47 regPhi = regReturns['PhiCentre'] 

48 

49 # catch 2D images 

50 if len(regCentre) == 2: 

51 regCentre = [0, regCentre[0], regCentre[1]] 

52 

53 # Make one big array for writing: 

54 header = "NodeNumber\tZpos\tYpos\tXpos\tFzz\tFzy\tFzx\tZdisp\tFyz\tFyy\tFyx\tYdisp\tFxz\tFxy\tFxx\tXdisp\terror\titerations\treturnStatus\tdeltaPhiNorm" 

55 try: 

56 outMatrix = numpy.array([[1], 

57 [regCentre[0]], 

58 [regCentre[1]], 

59 [regCentre[2]], 

60 [regPhi[0, 0]], 

61 [regPhi[0, 1]], 

62 [regPhi[0, 2]], 

63 [regPhi[0, 3]], 

64 [regPhi[1, 0]], 

65 [regPhi[1, 1]], 

66 [regPhi[1, 2]], 

67 [regPhi[1, 3]], 

68 [regPhi[2, 0]], 

69 [regPhi[2, 1]], 

70 [regPhi[2, 2]], 

71 [regPhi[2, 3]], 

72 [regReturns['error']], 

73 [regReturns['iterations']], 

74 [regReturns['returnStatus']], 

75 [regReturns['deltaPhiNorm']]]) 

76 except: 

77 print("spam.helpers.tsvio.writeRegistrationTSV(): Attempting to read old format") 

78 outMatrix = numpy.array([[1], 

79 [regCentre[0]], 

80 [regCentre[1]], 

81 [regCentre[2]], 

82 [regPhi[0, 0]], 

83 [regPhi[0, 1]], 

84 [regPhi[0, 2]], 

85 [regPhi[0, 3]], 

86 [regPhi[1, 0]], 

87 [regPhi[1, 1]], 

88 [regPhi[1, 2]], 

89 [regPhi[1, 3]], 

90 [regPhi[2, 0]], 

91 [regPhi[2, 1]], 

92 [regPhi[2, 2]], 

93 [regPhi[2, 3]], 

94 [regReturns['error']], 

95 [regReturns['iterationNumber']], 

96 [regReturns['returnStatus']], 

97 [regReturns['deltaPhiNorm']]]) 

98 

99 numpy.savetxt(fileName, 

100 outMatrix.T, 

101 fmt='%.7f', 

102 delimiter='\t', 

103 newline='\n', 

104 comments='', 

105 header=header) 

106 

107 

108def writeStrainTSV(fileName, points, decomposedFfield, firstColumn="StrainPointNumber", startRow=0): 

109 """ 

110 This function writes strains to a TSV file, hiding the complexity of counting and naming columns 

111 

112 Parameters 

113 ---------- 

114 fileName : string 

115 fileName including full path and .tsv at the end to write 

116 

117 points : Nx3 numpy array 

118 Points at which the strain is defined 

119 

120 decomposedFfield : dictionary 

121 Dictionary containing strain components as per output from spam.deformation.FfieldRegularQ8, FfieldRegularGeers or FfieldBagi 

122 

123 firstColumn : string, optional 

124 How to name the first column (series number) of the TSV 

125 Default = "StrainPointNumber" 

126 

127 startRow : int, optional 

128 Are your points and strains offset from zero? Offset TSV by adding blank lines, don't use this if you don't know what you're doing 

129 Default = 0 

130 

131 Returns 

132 ------- 

133 None 

134 """ 

135 # This is the minimum header for everyone 

136 header = "{}\tZpos\tYpos\tXpos".format(firstColumn) 

137 

138 # Allocate minimum output array 

139 outMatrix = numpy.array([numpy.arange(points.shape[0]), 

140 points[:, 0], 

141 points[:, 1], 

142 points[:, 2]]).T 

143 

144 nCols = 4 

145 

146 for component in decomposedFfield.keys(): 

147 if component == 'vol' or component == 'dev' or component == 'volss' or component == 'devss': 

148 header = header + "\t{}".format(component) 

149 outMatrix = numpy.hstack([outMatrix, numpy.array([decomposedFfield[component].ravel()]).T]) 

150 nCols += 1 

151 

152 if component == 'r' or component == 'z': 

153 for n, di in enumerate(['z', 'y', 'x']): 

154 header = header + "\t{}{}".format(component, di) 

155 outMatrix = numpy.hstack([outMatrix, numpy.array([decomposedFfield[component].reshape(-1,3)[:,n].ravel()]).T]) 

156 nCols += 1 

157 

158 if component == 'e' or component == 'U': 

159 for n, di in enumerate(['z', 'y', 'x']): 

160 for m, dj in enumerate(['z', 'y', 'x']): 

161 if m>=n: 

162 header = header + "\t{}{}{}".format(component, di, dj) 

163 outMatrix = numpy.hstack([outMatrix, numpy.array([decomposedFfield[component].reshape(-1,3,3)[:,n,m].ravel()]).T]) 

164 nCols += 1 

165 

166 # This is mostly for discrete Strains, where we can avoid or not the zero-numbered grain 

167 if startRow > 0: 

168 for i in range(startRow): 

169 header = header+'\n0.0' 

170 for j in range(1,nCols): 

171 header = header+'\t0.0' 

172 

173 numpy.savetxt(fileName, 

174 outMatrix, 

175 delimiter='\t', 

176 fmt='%.7f', 

177 newline='\n', 

178 comments='', 

179 header=header) 

180 

181 

182def readCorrelationTSV(fileName, fieldBinRatio=1.0, readOnlyDisplacements=False, readConvergence=True, readPixelSearchCC=False, readError=False, readLabelDilate=False): 

183 """ 

184 This function reads a TSV file containing a field of deformation functions **Phi** at one or a number of points. 

185 This is typically the output of the spam-ldic and spam-ddic scripts, 

186 or anything written by `writeRegistrationTSV`. 

187 

188 Parameters 

189 ---------- 

190 fileName : string 

191 Name of the file 

192 

193 fieldBinRatio : int, optional 

194 if the input field is refer to a binned version of the image 

195 `e.g.`, if ``fieldBinRatio = 2`` the field_name values have been calculated 

196 for an image half the size of what the returned PhiField is referring to 

197 Default = 1.0 

198 

199 readOnlyDisplacements : bool, optional 

200 Read "zDisp", "yDisp", "xDisp", displacements from the TSV file, and not the rest of the Phi matrix? 

201 Default = False 

202 

203 readConvergence : bool, optional 

204 Read "returnStatus", "deltaPhiNorm", "iterations", from file 

205 Default = True 

206 

207 readPixelSearchCC : bool, optional 

208 Read "pixelSearchCC" from file 

209 Default = False 

210 

211 readError : bool, optional 

212 Read '"error"from file 

213 Default = False 

214 

215 readLabelDilate : bool, optional 

216 Read "LabelDilate" from file 

217 Default = False 

218 

219 Returns 

220 ------- 

221 Dictionary containing: 

222 fieldDims: 1x3 array of the field dimensions (ZYX) (for a regular grid DIC result) 

223 

224 numberOfLabels: number of labels (for a discrete DIC result) 

225 

226 fieldCoords: nx3 array of n points coordinates (ZYX) 

227 

228 PhiField: nx4x4 array of n points transformation operators 

229 

230 returnStatus: nx1 array of n points returnStatus from the correlation 

231 

232 deltaPhiNorm: nx1 array of n points deltaPhiNorm from the correlation 

233 

234 iterations: nx1 array of n points iterations from the correlation 

235 

236 pixelSearchCC: nx1 array of n points pixelSearchCC from the correlation 

237 

238 error: nx1 array of n points error from the correlation 

239 

240 labelDilate: nx1 array of n points labelDilate from the correlation 

241 

242 """ 

243 if not os.path.isfile(fileName): 

244 print("\n\tspam.tsvio.readCorrelationTSV(): {} is not a file. Exiting.".format(fileName)) 

245 return 

246 

247 f = numpy.genfromtxt(fileName, delimiter="\t", names=True) 

248 # RS = [] 

249 # deltaPhiNorm = [] 

250 # pixelSearchCC = [] 

251 

252 # If this is a one-line TSV file (an initial registration for example) 

253 if f.size == 1: 

254 #print("\tspam.tsvio.readCorrelationTSV(): {} seems only to have one line.".format(fileName)) 

255 nPoints = 1 

256 numberOfLabels = 1 

257 fieldDims = [1, 1, 1] 

258 

259 # Sort out the field coordinates 

260 fieldCoords = numpy.zeros((nPoints, 3)) 

261 fieldCoords[:, 0] = f['Zpos'] * fieldBinRatio 

262 fieldCoords[:, 1] = f['Ypos'] * fieldBinRatio 

263 fieldCoords[:, 2] = f['Xpos'] * fieldBinRatio 

264 

265 # Sort out the components of Phi 

266 PhiField = numpy.zeros((nPoints, 4, 4)) 

267 PhiField[0] = numpy.eye(4) 

268 

269 # Fill in displacements 

270 try: 

271 PhiField[0, 0, 3] = f['Zdisp'] * fieldBinRatio 

272 PhiField[0, 1, 3] = f['Ydisp'] * fieldBinRatio 

273 PhiField[0, 2, 3] = f['Xdisp'] * fieldBinRatio 

274 except ValueError: 

275 PhiField[0, 0, 3] = f['F14'] * fieldBinRatio 

276 PhiField[0, 1, 3] = f['F24'] * fieldBinRatio 

277 PhiField[0, 2, 3] = f['F34'] * fieldBinRatio 

278 

279 if not readOnlyDisplacements: 

280 try: 

281 # Get non-displacement components 

282 PhiField[0, 0, 0] = f['Fzz'] 

283 PhiField[0, 0, 1] = f['Fzy'] 

284 PhiField[0, 0, 2] = f['Fzx'] 

285 PhiField[0, 1, 0] = f['Fyz'] 

286 PhiField[0, 1, 1] = f['Fyy'] 

287 PhiField[0, 1, 2] = f['Fyx'] 

288 PhiField[0, 2, 0] = f['Fxz'] 

289 PhiField[0, 2, 1] = f['Fxy'] 

290 PhiField[0, 2, 2] = f['Fxx'] 

291 except: 

292 print("spam.helpers.tsvio.readCorrelationTSV(): Attempting to read old format, please update your TSV file (F11 should be Fzz and so on)") 

293 # Get non-displacement components 

294 PhiField[0, 0, 0] = f['F11'] 

295 PhiField[0, 0, 1] = f['F12'] 

296 PhiField[0, 0, 2] = f['F13'] 

297 PhiField[0, 1, 0] = f['F21'] 

298 PhiField[0, 1, 1] = f['F22'] 

299 PhiField[0, 1, 2] = f['F23'] 

300 PhiField[0, 2, 0] = f['F31'] 

301 PhiField[0, 2, 1] = f['F32'] 

302 PhiField[0, 2, 2] = f['F33'] 

303 

304 if readConvergence: 

305 try: 

306 # Return ReturnStatus, SubPixelDeltaFnorm, SubPixelIterations 

307 RS = f['returnStatus'] 

308 deltaPhiNorm = f['deltaPhiNorm'] 

309 iterations = f['iterations'] 

310 except: 

311 print("spam.helpers.tsvio.readCorrelationTSV(): Attempting to read old format, please update your TSV file (SubPix should be )") 

312 # Return ReturnStatus, SubPixelDeltaFnorm, SubPixelIterations 

313 RS = f['SubPixReturnStat'] 

314 deltaPhiNorm = f['SubPixDeltaPhiNorm'] 

315 iterations = f['SubPixIterations'] 

316 if readError: 

317 try: 

318 error = f['error'] 

319 except ValueError: 

320 pass 

321 # Return pixelSearchCC 

322 if readPixelSearchCC: 

323 pixelSearchCC = numpy.zeros(nPoints) 

324 try: 

325 pixelSearchCC = f['pixelSearchCC'] 

326 except ValueError: 

327 pass 

328 

329 # Return error 

330 if readError: 

331 error = numpy.zeros(nPoints) 

332 try: 

333 error = f['error'] 

334 except ValueError: 

335 pass 

336 # Return labelDilate 

337 if readLabelDilate: 

338 labelDilate = numpy.zeros(nPoints) 

339 try: 

340 labelDilate = f['LabelDilate'] 

341 except ValueError: 

342 pass 

343 

344 

345 pixelSearchCC = 0 

346 

347 # there is more than one line in the TSV file -- a field -- typical case 

348 else: 

349 nPoints = f.size 

350 

351 # check if it is a ddic or ldic result 

352 try: 

353 f["NodeNumber"] 

354 # it's a local DIC result with grid points regularly spaced 

355 DICgrid = True 

356 DICdiscrete = False 

357 except ValueError: 

358 # it's a discrete DIC result with values in each label's centre of mass 

359 DICdiscrete = True 

360 DICgrid = False 

361 

362 # Sort out the field coordinates 

363 fieldCoords = numpy.zeros((nPoints, 3)) 

364 fieldCoords[:, 0] = f['Zpos'] * fieldBinRatio 

365 fieldCoords[:, 1] = f['Ypos'] * fieldBinRatio 

366 fieldCoords[:, 2] = f['Xpos'] * fieldBinRatio 

367 

368 if DICgrid: 

369 fieldDims = numpy.array([len(numpy.unique(f['Zpos'])), len(numpy.unique(f['Ypos'])), len(numpy.unique(f['Xpos']))]) 

370 numberOfLabels = 0 

371 print("\tspam.tsvio.readCorrelationTSV(): Field dimensions: {}".format(fieldDims)) 

372 elif DICdiscrete: 

373 numberOfLabels = len(f["Label"]) 

374 fieldDims = [0, 0, 0] 

375 print("\tspam.tsvio.readCorrelationTSV(): Number of labels: {}".format(numberOfLabels)) 

376 

377 # create ReturnStatus and deltaPhiNorm matrices if asked 

378 if readConvergence: 

379 try: 

380 RS = numpy.zeros(nPoints) 

381 RS[:] = f[:]['returnStatus'] 

382 deltaPhiNorm = numpy.zeros(nPoints) 

383 deltaPhiNorm = f[:]['deltaPhiNorm'] 

384 iterations = numpy.zeros(nPoints) 

385 iterations = f[:]['iterations'] 

386 except: 

387 print("spam.helpers.tsvio.readCorrelationTSV(): Attempting to read old format, please update your TSV file") 

388 RS = numpy.zeros(nPoints) 

389 RS[:] = f[:]['SubPixReturnStat'] 

390 deltaPhiNorm = numpy.zeros(nPoints) 

391 deltaPhiNorm = f[:]['SubPixDeltaPhiNorm'] 

392 iterations = numpy.zeros(nPoints) 

393 iterations = f[:]['SubPixIterations'] 

394 

395 # Return pixelSearchCC 

396 if readPixelSearchCC: 

397 pixelSearchCC = numpy.zeros(nPoints) 

398 try: 

399 pixelSearchCC = f[:]['pixelSearchCC'] 

400 except ValueError: 

401 pass 

402 

403 # Return error 

404 if readError: 

405 error = numpy.zeros(nPoints) 

406 try: 

407 error = f[:]['error'] 

408 except ValueError: 

409 pass 

410 # Return labelDilate 

411 if readLabelDilate: 

412 labelDilate = numpy.zeros(nPoints) 

413 try: 

414 labelDilate = f[:]['LabelDilate'] 

415 except ValueError: 

416 pass 

417 

418 # Sort out the components of Phi 

419 PhiField = numpy.zeros((nPoints, 4, 4)) 

420 for n in range(nPoints): 

421 # Initialise with Identity matrix 

422 PhiField[n] = numpy.eye(4) 

423 

424 # Fill in displacements 

425 try: 

426 PhiField[n, 0, 3] = f[n]['Zdisp'] * fieldBinRatio 

427 PhiField[n, 1, 3] = f[n]['Ydisp'] * fieldBinRatio 

428 PhiField[n, 2, 3] = f[n]['Xdisp'] * fieldBinRatio 

429 except ValueError: 

430 PhiField[n, 0, 3] = f[n]['F14'] * fieldBinRatio 

431 PhiField[n, 1, 3] = f[n]['F24'] * fieldBinRatio 

432 PhiField[n, 2, 3] = f[n]['F34'] * fieldBinRatio 

433 

434 if not readOnlyDisplacements: 

435 try: 

436 # Get non-displacement components 

437 PhiField[n, 0, 0] = f[n]['Fzz'] 

438 PhiField[n, 0, 1] = f[n]['Fzy'] 

439 PhiField[n, 0, 2] = f[n]['Fzx'] 

440 PhiField[n, 1, 0] = f[n]['Fyz'] 

441 PhiField[n, 1, 1] = f[n]['Fyy'] 

442 PhiField[n, 1, 2] = f[n]['Fyx'] 

443 PhiField[n, 2, 0] = f[n]['Fxz'] 

444 PhiField[n, 2, 1] = f[n]['Fxy'] 

445 PhiField[n, 2, 2] = f[n]['Fxx'] 

446 except: 

447 print("spam.helpers.tsvio.readCorrelationTSV(): Attempting to read old format, please update your TSV file (F11 should be Fzz and so on)") 

448 # Get non-displacement components 

449 PhiField[n, 0, 0] = f[n]['F11'] 

450 PhiField[n, 0, 1] = f[n]['F12'] 

451 PhiField[n, 0, 2] = f[n]['F13'] 

452 PhiField[n, 1, 0] = f[n]['F21'] 

453 PhiField[n, 1, 1] = f[n]['F22'] 

454 PhiField[n, 1, 2] = f[n]['F23'] 

455 PhiField[n, 2, 0] = f[n]['F31'] 

456 PhiField[n, 2, 1] = f[n]['F32'] 

457 PhiField[n, 2, 2] = f[n]['F33'] 

458 

459 output = {"fieldDims": fieldDims, 

460 "numberOfLabels": numberOfLabels, 

461 "fieldCoords": fieldCoords} 

462 if readConvergence: 

463 output.update({"returnStatus": RS, 

464 "deltaPhiNorm": deltaPhiNorm, 

465 "iterations": iterations}) 

466 if readError: 

467 output.update({"error": error}) 

468 if readPixelSearchCC: 

469 output.update({"pixelSearchCC": pixelSearchCC}) 

470 if readLabelDilate: 

471 output.update({"LabelDilate": labelDilate}) 

472 

473 if readOnlyDisplacements: 

474 output.update({"displacements": PhiField[:, 0:3, -1]}) 

475 else: 

476 output.update({"PhiField": PhiField}) 

477 

478 return output 

479 

480 

481def readStrainTSV(fileName): 

482 """ 

483 This function reads a strain TSV file written by `spam-discreteStrain` or `spam-regularStrain` 

484 

485 Parameters 

486 ---------- 

487 fileName : string 

488 Name of the file 

489 

490 Returns 

491 ------- 

492 Dictionary containing: 

493 

494 fieldDims: 1x3 array of the field dimensions (ZYX) 

495 

496 fieldCoords : nx3 array of the field coordinates (ZYX) 

497 

498 numberOfLabels: number of labels (for a discrete strain result) 

499 

500 vol: nx1 array of n points with volumetric strain computed under the hypotesis of large strains (if computed) 

501 

502 dev: nx1 array of n points with deviatoric strain computed under the hypotesis of large strains (if computed) 

503 

504 volss: nx1 array of n points with volumetric strain computed under the hypotesis of small strains (if computed) 

505 

506 devss: nx1 array of n points with deviatoric strain computed under the hypotesis of small strains (if computed) 

507 

508 r : nx3 array of n points with the components of the rotation vector (if computed) 

509 

510 z : nx3 array of n points with the components of the zoom vector (if computed) 

511 

512 U : nx3x3 array of n points with the components of the right-hand stretch tensor (if computed) 

513 

514 e : nx3x3 array of n points with the components of the strain tensor in small strains (if computed) 

515 

516 """ 

517 

518 if not os.path.isfile(fileName): 

519 print("\n\tspam.tsvio.readStrainTSV(): {} is not a file. Exiting.".format(fileName)) 

520 return 

521 #Read the TSV 

522 f = numpy.genfromtxt(fileName, delimiter="\t", names=True) 

523 

524 #Number of points 

525 nPoints = f.size 

526 

527 #Get keys from file 

528 keys = f.dtype.names 

529 

530 #Create empyt dictionary to be filled 

531 output = {} 

532 

533 #Read and add the label coordinates 

534 fieldCoords = numpy.zeros((nPoints, 3)) 

535 fieldCoords[:, 0] = f['Zpos'] 

536 fieldCoords[:, 1] = f['Ypos'] 

537 fieldCoords[:, 2] = f['Xpos'] 

538 output['fieldCoords'] = fieldCoords 

539 

540 #Check if we are working with a regular grid or discrete 

541 grid = False 

542 discrete = False 

543 if numpy.abs(fieldCoords[2,0] - fieldCoords[3,0]) == 0: 

544 grid = True 

545 else: 

546 discrete = True 

547 

548 if grid: 

549 fieldDims = numpy.array([len(numpy.unique(f['Zpos'])), len(numpy.unique(f['Ypos'])), len(numpy.unique(f['Xpos']))]) 

550 output['fieldDims'] = fieldDims 

551 output['numberOfLabels'] = 0 

552 else: 

553 output['fieldDims'] = [0, 0, 0] 

554 output['numberOfLabels'] = nPoints 

555 

556 #Check for all the possible keys 

557 if 'vol' in keys: 

558 volStrain = numpy.zeros((nPoints, 1)) 

559 volStrain[:, 0] = f['vol'] 

560 output['vol'] = volStrain 

561 

562 if 'dev' in keys: 

563 devStrain = numpy.zeros((nPoints, 1)) 

564 devStrain[:, 0] = f['dev'] 

565 output['dev'] = devStrain 

566 

567 if 'volss' in keys: 

568 volss = numpy.zeros((nPoints, 1)) 

569 volss[:, 0] = f['volss'] 

570 output['volss'] = volss 

571 

572 if 'devss' in keys: 

573 devss = numpy.zeros((nPoints, 1)) 

574 devss[:, 0] = f['devss'] 

575 output['devss'] = devss 

576 

577 if 'rz' in keys: 

578 r = numpy.zeros((nPoints, 3)) 

579 r[:, 0] = f['rz'] 

580 r[:, 1] = f['ry'] 

581 r[:, 2] = f['rx'] 

582 output['r'] = r 

583 

584 if 'zz' in keys: 

585 # Zooms, these are very badly named like this 

586 z = numpy.zeros((nPoints, 3)) 

587 z[:, 0] = f['zz'] 

588 z[:, 1] = f['zy'] 

589 z[:, 2] = f['zx'] 

590 output['z'] = z 

591 

592 if 'Uzz' in keys: 

593 # Symmetric, so fill in both sides 

594 U = numpy.zeros((nPoints, 3, 3)) 

595 U[:, 0, 0] = f['Uzz'] 

596 U[:, 1, 1] = f['Uyy'] 

597 U[:, 2, 2] = f['Uxx'] 

598 U[:, 0, 1] = f['Uzy'] 

599 U[:, 1, 0] = f['Uzy'] 

600 U[:, 0, 2] = f['Uzx'] 

601 U[:, 2, 0] = f['Uzx'] 

602 U[:, 1, 2] = f['Uyx'] 

603 U[:, 2, 1] = f['Uyx'] 

604 output['U'] = U 

605 

606 if 'ezz' in keys: 

607 # Symmetric, so fill in both sides 

608 e = numpy.zeros((nPoints, 3, 3)) 

609 e[:, 0, 0] = f['ezz'] 

610 e[:, 1, 1] = f['eyy'] 

611 e[:, 2, 2] = f['exx'] 

612 e[:, 0, 1] = f['ezy'] 

613 e[:, 1, 0] = f['ezy'] 

614 e[:, 0, 2] = f['ezx'] 

615 e[:, 2, 0] = f['ezx'] 

616 e[:, 1, 2] = f['eyx'] 

617 e[:, 2, 1] = f['eyx'] 

618 output['e'] = e 

619 

620 return output 

621 

622 

623def TSVtoTIFF(fileName, fieldBinRatio=1.0, lab=None, returnRS=False, outDir=None, prefix=None): 

624 ''' 

625 This function converts a TSV file (typically the output of spam-ldic and spam-ddic scripts) 

626 to a tiff file for visualising the deformation field. 

627 

628 Parameters 

629 ---------- 

630 fileName : string 

631 Name of the file 

632 

633 fieldBinRatio : int, optional 

634 if the input field is refer to a binned version of the image 

635 `e.g.`, if ``fieldBinRatio = 2`` the field_name values have been calculated 

636 for an image half the size of what the returned PhiField is referring to 

637 Default = 1.0 

638 

639 lab : 3D numpy array, optional 

640 The labelled image of the reference state. Highly recommended argument in case of a discrete correlation result. 

641 Default = None 

642 

643 returnRS : bool, optional 

644 if True: will return the returnStatus of the correlation as a tiff file 

645 Default = False 

646 

647 outDir : string, optional 

648 Output directory 

649 Default is directory of the input field file 

650 

651 prefix : string, optional 

652 Prefix for output files 

653 Default is the basename of the input field file (without extension) 

654 ''' 

655 

656 import tifffile 

657 # use the helper function to read the TSV file 

658 fi = readCorrelationTSV(fileName, fieldBinRatio=fieldBinRatio, readOnlyDisplacements=True, readConvergence=returnRS) 

659 displacements = fi["displacements"] 

660 PhiComponents = [['Zdisp', 0], 

661 ['Ydisp', 1], 

662 ['Xdisp', 2]] 

663 

664 # set output directory if none 

665 if outDir is None: 

666 if os.path.dirname(fileName) == "": 

667 outDir = "./" 

668 else: 

669 outDir = os.path.dirname(fileName) 

670 else: 

671 os.makedirs(outDir) 

672 

673 # output file name prefix 

674 if prefix is None: 

675 prefix = os.path.splitext(os.path.basename(fileName))[0] 

676 

677 # check if it is a ddic result 

678 if fi["numberOfLabels"] != 0: 

679 if lab: 

680 labelled = tifffile.imread(lab) 

681 import spam.label 

682 

683 for component in PhiComponents: 

684 tifffile.imwrite("{}/{}-{}.tif".format(outDir, prefix, component[0]), 

685 spam.label.convertLabelToFloat(labelled, displacements[:, component[1]]).astype('<f4')) 

686 if returnRS: 

687 tifffile.imwrite("{}/{}-RS.tif".format(outDir, prefix), 

688 spam.label.convertLabelToFloat(labelled, fi["returnStatus"]).astype('<f4')) 

689 else: 

690 print("\tspam.tsvio.TSVtoTIFF(): The labelled image of the reference state is needed as input. Exiting.") 

691 return 

692 

693 # if not, is a ldic result 

694 else: 

695 dims = fi["fieldDims"] 

696 

697 for component in PhiComponents: 

698 tifffile.imwrite("{}/{}-{}.tif".format(outDir, prefix, component[0]), 

699 displacements[:, component[1]].reshape(dims).astype('<f4')) 

700 

701 if returnRS: 

702 tifffile.imwrite("{}/{}-RS.tif".format(outDir, prefix), 

703 fi["returnStatus"].reshape(dims).astype('<f4')) 

704 

705 

706def TSVtoVTK(fileName, fieldBinRatio=1.0, pixelSize=1.0, returnRS=False, outDir=None, prefix=None): 

707 ''' 

708 This function converts a TSV file (typically the output of the ldic and ddic scripts) 

709 to a VTK file for visualising the deformation field. 

710 

711 Parameters 

712 ---------- 

713 fileName : string 

714 Name of the file 

715 

716 fieldBinRatio : int, optional 

717 if the input field is refer to a binned version of the image 

718 `e.g.`, if ``fieldBinRatio = 2`` the field values have been calculated 

719 for an image half the size of what the returned PhiField is referring to 

720 Default = 1.0 

721 

722 pixelSize: float 

723 physical size of a pixel (i.e. 1mm/px) 

724 Default = 1.0 

725 

726 returnRS : bool, optional 

727 if True: will return the SubPixelReturnStatus of the correlation 

728 Default = False 

729 

730 outDir : string 

731 Output directory 

732 Default is directory of the input field file 

733 

734 prefix : string 

735 Prefix for output files 

736 Default is the basename of the input field file (without extension) 

737 ''' 

738 import spam.helpers 

739 # use the helper function to read the TSV file 

740 fi = readCorrelationTSV(fileName, fieldBinRatio=fieldBinRatio) 

741 PhiField = fi["PhiField"] 

742 

743 # set output directory if none 

744 if outDir is None: 

745 if os.path.dirname(fileName) == "": 

746 outDir = "./" 

747 else: 

748 outDir = os.path.dirname(fileName) 

749 else: 

750 os.makedirs(outDir) 

751 

752 # output file name prefix 

753 if prefix is None: 

754 prefix = os.path.splitext(os.path.basename(fileName))[0] 

755 

756 # check if it is a ddic result 

757 if fi["numberOfLabels"] != 0: 

758 coords = fi["fieldCoords"][1:] * pixelSize 

759 if not returnRS: 

760 pointData = {"displacements": PhiField[1:, :-1, 3] * pixelSize} 

761 

762 else: 

763 pointData = {"displacements": PhiField[1:, :-1, 3] * pixelSize, 

764 "returnStatus": fi["returnStatus"][1:]} 

765 

766 spam.helpers.writeGlyphsVTK(coords, pointData, fileName="{}/{}.vtk".format(outDir, prefix)) 

767 

768 # if not, is a ldic result 

769 else: 

770 dims = fi["fieldDims"] 

771 coords = fi["fieldCoords"] * pixelSize 

772 aspectRatio = numpy.array([numpy.unique(coords[:, i])[1] - numpy.unique(coords[:, i])[0] if len(numpy.unique(coords[:, i])) > 1 else numpy.unique(coords[:, i])[0] for i in range(3)]) 

773 origin = coords[0] - aspectRatio/2.0 

774 

775 if not returnRS: 

776 cellData = {"displacements": (PhiField[:, :-1, 3] * pixelSize).reshape((dims[0], dims[1], dims[2], 3))} 

777 

778 else: 

779 cellData = {"displacements": (PhiField[:, :-1, 3] * pixelSize).reshape((dims[0], dims[1], dims[2], 3)), 

780 "returnStatus": fi["returnStatus"].reshape(dims[0], dims[1], dims[2])} 

781 

782 spam.helpers.writeStructuredVTK(aspectRatio=aspectRatio, origin = origin, cellData=cellData, fileName="{}/{}.vtk".format(outDir, prefix))