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 /***** This program makes a "duplicate" of a dataset, which is
10 nothing more than something that is warped from the parent
11 with the identity warp.
12
13 Why is this useful? Because you can then overwrite this
14 warped-on-demand dataset in AFNI.
15
16 RWCox, June 1995
17 *****/
18
19 static char DUP_session[THD_MAX_NAME] = "./" ;
20 static char DUP_prefix[THD_MAX_PREFIX] = "dup" ;
21 static char DUP_label[THD_MAX_LABEL] = "\0" ;
22 static char DUP_dname[THD_MAX_NAME] = "\0" ;
23
24 static int anatomy_type = ILLEGAL_TYPE ;
25 static int function_type = ILLEGAL_TYPE ;
26 static int dataset_type = ILLEGAL_TYPE ;
27
28 THD_3dim_dataset * duplicate_dataset( THD_3dim_dataset * parent ) ;
29
main(int argc,char * argv[])30 int main( int argc , char * argv[] )
31 {
32 int nopt , ii ;
33 THD_3dim_dataset * dset_in , * dset_out ;
34
35 /** check for help **/
36
37 if( argc < 2 || strncmp(argv[1],"-help",3) == 0 ){
38 printf(
39 "Usage: dsetdup [options] dataset\n"
40 " 'Duplicates' a dataset by making a warp-on-demand copy.\n"
41 " Applications:\n"
42 " - allows AFNI to resample a dataset to a new grid without\n"
43 " destroying an existing data .BRIK\n"
44 " - change a functional dataset to anatomical, or vice-versa\n"
45 "\n"
46 "OPTIONS:\n"
47 " -type = convert to the given 'type', which must be\n"
48 " chosen from the same list as in to3d\n"
49 " -session dirname = write output into given directory (default=./)\n"
50 " -prefix pname = use 'pname' for the output directory prefix\n"
51 " (default=dup)\n"
52 " -label string = use 'string' for the label in the output\n"
53 " dataset (default = pname)\n"
54 " -dname name = will make 3D dataset's name = 'name'\n"
55 "\n"
56 "N.B.: Even if the new dataset is anatomical, it will not contain\n"
57 " any markers, duplicated from the original, or otherwise.\n"
58 ) ;
59 exit(0) ;
60 }
61
62 /** scan command line options **/
63
64 #define DUPERR(str) \
65 do{ fprintf(stderr,"ERROR: %s\n",(str)) ; exit(1) ; } while(1)
66
67 nopt = 1 ;
68 while( nopt < argc && argv[nopt][0] == '-' ){
69
70 /*** the following code is borrowed from to3d ***/
71
72 /* -type from the anatomy prefixes */
73
74 for( ii=FIRST_ANAT_TYPE ; ii <= LAST_ANAT_TYPE ; ii++ )
75 if( strncmp( &(argv[nopt][1]) ,
76 ANAT_prefixstr[ii] , THD_MAX_PREFIX ) == 0 ) break ;
77
78 if( ii <= LAST_ANAT_TYPE ){
79 anatomy_type = ii ;
80 dataset_type = HEAD_ANAT_TYPE ;
81 nopt++ ; continue ;
82 }
83
84 /* -type from the function prefixes */
85
86 for( ii=FIRST_FUNC_TYPE ; ii <= LAST_FUNC_TYPE ; ii++ )
87 if( strncmp( &(argv[nopt][1]) ,
88 FUNC_prefixstr[ii] , THD_MAX_PREFIX ) == 0 ) break ;
89
90 if( ii <= LAST_FUNC_TYPE ){
91 function_type = ii ;
92 dataset_type = HEAD_FUNC_TYPE ;
93 nopt++ ; continue ;
94 }
95
96 /**** -session dirname ****/
97
98 if( strncmp(argv[nopt],"-session",6) == 0 ){
99 nopt++ ;
100 if( nopt >= argc ) DUPERR("need argument after -session!") ;
101 MCW_strncpy( DUP_session , argv[nopt++] , THD_MAX_NAME ) ;
102 continue ;
103 }
104
105 /**** -prefix prefix ****/
106
107 if( strncmp(argv[nopt],"-prefix",6) == 0 ){
108 nopt++ ;
109 if( nopt >= argc ) DUPERR("need argument after -prefix!") ;
110 MCW_strncpy( DUP_prefix , argv[nopt++] , THD_MAX_PREFIX ) ;
111 continue ;
112 }
113
114 /**** -label string ****/
115
116 if( strncmp(argv[nopt],"-label",6) == 0 ){
117 nopt++ ;
118 if( nopt >= argc ) DUPERR("need argument after -label!") ;
119 MCW_strncpy( DUP_label , argv[nopt++] , THD_MAX_LABEL ) ;
120 continue ;
121 }
122
123 /**** -dname string ****/
124
125 if( strncmp(argv[nopt],"-dname",6) == 0 ){
126 nopt++ ;
127 if( nopt >= argc ) DUPERR("need argument after -dname!") ;
128 MCW_strncpy( DUP_dname , argv[nopt++] , THD_MAX_NAME ) ;
129 continue ;
130 }
131
132 /**** unknown switch ****/
133
134 fprintf(stderr,"*** unrecognized option %s\n",argv[nopt]) ;
135 exit(1) ;
136 } /* end of loop over options */
137
138 if( strlen(DUP_label) == 0 ){
139 MCW_strncpy(DUP_label,DUP_prefix,THD_MAX_LABEL) ;
140 }
141
142 if( nopt >= argc ) DUPERR("no dataset name given!") ;
143
144 /*** read input dataset ***/
145
146 dset_in = THD_open_one_dataset( argv[nopt] ) ;
147 if( ! ISVALID_3DIM_DATASET(dset_in) ) DUPERR("cannot read dataset!\n") ;
148
149 /*** copy header info ***/
150
151 dset_out = duplicate_dataset( dset_in ) ;
152 if( ! ISVALID_3DIM_DATASET(dset_out) ) DUPERR("cannot make duplicate!\n") ;
153
154 /*** rewrite some strings ***/
155
156 strcpy( dset_out->label1 , DUP_label ) ;
157 if( strlen(DUP_dname) > 0 ) strcpy( dset_out->self_name , DUP_dname ) ;
158
159 /*** change of type? ***/
160
161 if( dataset_type >= FIRST_3DIM_TYPE && dataset_type <= LAST_3DIM_TYPE ){
162
163 int isfunc , new_nvals ;
164
165 isfunc = ISFUNCTYPE(dataset_type) ;
166 new_nvals = (isfunc) ? FUNC_nvals[function_type]
167 : ANAT_nvals[anatomy_type] ;
168
169 if( new_nvals > dset_in->dblk->nvals ){
170 fprintf(stderr,
171 "ERROR: new dataset type has %d values per voxel, but old has %d!\n"
172 " ==> cannot make duplicate!\n" ,
173 new_nvals , dset_in->dblk->nvals ) ;
174 exit(1) ;
175
176 } else if( new_nvals < dset_in->dblk->nvals ){
177 fprintf(stderr,
178 "WARNING: new dataset type has %d values per voxel, but old has %d!\n"
179 " ==> new dataset will not access all data in old!\n",
180 new_nvals , dset_in->dblk->nvals ) ;
181 }
182
183 dset_out->type = dataset_type ;
184 dset_out->func_type = ISANAT(dset_out) ? (anatomy_type)
185 : (function_type) ;
186 }
187
188 /*** done! ***/
189
190 THD_write_3dim_dataset( DUP_session , DUP_prefix , dset_out , False ) ;
191
192 exit(0) ;
193 }
194
195 /*---------------------------------------------------------------------
196 Adapted from AFNI_follower_dataset:
197 Make a warped dataset whose grid corresponds to the parent and
198 whose warp is just the identity warp.
199 -----------------------------------------------------------------------*/
200
duplicate_dataset(THD_3dim_dataset * parent)201 THD_3dim_dataset * duplicate_dataset( THD_3dim_dataset * parent )
202 {
203 THD_3dim_dataset * new_dset ;
204 int ii ;
205
206 /* sanity checks */
207
208 if( ! ISVALID_3DIM_DATASET(parent) ) return NULL ;
209
210 /* make new dataset, copying appropriate fields from its various parents */
211
212 new_dset = myXtNew( THD_3dim_dataset ) ; INIT_KILL( new_dset->kl ) ;
213
214 new_dset->type = parent->type ;
215 new_dset->func_type = parent->func_type ;
216 new_dset->view_type = parent->view_type ;
217 new_dset->Label_Dtable = NULL; /* ZSS Feb 26 2010 */
218
219 new_dset->anat_parent = NULL ; /* no anat parent */
220 new_dset->anat_parent_name[0] = '\0' ;
221
222 new_dset->warp_parent = parent ; /* yes warp parent */
223 MCW_strncpy( new_dset->warp_parent_name , parent->self_name , THD_MAX_NAME ) ;
224
225 /* make the actual warp from the warp_parent to this dataset */
226
227 new_dset->vox_warp = myXtNew( THD_warp ) ;
228 new_dset->vox_warp->type = ILLEGAL_TYPE ; /* created when needed */
229 new_dset->warp = myXtNew( THD_warp ) ;
230 *(new_dset->warp) = IDENTITY_WARP ;
231
232 /* make up some names for this new dataset */
233
234 MCW_strncpy( new_dset->self_name , parent->self_name , THD_MAX_NAME-5 ) ;
235 ii = strlen( new_dset->self_name ) ;
236 MCW_strncpy( &(new_dset->self_name[ii]) , "%duplicate" , THD_MAX_NAME-ii ) ;
237
238 MCW_strncpy( new_dset->label1 , parent->label1 , THD_MAX_LABEL ) ;
239 MCW_strncpy( new_dset->label2 , parent->label2 , THD_MAX_LABEL ) ;
240
241 /* set the axes for this new dataset
242 (same as parent, since that's the meaning of this routine) */
243
244 new_dset->daxes = myXtNew( THD_dataxes ) ; /* copy data axes of */
245 *(new_dset->daxes) = *(parent->daxes) ; /* parent */
246 new_dset->daxes->parent = (XtPointer) new_dset ; /* reset parent */
247
248 new_dset->wod_daxes = myXtNew( THD_dataxes ) ; /* warp-on-demand */
249 *(new_dset->wod_daxes) = *(new_dset->daxes) ;
250 new_dset->wod_flag = True ;
251
252 /* create a datablock and diskptr, in case the data is ever
253 filled into memory (instead of wod) and written to disk */
254
255 new_dset->dblk = myXtNew( THD_datablock ) ; INIT_KILL( new_dset->dblk->kl ) ;
256
257 new_dset->dblk->type = DATABLOCK_TYPE ;
258 new_dset->dblk->nvals = parent->dblk->nvals ;
259 new_dset->dblk->brick = NULL ;
260 new_dset->dblk->malloc_type = DATABLOCK_MEM_UNDEFINED ;
261 new_dset->dblk->total_bytes = 0 ;
262 new_dset->dblk->brick_bytes = NULL ;
263 new_dset->dblk->natr = new_dset->dblk->natr_alloc = 0 ;
264 new_dset->dblk->atr = NULL ;
265 new_dset->dblk->parent = (XtPointer) new_dset ;
266
267 DBLK_unlock(new_dset->dblk) ;
268
269 new_dset->dblk->diskptr = myXtNew( THD_diskptr ) ;
270 new_dset->dblk->diskptr->type = DISKPTR_TYPE ;
271 new_dset->dblk->diskptr->nvals = parent->dblk->nvals ;
272 new_dset->dblk->diskptr->rank = 3 ;
273 new_dset->dblk->diskptr->storage_mode = STORAGE_UNDEFINED ;
274 new_dset->dblk->diskptr->byte_order = THD_get_write_order() ; /* 25 April 1998 */
275 new_dset->dblk->diskptr->dimsizes[0] = new_dset->daxes->nxx ;
276 new_dset->dblk->diskptr->dimsizes[1] = new_dset->daxes->nyy ;
277 new_dset->dblk->diskptr->dimsizes[2] = new_dset->daxes->nzz ;
278
279 /* create the names for storage on disk (if ever)
280 -- note we put it in the same directory as the parent */
281
282 THD_init_diskptr_names( new_dset->dblk->diskptr ,
283 parent->dblk->diskptr->directory_name , NULL ,
284 parent->dblk->diskptr->prefix ,
285 new_dset->view_type , True ) ;
286
287 ADDTO_KILL( new_dset->dblk->kl , new_dset->dblk->diskptr ) ;
288
289 /* oh yeah, set the new_dset kill list,
290 copy statistics if available, and NULL out any unused stuff */
291
292 ADDTO_KILL( new_dset->kl , new_dset->warp ) ;
293 ADDTO_KILL( new_dset->kl , new_dset->vox_warp ) ;
294 ADDTO_KILL( new_dset->kl , new_dset->daxes ) ;
295 ADDTO_KILL( new_dset->kl , new_dset->wod_daxes ) ;
296 ADDTO_KILL( new_dset->kl , new_dset->dblk ) ;
297
298 new_dset->self_warp = NULL ; /* 26 Aug 2002 */
299
300 if( parent->stats != NULL ){
301 new_dset->stats = myXtNew( THD_statistics ) ; /* copy statistics */
302 *(new_dset->stats) = *(parent->stats) ; /* of parent */
303 new_dset->stats->parent = (XtPointer) new_dset ;
304 ADDTO_KILL( new_dset->kl , new_dset->stats ) ;
305 } else {
306 new_dset->stats = NULL ;
307 }
308
309 new_dset->markers = NULL ; /* no markers */
310 new_dset->death_mark = 0 ; /* don't kill me! */
311 new_dset->tcat_list = 0 ;
312 new_dset->tcat_num = 0 ;
313 new_dset->tcat_len = NULL ;
314
315 return(new_dset) ;
316 }
317