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