1 /*****************************************************************************
2    Major portions of this software are copyrighted by the Medical College
3    of Wisconsin, 1994-2000, and are released under the Gnu General Public
4    License, Version 2.  See the file README.Copyright for details.
5 ******************************************************************************/
6 
7 #include "mrilib.h"
8 
9 /** Error messaging **/
10 
11 #undef  EDERR
12 #define EDERR(str) \
13  do{ ERROR_message("EDIT_dset_items[%d]: %s\n",ncall,str); errnum++; } while(0)
14 
15 #undef  EDERR_int
16 #define EDERR_int(str,zqq) \
17  do{ ERROR_message("EDIT_dset_items[%d]: %s : %d\n",ncall,str,zqq); errnum++; } while(0)
18 
19 
20 /* Remove +view.BRIK ness ZSS Feb 2012 */
21 #define STRING_DEVIEW_DEEXT_BRICK(fname) {   \
22    if (STRING_HAS_SUFFIX((fname),"+orig.BRIK") || \
23       STRING_HAS_SUFFIX((fname),"+acpc.BRIK") ||  \
24       STRING_HAS_SUFFIX((fname),"+tlrc.BRIK") ) { /* ZSS Nov 2011 */   \
25       (fname)[ll-10] = '\0' ;   \
26    } else if (STRING_HAS_SUFFIX((fname),"+orig.BRIK.gz") ||   \
27              STRING_HAS_SUFFIX((fname),"+acpc.BRIK.gz") || \
28              STRING_HAS_SUFFIX((fname),"+tlrc.BRIK.gz") ) {/* ZSS Feb 2012 */   \
29      (fname)[ll-13] = '\0' ; \
30    }  \
31 }
32 
33 /*-----------------------------------------------------------------------*/
34 /*! Edit some internals of a dataset.  Notice that it is possible to
35   create a dataset which is inconsistent.  Note also that some operations
36   cannot be performed on a dataset containing actual data -- for example,
37   you cannot change the types of sub-bricks if they already are attached
38   to data arrays!
39 
40   This routine uses the <stdarg.h> variable argument interface.
41   The first argument is a pointer to the dataset to edit.
42   All succeeding arguments are pairs indicating which internal item
43   to edit, and the new value for that item.  The first entry of a pair
44   must be one of the ADN_ entries defined in editvol.h.  The type of the
45   second entry of a pair depends on the particular item.
46   [*** WARNING: due to C automatic 'type promotion', you cannot use
47        float as the type to extract from the list -- you must use double!]
48 
49   Finally, the end of the argument list is found by the last argument
50   being the special code ADN_none (0).
51 
52   The return value is the number of errors detected (hopefully, 0).
53 -------------------------------------------------------------------------*/
54 
EDIT_dset_items(THD_3dim_dataset * dset,...)55 int EDIT_dset_items( THD_3dim_dataset *dset , ... )
56 {
57    va_list vararg_ptr ;
58    int     flag_arg , errnum = 0 ;
59    int     redo_bricks , redo_daxes , redo_taxis , ii ;
60    void   *dummy ;
61    int     iarg ;
62    static int ncall=0 ;  /* 20 Dec 2005 */
63 
64    /**----- variables to flag and store presence of arguments -----**/
65 
66    int new_prefix        = 0; char *            prefix         = NULL ;
67    int new_directory_name= 0; char *            directory_name = NULL ;
68    int new_brick_fac     = 0; float *           brick_fac      = NULL ;
69    int new_malloc_type   = 0; int               malloc_type    = ILLEGAL_TYPE;
70    int new_datum_all     = 0; int               datum_all      = ILLEGAL_TYPE;
71    int new_datum_array   = 0; int *             datum_array    = NULL ;
72    int new_nvals         = 0; int               nvals          = 0 ;
73    int new_nxyz          = 0; THD_ivec3         nxyz           ;
74    int new_xyzdel        = 0; THD_fvec3         xyzdel         ;
75    int new_xyzorg        = 0; THD_fvec3         xyzorg         ;
76    int new_xyzorient     = 0; THD_ivec3         xyzorient      ;
77    int new_to_dicomm     = 0; THD_mat33         to_dicomm      ;
78    int new_ntt           = 0; int               ntt            = 0 ;
79    int new_ttorg         = 0; float             ttorg          = 0.0 ;
80    int new_ttdel         = 0; float             ttdel          = 0.0 ;
81    int new_ttdur         = 0; float             ttdur          = 0.0 ;
82    int new_nsl           = 0; int               nsl            = 0 ;
83    int new_zorg_sl       = 0; float             zorg_sl        = 0.0 ;
84    int new_dz_sl         = 0; float             dz_sl          = 0.0 ;
85    int new_toff_sl       = 0; float *           toff_sl        = NULL ;
86    int new_type          = 0; int               type           = ILLEGAL_TYPE;
87    int new_view_type     = 0; int               view_type      = ILLEGAL_TYPE;
88    int new_func_type     = 0; int               func_type      = ILLEGAL_TYPE;
89    int new_label1        = 0; char *            label1         = NULL ;
90    int new_label2        = 0; char *            label2         = NULL ;
91    int new_self_name     = 0; char *            self_name      = NULL ;
92    int new_warp_parent   = 0; THD_3dim_dataset *warp_parent    = NULL ;
93    int new_anat_parent   = 0; THD_3dim_dataset *anat_parent    = NULL ;
94    int new_stat_aux      = 0; float *           stat_aux       = NULL ;
95    int new_warp          = 0; THD_warp *        warp           = NULL ;
96    int new_tunits        = 0; int               tunits         = ILLEGAL_TYPE;
97    int new_keywords      = 0; char *            keywords       = NULL ;
98 
99    /* 30 Nov 1997 */
100 
101    int new_brick_label_one = 0 ; char * brick_label_one    = NULL ;
102                                  int    brick_label_one_iv = -1 ;
103 
104    int new_brick_fac_one = 0 ; float brick_fac_one    = 0.0 ;
105                                int   brick_fac_one_iv = -1 ;
106 
107    int new_brick_stataux_one = 0 ; float * brick_stataux_one    = NULL ;
108                                    int     brick_stataux_one_iv = -1 ;
109 
110    int new_brick_keywords_one = 0 ; char * brick_keywords_one    = NULL ;
111                                     int    brick_keywords_one_iv = -1 ;
112 
113    /* 19 Dec 2005 */
114 
115    int new_ijk_to_dicom = 0; mat44 ijk_to_dicom ;
116 
117    /* 14 July 2006   - check compression mode for NIFTI separately */
118    /*  1 June 2021   - never auto-compress NIFTI [rickr]           */
119    /* int cmode = COMPRESS_NOFILE;                                 */
120 
121    int new_smode=STORAGE_UNDEFINED; /* ZSS Feb 2012 */
122 
123 
124    /****---------------------- Sanity Check ----------------------****/
125 
126 ENTRY("EDIT_dset_items") ;
127 
128    ncall++ ;  /* 20 Dec 2005: to keep track of number of calls for EDERR */
129 
130    if( ! ISVALID_3DIM_DATASET(dset) ){                /* bad data */
131      EDERR("invalid input dataset"); RETURN(errnum);
132    }
133 
134    /****----------- Scan input argument list;
135                   - Load data into locals (va_arg);
136                   - Check for legal values;
137                   - Flag its presence (the new_ variables);
138                   - Carry out simple processing that doesn't
139                       depend on the presence of other arguments. ---------****/
140 
141    va_start( vararg_ptr , dset ) ;              /** Initialize arg reading **/
142    iarg = 1 ;
143    memset(&ijk_to_dicom, 0, sizeof(mat44));
144    memset(&xyzorient, 0, sizeof(THD_ivec3));
145    memset(&xyzorg, 0, sizeof(THD_fvec3));
146    memset(&xyzdel, 0, sizeof(THD_fvec3));
147    memset(&nxyz, 0, sizeof(THD_ivec3));
148    do{
149       flag_arg = va_arg( vararg_ptr , int ) ;   /** Get next arg  **/
150       if( flag_arg == ADN_none ) break ;        /** No more args! **/
151 #if 0
152 fprintf(stderr,"EDIT_dset_items: iarg=%d flag_arg=%d\n",iarg,flag_arg) ;
153 #endif
154       iarg++ ;
155 
156       switch( flag_arg ){
157 
158          default:{
159             int iv ;
160             char str[128] ;
161 
162             /** 30 Nov 1997: check for special cases **/
163 
164             iv = flag_arg - ADN_brick_label_one ;
165             if( iv >= 0 && iv < ADN_ONE_STEP ){
166                brick_label_one_iv  = iv ;
167                brick_label_one     = va_arg( vararg_ptr , char * ) ;
168                if( brick_label_one != NULL ) new_brick_label_one = 1 ;
169                break ; /* exit switch */
170             }
171 
172             iv = flag_arg - ADN_brick_fac_one ;
173             if( iv >= 0 && iv < ADN_ONE_STEP ){
174                brick_fac_one_iv  = iv ;
175                brick_fac_one     = va_arg( vararg_ptr , double ) ;
176                new_brick_fac_one = 1 ;
177                break ; /* exit switch */
178             }
179 
180             iv = flag_arg - ADN_brick_stataux_one ;
181             if( iv >= 0 && iv < ADN_ONE_STEP ){
182                brick_stataux_one_iv = iv ;
183                brick_stataux_one    = va_arg( vararg_ptr , float * ) ;
184                if( brick_stataux_one != NULL ) new_brick_stataux_one = 1 ;
185                break ; /* exit switch */
186             }
187 
188             iv = flag_arg - ADN_brick_keywords_replace_one ;
189             if( iv >= 0 && iv < ADN_ONE_STEP ){
190                brick_keywords_one_iv  = iv ;
191                brick_keywords_one     = va_arg( vararg_ptr , char * ) ;
192                new_brick_keywords_one = 1 ;
193                break ; /* exit switch */
194             }
195 
196             iv = flag_arg - ADN_brick_keywords_append_one ;
197             if( iv >= 0 && iv < ADN_ONE_STEP ){
198                brick_keywords_one_iv  = iv ;
199                brick_keywords_one     = va_arg( vararg_ptr , char * ) ;
200                new_brick_keywords_one = 2 ;
201                break ; /* exit switch */
202             }
203 
204             /** not a special case? error! **/
205 
206             sprintf(str,"illegal opcode = %d at arg #%d",flag_arg,iarg) ;
207             EDERR(str) ; if( errnum > 9 ) RETURN(errnum) ;
208             dummy = va_arg( vararg_ptr , void * ) ;  /* skip next arg */
209          }
210          break ;
211 
212          /** these two commands affect the disk file names **/
213 
214          case ADN_prefix:  /* processed later */
215             prefix = va_arg( vararg_ptr , char * ) ;
216             if( prefix != NULL ) {
217                new_prefix = 1 ;
218                new_smode = storage_mode_from_prefix(prefix);
219                if (dset->dblk && dset->dblk->diskptr) {
220                   /* if defined by prefix, apply, else if current is not a
221                      surface, clear (i.e. assume AFNI type) */
222                   if (new_smode != STORAGE_UNDEFINED)
223                      dset->dblk->diskptr->storage_mode = new_smode;
224                   else if ( ! is_surface_storage_mode(DSET_STORAGE_MODE(dset)) )
225                      dset->dblk->diskptr->storage_mode = STORAGE_BY_BRICK;
226                }
227             } else EDERR("illegal new prefix") ;
228          break ;
229 
230          case ADN_directory_name:  /* processed later */
231             directory_name = va_arg( vararg_ptr , char * ) ;
232             if( directory_name != NULL ) new_directory_name = 1 ;
233             else EDERR("illegal new directory_name") ;
234          break ;
235 
236          /** change the memory allocation type (mmap or malloc) **/
237 
238          case ADN_malloc_type:  /* processed now */
239             malloc_type = va_arg( vararg_ptr , int ) ;
240             if( ISVALID_MEM_CODE(malloc_type) ){
241                new_malloc_type = 1 ;
242                THD_force_malloc_type( dset->dblk , malloc_type ) ;
243             }
244             else EDERR("illegal new malloc_type") ;
245          break ;
246 
247          /** these commands affect the data in the bricks **/
248 
249          case ADN_brick_fac:  /* processed later */
250             brick_fac = va_arg( vararg_ptr , float * ) ;
251             new_brick_fac = 1 ;
252          break ;
253 
254          case ADN_datum_all:  /* processed later */
255             datum_all = va_arg( vararg_ptr , int ) ;
256             if( AFNI_GOOD_DTYPE(datum_all) ) new_datum_all = 1 ;
257             else EDERR("illegal new datum_all") ;
258          break ;
259 
260          case ADN_datum_array:  /* processed later */
261             datum_array = va_arg( vararg_ptr , int * ) ;
262             if( datum_array != NULL ) new_datum_array = 1 ;
263             else EDERR("illegal new datum_array") ;
264          break ;
265 
266          case ADN_nvals:  /* processed later */
267             nvals = va_arg( vararg_ptr , int ) ;
268             if( nvals > 0 ) new_nvals = 1 ;
269             else EDERR("illegal new nvals") ;
270          break ;
271 
272          /** these commands affect the spatial axes,
273              which may also influence size of the data bricks **/
274 
275          case ADN_ijk_to_dicom:  /* processed later [19 Dec 2005] */
276            ijk_to_dicom = va_arg( vararg_ptr , mat44 ) ;
277            if( ISVALID_MAT44(ijk_to_dicom) ) new_ijk_to_dicom = 1 ;
278            else EDERR("illegal new ijk_to_dicom") ;
279          break ;
280 
281          case ADN_nxyz:  /* processed later */
282            nxyz = va_arg( vararg_ptr , THD_ivec3 ) ;
283            if( nxyz.ijk[0] >= 1 && nxyz.ijk[1] >= 1 && nxyz.ijk[2] >= 1 )
284              new_nxyz = 1 ;
285            else
286              EDERR("illegal new nxyz") ;
287          break ;
288 
289          case ADN_xyzdel:  /* processed later */
290            xyzdel = va_arg( vararg_ptr , THD_fvec3 ) ;
291            if( xyzdel.xyz[0]!=0.0 && xyzdel.xyz[1]!=0.0 && xyzdel.xyz[2]!=0.0 )
292              new_xyzdel = 1 ;
293              else EDERR("illegal new xyzdel") ;
294          break ;
295 
296          case ADN_xyzorg:  /* processed later */
297            xyzorg = va_arg( vararg_ptr , THD_fvec3 ) ;
298            new_xyzorg = 1 ;
299          break ;
300 
301          case ADN_xyzorient:  /* processed later */
302             xyzorient = va_arg( vararg_ptr , THD_ivec3 ) ;
303             if( xyzorient.ijk[0] >= FIRST_ORIENT_TYPE &&
304                 xyzorient.ijk[0] <= LAST_ORIENT_TYPE  &&
305                 xyzorient.ijk[1] >= FIRST_ORIENT_TYPE &&
306                 xyzorient.ijk[1] <= LAST_ORIENT_TYPE  &&
307                 xyzorient.ijk[2] >= FIRST_ORIENT_TYPE &&
308                 xyzorient.ijk[2] <= LAST_ORIENT_TYPE  &&
309                   ORIENT_xyzint[xyzorient.ijk[0]]
310                 + ORIENT_xyzint[xyzorient.ijk[1]]
311                 + ORIENT_xyzint[xyzorient.ijk[2]] == 6  )
312 
313                new_xyzorient = 1 ;
314             else EDERR("illegal new xyzorient") ;
315          break ;
316 
317          case ADN_to_dicomm:   /* illegal at this time */
318             EDERR("to_dicomm not implemented") ;
319          break ;
320 
321          /** these commands affect the time axis of the dataset **/
322 
323          case ADN_ntt:  /* processed later */
324             ntt = va_arg( vararg_ptr , int ) ;
325             if( ntt >= 0 ) new_ntt = 1 ;
326             else EDERR("illegal new taxis ntt") ;
327          break ;
328 
329          case ADN_tunits:  /* processed later */
330             tunits = va_arg( vararg_ptr , int ) ;
331             if( tunits >= 0 ) new_tunits = 1 ;
332             else EDERR("illegal new taxis tunits") ;
333          break ;
334 
335          case ADN_nsl:  /* processed later */
336             nsl = va_arg( vararg_ptr , int ) ;
337             if( nsl >= 0 ) new_nsl = 1 ;
338             else EDERR("illegal new taxis nsl") ;
339          break ;
340 
341          case ADN_ttorg:  /* processed later */
342             ttorg = (float) va_arg( vararg_ptr , double ) ;
343             new_ttorg = 1 ;
344          break ;
345 
346          case ADN_ttdel:  /* processed later */
347             ttdel = (float) va_arg( vararg_ptr , double ) ;
348             new_ttdel = 1 ;
349          break ;
350 
351          case ADN_ttdur:  /* processed later */
352             ttdur = (float) va_arg( vararg_ptr , double ) ;
353             new_ttdur = 1 ;
354          break ;
355 
356          case ADN_zorg_sl:  /* processed later */
357             zorg_sl = (float) va_arg( vararg_ptr , double ) ;
358             new_zorg_sl = 1 ;
359          break ;
360 
361          case ADN_dz_sl:  /* processed later */
362             dz_sl = (float) va_arg( vararg_ptr , double ) ;
363             if( dz_sl != 0.0 ) new_dz_sl = 1 ;
364             else EDERR("illegal new taxis dz_sl") ;
365          break ;
366 
367          case ADN_toff_sl:  /* processed later */
368             toff_sl = va_arg( vararg_ptr , float * ) ;
369             new_toff_sl = 1 ;
370          break ;
371 
372          /** these commands affect the interpretation of the dataset
373              (e.g., is it functional or anatomical, which view type, ...) **/
374 
375          case ADN_type:  /* processed later */
376             type = va_arg( vararg_ptr , int ) ;
377             if( type >= FIRST_3DIM_TYPE && type <= LAST_3DIM_TYPE )
378                new_type = 1 ;
379             else EDERR("illegal new type") ;
380          break ;
381 
382          case ADN_view_type:  /* processed later */
383             view_type = va_arg( vararg_ptr , int ) ;
384             if( view_type >= FIRST_VIEW_TYPE && view_type <= LAST_VIEW_TYPE ) {
385                new_view_type = 1 ;
386                if (dset->dblk && dset->dblk->diskptr) { /* ZSS Feb 2012 */
387                   dset->dblk->diskptr->storage_mode = STORAGE_BY_BRICK;
388                }
389             } else EDERR("illegal new view_type") ;
390          break ;
391 
392          case ADN_func_type:  /* processed later */
393             func_type = va_arg( vararg_ptr , int ) ;
394             if( func_type >= 0 ) new_func_type = 1 ;
395             else EDERR("illegal new func_type") ;
396          break ;
397 
398          /** auxiliary statistical data, for interpretation of functions **/
399 
400          case ADN_stat_aux:  /* processed now */
401             stat_aux = va_arg( vararg_ptr , float * ) ;
402             if( stat_aux != NULL ){
403                new_stat_aux = 1 ;
404                for( ii=0 ; ii < MAX_STAT_AUX ; ii++ )
405                   dset->stat_aux[ii] = stat_aux[ii] ;
406             } else EDERR("illegal new stat_aux") ;
407          break ;
408 
409          /** dataset keywords **/
410 
411          case ADN_keywords_replace: /* processed now */
412             keywords = va_arg( vararg_ptr , char * ) ;
413             new_keywords = 1 ;
414             THD_store_dataset_keywords( dset , keywords ) ;
415          break ;
416 
417          case ADN_keywords_append: /* processed now */
418             keywords = va_arg( vararg_ptr , char * ) ;
419             new_keywords = 1 ;
420             THD_append_dataset_keywords( dset , keywords ) ;
421          break ;
422 
423          /** various labeling options **/
424 
425          case ADN_label1:  /* processed now */
426             label1 = va_arg( vararg_ptr , char * ) ;
427             if( label1 != NULL ){
428                MCW_strncpy( dset->label1 , label1 , THD_MAX_LABEL ) ;
429                new_label1 = 1 ;
430             }
431             else EDERR("illegal new label1") ;
432          break ;
433 
434          case ADN_label2:  /* processed now */
435             label2 = va_arg( vararg_ptr , char * ) ;
436             if( label2 != NULL ){
437                MCW_strncpy( dset->label2 , label2 , THD_MAX_LABEL ) ;
438                new_label2 = 1 ;
439             }
440             else EDERR("illegal new label2") ;
441          break ;
442 
443          case ADN_self_name:  /* processed now */
444             self_name = va_arg( vararg_ptr , char * ) ;
445             if( self_name != NULL ){
446                MCW_strncpy( dset->self_name , self_name , THD_MAX_NAME ) ;
447                new_self_name = 1 ;
448             }
449             else EDERR("illegal new self_name") ;
450          break ;
451 
452          /** relationships to other datasets **/
453 
454          case ADN_warp_parent:  /* processed now */
455             warp_parent = va_arg( vararg_ptr , THD_3dim_dataset * ) ;
456             if( ISVALID_3DIM_DATASET(warp_parent) ){
457                new_warp_parent = 1 ;
458                dset->warp_parent = warp_parent ;
459                MCW_strncpy(dset->warp_parent_name,warp_parent->self_name,THD_MAX_NAME) ;
460                dset->warp_parent_idcode = warp_parent->idcode ;
461             }
462             else EDERR("illegal new warp_parent") ;
463          break ;
464 
465          case ADN_warp:  /* processed now */
466             warp = va_arg( vararg_ptr , THD_warp * ) ;
467             if( ISVALID_WARP(warp) ){
468                new_warp = 1 ;
469                if( dset->warp == NULL ) dset->warp = myRwcNew(THD_warp) ;
470                *(dset->warp) =* warp ;
471             } else EDERR("illegal new warp") ;
472          break ;
473 
474          case ADN_anat_parent:  /* processed now */
475             anat_parent = va_arg( vararg_ptr , THD_3dim_dataset * ) ;
476             if( ISVALID_3DIM_DATASET(anat_parent) ){
477                new_anat_parent = 1 ;
478                dset->anat_parent = anat_parent ;
479                MCW_strncpy(dset->anat_parent_name,anat_parent->self_name,THD_MAX_NAME) ;
480                dset->anat_parent_idcode = anat_parent->idcode ;
481             }
482             else EDERR("illegal new anat_parent") ;
483          break ;
484 
485          case ADN_anatpar_idcode:{ /* processed now [13 Dec 1999] */
486             MCW_idcode * idc ;
487             idc = va_arg( vararg_ptr , MCW_idcode * ) ;
488             if( idc != NULL )
489                dset->anat_parent_idcode = *idc ;
490             else
491                EDERR("illegal new anatpar_idcode") ;
492          }
493          break ;
494 
495       }  /*- end of switch on flag_arg -*/
496 
497       iarg++ ;
498    } while( 1 ) ;  /* end of loop over arguments */
499    va_end( vararg_ptr ) ;
500    if( errnum > 0 ) RETURN(errnum) ;
501 
502    /**** carry out edits that were flagged above ****/
503 
504    /**---------- Need to reset the disk filename? ------------**/
505    /** 22 Nov 2002: remove +orig etc. from prefix, if present **/
506 
507    if( new_prefix || new_directory_name || new_view_type ){
508       char *nprefix = THD_deplus_prefix( prefix ) ;
509       int   smode ;
510 
511       THD_init_diskptr_names( dset->dblk->diskptr ,
512                               directory_name , NULL ,
513                               nprefix , view_type , True ) ;
514 
515       /* if the storage mode has been specified via the prefix, apply it */
516       /*                                             21 Aug 2008 [rickr] */
517       smode = storage_mode_from_filename(prefix);
518       if( smode != STORAGE_UNDEFINED )
519          dset->dblk->diskptr->storage_mode = smode;
520 
521       if( DSET_IS_1D(dset) || DSET_IS_3D(dset) ){         /* 21 Mar 2003 */
522         char *fname = dset->dblk->diskptr->brick_name ;
523         int  ll = strlen(fname) ;
524         STRING_DEVIEW_DEEXT_BRICK(fname);
525         if( DSET_IS_1D(dset) || (DSET_NY(dset)==1 && DSET_NZ(dset)==1) ) {
526           if( !STRING_HAS_SUFFIX(fname,".1D") &&
527               !STRING_HAS_SUFFIX(fname,".1D.dset")) strcat(fname,".1D");
528           fname = dset->dblk->diskptr->prefix ; /* also adjust prefix */
529           if( !STRING_HAS_SUFFIX(fname,".1D") &&
530               !STRING_HAS_SUFFIX(fname,".1D.dset")) strcat(fname,".1D");
531         } else {
532           strcat(fname,".3D");
533         }
534       }
535 
536       if( DSET_IS_NIML(dset) ){         /* 07 Jun 2006 [rickr] */
537         char *fname = dset->dblk->diskptr->brick_name ;
538         int  ll = strlen(fname) ;
539         STRING_DEVIEW_DEEXT_BRICK(fname);
540         if( !STRING_HAS_SUFFIX(fname,".niml") ) strcat(fname,".niml");
541         fname = dset->dblk->diskptr->prefix ; /* also adjust prefix */
542         if( !STRING_HAS_SUFFIX(fname,".niml") ) strcat(fname,".niml");
543       }
544 
545       if( DSET_IS_NI_SURF_DSET(dset) ){ /* 28 Jun 2006 [rickr] */
546         char *fname = dset->dblk->diskptr->brick_name ;
547         int  ll = strlen(fname) ;
548         STRING_DEVIEW_DEEXT_BRICK(fname);
549         fname = dset->dblk->diskptr->brick_name ;
550         if( !STRING_HAS_SUFFIX(fname,".niml.dset") ) strcat(fname,".niml.dset");
551         fname = dset->dblk->diskptr->prefix ; /* also adjust prefix */
552         if( !STRING_HAS_SUFFIX(fname,".niml.dset") ) strcat(fname,".niml.dset");
553       }
554 
555       if( DSET_IS_GIFTI(dset) ){ /* 13 Feb 2008 [rickr] */
556         char *fname = dset->dblk->diskptr->brick_name ;
557         int  ll = strlen(fname) ;
558         STRING_DEVIEW_DEEXT_BRICK(fname);
559         if( ! STRING_HAS_SUFFIX(fname,".gii") &&
560             ! STRING_HAS_SUFFIX(fname,".gii.dset") )
561            strcat(fname,".gii");
562         fname = dset->dblk->diskptr->prefix ; /* also adjust prefix */
563         if( ! STRING_HAS_SUFFIX(fname,".gii") &&
564             ! STRING_HAS_SUFFIX(fname,".gii.dset") )
565            strcat(fname,".gii");
566       }
567 
568       /** output of NIfTI-1.1 dataset: 06 May 2005 **/
569       /* if the prefix ends in .nii or .nii.gz, change filename in brick_name */
570       if( nprefix != NULL && ( STRING_HAS_SUFFIX(nprefix,".nii") ||
571                                STRING_HAS_SUFFIX(nprefix,".nii.gz") ) ){
572         char *fname = dset->dblk->diskptr->brick_name ;
573         int   gzpre = STRING_HAS_SUFFIX(nprefix,".nii.gz") ;
574         int   ll = strlen(fname) ; /* for DEVIEW macro */
575         STRING_DEVIEW_DEEXT_BRICK(fname) ;
576 
577         /* make sure brick_name suffix matches that of prefix      */
578         /* if gzpre, include .nii.gz, else include .nii            */
579         /* no automatic compression for NIFTI   1 Jun 2021 [rickr] */
580 
581         if ( gzpre && ! STRING_HAS_SUFFIX(fname,".nii.gz") )
582             strcat(fname,".nii.gz") ;
583         else if ( ! gzpre && ! STRING_HAS_SUFFIX(fname,".nii") )
584             strcat(fname,".nii");
585 
586         if (dset->dblk->diskptr->header_name) { /* ZSS: April 26 2012 */
587             /* header_name should be just like brick_name */
588             strcpy(dset->dblk->diskptr->header_name, fname);
589         }
590       }
591 
592       /** NIfTI-1.1 with .hdr suffix (2 file format) [08 May 2008] **/
593 
594       if( nprefix != NULL && STRING_HAS_SUFFIX(nprefix,".hdr") ){
595 
596         char *fname = dset->dblk->diskptr->brick_name ;
597         int  ll = strlen(fname) ;
598         STRING_DEVIEW_DEEXT_BRICK(fname);
599         if( !strcmp(fname+ll-14,".hdr") ) fname[ll-14] = '\0';
600         if (dset->dblk->diskptr->header_name) {/* and adjust header name
601                                                   ZSS April 26 2012 */
602             strcpy(dset->dblk->diskptr->header_name, fname);
603             strcat(dset->dblk->diskptr->header_name,".hdr") ;
604         }
605         if( !STRING_HAS_SUFFIX(fname,".img") ) strcat(fname,".img") ;
606 
607         /* and override the BRICK mode */
608         dset->dblk->diskptr->storage_mode = STORAGE_BY_NIFTI;
609       }
610 
611       if( nprefix != NULL ) free(nprefix) ;
612    }
613 
614    /**----------- Need to reconfigure the spatial axes? -----------**/
615    /**    Much of this code is from routine THD_3dim_from_block    **/
616 
617    redo_daxes = ( new_xyzorg || new_xyzdel || new_xyzorient ) ;
618 
619    redo_bricks = ( new_datum_all || new_datum_array ||
620                    new_nvals     || new_nxyz          ) ;
621 
622    if( new_nvals && nvals == 1 ){  /* 02 Dec 2009 */
623      new_ntt = 1 ; ntt = 0 ;
624    }
625 
626    /*----- ye newe waye for ye axes change [19 Dec 2005] -----*/
627 
628    /* check for conflicts */
629 
630    if( new_xyzorg && new_ijk_to_dicom )
631      EDERR("can't set ijk_to_dicom and xyzorg at same time");
632    if( new_xyzdel && new_ijk_to_dicom )
633      EDERR("can't set ijk_to_dicom and xyzdel at same time");
634    if( new_xyzorient && new_ijk_to_dicom )
635      EDERR("can't set ijk_to_dicom and xyzorient at same time");
636 
637    if( redo_bricks && THD_count_databricks(dset->dblk) > 0 )
638      EDERR("cannot reconfigure bricks that already are full") ;
639 
640    if( errnum > 0 ) RETURN(errnum) ;
641 
642    /* set new data grid size now */
643 
644    if( new_nxyz ){
645      THD_dataxes *daxes = dset->daxes ;
646      THD_diskptr *dkptr = dset->dblk->diskptr ;
647 
648      daxes->nxx  = dkptr->dimsizes[0] = nxyz.ijk[0] ;
649      daxes->nyy  = dkptr->dimsizes[1] = nxyz.ijk[1] ;
650      daxes->nzz  = dkptr->dimsizes[2] = nxyz.ijk[2] ;
651 
652      if( !redo_daxes && !new_ijk_to_dicom ){
653        THD_set_daxes_bbox(daxes) ;
654        THD_daxes_to_mat44(daxes) ;
655        dset->daxes->ijk_to_dicom_real = dset->daxes->ijk_to_dicom ;
656        THD_set_dicom_box (daxes) ;
657      }
658    }
659 
660    /* set the new matrix transform between index and space */
661 
662    if( new_ijk_to_dicom ){
663      THD_dataxes *daxes = dset->daxes ;
664 
665      daxes->ijk_to_dicom = ijk_to_dicom ;
666      daxes->dicom_to_ijk = nifti_mat44_inverse( ijk_to_dicom ) ;
667      THD_set_dicom_box( daxes ) ;
668      (void)THD_daxes_from_mat44( daxes ) ;  /* set the old stuff */
669    }
670 
671    /*------ ye olde waye for ye axes change -----*/
672 
673    if( redo_daxes ){
674      THD_dataxes *daxes = dset->daxes ;
675 #if 0
676 INFO_message("old geometry string = %s",EDIT_get_geometry_string(dset)) ;
677 #endif
678 
679      /** copy new stuff into the daxes structure **/
680 
681      if( new_xyzorg ){
682 #if 0
683 INFO_message("old daxes org = %g %g %g",daxes->xxorg,daxes->yyorg,daxes->zzorg) ;
684 #endif
685        daxes->xxorg = xyzorg.xyz[0] ;
686        daxes->yyorg = xyzorg.xyz[1] ;
687        daxes->zzorg = xyzorg.xyz[2] ;
688 #if 0
689 INFO_message("new daxes org = %g %g %g",daxes->xxorg,daxes->yyorg,daxes->zzorg) ;
690 #endif
691      }
692 
693      if( new_xyzdel ){
694 #if 0
695 INFO_message("old daxes del = %g %g %g",daxes->xxdel,daxes->yydel,daxes->zzdel) ;
696 #endif
697        daxes->xxdel = xyzdel.xyz[0] ;
698        daxes->yydel = xyzdel.xyz[1] ;
699        daxes->zzdel = xyzdel.xyz[2] ;
700 #if 0
701 INFO_message("new daxes del = %g %g %g",daxes->xxdel,daxes->yydel,daxes->zzdel) ;
702 #endif
703      }
704 
705      if( new_xyzorient ){
706 #if 0
707 INFO_message("old daxes orient = %d %d %d",daxes->xxorient,daxes->yyorient,daxes->zzorient) ;
708 #endif
709        daxes->xxorient = xyzorient.ijk[0] ;
710        daxes->yyorient = xyzorient.ijk[1] ;
711        daxes->zzorient = xyzorient.ijk[2] ;
712 #if 0
713 INFO_message("new daxes orient = %d %d %d",daxes->xxorient,daxes->yyorient,daxes->zzorient) ;
714 #endif
715      }
716 
717      /*-- set bounding box and to_dicomm matrix for this dataset --*/
718 
719      THD_set_daxes_bbox     ( daxes ) ; /* 20 Dec 2005 */
720      THD_daxes_to_mat44     ( daxes ) ; /* 19 Dec 2005 */
721      dset->daxes->ijk_to_dicom_real = dset->daxes->ijk_to_dicom ;
722      THD_set_dicom_box      ( daxes ) ;
723      THD_set_daxes_to_dicomm( daxes ) ; /* 20 Dec 2005 */
724 
725 #if 0
726 INFO_message("new geometry string = %s",EDIT_get_geometry_string(dset)) ;
727 #endif
728    }
729 
730    /**---------- Need to reconfigure the sub-bricks? ----------**/
731 
732    if( new_datum_all && new_datum_array ){
733      EDERR("datum_all and datum_array can't be used together") ;
734      RETURN(errnum) ;
735    }
736 
737    if( redo_bricks ){
738       int old_nvals = dset->dblk->nvals ;
739 #if 0
740 fprintf(stderr,"EDIT_dset_items: about to redo_bricks\n") ;
741 #endif
742       if( ! new_nvals ) nvals = old_nvals ;
743 
744       /** make an array of data types, if one not provided **/
745 
746       if( ! new_datum_array ){
747          datum_array = (int *) RwcMalloc( sizeof(int) * nvals ) ;
748 
749 #if 0
750 fprintf(stderr,"EDIT_dset_items: about to make datum_array\n") ;
751 #endif
752          for( ii=0 ; ii < nvals ; ii++ )
753             datum_array[ii] =  (new_datum_all)  ? datum_all
754                              : (ii < old_nvals) ? DSET_BRICK_TYPE(dset,ii)
755                                                 : DSET_BRICK_TYPE(dset,0) ;
756       }                                           /* 06 Apr 2005 [rickr] */
757 
758       if( new_nvals ){
759          if( dset->dblk->nvals != nvals )
760             THD_copy_datablock_auxdata( NULL , dset->dblk ) ; /* 30 Nov 1997 */
761 
762          myRwcFree( dset->dblk->brick_bytes ) ;
763          myRwcFree( dset->dblk->brick_fac   ) ;
764 
765          dset->dblk->nvals = dset->dblk->diskptr->nvals = nvals ;
766       }
767 
768       THD_init_datablock_brick( dset->dblk , nvals , datum_array ) ;
769 
770       if( ! new_datum_array ) myRwcFree(datum_array) ;
771    }
772 
773    /**---------- Need to add new brick_fac values? ----------**/
774 
775    if( new_brick_fac ){
776       if( brick_fac != NULL ){
777          for( ii=0 ; ii < dset->dblk->nvals ; ii++ )
778             dset->dblk->brick_fac[ii] = brick_fac[ii] ;
779       } else {
780          for( ii=0 ; ii < dset->dblk->nvals ; ii++ )
781             dset->dblk->brick_fac[ii] = 0.0 ;
782       }
783    }
784 
785    /** 30 Nov 1997: do just one brick_fac value **/
786 
787    if( new_brick_fac_one ){
788       if( brick_fac_one_iv < 0 || brick_fac_one_iv >= dset->dblk->nvals ){
789          EDERR_int("illegal index for ADN_brick_fac_one",brick_fac_one_iv) ;
790          RETURN(errnum) ;
791       }
792       dset->dblk->brick_fac[ brick_fac_one_iv ] = brick_fac_one ;
793    }
794 
795    /**--------- 30 Nov 1997: add a single brick label value --------**/
796 
797    if( new_brick_label_one ){
798       if( brick_label_one_iv < 0 || brick_label_one_iv >= dset->dblk->nvals ){
799          EDERR_int("illegal index for ADN_brick_label_one",brick_label_one_iv) ;
800          RETURN(errnum) ;
801       }
802 
803       THD_store_datablock_label( dset->dblk, brick_label_one_iv, brick_label_one ) ;
804    }
805 
806    /*---- add a single brick keywords value ----*/
807 
808    if( new_brick_keywords_one ){
809       if( brick_keywords_one_iv < 0 || brick_keywords_one_iv >= dset->dblk->nvals ){
810          EDERR_int("illegal index for ADN_brick_keywords_one",brick_keywords_one_iv) ;
811          RETURN(errnum) ;
812       }
813 
814       if( new_brick_keywords_one == 1 )
815          THD_store_datablock_keywords( dset->dblk, brick_keywords_one_iv,
816                                                    brick_keywords_one    );
817       else if( new_brick_keywords_one == 2 )
818          THD_append_datablock_keywords( dset->dblk, brick_keywords_one_iv,
819                                                     brick_keywords_one    );
820    }
821 
822    /*---- Add a single brick stataux value.
823           The input is a float array formatted like so:
824             <statcode> <npar> <value> ... <value>
825           where <statcode> is a FUNC_*_TYPE code
826                 <npar>     is the number of values to follow (may be 0);
827                              normally is FUNC_need_stat_aux[<statcode>]
828                 <value>    is an auxiliary statistical parameter needed
829                              for data of type <statcode>                ----*/
830 
831    if( new_brick_stataux_one ){
832       int jv , npar , kv , iv ;
833 
834       iv = brick_stataux_one_iv ;
835 
836 #if 0
837 fprintf(stderr,"stataux_one:  iv=%d bso[0]=%g bso[1]=%g bso[2]=%g\n",
838         iv, brick_stataux_one[0],  brick_stataux_one[1], brick_stataux_one[2] ) ;
839 #endif
840 
841       if( iv < 0 || iv >= dset->dblk->nvals ){
842          EDERR("illegal index for ADN_brick_stataux_one") ;
843          RETURN(errnum) ;
844       }
845 
846       jv = brick_stataux_one[0] ;  /* statcode */
847 
848       npar = brick_stataux_one[1] ;  /* # of values present */
849       if( npar < 0 ){
850          EDERR("illegal npar for ADN_brick_stataux_one") ;
851          RETURN(errnum) ;
852       }
853 
854       kv = FUNC_need_stat_aux[jv] ;  /* # of values needed */
855       if( npar > kv ) npar = kv ;
856 
857       THD_store_datablock_stataux( dset->dblk ,
858                                    iv , jv , npar , brick_stataux_one + 2 ) ;
859    }
860 
861    /**---------- Need to reconfigure the time axis? ----------**/
862 
863    redo_taxis = ( new_ntt   || new_nsl     || new_ttorg || new_ttdel ||
864                   new_ttdur || new_zorg_sl || new_dz_sl || new_toff_sl ) ;
865 
866    if( ! new_ntt ) ntt = ISVALID_TIMEAXIS(dset->taxis) ? dset->taxis->ntt : 0 ;
867 
868    if( ntt == 0 && dset->taxis != NULL ){
869       myRwcFree( dset->taxis->toff_sl ) ;
870       myRwcFree( dset->taxis ) ;
871       dset->taxis = NULL ;
872    }
873 
874    redo_taxis = ( redo_taxis && ntt > 0 ) ;
875 
876    if( (new_nsl && nsl > 0) && !new_toff_sl ){    /* if we have new slice count */
877       EDERR("have new_nsl but not new_toff_sl") ; /* but no new slice offsets */
878       RETURN(errnum) ;
879    }
880 
881    if( redo_taxis ){
882       THD_timeaxis *taxis = dset->taxis ;
883 
884       if( taxis == NULL ){
885          taxis          = dset->taxis     = myRwcNew( THD_timeaxis ) ;
886          taxis->type    = TIMEAXIS_TYPE ;
887          taxis->toff_sl = NULL ;
888          taxis->nsl     = 0 ;
889          taxis->ttorg   = taxis->ttdel = taxis->ttdur = 0.0 ;
890          taxis->ntt     = ntt ;
891       }
892 
893       if( new_ntt     ) taxis->ntt     = ntt ;
894       if( new_ttorg   ) taxis->ttorg   = ttorg ;
895       if( new_ttdel   ) taxis->ttdel   = ttdel ;
896       if( new_ttdur   ) taxis->ttdur   = ttdur ;
897       if( new_zorg_sl ) taxis->zorg_sl = zorg_sl ;
898       if( new_dz_sl   ) taxis->dz_sl   = dz_sl ;
899 
900       if( new_nsl ){
901          taxis->nsl = nsl ;
902          if( nsl > 0 )
903             taxis->toff_sl = (float *) RwcRealloc( (char *) taxis->toff_sl ,
904                                                   sizeof(float) * nsl      ) ;
905          else
906             myRwcFree(taxis->toff_sl) ;
907       }
908 
909       if( new_toff_sl )
910          for( ii=0 ; ii < taxis->nsl ; ii++ ) taxis->toff_sl[ii] = toff_sl[ii] ;
911    }
912 
913    if( new_tunits ){
914       THD_timeaxis * taxis = dset->taxis ;
915 
916       if( taxis == NULL) {
917          if (DSET_NVALS(dset) > 1) {
918             EDERR("have new_tunits but have no time axis") ;
919             RETURN(errnum) ;
920          }
921       } else {
922          taxis->units_type = tunits ;
923       }
924    }
925 
926    /**--------------- Need to redo dataset type codes? ------------**/
927    /**  Note that changing the type codes by themselves won't fix  **/
928    /**  nvals or other such stuff -- that must be done separately. **/
929 
930    if( new_type      ) dset->type      = type ;
931    if( new_view_type ) dset->view_type = view_type ;
932 
933    if( new_func_type ){
934       if( (ISANAT(dset) && func_type <= LAST_ANAT_TYPE) ||
935           (ISFUNC(dset) && func_type <= LAST_FUNC_TYPE)   ){
936 
937          dset->func_type = func_type ;
938 
939       } else{
940          EDERR("illegal new_func type combination") ; RETURN(errnum) ;
941       }
942    }
943 
944    /****--------------- hopefully, we are done! ---------------****/
945 
946    RETURN(errnum) ;
947 }
948 
949 /*!
950    Scale dataset's dxyz, same as 3drefit's -xyzscale
951 */
THD_volDXYZscale(THD_dataxes * daxes,float xyzscale,int reuse_shift)952 int THD_volDXYZscale( THD_dataxes  * daxes, float xyzscale, int reuse_shift)
953 {
954    static char FuncName[]={"THD_volDXYZscale"};
955    float dxp, dyp, dzp;
956    int   rl, ap , is;
957    float xop , yop , zop ;
958    static float shift[3] ;
959 
960    ENTRY("THD_volDXYZscale");
961 
962    if (!daxes) RETURN(0);
963 
964    if( xyzscale > 0.0f ){  /* 18 Jul 2006 */
965      dxp = daxes->xxdel * xyzscale ;  /* new grid */
966      dyp = daxes->yydel * xyzscale ;  /* spacings */
967      dzp = daxes->zzdel * xyzscale ;
968      rl  = abs(THD_get_axis_direction(daxes,ORI_R2L_TYPE)) ;
969      ap  = abs(THD_get_axis_direction(daxes,ORI_A2P_TYPE)) ;
970      is  = abs(THD_get_axis_direction(daxes,ORI_I2S_TYPE)) ;
971 
972      if( rl == 0 || ap == 0 || is == 0 )
973        ERROR_exit("-xyzscale: Indeterminate axis directions!") ;
974 
975      if( !reuse_shift ){  /* to calculate shift */
976        float op[3] , oo[3] ;
977        op[0] = xop = daxes->xxorg +
978                      (daxes->xxdel-dxp)*0.5f*(daxes->nxx-1) ;
979        op[1] = yop = daxes->yyorg +
980                      (daxes->yydel-dyp)*0.5f*(daxes->nyy-1) ;
981        op[2] = zop = daxes->zzorg +
982                      (daxes->zzdel-dzp)*0.5f*(daxes->nzz-1) ;
983        oo[0] = daxes->xxorg ;
984        oo[1] = daxes->yyorg ;
985        oo[2] = daxes->zzorg ;
986        shift[0] = op[rl-1] - xyzscale * oo[rl-1] ;   /* RL shift */
987        shift[1] = op[ap-1] - xyzscale * oo[ap-1] ;   /* AP shift */
988        shift[2] = op[is-1] - xyzscale * oo[is-1] ;   /* IS shift */
989 
990      } else {           /* to apply pre calculated shift */
991 
992        xop = xyzscale * daxes->xxorg + shift[daxes->xxorient/2] ;
993        yop = xyzscale * daxes->yyorg + shift[daxes->yyorient/2] ;
994        zop = xyzscale * daxes->zzorg + shift[daxes->zzorient/2] ;
995      }
996 
997      daxes->xxdel = dxp ; daxes->yydel = dyp ; daxes->zzdel = dzp ;
998      daxes->xxorg = xop ; daxes->yyorg = yop ; daxes->zzorg = zop ;
999    }
1000    RETURN(1);
1001 }
1002 
1003 /*-------------------------------------------------------------------*/
1004 #undef DPOLD  /* 22 Sep 2014 == Bilbo's birthday */
1005 
1006 /*-------------------------------------------------------------------*/
1007 /*! Remove any +???? suffix from a prefix, returning a new one.
1008     -- 22 Nov 2002 - RWCox
1009 ---------------------------------------------------------------------*/
1010 
THD_deplus_prefix(char * prefix)1011 char * THD_deplus_prefix( char *prefix )
1012 {
1013 #ifdef DPOLD
1014    static char *plussers[] = {
1015       "+orig", "+orig.", "+orig.HEAD", "+orig.BRIK", "+orig.BRIK.gz",
1016       "+acpc", "+acpc.", "+acpc.HEAD", "+acpc.BRIK", "+acpc.BRIK.gz",
1017       "+tlrc", "+tlrc.", "+tlrc.HEAD", "+tlrc.BRIK", "+tlrc.BRIK.gz"
1018       };
1019 #else
1020    static char *plussers[] = { "+orig" , "+acpc" , "+tlrc" } ;
1021 #endif
1022    char *newprefix , *cpt ;
1023    int nn, N_nn;
1024 
1025    if( prefix == NULL ) return NULL ;
1026 
1027    newprefix = strdup(prefix);
1028 
1029    N_nn = sizeof(plussers)/sizeof(char *);
1030    for (nn=0; nn<N_nn; ++nn) {
1031 #ifdef DPOLD
1032       if( STRING_HAS_SUFFIX(newprefix, plussers[nn]) ) {
1033          newprefix[strlen(newprefix)-strlen(plussers[nn])] = '\0';
1034          return newprefix ;
1035       }
1036 #else
1037       cpt = strstr(newprefix,plussers[nn]) ;
1038       if( cpt != NULL ) *cpt = '\0' ;
1039 #endif
1040    }
1041 
1042    return newprefix ;
1043 }
1044