1 #include "mrilib.h"
usage_3dZeropad(int detail)2 void usage_3dZeropad(int detail)
3 {
4 printf("Usage: 3dZeropad [options] dataset\n"
5 "** Adds planes of zeros to a dataset (i.e., pads it out).\n"
6 "** A negative 'add' count means to cut a dataset down in size.\n"
7 " [Remember 3rd grade arithmetic, please.]\n"
8 "\n"
9 "Options:\n"
10 " -I n = adds 'n' planes of zero at the Inferior edge\n"
11 " -S n = adds 'n' planes of zero at the Superior edge\n"
12 " -A n = adds 'n' planes of zero at the Anterior edge\n"
13 " -P n = adds 'n' planes of zero at the Posterior edge\n"
14 " -L n = adds 'n' planes of zero at the Left edge\n"
15 " -R n = adds 'n' planes of zero at the Right edge\n"
16 " -z n = adds 'n' planes of zeros on EACH of the\n"
17 " dataset z-axis (slice-direction) faces\n"
18 "\n"
19 " -RL a = These options specify that planes should be added/cut\n"
20 " -AP b = symmetrically to make the resulting volume have\n"
21 " -IS c = 'a', 'b', and 'c' slices in the respective directions.\n"
22 "\n"
23 " -pad2evens = add 0 or 1 plane in each of the R/A/S directions,\n"
24 " giving each axis an even number of slices\n"
25 "\n"
26 " -mm = pad counts 'n' are in mm instead of slices:\n"
27 " * each 'n' is an integer\n"
28 " * at least 'n' mm of slices will be added/removed:\n"
29 " n = 3 and slice thickness = 2.5 mm ==> 2 slices added\n"
30 " n = -6 and slice thickness = 2.5 mm ==> 3 slices removed\n"
31 "\n"
32 " -master mset = match the volume described in dataset 'mset':\n"
33 " * mset must have the same orientation and grid\n"
34 " spacing as dataset to be padded\n"
35 " * the goal of -master is to make the output dataset\n"
36 " from 3dZeropad match the spatial 'extents' of\n"
37 " mset (cf. 3dinfo output) as much as possible,\n"
38 " by adding/subtracting slices as needed.\n"
39 " * you can't use -I,-S,..., or -mm with -master\n"
40 "\n"
41 " -prefix ppp = write result into dataset with prefix 'ppp'\n"
42 " [default = 'zeropad']\n"
43 "\n"
44 "Nota Bene:\n"
45 " * You can use negative values of n to cut planes off the edges\n"
46 " of a dataset. At least one plane must be added/removed\n"
47 " or the program won't do anything.\n"
48 " * Anat parent and Talairach markers are NOT preserved in the\n"
49 " new dataset.\n"
50 #if 0
51 " * If the old dataset has z-slice-dependent time offsets, and\n"
52 " if new z-planes are added, all the slice-dependent time\n"
53 " offsets will be removed.\n"
54 #else
55 " * If the old dataset has z-slice-dependent time offsets, and\n"
56 " if new (zero filled) z-planes are added, the time offsets\n"
57 " of the new slices will be set to zero.\n"
58 #endif
59 " * You can use program '3dinfo' to find out how many planes\n"
60 " a dataset has in each direction.\n"
61 " * Program works for byte-, short-, float-, and complex-valued\n"
62 " datasets.\n"
63 " * You can use a sub-brick selector on the input dataset.\n"
64 "\n"
65 " Author: RWCox - July 2000\n"
66 ) ;
67 PRINT_COMPILE_DATE ; return ;
68
69 }
70
main(int argc,char * argv[])71 int main( int argc , char * argv[] )
72 {
73 int iarg ;
74 THD_3dim_dataset *inset , *outset ;
75 int add_I=0 , add_S=0 , add_A=0 , add_P=0 , add_L=0 , add_R=0 ;
76 int RLsiz=0, APsiz=0, ISsiz=0 ; /* 23 Mar 2004 */
77 int add_any=0 , pad2evens=0; /* 23 Oct 2019 [rickr] */
78 char * prefix="zeropad" ;
79
80 int add_z=0 ; /* 07 Feb 2001 */
81 int mm_flag=0 ; /* 13 Feb 2001 */
82 int flag ;
83
84 THD_3dim_dataset *mset=NULL ; /* 14 May 2002 */
85
86 /*-- help? --*/
87 mainENTRY("3dZeropad main"); machdep(); AFNI_logger("3dZeropad",argc,argv);
88 PRINT_VERSION("3dZeropad") ;
89
90 /*-- read command line options --*/
91 if( argc == 1){ usage_3dZeropad(1); exit(0); } /* Bob's help shortcut */
92
93 iarg = 1 ;
94 while( iarg < argc && argv[iarg][0] == '-' ){
95
96 if( strcmp(argv[iarg],"-help") == 0 || strcmp(argv[iarg],"-h") == 0){
97 usage_3dZeropad(strlen(argv[iarg])>3 ? 2:1);
98 exit(0);
99 }
100
101 /*- -I, -S, etc. -*/
102
103 if( strlen(argv[iarg]) == 2 ){
104 switch( argv[iarg][1] ){
105 case 'I': add_I = (int) strtod(argv[++iarg],NULL) ; break ;
106 case 'S': add_S = (int) strtod(argv[++iarg],NULL) ; break ;
107 case 'A': add_A = (int) strtod(argv[++iarg],NULL) ; break ;
108 case 'P': add_P = (int) strtod(argv[++iarg],NULL) ; break ;
109 case 'L': add_L = (int) strtod(argv[++iarg],NULL) ; break ;
110 case 'R': add_R = (int) strtod(argv[++iarg],NULL) ; break ;
111
112 /* 07 Feb 2001: slice-direction is special */
113
114 case 'z':
115 case 'Z': add_z = (int) strtod(argv[++iarg],NULL) ; break ;
116
117 default:
118 fprintf(stderr,"** 3dZeropad: Illegal option: %s\n",argv[iarg]) ; exit(1) ;
119 }
120
121 if( mset != NULL ){
122 fprintf(stderr,"** 3dZeropad: Can't use %s with -master!\n",argv[iarg-1]) ;
123 exit(1) ;
124 }
125
126 iarg++ ; continue ; /* skip to next argument */
127 }
128
129 /*- -RL, -AP, -IS [23 Mar 2004] -*/
130
131 if( strcmp(argv[iarg],"-RL") == 0 || strcmp(argv[iarg],"-LR") == 0 ){
132 if( add_R || add_L || mset != NULL ){
133 fprintf(stderr,"** 3dZeropad: Can't use -RL with -R, -L, or -master!\n");
134 exit(1) ;
135 }
136 RLsiz = (int) strtod(argv[++iarg],NULL) ;
137 if( RLsiz < 1 ){
138 fprintf(stderr,"** 3dZeropad: value after -RL is illegal!\n") ;
139 exit(1) ;
140 }
141 iarg++ ; continue ;
142 }
143
144 if( strcmp(argv[iarg],"-AP") == 0 || strcmp(argv[iarg],"-PA") == 0 ){
145 if( add_A || add_P || mset != NULL ){
146 fprintf(stderr,"** 3dZeropad: Can't use -AP with -A, -P, or -master!\n");
147 exit(1) ;
148 }
149 APsiz = (int) strtod(argv[++iarg],NULL) ;
150 if( APsiz < 1 ){
151 fprintf(stderr,"** 3dZeropad: value after -AP is illegal!\n") ;
152 exit(1) ;
153 }
154 iarg++ ; continue ;
155 }
156
157 if( strcmp(argv[iarg],"-IS") == 0 || strcmp(argv[iarg],"-SI") == 0 ){
158 if( add_S || add_I || mset != NULL ){
159 fprintf(stderr,"** 3dZeropad: Can't use -IS with -I, -S, or -master!\n");
160 exit(1) ;
161 }
162 ISsiz = (int) strtod(argv[++iarg],NULL) ;
163 if( ISsiz < 1 ){
164 fprintf(stderr,"** 3dZeropad: value after -IS is illegal!\n") ;
165 exit(1) ;
166 }
167 iarg++ ; continue ;
168 }
169
170 /*- -mm -*/
171
172 if( strcmp(argv[iarg],"-mm") == 0 ){
173 if( mset != NULL ){
174 fprintf(stderr,"** 3dZeropad: Can't use %s with -master!\n",argv[iarg]) ;
175 exit(1) ;
176 }
177 mm_flag = 1 ;
178 iarg++ ; continue ;
179 }
180
181 /*- -pad2evens -*/
182
183 if( strcmp(argv[iarg],"-pad2evens") == 0 ){
184 pad2evens = 1 ;
185 iarg++ ; continue ;
186 }
187
188 /*- -prefix -*/
189
190 if( strcmp(argv[iarg],"-prefix") == 0 ){
191 prefix = argv[++iarg] ;
192 if( !THD_filename_ok(prefix) ){
193 fprintf(stderr,"** 3dZeropad: Illegal string after -prefix!\n"); exit(1) ;
194 }
195 iarg++ ; continue ;
196 }
197
198 /*-- -master [14 May 2002] --*/
199
200 if( strcmp(argv[iarg],"-master") == 0 ){
201 if( add_I || add_S || add_A || mm_flag ||
202 add_P || add_R || add_L || add_z ||
203 RLsiz || APsiz || ISsiz ){
204
205 fprintf(stderr,"** 3dZeropad: Can't use -master with -I,-S,-A,-P,-R,-L, or -mm!\n");
206 exit(1) ;
207 }
208 if( mset != NULL ){
209 fprintf(stderr,"** 3dZeropad: Can't use -master twice!\n"); exit(1);
210 }
211
212 mset = THD_open_dataset( argv[++iarg] ) ;
213 if( !ISVALID_DSET(mset) ){
214 fprintf(stderr,"** 3dZeropad: Can't open -master %s\n",argv[iarg]); exit(1);
215 }
216 THD_make_cardinal(mset); /* deoblique 21 Oct, 2011 [rickr] */
217 iarg++ ; continue ;
218 }
219
220 /*- what the hell? -*/
221
222 fprintf(stderr,"** 3dZeropad: Illegal option: %s\n",argv[iarg]) ;
223 suggest_best_prog_option(argv[0], argv[iarg]);
224 exit(1) ;
225 }
226
227 if (iarg < 2) {
228 ERROR_message("Too few options, try %s -help for details\n",argv[0]);
229 exit(1);
230 }
231
232 /*- check to see if the user asked for something, anything -*/
233
234 add_any = add_I || add_S || add_P || add_A || add_L || add_R
235 || add_z || RLsiz || APsiz || ISsiz ;
236
237 /* pad2evens should be used alone */
238 if( pad2evens && (add_any || mset) )
239 ERROR_exit("Cannot combine -pad2evens with other padding or master") ;
240
241 if( mset == NULL && add_any == 0 && pad2evens == 0 ) {
242 fprintf(stderr,"++ 3dZeropad: All inputs are zero? Making a copy!\n") ;
243 }
244
245 /* check for conflicts [23 Mar 2004] */
246
247 if( RLsiz > 0 && (add_R || add_L || add_z) ){
248 fprintf(stderr,"** 3dZeropad: Can't use -R or -L or -z with -RL!\n"); exit(1);
249 }
250 if( APsiz > 0 && (add_A || add_P || add_z) ){
251 fprintf(stderr,"** 3dZeropad: Can't use -A or -P or -z with -AP!\n"); exit(1);
252 }
253 if( ISsiz > 0 && (add_I || add_S || add_z) ){
254 fprintf(stderr,"** 3dZeropad: Can't use -I or -S or -z with -IS!\n"); exit(1);
255 }
256
257 /*-- read the input dataset --*/
258
259 if( iarg >= argc ){
260 fprintf(stderr,"** 3dZeropad: No input dataset on command line!\n"); exit(1);
261 }
262
263 #if 0
264 if( strncmp(argv[iarg],"3dcalc(",7) == 0 ){
265 fprintf(stderr,"** 3dZeropad: Can't use '3dcalc()' input datasets here!\n"); exit(1);
266 }
267 #endif
268
269 inset = THD_open_dataset( argv[iarg] ) ;
270 if( inset == NULL ){
271 fprintf(stderr,"** 3dZeropad: Can't open dataset %s\n",argv[iarg]); exit(1);
272 }
273 THD_make_cardinal(inset); /* deoblique 21 Oct, 2011 [rickr] */
274
275 #if 0
276 if( DSET_IS_MASTERED(inset) ){
277 fprintf(stderr,"** 3dZeropad: Can't use partial datasets!\n"); exit(1);
278 }
279 #endif
280
281 /*-- if pad2evens, decide on padding [23 Oct 2019 rickr] --*/
282 /* do not worry about nx,ny,nz, focus on RL/AP,IS */
283 if( pad2evens ) {
284 THD_dataxes * iax = inset->daxes ;
285 int ndr, nda, ndi ;
286 ndr = DAXES_NUM(iax,ORI_R2L_TYPE) ;
287 nda = DAXES_NUM(iax,ORI_A2P_TYPE) ;
288 ndi = DAXES_NUM(iax,ORI_I2S_TYPE) ;
289 add_R = ndr % 2 ; /* add 1 if odd */
290 add_A = nda % 2 ;
291 add_I = ndi % 2 ;
292 INFO_message("pad2evens: applying -R %d -A %d -I %d\n",
293 add_R, add_A, add_I);
294 }
295
296 /*-- 14 May 2002: use master dataset now? --*/
297
298 if( mset != NULL ){
299 THD_dataxes *max=mset->daxes, *iax=inset->daxes ;
300 int nerr=0 ;
301 float mxbot,mybot,mzbot , mxtop,mytop,mztop , mdx,mdy,mdz ;
302 float ixbot,iybot,izbot , ixtop,iytop,iztop , idx,idy,idz ;
303 int mnx,mny,mnz , inx,iny,inz ;
304 int add_xb,add_xt , add_yb,add_yt , add_zb,add_zt ;
305
306 /* check if datasets are oriented the same */
307
308 if( max->xxorient != iax->xxorient ||
309 max->yyorient != iax->yyorient ||
310 max->zzorient != iax->zzorient ){
311
312 fprintf(stderr,
313 "** 3dZeropad: Master (%s) and Input (%s) dataset not oriented the same!\n",
314 DSET_PREFIX(mset), DSET_PREFIX(inset));
315 nerr++ ;
316 }
317
318 /* check if datasets have same voxel dimensions */
319
320 mdx = max->xxdel ; mdy = max->yydel ; mdz = max->zzdel ;
321 idx = iax->xxdel ; idy = iax->yydel ; idz = iax->zzdel ;
322 mnx = max->nxx ; mny = max->nyy ; mnz = max->nzz ;
323 inx = iax->nxx ; iny = iax->nyy ; inz = iax->nzz ;
324
325 if( fabs(mdx-idx) > 0.01*fabs(mdx) ||
326 fabs(mdy-idy) > 0.01*fabs(mdy) ||
327 fabs(mdz-idz) > 0.01*fabs(mdz) ){
328
329 fprintf(stderr,"** 3dZeropad: Master and Input datasets don't have same voxel size!\n");
330 nerr++ ;
331 }
332
333 if( nerr ) exit(1) ;
334
335 /* calculate coords at top and bottom of each dataset */
336
337 mxbot = max->xxorg ; mxtop = mxbot + mnx*mdx ;
338 mybot = max->yyorg ; mytop = mybot + mny*mdy ;
339 mzbot = max->zzorg ; mztop = mzbot + mnz*mdz ;
340
341 ixbot = iax->xxorg ; ixtop = ixbot + inx*idx ;
342 iybot = iax->yyorg ; iytop = iybot + iny*idy ;
343 izbot = iax->zzorg ; iztop = izbot + inz*idz ;
344
345 /* calculate amount to add/trim at each face */
346
347 add_xb = (int) rint((ixbot-mxbot)/idx) ;
348 add_xt = (int) rint((mxtop-ixtop)/idx) ;
349 add_yb = (int) rint((iybot-mybot)/idy) ;
350 add_yt = (int) rint((mytop-iytop)/idy) ;
351 add_zb = (int) rint((izbot-mzbot)/idz) ;
352 add_zt = (int) rint((mztop-iztop)/idz) ;
353
354 /* map trims from x,y,z to RL,AP,IS coords */
355
356 switch( iax->xxorient ){
357 case ORI_R2L_TYPE: add_R = add_xb ; add_L = add_xt ; break ;
358 case ORI_L2R_TYPE: add_L = add_xb ; add_R = add_xt ; break ;
359 case ORI_I2S_TYPE: add_I = add_xb ; add_S = add_xt ; break ;
360 case ORI_S2I_TYPE: add_S = add_xb ; add_I = add_xt ; break ;
361 case ORI_A2P_TYPE: add_A = add_xb ; add_P = add_xt ; break ;
362 case ORI_P2A_TYPE: add_P = add_xb ; add_A = add_xt ; break ;
363 }
364
365 switch( iax->yyorient ){
366 case ORI_R2L_TYPE: add_R = add_yb ; add_L = add_yt ; break ;
367 case ORI_L2R_TYPE: add_L = add_yb ; add_R = add_yt ; break ;
368 case ORI_I2S_TYPE: add_I = add_yb ; add_S = add_yt ; break ;
369 case ORI_S2I_TYPE: add_S = add_yb ; add_I = add_yt ; break ;
370 case ORI_A2P_TYPE: add_A = add_yb ; add_P = add_yt ; break ;
371 case ORI_P2A_TYPE: add_P = add_yb ; add_A = add_yt ; break ;
372 }
373
374 switch( iax->zzorient ){
375 case ORI_R2L_TYPE: add_R = add_zb ; add_L = add_zt ; break ;
376 case ORI_L2R_TYPE: add_L = add_zb ; add_R = add_zt ; break ;
377 case ORI_I2S_TYPE: add_I = add_zb ; add_S = add_zt ; break ;
378 case ORI_S2I_TYPE: add_S = add_zb ; add_I = add_zt ; break ;
379 case ORI_A2P_TYPE: add_A = add_zb ; add_P = add_zt ; break ;
380 case ORI_P2A_TYPE: add_P = add_zb ; add_A = add_zt ; break ;
381 }
382
383 fprintf(stderr,"++ 3dZeropad -master => -I %d -S %d -A %d -P %d -R %d -L %d\n",
384 add_I,add_S,add_A,add_P,add_R,add_L ) ;
385
386 DSET_delete(mset) ;
387 }
388
389 /*-- 07 Feb 2001: if -z was used, fix that now --*/
390
391 if( add_z != 0 ){
392 switch( inset->daxes->zzorient ){
393 case ORI_R2L_TYPE:
394 case ORI_L2R_TYPE:
395 if( add_R != 0 && add_R != add_z ) fprintf(stderr,"++ 3dZeropad: -z overrides -R\n");
396 if( add_L != 0 && add_L != add_z ) fprintf(stderr,"++ 3dZeropad: -z overrides -L\n");
397 add_R = add_L = add_z ;
398 break ;
399
400 case ORI_P2A_TYPE:
401 case ORI_A2P_TYPE:
402 if( add_P != 0 && add_P != add_z ) fprintf(stderr,"++ 3dZeropad: -z overrides -P\n");
403 if( add_A != 0 && add_A != add_z ) fprintf(stderr,"++ 3dZeropad: -z overrides -A\n");
404 add_P = add_A = add_z ;
405 break ;
406
407 case ORI_I2S_TYPE:
408 case ORI_S2I_TYPE:
409 if( add_I != 0 && add_I != add_z ) fprintf(stderr,"++ 3dZeropad: -z overrides -I\n");
410 if( add_I != 0 && add_S != add_z ) fprintf(stderr,"++ 3dZeropad: -z overrides -S\n");
411 add_I = add_S = add_z ;
412 break ;
413 }
414 }
415
416 /*-- 23 Mar 2004: expand/contract if ordered --*/
417
418 if( RLsiz > 0 ){
419 int nold=0 ;
420 if( inset->daxes->xxorient == ORI_R2L_TYPE || inset->daxes->xxorient == ORI_L2R_TYPE )
421 nold = inset->daxes->nxx ;
422 else if( inset->daxes->yyorient == ORI_R2L_TYPE || inset->daxes->yyorient == ORI_L2R_TYPE )
423 nold = inset->daxes->nyy ;
424 else if( inset->daxes->zzorient == ORI_R2L_TYPE || inset->daxes->zzorient == ORI_L2R_TYPE )
425 nold = inset->daxes->nzz ;
426 if( nold > 0 ){
427 add_R = (RLsiz-nold) / 2 ;
428 add_L = RLsiz-(nold+add_R) ;
429 }
430 }
431
432 if( APsiz > 0 ){
433 int nold=0 ;
434 if( inset->daxes->xxorient == ORI_A2P_TYPE || inset->daxes->xxorient == ORI_P2A_TYPE )
435 nold = inset->daxes->nxx ;
436 else if( inset->daxes->yyorient == ORI_A2P_TYPE || inset->daxes->yyorient == ORI_P2A_TYPE )
437 nold = inset->daxes->nyy ;
438 else if( inset->daxes->zzorient == ORI_A2P_TYPE || inset->daxes->zzorient == ORI_P2A_TYPE )
439 nold = inset->daxes->nzz ;
440 if( nold > 0 ){
441 add_A = (APsiz-nold) / 2 ;
442 add_P = APsiz-(nold+add_A) ;
443 }
444 }
445
446 if( ISsiz > 0 ){
447 int nold=0 ;
448 if( inset->daxes->xxorient == ORI_I2S_TYPE || inset->daxes->xxorient == ORI_S2I_TYPE )
449 nold = inset->daxes->nxx ;
450 else if( inset->daxes->yyorient == ORI_I2S_TYPE || inset->daxes->yyorient == ORI_S2I_TYPE )
451 nold = inset->daxes->nyy ;
452 else if( inset->daxes->zzorient == ORI_I2S_TYPE || inset->daxes->zzorient == ORI_S2I_TYPE )
453 nold = inset->daxes->nzz ;
454 if( nold > 0 ){
455 add_I = (ISsiz-nold) / 2 ;
456 add_S = ISsiz-(nold+add_I) ;
457 }
458 }
459
460 /*-- 04 Oct 2000: all the real work is now in thd_zeropad.c --*/
461
462 flag = ZPAD_PURGE ;
463 if( mm_flag ) flag |= ZPAD_MM ;
464
465 outset = THD_zeropad( inset ,
466 add_I, add_S, add_A, add_P, add_L, add_R,
467 prefix , flag ) ;
468
469 if( THD_deathcon() && THD_is_file(DSET_HEADNAME(outset)) ){
470 fprintf(stderr,
471 "** 3dZeropad: output file %s already exists - FATAL ERROR!\n",
472 DSET_HEADNAME(outset) ) ;
473 exit(1) ;
474 }
475
476 if( outset == NULL ){
477 fprintf(stderr,"** 3dZeropad: Some error occurred in processing!\n") ;
478 exit(1) ;
479 }
480
481 tross_Copy_History( inset , outset ) ; /* 31 Jan 2001 - RWCox */
482 tross_Make_History( "3dZeropad" , argc,argv , outset ) ;
483
484 if (DSET_write(outset) != False) {
485 fprintf(stderr,"++ output dataset: %s\n",DSET_BRIKNAME(outset)) ;
486 exit(0) ;
487 } else {
488 fprintf(stderr,
489 "** 3dZeropad: Failed to write output!\n" ) ;
490 exit(1) ;
491 }
492
493 }
494