/***************************************************************************** Major portions of this software are copyrighted by the Medical College of Wisconsin, 1994-2000, and are released under the Gnu General Public License, Version 2. See the file README.Copyright for details. ******************************************************************************/ #include "mrilib.h" /***** This program makes a "duplicate" of a dataset, which is nothing more than something that is warped from the parent with the identity warp. Why is this useful? Because you can then overwrite this warped-on-demand dataset in AFNI. RWCox, June 1995 *****/ static char DUP_session[THD_MAX_NAME] = "./" ; static char DUP_prefix[THD_MAX_PREFIX] = "dup" ; static char DUP_label[THD_MAX_LABEL] = "\0" ; static char DUP_dname[THD_MAX_NAME] = "\0" ; static int anatomy_type = ILLEGAL_TYPE ; static int function_type = ILLEGAL_TYPE ; static int dataset_type = ILLEGAL_TYPE ; THD_3dim_dataset * duplicate_dataset( THD_3dim_dataset * parent ) ; int main( int argc , char * argv[] ) { int nopt , ii ; THD_3dim_dataset * dset_in , * dset_out ; /** check for help **/ if( argc < 2 || strncmp(argv[1],"-help",3) == 0 ){ printf( "Usage: dsetdup [options] dataset\n" " 'Duplicates' a dataset by making a warp-on-demand copy.\n" " Applications:\n" " - allows AFNI to resample a dataset to a new grid without\n" " destroying an existing data .BRIK\n" " - change a functional dataset to anatomical, or vice-versa\n" "\n" "OPTIONS:\n" " -type = convert to the given 'type', which must be\n" " chosen from the same list as in to3d\n" " -session dirname = write output into given directory (default=./)\n" " -prefix pname = use 'pname' for the output directory prefix\n" " (default=dup)\n" " -label string = use 'string' for the label in the output\n" " dataset (default = pname)\n" " -dname name = will make 3D dataset's name = 'name'\n" "\n" "N.B.: Even if the new dataset is anatomical, it will not contain\n" " any markers, duplicated from the original, or otherwise.\n" ) ; exit(0) ; } /** scan command line options **/ #define DUPERR(str) \ do{ fprintf(stderr,"ERROR: %s\n",(str)) ; exit(1) ; } while(1) nopt = 1 ; while( nopt < argc && argv[nopt][0] == '-' ){ /*** the following code is borrowed from to3d ***/ /* -type from the anatomy prefixes */ for( ii=FIRST_ANAT_TYPE ; ii <= LAST_ANAT_TYPE ; ii++ ) if( strncmp( &(argv[nopt][1]) , ANAT_prefixstr[ii] , THD_MAX_PREFIX ) == 0 ) break ; if( ii <= LAST_ANAT_TYPE ){ anatomy_type = ii ; dataset_type = HEAD_ANAT_TYPE ; nopt++ ; continue ; } /* -type from the function prefixes */ for( ii=FIRST_FUNC_TYPE ; ii <= LAST_FUNC_TYPE ; ii++ ) if( strncmp( &(argv[nopt][1]) , FUNC_prefixstr[ii] , THD_MAX_PREFIX ) == 0 ) break ; if( ii <= LAST_FUNC_TYPE ){ function_type = ii ; dataset_type = HEAD_FUNC_TYPE ; nopt++ ; continue ; } /**** -session dirname ****/ if( strncmp(argv[nopt],"-session",6) == 0 ){ nopt++ ; if( nopt >= argc ) DUPERR("need argument after -session!") ; MCW_strncpy( DUP_session , argv[nopt++] , THD_MAX_NAME ) ; continue ; } /**** -prefix prefix ****/ if( strncmp(argv[nopt],"-prefix",6) == 0 ){ nopt++ ; if( nopt >= argc ) DUPERR("need argument after -prefix!") ; MCW_strncpy( DUP_prefix , argv[nopt++] , THD_MAX_PREFIX ) ; continue ; } /**** -label string ****/ if( strncmp(argv[nopt],"-label",6) == 0 ){ nopt++ ; if( nopt >= argc ) DUPERR("need argument after -label!") ; MCW_strncpy( DUP_label , argv[nopt++] , THD_MAX_LABEL ) ; continue ; } /**** -dname string ****/ if( strncmp(argv[nopt],"-dname",6) == 0 ){ nopt++ ; if( nopt >= argc ) DUPERR("need argument after -dname!") ; MCW_strncpy( DUP_dname , argv[nopt++] , THD_MAX_NAME ) ; continue ; } /**** unknown switch ****/ fprintf(stderr,"*** unrecognized option %s\n",argv[nopt]) ; exit(1) ; } /* end of loop over options */ if( strlen(DUP_label) == 0 ){ MCW_strncpy(DUP_label,DUP_prefix,THD_MAX_LABEL) ; } if( nopt >= argc ) DUPERR("no dataset name given!") ; /*** read input dataset ***/ dset_in = THD_open_one_dataset( argv[nopt] ) ; if( ! ISVALID_3DIM_DATASET(dset_in) ) DUPERR("cannot read dataset!\n") ; /*** copy header info ***/ dset_out = duplicate_dataset( dset_in ) ; if( ! ISVALID_3DIM_DATASET(dset_out) ) DUPERR("cannot make duplicate!\n") ; /*** rewrite some strings ***/ strcpy( dset_out->label1 , DUP_label ) ; if( strlen(DUP_dname) > 0 ) strcpy( dset_out->self_name , DUP_dname ) ; /*** change of type? ***/ if( dataset_type >= FIRST_3DIM_TYPE && dataset_type <= LAST_3DIM_TYPE ){ int isfunc , new_nvals ; isfunc = ISFUNCTYPE(dataset_type) ; new_nvals = (isfunc) ? FUNC_nvals[function_type] : ANAT_nvals[anatomy_type] ; if( new_nvals > dset_in->dblk->nvals ){ fprintf(stderr, "ERROR: new dataset type has %d values per voxel, but old has %d!\n" " ==> cannot make duplicate!\n" , new_nvals , dset_in->dblk->nvals ) ; exit(1) ; } else if( new_nvals < dset_in->dblk->nvals ){ fprintf(stderr, "WARNING: new dataset type has %d values per voxel, but old has %d!\n" " ==> new dataset will not access all data in old!\n", new_nvals , dset_in->dblk->nvals ) ; } dset_out->type = dataset_type ; dset_out->func_type = ISANAT(dset_out) ? (anatomy_type) : (function_type) ; } /*** done! ***/ THD_write_3dim_dataset( DUP_session , DUP_prefix , dset_out , False ) ; exit(0) ; } /*--------------------------------------------------------------------- Adapted from AFNI_follower_dataset: Make a warped dataset whose grid corresponds to the parent and whose warp is just the identity warp. -----------------------------------------------------------------------*/ THD_3dim_dataset * duplicate_dataset( THD_3dim_dataset * parent ) { THD_3dim_dataset * new_dset ; int ii ; /* sanity checks */ if( ! ISVALID_3DIM_DATASET(parent) ) return NULL ; /* make new dataset, copying appropriate fields from its various parents */ new_dset = myXtNew( THD_3dim_dataset ) ; INIT_KILL( new_dset->kl ) ; new_dset->type = parent->type ; new_dset->func_type = parent->func_type ; new_dset->view_type = parent->view_type ; new_dset->anat_parent = NULL ; /* no anat parent */ new_dset->anat_parent_name[0] = '\0' ; new_dset->warp_parent = parent ; /* yes warp parent */ MCW_strncpy( new_dset->warp_parent_name , parent->self_name , THD_MAX_NAME ) ; /* make the actual warp from the warp_parent to this dataset */ new_dset->vox_warp = myXtNew( THD_warp ) ; new_dset->vox_warp->type = ILLEGAL_TYPE ; /* created when needed */ new_dset->warp = myXtNew( THD_warp ) ; *(new_dset->warp) = IDENTITY_WARP ; /* make up some names for this new dataset */ MCW_strncpy( new_dset->self_name , parent->self_name , THD_MAX_NAME-5 ) ; ii = strlen( new_dset->self_name ) ; MCW_strncpy( &(new_dset->self_name[ii]) , "%duplicate" , THD_MAX_NAME-ii ) ; MCW_strncpy( new_dset->label1 , parent->label1 , THD_MAX_LABEL ) ; MCW_strncpy( new_dset->label2 , parent->label2 , THD_MAX_LABEL ) ; /* set the axes for this new dataset (same as parent, since that's the meaning of this routine) */ new_dset->daxes = myXtNew( THD_dataxes ) ; /* copy data axes of */ *(new_dset->daxes) = *(parent->daxes) ; /* parent */ new_dset->daxes->parent = (XtPointer) new_dset ; /* reset parent */ new_dset->wod_daxes = myXtNew( THD_dataxes ) ; /* warp-on-demand */ *(new_dset->wod_daxes) = *(new_dset->daxes) ; new_dset->wod_flag = True ; /* create a datablock and diskptr, in case the data is ever filled into memory (instead of wod) and written to disk */ new_dset->dblk = myXtNew( THD_datablock ) ; INIT_KILL( new_dset->dblk->kl ) ; new_dset->dblk->type = DATABLOCK_TYPE ; new_dset->dblk->nvals = parent->dblk->nvals ; new_dset->dblk->brick = NULL ; new_dset->dblk->malloc_type = DATABLOCK_MEM_UNDEFINED ; new_dset->dblk->total_bytes = 0 ; new_dset->dblk->brick_bytes = 0 ; new_dset->dblk->natr = new_dset->dblk->natr_alloc = 0 ; new_dset->dblk->atr = NULL ; new_dset->dblk->parent = (XtPointer) new_dset ; DBLK_unlock(new_dset->dblk) ; new_dset->dblk->diskptr = myXtNew( THD_diskptr ) ; new_dset->dblk->diskptr->type = DISKPTR_TYPE ; new_dset->dblk->diskptr->nvals = parent->dblk->nvals ; new_dset->dblk->diskptr->rank = 3 ; new_dset->dblk->diskptr->storage_mode = STORAGE_UNDEFINED ; new_dset->dblk->diskptr->byte_order = THD_get_write_order() ; /* 25 April 1998 */ new_dset->dblk->diskptr->dimsizes[0] = new_dset->daxes->nxx ; new_dset->dblk->diskptr->dimsizes[1] = new_dset->daxes->nyy ; new_dset->dblk->diskptr->dimsizes[2] = new_dset->daxes->nzz ; /* create the names for storage on disk (if ever) -- note we put it in the same directory as the parent */ THD_init_diskptr_names( new_dset->dblk->diskptr , parent->dblk->diskptr->directory_name , NULL , parent->dblk->diskptr->prefix , new_dset->view_type , True ) ; ADDTO_KILL( new_dset->dblk->kl , new_dset->dblk->diskptr ) ; /* oh yeah, set the new_dset kill list, copy statistics if available, and NULL out any unused stuff */ ADDTO_KILL( new_dset->kl , new_dset->warp ) ; ADDTO_KILL( new_dset->kl , new_dset->vox_warp ) ; ADDTO_KILL( new_dset->kl , new_dset->daxes ) ; ADDTO_KILL( new_dset->kl , new_dset->wod_daxes ) ; ADDTO_KILL( new_dset->kl , new_dset->dblk ) ; new_dset->self_warp = NULL ; /* 26 Aug 2002 */ if( parent->stats != NULL ){ new_dset->stats = myXtNew( THD_statistics ) ; /* copy statistics */ *(new_dset->stats) = *(parent->stats) ; /* of parent */ new_dset->stats->parent = (XtPointer) new_dset ; ADDTO_KILL( new_dset->kl , new_dset->stats ) ; } else { new_dset->stats = NULL ; } new_dset->markers = NULL ; /* no markers */ new_dset->death_mark = 0 ; /* don't kill me! */ new_dset->tcat_list = 0 ; new_dset->tcat_num = 0 ; new_dset->tcat_len = NULL ; return(new_dset) ; }