optionsParser.py 104 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
"""
Library of SPAM functions for parsing inputs to the scripts
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 argparse
20
import numpy
21
import tifffile
22
23
import os

24
# Nice str2bool suggestion from Maxim (https://stackoverflow.com/questions/15008758/parsing-boolean-values-with-argparse)
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
25

26
def str2bool(v):
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
27
28
29
30
31
32
33
    if v.lower() in ('yes', 'true', 't', 'y', '1'):
        return True
    elif v.lower() in ('no', 'false', 'f', 'n', '0'):
        return False
    else:
        raise argparse.ArgumentTypeError('Boolean value expected.')

Edward Andò's avatar
Edward Andò committed
34
35
36
GLPv3descriptionHeader = "Copyright (C) 2020 SPAM developers\n"+\
                         "This program comes with ABSOLUTELY NO WARRANTY.\n"+\
                         "This is free software, and you are welcome to redistribute it under certain conditions\n\n\n"
37

38

39
def ldicParser(parser):
40
41
42
    parser.add_argument('inFiles',
                        nargs='+',
                        type=argparse.FileType('r'),
43
                        help="A space-separated list of two or more 3D greyscale tiff files to correlate, in order")
44

45
46
47
48
49
50
51
    parser.add_argument('-np',
                        '--number-of-processes',
                        default=None,
                        type=int,
                        dest='PROCESSES',
                        help="Number of parallel processes to use. Default = multiprocessing.cpu_count()")

52
53
54
    parser.add_argument('-mf1',
                        '--maskFile1',
                        dest='MASK1',
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
55
                        default=None,
56
                        type=argparse.FileType('r'),
57
                        help="Path to tiff file containing the mask of image 1 -- masks zones not to correlate, which should be == 0")
58

Emmanuel Roubin's avatar
Emmanuel Roubin committed
59
60
61
62
63
64
    # parser.add_argument('-mf2',
    #                     '--maskFile2',
    #                     dest='MASK2',
    #                     default=None,
    #                     type=argparse.FileType('r'),
    #                     help="Path to tiff file containing the mask of image 2 -- masks correlation windows")
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
65

Edward Andò's avatar
Edward Andò committed
66
67
68
    parser.add_argument('-pf',
                        '-phiFile',
                        dest='PHIFILE',
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
69
                        default=None,
70
71
72
                        type=argparse.FileType('r'),
                        help="Path to TSV file containing initial F guess, can be single-point registration or multiple point correlation. Default = None")

Edward Andò's avatar
Edward Andò committed
73
74
    parser.add_argument('-pfb',
                        '--phiFile-bin-ratio',
75
76
                        type=int,
                        default=1,
Edward Andò's avatar
Edward Andò committed
77
                        dest='PHIFILE_BIN_RATIO',
78
                        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")
79

80
81
82
83
84
85
86
87
88
89
90
91
92
93
    parser.add_argument('-pfd',
                        '--phiFile-direct',
                        action="store_true",
                        #default=1,
                        dest='PHIFILE_DIRECT',
                        help="Trust the Phi file completely? This option ignores and overrides -pfni and requires same nodes in same positions. Default = False")

    parser.add_argument('-pfni',
                        '--neighbours-for-phi-field-interpolation',
                        type=int,
                        default=6,
                        dest='NEIGHBOURS',
                        help="Number of neighbours for field interpolation. Default = 6")

94
95
96
    parser.add_argument('-glt',
                        '--grey-low-threshold',
                        type=float,
97
                        default=-numpy.inf,
98
                        dest='GREY_LOW_THRESH',
99
100
101
102
103
104
105
106
                        help="Grey threshold on mean of reference imagette BELOW which the correlation is not performed. Default = -infinity")

    parser.add_argument('-ght',
                        '--grey-high-threshold',
                        type=float,
                        default=numpy.inf,
                        dest='GREY_HIGH_THRESH',
                        help="Grey threshold on mean of reference imagette ABOVE which the correlation is not performed. Default = infinity")
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

    # Default: node spacing equal in all three directions
    parser.add_argument('-ns',
                        '--node-spacing',
                        nargs=1,
                        type=int,
                        default=None,
                        dest='NS',
                        help="Node spacing in pixels (assumed equal in all 3 directions -- see -ns3 for different setting). Default = 10px")

    # Possible: node spacing different in all three directions
    parser.add_argument('-ns3',
                        '--node-spacing-3',
                        nargs=3,
                        type=int,
                        default=None,
                        dest='NS',
                        help="Node spacing in pixels (different in 3 directions). Default = 10, 10, 10px")

    # Default: window size equal in all three directions
    parser.add_argument('-hws',
                        '--half-window-size',
                        nargs=1,
Olga Stamati's avatar
Olga Stamati committed
130
                        type=int,
131
132
                        default=None,
                        dest='HWS',
133
                        help="Half correlation window size, measured each side of the node pixel (assumed equal in all 3 directions -- see -hws3 for different setting). Default = 10 px")
134
135
136
137
138
139
140
141
142
143

    # Possible: node spacing different in all three directions
    parser.add_argument('-hws3',
                        '--half-window-size-3',
                        nargs=3,
                        type=int,
                        default=None,
                        dest='HWS',
                        help="Half correlation window size, measured each side of the node pixel (different in 3 directions). Default = 10, 10, 10px")

144
145
146
    parser.add_argument('-m',
                        '-mar',
                        '-margin',
147
                        nargs=1,
Olga Stamati's avatar
Olga Stamati committed
148
                        type=int,
149
                        default=[3],
150
151
                        dest='MARGIN',
                        help="Margin in pixels for the correlation of each local subvolume. Default = 3 px")
152

153
154
155
    parser.add_argument('-m3',
                        '-mar3',
                        '-margin3',
156
                        nargs=3,
Olga Stamati's avatar
Olga Stamati committed
157
                        type=int,
158
                        default=None,
159
160
                        dest='MARGIN',
                        help="Margin in pixels for the correlation of each local subvolume. Default = 3 px")
161

162
163
    parser.add_argument('-it',
                        '--max-iterations',
Olga Stamati's avatar
Olga Stamati committed
164
                        type=int,
165
                        default=50,
166
167
                        dest='MAX_ITERATIONS',
                        help="Maximum iterations for local correlation. Default = 50")
168

169
170
    parser.add_argument('-dp',
                        '--min-delta-phi',
171
172
                        type=numpy.float,
                        default=0.001,
173
174
                        dest='MIN_DELTA_PHI',
                        help="Minimum change in Phi for local convergence. Default = 0.001")
175

176
177
    parser.add_argument('-o',
                        '--interpolation-order',
Olga Stamati's avatar
Olga Stamati committed
178
                        type=int,
179
                        default=1,
180
181
                        dest='INTERPOLATION_ORDER',
                        help="Image interpolation order for local correlation. Default = 1, i.e., linear interpolation")
182

183
184
    parser.add_argument('-mc',
                        '--mask-coverage',
185
186
                        type=float,
                        default=0.5,
187
                        dest='MASK_COVERAGE',
188
189
                        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")

190
191
    parser.add_argument('-ug',
                        '--update-gradient',
192
                        action="store_true",
193
194
                        dest='UPDATE_GRADIENT',
                        help='Update gradient in local correlation? More computation time but sometimes more robust and possibly fewer iterations.')
195

196
197
198
199
200
    #parser.add_argument('-sef',
                        #'--series-Ffile',
                        #action="store_true",
                        #dest='SERIES_PHIFILE',
                        #help='During a total analysis, activate use of previous Ffield for next correlation')
201

202
203
204
205
206
207
    parser.add_argument('-sei',
                        '--series-incremental',
                        action="store_true",
                        dest='SERIES_INCREMENTAL',
                        help='Perform incremental correlations between images')

208
209
210
211
212
213
214
215
216
217
218
219
    parser.add_argument('-od',
                        '--out-dir',
                        type=str,
                        default=None,
                        dest='OUT_DIR',
                        help="Output directory, default is the dirname of input file")

    parser.add_argument('-pre',
                        '--prefix',
                        type=str,
                        default=None,
                        dest='PREFIX',
Edward Andò's avatar
Edward Andò committed
220
                        help="Prefix for output files (without extension). Default is basename of input file")
221
222
223
224
225
226
227

    parser.add_argument('-vtk',
                        '--VTKout',
                        action="store_true",
                        dest='VTK',
                        help='Activate VTK output format. Default = False')

Edward Andò's avatar
Edward Andò committed
228
229
    parser.add_argument('-notsv',
                        '--noTSV',
230
                        action="store_false",
231
                        dest='TSV',
Edward Andò's avatar
Edward Andò committed
232
                        help='Disactivate TSV output format. Default = True')
233
234
235
236
237
238

    parser.add_argument('-tif',
                        '-tiff',
                        '--TIFFout',
                        '--TIFout',
                        action="store_true",
Edward Andò's avatar
Edward Andò committed
239
240
                        dest='TIFF',
                        help='Activate TIFFoutput format. Default = False')
241
242
243

    args = parser.parse_args()

Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
244
    # 2018-03-24 check for 2D without loading images
Emmanuel Roubin's avatar
Emmanuel Roubin committed
245
    # try:
246
    # except BaseException:
Edward Andò's avatar
Edward Andò committed
247
    #     print("DICregularGrid: Input TIFF files need to be writeable in order to guess their dimensionality")
Emmanuel Roubin's avatar
Emmanuel Roubin committed
248
    #     exit()
Edward Andò's avatar
Edward Andò committed
249
250
    # 2019-03-21 EA: better check for dimensions, doesn't depend on writability of files
    tiff = tifffile.TiffFile(args.inFiles[0].name)
251
    #imagejSingleSlice = True
Emmanuel Roubin's avatar
Emmanuel Roubin committed
252
253
254
255
    # if tiff.imagej_metadata is not None:
    #     if 'slices' in tiff.imagej_metadata:
    #         if tiff.imagej_metadata['slices'] > 1:
    #             imagejSingleSlice = False
Edward Andò's avatar
Edward Andò committed
256

257
258
    # 2019-04-05 EA: 2D image detection approved by Christophe Golke, update for shape 2019-08-29
    if len(tiff.pages) == 1 and len(tiff.series[0].shape) == 2:
Edward Andò's avatar
Edward Andò committed
259
260
261
262
        twoD = True
    else:
        twoD = False
    tiff.close()
263

264
    # 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.
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
265
266
    if args.OUT_DIR is None:
        args.OUT_DIR = os.path.dirname(args.inFiles[0].name)
267
        # However if we have no dir, notice this and make it the current directory.
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
268
269
        if args.OUT_DIR == "":
            args.OUT_DIR = "./"
270
271
272
273
274
275
    else:
        # Check existence of output directory
        try:
            if args.OUT_DIR:
                os.makedirs(args.OUT_DIR)
            else:
Emmanuel Roubin's avatar
gdic    
Emmanuel Roubin committed
276
                args.DIR_out = os.path.dirname(args.inFiles[0].name)
277
278
279
280
281
282
        except OSError:
            if not os.path.isdir(args.OUT_DIR):
                raise

    # Catch interdependent node spacing and correlation window sizes
    if args.NS is None:
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
283
        print("\nUsing default node spacing: "),
284
        if args.HWS is None:
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
285
            print("2x default half window size"),
286
            args.HWS = [10]
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
287
288
            print("({}) which is".format(args.HWS[0])),
            args.NS = [args.HWS[0] * 2]
289
        else:
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
290
291
292
293
294
295
296
297
            print("2x user-set half window size"),
            if len(args.HWS) == 1:
                print("({}) which is".format(args.HWS[0])),
                args.NS = [int(args.HWS[0] * 2)]
            elif len(args.HWS) == 3:
                print("({} -- selecting smallest) which is".format(args.HWS)),
                args.NS = [int(min(args.HWS) * 2)]
        print(args.NS)
298
299

    # Catch 3D options
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
300
301
    if len(args.NS) == 1:
        args.NS = [args.NS[0], args.NS[0], args.NS[0]]
302

Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
303
304
    if len(args.HWS) == 1:
        args.HWS = [args.HWS[0], args.HWS[0], args.HWS[0]]
305

306
307
    if len(args.MARGIN) == 1:
        args.MARGIN = [args.MARGIN[0], args.MARGIN[0], args.MARGIN[0]]
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
308

309
310
    if type(args.MAX_ITERATIONS) == list:
        args.MAX_ITERATIONS = args.MAX_ITERATIONS[0]
311

312
313
    # Catch and overwrite 2D options
    if twoD:
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
314
        args.NS[0] = 1
315
        args.HWS[0] = 0
316
317
        args.MARGIN[0] = 0

318
    
319
320
321
322
323
324
325
326
327
    # Behaviour undefined for series run and im1 mask since im1 will change, complain and continue
    if args.MASK1 is not None and args.SERIES_INCREMENTAL:
        print("#############################################################")
        print("#############################################################")
        print("###  WARNING: You set an im1 mask and an incremental      ###")
        print("###  series correlation, meaning that im1 will change...  ###")
        print("#############################################################")
        print("#############################################################")

328
    # Make sure at least one output format has been asked for
Edward Andò's avatar
Edward Andò committed
329
    if args.VTK + args.TSV + args.TIFF== 0:
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
330
331
        print("#############################################################")
        print("#############################################################")
Edward Andò's avatar
Edward Andò committed
332
        print("###  WARNING: No output type of VTK, TSV and TIFFoptions  ###")
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
333
334
335
        print("###  Are you sure this is right?!                         ###")
        print("#############################################################")
        print("#############################################################")
336

337
338
    #if args.SERIES_PHIFILE:
        #args.TSV = True
339

340
341
    # Nor prefix here because LDIC can still do an image series and needs to update the name

342
343
344
    return args


345
def ddicParser(parser):
346
347
348
349
350
    parser.add_argument('im1',
                        metavar='im1',
                        type=argparse.FileType('r'),
                        help="Greyscale image of reference state for correlation")

351
352
353
354
355
    parser.add_argument('lab1',
                        metavar='lab1',
                        type=argparse.FileType('r'),
                        help="Labelled image of reference state for correlation")

356
357
358
359
    parser.add_argument('im2',
                        metavar='im2',
                        type=argparse.FileType('r'),
                        help="Greyscale image of deformed state for correlation")
360

361
362
363
364
365
366
367
    parser.add_argument('-np',
                        '--number-of-processes',
                        default=None,
                        type=int,
                        dest='PROCESSES',
                        help="Number of parallel processes to use. Default = multiprocessing.cpu_count()")

368
369
    parser.add_argument('-ld',
                        '--label-dilate',
370
                        type=int,
371
372
373
374
                        default=1,
                        dest='LABEL_DILATE',
                        help="Number of times to dilate labels. Default = 1")

Edward Andò's avatar
Edward Andò committed
375
376
377
378
379
380
    #parser.add_argument('-ldmax',
                        #'--label-dilate-maximum',
                        #type=int,
                        #default=None,
                        #dest='LABEL_DILATE_MAX',
                        #help="Maximum dilation for label if they don't converge with -ld setting. Default = same as -ld setting")
Edward Andò's avatar
Edward Andò committed
381

382
383
384
385
386
387
388
    parser.add_argument('-vt',
                        '--volume-threshold',
                        type=numpy.uint,
                        default=100,
                        dest='VOLUME_THRESHOLD',
                        help="Volume threshold below which labels are ignored. Default = 100")

Edward Andò's avatar
Edward Andò committed
389
390
391
    parser.add_argument('-pf',
                        '-phiFile',
                        dest='PHIFILE',
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
392
                        default=None,
393
394
395
                        type=argparse.FileType('r'),
                        help="Path to TSV file containing initial F guess, can be single-point registration or multiple point correlation. Default = None")

Edward Andò's avatar
Edward Andò committed
396
397
    parser.add_argument('-pfb',
                        '--phiFile-bin-ratio',
398
399
                        type=int,
                        default=1,
Edward Andò's avatar
Edward Andò committed
400
                        dest='PHIFILE_BIN_RATIO',
401
                        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")
402

403
404
405
    parser.add_argument('-pfd',
                        '--phiFile-direct',
                        action="store_true",
406
                        #default=1,
407
                        dest='PHIFILE_DIRECT',
408
                        help="Trust the Phi file completely? This option ignores and overrides -cif and requires labels to be aligned between Phi file and labelled image. Default = False")
409

410
411
412
413
414
415
416
417
    parser.add_argument('-cif',
                        '--correct-input-field',
                        action="store_true",
                        dest='CF',
                        help='Correction of the input F field. Default = True')

    parser.add_argument('-nfi',
                        '--neighbours-for-field-interpolation',
Olga Stamati's avatar
Olga Stamati committed
418
                        type=int,
419
420
                        default=12,
                        dest='NEIGHBOURS',
421
                        help="Number of neighbours for field interpolation. Default = 12")
422

423
424
    parser.add_argument('-lcm',
                        '--label-correlate-margin',
425
                        type=numpy.uint,
426
427
                        default=5,
                        dest='LABEL_CORRELATE_MARGIN',
428
                        help="Margin in pixels for label correlation. Note: this is added to label dilate. Default = 2px")
429

430
431
    parser.add_argument('-lci',
                        '--label-correlate-max-iterations',
432
                        type=numpy.uint,
433
                        default=50,
434
                        dest='LABEL_CORRELATE_MAX_ITERATIONS',
435
                        help="Maximum iterations for label correlation. Default = 50")
436

437
438
    parser.add_argument('-lcdp',
                        '--label-correlate-min-delta-phi',
439
440
                        type=numpy.float,
                        default=0.001,
441
                        dest='LABEL_CORRELATE_MIN_PHI_CHANGE',
442
                        help="Minimum change in Phi to consider label correlation as converged. Default = 0.001")
443

444
445
    parser.add_argument('-lco',
                        '--label-correlate-interpolation-order',
446
                        type=numpy.uint,
447
                        default=1,
448
                        dest='LABEL_CORRELATE_INTERPOLATION_ORDER',
449
                        help="Interpolation order for label correlation. Default = 3")
450

Edward Andò's avatar
Edward Andò committed
451
    parser.add_argument('-lcnr',
452
453
454
455
456
457
458
                        '--label-correlate-non-rigid',
                        action="store_false",
                        dest='LABEL_CORRELATE_RIGID',
                        help='Activate non-rigid registration for each label')

    parser.add_argument('-lcug',
                        '--label-correlate-update-gradient',
459
                        action="store_true",
460
                        dest='LABEL_CORRELATE_UPDATE_GRADIENT',
461
462
                        help='Update gradient in label registration? More computation time but more robust and possibly fewer iterations.')

463
464
465
466
467
468
469
470
471
472
473
474
475
    #parser.add_argument('-lcms',
                        #'--label-correlate-multiscale',
                        #action="store_true",
                        #dest='LABEL_CORRELATE_MULTISCALE',
                        #help='Activate multiscale correlation for the label? If you set this, please indicate -lcmsb')

    parser.add_argument('-lcmsb',
                        '--label-correlate-multiscale-binning',
                        type=numpy.uint,
                        default=1,
                        dest='LABEL_CORRELATE_MULTISCALE_BINNING',
                        help="Binning level for multiscale label correlation. Default = 1")

476
477
478
479
480
    parser.add_argument('-lcmo',
                        '--label-correlate-mask-others',
                        action="store_false",
                        dest='LABEL_CORRELATE_MASK_OTHERS',
                        help='Prevent masking other labels when dilating?')
481
482
483
484
485
486
487
488
489
490
491
492
493

    parser.add_argument('-od',
                        '--out-dir',
                        type=str,
                        default=None,
                        dest='OUT_DIR',
                        help="Output directory, default is the dirname of input file")

    parser.add_argument('-pre',
                        '--prefix',
                        type=str,
                        default=None,
                        dest='PREFIX',
Edward Andò's avatar
Edward Andò committed
494
                        help="Prefix for output files (without extension). Default is basename of input file")
495

496
497
498
    parser.add_argument('-skp',
                        '--skip',
                        action="store_true",
Edward Andò's avatar
Edward Andò committed
499
                        default=False,
500
                        dest='SKIP_PARTICLES',
501
                        help="Read the return status of the Phi file run ddic only for the non-converged grains. Default = False")
502

503
504
505
    parser.add_argument('-d',
                        '--debug',
                        action="store_true",
Edward Andò's avatar
Edward Andò committed
506
                        default=False,
507
508
509
                        dest='DEBUG',
                        help="Extremely verbose mode with graphs and text output. Only use for a few particles. Do not use with mpirun")

510
511
512
    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.
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
513
514
    if args.OUT_DIR is None:
        args.OUT_DIR = os.path.dirname(args.lab1.name)
515
        # However if we have no dir, notice this and make it the current directory.
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
516
517
        if args.OUT_DIR == "":
            args.OUT_DIR = "./"
518
519
520
521
522
    else:
        # Check existence of output directory
        try:
            if args.OUT_DIR:
                os.makedirs(args.OUT_DIR)
523
            else:
Emmanuel Roubin's avatar
gdic    
Emmanuel Roubin committed
524
                args.DIR_out = os.path.dirname(args.lab1.name)
525
526
527
528
529
        except OSError:
            if not os.path.isdir(args.OUT_DIR):
                raise

    # Output file name prefix
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
530
    if args.PREFIX is None:
Emmanuel Roubin's avatar
Emmanuel Roubin committed
531
        args.PREFIX = os.path.splitext(os.path.basename(args.im1.name))[0] + "-" + os.path.splitext(os.path.basename(args.im2.name))[0]
532

Edward Andò's avatar
Edward Andò committed
533
534
535
    ## Set label dilate max as label dilate if it is none
    #if args.LABEL_DILATE_MAX is None:
        #args.LABEL_DILATE_MAX = args.LABEL_DILATE
Edward Andò's avatar
Edward Andò committed
536

Edward Andò's avatar
Edward Andò committed
537
538
539
    #if args.LABEL_DILATE_MAX < args.LABEL_DILATE:
        #print("spam-ddic: Warning \"label dilate max\" is less than \"label dilate\" setting them equal")
        #args.LABEL_DILATE_MAX = args.LABEL_DILATE
Edward Andò's avatar
Edward Andò committed
540

541
542
543
544
    if args.DEBUG:
        print("spam-ddic: DEBUG mode activated, forcing number of processes to 1")
        args.PROCESSES = 1

545
    return args
546
547


Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
548
def multiModalRegistrationParser(parser):
549
    import spam.DIC
Edward Andò's avatar
Edward Andò committed
550
    import numpy
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585

    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('-im1min',
                        type=float,
                        default=None,
                        dest='IM1_MIN',
                        help="Minimum of im1 for greylevel scaling. Default = im1.min()")

    parser.add_argument('-im1max',
                        type=float,
                        default=None,
                        dest='IM1_MAX',
                        help="Maximum of im1 for greylevel scaling. Default = im1.max()")

    parser.add_argument('-im2min',
                        type=float,
                        default=None,
                        dest='IM2_MIN',
                        help="Minimum of im2 for greylevel scaling. Default = im2.min()")

    parser.add_argument('-im2max',
                        type=float,
                        default=None,
                        dest='IM2_MAX',
                        help="Maximum of im2 for greylevel scaling. Default = im2.max()")

Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
586
587
588
589
590
591
592
593
594
595
596
597
598
599
    parser.add_argument('-im1th',
                        '--im1-threshold',
                        type=int,
                        default=0,
                        dest='IM1_THRESHOLD',
                        help='Greylevel threshold for image 1. Below this threshold, peaks in the histogram are ignored.')

    parser.add_argument('-im2th',
                        '--im2-threshold',
                        type=int,
                        default=0,
                        dest='IM2_THRESHOLD',
                        help='Greylevel threshold for image 2. Below this threshold, peaks in the histogram are ignored.')

600
601
    parser.add_argument('-bin',
                        '--bin-levels',
Edward Andò's avatar
Edward Andò committed
602
                        type=int,
Edward Andò's avatar
Edward Andò committed
603
604
605
                        default=1,
                        dest='NBINS',
                        help='Number of binning levels to apply to the data (if given 3, the binning levels used will be 4 2 1). The -phase option is necessary and should define this many phases (i.e., 3 different numbers in this example)')
606
607
608
609
610
611
612

    parser.add_argument('-ph',
                        '--phases',
                        nargs='+',
                        type=int,
                        default=[2],
                        dest='PHASES',
613
                        help='Number of phases?')
614
615
616

    parser.add_argument('-jhb',
                        '--joint-histogram-bins',
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
617
                        # nargs=1,
618
619
620
621
622
                        type=int,
                        default=128,
                        dest='JOINT_HISTO_BINS',
                        help='The number of greylevel bins for both images in the joint histogram')

Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
623
624
625
626
627
    parser.add_argument('-dst',
                        '--dist-between-max',
                        type=int,
                        default=None,
                        dest='DIST_BETWEEN_MAX',
Emmanuel Roubin's avatar
Emmanuel Roubin committed
628
629
630
631
632
633
634
635
                        help='Minimal distance between two maxima in the histogram')

    parser.add_argument('-fdi',
                        '--fit-distance',
                        type=float,
                        default=None,
                        dest='FIT_DISTANCE',
                        help='Distance considered around a peak for the Gaussian ellipsoid fitting')
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
636

Emmanuel Roubin's avatar
Emmanuel Roubin committed
637
638
639
640
641
    parser.add_argument('-voc',
                        '--voxel-coverage',
                        type=float,
                        default=1.0,
                        dest='VOXEL_COVERAGE',
Emmanuel Roubin's avatar
Emmanuel Roubin committed
642
                        help='Percentage (between 0 and 1) of voxel coverage of the phases in the joint histogram')
Emmanuel Roubin's avatar
Emmanuel Roubin committed
643

644
645
646
647
648
649
650
651
652
653
654
655
    parser.add_argument('-int',
                        '--interactive',
                        action="store_true",
                        dest='INTERACTIVE',
                        help='Present live-updating plots to the user')

    parser.add_argument('-gra',
                        '--graphs',
                        action="store_true",
                        dest='GRAPHS',
                        help='Save graphs to file')

Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
656
657
658
659
660
661
662
    parser.add_argument('-ssl',
                        '--show-slice-axis',
                        type=int,
                        default=0,
                        dest='SHOW_SLICE_AXIS',
                        help='Axis of the cut used for the plots')

663
    parser.add_argument('-spp',
664
                        '--grid-point-min-phi-change',
665
                        type=numpy.float,
666
                        default=0.0005,
667
                        dest='GRID_POINT_MIN_PHI_CHANGE',
Edward Andò's avatar
Edward Andò committed
668
669
670
                        help="Subpixel min change in Phi to stop iterations. Default = 0.001")

    parser.add_argument('-spi',
671
                        '--grid-point-max-iterations',
Olga Stamati's avatar
Olga Stamati committed
672
                        type=int,
Edward Andò's avatar
Edward Andò committed
673
                        default=50,
674
                        dest='GRID_POINT_MAX_ITERATIONS',
Edward Andò's avatar
Edward Andò committed
675
                        help="Max number of iterations to optimise Phi. Default = 50")
676

Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
677
678
679
680
681
    # parser.add_argument('-tmp',
    #                     '--writeTemporaryFiles',
    #                     action="store_true",
    #                     dest='DATA',
    #                     help='Save temporary files (joint histogram) to \"dat\" file')
682

683
684
685
686
687
    #parser.add_argument('-loadprev',
                        #'--load-previous-iteration',
                        #action="store_true",
                        #dest='LOADPREV',
                        #help='Load output pickle files from previous iterations (2* coarser binning)')
Edward Andò's avatar
Edward Andò committed
688

689
    parser.add_argument('-mar',
Emmanuel Roubin's avatar
Emmanuel Roubin committed
690
                        '--margin',
691
692
                        type=float,
                        default=0.1,
Emmanuel Roubin's avatar
Emmanuel Roubin committed
693
694
695
696
697
698
699
700
701
                        dest='MARGIN',
                        help='Margin of both images. Default = 0.1, which means 0.1 * image size from both sides')

    parser.add_argument('-cro',
                        '--crop',
                        type=float,
                        default=0.1,
                        dest='CROP',
                        help='Initial crop of both images. Default = 0.1, which means 0.1 * image size from both sides')
702

703
704
705
706
707
    #parser.add_argument('-pif',
                        #default=None,
                        #type=argparse.FileType('rb'),
                        #dest='FGUESS_PICKLE',
                        #help="Pickle file name for initial guess. Should be in position 0 in the array and labeled as 'F' as for registration.")
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
708

Edward Andò's avatar
Edward Andò committed
709
    # Remove next two arguments for F input, and replace with displacement and rotation inputs on command line
710
711
712
    parser.add_argument('-pf',
                        '--phiFile',
                        dest='PHIFILE',
713
                        default=None,
714
                        type=argparse.FileType('r'),
715
                        help="Path to TSV file containing a single Phi guess (not a field) that deforms im1 onto im2. Default = None")
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
716
717
718
719
720

    # parser.add_argument('-Ffb',
    # '--Ffile-bin-ratio',
    # type=int,
    # default=1,
Edward Andò's avatar
Edward Andò committed
721
    # dest='PHIFILE_BIN_RATIO',
722
    # 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")
Edward Andò's avatar
Edward Andò committed
723

724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
    # parser.add_argument('-tra',
    # '--translation',
    # nargs=3,
    # type=float,
    # default=None,
    # dest='TRA',
    # help="Z, Y, X initial displacements to apply at the bin 1 scale")

    # parser.add_argument('-rot',
    # '--rotation',
    # nargs=3,
    # type=float,
    # default=None,
    # dest='ROT',
    # help="Z, Y, X components of rotation vector to apply at the bin 1 scale")
739
740
741
742
743
744
745
746
747
748
749
750
751

    parser.add_argument('-od',
                        '--out-dir',
                        type=str,
                        default=None,
                        dest='OUT_DIR',
                        help="Output directory, default is the dirname of input file")

    parser.add_argument('-pre',
                        '--prefix',
                        type=str,
                        default=None,
                        dest='PREFIX',
Edward Andò's avatar
Edward Andò committed
752
                        help="Prefix for output files (without extension). Default is basename of input file")
753
754
755
756

    args = parser.parse_args()

    # The number of bin levels must be the same as the number of phases
Edward Andò's avatar
Edward Andò committed
757
    if (args.NBINS != len(args.PHASES)):
758
759
760
        print("\toptionsParser.multiModalRegistrationParser(): Number of bin levels and number of phases not the same, exiting")
        exit()

Edward Andò's avatar
Edward Andò committed
761
762
763
    # For back compatibility, generate list of bins
    args.BINS = []
    for i in range(args.NBINS)[::-1]:
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
764
        args.BINS.append(2**i)
Edward Andò's avatar
Edward Andò committed
765

766
    # 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.
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
767
768
    if args.OUT_DIR is None:
        args.OUT_DIR = os.path.dirname(args.im1.name)
769
        # However if we have no dir, notice this and make it the current directory.
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
770
771
        if args.OUT_DIR == "":
            args.OUT_DIR = "./"
772
773
774
775
776
777
    else:
        # Check existence of output directory
        try:
            if args.OUT_DIR:
                os.makedirs(args.OUT_DIR)
            else:
Emmanuel Roubin's avatar
gdic    
Emmanuel Roubin committed
778
                args.DIR_out = os.path.dirname(args.im1.name)
779
780
781
782
        except OSError:
            if not os.path.isdir(args.OUT_DIR):
                raise

Edward Andò's avatar
Edward Andò committed
783
    # Get initial guesses
784
785
    if args.PHIFILE is not None:
        import spam.helpers
786
        args.FGUESS = spam.helpers.readCorrelationTSV(args.PHIFILE.name, readConvergence=False, readOnlyDisplacements=False)['PhiField'][0]
Edward Andò's avatar
Edward Andò committed
787
788
789
    else:
        args.FGUESS = numpy.eye(4)

790
    # Output file name prefix
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
791
    if args.PREFIX is None:
Emmanuel Roubin's avatar
Emmanuel Roubin committed
792
        args.PREFIX = os.path.splitext(os.path.basename(args.im1.name))[0] + "-" + os.path.splitext(os.path.basename(args.im2.name))[0]
793
794

    return args
Emmanuel Roubin's avatar
gdic    
Emmanuel Roubin committed
795
796


Emmanuel Roubin's avatar
Emmanuel Roubin committed
797
def gdicParser(parser):
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
    parser.add_argument('inFiles',
                        nargs='+',
                        type=argparse.FileType('r'),
                        help="A space-separated list of two 3D greyscale tiff files to correlate, in order")

    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")

    parser.add_argument('-mf2',
                        '--maskFile2',
                        dest='MASK2',
                        default=None,
                        type=argparse.FileType('r'),
                        help="Path to tiff file containing the mask of image 2 -- masks correlation windows")

    parser.add_argument('-pf',
                        '-phiFile',
                        dest='PHIFILE',
                        default=None,
                        type=argparse.FileType('r'),
                        help="Path to TSV file containing initial F guess, can be single-point registration or multiple point correlation. Default = None")

    parser.add_argument('-pfb',
                        '--phiFile-bin-ratio',
                        type=int,
                        default=1,
                        dest='PHIFILE_BIN_RATIO',
829
                        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")
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844

    # parser.add_argument('-glt',
    #                     '--grey-low-threshold',
    #                     type=float,
    #                     default=-numpy.inf,
    #                     dest='GREY_LOW_THRESH',
    #                     help="Grey threshold on mean of reference imagette BELOW which the correlation is not performed. Default = -infinity")
    #
    # parser.add_argument('-ght',
    #                     '--grey-high-threshold',
    #                     type=float,
    #                     default=numpy.inf,
    #                     dest='GREY_HIGH_THRESH',
    #                     help="Grey threshold on mean of reference imagette ABOVE which the correlation is not performed. Default = infinity")

Edward's avatar
Edward committed
845
846
847
848
849
850
    parser.add_argument('-d',
                        '--debug',
                        action="store_true",
                        dest='DEBUG_FILES',
                        help='Output debug files during iterations? Default = False')

851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
    parser.add_argument('-reg',
                        '--registration',
                        action="store_true",
                        dest='REG',
                        help='Perform an initial registration? Default = False')

    parser.add_argument('-regb',
                        '--registration-binning',
                        type=int,
                        default=1,
                        dest='REG_BIN',
                        help='Binning to apply to input images for registration. Default = 1')

    parser.add_argument('-regm',
                        '--registration-margin',
                        type=float,
                        default=0.1,
                        dest='REG_MARGIN',
                        help='Registration margin in proportions of image size. Default = 0.1, which means 0.1 * image size from both sides')

871
872
873
874
875
876
    parser.add_argument('-regu',
                        '--registration-update',
                        action="store_true",
                        dest='REG_UPDATE',
                        help='Update gradient in initial registration? More computation time but more robust and possibly fewer iterations. Default = False')

877
878
    parser.add_argument('-mit',
                        '--max-iterations',
Olga Stamati's avatar
Olga Stamati committed
879
                        type=int,
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
                        default=25,
                        dest='MAX_ITERATIONS',
                        help="Max iterations for global correlation. Default = 25")

    parser.add_argument('-cc',
                        '--convergence-criterion',
                        type=numpy.float,
                        default=0.01,
                        dest='CONVERGENCE_CRITERION',
                        help="Displacement convergence criterion in pixels (norm of incremental displacements). Default = 0.01")

    parser.add_argument('-str',
                        '--calculate-strain',
                        action="store_true",
                        dest='STRAIN',
                        help='Calculate strain? This is added to the VTK output files')
Emmanuel Roubin's avatar
gdic    
Emmanuel Roubin committed
896

897
898
899
900
901
    parser.add_argument('-ss',
                        '--small--strains',
                        action="store_true",
                        dest='SMALL_STRAINS',
                        help='Strain field is computed under the hypothesis of small strain. Default = False')
Emmanuel Roubin's avatar
gdic    
Emmanuel Roubin committed
902

903
    # parser.add_argument('-spo',
904
    #                     '--grid-point-interpolation-order',
905
906
    #                     type=numpy.uint,
    #                     default=1,
907
    #                     dest='GRID_POINT_INTERPOLATION_ORDER',
908
    #                     help="Subpixel interpolation order. Default = 1")
Emmanuel Roubin's avatar
gdic    
Emmanuel Roubin committed
909

910
911
912
913
914
    # parser.add_argument('-cif',
    #                     '--correct-input-field',
    #                     action="store_true",
    #                     dest='CF',
    #                     help='Correction of the input F field. Default = True')
Emmanuel Roubin's avatar
gdic    
Emmanuel Roubin committed
915

916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
    # parser.add_argument('-nfi',
    #                     '--neighbours-for-field-interpolation',
    #                     type=numpy.uint,
    #                     default=12,
    #                     dest='NEIGHBOURS',
    #                     help="Neighbours for field interpolation. Default = 12")

    parser.add_argument('-od',
                        '--out-dir',
                        type=str,
                        default=None,
                        dest='OUT_DIR',
                        help="Output directory, default is the dirname of input file")

    parser.add_argument('-pre',
                        '--prefix',
                        type=str,
Emmanuel Roubin's avatar
Emmanuel Roubin committed
933
                        default=None,
934
                        dest='PREFIX',
Edward Andò's avatar
Edward Andò committed
935
                        help="Prefix for output files (without extension). Default is basename of input file")
936
937
938
939
940
941
942
943
944
945
946
947
948

    parser.add_argument('-Mfile',
                        dest='MESH_FILE',
                        default=None,
                        type=argparse.FileType('rb'),
                        help="Path to pickle file containing mesh information needed for the correlation (coordinates, connectivity, labels and padding). Default = None.")

    parser.add_argument('-Mcube',
                        '--mesh-cuboid',
                        nargs=7,
                        type=numpy.float,
                        default=None,
                        dest='MESH_CUBOID',
949
                        help='7 floats parameters to mesh a cuboid. first 3 are position of the bottom corner (Z, Y, X), next 3 are the lenghts of the cube (Z, Y, X) and the last one is the average length between two nodes.')
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973

    args = parser.parse_args()

    if args.MESH_FILE is None and args.MESH_CUBOID is None:
        print("\tgdic: a mesh is needed. Use one of this option: -Mcube or -Mfile.")
        print("\tgdic: exiting.")
        exit()

    # 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.inFiles[0].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.inFiles[0].name)
        except OSError:
            if not os.path.isdir(args.OUT_DIR):
                raise
Emmanuel Roubin's avatar
gdic    
Emmanuel Roubin committed
974

975
976
    # Output file name prefix
    if args.PREFIX is None:
Emmanuel Roubin's avatar
Emmanuel Roubin committed
977
        args.PREFIX = "GDIC_{}-{}".format(os.path.splitext(os.path.basename(args.inFiles[0].name))[0], os.path.splitext(os.path.basename(args.inFiles[1].name))[0])
Emmanuel Roubin's avatar
gdic    
Emmanuel Roubin committed
978

979
980
    if type(args.MAX_ITERATIONS) == list:
        args.MAX_ITERATIONS = args.MAX_ITERATIONS[0]
Emmanuel Roubin's avatar
gdic    
Emmanuel Roubin committed
981

982
983
    if args.REG_MARGIN > 0.45:
        print("Registration margin cannot be bigger than 0.45 since 0.5 would contain no data!!")
Emmanuel Roubin's avatar
gdic    
Emmanuel Roubin committed
984

985
    return args
986

Edward Andò's avatar
Edward Andò committed
987

988
def regularStrainParser(parser):
989
990
991
992
993
    parser.add_argument('inFile',
                        metavar='inFile',
                        type=argparse.FileType('r'),
                        help='Path to TSV file containing the result of the correlation')

994
995
996
997
998
999
1000
1001
    parser.add_argument('-comp',
                        '--strain-components',
                        nargs='*',
                        type=str,
                        default=['vol', 'dev'],
                        dest='COMPONENTS',
                        help='Selection of which strain components to save, options are: vol (volumetric strain), dev (deviatoric strain), volss (volumetric strain in small strains), devss (deviatoric strain in small strains), r (rotation vector), z (zoom vector), U (right-hand stretch tensor), e (strain tensor in small strains)')

1002
1003
1004
1005
1006
1007
    parser.add_argument('-mask',
                        '--mask',
                        action="store_true",
                        dest='MASK',
                        help='Mask correlation points according to return status')

1008
1009
1010
1011
1012
1013
    parser.add_argument('-r',
                        '--neighbourhood-radius-for-strain-calculation',
                        type=float,
                        default=1.5,
                        dest='STRAIN_NEIGHBOUR_RADIUS',
                        help="Radius (in units of nodeSpacing) inside which to select neighbours for displacement gradient calculation. Ignored if -cub is set. Default = 1.5")
1014
1015
1016

    parser.add_argument('-cub',
                        '--cubic-element',
1017
                        '--Q8',
1018
1019
1020
1021
                        action="store_true",
                        dest='Q8',
                        help='Use Q8 element interpolation? More noisy and strain values not centred on displacement points')

1022
1023
1024
1025
1026
1027
1028
1029
    parser.add_argument('-cif',
                        '--correct-input-field',
                        action="store_true",
                        dest='CORRECT_FIELD',
                        help='Activates correction of the input displacement field')

    parser.add_argument('-cni',
                        '--correct-neighbours-for-field-interpolation',
Olga Stamati's avatar
Olga Stamati committed
1030
                        type=int,
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
                        default=12,
                        dest='CORRECT_NEIGHBOURS',
                        help="Neighbours for field interpolation. Default = 12")

    parser.add_argument('-cmf',
                        '--correct-median-filter',
                        action="store_true",
                        dest='CORRECT_MEDIAN_FILTER',
                        help="Activates an overall median filter on the input displacement field")

    parser.add_argument('-cmfr',
                        '--correct-median-filter-radius',
Olga Stamati's avatar
Olga Stamati committed
1043
                        type=int,
1044
1045
1046
1047
                        default=2,
                        dest='CORRECT_MEDIAN_FILTER_RADIUS',
                        help="Radius of median filter for correction of input displacement field. Default = 2")

1048
1049
    parser.add_argument('-cdp',
                        '--correct-delta-phi-norm',
1050
                        type=numpy.float,
1051
                        default=0.001,
1052
                        dest='CORRECT_DELTA_PHI_NORM',
1053
                        help="Delta Phi norm for a return status = 1 correlation window to consider the point good. Default = 0.001")
1054
1055
1056
1057

    parser.add_argument('-cpscc',
                        '--correct-pixel-search-cc',
                        type=numpy.float,
1058
                        default=0,
1059
                        dest='CORRECT_PIXEL_SEARCH_CC',
1060
                        help="Pixel search correlation coefficient to consider the point good. Default = 0")
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073

    parser.add_argument('-od',
                        '--out-dir',
                        type=str,
                        default=None,
                        dest='OUT_DIR',
                        help='Output directory, default is the dirname of input file')

    parser.add_argument('-pre',
                        '--prefix',
                        type=str,
                        default=None,
                        dest='PREFIX',
Edward Andò's avatar
Edward Andò committed
1074
                        help='Prefix for output files (without extension). Default is basename of input file')
Edward Andò's avatar
Edward Andò committed
1075

1076
1077
1078
    parser.add_argument('-tif',
                        '-tiff',
                        action="store_true",
Edward Andò's avatar
Edward Andò committed
1079
                        dest='TIFF',
1080
1081
1082
1083
1084
1085
1086
                        help='Activate TIFF output format. Default = False')

    parser.add_argument('-tsv',
                        '-TSV',
                        action="store_true",
                        dest='TSV',
                        help='Activate TSV output format. Default = False')
Edward Andò's avatar
Edward Andò committed
1087
1088
1089
1090
1091

    parser.add_argument('-vtk',
                        '--VTKout',
                        action="store_true",
                        dest='VTK',
1092
                        help='Activate VTK output format. Default = False')
Edward Andò's avatar
Edward Andò committed
1093

1094
1095
1096
1097
1098
1099
    parser.add_argument('-vtkmn',
                        '--VTKmaskNANs',
                        action="store_true",
                        dest='VTKmaskNAN',
                        help='Mask NaNs in VTK output (replace them with 0.0). Default = False')

Edward Andò's avatar
Edward Andò committed
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
    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.inFile.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.lab1.name)
        except OSError:
            if not os.path.isdir(args.OUT_DIR):
                raise
Emmanuel Roubin's avatar
Emmanuel Roubin committed
1118
    # Output file name prefix
Edward Andò's avatar
Edward Andò committed
1119
    if args.PREFIX is None:
1120
        args.PREFIX = os.path.splitext(os.path.basename(args.inFile.name))[0]
Edward Andò's avatar
Edward Andò committed
1121

Emmanuel Roubin's avatar
Emmanuel Roubin committed
1122
    # Make sure at least one output format has been asked for
1123
    if args.VTK + args.TIFF + args.TSV == 0:
Edward Andò's avatar
Edward Andò committed
1124
1125
        print("#############################################################")
        print("#############################################################")
1126
        print("###  WARNING: No output type of VTK, TSV or TIFF          ###")
Edward Andò's avatar
Edward Andò committed
1127
1128
1129
1130
1131
1132
        print("###  Are you sure this is right?!                         ###")
        print("#############################################################")
        print("#############################################################")

    return args

Edward Andò's avatar
Edward Andò committed
1133

Edward Andò's avatar
Edward Andò committed
1134
1135
1136
1137
1138
1139
def discreteStrainsCalcParser(parser):
    parser.add_argument('inFile',
                        metavar='inFile',
                        type=argparse.FileType('r'),
                        help='Path to TSV file containing the result of the correlation')

1140
1141
1142
1143
1144
1145
1146
    parser.add_argument('-comp',
                        '--strain-components',
                        nargs='*',
                        type=str,
                        default=['vol', 'dev'],
                        dest='COMPONENTS',
                        help='Selection of which strain components to save, options are: vol (volumetric strain), dev (deviatoric strain), volss (volumetric strain in small strains), devss (deviatoric strain in small strains), r (rotation vector), z (zoom vector), U (right-hand stretch tensor), e (strain tensor in small strains)')
Edward Andò's avatar
Edward Andò committed
1147
1148
1149
1150
1151
1152
1153
1154

    parser.add_argument('-od',
                        '--out-dir',
                        type=str,
                        default=None,
                        dest='OUT_DIR',
                        help='Output directory, default is the dirname of input file')

Edward Andò's avatar
Edward Andò committed
1155
1156
    parser.add_argument('-tri',
                        '--perform-triangulation',
1157
                        action="store_true",
Edward Andò's avatar
Edward Andò committed
1158
                        dest='TRI',
1159
                        help='Perform triangulation of grain centres?')
Edward Andò's avatar
Edward Andò committed
1160

1161
1162
1163
1164
1165
1166
1167
    parser.add_argument('-a',
                        '-triangulation-alpha-value',
                        type=float,
                        default=0.0,
                        dest='TRI_ALPHA',
                        help='CGAL Alpha value for triangulation cleanup (negative = auto, zero = no cleanup, positive = userval). Default = 0')

Edward Andò's avatar
Edward Andò committed
1168
    parser.add_argument('-tf',
1169
                        '--triangulation-file',
Edward Andò's avatar
Edward Andò committed
1170
1171
1172
                        typ