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 #include "thd.h"
9
10 /*---------------------------------------------------------------*/
11 static int allow_nodata = 0 ; /* 23 Mar 2001 */
12
THD_allow_empty_dataset(int n)13 void THD_allow_empty_dataset( int n ){ allow_nodata = n ; }
14 /*---------------------------------------------------------------*/
15
16 /*! With this macro defined, many of the attributes will actually
17 be set in function THD_datablock_apply_atr() instead of herein.
18 This change is to allow attributes read after the dataset struct
19 is already created to be useful, for the NIfTI-ization project. */
20
21 #define USE_APPLICATOR /* 10 May 2005 */
22
23 extern int Matvec_2_WarpData(ATR_float *atr_flo, THD_affine_warp *ww, float *wdv);
24 extern int THD_WarpData_From_3dWarpDrive(THD_3dim_dataset *dset, ATR_float *atr_flt);
25
DSET_Label_Dtable(THD_3dim_dataset * dset)26 void *DSET_Label_Dtable(THD_3dim_dataset *dset)
27 {
28 ATR_string *atr_str = NULL;
29
30 if (!dset) return(NULL);
31 if (dset->Label_Dtable) return(dset->Label_Dtable);
32
33 atr_str = THD_find_string_atr( dset->dblk , "VALUE_LABEL_DTABLE" ) ;
34 if (atr_str) {
35 dset->Label_Dtable = (void *)Dtable_from_nimlstring(atr_str->ch);
36 } else {
37 dset->Label_Dtable = NULL;
38 }
39
40 return(dset->Label_Dtable);
41 }
42 /*-------------------------------------------------------------------*/
43 /*! Given a datablock, make it into a 3D dataset if possible.
44 ---------------------------------------------------------------------*/
45
THD_3dim_from_block(THD_datablock * blk)46 THD_3dim_dataset * THD_3dim_from_block( THD_datablock *blk )
47 {
48 THD_3dim_dataset *dset ;
49 THD_diskptr *dkptr ;
50 THD_dataxes *daxes ;
51
52 RwcBoolean dset_ok = True ;
53 int iq ;
54
55 ATR_int *atr_int ;
56 ATR_string *atr_str ;
57 ATR_float *atr_flo ;
58
59 #if 0
60 int new_idcode = 0 ; /* no longer needed */
61 #endif
62
63 ENTRY("THD_3dim_from_block") ; /* 29 Aug 2001 */
64
65 /* sanity check */
66
67 if( ! ISVALID_DATABLOCK(blk) || ! ISVALID_DISKPTR(blk->diskptr) )
68 RETURN( NULL );
69
70 /*-- initialize a new 3D dataset --*/
71
72 dset = myRwcNew( THD_3dim_dataset ) ; /* uses RwcCalloc() */
73 dset->dblk = blk ;
74 dkptr = blk->diskptr ;
75
76 if( PRINT_TRACING ){
77 char str[256] ;
78 sprintf(str,"rank=%d nvals=%d dim[0]=%d dim[1]=%d dim[2]=%d",
79 dkptr->rank , dkptr->nvals ,
80 dkptr->dimsizes[0] , dkptr->dimsizes[1] , dkptr->dimsizes[2] ) ;
81 STATUS(str) ;
82 }
83
84 INIT_KILL(dset->kl) ;
85 ADDTO_KILL(dset->kl,blk) ;
86
87 blk->parent = (RwcPointer) dset ;
88 dset->parent = NULL ;
89
90 daxes = dset->daxes = myRwcNew(THD_dataxes) ;
91 daxes->parent = (RwcPointer) dset ;
92
93 dset->wod_daxes = NULL ; /* 02 Nov 1996 */
94
95 dset->wod_flag = False ; /* set special flags */
96 dset->death_mark = 0 ;
97 dset->tcat_list = NULL ;
98 dset->tcat_num = 0 ;
99 dset->tcat_len = NULL ;
100 dset->Label_Dtable = NULL; /* ZSS Feb 26 2010 */
101
102 ADDTO_KILL(dset->kl,daxes) ;
103
104 dset->stats = NULL ;
105 #ifdef ALLOW_DATASET_VLIST
106 dset->pts = NULL ;
107 #endif
108 dset->taxis = NULL ;
109 dset->tagset = NULL ; /* 23 Oct 1998 */
110
111 /*------------------*/
112 /*-- check for 3D --*/
113 /*------------------*/
114
115 if( dkptr->rank != 3 ) DSET_ERRN("illegal # of dimensions",dkptr->rank) ;
116
117 /*--------------------------------------------------*/
118 /*-- find type of image from TYPESTRING attribute --*/
119 /*--------------------------------------------------*/
120
121 atr_str = THD_find_string_atr( blk , ATRNAME_TYPESTRING ) ;
122 if( atr_str == NULL ){
123 DSET_ERR("no TYPESTRING") ;
124 dset->type = -1 ;
125 } else {
126 int type ;
127 for( type=FIRST_3DIM_TYPE ; type <= LAST_3DIM_TYPE ; type++ )
128 if( strcmp( atr_str->ch , DATASET_typestr[type] ) == 0 ) break ;
129
130 if( type > LAST_3DIM_TYPE ) DSET_ERR("illegal TYPESTRING") ;
131 dset->type = type ;
132 }
133
134 /*-------------------------------------------------------*/
135 /*-- find view_type and func_type from SCENE_TYPE data --*/
136 /*-------------------------------------------------------*/
137
138 atr_int = THD_find_int_atr( blk , ATRNAME_SCENE_TYPE ) ;
139 if( atr_int == NULL ){
140 DSET_ERR("missing or illegal SCENE_TYPE") ;
141 } else {
142 dset->view_type = atr_int->in[0] ;
143 dset->func_type = atr_int->in[1] ;
144
145 if( dset->type != atr_int->in[2] ){
146 DSET_ERR("non-matching SCENE_TYPE[2]") ;
147 }
148 }
149
150 /*-------------------------------------------------------*/
151 /*-- find identifier codes --*/
152 /*-------------------------------------------------------*/
153
154 #ifndef USE_APPLICATOR
155 atr_str = THD_find_string_atr( blk , ATRNAME_IDSTRING ) ;
156 if( atr_str != NULL ){
157 MCW_strncpy( dset->idcode.str , atr_str->ch , MCW_IDSIZE ) ;
158 atr_str = THD_find_string_atr( blk , ATRNAME_IDDATE ) ;
159 if( atr_str == NULL )
160 MCW_strncpy( dset->idcode.date , "None" , MCW_IDDATE ) ;
161 else
162 MCW_strncpy( dset->idcode.date , atr_str->ch , MCW_IDDATE ) ;
163 }
164 #endif
165
166 ZERO_IDCODE(dset->anat_parent_idcode) ;
167 ZERO_IDCODE(dset->warp_parent_idcode) ;
168
169 #ifndef USE_APPLICATOR
170 atr_str = THD_find_string_atr( blk , ATRNAME_IDANATPAR ) ;
171 if( atr_str != NULL )
172 MCW_strncpy( dset->anat_parent_idcode.str , atr_str->ch , MCW_IDSIZE ) ;
173
174 atr_str = THD_find_string_atr( blk , ATRNAME_IDWARPPAR ) ;
175 if( atr_str != NULL )
176 MCW_strncpy( dset->warp_parent_idcode.str , atr_str->ch , MCW_IDSIZE ) ;
177 #endif
178
179 /*--------------------------------*/
180 /*-- get data labels (optional) --*/
181 /*--------------------------------*/
182
183 atr_str = THD_find_string_atr( blk , ATRNAME_LABEL1 ) ;
184 if( atr_str == NULL )
185 atr_str = THD_find_string_atr( blk , ATRNAME_DATANAME ) ;
186
187 if( atr_str != NULL ){
188 MCW_strncpy( dset->label1 , atr_str->ch , THD_MAX_LABEL ) ;
189 } else {
190 MCW_strncpy( dset->label1 , THD_DEFAULT_LABEL , THD_MAX_LABEL ) ;
191 }
192
193 atr_str = THD_find_string_atr( blk , ATRNAME_LABEL2 ) ;
194 if( atr_str != NULL ){
195 MCW_strncpy( dset->label2 , atr_str->ch , THD_MAX_LABEL ) ;
196 } else {
197 MCW_strncpy( dset->label2 , THD_DEFAULT_LABEL , THD_MAX_LABEL ) ;
198 }
199
200 dset->keywords = NULL ;
201 #ifndef USE_APPLICATOR
202 atr_str = THD_find_string_atr( blk , ATRNAME_KEYWORDS ) ;
203 if( atr_str != NULL )
204 dset->keywords = RwcNewString( atr_str->ch ) ;
205 #endif
206
207 /*---------------------------------*/
208 /*-- get parent names (optional) --*/
209 /*---------------------------------*/
210
211 dset->anat_parent_name[0] = '\0' ;
212 dset->warp_parent_name[0] = '\0' ;
213 MCW_strncpy( dset->self_name , THD_DEFAULT_LABEL , THD_MAX_NAME ) ;
214 dset->anat_parent = dset->warp_parent = NULL ; /* must be set later */
215
216 #ifndef USE_APPLICATOR
217 atr_str = THD_find_string_atr( blk , ATRNAME_ANATOMY_PARENT ) ;
218 if( atr_str != NULL && ISZERO_IDCODE(dset->anat_parent_idcode) ){
219 MCW_strncpy( dset->anat_parent_name , atr_str->ch , THD_MAX_NAME ) ;
220 }
221
222 atr_str = THD_find_string_atr( blk , ATRNAME_WARP_PARENT ) ;
223 if( atr_str != NULL && ISZERO_IDCODE(dset->warp_parent_idcode) ){
224 MCW_strncpy( dset->warp_parent_name , atr_str->ch , THD_MAX_NAME ) ;
225 }
226
227 atr_str = THD_find_string_atr( blk , ATRNAME_DATANAME ) ;
228 if( atr_str != NULL ){
229 MCW_strncpy( dset->self_name , atr_str->ch , THD_MAX_NAME ) ;
230 }
231 #endif
232
233 /*---------------------------*/
234 /*-- find axes orientation --*/
235 /*---------------------------*/
236
237 daxes->type = DATAXES_TYPE ;
238 daxes->nxx = dkptr->dimsizes[0] ;
239 daxes->nyy = dkptr->dimsizes[1] ;
240 daxes->nzz = dkptr->dimsizes[2] ;
241
242 atr_int = THD_find_int_atr( blk , ATRNAME_ORIENT_SPECIFIC ) ;
243 if( atr_int == NULL ){
244 DSET_ERR("illegal or missing ORIENT_SPECIFIC") ;
245 } else {
246 daxes->xxorient = atr_int->in[0] ;
247 daxes->yyorient = atr_int->in[1] ;
248 daxes->zzorient = atr_int->in[2] ;
249 }
250
251 /*----------------------*/
252 /*-- find axes origin --*/
253 /*----------------------*/
254
255 atr_flo = THD_find_float_atr( blk , ATRNAME_ORIGIN ) ;
256 if( atr_flo == NULL ){
257 DSET_ERR("illegal or missing ORIGIN") ;
258 } else {
259 daxes->xxorg = atr_flo->fl[0] ;
260 daxes->yyorg = atr_flo->fl[1] ;
261 daxes->zzorg = atr_flo->fl[2] ;
262 }
263
264 /*------------------------*/
265 /*-- find axes spacings --*/
266 /*------------------------*/
267
268 atr_flo = THD_find_float_atr( blk , ATRNAME_DELTA ) ;
269 if( atr_flo == NULL ){
270 DSET_ERR("illegal or missing DELTA") ;
271 } else {
272 daxes->xxdel = atr_flo->fl[0] ;
273 daxes->yydel = atr_flo->fl[1] ;
274 daxes->zzdel = atr_flo->fl[2] ;
275 }
276
277 /*---------------------------------------*/
278 /*-- set bounding box for this dataset --*/
279 /*---------------------------------------*/
280
281 THD_set_daxes_bbox( daxes ) ; /* 20 Dec 2005 */
282
283 /*----------------------------------------------------------------*/
284 /*-- matrix that transforms to Dicom (left-posterior-superior) --*/
285 /*----------------------------------------------------------------*/
286
287 THD_set_daxes_to_dicomm( daxes ) ; /* 20 Dec 2005 */
288
289 /* 09 Dec 2005: set ijk_to_dicom matrix and its inverse */
290
291 if( !ISVALID_MAT44(daxes->ijk_to_dicom) )
292 THD_daxes_to_mat44( daxes ) ;
293
294 atr_flo = THD_find_float_atr( blk, "IJK_TO_DICOM_REAL" );
295 /* load oblique transformation matrix */
296 if(atr_flo) {
297 LOAD_MAT44(daxes->ijk_to_dicom_real, \
298 atr_flo->fl[0], atr_flo->fl[1], atr_flo->fl[2], atr_flo->fl[3], \
299 atr_flo->fl[4], atr_flo->fl[5], atr_flo->fl[6], atr_flo->fl[7], \
300 atr_flo->fl[8], atr_flo->fl[9], atr_flo->fl[10], atr_flo->fl[11]);
301 }
302 else {
303 ZERO_MAT44(daxes->ijk_to_dicom_real); /* clear values */
304 daxes->ijk_to_dicom_real.m[3][3] = 0.0; /* and make invalid */
305 }
306
307 /*------------------------------------*/
308 /*-- read set of markers (optional) --*/
309 /*------------------------------------*/
310
311 dset->markers = NULL ;
312
313 #ifndef USE_APPLICATOR
314 atr_flo = THD_find_float_atr( blk , ATRNAME_MARKSXYZ ) ;
315
316 if( atr_flo != NULL ){
317 dset->markers = myRwcNew( THD_marker_set ) ; /* new set */
318 ADDTO_KILL(dset->kl , dset->markers) ;
319
320 /*-- copy floating coordinates into marker struct --*/
321
322 COPY_INTO_STRUCT( *(dset->markers) , /* actual struct */
323 MARKS_FSTART , /* byte offset */
324 float , /* type being copied */
325 atr_flo->fl , /* start of source */
326 MARKS_FSIZE ) ; /* number of floats */
327
328 /*----- must have labels along with coordinates -----*/
329
330 atr_str = THD_find_string_atr( blk , ATRNAME_MARKSLAB ) ;
331 if( atr_str == NULL ){
332 DSET_ERR("MARKS_XYZ present but not MARKS_LAB!") ;
333 } else {
334 int im , llen ;
335 THD_ivec3 iv ;
336 float xxdown,xxup , yydown,yyup , zzdown,zzup ;
337
338 /*-- copy labels into marker struct --*/
339
340 COPY_INTO_STRUCT( *(dset->markers) ,
341 MARKS_LSTART ,
342 char ,
343 atr_str->ch ,
344 MARKS_LSIZE ) ;
345
346 /*-- check each marker for validity:
347 non-blank label string,
348 all coordinates inside bounding box --*/
349
350 /** July 1995: extend bounding box a little, maybe **/
351
352 #ifndef EXTEND_BBOX
353 xxdown = daxes->xxmin - 0.501 * fabs(daxes->xxdel) ;
354 xxup = daxes->xxmax + 0.501 * fabs(daxes->xxdel) ;
355 yydown = daxes->yymin - 0.501 * fabs(daxes->yydel) ;
356 yyup = daxes->yymax + 0.501 * fabs(daxes->yydel) ;
357 zzdown = daxes->zzmin - 0.501 * fabs(daxes->zzdel) ;
358 zzup = daxes->zzmax + 0.501 * fabs(daxes->zzdel) ;
359 #else
360 xxdown = daxes->xxmin ;
361 xxup = daxes->xxmax ;
362 yydown = daxes->yymin ;
363 yyup = daxes->yymax ;
364 zzdown = daxes->zzmin ;
365 zzup = daxes->zzmax ;
366 #endif
367
368 dset->markers->numdef = dset->markers->numset = 0 ;
369
370 for( im=0 ; im < MARKS_MAXNUM ; im++ ){
371 llen = strlen( &(dset->markers->label[im][0]) ) ;
372 dset->markers->valid[im] =
373 (llen > 0) &&
374 ( dset->markers->xyz[im][0] >= xxdown ) &&
375 ( dset->markers->xyz[im][0] <= xxup ) &&
376 ( dset->markers->xyz[im][1] >= yydown ) &&
377 ( dset->markers->xyz[im][1] <= yyup ) &&
378 ( dset->markers->xyz[im][2] >= zzdown ) &&
379 ( dset->markers->xyz[im][2] <= zzup ) ;
380
381 if( dset->markers->valid[im] ) (dset->markers->numset)++ ;
382
383 if( llen > 0 ) (dset->markers->numdef)++ ;
384
385 dset->markers->ovcolor[im] = -1 ; /* default color */
386
387 } /* end of loop over markers */
388 } /* end of if marker labels exist */
389
390 /*----- should also have help for each marker -----*/
391
392 atr_str = THD_find_string_atr( blk , ATRNAME_MARKSHELP ) ;
393 if( atr_str == NULL ){
394 int im ;
395 for( im=0 ; im < MARKS_MAXNUM ; im++ )
396 dset->markers->help[im][0] = '\0' ; /* empty string */
397 } else {
398 COPY_INTO_STRUCT( *(dset->markers) ,
399 MARKS_HSTART ,
400 char ,
401 atr_str->ch ,
402 MARKS_HSIZE ) ;
403 } /* end of if marker help exists */
404
405 /*----- should also have action flags for the marker set -----*/
406
407 atr_int = THD_find_int_atr( blk , ATRNAME_MARKSFLAG ) ;
408 if( atr_int == NULL ){
409 int im ;
410 for( im=0 ; im < MARKS_MAXFLAG ; im++ )
411 dset->markers->aflags[im] = -1 ;
412 } else {
413 COPY_INTO_STRUCT( *(dset->markers) ,
414 MARKS_ASTART ,
415 int ,
416 atr_int->in ,
417 MARKS_ASIZE ) ;
418 dset->markers->type = dset->markers->aflags[0] ;
419 } /* end of if marker flags exist */
420
421 } /* end of if markers exist */
422 #endif
423
424 /*--------------------------*/
425 /*-- read warp (optional) --*/
426 /*--------------------------*/
427
428 dset->vox_warp = NULL ; /* 02 Nov 1996 */
429 dset->self_warp = NULL ; /* 26 Aug 2002 */
430 dset->warp = NULL ;
431
432 #ifndef USE_APPLICATOR
433 atr_int = THD_find_int_atr( blk , ATRNAME_WARP_TYPE ) ;
434 if( atr_int != NULL ){ /* no warp */
435 int wtype = atr_int->in[0] , rtype = atr_int->in[1] ;
436
437 dset->warp = myRwcNew( THD_warp ) ;
438 ADDTO_KILL( dset->kl , dset->warp ) ;
439
440 atr_flo = THD_find_float_atr( blk , ATRNAME_WARP_DATA ) ;
441 if( atr_flo == NULL ){
442 DSET_ERR("illegal or missing WARP_DATA") ;
443 } else {
444 switch( wtype ){
445
446 default: DSET_ERR("illegal WARP_TYPE warp code") ; break;
447
448 case WARP_AFFINE_TYPE:{
449 THD_affine_warp *ww = (THD_affine_warp *) dset->warp ;
450 ww->type = wtype ;
451 ww->resam_type = rtype ;
452 ww->warp.type = MAPPING_LINEAR_TYPE ;
453
454 COPY_INTO_STRUCT( ww->warp ,
455 MAPPING_LINEAR_FSTART ,
456 float ,
457 atr_flo->fl ,
458 MAPPING_LINEAR_FSIZE ) ;
459 }
460 break ; /* end affine warp */
461
462 case WARP_TALAIRACH_12_TYPE:{
463 THD_talairach_12_warp *ww =
464 (THD_talairach_12_warp *) dset->warp ;
465 int iw , ioff ;
466 ww->type = wtype ;
467 ww->resam_type = rtype ;
468 for( iw=0 ; iw < 12 ; iw++ ){
469 ww->warp[iw].type = MAPPING_LINEAR_TYPE ;
470
471 ioff = iw * MAPPING_LINEAR_FSIZE ;
472
473 COPY_INTO_STRUCT( ww->warp[iw] ,
474 MAPPING_LINEAR_FSTART ,
475 float ,
476 &(atr_flo->fl[ioff]) ,
477 MAPPING_LINEAR_FSIZE ) ;
478
479 } /* end loop over 12 warps */
480 }
481 break ; /* end talairach_12 warp */
482
483 } /* end of switch on warp type */
484 } /* end of if on legal warp data */
485 } /* end of if on warp existing */ else { /* But perhaps there is a
486 little something from auto talairaching ZSS, June 06 */
487 if (dset->view_type == VIEW_TALAIRACH_TYPE) { /* something to do */
488 atr_flo = THD_find_float_atr( blk , ATRNAME_WARP_DATA_3DWD_AF ) ;
489 if ( atr_flo == NULL ){
490 /* A tlrc set with no transform. No problem */
491 } else {
492 if (!THD_WarpData_From_3dWarpDrive(dset, atr_flo)) {
493 fprintf(stderr,"Error: Failed to create WarpData!\n");
494 }
495 }
496 } else {
497 /* fprintf(stderr,"Not in TLRC space, bother not.\n"); */
498 }
499 } /* the very end of if on warp existing */
500 #endif
501
502 /*----- read statistics, if available -----*/
503
504 #ifndef USE_APPLICATOR
505 atr_flo = THD_find_float_atr( blk , ATRNAME_BRICK_STATS ) ; /* new style */
506
507 if( atr_flo != NULL ){ /*** have new style statistics ***/
508 int qq ;
509 dset->stats = myRwcNew( THD_statistics ) ;
510 dset->stats->type = STATISTICS_TYPE ;
511 dset->stats->parent = (RwcPointer) dset ;
512 dset->stats->nbstat = blk->nvals ;
513 dset->stats->bstat = (THD_brick_stats *)
514 RwcMalloc( sizeof(THD_brick_stats) * blk->nvals ) ;
515 for( qq=0 ; qq < blk->nvals ; qq++ ){
516 if( 2*qq+1 < atr_flo->nfl ){
517 dset->stats->bstat[qq].min = atr_flo->fl[2*qq] ;
518 dset->stats->bstat[qq].max = atr_flo->fl[2*qq+1] ;
519 } else {
520 INVALIDATE_BSTAT( dset->stats->bstat[qq] ) ;
521 }
522 }
523 ADDTO_KILL( dset->kl , dset->stats->bstat ) ;
524 ADDTO_KILL( dset->kl , dset->stats ) ;
525
526 } else { /**** check for old style (version 1.03-4) statistics ****/
527
528 atr_int = THD_find_int_atr( blk , ATRNAME_MINMAX ) ;
529
530 if( atr_int == NULL ){ /*** no statistics at all ***/
531 dset->stats = NULL ;
532
533 } else { /*** have old style (integer) statistics ***/
534 int qq ;
535 dset->stats = myRwcNew( THD_statistics ) ;
536 dset->stats->type = STATISTICS_TYPE ;
537 dset->stats->parent = (RwcPointer) dset ;
538 dset->stats->nbstat = blk->nvals ;
539 dset->stats->bstat = (THD_brick_stats *)
540 RwcMalloc( sizeof(THD_brick_stats) * blk->nvals ) ;
541 for( qq=0 ; qq < blk->nvals ; qq++ ){
542 if( 2*qq+1 < atr_int->nin ){
543 dset->stats->bstat[qq].min = (float) atr_int->in[2*qq] ;
544 dset->stats->bstat[qq].max = (float) atr_int->in[2*qq+1] ;
545 } else {
546 INVALIDATE_BSTAT( dset->stats->bstat[qq] ) ;
547 }
548 }
549 ADDTO_KILL( dset->kl , dset->stats->bstat ) ;
550 ADDTO_KILL( dset->kl , dset->stats ) ;
551 }
552 }
553 #endif
554
555 /*--- read auxiliary statistics info, if any ---*/
556
557 atr_flo = THD_find_float_atr( blk , ATRNAME_STAT_AUX ) ;
558
559 if( atr_flo != NULL ){
560 INIT_STAT_AUX( dset , atr_flo->nfl , atr_flo->fl ) ;
561 iq = atr_flo->nfl ;
562 } else {
563 ZERO_STAT_AUX( dset ) ;
564 iq = 0 ;
565 }
566
567 if( ISFUNC(dset) && FUNC_need_stat_aux[dset->func_type] > iq ){
568 DSET_ERR("function type missing auxiliary statistical data") ;
569 }
570
571 /*--- read time-dependent information, if any ---*/
572
573 atr_int = THD_find_int_atr ( blk , ATRNAME_TAXIS_NUMS ) ;
574 atr_flo = THD_find_float_atr( blk , ATRNAME_TAXIS_FLOATS ) ;
575
576 if( atr_int != NULL && atr_flo != NULL ){
577 int isfunc , nvals ;
578
579 dset->taxis = myRwcNew( THD_timeaxis ) ;
580 ADDTO_KILL(dset->kl,dset->taxis) ;
581
582 dset->taxis->type = TIMEAXIS_TYPE ;
583 dset->taxis->ntt = atr_int->in[0] ;
584 dset->taxis->nsl = atr_int->in[1] ;
585 dset->taxis->ttorg = atr_flo->fl[0] ;
586 dset->taxis->ttdel = atr_flo->fl[1] ;
587 dset->taxis->ttdur = atr_flo->fl[2] ;
588 dset->taxis->zorg_sl = atr_flo->fl[3] ;
589 dset->taxis->dz_sl = atr_flo->fl[4] ;
590
591 dset->taxis->units_type = atr_int->in[2] ; /* 21 Oct 1996 */
592 if( dset->taxis->units_type < 0 ) /* assign units */
593 dset->taxis->units_type = UNITS_SEC_TYPE ; /* to the time axis */
594
595 if( dset->taxis->nsl > 0 ){
596 atr_flo = THD_find_float_atr( blk , ATRNAME_TAXIS_OFFSETS ) ;
597 if( atr_flo == NULL || atr_flo->nfl < dset->taxis->nsl ){
598 dset->taxis->nsl = 0 ;
599 dset->taxis->toff_sl = NULL ;
600 dset->taxis->zorg_sl = 0.0 ;
601 dset->taxis->dz_sl = 0.0 ;
602 } else {
603 int ii ;
604 dset->taxis->toff_sl = (float *) RwcMalloc(sizeof(float)*dset->taxis->nsl) ;
605 ADDTO_KILL(dset->kl,dset->taxis->toff_sl) ;
606 for( ii=0 ; ii < dset->taxis->nsl ; ii++ )
607 dset->taxis->toff_sl[ii] = atr_flo->fl[ii] ;
608 }
609 } else {
610 dset->taxis->nsl = 0 ;
611 dset->taxis->toff_sl = NULL ;
612 dset->taxis->zorg_sl = 0.0 ;
613 dset->taxis->dz_sl = 0.0 ;
614 }
615
616 isfunc = ISFUNCTYPE(dset->type) ;
617 nvals = (isfunc) ? FUNC_nvals[dset->func_type]
618 : ANAT_nvals[dset->func_type] ;
619
620 if( nvals != 1 ){
621 WARNING_message("Illegal 3D+time dataset & func_type combination: '%s'" ,
622 DSET_HEADNAME(dset) ) ;
623 if( dset->taxis->toff_sl != NULL ) myRwcFree(dset->taxis->toff_sl) ;
624 myRwcFree(dset->taxis) ;
625 }
626
627 /** 15 Aug 2005: don't allow milliseconds on input any more **/
628
629 if( !AFNI_yesenv("AFNI_ALLOW_MILLISECONDS") ){ DSET_UNMSEC(dset); }
630 }
631
632 /*--- 23 Oct 1998: read the tagset information ---*/
633
634 #ifndef USE_APPLICATOR
635 atr_int = THD_find_int_atr ( blk , ATRNAME_TAGSET_NUM ) ;
636 atr_flo = THD_find_float_atr ( blk , ATRNAME_TAGSET_FLOATS ) ;
637 atr_str = THD_find_string_atr( blk , ATRNAME_TAGSET_LABELS ) ;
638
639 if( atr_int != NULL && atr_flo != NULL && atr_str != NULL ){
640 int nin=atr_int->nin , nfl=atr_flo->nfl , nch=atr_str->nch ;
641 int ii , ntag , nfper , jj , kk ;
642
643 ntag = atr_int->in[0] ; /* number of tags */
644 nfper = atr_int->in[1] ; /* number of floats per tag */
645
646 if( ntag > MAX_TAG_NUM ) ntag = MAX_TAG_NUM ;
647
648 dset->tagset = myRwcNew( THD_usertaglist ) ; /* create tagset */
649 ADDTO_KILL( dset->kl , dset->tagset ) ;
650
651 dset->tagset->num = ntag ;
652 strcpy( dset->tagset->label , "Bebe Rebozo" ) ; /* not used */
653
654 /* read out tag values; allow for chance there isn't enough data */
655
656 #undef TF
657 #define TF(i,j) ( ((j)<nfper && (i)*nfper+(j)<nfl) ? atr_flo->fl[(i)*nfper+(j)] : -666.0 )
658 for( ii=0 ; ii < ntag ; ii++ ){
659 dset->tagset->tag[ii].x = TF(ii,0) ; /* coords */
660 dset->tagset->tag[ii].y = TF(ii,1) ;
661 dset->tagset->tag[ii].z = TF(ii,2) ;
662 dset->tagset->tag[ii].val = TF(ii,3) ; /* value */
663 dset->tagset->tag[ii].ti = TF(ii,4) ; /* time index; if < 0 ==> not set */
664 if( dset->tagset->tag[ii].ti >= 0 ){
665 dset->tagset->tag[ii].set = 1 ;
666 } else {
667 dset->tagset->tag[ii].set = 0 ; dset->tagset->tag[ii].ti = 0 ;
668 }
669 }
670 #undef TF
671
672 /* read out tag labels; allow for empty labels */
673
674 jj = 0 ;
675 for( ii=0 ; ii < ntag ; ii++ ){
676 if( jj < nch ){
677 kk = strlen( atr_str->ch + jj ) ;
678 if( kk > 0 ) TAG_SETLABEL( dset->tagset->tag[ii] , atr_str->ch + jj ) ;
679 else sprintf( dset->tagset->tag[ii].label , "Tag %d" , ii+1 ) ;
680 jj += kk+1 ;
681 } else {
682 sprintf( dset->tagset->tag[ii].label , "Tag %d" , ii+1 ) ;
683 }
684 }
685 }
686 #endif
687
688 /* 10 May 2005: new function to apply some attributes
689 to dataset, rather than doing it here */
690
691 #ifdef USE_APPLICATOR
692 THD_datablock_apply_atr( dset ) ;
693 #endif
694
695 /*--- check for the following conditions:
696 if warp exists, warp_parent_name or _idcode must exist;
697 if warp nonexists, warp_parent_name and _idcode must nonexist,
698 AND data must exist on disk ---*/
699
700 if( dset->warp != NULL ){
701 if( strlen(dset->warp_parent_name) <= 0 &&
702 ISZERO_IDCODE(dset->warp_parent_idcode) )
703 DSET_ERR("have warp but have no warp parent") ;
704
705 dset->wod_flag = !allow_nodata && !DSET_ONDISK(dset) ;
706 } else {
707 if( strlen(dset->warp_parent_name) > 0 ||
708 !ISZERO_IDCODE(dset->warp_parent_idcode) )
709 DSET_ERR("have no warp but have warp parent") ;
710
711 if( !allow_nodata && !DSET_ONDISK(dset) )
712 DSET_ERR("have no warp but have no data on disk as well") ;
713 }
714
715 /* backup assignment of ID code if not assigned earlier */
716
717 if( dset->idcode.str[0] == '\0' ) dset->idcode = MCW_new_idcode() ;
718
719 /*--- that's all the work for now;
720 if any error was flagged, kill this dataset and return nothing ---*/
721
722 if( dset_ok == False ){
723 fprintf(stderr,"PURGING dataset %s from memory\n",DSET_HEADNAME(dset)) ;
724 THD_delete_3dim_dataset( dset , False ) ;
725 RETURN(NULL) ;
726 }
727
728 /*--- If we assigned a new dataset idcode, write it back to disk ---*/
729 /* (This code was for the old days, when there were datasets)
730 (hanging around that hadn't yet been assigned ID codes. ) */
731
732 #if 0
733 if( dset != NULL && new_idcode ){
734 fprintf(stderr,"** Writing new ID code to dataset header %s\n",
735 dset->dblk->diskptr->header_name ) ;
736 THD_write_3dim_dataset( NULL , NULL , dset , False ) ;
737 }
738 #endif
739
740 /* Create label table struct if attribute is present in header*/
741 dset->Label_Dtable = DSET_Label_Dtable(dset);
742
743 THD_patch_brickim(dset) ; RETURN(dset);
744 }
745