optionsParser.py 112 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
    # PFD now assumed to be true
    #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")
87

88
89
90
91
92
93
    #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
97
    parser.add_argument('-glt',
                        '--grey-low-threshold',
                        type=float,
98
                        default=-numpy.inf,
99
                        dest='GREY_LOW_THRESH',
100
101
102
103
104
105
106
107
                        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")
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130

    # 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
131
                        type=int,
132
133
                        default=None,
                        dest='HWS',
134
                        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")
135
136
137
138
139
140
141
142
143
144

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

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

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

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

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

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

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

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

197
198
199
200
201
    #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')
202

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

209
210
211
212
213
214
215
216
217
218
219
220
    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
221
                        help="Prefix for output files (without extension). Default is basename of input file")
222
223
224
225
226
227
228

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

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

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

    args = parser.parse_args()

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

258
259
    # 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
260
261
262
263
        twoD = True
    else:
        twoD = False
    tiff.close()
264

265
    # 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
266
267
    if args.OUT_DIR is None:
        args.OUT_DIR = os.path.dirname(args.inFiles[0].name)
268
        # However if we have no dir, notice this and make it the current directory.
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
269
270
        if args.OUT_DIR == "":
            args.OUT_DIR = "./"
271
272
273
274
275
276
    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
277
                args.DIR_out = os.path.dirname(args.inFiles[0].name)
278
279
280
281
282
283
        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
284
        print("\nUsing default node spacing: "),
285
        if args.HWS is None:
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
286
            print("2x default half window size"),
287
            args.HWS = [10]
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
288
289
            print("({}) which is".format(args.HWS[0])),
            args.NS = [args.HWS[0] * 2]
290
        else:
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
291
292
293
294
295
296
297
298
            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)
299
300

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

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

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

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

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

319
    
320
321
322
323
324
325
326
327
328
    # 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("#############################################################")

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

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

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

343
344
345
    return args


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

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

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

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

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

Edward Andò's avatar
Edward Andò committed
376
377
378
379
380
381
    #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
382

383
384
385
386
387
388
389
    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
390
391
392
    parser.add_argument('-pf',
                        '-phiFile',
                        dest='PHIFILE',
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
393
                        default=None,
394
395
396
                        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
397
398
    parser.add_argument('-pfb',
                        '--phiFile-bin-ratio',
399
400
                        type=int,
                        default=1,
Edward Andò's avatar
Edward Andò committed
401
                        dest='PHIFILE_BIN_RATIO',
402
                        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")
403

404
405
406
407
408
409
410
    # PFD now strictly assumed
    #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 -cif and requires labels to be aligned between Phi file and labelled image. Default = False")
411

412
413
414
415
416
417
418
419
    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
420
                        type=int,
421
422
                        default=12,
                        dest='NEIGHBOURS',
423
                        help="Number of neighbours for field interpolation. Default = 12")
424

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

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

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

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

Edward Andò's avatar
Edward Andò committed
453
    parser.add_argument('-lcnr',
454
455
456
457
458
459
460
                        '--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',
461
                        action="store_true",
462
                        dest='LABEL_CORRELATE_UPDATE_GRADIENT',
463
464
                        help='Update gradient in label registration? More computation time but more robust and possibly fewer iterations.')

465
466
467
468
469
470
471
472
473
474
475
476
477
    #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")

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

    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
496
                        help="Prefix for output files (without extension). Default is basename of input file")
497

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

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

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

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

Edward Andò's avatar
Edward Andò committed
535
536
537
    ## 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
538

Edward Andò's avatar
Edward Andò committed
539
540
541
    #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
542

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

547
    return args
548
549


Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
550
def multiModalRegistrationParser(parser):
551
    import spam.DIC
Edward Andò's avatar
Edward Andò committed
552
    import numpy
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
586
587

    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
588
589
590
591
592
593
594
595
596
597
598
599
600
601
    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.')

602
603
    parser.add_argument('-bin',
                        '--bin-levels',
Edward Andò's avatar
Edward Andò committed
604
                        type=int,
Edward Andò's avatar
Edward Andò committed
605
606
607
                        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)')
608
609
610
611
612
613
614

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

    parser.add_argument('-jhb',
                        '--joint-histogram-bins',
Emmanuel Roubin's avatar
MMR    
Emmanuel Roubin committed
619
                        # nargs=1,
620
621
622
623
624
                        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
625
626
627
628
629
    parser.add_argument('-dst',
                        '--dist-between-max',
                        type=int,
                        default=None,
                        dest='DIST_BETWEEN_MAX',
Emmanuel Roubin's avatar
Emmanuel Roubin committed
630
631
632
633
634
635
636
637
                        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
638

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

646
647
648
649
650
651
652
653
654
655
656
657
    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
658
659
660
661
662
663
664
    parser.add_argument('-ssl',
                        '--show-slice-axis',
                        type=int,
                        default=0,
                        dest='SHOW_SLICE_AXIS',
                        help='Axis of the cut used for the plots')

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

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

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

685
686
687
688
689
    #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
690

691
    parser.add_argument('-mar',
Emmanuel Roubin's avatar
Emmanuel Roubin committed
692
                        '--margin',
693
694
                        type=float,
                        default=0.1,
Emmanuel Roubin's avatar
Emmanuel Roubin committed
695
696
697
698
699
700
701
702
703
                        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')
704

705
706
707
708
709
    #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
710

Edward Andò's avatar
Edward Andò committed
711
    # Remove next two arguments for F input, and replace with displacement and rotation inputs on command line
712
713
714
    parser.add_argument('-pf',
                        '--phiFile',
                        dest='PHIFILE',
715
                        default=None,
716
                        type=argparse.FileType('r'),
717
                        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
718
719
720
721
722

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

726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
    # 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")
741
742
743
744
745
746
747
748
749
750
751
752
753

    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
754
                        help="Prefix for output files (without extension). Default is basename of input file")
755
756
757
758

    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
759
    if (args.NBINS != len(args.PHASES)):
760
761
762
        print("\toptionsParser.multiModalRegistrationParser(): Number of bin levels and number of phases not the same, exiting")
        exit()

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

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

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

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

    return args
Emmanuel Roubin's avatar
gdic    
Emmanuel Roubin committed
797
798


Emmanuel Roubin's avatar
Emmanuel Roubin committed
799
def gdicParser(parser):
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
829
830
    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',
831
                        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")
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846

    # 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
847
848
849
850
851
852
    parser.add_argument('-d',
                        '--debug',
                        action="store_true",
                        dest='DEBUG_FILES',
                        help='Output debug files during iterations? Default = False')

853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
    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')

873
874
875
876
877
878
    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')

879
880
    parser.add_argument('-mit',
                        '--max-iterations',
Olga Stamati's avatar
Olga Stamati committed
881
                        type=int,
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
                        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
898

899
900
901
902
903
    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
904

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

912
913
914
915
916
    # 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
917

918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
    # 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
935
                        default=None,
936
                        dest='PREFIX',
Edward Andò's avatar
Edward Andò committed
937
                        help="Prefix for output files (without extension). Default is basename of input file")
938
939
940
941
942
943
944
945
946
947
948
949
950

    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',
951
                        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.')
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975

    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
976

977
978
    # Output file name prefix
    if args.PREFIX is None:
Emmanuel Roubin's avatar
Emmanuel Roubin committed
979
        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
980

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

984
985
    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
986

987
    return args
988

Edward Andò's avatar
Edward Andò committed
989

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

996
997
998
999
1000
1001
1002
1003
    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)')

1004
1005
1006
1007
1008
1009
1010
    parser.add_argument('-np',
                        '--number-of-processes',
                        default=None,
                        type=int,
                        dest='PROCESSES',
                        help="Number of parallel processes to use. Default = multiprocessing.cpu_count()")

1011
1012
1013
1014
1015
1016
    parser.add_argument('-mask',
                        '--mask',
                        action="store_true",
                        dest='MASK',
                        help='Mask correlation points according to return status')

1017
1018
1019
1020
1021
1022
    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")
1023
1024
1025

    parser.add_argument('-cub',
                        '--cubic-element',
1026
                        '--Q8',
1027
1028
1029
1030
                        action="store_true",
                        dest='Q8',
                        help='Use Q8 element interpolation? More noisy and strain values not centred on displacement points')

1031
1032
1033
1034
1035
1036
1037
1038
    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
1039
                        type=int,
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
                        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
1052
                        type=int,
1053
1054
1055
1056
                        default=2,
                        dest='CORRECT_MEDIAN_FILTER_RADIUS',
                        help="Radius of median filter for correction of input displacement field. Default = 2")

1057
1058
    parser.add_argument('-cdp',
                        '--correct-delta-phi-norm',
1059
                        type=numpy.float,
1060
                        default=0.001,
1061
                        dest='CORRECT_DELTA_PHI_NORM',
1062
                        help="Delta Phi norm for a return status = 1 correlation window to consider the point good. Default = 0.001")
1063
1064
1065
1066

    parser.add_argument('-cpscc',
                        '--correct-pixel-search-cc',
                        type=numpy.float,
1067
                        default=0,
1068
                        dest='CORRECT_PIXEL_SEARCH_CC',
1069
                        help="Pixel search correlation coefficient to consider the point good. Default = 0")
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082

    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
1083
                        help='Prefix for output files (without extension). Default is basename of input file')
Edward Andò's avatar
Edward Andò committed
1084

1085
1086
1087
    parser.add_argument('-tif',
                        '-tiff',
                        action="store_true",
Edward Andò's avatar
Edward Andò committed
1088
                        dest='TIFF',
1089
1090
                        help='Activate TIFF output format. Default = False')

1091
1092
1093
    parser.add_argument('-notsv',
                        '-noTSV',
                        action="store_false",
1094
                        dest='TSV',
1095
                        help='Disactivate TSV output format?')
Edward Andò's avatar
Edward Andò committed
1096
1097
1098
1099
1100

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

1103
1104
1105
    parser.add_argument('-vtkln',
                        '--VTKleaveNANs',
                        action="store_false",
1106
                        dest='VTKmaskNAN',
1107
                        help='Leave NaNs in VTK output? If this option is not set they are replaced with 0.0')
1108

Edward Andò's avatar
Edward Andò committed
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
    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
1127
    # Output file name prefix
Edward Andò's avatar
Edward Andò committed
1128
    if args.PREFIX is None:
1129
        args.PREFIX = os.path.splitext(os.path.basename(args.inFile.name))[0]
Edward Andò's avatar
Edward Andò committed
1130

Emmanuel Roubin's avatar
Emmanuel Roubin committed
1131
    # Make sure at least one output format has been asked for
1132
    if args.VTK + args.TIFF + args.TSV == 0:
Edward Andò's avatar
Edward Andò committed
1133
1134
        print("#############################################################")
        print("#############################################################")
1135
        print("###  WARNING: No output type of VTK, TSV or TIFF          ###")
Edward Andò's avatar
Edward Andò committed
1136
1137
1138
1139
1140
1141
        print("###  Are you sure this is right?!                         ###")
        print("#############################################################")
        print("#############################################################")

    return args

Edward Andò's avatar
Edward Andò committed
1142

Edward Andò's avatar
Edward Andò committed
1143
1144
1145
1146
1147
1148
def discreteStrainsCalcParser(parser):
    parser.add_argument('inFile',
                        metavar='inFile',
                        type=argparse.FileType('r'),
                        help='Path to TSV file containing the result of the correlation')

1149
1150
1151
1152
1153
1154
1155
    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
1156

1157
1158
1159
1160
1161
1162
1163
    parser.add_argument('-np',
                        '--number-of-processes',
                        default=None,
                        type=int,
                        dest='PROCESSES',
                        help="Number of parallel processes to use. Default = multiprocessing.cpu_count()")

Edward Andò's avatar
Edward Andò committed
1164
1165
1166
1167
1168
1169
1170