Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

thd_niftiwrite.c

Go to the documentation of this file.
00001 #include "mrilib.h"
00002 #include "thd_niftiwrite.h"
00003 
00004 /* prototypes */
00005 
00006 nifti_image * populate_nifti_image(THD_3dim_dataset *dset, niftiwr_opts_t options) ;
00007 
00008 void nifti_set_afni_extension(THD_3dim_dataset *dset,nifti_image *nim) ;
00009 
00010 /*******************************************************************/
00011 /*!  Write an AFNI dataset as a NIFTI file.
00012      - fname = NIFTI filename
00013      - dset = AFNI dataset
00014      - flags = logical OR of various masks:
00015 
00016    Return value is 1 if went OK, 0 if not.
00017 -------------------------------------------------------------------*/
00018 
00019 int THD_write_nifti( THD_3dim_dataset *dset, niftiwr_opts_t options )
00020 {
00021   nifti_image * nim ;
00022   nifti_brick_list nbl ;
00023   int ii ;
00024   char * fname ;
00025 
00026 ENTRY("THD_write_nifti") ;
00027 
00028   nifti_set_debug_level(options.debug_level) ;
00029 
00030    /*-- check inputs for goodness --*/
00031 
00032   fname = nifti_strdup(options.infile_name );
00033 
00034   if( !THD_filename_ok(fname) || fname[0] == '-' ){
00035     fprintf(stderr,"** ERROR: Illegal filename for NIFTI output: %s\n",
00036       (fname != NULL) ? fname : "(null)" ) ;
00037     RETURN(0) ;
00038   }
00039 
00040   if( !ISVALID_DSET(dset) ){
00041     fprintf(stderr,
00042          "** ERROR: Illegal input dataset for NIFTI output: %s\n",
00043          fname ) ;
00044     RETURN(0) ;
00045   }
00046 
00047   /*-- load dataset from disk, if need be --*/
00048 
00049   DSET_load(dset) ;
00050   if( !DSET_LOADED(dset) ){
00051     fprintf(stderr,
00052             "** ERROR: Can't write NIFTI file since dataset isn't loaded: %s\n", fname) ;
00053     RETURN(0) ;
00054   }
00055 
00056   nim = populate_nifti_image(dset,options) ;
00057 
00058   /*-- construct filename --*/
00059 
00060    nim->fname = malloc( strlen(fname)+16 ) ;
00061    nim->iname = malloc( strlen(fname)+16 ) ;
00062    strcpy(nim->fname,fname) ;
00063    strcpy(nim->iname,fname) ;
00064 
00065   /*-- construct nifti_brick_list of pointers to data briks */
00066 
00067   if( options.debug_level > 2 ) nifti_image_infodump(nim) ;
00068   nbl.bricks = (void **) malloc ( DSET_NVALS(dset) * sizeof(void*) ) ;
00069   nbl.nbricks = DSET_NVALS(dset) ;
00070   nbl.bsize = DSET_BRICK_BYTES(dset,0) ;
00071   for (ii = 0 ; ii < DSET_NVALS(dset) ; ii++ ) {
00072     nbl.bricks[ii] = DSET_ARRAY(dset,ii) ;
00073   }
00074 
00075   /*-- use handy-dandy library function to write out data */
00076 
00077   nifti_set_afni_extension( dset , nim ) ;  /* 09 May 2005 - RWCox */
00078 
00079   nifti_image_write_bricks (nim, &nbl ) ;
00080   RETURN(1) ;
00081 }
00082 
00083 /*******************************************************************/
00084 
00085 nifti_image * populate_nifti_image(THD_3dim_dataset *dset, niftiwr_opts_t options)
00086 {
00087   int nparam, type0 , ii , jj, val;
00088   int nif_x_axnum, nif_y_axnum, nif_z_axnum ;
00089   int slast, sfirst ;
00090   int pattern_unknown = 0 ;
00091   nifti_image * nim ;
00092   char axcode[3], axsign[3] ;
00093   float axstep[3] , axstart[3] ;
00094   int   axnum[3] ;
00095   float fac0 ;
00096   float dumqx, dumqy, dumqz, dumdx, dumdy, dumdz ;
00097   float pixdimfac[4] ;
00098   float odd_del, even_del, tmp_float ;
00099   int even_parity_sign = 0 ;
00100 
00101 ENTRY("populate_nifti_image") ;
00102   /*-- create nifti_image structure --*/
00103 
00104   nim = (nifti_image *) calloc( 1 , sizeof(nifti_image) ) ;
00105   if( !nim ) {
00106     fprintf(stderr, "** ERROR: failed to allocate nifti image\n");
00107     RETURN(0) ;
00108   }
00109 
00110   /*-- calculate and set ndim and intents --*/
00111   /* cases to allow for:
00112               1. 3d+time dataset
00113               2. 3d func bucket
00114                  (not going to handle this currently, may extend later)
00115                  -- RWC: modified so that 'u' dimension is for buckets
00116               3. 3d single brick
00117               4. 2d and 1d spatial
00118                  (if 2d or 1d spatial + time, treat as #1)
00119               5. Don't know of any vectors in AFNI, so won't do those either
00120               6. Single 3d (or 2d or 1d) functional brik  */
00121 
00122   if (dset->dblk->nvals > 1) {
00123     STATUS("4D dataset") ;
00124     nim->ndim = (dset->taxis != NULL) ? 4 : 5 ;  /* RWC: bucket stored as 5th dimen */
00125 
00126     /*-- check sub-bricks for uniformity in type and scale --*/
00127 
00128     type0 = DSET_BRICK_TYPE(dset,0) ;
00129     fac0  = DSET_BRICK_FACTOR(dset,0) ;
00130 
00131     for( ii=1 ; ii < DSET_NVALS(dset) ; ii++ ){
00132       if( DSET_BRICK_TYPE(dset,ii) != type0){
00133         fprintf(stderr,
00134         "** ERROR: CANNOT WRITE NIFTI FILE; BRICK DATA TYPES NOT CONSISTENT\n") ;
00135         RETURN(0);
00136       } else if( DSET_BRICK_FACTOR(dset,ii) != fac0) {
00137         fprintf(stderr,
00138         "** ERROR: CANNOT WRITE NIFTI FILE; BRICK FACTORS NOT CONSISTENT\n") ;
00139         fprintf(stderr,
00140         "RICH HAMMETT SHOULD FIX THIS REAL SOON NOW\n") ;
00141         RETURN(0);
00142       }
00143     }
00144   } else {  /* we only have one brick */
00145     STATUS("3D dataset") ;
00146     if( options.debug_level > 1 ) fprintf(stderr,"ONLY ONE BRICK!!!\n") ;
00147     type0 = DSET_BRICK_TYPE(dset,0);
00148     fac0  = DSET_BRICK_FACTOR(dset,0) ;
00149     if (ISFUNC(dset)) {
00150       STATUS("functional dataset") ;
00151       if( options.debug_level > 1 )
00152         fprintf(stderr,"ONLY ONE BRICK, AND IT'S FUNCTIONAL!!!\n") ;
00153       nim->intent_code = DSET_BRICK_STATCODE(dset,0);
00154       if (nim->intent_code < 0) nim->intent_code = dset->func_type ;
00155       if (nim->intent_code < 0) nim->intent_code = NIFTI_INTENT_NONE ;
00156       if( options.debug_level > 1 )
00157         fprintf(stderr,"ONLY ONE BRICK, AND ITS FUNCTIONAL STAT CODE IS %d !!!\n",nim->intent_code) ;
00158       if(PRINT_TRACING){
00159         char str[256]; sprintf(str,"intent_code = %d",nim->intent_code);STATUS(str);
00160       }
00161       if (nim->intent_code > -1) {
00162         nparam = FUNC_need_stat_aux[nim->intent_code];
00163         if (nparam >= 1) nim->intent_p1 = DSET_BRICK_STATPAR(dset,0,1);
00164         if (nparam >= 2) nim->intent_p2 = DSET_BRICK_STATPAR(dset,0,2);
00165         if (nparam == 3) nim->intent_p3 = DSET_BRICK_STATPAR(dset,0,3);
00166       }
00167     }
00168     if (dset->daxes->nzz > 1) {
00169       nim->ndim = 3 ;
00170     } else if (dset->daxes->nyy > 1) {
00171       nim->ndim = 2 ;
00172     } else {
00173       nim->ndim = 1;
00174     }
00175   }
00176 
00177 
00178   /*-- set datatype, size, etc. --*/
00179 
00180   STATUS("set datatype") ;
00181   switch(type0) {
00182     case MRI_byte:
00183       nim->datatype = DT_UNSIGNED_CHAR;
00184       nim->nbyper = 1 ;
00185       break;
00186     case MRI_short:
00187       nim->datatype = DT_SIGNED_SHORT;
00188       nim->nbyper = 2 ;
00189       break;
00190     case MRI_int:
00191       nim->datatype = DT_SIGNED_INT;
00192       nim->nbyper = 4 ;
00193       break;
00194     case MRI_float:
00195       nim->datatype = DT_FLOAT;
00196       nim->nbyper = 4 ;
00197       break;
00198     case MRI_double:
00199       nim->datatype = DT_DOUBLE;
00200       nim->nbyper = 8 ;
00201       break;
00202     case MRI_complex:
00203       nim->datatype = DT_COMPLEX;
00204       nim->nbyper = 8 ;
00205       break;
00206     case MRI_rgb:
00207       nim->datatype = DT_RGB24;
00208       nim->nbyper = 3 ;
00209       break;
00210     case MRI_rgba:
00211       fprintf(stderr,
00212                "** ERROR: Can't write NIFTI file since dataset is RGBA: %s\n",
00213                options.infile_name) ;
00214       RETURN(0) ;
00215       break;
00216     default:
00217       fprintf(stderr,
00218                "** ERROR: Can't write NIFTI file since datatype is unknown: %s\n",
00219                options.infile_name) ;
00220       RETURN(0) ;
00221       break;
00222   }
00223 
00224   /*-- scaling --*/
00225 
00226   nim->scl_slope = fac0 ;
00227   nim->scl_inter = 0 ;
00228 
00229   /*-- spatial transforms --*/
00230 
00231   STATUS("set orientation") ;
00232 
00233   axcode[0] = ORIENT_xyz[ dset->daxes->xxorient ] ; axnum[0] = dset->daxes->nxx ;
00234   axcode[1] = ORIENT_xyz[ dset->daxes->yyorient ] ; axnum[1] = dset->daxes->nyy ;
00235   axcode[2] = ORIENT_xyz[ dset->daxes->zzorient ] ; axnum[2] = dset->daxes->nzz ;
00236 
00237   axsign[0] = ORIENT_sign[ dset->daxes->xxorient ] ;
00238   axsign[1] = ORIENT_sign[ dset->daxes->yyorient ] ;
00239   axsign[2] = ORIENT_sign[ dset->daxes->zzorient ] ;
00240 
00241   axstep[0] = dset->daxes->xxdel ; axstart[0] = dset->daxes->xxorg ;
00242   axstep[1] = dset->daxes->yydel ; axstart[1] = dset->daxes->yyorg ;
00243   axstep[2] = dset->daxes->zzdel ; axstart[2] = dset->daxes->zzorg ;
00244 
00245   for (ii = 0 ; ii < 3 ; ii++ ) {
00246     if (axcode[ii] == 'x') {
00247       nif_x_axnum = ii ;
00248     } else if (axcode[ii] == 'y') {
00249       nif_y_axnum = ii ;
00250     } else nif_z_axnum = ii ;
00251   }
00252 
00253   nim->qto_xyz.m[0][0] = nim->qto_xyz.m[0][1] = nim->qto_xyz.m[0][2] =
00254   nim->qto_xyz.m[1][0] = nim->qto_xyz.m[1][1] = nim->qto_xyz.m[1][2] =
00255   nim->qto_xyz.m[2][0] = nim->qto_xyz.m[2][1] = nim->qto_xyz.m[2][2] = 0.0 ;
00256 
00257   /*-- set voxel and time deltas and units --*/
00258 
00259   nim->dx = nim->pixdim[1] = fabs ( axstep[0] ) ;
00260   nim->dy = nim->pixdim[2] = fabs ( axstep[1] ) ;
00261   nim->dz = nim->pixdim[3] = fabs ( axstep[2] ) ;
00262 
00263   nim->du = nim->pixdim[5] = 0 ;
00264   nim->dv = nim->pixdim[6] = 0 ;
00265   nim->dw = nim->pixdim[7] = 0 ;
00266 
00267 #if 0
00268   val = (axsign[nif_x_axnum] == '+')  ? -1 : 1 ;
00269   nim->qto_xyz.m[0][nif_x_axnum] = val  * nim->pixdim[nif_x_axnum + 1];
00270   val = (axsign[nif_y_axnum] == '+')  ? -1 : 1 ;
00271   nim->qto_xyz.m[1][nif_y_axnum] = val  * nim->pixdim[nif_y_axnum + 1];
00272   val = (axsign[nif_x_axnum] == '-')  ? -1 : 1 ;
00273   nim->qto_xyz.m[2][nif_z_axnum] = val  * nim->pixdim[nif_z_axnum + 1];
00274 #else
00275   nim->qto_xyz.m[0][nif_x_axnum] = - axstep[nif_x_axnum];
00276   nim->qto_xyz.m[1][nif_y_axnum] = - axstep[nif_y_axnum];
00277   nim->qto_xyz.m[2][nif_z_axnum] =   axstep[nif_z_axnum];
00278 #endif
00279 
00280   /* nifti origin stuff */
00281 
00282 #if 0
00283   nim->qoffset_x =  axstart[nif_x_axnum] ;
00284   if (axsign[nif_x_axnum] == '+') nim->qoffset_x = - nim->qoffset_x ;
00285   nim->qoffset_y =  axstart[nif_y_axnum];
00286   if (axsign[nif_y_axnum] == '+') nim->qoffset_y = - nim->qoffset_y ;
00287   nim->qoffset_z =  axstart[nif_z_axnum];
00288   if (axsign[nif_z_axnum] == '-') nim->qoffset_z = - nim->qoffset_z ;
00289 #endif
00290 
00291   nim->qoffset_x =  -axstart[nif_x_axnum] ;
00292   nim->qoffset_y =  -axstart[nif_y_axnum];
00293   nim->qoffset_z =  axstart[nif_z_axnum];
00294 
00295 #if 0
00296   nim->qoffset_x =  -axstart[0] ;
00297   nim->qoffset_y =  -axstart[1];
00298   nim->qoffset_z =  axstart[2];
00299 #endif
00300 
00301   nim->qto_xyz.m[0][3] = nim->qoffset_x ;
00302   nim->qto_xyz.m[1][3] = nim->qoffset_y ;
00303   nim->qto_xyz.m[2][3] = nim->qoffset_z ;
00304 
00305   /*-- from the above info, calculate the quaternion qform --*/
00306 
00307   STATUS("set quaternion") ;
00308 
00309   nifti_mat44_to_quatern( nim->qto_xyz , &nim->quatern_b, &nim->quatern_c, &nim->quatern_d,
00310                     &dumqx, &dumqy, &dumqz, &dumdx, &dumdy, &dumdz, &nim->qfac ) ;
00311 
00312   /*-- from the same above info, set the sform matrix to equal the qform --*/
00313   /* KRH 7/6/05 - using sform to duplicate qform for
00314                            interoperability with FSL                       */
00315 
00316   for ( ii = 0 ; ii < 3 ; ii++ ) {
00317     for ( jj = 0 ; jj < 4 ; jj++ ) {
00318       nim->sto_xyz.m[ii][jj] = nim->qto_xyz.m[ii][jj] ;
00319     }
00320   }
00321 
00322   /*-- verify dummy quaternion parameters --*/
00323 
00324   if( options.debug_level > 2 )
00325     fprintf(stderr,"++ Quaternion check:\n"
00326           "%f , %f\n %f , %f\n %f , %f\n %f , %f\n %f , %f\n %f , %f\n; %f\n",
00327            nim->qoffset_x, dumqx , nim->qoffset_y, dumqy , nim->qoffset_z, dumqz ,
00328            nim->dx, dumdx , nim->dy, dumdy , nim->dz, dumdz, nim->qfac ) ;
00329 
00330   /*-- calculate inverse qform            --*/
00331 
00332   nim->qto_ijk = nifti_mat44_inverse( nim->qto_xyz ) ;
00333 
00334   /*-- set dimensions of grid array --*/
00335 
00336   nim->nt = nim->nu = nim->nv = nim->nw = 1 ;
00337   nim->nx = axnum[0] ;
00338   nim->ny = axnum[1] ;
00339   nim->nz = axnum[2] ;
00340 
00341   if (dset->taxis == NULL) {
00342     nim->nu = DSET_NVALS(dset) ;   /* RWC: bucket is 5th dimension */
00343   } else {
00344     nim->nt = DSET_NUM_TIMES(dset) ;  /* time is 4th dimension */
00345   }
00346 
00347   if ( nim->nt > 1){
00348     float TR = dset->taxis->ttdel ;
00349     if( DSET_TIMEUNITS(dset) == UNITS_MSEC_TYPE ) TR *= 0.001; /* 10 May 2005 */
00350     nim->dt = nim->pixdim[4] = TR ;
00351   }
00352 
00353   nim->dim[0] = nim->ndim;
00354   nim->dim[1] = nim->nx;
00355   nim->dim[2] = nim->ny;
00356   nim->dim[3] = nim->nz;
00357   nim->dim[4] = nim->nt;  /* RWC: at most one of nt and nu is > 1 */
00358   nim->dim[5] = nim->nu;
00359   nim->dim[6] = nim->nv;
00360   nim->dim[7] = nim->nw;
00361 
00362   nim->nvox = nim->nx * nim->ny * nim->nz * nim->nt
00363                                 * nim->nu * nim->nv * nim->nw ;
00364 
00365   /*-- slice timing --*/
00366 
00367   nim->freq_dim = nim->phase_dim = 0 ;
00368   if (dset->taxis != NULL) {  /* if time axis exists */
00369     nim->slice_dim = 3 ;
00370     nim->slice_duration = 0 ;
00371     nim->slice_start = 0 ;
00372     nim->slice_end = nim->nz - 1;
00373     nim->toffset =  DSET_TIMEORIGIN(dset);
00374 
00375     /*-- this bit assumes that afni slice timing offsets  *
00376      *-- are created starting from zero and including all *
00377      *-- slices initially.  They may later be modified by *
00378      *-- zero padding at either end.  No other            *
00379      *-- modifications are intentionally accepted right now. */
00380 
00381     if (DSET_NUM_TTOFF(dset) > 0 ) { /* if time offset exists */
00382 
00383       /*-- Find first and last non-zero element */
00384 #define MYEPSILON 0.00001
00385 #define MYFPEQ(a, b) (fabs((a) - (b)) < MYEPSILON)
00386 
00387       for (ii = 0 ; ii < nim->nz ; ii++ ) {
00388         if (!MYFPEQ(dset->taxis->toff_sl[ii],0.0)) break ;
00389       }
00390       sfirst = ii ;
00391       for (ii = nim->nz - 1 ; ii >= sfirst ; ii-- ) {
00392         if (!MYFPEQ(dset->taxis->toff_sl[ii],0.0)) break ;
00393       }
00394       slast = ii ;
00395 
00396       if (slast == sfirst) {
00397         /* only zero or one non-zero elements  */
00398         pattern_unknown = 1 ;
00399       } else { /* if there is more than one non-zero slice time */
00400 
00401       /*-- Calc deltas between offsets in above range.     */
00402       /*-- Special case for only two elements!!!!!!!!!!!!!!*/
00403 
00404         if ( slast - sfirst == 1 ) {
00405           if (dset->taxis->toff_sl[slast] > dset->taxis->toff_sl[sfirst] ) {
00406             nim->slice_code = NIFTI_SLICE_SEQ_INC ;
00407           } else {
00408             nim->slice_code = NIFTI_SLICE_SEQ_DEC ;
00409           }
00410         } else { /* if there are more than two slice timing offsets */
00411 
00412       /*-- While storing in two variables, delta_even and  *
00413        *-- delta_odd, check to see if all evens are equal  *
00414        *-- and all odds are equal. Fail if not.            */
00415 
00416           odd_del = dset->taxis->toff_sl[sfirst +  1] -
00417                             dset->taxis->toff_sl[sfirst] ;
00418           even_del = dset->taxis->toff_sl[sfirst +  2] -
00419                        dset->taxis->toff_sl[sfirst +  1];
00420           for (ii = sfirst + 2 ; ii < slast - 1 ; ii += 2 ) {
00421             if (MYFPEQ(odd_del, dset->taxis->toff_sl[ii + 1] - dset->taxis->toff_sl[ii])) {
00422               if (MYFPEQ(even_del, dset->taxis->toff_sl[ii +  2] - dset->taxis->toff_sl[ii +  1])) {
00423                 continue;
00424               }
00425             }
00426             pattern_unknown = 1 ;
00427             break ;
00428           }
00429 
00430           if (ii == slast - 1 ) {
00431             if (!MYFPEQ(odd_del, dset->taxis->toff_sl[ii + 1] - dset->taxis->toff_sl[ii])) {
00432               pattern_unknown = 1 ;
00433             }
00434           } else {
00435             tmp_float = (dset->taxis->toff_sl[ii] - dset->taxis->toff_sl[ii - 1]) / odd_del ;
00436             even_parity_sign = tmp_float / fabs (tmp_float) ;
00437           }
00438 
00439       /*-- If evens equal odds, it's NIFTI_SLICE_SEQ_INC (if *
00440        *-- positive) or NIFTI_SLICE_SEQ_DEC (if negative)    */
00441           if (!pattern_unknown ) {
00442             if (MYFPEQ(odd_del, even_del)) {
00443               if (odd_del > 0) nim->slice_code = NIFTI_SLICE_SEQ_INC ;
00444                 else nim->slice_code = NIFTI_SLICE_SEQ_INC ;
00445             } else {
00446 
00447       /*-- Else if they ARE of opposite sign, then the           *
00448        *-- order is NIFTI_SLICE_ALT_INC if the sum of delta_odd  *
00449        *-- and delta_even is positive, and NIFTI_SLICE_ALT_DEC   *
00450        *-- if negative.                                          */
00451 
00452               if ((odd_del * even_del < 0 ) && (even_parity_sign != -1)) {
00453                 if (odd_del + even_del > 0 ) {
00454                   nim->slice_code = NIFTI_SLICE_ALT_INC ;
00455                 } else {
00456                   if (odd_del + even_del < 0 ) {
00457                     nim->slice_code = NIFTI_SLICE_ALT_DEC ;
00458                   } else {
00459                     pattern_unknown = 1 ;
00460                   }
00461                 }
00462               } else {
00463                 pattern_unknown = 1 ;
00464               }
00465             }
00466           }
00467         } /* if there are more than two slice timing offsets */
00468       } /* if there is more than one non-zero slice time */
00469     } else { /* time offset not exists */
00470       pattern_unknown = 1 ;
00471     }
00472 
00473   /*-- Now store slice_start and slice_end from the position *
00474    *-- of the first and last non-zero elements above.  IFF   *
00475    *-- we have removed at least one zero from the beginning  *
00476    *-- of an INC order or the end of a DEC order, then       *
00477    *-- shift slice_start or slice end to add exactly one zero*
00478    *-- back to the appropriate end.                          */
00479   /*-- If we've done all of this, we might as well populate  *
00480    *-- slice_duration as well.  It is the absolute value of  *
00481    *-- the delta for the sequential cases, or the sum of the *
00482    *-- two deltas for the alternating cases.                 */
00483 
00484     if (!pattern_unknown ) {
00485       switch (nim->slice_code) {
00486         case NIFTI_SLICE_SEQ_INC:
00487           nim->slice_duration = odd_del ;
00488           if (sfirst > 0) sfirst-- ;
00489           break ;
00490         case NIFTI_SLICE_ALT_INC:
00491           nim->slice_duration = fabs (odd_del + even_del ) ;
00492           if (sfirst > 0) sfirst-- ;
00493           break ;
00494         case NIFTI_SLICE_SEQ_DEC:
00495           nim->slice_duration = fabs (odd_del) ;
00496           if (slast < nim->nz - 1) slast++ ;
00497           break ;
00498         case NIFTI_SLICE_ALT_DEC:
00499           nim->slice_duration = fabs (odd_del + even_del ) ;
00500           if (slast < nim->nz - 1) slast++ ;
00501           break ;
00502         default: /* sanity check */
00503           fprintf(stderr,
00504           "++ ERROR: CANNOT WRITE NIFTI FILE; LOGIC BORKED IN SLICE TIMING\n") ;
00505           fprintf(stderr, "RICH HAMMETT SHOULD FIX THIS REAL SOON NOW\n") ;
00506           RETURN(0);
00507       }
00508 
00509       nim->slice_start = sfirst ;
00510       nim->slice_end = slast ;
00511 
00512     } else {
00513       nim->slice_code = NIFTI_SLICE_UNKNOWN ;
00514       nim->slice_start = 0 ;
00515       nim->slice_end = 0 ;
00516     } /* end the if !pattern_unknown final assignment section */
00517 
00518     nim->time_units = NIFTI_UNITS_SEC ;
00519 
00520   } else { /* if time axis not exists */
00521     nim->slice_dim = 0 ;
00522     nim->time_units = NIFTI_UNITS_UNKNOWN ;
00523   }
00524 
00525   /*-- byte order --*/
00526 
00527   nim->byteorder = nifti_short_order() ;
00528 
00529   /* KRH 7/25/05 modified to note talairach view into NIfTI file */
00530 
00531   if ( dset->view_type == VIEW_TALAIRACH_TYPE ) {
00532     nim->qform_code = NIFTI_XFORM_TALAIRACH ;
00533   } else {
00534     nim->qform_code = NIFTI_XFORM_SCANNER_ANAT ;
00535   }
00536   nim->sform_code = nim->qform_code ; /* KRH 7/6/05 - using */
00537            /* sform to duplicate qform for interoperability with FSL */
00538 
00539 
00540   /*-- odds and ends that are constant for AFNI files --*/
00541   nim->cal_min = nim->cal_max = 0 ;
00542   nim->nifti_type = 1 ;
00543   nim->xyz_units = NIFTI_UNITS_MM ;
00544   nim->num_ext = 0;
00545   nim->ext_list = NULL ;
00546   nim->iname_offset = 352 ; /* until extensions are added */
00547   nim->data = NULL ;
00548 
00549   RETURN(nim) ;
00550 }
00551 
00552 /*-------------------------------------------------------------------*/
00553 /*! List of dataset attributes NOT to save in a NIfTI-1.1 file. -----*/
00554 
00555 static char *badlist[] = {
00556      "IDCODE_STRING"      ,   /* this goes in the NI_group header */
00557      "DATASET_RANK"       ,
00558      "DATASET_DIMENSIONS" ,
00559      "TYPESTRING"         ,
00560      "SCENE_DATA"         ,
00561      "ORIENT_SPECIFIC"    ,
00562      "ORIGIN"             ,
00563      "DELTA"              ,
00564      "TAXIS_NUMS"         ,
00565      "TAXIS_FLOATS"       ,
00566      "TAXIS_OFFSETS"      ,
00567      "BYTEORDER_STRING"   ,
00568      "BRICK_TYPES"        ,
00569      "BRICK_FLOAT_FACS"   ,
00570      "STAT_AUX"           ,
00571      "LABEL_1"            ,
00572      "LABEL_2"            ,
00573      "DATASET_NAME"       ,
00574  NULL } ;
00575 
00576 /*-------------------------------------------------------------------*/
00577 /*! Create the AFNI extension string for a NIfTI-1.1 file, and insert
00578     this metadata into the nifti_image struct for output to disk.
00579     - If something bad happens, fails silently
00580     - 09 May 2005 - RWCox
00581 ---------------------------------------------------------------------*/
00582 
00583 void nifti_set_afni_extension( THD_3dim_dataset *dset , nifti_image *nim )
00584 {
00585    THD_datablock *blk ;
00586    NI_group      *ngr ;
00587    NI_element    *nel ;
00588    NI_stream      ns  ;
00589    char *rhs , buf[128] ;
00590    int ii,bb , npart,*bpart ;
00591 
00592    if( nim == NULL                     ) return ;  /* stupid or evil caller */
00593    if( AFNI_yesenv("AFNI_NIFTI_NOEXT") ) return ;  /* not allowed */
00594 
00595    /** write all dataset 'attributes' into a NIML group */
00596 
00597    ngr = THD_nimlize_dsetatr( dset ) ;
00598    if( ngr == NULL ) return ;            /* bad */
00599    NI_rename_group( ngr , "AFNI_attributes" ) ;
00600 
00601    /* 12 May 2005: add a signature to check the file on input to AFNI */
00602 
00603    sprintf(buf,"%d,%d,%d,%d,%d,%d" ,
00604            nim->nx, nim->ny, nim->nz, nim->nt, nim->nu, nim->datatype ) ;
00605    NI_set_attribute( ngr , "NIfTI_nums" , buf ) ;
00606 
00607    /** now, scan attribute elements in the group, and mark some
00608        of them as being useless or redundant in the NIfTI world **/
00609 
00610    npart = ngr->part_num ;
00611    bpart = (int *)calloc(sizeof(int),npart) ;
00612    for( ii=0 ; ii < npart ; ii++ ){
00613      if( ngr->part_typ[ii] != NI_ELEMENT_TYPE ) continue ;
00614      nel = (NI_element *) ngr->part[ii] ;
00615      if( strcmp(nel->name,"AFNI_atr") != 0 )    continue ;
00616      rhs = NI_get_attribute( nel , "AFNI_name" ) ;
00617      if( rhs == NULL )                          continue ;
00618 
00619      for( bb=0 ; badlist[bb] != NULL ; bb++ )
00620        if( strcmp(rhs,badlist[bb]) == 0 ){ bpart[ii] = 1; break; }
00621    }
00622 
00623    /** remove marked attributes from the NIML group **/
00624 
00625    for( ii=npart-1 ; ii >= 0 ; ii-- ){
00626      if( bpart[ii] )
00627        NI_remove_from_group( ngr , ngr->part[ii] ) ;
00628    }
00629    free((void *)bpart) ;  /* done with this */
00630    if( ngr->part_num <= 0 ){ NI_free_element(ngr); return; }
00631 
00632    /** format into a character string to put in the NIfTI-1.1 extension **/
00633 
00634    ns = NI_stream_open( "str:" , "w" ) ;
00635    NI_stream_writestring( ns , "<?xml version='1.0' ?>\n" ) ;
00636    NI_write_element( ns , ngr , NI_TEXT_MODE ) ;
00637    rhs = NI_stream_getbuf( ns ) ;
00638 
00639    /** write contents of the string into the nifti_image struct **/
00640 
00641    nifti_add_extension( nim , rhs , strlen(rhs)+1 , NIFTI_ECODE_AFNI ) ;
00642 
00643    NI_stream_close(ns) ;   /* frees the string buffer, too */
00644    NI_free_element(ngr) ;  /* done with this trashola */
00645    return ;
00646 }
 

Powered by Plone

This site conforms to the following standards: