int SUMA_ShortizeDset(THD_3dim_dataset **dsetp, float thisfac) { static char FuncName[]={"SUMA_ShortizeDset"}; char sprefix[THD_MAX_PREFIX+10]; int i, j; byte *bb=NULL; short *sb=NULL; float bbf=0.0; THD_3dim_dataset *cpset=NULL, *dset=*dsetp; SUMA_ENTRY; if (!dset) { SUMA_S_Err("NULL *dsetp at input!"); SUMA_RETURN(0); } sprintf(sprefix, "%s.s", dset->dblk->diskptr->prefix); NEW_SHORTY(dset, DSET_NVALS(dset), "ss.cp", cpset); for (i=0; i<DSET_NVALS(dset); ++i) { if (DSET_BRICK_TYPE(dset,i) == MRI_byte) { bb = (byte *)DSET_ARRAY(dset,i); sb = (short *)DSET_ARRAY(cpset,i); if (thisfac <= 0.0) { for (j=0; j<DSET_NVOX(dset); ++j) { sb[j] = (short)bb[j]; } thisfac = DSET_BRICK_FACTOR(dset,i); } else { bbf = DSET_BRICK_FACTOR(dset,i); if (bbf == 0.0f) bbf = 1.0; bbf = bbf/thisfac; for (j=0; j<DSET_NVOX(dset); ++j) { sb[j] = SHORTIZE((((float)bb[j])*bbf)); } } EDIT_BRICK_FACTOR( cpset,i,thisfac ) ; } else { EDIT_substscale_brick(cpset, i, DSET_BRICK_TYPE(dset,i), DSET_ARRAY(dset,i), MRI_short, thisfac); if (DSET_BRICK_TYPE(dset,i) != MRI_short) { DSET_FREE_ARRAY(dset, i); } else { DSET_NULL_ARRAY(dset, i); } } } /* preserve tables, if any */ THD_copy_labeltable_atr( cpset->dblk, dset->dblk); DSET_delete(dset); dset = NULL; *dsetp=cpset; SUMA_RETURN(1); }
float THD_get_float_value( int ind , int ival , THD_3dim_dataset *dset ) { MRI_TYPE typ ; float val=0.0f ; if( ind < 0 || ival < 0 || !ISVALID_DSET(dset) || ival >= DSET_NVALS(dset) || ind >= DSET_NVOX(dset) ) return val ; typ = DSET_BRICK_TYPE(dset,ival) ; /* raw data type */ switch( typ ){ default: /* don't know what to do --> return nada */ return(-1); break ; case MRI_byte:{ byte *bar ; bar = (byte *) DSET_ARRAY(dset,ival) ; if( bar != NULL ) val = (float)bar[ind] ; } break ; case MRI_short:{ short *bar ; bar = (short *) DSET_ARRAY(dset,ival) ; if( bar != NULL ) val = (float)bar[ind] ; } break ; case MRI_float:{ float *bar ; bar = (float *) DSET_ARRAY(dset,ival) ; if( bar != NULL ) val = bar[ind] ; } break ; case MRI_complex:{ complex *bar ; bar = (complex *) DSET_ARRAY(dset,ival) ; if( bar != NULL ) val = CABS(bar[ind]) ; } break ; } if( DSET_BRICK_FACTOR(dset,ival) > 0.0f ) val *= DSET_BRICK_FACTOR(dset,ival) ; return val ; }
/*---------------------------------------------------------------------- ** ** Subtract hemispheres. ** ** Check if we need to create or change the factor. ** **---------------------------------------------------------------------- */ static char * process_data( THD_3dim_dataset * dset, hemi_s * hs ) { int count, nx, ny, nz, cx, cx2; int type, diff, floats = ( DSET_BRICK_FACTOR( dset, 0 ) != 0.0 ); short * data, * sp, * sp2; nx = dset->daxes->nxx; ny = dset->daxes->nyy; nz = dset->daxes->nzz; type = hs->thresh_type; data = (short *)DSET_ARRAY( dset, 0 ); for ( count = 0; ! floats && count < ny*nz; count++ ) { sp = data; sp2 = data + nx - 1; for ( cx = 0; cx < (nx+1)/2; cx++ ) { if ( type == 1 ) /* positives only */ { if ( *sp < 0 ) *sp = 0; if ( *sp2 < 0 ) *sp2 = 0; } else if ( type == 2 ) /* negatives only */ { if ( *sp > 0 ) *sp = 0; if ( *sp2 > 0 ) *sp2 = 0; } diff = *sp - *sp2; /* if out of short range */ if ( ( diff > 32767 ) || ( diff < -32768 ) ) floats = 1; else { *sp = diff; *sp2 = -diff; } sp++; sp2--; } data += nx; } if ( floats ) return process_as_floats( dset, hs ); return NULL; /* success */ }
int is_integral_sub_brick ( THD_3dim_dataset *dset, int isb, int check_values) { float mfac = 0.0; void *vv=NULL; if( !ISVALID_DSET(dset) || isb < 0 || isb >= DSET_NVALS(dset) ) { fprintf(stderr,"** Bad dset or sub-brick index.\n"); return (0) ; } if( !DSET_LOADED(dset) ) DSET_load(dset); switch( DSET_BRICK_TYPE(dset,isb) ){ case MRI_short: case MRI_byte: if (check_values) { mfac = DSET_BRICK_FACTOR(dset,isb) ; if (mfac != 0.0f && mfac != 1.0f) return(0); } break; case MRI_double: case MRI_complex: case MRI_float: vv = (void *)DSET_ARRAY(dset,isb); mfac = DSET_BRICK_FACTOR(dset,isb) ; if (mfac != 0.0f && mfac != 1.0f) return(0); if (!vv) { fprintf(stderr,"** NULL array!\n"); return(0); } return(is_integral_data(DSET_NVOX(dset), DSET_BRICK_TYPE(dset,isb), DSET_ARRAY(dset,isb) ) ); break; default: return(0); } return(1); }
void THD_load_tcat( THD_datablock *dblk ) { int ivout , dd , iv ; THD_3dim_dataset *dset_in , *dset_out ; NI_str_array *sar ; ENTRY("THD_load_tcat") ; if( !ISVALID_DBLK(dblk) ) EXRETURN ; dset_out = (THD_3dim_dataset *)dblk->parent ; if( !ISVALID_DSET(dset_out) ) EXRETURN ; sar = NI_decode_string_list( dset_out->tcat_list , "~" ) ; if( sar == NULL ) EXRETURN ; if( sar->num != dset_out->tcat_num ){ NI_delete_str_array(sar); EXRETURN; } ivout = 0 ; for( dd=0 ; dd < sar->num ; dd++ ){ dset_in = THD_open_dataset( sar->str[dd] ) ; if( dset_in == NULL ){ NI_delete_str_array(sar) ; DSET_unload(dset_out) ; EXRETURN ; } DSET_mallocize(dset_in) ; DSET_load(dset_in) ; if( !DSET_LOADED(dset_in) ){ NI_delete_str_array(sar) ; DSET_unload(dset_out) ; DSET_delete(dset_in) ; EXRETURN ; } for( iv=0 ; iv < DSET_NVALS(dset_in) ; iv++ ){ EDIT_substitute_brick( dset_out , ivout , DSET_BRICK_TYPE(dset_in,iv), DSET_ARRAY(dset_in,iv) ); mri_fix_data_pointer( NULL , DSET_BRICK(dset_in,iv) ) ; EDIT_BRICK_FACTOR( dset_out , ivout , DSET_BRICK_FACTOR(dset_in,iv) ) ; EDIT_BRICK_LABEL(dset_out, ivout, DSET_BRICK_LABEL(dset_in, iv)); /* ZSS Aug. 27 2012 */ ivout++ ; } DSET_delete(dset_in) ; } NI_delete_str_array(sar) ; EXRETURN ; }
MRI_IMAGE * FD_brick_to_series( int ixyz , FD_brick *br ) { MRI_IMAGE *im ; /* output */ int nv , ival ; char *iar ; /* brick in the input */ MRI_TYPE typ ; int ix,jy,kz , ind ; THD_ivec3 ind_fd , ind_ds ; if( ixyz < 0 || ixyz >= br->n1 * br->n2 * br->n3 ) return NULL ; /** otherwise, get ready for a real image **/ ix = ixyz % br->n1 ; jy = ( ixyz % (br->n1 * br->n2) ) / br->n1 ; kz = ixyz / (br->n1 * br->n2) ; LOAD_IVEC3( ind_fd , ix,jy,kz ) ; ind_ds = THD_fdind_to_3dind( br , ind_fd ) ; ix = ind_ds.ijk[0] ; jy = ind_ds.ijk[1] ; kz = ind_ds.ijk[2] ; ind = (kz * br->dset->daxes->nyy + jy) * br->dset->daxes->nxx + ix ; nv = br->dset->dblk->nvals ; iar = DSET_ARRAY(br->dset,0) ; if( iar == NULL ){ /* if data needs to be loaded from disk */ (void) THD_load_datablock( br->dset->dblk ) ; iar = DSET_ARRAY(br->dset,0) ; if( iar == NULL ) return NULL ; } /* 15 Sep 2004: allow for nonconstant datum */ if( !DSET_datum_constant(br->dset) ){ /* only for stupid users */ float *ar ; im = mri_new( nv , 1 , MRI_float ) ; ar = MRI_FLOAT_PTR(im) ; for( ival = 0 ; ival < nv ; ival++ ) ar[ival] = THD_get_voxel( br->dset , ind , ival ) ; goto image_done ; } /* the older (more efficient) way */ typ = DSET_BRICK_TYPE(br->dset,0) ; im = mri_new( nv , 1 , typ ) ; #if 0 mri_zero_image(im) ; /* 18 Oct 2001 */ #endif switch( typ ){ default: /* don't know what to do --> return nada */ mri_free( im ) ; return NULL ; case MRI_byte:{ byte *ar = MRI_BYTE_PTR(im) , *bar ; for( ival=0 ; ival < nv ; ival++ ){ bar = (byte *) DSET_ARRAY(br->dset,ival) ; if( bar != NULL ) ar[ival] = bar[ind] ; } } break ; case MRI_short:{ short *ar = MRI_SHORT_PTR(im) , *bar ; for( ival=0 ; ival < nv ; ival++ ){ bar = (short *) DSET_ARRAY(br->dset,ival) ; if( bar != NULL ) ar[ival] = bar[ind] ; } } break ; case MRI_float:{ float *ar = MRI_FLOAT_PTR(im) , *bar ; for( ival=0 ; ival < nv ; ival++ ){ bar = (float *) DSET_ARRAY(br->dset,ival) ; if( bar != NULL ) ar[ival] = bar[ind] ; } } break ; case MRI_int:{ int *ar = MRI_INT_PTR(im) , *bar ; for( ival=0 ; ival < nv ; ival++ ){ bar = (int *) DSET_ARRAY(br->dset,ival) ; if( bar != NULL ) ar[ival] = bar[ind] ; } } break ; case MRI_double:{ double *ar = MRI_DOUBLE_PTR(im) , *bar ; for( ival=0 ; ival < nv ; ival++ ){ bar = (double *) DSET_ARRAY(br->dset,ival) ; if( bar != NULL ) ar[ival] = bar[ind] ; } } break ; case MRI_complex:{ complex *ar = MRI_COMPLEX_PTR(im) , *bar ; for( ival=0 ; ival < nv ; ival++ ){ bar = (complex *) DSET_ARRAY(br->dset,ival) ; if( bar != NULL ) ar[ival] = bar[ind] ; } } break ; /* 15 Apr 2002: RGB types */ case MRI_rgb:{ rgbyte *ar = (rgbyte *) MRI_RGB_PTR(im) , *bar ; for( ival=0 ; ival < nv ; ival++ ){ bar = (rgbyte *) DSET_ARRAY(br->dset,ival) ; if( bar != NULL ) ar[ival] = bar[ind] ; } } break ; case MRI_rgba:{ rgba *ar = (rgba *) MRI_RGBA_PTR(im) , *bar ; for( ival=0 ; ival < nv ; ival++ ){ bar = (rgba *) DSET_ARRAY(br->dset,ival) ; if( bar != NULL ) ar[ival] = bar[ind] ; } } break ; } if( THD_need_brick_factor(br->dset) ){ MRI_IMAGE *qim ; qim = mri_mult_to_float( br->dset->dblk->brick_fac , im ) ; mri_free(im) ; im = qim ; } /* at this point, the image is ready to ship out; but first, maybe attach a time origin and spacing */ image_done: if( br->dset->taxis != NULL ){ /* 21 Oct 1996 */ float zz , tt ; zz = br->dset->daxes->zzorg + kz * br->dset->daxes->zzdel ; tt = THD_timeof( 0 , zz , br->dset->taxis ) ; im->xo = tt ; im->dx = br->dset->taxis->ttdel ; /* origin and delta */ if( br->dset->taxis->units_type == UNITS_MSEC_TYPE ){ /* convert to sec */ im->xo *= 0.001 ; im->dx *= 0.001 ; } } else { im->xo = 0.0 ; im->dx = 1.0 ; /* 08 Nov 1996 */ } return im ; }
/*! contains code shamelessly stolen from Rick who stole it from Bob. */ SUMA_Boolean SUMA_Get_isosurface_datasets ( SUMA_GENERIC_PROG_OPTIONS_STRUCT * Opt) { static char FuncName[]={"SUMA_Get_isosurface_datasets"}; int i; SUMA_Boolean LocalHead = NOPE; SUMA_ENTRY; if (!Opt->in_vol && !Opt->in_name) { SUMA_S_Err("NULL input"); SUMA_RETURN(NOPE); } if (!Opt->in_vol) { /* open it */ Opt->in_vol = THD_open_dataset( Opt->in_name ); } if (!Opt->in_vol) { SUMA_S_Err("No volume could be had"); SUMA_RETURN(NOPE); } if (!ISVALID_DSET(Opt->in_vol)) { if (!Opt->in_name) { SUMA_SL_Err("NULL input volume."); SUMA_RETURN(NOPE); } else { SUMA_SL_Err("invalid volume."); SUMA_RETURN(NOPE); } } else if ( DSET_BRICK_TYPE(Opt->in_vol, 0) == MRI_complex) { SUMA_SL_Err("Can't do complex data."); SUMA_RETURN(NOPE); } Opt->nvox = DSET_NVOX( Opt->in_vol ); if (DSET_NVALS( Opt->in_vol) != 1) { SUMA_SL_Err("Input volume can only have one sub-brick in it.\n" "Use [.] selectors to choose sub-brick needed."); SUMA_RETURN(NOPE); } Opt->mcdatav = (double *)SUMA_malloc(sizeof(double)*Opt->nvox); if (!Opt->mcdatav) { SUMA_SL_Crit("Failed to allocate for maskv"); SUMA_RETURN(NOPE); } if (Opt->xform == SUMA_ISO_XFORM_MASK) { SUMA_LH("SUMA_ISO_XFORM_MASK"); switch (Opt->MaskMode) { case SUMA_ISO_CMASK: SUMA_LH("SUMA_ISO_CMASK"); if (Opt->cmask) { /* here's the second order grand theft */ int clen = strlen( Opt->cmask ); char * cmd; byte *bmask; cmd = (char *)malloc((clen + 1) * sizeof(char)); strcpy( cmd, Opt->cmask); bmask = EDT_calcmask( cmd, &Opt->ninmask, 0 ); SUMA_LHv("Have %d\n", Opt->ninmask); free( cmd ); /* free EDT_calcmask() string */ if ( bmask == NULL ) { SUMA_SL_Err("Failed to compute mask from -cmask option"); SUMA_free(Opt->mcdatav); Opt->mcdatav=NULL; SUMA_RETURN(NOPE); } if ( Opt->ninmask != Opt->nvox ) { SUMA_SL_Err("Input and cmask datasets do not have " "the same dimensions\n" ); SUMA_free(Opt->mcdatav); Opt->mcdatav=NULL; SUMA_RETURN(NOPE); } Opt->ninmask = THD_countmask( Opt->ninmask, bmask ); SUMA_LHv("Have %d\n", Opt->ninmask); for (i=0; i<Opt->nvox; ++i) if (bmask[i]) Opt->mcdatav[i] = (double)bmask[i]; else Opt->mcdatav[i] = -1; free(bmask);bmask=NULL; } else { SUMA_SL_Err("NULL cmask"); SUMA_RETURN(NOPE); } break; case SUMA_ISO_VAL: case SUMA_ISO_RANGE: SUMA_LH("SUMA_ISO_VAL, SUMA_ISO_RANGE"); /* load the dset */ DSET_load(Opt->in_vol); Opt->dvec = (double *)SUMA_malloc(sizeof(double) * Opt->nvox); if (!Opt->dvec) { SUMA_SL_Crit("Faile to allocate for dvec.\nOh misery."); SUMA_RETURN(NOPE); } EDIT_coerce_scale_type( Opt->nvox , DSET_BRICK_FACTOR(Opt->in_vol,0) , DSET_BRICK_TYPE(Opt->in_vol,0), DSET_ARRAY(Opt->in_vol, 0) , MRI_double , Opt->dvec ) ; /* no need for data in input volume anymore */ PURGE_DSET(Opt->in_vol); Opt->ninmask = 0; if (Opt->MaskMode == SUMA_ISO_VAL) { for (i=0; i<Opt->nvox; ++i) { if (Opt->dvec[i] == Opt->v0) { Opt->mcdatav[i] = 1; ++ Opt->ninmask; } else Opt->mcdatav[i] = -1; } } else if (Opt->MaskMode == SUMA_ISO_RANGE) { for (i=0; i<Opt->nvox; ++i) { if (Opt->dvec[i] >= Opt->v0 && Opt->dvec[i] < Opt->v1) { Opt->mcdatav[i] = 1; ++ Opt->ninmask; } else Opt->mcdatav[i] = -1; } } else { SUMA_SL_Err("Bad Miracle."); SUMA_RETURN(NOPE); } SUMA_free(Opt->dvec); Opt->dvec = NULL; /* this vector is not even created in SUMA_ISO_CMASK mode ...*/ break; default: SUMA_SL_Err("Unexpected value of MaskMode"); SUMA_RETURN(NOPE); break; } } else if (Opt->xform == SUMA_ISO_XFORM_SHIFT) { /* load the dset */ DSET_load(Opt->in_vol); Opt->dvec = (double *)SUMA_malloc(sizeof(double) * Opt->nvox); if (!Opt->dvec) { SUMA_SL_Crit("Failed to allocate for dvec.\nOh misery."); SUMA_RETURN(NOPE); } EDIT_coerce_scale_type( Opt->nvox , DSET_BRICK_FACTOR(Opt->in_vol,0) , DSET_BRICK_TYPE(Opt->in_vol,0), DSET_ARRAY(Opt->in_vol, 0) , MRI_double , Opt->dvec ) ; /* no need for data in input volume anymore */ PURGE_DSET(Opt->in_vol); Opt->ninmask = Opt->nvox; for (i=0; i<Opt->nvox; ++i) { Opt->mcdatav[i] = Opt->dvec[i] - Opt->v0; } SUMA_free(Opt->dvec); Opt->dvec = NULL; } else if (Opt->xform == SUMA_ISO_XFORM_NONE) { /* load the dset */ DSET_load(Opt->in_vol); Opt->dvec = (double *)SUMA_malloc(sizeof(double) * Opt->nvox); if (!Opt->dvec) { SUMA_SL_Crit("Faile to allocate for dvec.\nOh misery."); SUMA_RETURN(NOPE); } EDIT_coerce_scale_type( Opt->nvox , DSET_BRICK_FACTOR(Opt->in_vol,0) , DSET_BRICK_TYPE(Opt->in_vol,0), DSET_ARRAY(Opt->in_vol, 0) , MRI_double , Opt->dvec ) ; /* no need for data in input volume anymore */ PURGE_DSET(Opt->in_vol); Opt->ninmask = Opt->nvox; for (i=0; i<Opt->nvox; ++i) { Opt->mcdatav[i] = Opt->dvec[i]; } SUMA_free(Opt->dvec); Opt->dvec = NULL; } else { SUMA_SL_Err("Bad Opt->xform."); SUMA_RETURN(NOPE); } if ( Opt->ninmask <= 0 ) { if (Opt->ninmask == 0) { SUMA_SL_Err("A negative value!\nNothing to do." ); } else { SUMA_SL_Err("An empty mask!\n Nothing to do." ); } SUMA_RETURN(NOPE); } if (Opt->debug > 0) { fprintf( SUMA_STDERR, "%s:\nInput dset %s has nvox = %d, nvals = %d", FuncName, SUMA_CHECK_NULL_STR(Opt->in_name), Opt->nvox, DSET_NVALS(Opt->in_vol) ); fprintf( SUMA_STDERR, " (%d voxels in mask)\n", Opt->ninmask ); } SUMA_RETURN(YUP); }
int main( int argc , char *argv[] ) { THD_3dim_dataset *xset , *cset, *mset=NULL ; int nopt=1 , method=PEARSON , do_autoclip=0 ; int nvox , nvals , ii, jj, kout, kin, polort=1 ; int ix1,jy1,kz1, ix2, jy2, kz2 ; char *prefix = "degree_centrality" ; byte *mask=NULL; int nmask , abuc=1 ; int all_source=0; /* output all source voxels 25 Jun 2010 [rickr] */ char str[32] , *cpt ; int *imap = NULL ; MRI_vectim *xvectim ; float (*corfun)(int,float *,float*) = NULL ; /* djc - add 1d file output for similarity matrix */ FILE *fout1D=NULL; /* CC - we will have two subbricks: binary and weighted centrality */ int nsubbriks = 2; int subbrik = 0; float * bodset; float * wodset; int nb_ctr = 0; /* CC - added flags for thresholding correlations */ double thresh = 0.0; double othresh = 0.0; int dothresh = 0; double sparsity = 0.0; int dosparsity = 0; /* variables for calculating degree centrality */ long * binaryDC = NULL; double * weightedDC = NULL; /* variables for histogram */ hist_node_head* histogram=NULL; hist_node* hptr=NULL; hist_node* pptr=NULL; int bottom_node_idx = 0; int totNumCor = 0; long totPosCor = 0; int ngoal = 0; int nretain = 0; float binwidth = 0.0; int nhistnodes = 50; /*----*/ AFNI_SETUP_OMP(0) ; /* 24 Jun 2013 */ if( argc < 2 || strcmp(argv[1],"-help") == 0 ){ printf( "Usage: 3dDegreeCentrality [options] dset\n" " Computes voxelwise weighted and binary degree centrality and\n" " stores the result in a new 3D bucket dataset as floats to\n" " preserve their values. Degree centrality reflects the strength and\n" " extent of the correlation of a voxel with every other voxel in\n" " the brain.\n\n" " Conceptually the process involves: \n" " 1. Calculating the correlation between voxel time series for\n" " every pair of voxels in the brain (as determined by masking)\n" " 2. Applying a threshold to the resulting correlations to exclude\n" " those that might have arisen by chance, or to sparsify the\n" " connectivity graph.\n" " 3. At each voxel, summarizing its correlation with other voxels\n" " in the brain, by either counting the number of voxels correlated\n" " with the seed voxel (binary) or by summing the correlation \n" " coefficients (weighted).\n" " Practically the algorithm is ordered differently to optimize for\n" " computational time and memory usage.\n\n" " The threshold can be supplied as a correlation coefficient, \n" " or a sparsity threshold. The sparsity threshold reflects the fraction\n" " of connections that should be retained after the threshold has been\n" " applied. To minimize resource consumption, using a sparsity threshold\n" " involves a two-step procedure. In the first step, a correlation\n" " coefficient threshold is applied to substantially reduce the number\n" " of correlations. Next, the remaining correlations are sorted and a\n" " threshold is calculated so that only the specified fraction of \n" " possible correlations are above threshold. Due to ties between\n" " correlations, the fraction of correlations that pass the sparsity\n" " threshold might be slightly more than the number specified.\n\n" " Regardless of the thresholding procedure employed, negative \n" " correlations are excluded from the calculations.\n" "\n" "Options:\n" " -pearson = Correlation is the normal Pearson (product moment)\n" " correlation coefficient [default].\n" #if 0 " -spearman = Correlation is the Spearman (rank) correlation\n" " coefficient.\n" " -quadrant = Correlation is the quadrant correlation coefficient.\n" #else " -spearman AND -quadrant are disabled at this time :-(\n" #endif "\n" " -thresh r = exclude correlations <= r from calculations\n" " -sparsity s = only use top s percent of correlations in calculations\n" " s should be an integer between 0 and 100. Uses an\n" " an adaptive thresholding procedure to reduce memory.\n" " The speed of determining the adaptive threshold can\n" " be improved by specifying an initial threshold with\n" " the -thresh flag.\n" "\n" " -polort m = Remove polynomical trend of order 'm', for m=-1..3.\n" " [default is m=1; removal is by least squares].\n" " Using m=-1 means no detrending; this is only useful\n" " for data/information that has been pre-processed.\n" "\n" " -autoclip = Clip off low-intensity regions in the dataset,\n" " -automask = so that the correlation is only computed between\n" " high-intensity (presumably brain) voxels. The\n" " mask is determined the same way that 3dAutomask works.\n" "\n" " -mask mmm = Mask to define 'in-brain' voxels. Reducing the number\n" " the number of voxels included in the calculation will\n" " significantly speedup the calculation. Consider using\n" " a mask to constrain the calculations to the grey matter\n" " rather than the whole brain. This is also preferrable\n" " to using -autoclip or -automask.\n" "\n" " -prefix p = Save output into dataset with prefix 'p', this file will\n" " contain bricks for both 'weighted' or 'degree' centrality\n" " [default prefix is 'deg_centrality'].\n" "\n" " -out1D f = Save information about the above threshold correlations to\n" " 1D file 'f'. Each row of this file will contain:\n" " Voxel1 Voxel2 i1 j1 k1 i2 j2 k2 Corr\n" " Where voxel1 and voxel2 are the 1D indices of the pair of\n" " voxels, i j k correspond to their 3D coordinates, and Corr\n" " is the value of the correlation between the voxel time courses.\n" "\n" "Notes:\n" " * The output dataset is a bucket type of floats.\n" " * The program prints out an estimate of its memory used\n" " when it ends. It also prints out a progress 'meter'\n" " to keep you pacified.\n" "\n" "-- RWCox - 31 Jan 2002 and 16 Jul 2010\n" "-- Cameron Craddock - 26 Sept 2015 \n" ) ; PRINT_AFNI_OMP_USAGE("3dDegreeCentrality",NULL) ; PRINT_COMPILE_DATE ; exit(0) ; } mainENTRY("3dDegreeCentrality main"); machdep(); PRINT_VERSION("3dDegreeCentrality"); AFNI_logger("3dDegreeCentrality",argc,argv); /*-- option processing --*/ while( nopt < argc && argv[nopt][0] == '-' ){ if( strcmp(argv[nopt],"-time") == 0 ){ abuc = 0 ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-autoclip") == 0 || strcmp(argv[nopt],"-automask") == 0 ){ do_autoclip = 1 ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-mask") == 0 ){ mset = THD_open_dataset(argv[++nopt]); CHECK_OPEN_ERROR(mset,argv[nopt]); nopt++ ; continue ; } if( strcmp(argv[nopt],"-pearson") == 0 ){ method = PEARSON ; nopt++ ; continue ; } #if 0 if( strcmp(argv[nopt],"-spearman") == 0 ){ method = SPEARMAN ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-quadrant") == 0 ){ method = QUADRANT ; nopt++ ; continue ; } #endif if( strcmp(argv[nopt],"-eta2") == 0 ){ method = ETA2 ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-prefix") == 0 ){ prefix = strdup(argv[++nopt]) ; if( !THD_filename_ok(prefix) ){ ERROR_exit("Illegal value after -prefix!") ; } nopt++ ; continue ; } if( strcmp(argv[nopt],"-thresh") == 0 ){ double val = (double)strtod(argv[++nopt],&cpt) ; if( *cpt != '\0' || val >= 1.0 || val < 0.0 ){ ERROR_exit("Illegal value (%f) after -thresh!", val) ; } dothresh = 1; thresh = val ; othresh = val ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-sparsity") == 0 ){ double val = (double)strtod(argv[++nopt],&cpt) ; if( *cpt != '\0' || val > 100 || val <= 0 ){ ERROR_exit("Illegal value (%f) after -sparsity!", val) ; } if( val > 5.0 ) { WARNING_message("Sparsity %3.2f%% is large and will require alot of memory and time, consider using a smaller value. ", val); } dosparsity = 1 ; sparsity = val ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-polort") == 0 ){ int val = (int)strtod(argv[++nopt],&cpt) ; if( *cpt != '\0' || val < -1 || val > 3 ){ ERROR_exit("Illegal value after -polort!") ; } polort = val ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-mem_stat") == 0 ){ MEM_STAT = 1 ; nopt++ ; continue ; } if( strncmp(argv[nopt],"-mem_profile",8) == 0 ){ MEM_PROF = 1 ; nopt++ ; continue ; } /* check for 1d argument */ if ( strcmp(argv[nopt],"-out1D") == 0 ){ if (!(fout1D = fopen(argv[++nopt], "w"))) { ERROR_message("Failed to open %s for writing", argv[nopt]); exit(1); } nopt++ ; continue ; } ERROR_exit("Illegal option: %s",argv[nopt]) ; } /*-- open dataset, check for legality --*/ if( nopt >= argc ) ERROR_exit("Need a dataset on command line!?") ; xset = THD_open_dataset(argv[nopt]); CHECK_OPEN_ERROR(xset,argv[nopt]); if( DSET_NVALS(xset) < 3 ) ERROR_exit("Input dataset %s does not have 3 or more sub-bricks!",argv[nopt]) ; DSET_load(xset) ; CHECK_LOAD_ERROR(xset) ; /*-- compute mask array, if desired --*/ nvox = DSET_NVOX(xset) ; nvals = DSET_NVALS(xset) ; INC_MEM_STATS((nvox * nvals * sizeof(double)), "input dset"); PRINT_MEM_STATS("inset"); /* if a mask was specified make sure it is appropriate */ if( mset ){ if( DSET_NVOX(mset) != nvox ) ERROR_exit("Input and mask dataset differ in number of voxels!") ; mask = THD_makemask(mset, 0, 1.0, 0.0) ; /* update running memory statistics to reflect loading the image */ INC_MEM_STATS( mset->dblk->total_bytes, "mask dset" ); PRINT_MEM_STATS( "mset load" ); nmask = THD_countmask( nvox , mask ) ; INC_MEM_STATS( nmask * sizeof(byte), "mask array" ); PRINT_MEM_STATS( "mask" ); INFO_message("%d voxels in -mask dataset",nmask) ; if( nmask < 2 ) ERROR_exit("Only %d voxels in -mask, exiting...",nmask); /* update running memory statistics to reflect loading the image */ DEC_MEM_STATS( mset->dblk->total_bytes, "mask dset" ); DSET_unload(mset) ; PRINT_MEM_STATS( "mset unload" ); } /* if automasking is requested, handle that now */ else if( do_autoclip ){ mask = THD_automask( xset ) ; nmask = THD_countmask( nvox , mask ) ; INFO_message("%d voxels survive -autoclip",nmask) ; if( nmask < 2 ) ERROR_exit("Only %d voxels in -automask!",nmask); } /* otherwise we use all of the voxels in the image */ else { nmask = nvox ; INFO_message("computing for all %d voxels",nmask) ; } if( method == ETA2 && polort >= 0 ) WARNING_message("Polort for -eta2 should probably be -1..."); /* djc - 1d file out init */ if (fout1D != NULL) { /* define affine matrix */ mat44 affine_mat = xset->daxes->ijk_to_dicom; /* print command line statement */ fprintf(fout1D,"#Similarity matrix from command:\n#"); for(ii=0; ii<argc; ++ii) fprintf(fout1D,"%s ", argv[ii]); /* Print affine matrix */ fprintf(fout1D,"\n"); fprintf(fout1D,"#[ "); int mi, mj; for(mi = 0; mi < 4; mi++) { for(mj = 0; mj < 4; mj++) { fprintf(fout1D, "%.6f ", affine_mat.m[mi][mj]); } } fprintf(fout1D, "]\n"); /* Print image extents*/ THD_dataxes *xset_daxes = xset->daxes; fprintf(fout1D, "#Image dimensions:\n"); fprintf(fout1D, "#[%d, %d, %d]\n", xset_daxes->nxx, xset_daxes->nyy, xset_daxes->nzz); /* Similarity matrix headers */ fprintf(fout1D,"#Voxel1 Voxel2 i1 j1 k1 i2 j2 k2 Corr\n"); } /* CC calculate the total number of possible correlations, will be usefule down the road */ totPosCor = (.5*((float)nmask))*((float)(nmask-1)); /** For the case of Pearson correlation, we make sure the **/ /** data time series have their mean removed (polort >= 0) **/ /** and are normalized, so that correlation = dot product, **/ /** and we can use function zm_THD_pearson_corr for speed. **/ switch( method ){ default: case PEARSON: corfun = zm_THD_pearson_corr ; break ; case ETA2: corfun = my_THD_eta_squared ; break ; } /*-- create vectim from input dataset --*/ INFO_message("vectim-izing input dataset") ; /*-- CC added in mask to reduce the size of xvectim -- */ xvectim = THD_dset_to_vectim( xset , mask , 0 ) ; if( xvectim == NULL ) ERROR_exit("Can't create vectim?!") ; /*-- CC update our memory stats to reflect vectim -- */ INC_MEM_STATS((xvectim->nvec*sizeof(int)) + ((xvectim->nvec)*(xvectim->nvals))*sizeof(float) + sizeof(MRI_vectim), "vectim"); PRINT_MEM_STATS( "vectim" ); /*--- CC the vectim contains a mapping between voxel index and mask index, tap into that here to avoid duplicating memory usage ---*/ if( mask != NULL ) { imap = xvectim->ivec; /* --- CC free the mask */ DEC_MEM_STATS( nmask*sizeof(byte), "mask array" ); free(mask); mask=NULL; PRINT_MEM_STATS( "mask unload" ); } /* -- CC unloading the dataset to reduce memory usage ?? -- */ DEC_MEM_STATS((DSET_NVOX(xset) * DSET_NVALS(xset) * sizeof(double)), "input dset"); DSET_unload(xset) ; PRINT_MEM_STATS("inset unload"); /* -- CC configure detrending --*/ if( polort < 0 && method == PEARSON ){ polort = 0; WARNING_message("Pearson correlation always uses polort >= 0"); } if( polort >= 0 ){ for( ii=0 ; ii < xvectim->nvec ; ii++ ){ /* remove polynomial trend */ DETREND_polort(polort,nvals,VECTIM_PTR(xvectim,ii)) ; } } /* -- this procedure does not change time series that have zero variance -- */ if( method == PEARSON ) THD_vectim_normalize(xvectim) ; /* L2 norm = 1 */ /* -- CC create arrays to hold degree and weighted centrality while they are being calculated -- */ if( dosparsity == 0 ) { if( ( binaryDC = (long*)calloc( nmask, sizeof(long) )) == NULL ) { ERROR_message( "Could not allocate %d byte array for binary DC calculation\n", nmask*sizeof(long)); } /* -- update running memory estimate to reflect memory allocation */ INC_MEM_STATS( nmask*sizeof(long), "binary DC array" ); PRINT_MEM_STATS( "binaryDC" ); if( ( weightedDC = (double*)calloc( nmask, sizeof(double) )) == NULL ) { if (binaryDC){ free(binaryDC); binaryDC = NULL; } ERROR_message( "Could not allocate %d byte array for weighted DC calculation\n", nmask*sizeof(double)); } /* -- update running memory estimate to reflect memory allocation */ INC_MEM_STATS( nmask*sizeof(double), "weighted DC array" ); PRINT_MEM_STATS( "weightedDC" ); } /* -- CC if we are using a sparsity threshold, build a histogram to calculate the threshold */ if (dosparsity == 1) { /* make sure that there is a bin for correlation values that == 1.0 */ binwidth = (1.005-thresh)/nhistnodes; /* calculate the number of correlations we wish to retain */ ngoal = nretain = (int)(((double)totPosCor)*((double)sparsity) / 100.0); /* allocate memory for the histogram bins */ if(( histogram = (hist_node_head*)malloc(nhistnodes*sizeof(hist_node_head))) == NULL ) { /* if the allocation fails, free all memory and exit */ if (binaryDC){ free(binaryDC); binaryDC = NULL; } if (weightedDC){ free(weightedDC); weightedDC = NULL; } ERROR_message( "Could not allocate %d byte array for histogram\n", nhistnodes*sizeof(hist_node_head)); } else { /* -- update running memory estimate to reflect memory allocation */ INC_MEM_STATS( nhistnodes*sizeof(hist_node_head), "hist bins" ); PRINT_MEM_STATS( "hist1" ); } /* initialize history bins */ for( kout = 0; kout < nhistnodes; kout++ ) { histogram[ kout ].bin_low = thresh+kout*binwidth; histogram[ kout ].bin_high = histogram[ kout ].bin_low+binwidth; histogram[ kout ].nbin = 0; histogram[ kout ].nodes = NULL; /*INFO_message("Hist bin %d [%3.3f, %3.3f) [%d, %p]\n", kout, histogram[ kout ].bin_low, histogram[ kout ].bin_high, histogram[ kout ].nbin, histogram[ kout ].nodes );*/ } } /*-- tell the user what we are about to do --*/ if (dosparsity == 0 ) { INFO_message( "Calculating degree centrality with threshold = %f.\n", thresh); } else { INFO_message( "Calculating degree centrality with threshold = %f and sparsity = %3.2f%% (%d)\n", thresh, sparsity, nretain); } /*---------- loop over mask voxels, correlate ----------*/ AFNI_OMP_START ; #pragma omp parallel if( nmask > 999 ) { int lii,ljj,lin,lout,ithr,nthr,vstep,vii ; float *xsar , *ysar ; hist_node* new_node = NULL ; hist_node* tptr = NULL ; hist_node* rptr = NULL ; int new_node_idx = 0; double car = 0.0 ; /*-- get information about who we are --*/ #ifdef USE_OMP ithr = omp_get_thread_num() ; nthr = omp_get_num_threads() ; if( ithr == 0 ) INFO_message("%d OpenMP threads started",nthr) ; #else ithr = 0 ; nthr = 1 ; #endif /*-- For the progress tracker, we want to print out 50 numbers, figure out a number of loop iterations that will make this easy */ vstep = (int)( nmask / (nthr*50.0f) + 0.901f ) ; vii = 0 ; if((MEM_STAT==0) && (ithr == 0 )) fprintf(stderr,"Looping:") ; #pragma omp for schedule(static, 1) for( lout=0 ; lout < xvectim->nvec ; lout++ ){ /*----- outer voxel loop -----*/ if( ithr == 0 && vstep > 2 ) /* allow small dsets 16 Jun 2011 [rickr] */ { vii++ ; if( vii%vstep == vstep/2 && MEM_STAT == 0 ) vstep_print(); } /* get ref time series from this voxel */ xsar = VECTIM_PTR(xvectim,lout) ; /* try to make calculation more efficient by only calculating the unique correlations */ for( lin=(lout+1) ; lin < xvectim->nvec ; lin++ ){ /*----- inner loop over voxels -----*/ /* extract the voxel time series */ ysar = VECTIM_PTR(xvectim,lin) ; /* now correlate the time series */ car = (double)(corfun(nvals,xsar,ysar)) ; if ( car <= thresh ) { continue ; } /* update degree centrality values, hopefully the pragma will handle mutual exclusion */ #pragma omp critical(dataupdate) { /* if the correlation is less than threshold, ignore it */ if ( car > thresh ) { totNumCor += 1; if ( dosparsity == 0 ) { binaryDC[lout] += 1; binaryDC[lin] += 1; weightedDC[lout] += car; weightedDC[lin] += car; /* print correlation out to the 1D file */ if ( fout1D != NULL ) { /* determine the i,j,k coords */ ix1 = DSET_index_to_ix(xset,lii) ; jy1 = DSET_index_to_jy(xset,lii) ; kz1 = DSET_index_to_kz(xset,lii) ; ix2 = DSET_index_to_ix(xset,ljj) ; jy2 = DSET_index_to_jy(xset,ljj) ; kz2 = DSET_index_to_kz(xset,ljj) ; /* add source, dest, correlation to 1D file */ fprintf(fout1D, "%d %d %d %d %d %d %d %d %.6f\n", lii, ljj, ix1, jy1, kz1, ix2, jy2, kz2, car); } } else { /* determine the index in the histogram to add the node */ new_node_idx = (int)floor((double)(car-othresh)/(double)binwidth); if ((new_node_idx > nhistnodes) || (new_node_idx < bottom_node_idx)) { /* this error should indicate a programming error and should not happen */ WARNING_message("Node index %d is out of range [%d,%d)!",new_node_idx, bottom_node_idx, nhistnodes); } else { /* create a node to add to the histogram */ new_node = (hist_node*)calloc(1,sizeof(hist_node)); if( new_node == NULL ) { /* allocate memory for this node, rather than fiddling with error handling here, lets just move on */ WARNING_message("Could not allocate a new node!"); } else { /* populate histogram node */ new_node->i = lout; new_node->j = lin; new_node->corr = car; new_node->next = NULL; /* -- update running memory estimate to reflect memory allocation */ INC_MEM_STATS( sizeof(hist_node), "hist nodes" ); if ((totNumCor % (1024*1024)) == 0) PRINT_MEM_STATS( "hist nodes" ); /* populate histogram */ new_node->next = histogram[new_node_idx].nodes; histogram[new_node_idx].nodes = new_node; histogram[new_node_idx].nbin++; /* see if there are enough correlations in the histogram for the sparsity */ if ((totNumCor - histogram[bottom_node_idx].nbin) > nretain) { /* delete the list of nodes */ rptr = histogram[bottom_node_idx].nodes; while(rptr != NULL) { tptr = rptr; rptr = rptr->next; /* check that the ptr is not null before freeing it*/ if(tptr!= NULL) { DEC_MEM_STATS( sizeof(hist_node), "hist nodes" ); free(tptr); } } PRINT_MEM_STATS( "unloaded hist nodes - thresh increase" ); histogram[bottom_node_idx].nodes = NULL; totNumCor -= histogram[bottom_node_idx].nbin; histogram[bottom_node_idx].nbin=0; /* get the new threshold */ thresh = (double)histogram[++bottom_node_idx].bin_low; if(MEM_STAT == 1) INFO_message("Increasing threshold to %3.2f (%d)\n", thresh,bottom_node_idx); } } /* else, newptr != NULL */ } /* else, new_node_idx in range */ } /* else, do_sparsity == 1 */ } /* car > thresh */ } /* this is the end of the critical section */ } /* end of inner loop over voxels */ } /* end of outer loop over ref voxels */ if( ithr == 0 ) fprintf(stderr,".\n") ; } /* end OpenMP */ AFNI_OMP_END ; /* update the user so that they know what we are up to */ INFO_message ("AFNI_OMP finished\n"); INFO_message ("Found %d (%3.2f%%) correlations above threshold (%f)\n", totNumCor, 100.0*((float)totNumCor)/((float)totPosCor), thresh); /*---------- Finish up ---------*/ /*if( dosparsity == 1 ) { for( kout = 0; kout < nhistnodes; kout++ ) { INFO_message("Hist bin %d [%3.3f, %3.3f) [%d, %p]\n", kout, histogram[ kout ].bin_low, histogram[ kout ].bin_high, histogram[ kout ].nbin, histogram[ kout ].nodes ); } }*/ /*-- create output dataset --*/ cset = EDIT_empty_copy( xset ) ; /*-- configure the output dataset */ if( abuc ){ EDIT_dset_items( cset , ADN_prefix , prefix , ADN_nvals , nsubbriks , /* 2 subbricks, degree and weighted centrality */ ADN_ntt , 0 , /* no time axis */ ADN_type , HEAD_ANAT_TYPE , ADN_func_type , ANAT_BUCK_TYPE , ADN_datum_all , MRI_float , ADN_none ) ; } else { EDIT_dset_items( cset , ADN_prefix , prefix , ADN_nvals , nsubbriks , /* 2 subbricks, degree and weighted centrality */ ADN_ntt , nsubbriks , /* num times */ ADN_ttdel , 1.0 , /* fake TR */ ADN_nsl , 0 , /* no slice offsets */ ADN_type , HEAD_ANAT_TYPE , ADN_func_type , ANAT_EPI_TYPE , ADN_datum_all , MRI_float , ADN_none ) ; } /* add history information to the hearder */ tross_Make_History( "3dDegreeCentrality" , argc,argv , cset ) ; ININFO_message("creating output dataset in memory") ; /* -- Configure the subbriks: Binary Degree Centrality */ subbrik = 0; EDIT_BRICK_TO_NOSTAT(cset,subbrik) ; /* stat params */ /* CC this sets the subbrik scaling factor, which we will probably want to do again after we calculate the voxel values */ EDIT_BRICK_FACTOR(cset,subbrik,1.0) ; /* scale factor */ sprintf(str,"Binary Degree Centrality") ; EDIT_BRICK_LABEL(cset,subbrik,str) ; EDIT_substitute_brick(cset,subbrik,MRI_float,NULL) ; /* make array */ /* copy measure data into the subbrik */ bodset = DSET_ARRAY(cset,subbrik); /* -- Configure the subbriks: Weighted Degree Centrality */ subbrik = 1; EDIT_BRICK_TO_NOSTAT(cset,subbrik) ; /* stat params */ /* CC this sets the subbrik scaling factor, which we will probably want to do again after we calculate the voxel values */ EDIT_BRICK_FACTOR(cset,subbrik,1.0) ; /* scale factor */ sprintf(str,"Weighted Degree Centrality") ; EDIT_BRICK_LABEL(cset,subbrik,str) ; EDIT_substitute_brick(cset,subbrik,MRI_float,NULL) ; /* make array */ /* copy measure data into the subbrik */ wodset = DSET_ARRAY(cset,subbrik); /* increment memory stats */ INC_MEM_STATS( (DSET_NVOX(cset)*DSET_NVALS(cset)*sizeof(float)), "output dset"); PRINT_MEM_STATS( "outset" ); /* pull the values out of the histogram */ if( dosparsity == 0 ) { for( kout = 0; kout < nmask; kout++ ) { if ( imap != NULL ) { ii = imap[kout] ; /* ii= source voxel (we know that ii is in the mask) */ } else { ii = kout ; } if( ii >= DSET_NVOX(cset) ) { WARNING_message("Avoiding bodset, wodset overflow %d > %d (%s,%d)\n", ii,DSET_NVOX(cset),__FILE__,__LINE__ ); } else { bodset[ ii ] = (float)(binaryDC[kout]); wodset[ ii ] = (float)(weightedDC[kout]); } } /* we are done with this memory, and can kill it now*/ if(binaryDC) { free(binaryDC); binaryDC=NULL; /* -- update running memory estimate to reflect memory allocation */ DEC_MEM_STATS( nmask*sizeof(long), "binary DC array" ); PRINT_MEM_STATS( "binaryDC" ); } if(weightedDC) { free(weightedDC); weightedDC=NULL; /* -- update running memory estimate to reflect memory allocation */ DEC_MEM_STATS( nmask*sizeof(double), "weighted DC array" ); PRINT_MEM_STATS( "weightedDC" ); } } else { /* add in the values from the histogram, this is a two stage procedure: at first we add in values a whole bin at the time until we get to a point where we need to add in a partial bin, then we create a new histogram to sort the values in the bin and then add those bins at a time */ kout = nhistnodes - 1; while (( histogram[kout].nbin < nretain ) && ( kout >= 0 )) { hptr = pptr = histogram[kout].nodes; while( hptr != NULL ) { /* determine the indices corresponding to this node */ if ( imap != NULL ) { ii = imap[hptr->i] ; /* ii= source voxel (we know that ii is in the mask) */ } else { ii = hptr->i ; } if ( imap != NULL ) { jj = imap[hptr->j] ; /* ii= source voxel (we know that ii is in the mask) */ } else { jj = hptr->j ; } /* add in the values */ if(( ii >= DSET_NVOX(cset) ) || ( jj >= DSET_NVOX(cset))) { if( ii >= DSET_NVOX(cset)) { WARNING_message("Avoiding bodset, wodset overflow (ii) %d > %d\n (%s,%d)\n", ii,DSET_NVOX(cset),__FILE__,__LINE__ ); } if( jj >= DSET_NVOX(cset)) { WARNING_message("Avoiding bodset, wodset overflow (jj) %d > %d\n (%s,%d)\n", jj,DSET_NVOX(cset),__FILE__,__LINE__ ); } } else { bodset[ ii ] += 1.0 ; wodset[ ii ] += (float)(hptr->corr); bodset[ jj ] += 1.0 ; wodset[ jj ] += (float)(hptr->corr); } if( fout1D != NULL ) { /* add source, dest, correlation to 1D file */ ix1 = DSET_index_to_ix(cset,ii) ; jy1 = DSET_index_to_jy(cset,ii) ; kz1 = DSET_index_to_kz(cset,ii) ; ix2 = DSET_index_to_ix(cset,jj) ; jy2 = DSET_index_to_jy(cset,jj) ; kz2 = DSET_index_to_kz(cset,jj) ; fprintf(fout1D, "%d %d %d %d %d %d %d %d %.6f\n", ii, jj, ix1, jy1, kz1, ix2, jy2, kz2, (float)(hptr->corr)); } /* increment node pointers */ pptr = hptr; hptr = hptr->next; /* delete the node */ if(pptr) { /* -- update running memory estimate to reflect memory allocation */ DEC_MEM_STATS(sizeof( hist_node ), "hist nodes" ); /* free the mem */ free(pptr); pptr=NULL; } } /* decrement the number of correlations we wish to retain */ nretain -= histogram[kout].nbin; histogram[kout].nodes = NULL; /* go on to the next bin */ kout--; } PRINT_MEM_STATS( "hist1 bins free - inc into output" ); /* if we haven't used all of the correlations that are available, go through and add a subset of the voxels from the remaining bin */ if(( nretain > 0 ) && (kout >= 0)) { hist_node_head* histogram2 = NULL; hist_node_head* histogram2_save = NULL; int h2nbins = 100; float h2binwidth = 0.0; int h2ndx=0; h2binwidth = (((1.0+binwidth/((float)h2nbins))*histogram[kout].bin_high) - histogram[kout].bin_low) / ((float)h2nbins); /* allocate the bins */ if(( histogram2 = (hist_node_head*)malloc(h2nbins*sizeof(hist_node_head))) == NULL ) { if (binaryDC){ free(binaryDC); binaryDC = NULL; } if (weightedDC){ free(weightedDC); weightedDC = NULL; } if (histogram){ histogram = free_histogram(histogram, nhistnodes); } ERROR_message( "Could not allocate %d byte array for histogram2\n", h2nbins*sizeof(hist_node_head)); } else { /* -- update running memory estimate to reflect memory allocation */ histogram2_save = histogram2; INC_MEM_STATS(( h2nbins*sizeof(hist_node_head )), "hist bins"); PRINT_MEM_STATS( "hist2" ); } /* initiatize the bins */ for( kin = 0; kin < h2nbins; kin++ ) { histogram2[ kin ].bin_low = histogram[kout].bin_low + kin*h2binwidth; histogram2[ kin ].bin_high = histogram2[ kin ].bin_low + h2binwidth; histogram2[ kin ].nbin = 0; histogram2[ kin ].nodes = NULL; /*INFO_message("Hist2 bin %d [%3.3f, %3.3f) [%d, %p]\n", kin, histogram2[ kin ].bin_low, histogram2[ kin ].bin_high, histogram2[ kin ].nbin, histogram2[ kin ].nodes );*/ } /* move correlations from histogram to histgram2 */ INFO_message ("Adding %d nodes from histogram to histogram2",histogram[kout].nbin); while ( histogram[kout].nodes != NULL ) { hptr = histogram[kout].nodes; h2ndx = (int)floor((double)(hptr->corr - histogram[kout].bin_low)/(double)h2binwidth); if(( h2ndx < h2nbins ) && ( h2ndx >= 0 )) { histogram[kout].nodes = hptr->next; hptr->next = histogram2[h2ndx].nodes; histogram2[h2ndx].nodes = hptr; histogram2[h2ndx].nbin++; histogram[kout].nbin--; } else { WARNING_message("h2ndx %d is not in range [0,%d) :: %.10f,%.10f\n",h2ndx,h2nbins,hptr->corr, histogram[kout].bin_low); } } /* free the remainder of histogram */ { int nbins_rem = 0; for(ii = 0; ii < nhistnodes; ii++) nbins_rem+=histogram[ii].nbin; histogram = free_histogram(histogram, nhistnodes); PRINT_MEM_STATS( "free remainder of histogram1" ); } kin = h2nbins - 1; while (( nretain > 0 ) && ( kin >= 0 )) { hptr = pptr = histogram2[kin].nodes; while( hptr != NULL ) { /* determine the indices corresponding to this node */ if ( imap != NULL ) { ii = imap[hptr->i] ; } else { ii = hptr->i ; } if ( imap != NULL ) { jj = imap[hptr->j] ; } else { jj = hptr->j ; } /* add in the values */ if(( ii >= DSET_NVOX(cset) ) || ( jj >= DSET_NVOX(cset))) { if( ii >= DSET_NVOX(cset)) { WARNING_message("Avoiding bodset, wodset overflow (ii) %d > %d\n (%s,%d)\n", ii,DSET_NVOX(cset),__FILE__,__LINE__ ); } if( jj >= DSET_NVOX(cset)) { WARNING_message("Avoiding bodset, wodset overflow (jj) %d > %d\n (%s,%d)\n", jj,DSET_NVOX(cset),__FILE__,__LINE__ ); } } else { bodset[ ii ] += 1.0 ; wodset[ ii ] += (float)(hptr->corr); bodset[ jj ] += 1.0 ; wodset[ jj ] += (float)(hptr->corr); } if( fout1D != NULL ) { /* add source, dest, correlation to 1D file */ ix1 = DSET_index_to_ix(cset,ii) ; jy1 = DSET_index_to_jy(cset,ii) ; kz1 = DSET_index_to_kz(cset,ii) ; ix2 = DSET_index_to_ix(cset,jj) ; jy2 = DSET_index_to_jy(cset,jj) ; kz2 = DSET_index_to_kz(cset,jj) ; fprintf(fout1D, "%d %d %d %d %d %d %d %d %.6f\n", ii, jj, ix1, jy1, kz1, ix2, jy2, kz2, (float)(hptr->corr)); } /* increment node pointers */ pptr = hptr; hptr = hptr->next; /* delete the node */ if(pptr) { free(pptr); DEC_MEM_STATS(( sizeof(hist_node) ), "hist nodes"); pptr=NULL; } } /* decrement the number of correlations we wish to retain */ nretain -= histogram2[kin].nbin; histogram2[kin].nodes = NULL; /* go on to the next bin */ kin--; } PRINT_MEM_STATS("hist2 nodes free - incorporated into output"); /* we are finished with histogram2 */ { histogram2 = free_histogram(histogram2, h2nbins); /* -- update running memory estimate to reflect memory allocation */ PRINT_MEM_STATS( "free hist2" ); } if (nretain < 0 ) { WARNING_message( "Went over sparsity goal %d by %d, with a resolution of %f", ngoal, -1*nretain, h2binwidth); } } if (nretain > 0 ) { WARNING_message( "Was not able to meet goal of %d (%3.2f%%) correlations, %d (%3.2f%%) correlations passed the threshold of %3.2f, maybe you need to change the threshold or the desired sparsity?", ngoal, 100.0*((float)ngoal)/((float)totPosCor), totNumCor, 100.0*((float)totNumCor)/((float)totPosCor), thresh); } } INFO_message("Done..\n") ; /* update running memory statistics to reflect freeing the vectim */ DEC_MEM_STATS(((xvectim->nvec*sizeof(int)) + ((xvectim->nvec)*(xvectim->nvals))*sizeof(float) + sizeof(MRI_vectim)), "vectim"); /* toss some trash */ VECTIM_destroy(xvectim) ; DSET_delete(xset) ; if(fout1D!=NULL)fclose(fout1D); PRINT_MEM_STATS( "vectim unload" ); if (weightedDC) free(weightedDC) ; weightedDC = NULL; if (binaryDC) free(binaryDC) ; binaryDC = NULL; /* finito */ INFO_message("Writing output dataset to disk [%s bytes]", commaized_integer_string(cset->dblk->total_bytes)) ; /* write the dataset */ DSET_write(cset) ; WROTE_DSET(cset) ; /* increment our memory stats, since we are relying on the header for this information, we update the stats before actually freeing the memory */ DEC_MEM_STATS( (DSET_NVOX(cset)*DSET_NVALS(cset)*sizeof(float)), "output dset"); /* free up the output dataset memory */ DSET_unload(cset) ; DSET_delete(cset) ; /* force a print */ MEM_STAT = 1; PRINT_MEM_STATS( "Fin" ); exit(0) ; }
int main( int argc , char * argv[] ) { THD_dfvec3 *xx , *yy , dv ; int nvec=0 , ii,jj, iarg ; THD_dvecmat rt , rtinv ; THD_dmat33 pp,ppt , rr ; THD_dfvec3 tt ; THD_3dim_dataset *mset=NULL , *dset=NULL ; double *ww=NULL ; int nww=0 ; int keeptags=1 , wtval=0 , verb=0 , dummy=0 ; char * prefix = "tagalign" , *mfile=NULL ; float *fvol , cbot,ctop , dsum ; int nval , nvox , clipit , ival, RMETH=MRI_CUBIC; float matar[12] ; int use_3dWarp=1 , matrix_type=ROTATION ; mainENTRY("3dTagalign main"); /*--- help? ---*/ /*- scan args -*/ iarg = 1 ; RMETH=MRI_CUBIC; while( iarg < argc && argv[iarg][0] == '-' ){ /*-----*/ if( strcmp(argv[iarg],"-h") == 0 || strcmp(argv[iarg],"-help") == 0){ /* 22 Apr 2003 */ usage_3dTagalign(strlen(argv[iarg]) > 3 ? 2:1); exit(0); } /*-----*/ if( strcmp(argv[iarg],"-NN") == 0 ){ RMETH = MRI_NN ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-linear") == 0 ){ RMETH = MRI_LINEAR ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-cubic") == 0 ){ RMETH = MRI_CUBIC ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-quintic") == 0 ){ RMETH = MRI_QUINTIC ; iarg++ ; continue ; } /*-----*/ if( strcmp(argv[iarg],"-rotate") == 0 ){ /* 22 Apr 2003 */ matrix_type = ROTATION ; use_3dWarp = 1 ; iarg++ ; continue ; } /*-----*/ if( strcmp(argv[iarg],"-affine") == 0 ){ /* 21 Apr 2003 */ matrix_type = AFFINE ; use_3dWarp = 1 ; iarg++ ; continue ; } /*-----*/ if( strcmp(argv[iarg],"-rotscl") == 0 ){ /* 22 Apr 2003 */ matrix_type = ROTSCL ; use_3dWarp = 1 ; iarg++ ; continue ; } #if 0 /*-----*/ if( strcmp(argv[iarg],"-3dWarp") == 0 ){ /* 21 Apr 2003 */ use_3dWarp = 1 ; iarg++ ; continue ; } #endif /*-----*/ if( strcmp(argv[iarg],"-master") == 0 ){ if( mset != NULL ) ERREX("Can only have one -master option") ; if( ++iarg >= argc ) ERREX("Need an argument after -master") ; mset = THD_open_dataset( argv[iarg] ) ; if( mset == NULL ) ERREX("Can't open -master dataset") ; if( mset->tagset == NULL ) ERREX("No tags in -master dataset") ; if( TAGLIST_COUNT(mset->tagset) < 3 ) ERREX("Not enough tags in -master dataset") ; for( nvec=ii=0 ; ii < TAGLIST_COUNT(mset->tagset) ; ii++ ) if( TAG_SET(TAGLIST_SUBTAG(mset->tagset,ii)) ) nvec++ ; if( nvec < 3 ) ERREX("Not enough tags set in -master dataset") ; if( nvec < TAGLIST_COUNT(mset->tagset) ) fprintf(stderr,"++ WARNING: not all tags are set in -master dataset\n") ; if( verb ) fprintf(stderr,"++ Found %d tags in -master dataset\n",nvec) ; iarg++ ; continue ; } #if 0 /*-----*/ if( strcmp(argv[iarg],"-wtval") == 0 ){ if( ww != NULL ) ERREX("Can't have -wtval after -wt1D") ; wtval++ ; iarg++ ; continue ; } /*-----*/ if( strcmp(argv[iarg],"-wt1D") == 0 ){ MRI_IMAGE * wtim ; float * wtar ; if( wtval ) ERREX("Can't have -wt1D after -wtval") ; if( ww != NULL ) ERREX("Can't have two -wt1D options!") ; if( ++iarg >= argc ) ERREX("Need an argument after -wt1D") ; wtim = mri_read_1D( argv[iarg] ) ; if( wtim == NULL ) ERREX("Can't read -wtim file") ; if( wtim->ny > 1 ) ERREX("-wtim file has more than one columm") ; wtar = MRI_FLOAT_PTR(wtim) ; ww = (double *) malloc(sizeof(double)*wtim->nx) ; nww = wtim->nx ; for( ii=0 ; ii < nww ; ii++ ){ ww[ii] = (double) wtar[ii] ; if( ww[ii] < 0.0 ) ERREX("Negative value found in -wt1D file") ; } mri_free(wtim) ; iarg++ ; continue ; } #endif /*-----*/ if( strcmp(argv[iarg],"-nokeeptags") == 0 ){ keeptags = 0 ; iarg++ ; continue ; } /*-----*/ if( strncmp(argv[iarg],"-verb",5) == 0 ){ verb++ ; iarg++ ; continue ; } /*-----*/ if( strcmp(argv[iarg],"-dummy") == 0 ){ dummy++ ; iarg++ ; continue ; } /*-----*/ if( strcmp(argv[iarg],"-prefix") == 0 ){ if( ++iarg >= argc ) ERREX("Need an argument after -prefix") ; prefix = argv[iarg] ; if( !THD_filename_ok(prefix) ) ERREX("-prefix string is illegal") ; iarg++ ; continue ; } /*-----*/ if( strcmp(argv[iarg],"-matvec") == 0 ){ if( ++iarg >= argc ) ERREX("Need an argument after -matvec") ; mfile = argv[iarg] ; if( !THD_filename_ok(mfile) ) ERREX("-matvec string is illegal") ; iarg++ ; continue ; } /*-----*/ fprintf(stderr,"** Unknown option: %s\n",argv[iarg]) ; suggest_best_prog_option(argv[0], argv[iarg]); exit(1) ; } /* end of scanning command line for options */ if( argc < 2 ){ ERROR_message("Too few options"); usage_3dTagalign(0); exit(1) ; } if( mset == NULL ) ERREX("No -master option found on command line") ; #if 0 if( ww != NULL && nww < nvec ) ERREX("Not enough weights found in -wt1D file") ; /*-- if -wtval, setup weights from master tag values --*/ if( wtval ){ ww = (double *) malloc(sizeof(double)*nvec) ; nww = nvec ; for( ii=jj=0 ; ii < TAGLIST_COUNT(mset->tagset) ; ii++ ){ if( TAG_SET(TAGLIST_SUBTAG(mset->tagset,ii)) ){ ww[jj] = (double) TAG_VAL(TAGLIST_SUBTAG(mset->tagset,ii)) ; if( ww[jj] < 0.0 ) ERREX("Negative value found in -master tag values") ; jj++ ; } } } #endif /*-- read input dataset (to match to master dataset) --*/ if( iarg >= argc ) ERREX("No input dataset?") ; dset = THD_open_dataset( argv[iarg] ) ; if( dset == NULL ) ERREX("Can't open input dataset") ; if( dset->tagset == NULL ) ERREX("No tags in input dataset") ; if( TAGLIST_COUNT(dset->tagset) != TAGLIST_COUNT(mset->tagset) ) ERREX("Tag counts don't match in -master and input") ; /* check if set tags match exactly */ for( ii=0 ; ii < TAGLIST_COUNT(mset->tagset) ; ii++ ){ if( TAG_SET(TAGLIST_SUBTAG(mset->tagset,ii)) != TAG_SET(TAGLIST_SUBTAG(dset->tagset,ii)) ) ERREX("Set tags don't match in -master and input") ; } /*-- load vector lists: xx=master, yy=input --*/ xx = (THD_dfvec3 *) malloc( sizeof(THD_dfvec3) * nvec ) ; yy = (THD_dfvec3 *) malloc( sizeof(THD_dfvec3) * nvec ) ; dsum = 0.0 ; for( ii=jj=0 ; ii < nvec ; ii++ ){ if( TAG_SET(TAGLIST_SUBTAG(mset->tagset,ii)) ){ LOAD_DFVEC3( xx[jj] , /* N.B.: */ TAG_X( TAGLIST_SUBTAG(mset->tagset,ii) ) , /* these are */ TAG_Y( TAGLIST_SUBTAG(mset->tagset,ii) ) , /* in Dicom */ TAG_Z( TAGLIST_SUBTAG(mset->tagset,ii) ) ) ; /* order now */ LOAD_DFVEC3( yy[jj] , TAG_X( TAGLIST_SUBTAG(dset->tagset,ii) ) , TAG_Y( TAGLIST_SUBTAG(dset->tagset,ii) ) , TAG_Z( TAGLIST_SUBTAG(dset->tagset,ii) ) ) ; dv = SUB_DFVEC3( xx[jj] , yy[jj] ) ; dsum += dv.xyz[0]*dv.xyz[0] + dv.xyz[1]*dv.xyz[1] + dv.xyz[2]*dv.xyz[2] ; jj++ ; } } dsum = sqrt(dsum/nvec) ; fprintf(stderr,"++ RMS distance between tags before = %.2f mm\n" , dsum ) ; /*-- compute best transformation from mset to dset coords --*/ switch( matrix_type ){ default: case ROTATION: rt = DLSQ_rot_trans( nvec , yy , xx , ww ) ; /* in thd_rot3d.c */ break ; case AFFINE: rt = DLSQ_affine ( nvec , yy , xx ) ; /* 21 Apr 2003 */ break ; case ROTSCL: rt = DLSQ_rotscl ( nvec , yy , xx , (DSET_NZ(dset)==1) ? 2 : 3 ) ; break ; } rtinv = INV_DVECMAT(rt) ; /*-- check for floating point legality --*/ nval = 0 ; for( ii=0 ; ii < 3 ; ii++ ){ dsum = rt.vv.xyz[ii] ; nval += thd_floatscan(1,&dsum) ; for( jj=0 ; jj < 3 ; jj++ ){ dsum = rt.mm.mat[ii][jj] ; nval += thd_floatscan(1,&dsum) ; } } if( nval > 0 ){ fprintf(stderr,"** Floating point errors during calculation\n" "** of transform matrix and translation vector\n" ) ; exit(1) ; } /*-- check for rotation matrix legality --*/ dsum = DMAT_DET(rt.mm) ; if( dsum == 0.0 || (matrix_type == ROTATION && fabs(dsum-1.0) > 0.01) ){ fprintf(stderr,"** Invalid transform matrix computed: tags dependent?\n" "** computed [matrix] and [vector] follow:\n" ) ; for( ii=0 ; ii < 3 ; ii++ ) fprintf(stderr," [ %10.5f %10.5f %10.5f ] [ %10.5f ] \n", rt.mm.mat[ii][0],rt.mm.mat[ii][1],rt.mm.mat[ii][2],rt.vv.xyz[ii] ); exit(1) ; } /*-- print summary --*/ if( verb ){ fprintf(stderr,"++ Matrix & Vector [Dicom: x=R-L; y=A-P; z=I-S]\n") ; for( ii=0 ; ii < 3 ; ii++ ) fprintf(stderr," %10.5f %10.5f %10.5f %10.5f\n", rt.mm.mat[ii][0],rt.mm.mat[ii][1],rt.mm.mat[ii][2],rt.vv.xyz[ii] ); } if( matrix_type == ROTATION || matrix_type == ROTSCL ){ double theta, costheta , dist , fac=1.0 ; if( matrix_type == ROTSCL ){ fac = DMAT_DET(rt.mm); fac = fabs(fac); if( DSET_NZ(dset) == 1 ) fac = sqrt(fac) ; else fac = cbrt(fac) ; } costheta = 0.5 * sqrt(1.0 + DMAT_TRACE(rt.mm)/fac ) ; theta = 2.0 * acos(costheta) * 180/3.14159265 ; dist = SIZE_DFVEC3(rt.vv) ; fprintf(stderr,"++ Total rotation=%.2f degrees; translation=%.2f mm; scaling=%.2f\n", theta,dist,fac) ; } if( mfile ){ FILE * mp ; if( THD_is_file(mfile) ) fprintf(stderr,"++ Warning: -matvec will overwrite file %s\n",mfile) ; mp = fopen(mfile,"w") ; if( mp == NULL ){ fprintf(stderr,"** Can't write to -matvec %s\n",mfile) ; } else { for( ii=0 ; ii < 3 ; ii++ ) fprintf(mp," %10.5f %10.5f %10.5f %10.5f\n", rt.mm.mat[ii][0],rt.mm.mat[ii][1],rt.mm.mat[ii][2],rt.vv.xyz[ii] ); fclose(mp) ; if( verb ) fprintf(stderr,"++ Wrote matrix+vector to %s\n",mfile) ; } } if( dummy ){ fprintf(stderr,"++ This was a -dummy run: no output dataset\n") ; exit(0) ; } /*-- 21 Apr 2003: transformation can be done the old way (a la 3drotate), or the new way (a la 3dWarp). --*/ #if 0 if( !use_3dWarp ){ /**** the old way ****/ /*-- now must scramble the rotation matrix and translation vector from Dicom coordinate order to dataset brick order --*/ pp = DBLE_mat_to_dicomm( dset ) ; ppt = TRANSPOSE_DMAT(pp) ; rr = DMAT_MUL(ppt,rt.mm) ; rr = DMAT_MUL(rr,pp) ; tt = DMATVEC(ppt,rt.vv) ; /*-- now create the output dataset by screwing with the input dataset (this code is adapted from 3drotate.c) --*/ DSET_mallocize(dset) ; DSET_load( dset ) ; CHECK_LOAD_ERROR(dset) ; dset->idcode = MCW_new_idcode() ; dset->dblk->diskptr->storage_mode = STORAGE_BY_BRICK ; /* 14 Jan 2004 */ EDIT_dset_items( dset , ADN_prefix , prefix , ADN_label1 , prefix , ADN_none ) ; if( !THD_ok_overwrite() && (THD_deathcon() && THD_is_file(dset->dblk->diskptr->header_name) )){ fprintf(stderr, "** Output file %s already exists -- cannot continue!\n", dset->dblk->diskptr->header_name ) ; exit(1) ; } tross_Make_History( "3dTagalign" , argc,argv , dset ) ; /*-- if desired, keep old tagset --*/ if( keeptags ){ THD_dfvec3 rv ; dsum = 0.0 ; for( jj=ii=0 ; ii < TAGLIST_COUNT(dset->tagset) ; ii++ ){ if( TAG_SET(TAGLIST_SUBTAG(dset->tagset,ii)) ){ rv = DMATVEC( rt.mm , yy[jj] ) ; /* operating on */ rv = ADD_DFVEC3( rt.vv , rv ) ; /* Dicom order */ dv = SUB_DFVEC3( xx[jj] , rv ) ; dsum += dv.xyz[0]*dv.xyz[0] + dv.xyz[1]*dv.xyz[1] + dv.xyz[2]*dv.xyz[2] ; UNLOAD_DFVEC3( rv , TAG_X( TAGLIST_SUBTAG(dset->tagset,ii) ) , TAG_Y( TAGLIST_SUBTAG(dset->tagset,ii) ) , TAG_Z( TAGLIST_SUBTAG(dset->tagset,ii) ) ) ; jj++ ; } } dsum = sqrt(dsum/nvec) ; fprintf(stderr,"++ RMS distance between tags after = %.2f mm\n" , dsum ) ; } else { myXtFree(dset->tagset) ; /* send it to the dustbin */ } /*-- rotate sub-bricks --*/ if( verb ) fprintf(stderr,"++ computing output BRIK") ; nvox = DSET_NVOX(dset) ; nval = DSET_NVALS(dset) ; fvol = (float *) malloc( sizeof(float) * nvox ) ; THD_rota_method( MRI_HEPTIC ) ; clipit = 1 ; for( ival=0 ; ival < nval ; ival++ ){ /*- get sub-brick out of dataset -*/ EDIT_coerce_type( nvox , DSET_BRICK_TYPE(dset,ival),DSET_ARRAY(dset,ival) , MRI_float,fvol ) ; if( clipit ){ register int ii ; register float bb,tt ; bb = tt = fvol[0] ; for( ii=1 ; ii < nvox ; ii++ ){ if( fvol[ii] < bb ) bb = fvol[ii] ; else if( fvol[ii] > tt ) tt = fvol[ii] ; } cbot = bb ; ctop = tt ; } if( verb && nval < 5 ) fprintf(stderr,".") ; /*- rotate it -*/ THD_rota_vol_matvec( DSET_NX(dset) , DSET_NY(dset) , DSET_NZ(dset) , fabs(DSET_DX(dset)) , fabs(DSET_DY(dset)) , fabs(DSET_DZ(dset)) , fvol , rr , tt ) ; if( verb ) fprintf(stderr,".") ; if( clipit ){ register int ii ; register float bb,tt ; bb = cbot ; tt = ctop ; for( ii=0 ; ii < nvox ; ii++ ){ if( fvol[ii] < bb ) fvol[ii] = bb ; else if( fvol[ii] > tt ) fvol[ii] = tt ; } } if( verb && nval < 5 ) fprintf(stderr,".") ; /*- put it back into dataset -*/ EDIT_coerce_type( nvox, MRI_float,fvol , DSET_BRICK_TYPE(dset,ival),DSET_ARRAY(dset,ival) ); } /* end of loop over sub-brick index */ if( verb ) fprintf(stderr,":") ; /* save matrix+vector into dataset, too */ UNLOAD_DMAT(rt.mm,matar[0],matar[1],matar[2], matar[4],matar[5],matar[6], matar[8],matar[9],matar[10] ) ; UNLOAD_DFVEC3(rt.vv,matar[3],matar[7],matar[11]) ; THD_set_atr( dset->dblk, "TAGALIGN_MATVEC", ATR_FLOAT_TYPE, 12, matar ) ; /* write dataset to disk */ dset->dblk->master_nvals = 0 ; /* in case this was a mastered dataset */ DSET_write(dset) ; if( verb ) fprintf(stderr,"\n") ; } else #endif { /**** the new way: use 3dWarp type transformation ****/ THD_3dim_dataset *oset ; THD_vecmat tran ; #if 0 DFVEC3_TO_FVEC3( rt.vv , tran.vv ) ; DMAT_TO_MAT ( rt.mm , tran.mm ) ; #else DFVEC3_TO_FVEC3( rtinv.vv , tran.vv ) ; DMAT_TO_MAT ( rtinv.mm , tran.mm ) ; #endif mri_warp3D_method( RMETH ) ; oset = THD_warp3D_affine( dset, tran, mset, prefix, 0, WARP3D_NEWDSET ) ; if( oset == NULL ){ fprintf(stderr,"** ERROR: THD_warp3D() fails!\n"); exit(1); } tross_Copy_History( dset , oset ) ; tross_Make_History( "3dTagalign" , argc,argv , oset ) ; UNLOAD_DMAT(rt.mm,matar[0],matar[1],matar[2], matar[4],matar[5],matar[6], matar[8],matar[9],matar[10] ) ; UNLOAD_DFVEC3(rt.vv,matar[3],matar[7],matar[11]) ; THD_set_atr( oset->dblk, "TAGALIGN_MATVEC", ATR_FLOAT_TYPE, 12, matar ) ; /*-- if desired, keep old tagset --*/ if( keeptags ){ THD_dfvec3 rv ; oset->tagset = myXtNew(THD_usertaglist) ; *(oset->tagset) = *(dset->tagset) ; dsum = 0.0 ; for( jj=ii=0 ; ii < TAGLIST_COUNT(oset->tagset) ; ii++ ){ if( TAG_SET(TAGLIST_SUBTAG(oset->tagset,ii)) ){ rv = DMATVEC( rt.mm , yy[jj] ) ; rv = ADD_DFVEC3( rt.vv , rv ) ; dv = SUB_DFVEC3( xx[jj] , rv ) ; dsum += dv.xyz[0]*dv.xyz[0] + dv.xyz[1]*dv.xyz[1] + dv.xyz[2]*dv.xyz[2] ; UNLOAD_DFVEC3( rv , TAG_X( TAGLIST_SUBTAG(oset->tagset,ii) ) , TAG_Y( TAGLIST_SUBTAG(oset->tagset,ii) ) , TAG_Z( TAGLIST_SUBTAG(oset->tagset,ii) ) ) ; jj++ ; } } dsum = sqrt(dsum/nvec) ; fprintf(stderr,"++ RMS distance between tags after = %.2f mm\n" , dsum ) ; } DSET_write(oset) ; } /* end of 3dWarp-like work */ exit(0) ; }
int SUMA_SegEngine(SEG_OPTS *Opt) { static char FuncName[]={"SUMA_SegEngine"}; THD_3dim_dataset *pygcbo=NULL; int iter=0, kk, UseK[500]; char sinf[256]; char sreport[512]={"unset_report_name.txt"}; SUMA_Boolean LocalHead = YUP; SUMA_ENTRY; #ifdef USE_OMP #pragma omp parallel { if( LocalHead && omp_get_thread_num() == 0 ) INFO_message("OpenMP thread count = %d",omp_get_num_threads()) ; } #endif if (Opt->cset) {/* Hide Classes not for analysis */ int mm; short *sc=NULL; sc= (short *)DSET_ARRAY (Opt->cset, 0); for (kk=0 ; kk<DSET_NVOX(Opt->cset); ++kk) { for (mm=0; mm<Opt->cs->N_label; ++mm) { if (sc[kk] == Opt->cs->keys[mm]) break; } if (mm >= Opt->cs->N_label) sc[kk] = 0; } } else { SUMA_S_Err("Need cset"); SUMA_RETURN(0); } if (!Opt->priCgALL) { if ((Opt->priCgA || Opt->priCgL)) { if (!SUMA_MergeCpriors( Opt->cs, Opt->cmask, Opt->aset, Opt->priCgA, Opt->wA, Opt->priCgL, Opt->wL, &Opt->priCgALL, Opt)) { SUMA_S_Err("NULL Opt->priCgALL"); SUMA_RETURN(0); } } else if ((Opt->priCgLname && !strcmp(Opt->priCgLname,"INIT_MIXFRAC")) || (Opt->priCgAname && !strcmp(Opt->priCgAname,"INIT_MIXFRAC")) ){ SUMA_S_Note("Forcing spatial priors at initial mixing fraction"); if (!SUMA_MergeCpriors( Opt->cs, Opt->cmask, Opt->aset, NULL, 0.0, NULL, 0.0, &Opt->priCgALL, Opt)) { SUMA_S_Err("NULL Opt->priCgALL"); SUMA_RETURN(0); } } if (Opt->priCgALL && Opt->debug > 1) { SUMA_Seg_Write_Dset(Opt->proot,"priCgALLmerged", Opt->priCgALL, -1, Opt->hist); } } /* split the classes */ if (Opt->Split) { THD_3dim_dataset *Scset=NULL; int N_split=0; SUMA_CLASS_STAT *Scs=NULL; SUMA_S_Warn("Splitting classes"); while (Opt->Split[N_split] > 0) ++N_split; if (N_split != Opt->cs->N_label) { SUMA_S_Errv("Split vector malformed.\n" "Have %d values in Split, but %d classes\n", N_split, Opt->cs->N_label); SUMA_RETURN(0); } if (!SUMA_Split_Classes(Opt->cs->label, Opt->cs->N_label, Opt->cs->keys, Opt->Split, Opt->aset, Opt->cset, Opt->cmask, &Scset, &Scs, Opt)) { SUMA_S_Err("Failed to split classes"); SUMA_RETURN(0); } /* Save old class stats and replace by split classes */ Opt->Gcs = Opt->cs; Opt->cs = Scs; Scs=NULL; DSET_delete(Opt->cset); Opt->cset = Scset; Scset=NULL; } /* get the initial parameters pstCgALL is still null here normally and priCgALL will not be used when that is the case. So these estimates are from cset alone */ if (!SUMA_Class_stats( Opt->aset, Opt->cset, Opt->cmask, Opt->cmask_count, Opt->pstCgALL, Opt->priCgALL, Opt->gold, Opt->cs, Opt->mix_frac_floor)) { SUMA_S_Err("Failed in class stats"); SUMA_RETURN(0); } if (Opt->debug) SUMA_show_Class_Stat(Opt->cs, "Class Stat At Input:\n", NULL); /* Make sure there are good estimates for all classes */ if (SUMA_ZeroSamp_from_ClassStat(Opt->cs)) { if (!Opt->debug) SUMA_show_Class_Stat(Opt->cs, "Class Stat At Input:\n", NULL); SUMA_S_Err("Have empty classes at initialization. Not cool\n"); SUMA_RETURN(0); } if (!Opt->pstCgALL) { /* Compute initial posterior distribution */ if (!(SUMA_pst_C_giv_ALL(Opt->aset, Opt->cmask, Opt->cmask_count, Opt->cs, Opt->priCgALL, Opt->pCgN, Opt->B, Opt->T, (!Opt->mixopt || strcmp(Opt->mixopt,"IGNORE")) ? 1:0, &Opt->pstCgALL))) { SUMA_S_Err("Failed in SUMA_pst_C_giv_ALL"); SUMA_RETURN(0); } } if (!SUMA_Class_stats( Opt->aset, Opt->cset, Opt->cmask, Opt->cmask_count, Opt->pstCgALL, Opt->priCgALL, Opt->gold, Opt->cs, Opt->mix_frac_floor)) { SUMA_S_Err("Failed in class stats"); SUMA_RETURN(0); } if (Opt->debug) SUMA_show_Class_Stat(Opt->cs, "Posterior Weighted Class Stat At Input:\n", NULL); /* To begin iterations, we should have class stats and pstCgALL. Also, need an initial cset if B > 0.0 */ for (iter=0; iter<Opt->N_main; ++iter) { if (Opt->debug) { INFO_message("Iteration %d memory check:\n",iter);MCHECK; } /* improve parameters based on edge energy */ if (Opt->edge) { double en; float vv=1.0; int *UseK, N_kok; THD_3dim_dataset *skelset=NULL, *l_Bset=NULL, *l_aset=NULL; NEW_SHORTY(Opt->aset, Opt->cs->N_label*(Opt->cs->N_label-1)/2, "skelly", skelset); UseK = (int *)SUMA_calloc(Opt->cs->N_label, sizeof(int)); if ((N_kok = SUMA_Class_k_Selector(Opt->cs, "classes_string", "CSF; GM; WM", UseK))<0) { SUMA_S_Err("Failed to find classes"); SUMA_RETURN(0); } if (1) { /* It should be the case that edge energy should not be affected by the presence of bias field (METH2), for now, I will pass a constant field here for testing */ NEW_SHORTY(Opt->aset, 1, "l_Bset", l_Bset); if (!SUMA_InitDset(l_Bset, &vv, 1, Opt->cmask, 1)) { SUMA_S_Err("Failed to initialize l_Bset"); SUMA_RETURN(0); } if (iter == 0) l_aset = Opt->aset; else l_aset = Opt->xset; } else { /* old approach */ l_aset = Opt->aset; l_Bset = Opt->Bset; } en = SUMA_DsetEdgeEnergy(l_aset, Opt->cset, Opt->cmask, l_Bset, skelset, Opt->cs, Opt->edge, UseK, N_kok); SUMA_Seg_Write_Dset(Opt->proot, "PreSkel", skelset, iter, Opt->hist); SUMA_S_Notev("Edge Enenergy, Pre MAP : %f\n", en); #if 1 if (!SUMA_MAP_EdgeEnergy( l_aset, Opt->cmask, Opt->cmask_count, l_Bset, Opt->cs, Opt->cset, Opt->edge, Opt->priCgALL, Opt->pCgN, Opt->B, Opt->T, 0.4, 0.4, Opt)) { SUMA_S_Err("Failed in MAP_EdgeEnergy"); exit(1); } en = SUMA_DsetEdgeEnergy(l_aset, Opt->cset, Opt->cmask, l_Bset, skelset, Opt->cs, Opt->edge, UseK, N_kok); SUMA_Seg_Write_Dset(Opt->proot, "PstSkel", skelset, iter, Opt->hist); SUMA_S_Notev("Edge Enenergy, Post MAP : %f\n", en); #endif DSET_delete(skelset); skelset=NULL; if (l_Bset && l_Bset != Opt->Bset) DSET_delete(l_Bset); l_Bset=NULL; SUMA_ifree(UseK); } if (Opt->bias_param > 0) { if (Opt->debug > 1) SUMA_S_Notev("Wells Bias field correction, FWHM %f, iteration %d\n", Opt->bias_param, iter); if (!strcmp(Opt->bias_meth,"Wells")) { if (!(SUMA_estimate_bias_field_Wells(Opt, Opt->cmask, Opt->cs, Opt->bias_param, Opt->bias_classes, Opt->aset, Opt->pstCgALL, &Opt->Bset ))) { SUMA_S_Err("Failed to estimate bias"); SUMA_RETURN(0); } } else { SUMA_S_Errv("Only Wells is allowed for now, have %s\n", Opt->bias_meth); SUMA_RETURN(0); } if (!(SUMA_apply_bias_field(Opt, Opt->aset, Opt->Bset, &Opt->xset))) { SUMA_S_Err("Failed to apply field"); SUMA_RETURN(0); } } else { if (iter == 0) { if (Opt->debug > 1) SUMA_S_Note("Skipping bias field correction"); if (!Opt->xset) Opt->xset = EDIT_full_copy(Opt->aset, Opt->xrefix); if (!Opt->Bset) { float vv=1.0; NEW_SHORTY(Opt->aset,1, "ConstantField", Opt->Bset); if (!SUMA_InitDset(Opt->Bset, &vv, 1, Opt->cmask, 1)) { SUMA_S_Err("Failed to initialize Bset"); SUMA_RETURN(0); } } } } if (Opt->B > 0) { if (Opt->debug > 1 && iter==0) { SUMA_Seg_Write_Dset(Opt->proot, "MAPlabel.-1", Opt->cset, -1, Opt->hist); } if (!(SUMA_MAP_labels(Opt->xset, Opt->cmask, Opt->cs, 6, Opt->priCgALL, &Opt->cset, &Opt->pCgN, Opt))) { SUMA_S_Err("Failed in SUMA_MAP_labels"); SUMA_RETURN(0); } if (Opt->debug > 1) { SUMA_Seg_Write_Dset(Opt->proot, "MAPlabel", Opt->cset, iter, Opt->hist); SUMA_Seg_Write_Dset(Opt->proot, "pCgN", Opt->pCgN, iter, Opt->hist); } AFNI_FEED(Opt->ps->cs, "MAPlabel", iter, Opt->cset); } if (!(SUMA_pst_C_giv_ALL(Opt->xset, Opt->cmask, Opt->cmask_count, Opt->cs, Opt->priCgALL, Opt->pCgN, Opt->B, Opt->T, (!Opt->mixopt || strcmp(Opt->mixopt,"IGNORE")) ? 1:0, &Opt->pstCgALL))) { SUMA_S_Err("Failed in SUMA_pst_C_giv_ALL"); SUMA_RETURN(0); } if (Opt->debug > 1) { SUMA_Seg_Write_Dset(Opt->proot, "pstCgALL", Opt->pstCgALL, iter, Opt->hist); } if (Opt->B <= 0.0f) { /* no need if B > 0 because cset is set in SUMA_MAP_labels*/ /* update class based on max(Opt->pstCgALL) */ if (!(SUMA_assign_classes( Opt->pstCgALL, Opt->cs, Opt->cmask, &Opt->cset))) { SUMA_S_Err("Failed in assign_classes"); SUMA_RETURN(0); } } /* Now update class stats */ if (!SUMA_Class_stats( Opt->xset, Opt->cset, Opt->cmask, Opt->cmask_count, Opt->pstCgALL, Opt->priCgALL, Opt->gold, Opt->cs, Opt->mix_frac_floor)) { SUMA_S_Err("Failed in class stats"); SUMA_RETURN(0); } if (Opt->debug || Opt->gold || Opt->gold_bias) { double bad_bias_thresh, bias_bad_count; char *sbig=NULL; sprintf(sinf, "Class Stat iter %d:\n", iter+1); if (iter == Opt->N_main-1 || Opt->debug) { SUMA_show_Class_Stat(Opt->cs, sinf, NULL); if (Opt->proot) sprintf(sreport, "%s/ClassStat.i%02d%s.txt", Opt->proot, iter+1, (iter==Opt->N_main-1) ? ".FINAL":""); else snprintf(sreport, 500, "%s.ClassStat.i%02d%s.txt", Opt->prefix, iter+1, (iter==Opt->N_main-1) ? ".FINAL":""); sbig = SUMA_append_replace_string(Opt->hist, sinf,"\n",0); SUMA_show_Class_Stat(Opt->cs, sbig, sreport); SUMA_ifree(sbig); } /* Report on bias correction */ bad_bias_thresh = 0.06; if ((Opt->gold_bias && Opt->Bset) && (iter == Opt->N_main-1 || Opt->debug)) { FILE *fout = fopen(sreport,"a"); bias_bad_count = SUMA_CompareBiasDsets(Opt->gold_bias, Opt->Bset, Opt->cmask, Opt->cmask_count, bad_bias_thresh, NULL); SUMA_S_Notev("bad_count at thresh %f = %f%% of mask.\n", bad_bias_thresh, bias_bad_count); if (fout) { fprintf(fout, "bad_count at thresh %f = %f%% of mask.\n", bad_bias_thresh, bias_bad_count); fclose(fout); fout = NULL; } } } } if (Opt->Split) { THD_3dim_dataset *Gcset=NULL; THD_3dim_dataset *GpstCgALL=NULL; /* need to put things back */ if (!SUMA_Regroup_classes(Opt, Opt->cs->label, Opt->cs->N_label, Opt->cs->keys, Opt->Gcs->label, Opt->Gcs->N_label, Opt->Gcs->keys, Opt->cmask, Opt->pstCgALL, Opt->cset, &GpstCgALL, &Gcset)) { } /* switch dsets */ DSET_delete(Opt->pstCgALL); Opt->pstCgALL = GpstCgALL; GpstCgALL = NULL; DSET_delete(Opt->cset); Opt->cset = Gcset; Gcset = NULL; } SUMA_RETURN(1); }
int main( int argc , char *argv[] ) { int nx,ny,nz , nxyz , ii,kk , num1,num2 , num_tt=0 , iv , piece , fim_offset; float dx,dy,dz , dxyz , num1_inv=0.0 , num2_inv , num1m1_inv=0.0 , num2m1_inv , dof , dd,tt,q1,q2 , f1,f2 , tt_max=0.0 ; THD_3dim_dataset *dset=NULL , *new_dset=NULL ; THD_3dim_dataset * base_dset; float *av1 , *av2 , *sd1 , *sd2 , *ffim , *gfim ; float *base_ary=NULL; void *vsp ; void *vdif ; /* output mean difference */ char cbuf[THD_MAX_NAME] ; float fbuf[MAX_STAT_AUX] , fimfac ; int output_datum ; float npiece , memuse ; float *dofbrik=NULL , *dofar=NULL ; THD_3dim_dataset *dof_dset=NULL ; /*-- read command line arguments --*/ if( argc < 2 || strncmp(argv[1],"-help",5) == 0 ) TT_syntax(NULL) ; /*-- 20 Apr 2001: addto the arglist, if user wants to [RWCox] --*/ mainENTRY("3dttest main"); machdep() ; PRINT_VERSION("3dttest") ; INFO_message("For most purposes, 3dttest++ should be used instead of 3dttest!") ; { int new_argc ; char ** new_argv ; addto_args( argc , argv , &new_argc , &new_argv ) ; if( new_argv != NULL ){ argc = new_argc ; argv = new_argv ; } } AFNI_logger("3dttest",argc,argv) ; TT_read_opts( argc , argv ) ; if( ! TT_be_quiet ) printf("3dttest: t-tests of 3D datasets, by RW Cox\n") ; /*-- read first dataset in set2 to get dimensions, etc. --*/ dset = THD_open_dataset( TT_set2->ar[0] ) ; /* 20 Dec 1999 BDW */ if( ! ISVALID_3DIM_DATASET(dset) ) ERROR_exit("Unable to open dataset file %s",TT_set2->ar[0]); nx = dset->daxes->nxx ; ny = dset->daxes->nyy ; nz = dset->daxes->nzz ; nxyz = nx * ny * nz ; dx = fabs(dset->daxes->xxdel) ; dy = fabs(dset->daxes->yydel) ; dz = fabs(dset->daxes->zzdel) ; dxyz = dx * dy * dz ; #ifdef TTDEBUG printf("*** nx=%d ny=%d nz=%d\n",nx,ny,nz) ; #endif /*-- make an empty copy of this dataset, for eventual output --*/ #ifdef TTDEBUG printf("*** making empty dataset\n") ; #endif new_dset = EDIT_empty_copy( dset ) ; tross_Make_History( "3dttest" , argc,argv , new_dset ) ; strcpy( cbuf , dset->self_name ) ; strcat( cbuf , "+TT" ) ; iv = DSET_PRINCIPAL_VALUE(dset) ; if( TT_datum >= 0 ){ output_datum = TT_datum ; } else { output_datum = DSET_BRICK_TYPE(dset,iv) ; if( output_datum == MRI_byte ) output_datum = MRI_short ; } #ifdef TTDEBUG printf(" ** datum = %s\n",MRI_TYPE_name[output_datum]) ; #endif iv = EDIT_dset_items( new_dset , ADN_prefix , TT_prefix , ADN_label1 , TT_prefix , ADN_directory_name , TT_session , ADN_self_name , cbuf , ADN_type , ISHEAD(dset) ? HEAD_FUNC_TYPE : GEN_FUNC_TYPE , ADN_func_type , FUNC_TT_TYPE , ADN_nvals , FUNC_nvals[FUNC_TT_TYPE] , ADN_ntt , 0 , /* 07 Jun 2007 */ ADN_datum_all , output_datum , ADN_none ) ; if( iv > 0 ) ERROR_exit("%d errors in attempting to create output dataset!",iv ) ; if( THD_deathcon() && THD_is_file(new_dset->dblk->diskptr->header_name) ) ERROR_exit( "Output dataset file %s already exists--cannot continue!\a", new_dset->dblk->diskptr->header_name ) ; #ifdef TTDEBUG printf("*** deleting exemplar dataset\n") ; #endif THD_delete_3dim_dataset( dset , False ) ; dset = NULL ; /** macro to test a malloc-ed pointer for validity **/ #define MTEST(ptr) \ if((ptr)==NULL) \ ( fprintf(stderr,"*** Cannot allocate memory for statistics!\n"), exit(0) ) /*-- make space for the t-test computations --*/ /* (allocate entire volumes) 13 Dec 2005 [rickr] */ npiece = 3.0 ; /* need at least this many */ if( TT_paired ) npiece += 1.0 ; else if( TT_set1 != NULL ) npiece += 2.0 ; npiece += mri_datum_size(output_datum) / (float) sizeof(float) ; npiece += mri_datum_size(output_datum) / (float) sizeof(float) ; #if 0 piece_size = TT_workmem * MEGA / ( npiece * sizeof(float) ) ; if( piece_size > nxyz ) piece_size = nxyz ; #ifdef TTDEBUG printf("*** malloc-ing space for statistics: %g float arrays of length %d\n", npiece,piece_size) ; #endif #endif av2 = (float *) malloc( sizeof(float) * nxyz ) ; MTEST(av2) ; sd2 = (float *) malloc( sizeof(float) * nxyz ) ; MTEST(sd2) ; ffim = (float *) malloc( sizeof(float) * nxyz ) ; MTEST(ffim) ; num2 = TT_set2->num ; if( TT_paired ){ av1 = sd1 = NULL ; gfim = (float *) malloc( sizeof(float) * nxyz ) ; MTEST(gfim) ; num1 = num2 ; } else if( TT_set1 != NULL ){ av1 = (float *) malloc( sizeof(float) * nxyz ) ; MTEST(av1) ; sd1 = (float *) malloc( sizeof(float) * nxyz ) ; MTEST(sd1) ; gfim = NULL ; num1 = TT_set1->num ; } else { av1 = sd1 = NULL ; gfim = NULL ; num1 = 0 ; } vdif = (void *) malloc( mri_datum_size(output_datum) * nxyz ) ; MTEST(vdif) ; vsp = (void *) malloc( mri_datum_size(output_datum) * nxyz ) ; MTEST(vsp) ; /* 27 Dec 2002: make DOF dataset (if prefix is given, and unpooled is on) */ if( TT_pooled == 0 && TT_dof_prefix[0] != '\0' ){ dofbrik = (float *) malloc( sizeof(float) * nxyz ) ; MTEST(dofbrik) ; dof_dset = EDIT_empty_copy( new_dset ) ; tross_Make_History( "3dttest" , argc,argv , dof_dset ) ; EDIT_dset_items( dof_dset , ADN_prefix , TT_dof_prefix , ADN_directory_name , TT_session , ADN_type , ISHEAD(dset) ? HEAD_FUNC_TYPE : GEN_FUNC_TYPE, ADN_func_type , FUNC_BUCK_TYPE , ADN_nvals , 1 , ADN_datum_all , MRI_float , ADN_none ) ; if( THD_is_file(dof_dset->dblk->diskptr->header_name) ) ERROR_exit( "-dof_prefix dataset file %s already exists--cannot continue!\a", dof_dset->dblk->diskptr->header_name ) ; EDIT_substitute_brick( dof_dset , 0 , MRI_float , dofbrik ) ; } /* print out memory usage to edify the user */ if( ! TT_be_quiet ){ memuse = sizeof(float) * nxyz * npiece + ( mri_datum_size(output_datum) + sizeof(short) ) * nxyz ; if( dofbrik != NULL ) memuse += sizeof(float) * nxyz ; /* 27 Dec 2002 */ printf("--- allocated %d Megabytes memory for internal use (%d volumes)\n", (int)(memuse/MEGA), (int)npiece) ; } mri_fix_data_pointer( vdif , DSET_BRICK(new_dset,0) ) ; /* attach bricks */ mri_fix_data_pointer( vsp , DSET_BRICK(new_dset,1) ) ; /* to new dataset */ /** only short and float are allowed for output **/ if( output_datum != MRI_short && output_datum != MRI_float ) ERROR_exit("Illegal output data type %d = %s", output_datum , MRI_TYPE_name[output_datum] ) ; num2_inv = 1.0 / num2 ; num2m1_inv = 1.0 / (num2-1) ; if( num1 > 0 ){ num1_inv = 1.0 / num1 ; num1m1_inv = 1.0 / (num1-1) ; } /*----- loop over pieces to process the input datasets with -----*/ /** macro to open a dataset and make it ready for processing **/ #define DOPEN(ds,name) \ do{ int pv ; (ds) = THD_open_dataset((name)) ; /* 16 Sep 1999 */ \ if( !ISVALID_3DIM_DATASET((ds)) ) \ ERROR_exit("Can't open dataset: %s",(name)) ; \ if( (ds)->daxes->nxx!=nx || (ds)->daxes->nyy!=ny || (ds)->daxes->nzz!=nz ) \ ERROR_exit("Axes size mismatch: %s",(name)) ; \ if( !EQUIV_GRIDS((ds),new_dset) ) \ WARNING_message("Grid mismatch: %s",(name)) ; \ if( DSET_NUM_TIMES((ds)) > 1 ) \ ERROR_exit("Can't use time-dependent data: %s",(name)) ; \ if( TT_use_editor ) EDIT_one_dataset( (ds), &TT_edopt ) ; \ else DSET_load((ds)) ; \ pv = DSET_PRINCIPAL_VALUE((ds)) ; \ if( DSET_ARRAY((ds),pv) == NULL ) \ ERROR_exit("Can't access data: %s",(name)) ; \ if( DSET_BRICK_TYPE((ds),pv) == MRI_complex ) \ ERROR_exit("Can't use complex data: %s",(name)) ; \ break ; } while (0) #if 0 /* can do it directly now (without offsets) 13 Dec 2005 [rickr] */ /** macro to return pointer to correct location in brick for current processing **/ #define SUB_POINTER(ds,vv,ind,ptr) \ do{ switch( DSET_BRICK_TYPE((ds),(vv)) ){ \ default: ERROR_exit("Illegal datum! ***"); \ case MRI_short:{ short * fim = (short *) DSET_ARRAY((ds),(vv)) ; \ (ptr) = (void *)( fim + (ind) ) ; \ } break ; \ case MRI_byte:{ byte * fim = (byte *) DSET_ARRAY((ds),(vv)) ; \ (ptr) = (void *)( fim + (ind) ) ; \ } break ; \ case MRI_float:{ float * fim = (float *) DSET_ARRAY((ds),(vv)) ; \ (ptr) = (void *)( fim + (ind) ) ; \ } break ; } break ; } while(0) #endif /** number of pieces to process **/ /* num_piece = (nxyz + piece_size - 1) / nxyz ; */ #if 0 nice(2) ; /** lower priority a little **/ #endif /* possibly open TT_base_dset now, and convert to floats */ if( TT_base_dname ) { DOPEN(base_dset, TT_base_dname) ; base_ary = (float *) malloc( sizeof(float) * nxyz ) ; MTEST(base_ary) ; EDIT_coerce_scale_type(nxyz , DSET_BRICK_FACTOR(base_dset,0) , DSET_BRICK_TYPE(base_dset,0),DSET_ARRAY(base_dset,0), /* input */ MRI_float ,base_ary ) ; /* output */ THD_delete_3dim_dataset( base_dset , False ) ; base_dset = NULL ; } /* only 1 'piece' now 13 Dec 2005 [rickr] */ for( piece=0 ; piece < 1 ; piece++ ){ fim_offset = 0 ; #ifdef TTDEBUG printf("*** start of piece %d: length=%d offset=%d\n",piece,nxyz,fim_offset) ; #else if( ! TT_be_quiet ){ printf("--- starting piece %d/%d (%d voxels) ",piece+1,1,nxyz) ; fflush(stdout) ; } #endif /** process set2 (and set1, if paired) **/ for( ii=0 ; ii < nxyz ; ii++ ) av2[ii] = 0.0 ; for( ii=0 ; ii < nxyz ; ii++ ) sd2[ii] = 0.0 ; for( kk=0 ; kk < num2 ; kk++ ){ /** read in the data **/ DOPEN(dset,TT_set2->ar[kk]) ; iv = DSET_PRINCIPAL_VALUE(dset) ; #ifndef TTDEBUG if( ! TT_be_quiet ){ printf(".") ; fflush(stdout) ; } /* progress */ #else printf(" ** opened dataset file %s\n",TT_set2->ar[kk]); #endif #if 0 /* fimfac will be compute when the results are ready */ if( piece == 0 && kk == 0 ){ fimfac = DSET_BRICK_FACTOR(dset,iv) ; if( fimfac == 0.0 ) fimfac = 1.0 ; fimfacinv = 1.0 / fimfac ; #ifdef TTDEBUG printf(" ** set fimfac = %g\n",fimfac) ; #endif } #endif /** convert it to floats (in ffim) **/ EDIT_coerce_scale_type(nxyz , DSET_BRICK_FACTOR(dset,iv) , DSET_BRICK_TYPE(dset,iv),DSET_ARRAY(dset,iv), /* input */ MRI_float ,ffim ) ; /* output */ THD_delete_3dim_dataset( dset , False ) ; dset = NULL ; /** get the paired dataset, if present **/ if( TT_paired ){ DOPEN(dset,TT_set1->ar[kk]) ; iv = DSET_PRINCIPAL_VALUE(dset) ; #ifndef TTDEBUG if( ! TT_be_quiet ){ printf(".") ; fflush(stdout) ; } /* progress */ #else printf(" ** opened dataset file %s\n",TT_set1->ar[kk]); #endif EDIT_coerce_scale_type( nxyz , DSET_BRICK_FACTOR(dset,iv) , DSET_BRICK_TYPE(dset,iv),DSET_ARRAY(dset,iv), /* input */ MRI_float ,gfim ) ; /* output */ THD_delete_3dim_dataset( dset , False ) ; dset = NULL ; if( TT_voxel >= 0 ) fprintf(stderr,"-- paired values #%02d: %f, %f\n", kk,ffim[TT_voxel],gfim[TT_voxel]) ; for( ii=0 ; ii < nxyz ; ii++ ) ffim[ii] -= gfim[ii] ; } else if( TT_voxel >= 0 ) fprintf(stderr,"-- set2 value #%02d: %f\n",kk,ffim[TT_voxel]); #ifdef TTDEBUG printf(" * adding into av2 and sd2\n") ; #endif /* accumulate into av2 and sd2 */ for( ii=0 ; ii < nxyz ; ii++ ){ dd = ffim[ii] ; av2[ii] += dd ; sd2[ii] += dd * dd ; } } /* end of loop over set2 datasets */ /** form the mean and stdev of set2 **/ #ifdef TTDEBUG printf(" ** forming mean and sigma of set2\n") ; #endif for( ii=0 ; ii < nxyz ; ii++ ){ av2[ii] *= num2_inv ; dd = (sd2[ii] - num2*av2[ii]*av2[ii]) ; sd2[ii] = (dd > 0.0) ? sqrt( num2m1_inv * dd ) : 0.0 ; } if( TT_voxel >= 0 ) fprintf(stderr,"-- s2 mean = %g, sd = %g\n", av2[TT_voxel],sd2[TT_voxel]) ; /** if set1 exists but is not paired with set2, process it now **/ if( ! TT_paired && TT_set1 != NULL ){ for( ii=0 ; ii < nxyz ; ii++ ) av1[ii] = 0.0 ; for( ii=0 ; ii < nxyz ; ii++ ) sd1[ii] = 0.0 ; for( kk=0 ; kk < num1 ; kk++ ){ DOPEN(dset,TT_set1->ar[kk]) ; iv = DSET_PRINCIPAL_VALUE(dset) ; #ifndef TTDEBUG if( ! TT_be_quiet ){ printf(".") ; fflush(stdout) ; } /* progress */ #else printf(" ** opened dataset file %s\n",TT_set1->ar[kk]); #endif EDIT_coerce_scale_type( nxyz , DSET_BRICK_FACTOR(dset,iv) , DSET_BRICK_TYPE(dset,iv),DSET_ARRAY(dset,iv), /* input */ MRI_float ,ffim ) ; /* output */ THD_delete_3dim_dataset( dset , False ) ; dset = NULL ; #ifdef TTDEBUG printf(" * adding into av1 and sd1\n") ; #endif for( ii=0 ; ii < nxyz ; ii++ ){ dd = ffim[ii] ; av1[ii] += dd ; sd1[ii] += dd * dd ; } if( TT_voxel >= 0 ) fprintf(stderr,"-- set1 value #%02d: %g\n",kk,ffim[TT_voxel]) ; } /* end of loop over set1 datasets */ /** form the mean and stdev of set1 **/ #ifdef TTDEBUG printf(" ** forming mean and sigma of set1\n") ; #endif for( ii=0 ; ii < nxyz ; ii++ ){ av1[ii] *= num1_inv ; dd = (sd1[ii] - num1*av1[ii]*av1[ii]) ; sd1[ii] = (dd > 0.0) ? sqrt( num1m1_inv * dd ) : 0.0 ; } if( TT_voxel >= 0 ) fprintf(stderr,"-- s1 mean = %g, sd = %g\n", av1[TT_voxel], sd1[TT_voxel]) ; } /* end of processing set1 by itself */ /***** now form difference and t-statistic *****/ #ifndef TTDEBUG if( ! TT_be_quiet ){ printf("+") ; fflush(stdout) ; } /* progress */ #else printf(" ** computing t-tests next\n") ; #endif #if 0 /* will do at end using EDIT_convert_dtype 13 Dec 2005 [rickr] */ /** macro to assign difference value to correct type of array **/ #define DIFASS switch( output_datum ){ \ case MRI_short: sdar[ii] = (short) (fimfacinv*dd) ; break ; \ case MRI_float: fdar[ii] = (float) dd ; break ; } #define TOP_SS 32700 #define TOP_TT (32700.0/FUNC_TT_SCALE_SHORT) #endif if( TT_paired || TT_use_bval == 1 ){ /** case 1: paired estimate or 1-sample **/ if( TT_paired || TT_n1 == 0 ){ /* the olde waye: 1 sample test */ f2 = 1.0 / sqrt( (double) num2 ) ; for( ii=0 ; ii < nxyz ; ii++ ){ av2[ii] -= (base_ary ? base_ary[ii] : TT_bval) ; /* final mean */ if( sd2[ii] > 0.0 ){ num_tt++ ; tt = av2[ii] / (f2 * sd2[ii]) ; sd2[ii] = tt; /* final t-stat */ tt = fabs(tt) ; if( tt > tt_max ) tt_max = tt ; } else { sd2[ii] = 0.0; } } if( TT_voxel >= 0 ) fprintf(stderr,"-- paired/bval mean = %g, t = %g\n", av2[TT_voxel], sd2[TT_voxel]) ; } else { /* 10 Oct 2007: -sdn1 was used with -base1: 'two' sample test */ f1 = (TT_n1-1.0) * (1.0/TT_n1 + 1.0/num2) / (TT_n1+num2-2.0) ; f2 = (num2 -1.0) * (1.0/TT_n1 + 1.0/num2) / (TT_n1+num2-2.0) ; for( ii=0 ; ii < nxyz ; ii++ ){ av2[ii] -= (base_ary ? base_ary[ii] : TT_bval) ; /* final mean */ q1 = f1 * TT_sd1*TT_sd1 + f2 * sd2[ii]*sd2[ii] ; if( q1 > 0.0 ){ num_tt++ ; tt = av2[ii] / sqrt(q1) ; sd2[ii] = tt ; /* final t-stat */ tt = fabs(tt) ; if( tt > tt_max ) tt_max = tt ; } else { sd2[ii] = 0.0 ; } } } /* end of -sdn1 special case */ #ifdef TTDEBUG printf(" ** paired or bval test: num_tt = %d\n",num_tt) ; #endif } else if( TT_pooled ){ /** case 2: unpaired 2-sample, pooled variance **/ f1 = (num1-1.0) * (1.0/num1 + 1.0/num2) / (num1+num2-2.0) ; f2 = (num2-1.0) * (1.0/num1 + 1.0/num2) / (num1+num2-2.0) ; for( ii=0 ; ii < nxyz ; ii++ ){ av2[ii] -= av1[ii] ; /* final mean */ q1 = f1 * sd1[ii]*sd1[ii] + f2 * sd2[ii]*sd2[ii] ; if( q1 > 0.0 ){ num_tt++ ; tt = av2[ii] / sqrt(q1) ; sd2[ii] = tt ; /* final t-stat */ tt = fabs(tt) ; if( tt > tt_max ) tt_max = tt ; } else { sd2[ii] = 0.0 ; } } if( TT_voxel >= 0 ) fprintf(stderr,"-- unpaired, pooled mean = %g, t = %g\n", av2[TT_voxel], sd2[TT_voxel]) ; #ifdef TTDEBUG printf(" ** pooled test: num_tt = %d\n",num_tt) ; #endif } else { /** case 3: unpaired 2-sample, unpooled variance **/ /** 27 Dec 2002: modified to save DOF into dofar **/ if( dofbrik != NULL ) dofar = dofbrik + fim_offset ; /* 27 Dec 2002 */ for( ii=0 ; ii < nxyz ; ii++ ){ av2[ii] -= av1[ii] ; q1 = num1_inv * sd1[ii]*sd1[ii] ; q2 = num2_inv * sd2[ii]*sd2[ii] ; if( q1>0.0 && q2>0.0 ){ /* have positive variances? */ num_tt++ ; tt = av2[ii] / sqrt(q1+q2) ; sd2[ii] = tt ; /* final t-stat */ tt = fabs(tt) ; if( tt > tt_max ) tt_max = tt ; if( dofar != NULL ) /* 27 Dec 2002 */ dofar[ii] = (q1+q2)*(q1+q2) / (num1m1_inv*q1*q1 + num2m1_inv*q2*q2) ; } else { sd2[ii] = 0.0 ; if( dofar != NULL ) dofar[ii] = 1.0 ; /* 27 Dec 2002 */ } } if( TT_voxel >= 0 ) fprintf(stderr,"-- unpaired, unpooled mean = %g, t = %g\n", av2[TT_voxel], sd2[TT_voxel]) ; #ifdef TTDEBUG printf(" ** unpooled test: num_tt = %d\n",num_tt) ; #endif } #ifndef TTDEBUG if( ! TT_be_quiet ){ printf("\n") ; fflush(stdout) ; } #endif } /* end of loop over pieces of the input */ if( TT_paired ){ printf("--- Number of degrees of freedom = %d (paired test)\n",num2-1) ; dof = num2 - 1 ; } else if( TT_use_bval == 1 ){ if( TT_n1 == 0 ){ printf("--- Number of degrees of freedom = %d (1-sample test)\n",num2-1) ; dof = num2 - 1 ; } else { dof = TT_n1+num2-2 ; printf("--- Number of degrees of freedom = %d (-sdn1 2-sample test)\n",(int)dof) ; } } else { printf("--- Number of degrees of freedom = %d (2-sample test)\n",num1+num2-2) ; dof = num1+num2-2 ; if( ! TT_pooled ) printf(" (For unpooled variance estimate, this is only approximate!)\n") ; } printf("--- Number of t-tests performed = %d out of %d voxels\n",num_tt,nxyz) ; printf("--- Largest |t| value found = %g\n",tt_max) ; kk = sizeof(ptable) / sizeof(float) ; for( ii=0 ; ii < kk ; ii++ ){ tt = student_p2t( ptable[ii] , dof ) ; printf("--- Double sided tail p = %8f at t = %8f\n" , ptable[ii] , tt ) ; } /**----------------------------------------------------------------------**/ /** now convert data to output format 13 Dec 2005 [rickr] **/ /* first set mean */ fimfac = EDIT_convert_dtype(nxyz , MRI_float,av2 , output_datum,vdif , 0.0) ; DSET_BRICK_FACTOR(new_dset, 0) = (fimfac != 0.0) ? 1.0/fimfac : 0.0 ; dd = fimfac; /* save for debug output */ /* if output is of type short, limit t-stat magnitude to 32.7 */ if( output_datum == MRI_short ){ for( ii=0 ; ii < nxyz ; ii++ ){ if ( sd2[ii] > 32.7 ) sd2[ii] = 32.7 ; else if( sd2[ii] < -32.7 ) sd2[ii] = -32.7 ; } } fimfac = EDIT_convert_dtype(nxyz , MRI_float,sd2 , output_datum,vsp , 0.0) ; DSET_BRICK_FACTOR(new_dset, 1) = (fimfac != 0.0) ? 1.0/fimfac : 0.0 ; #ifdef TTDEBUG printf(" ** fimfac for mean, t-stat = %g, %g\n",dd, fimfac) ; #endif /**----------------------------------------------------------------------**/ INFO_message("Writing combined dataset into %s\n", DSET_BRIKNAME(new_dset) ) ; fbuf[0] = dof ; for( ii=1 ; ii < MAX_STAT_AUX ; ii++ ) fbuf[ii] = 0.0 ; (void) EDIT_dset_items( new_dset , ADN_stat_aux , fbuf , ADN_none ) ; #if 0 /* factors already set */ fbuf[0] = (output_datum == MRI_short && fimfac != 1.0 ) ? fimfac : 0.0 ; fbuf[1] = (output_datum == MRI_short ) ? 1.0 / FUNC_TT_SCALE_SHORT : 0.0 ; (void) EDIT_dset_items( new_dset , ADN_brick_fac , fbuf , ADN_none ) ; #endif if( !AFNI_noenv("AFNI_AUTOMATIC_FDR") ) ii = THD_create_all_fdrcurves(new_dset) ; else ii = 0 ; THD_load_statistics( new_dset ) ; THD_write_3dim_dataset( NULL,NULL , new_dset , True ) ; if( ii > 0 ) ININFO_message("created %d FDR curves in header",ii) ; if( dof_dset != NULL ){ /* 27 Dec 2002 */ DSET_write( dof_dset ) ; WROTE_DSET( dof_dset ) ; } exit(0) ; }
int main(int argc, char **argv) { static char FuncName[]={"3dGenFeatureDist"}; SEG_OPTS *Opt=NULL; char *atr=NULL, sbuf[512], *methods=NULL; int cc, /* class counter */ kk, /* key counter */ aa, /* feature counter */ nn, /* sub-brick index */ vv, /* voxel index */ ss, /* subjects counter */ iii, /* dummy counter */ nbins, /* number of bins */ *ifeat=NULL, key, **N_alloc_FCset=NULL, /* Number of values allocated for each vector in FCset */ **N_FCset=NULL, /* Number of filled values for each vector in FCset */ N_ffalloc=0, N_ff, isneg=0, missfeatwarn=-1 /* Missing feature warning for some subject */; float fsf=0.0, fsb=0.0, ***FCset=NULL, /* Table holding samples for each feature/class combo */ hrange[2]={-3.0, 3.0}, bwidth1=0.05, bwidth=0.0, *ff=NULL; short *sf=NULL, *sb=NULL; byte **masks=NULL; SUMA_HIST ***hh=NULL, **hf=NULL; double ff_m, ff_s; SUMA_Boolean LocalHead = NOPE; SUMA_STANDALONE_INIT; SUMA_mainENTRY; SUMAg_DOv = SUMA_Alloc_DisplayObject_Struct (SUMA_MAX_DISPLAYABLE_OBJECTS); Opt = GenFeatureDist_Default(argv, argc); Opt = GenFeatureDist_ParseInput (Opt, argv, argc); Opt->hist = tross_commandline( FuncName , argc , argv ) ; if (!GenFeatureDist_CheckOpts(Opt)) { ERROR_exit("Failed on option check"); } /* labeltable? */ if (Opt->labeltable_name) { Dtable *vl_dtable=NULL; char *labeltable_str=NULL; /* read the table */ if (!(labeltable_str = AFNI_suck_file( Opt->labeltable_name))) { ERROR_exit("Failed to read %s", Opt->labeltable_name); } if (!(vl_dtable = Dtable_from_nimlstring(labeltable_str))) { ERROR_exit("Could not parse labeltable"); } /* make sure all classes are in the labeltable */ for (cc=0; cc<Opt->clss->num; ++cc) { if ((key = SUMA_KeyofLabel_Dtable(vl_dtable, Opt->clss->str[cc]))<0){ ERROR_exit("Key not found in %s for %s ", Opt->labeltable_name, Opt->clss->str[cc]); } if (Opt->keys) { if (Opt->keys[cc]!=key) { ERROR_exit("Key mismatch %d %d", Opt->keys[cc], key); } } } if (!Opt->keys) { /* get them from table */ Opt->keys = (int *)calloc(Opt->clss->num, sizeof(int)); for (cc=0; cc<Opt->clss->num; ++cc) { if ((key = SUMA_KeyofLabel_Dtable(vl_dtable, Opt->clss->str[cc]))<0){ ERROR_exit("(should noy happen) Key not found in %s for %s ", Opt->labeltable_name, Opt->clss->str[cc]); } Opt->keys[cc] = key; } } destroy_Dtable(vl_dtable); vl_dtable=NULL; } if (!Opt->keys) { /* add default keys */ SUMA_S_Note("Keys not available, assuming defaults"); Opt->keys = (int *)calloc(Opt->clss->num, sizeof(int)); for (cc=0; cc<Opt->clss->num; ++cc) { Opt->keys[cc] = cc+1; } } /* Show the match between keys and classes */ SUMA_ShowClssKeys(Opt->clss->str, Opt->clss->num, Opt->keys); /* For each feature, each class, collect the values */ SUMA_S_Notev("Collecting data from %d subjects\n", Opt->sig_names->num); missfeatwarn = -1; for (ss=0; ss<Opt->sig_names->num; ++ss) { /* for each subject */ /* load the input data */ if (!(Opt->sig = Seg_load_dset( Opt->sig_names->str[ss] ))) { exit(1); } if (Opt->debug > 1) { SUMA_S_Notev("Have %d sub-bricks in signatures of dude %d\n", DSET_NVALS(Opt->sig), ss); } if (ss == 0) { /* some setup based on initial grid */ if (!Opt->feats) { /* create features from signature */ char *allfeats=NULL; for (nn=0; nn<DSET_NVALS(Opt->sig); ++nn) { allfeats = SUMA_append_replace_string(allfeats, DSET_BRICK_LABEL(Opt->sig,nn),";", 1); } Opt->feats = NI_strict_decode_string_list(allfeats,";, "); SUMA_free(allfeats); allfeats=NULL; } SUMA_S_Notev("Have to work with %d classes, %d features\n", Opt->clss->num, Opt->feats->num); SUMA_S_Note("Initializing storage"); /* Receptacles for all observations for each feature and class combination */ FCset = (float ***)SUMA_calloc(Opt->feats->num, sizeof(float **)); N_FCset = (int **)SUMA_calloc(Opt->feats->num, sizeof(int *)); N_alloc_FCset = (int **)SUMA_calloc(Opt->feats->num, sizeof(int *)); ifeat = (int *)SUMA_calloc(Opt->feats->num, sizeof(int)); for (aa=0; aa<Opt->feats->num; ++aa) { FCset[aa] = (float **)calloc(Opt->clss->num, sizeof(float *)); N_FCset[aa] = (int *)SUMA_calloc(Opt->clss->num, sizeof(int)); N_alloc_FCset[aa] = (int *)SUMA_calloc(Opt->clss->num, sizeof(int)); } masks = (byte **)SUMA_calloc(Opt->sig_names->num, sizeof (byte *)); /* Fix VoxDbg */ if (Opt->VoxDbg >= 0) { Vox1D2Vox3D(Opt->VoxDbg, DSET_NX(Opt->sig), DSET_NX(Opt->sig)*DSET_NY(Opt->sig), Opt->VoxDbg3); } else if (Opt->VoxDbg3[0]>=0) { Opt->VoxDbg = Opt->VoxDbg3[0] + Opt->VoxDbg3[1]*DSET_NX(Opt->sig) + Opt->VoxDbg3[2]*DSET_NX(Opt->sig)*DSET_NY(Opt->sig); } } /* allocate for mask which will be non-zero whenever a voxel is in at least 1 mask. It will have the 1st assignment */ masks[ss] = (byte *)SUMA_calloc(DSET_NVOX(Opt->sig), sizeof(byte)); /* create mapping between feature names and sub-briks */ for (aa=0; aa<Opt->feats->num; ++aa) { ifeat[aa] = 0; while (ifeat[aa] < DSET_NVALS(Opt->sig) && strcmp(DSET_BRICK_LABEL(Opt->sig,ifeat[aa]), Opt->feats->str[aa])) ++ifeat[aa]; if (ifeat[aa] >= DSET_NVALS(Opt->sig)) ifeat[aa]=-1; if (Opt->debug > 1) { SUMA_S_Notev("Have feature %s in sub-brick %d\n", Opt->feats->str[aa], ifeat[aa]); } } SUMA_S_Notev("Loading sample classes for subject #%d\n", ss); if (!(Opt->samp = Seg_load_dset( Opt->samp_names->str[ss] ))) { exit(1); } if (THD_dataset_mismatch(Opt->samp, Opt->sig)) { SUMA_S_Err( "Grid mismatch between -samp [%dx%dx%d] and \n" " -sig [%dx%dx%d] volumes for pair #%d\n", DSET_NX(Opt->samp), DSET_NY(Opt->samp), DSET_NZ(Opt->samp), DSET_NX(Opt->sig), DSET_NY(Opt->sig), DSET_NZ(Opt->sig), ss); exit(1); } if (Opt->debug > 1) { SUMA_S_Notev("Have %d sub-bricks in samples of dude %d\n", DSET_NVALS(Opt->samp), ss); } /* Now collect features for each class */ SUMA_S_Note("Collecting features for each class"); for (cc=0; cc<Opt->clss->num; ++cc) { if (Opt->debug > 1) { SUMA_S_Notev("Working class %s\n", Opt->clss->str[cc]); } key = Opt->keys[cc]; for (nn=0; nn<DSET_NVALS(Opt->samp); ++nn) { if (Opt->debug > 2) { SUMA_S_Notev("Looking for key %d for class %s in sb %d\n", key, Opt->clss->str[cc], nn); } sb = (short *)DSET_ARRAY(Opt->samp,nn); fsb = DSET_BRICK_FACTOR(Opt->samp,nn); if (fsb == 0.0) fsb = 1.0; if (fsb != 1.0) { SUMA_S_Err("Non-integral dset, possibly."); exit(1); } for (vv=0; vv<DSET_NVOX(Opt->samp); ++vv) { if (sb[vv] == key) { for (aa=0; aa<Opt->feats->num; ++aa) { if (ifeat[aa]>-1) { if (N_alloc_FCset[aa][cc] <= N_FCset[aa][cc]) { N_alloc_FCset[aa][cc] += 10000; FCset[aa][cc] = (float*)SUMA_realloc(FCset[aa][cc], N_alloc_FCset[aa][cc]*sizeof(float)); } sf = (short *)DSET_ARRAY(Opt->sig, ifeat[aa]); fsf = DSET_BRICK_FACTOR(Opt->sig,ifeat[aa]); if (fsf == 0.0) fsf = 1.0; FCset[aa][cc][N_FCset[aa][cc]] = sf[vv]*fsf; ++N_FCset[aa][cc]; if (!masks[ss][vv]) { masks[ss][vv] = (short)key; /* fcfs */ /* in case we exceed short range */ if (masks[ss][vv]) masks[ss][vv] = 1; } } else { if (missfeatwarn != ss) { SUMA_S_Warnv("Feature %s not found in subject %d\n", Opt->feats->str[aa], ss); missfeatwarn = ss; } } } } } } } DSET_delete(Opt->sig); Opt->sig=NULL; DSET_delete(Opt->samp); Opt->samp=NULL; } /* loop across all subjects */ /* compute histograms of features across all classes and save them */ hf = (SUMA_HIST **)SUMA_calloc(Opt->feats->num, sizeof(SUMA_HIST *)); SUMA_S_Note("Computing histograms of features across all classes"); ff = NULL; N_ffalloc = 0; for (aa=0; aa<Opt->feats->num; ++aa) { N_ff=0; for (cc=0; cc<Opt->clss->num; ++cc) { N_ff += N_FCset[aa][cc]; /* more than I need because same voxel can belong to multiple classes, but just to be safe */ } if (N_ffalloc < N_ff) { N_ffalloc = N_ff; if (ff) SUMA_free(ff); ff=NULL; if (!(ff = (float*)SUMA_calloc(N_ff, sizeof(float)))) { SUMA_S_Crit("Failed to allocate"); exit(1); } } N_ff=0; isneg = 0; ff_m=0.0; for (ss=0; ss<Opt->sig_names->num; ++ss) { /* Once again, unfortunately */ /* load the input data */ if (!(Opt->sig = Seg_load_dset( Opt->sig_names->str[ss] ))) { exit(1); } if (Opt->debug > 1) { SUMA_S_Notev("Have %d sub-bricks in signatures of dude %d\n", DSET_NVALS(Opt->sig), ss); } if (ifeat[aa]>-1) { sb = (short *)DSET_ARRAY(Opt->sig,ifeat[aa]); fsb = DSET_BRICK_FACTOR(Opt->sig,ifeat[aa]); if (fsb == 0.0) fsb = 1.0; for (vv=0; vv<DSET_NVOX(Opt->sig); ++vv) { if (masks[ss][vv]) { ff[N_ff] = sb[vv]*fsb; if (ff[N_ff] < 0) ++isneg; ff_m += ff[N_ff]; ++N_ff; } } } DSET_delete(Opt->sig); Opt->sig=NULL; } ff_m /= N_ff; ff_s=0.0; for (iii=0; iii<N_ff; ++iii) { ff_s += SUMA_POW2(ff[iii]-ff_m); } ff_s = sqrt(ff_s/N_ff); sprintf(sbuf, "h(%s)",Opt->feats->str[aa]); /* Check if you have user specified binning specs */ bwidth = -1; nbins = -1; for (iii=0; iii<Opt->N_hspec; ++iii) { if (!strcmp(Opt->feats->str[aa], Opt->hspec[iii]->label)) { hrange[0] = Opt->hspec[iii]->min; hrange[1] = Opt->hspec[iii]->max; nbins = Opt->hspec[iii]->K; bwidth = 0; methods = "hands off sir"; break; } } if (bwidth < 0) { int nmatch = -1; /* Check the wildcard option */ for (iii=0; iii<Opt->N_hspec; ++iii) { if ((nmatch = SUMA_is_wild_hspec_label(Opt->hspec[iii]->label))>=0) { if (!nmatch || !strncmp(Opt->feats->str[aa], Opt->hspec[iii]->label, nmatch)) { SUMA_S_Note("Feature %s matched with hspec %s\n", Opt->feats->str[aa], Opt->hspec[iii]->label); hrange[0] = Opt->hspec[iii]->min; hrange[1] = Opt->hspec[iii]->max; nbins = Opt->hspec[iii]->K; bwidth = 0; methods = "hands woff sir"; break; } } } } if (bwidth < 0) { /* no user specs found */ nbins = 0; methods = "Range|OsciBinWidth"; if ((float)isneg/(float)N_ff*100.0 > 1.0) { hrange[0] = ff_m-3*ff_s; hrange[1] = ff_m+3*ff_s; bwidth = bwidth1*ff_s; } else if (ff_m-3*ff_s > 0) { hrange[0] = ff_m-3*ff_s; hrange[1] = ff_m+3*ff_s; bwidth = bwidth1*ff_s; } else { hrange[0] = 0; hrange[1] = 6.0*ff_s/2.0; bwidth = bwidth1*ff_s/2.0; } } SUMA_S_Notev("Feature %s: mean %f, std %f\n" "Hist params: [%f %f], binwidth %f\n", Opt->feats->str[aa], ff_m, ff_s, hrange[0], hrange[1], bwidth); if (!(hf[aa] = SUMA_hist_opt(ff, N_ff, nbins, bwidth, hrange, sbuf, 1, 0.1, methods))) { SUMA_S_Errv("Failed to generate histogram for %s. \n" "This will cause trouble at classification.\n", Opt->feats->str[aa]); } else { if ((float)hf[aa]->N_ignored/(float)hf[aa]->n > 0.05) { SUMA_S_Warnv("For histogram %s, %.2f%% of the samples were\n" "ignored for being outside the range [%f %f]\n", Opt->feats->str[aa], 100*(float)hf[aa]->N_ignored/(float)hf[aa]->n, hf[aa]->min, hf[aa]->max); } if (Opt->debug > 1) SUMA_Show_hist(hf[aa], 1, NULL); /* save the histogram */ if (!SUMA_write_hist(hf[aa], SUMA_hist_fname(Opt->proot, Opt->feats->str[aa], NULL, 0))) { SUMA_S_Errv("Failed to write histog to %s\n", sbuf); } } } if (ff) SUMA_free(ff); ff = NULL; /* Compute histograms of features per class && save them*/ hh = (SUMA_HIST ***)SUMA_calloc(Opt->feats->num, sizeof(SUMA_HIST **)); for (aa=0; aa<Opt->feats->num; ++aa) { hh[aa] = (SUMA_HIST **)SUMA_calloc(Opt->clss->num, sizeof(SUMA_HIST *)); } SUMA_S_Note("Computing histograms of features per class"); for (cc=0; cc<Opt->clss->num; ++cc) { if (N_FCset[0][cc] < 10) { SUMA_S_Errv("Requested class %s (%d) has just %d samples.\n" "Not enough to grease your pan.\n", Opt->clss->str[cc], Opt->keys[cc], N_FCset[0][cc]); exit(1); } for (aa=0; aa<Opt->feats->num; ++aa) { sprintf(sbuf, "h(%s|%s)",Opt->feats->str[aa], Opt->clss->str[cc]); hrange[0] = hf[aa]->min; hrange[1] = hf[aa]->max; /* Do not optimize hist range and binwidth anymore, but allow smoothing. This is needed when a particular class has very few samples */ if (!(hh[aa][cc] = SUMA_hist_opt(FCset[aa][cc], N_FCset[aa][cc], hf[aa]->K, hf[aa]->W, hrange, sbuf, 1, 0.1, "OsciSmooth"))) { SUMA_S_Errv("Failed to generate histogram for %s|%s. \n" "This will cause trouble at classification.\n", Opt->feats->str[aa], Opt->clss->str[cc]) } else { if (Opt->debug > 1) SUMA_Show_hist(hh[aa][cc], 1, NULL); /* save the histogram */ if (!SUMA_write_hist(hh[aa][cc], SUMA_hist_fname(Opt->proot, Opt->feats->str[aa], Opt->clss->str[cc], 0))) { SUMA_S_Errv("Failed to write histog to %s\n", sbuf); } } } } SUMA_S_Note("Computing Correlation matrices"); /* L2 normalize all of FCset */ for (cc=0; cc<Opt->clss->num; ++cc) { for (aa=0; aa<Opt->feats->num; ++aa) { THD_normalize(N_FCset[aa][cc], FCset[aa][cc]); } } { NI_element **CC=NULL; float *fm=NULL, *fn=NULL; NI_element *nel = NULL; int suc; /* Compute the correlation matrices for each class */ CC = (NI_element **) SUMA_calloc(Opt->clss->num, sizeof(NI_element *)); for(cc=0; cc<Opt->clss->num; ++cc) { sprintf(sbuf, "CorrMat(%s)", Opt->clss->str[cc]); CC[cc] = NI_new_data_element(sbuf, Opt->feats->num); NI_set_attribute(CC[cc],"Measure","correlation"); atr = SUMA_NI_str_ar_2_comp_str(Opt->feats, " ; "); NI_set_attribute(CC[cc],"ColumnLabels", atr);SUMA_free(atr); atr = NULL; atr = SUMA_HistString (FuncName, argc, argv, NULL); NI_set_attribute(CC[cc],"CommandLine", atr);SUMA_free(atr); atr = NULL; for (aa=0; aa<Opt->feats->num; ++aa) { NI_add_column_stride ( CC[cc], NI_FLOAT, NULL, 1 ); } for (aa=0; aa<Opt->feats->num; ++aa) { fm = (float*)CC[cc]->vec[aa]; for (iii=0; iii<aa; ++iii) fm[iii] = 0.0; /* will fill later */ fm[aa]=1.0; for (iii=aa+1; iii<Opt->feats->num; ++iii) { if (N_FCset[aa][cc]!=N_FCset[iii][cc]) { SUMA_S_Errv("Sanity check failed, %d != %d\n", N_FCset[aa][cc], N_FCset[iii][cc]); } SUMA_DOTP_VEC(FCset[aa][cc], FCset[iii][cc], fm[iii], N_FCset[aa][cc], float, float); } } /* Now fill the remainder */ for (aa=0; aa<Opt->feats->num; ++aa) { fm = (float*)CC[cc]->vec[aa]; for (iii=0; iii<aa; ++iii) { fn = (float*)CC[cc]->vec[iii]; fm[iii] = fn[aa]; } } snprintf(sbuf, 510, "file:%s.niml.cormat", SUMA_corrmat_fname(Opt->proot, Opt->clss->str[cc], 0)); NEL_WRITE_TXH(CC[cc], sbuf, suc); } } /* free everything */ if (FCset) { for (aa=0; aa<Opt->feats->num; ++aa) { for (cc=0; cc<Opt->clss->num; ++cc) { if (FCset[aa][cc]) SUMA_free(FCset[aa][cc]); } SUMA_free(FCset[aa]); } SUMA_free(FCset); FCset=NULL; } if (N_FCset) { for (aa=0; aa<Opt->feats->num; ++aa) { SUMA_free(N_FCset[aa]); } SUMA_free(N_FCset); N_FCset=NULL; } if (N_alloc_FCset) { for (aa=0; aa<Opt->feats->num; ++aa) { SUMA_free(N_alloc_FCset[aa]); } SUMA_free(N_alloc_FCset); N_alloc_FCset=NULL; } if (ifeat) SUMA_free(ifeat); ifeat=NULL; if (hh) { for (aa=0; aa<Opt->feats->num; ++aa) { for (cc=0; cc<Opt->clss->num; ++cc) { if (hh[aa][cc]) hh[aa][cc] = SUMA_Free_hist(hh[aa][cc]); } SUMA_free(hh[aa]); } SUMA_free(hh); hh=NULL; } if (hf) { for (aa=0; aa<Opt->feats->num; ++aa) { if (hf[aa]) hf[aa] = SUMA_Free_hist(hf[aa]); } SUMA_free(hf); hf=NULL; } if (masks) { for (ss=0; ss<Opt->sig_names->num; ++ss) { if (masks[ss]) SUMA_free(masks[ss]); } masks[ss]=NULL; } SUMA_S_Notev("\n" "Consider running this script to examine the distributions:\n" " @ExamineGenFeatDists -fdir %s -odir %s\n", Opt->proot, Opt->proot); /* all done, free */ Opt = free_SegOpts(Opt); PRINT_COMPILE_DATE ; exit(0); }
void UC_read_opts( int argc , char * argv[] ) { int nopt = 1 ; float val ; int kk, nxyz, mm,nn ; float * vv , * bb ; while( nopt < argc && argv[nopt][0] == '-' ){ /**** -verbose ****/ if( strncmp(argv[nopt],"-verbose",5) == 0 ){ UC_be_quiet = 0 ; nopt++ ; continue ; } /**** -ref file.1D ****/ if( strncmp(argv[nopt],"-ref",4) == 0 ){ MRI_IMAGE * im ; nopt++ ; if( nopt >= argc ) UC_syntax("-ref needs an argument!") ; im = mri_read( argv[nopt] ) ; if( im == NULL ) UC_syntax("Can't read -ref file!") ; if( im->kind == MRI_float ){ UC_ref = im ; } else { UC_ref = mri_to_float(im) ; mri_free(im) ; } im = mri_transpose(UC_ref) ; mri_free(UC_ref) ; UC_ref = im ; nopt++ ; continue ; } /**** -prefix prefix ****/ if( strncmp(argv[nopt],"-prefix",6) == 0 ){ nopt++ ; if( nopt >= argc ) UC_syntax("-prefix needs an argument!") ; MCW_strncpy( UC_prefix , argv[nopt++] , THD_MAX_PREFIX ) ; continue ; } /**** -mask mset ****/ if( strncmp(argv[nopt],"-mask",5) == 0 ){ THD_3dim_dataset * mset ; int ii ; nopt++ ; if( nopt >= argc ) UC_syntax("need arguments after -mask!") ; mset = THD_open_dataset( argv[nopt] ) ; if( mset == NULL ) UC_syntax("can't open -mask dataset!") ; UC_mask = THD_makemask( mset , 0 , 1.0,0.0 ) ; UC_mask_nvox = DSET_NVOX(mset) ; DSET_delete(mset) ; if( UC_mask == NULL ) UC_syntax("can't use -mask dataset!") ; UC_mask_hits = THD_countmask( UC_mask_nvox , UC_mask ) ; if( UC_mask_hits == 0 ) UC_syntax("mask is all zeros!") ; if( !UC_be_quiet ) printf("--- %d voxels in mask\n",UC_mask_hits) ; nopt++ ; continue ; } /**** unknown switch ****/ fprintf(stderr,"\n*** unrecognized option %s\n",argv[nopt]) ; exit(1) ; } /* end of loop over options */ /*--- a simple consistency check ---*/ /*--- last input is dataset name ---*/ if( nopt >= argc ) UC_syntax("no input dataset name?") ; UC_dset = THD_open_dataset( argv[nopt] ) ; if( !ISVALID_3DIM_DATASET(UC_dset) ){ fprintf(stderr,"\n*** can't open dataset file %s\n",argv[nopt]) ; exit(1) ; } nxyz = DSET_NVOX(UC_dset) ; if( UC_mask != NULL && nxyz != UC_mask_nvox ) UC_syntax("mask and input dataset size mismatch!") ; /*--- load vectors ---*/ UC_nvec = (UC_mask_hits > 0) ? UC_mask_hits : nxyz ; UC_vdim = DSET_NVALS(UC_dset) ; if( UC_vdim < 4 ) UC_syntax("input dataset needs at least 4 sub-bricks!") ; if( UC_ref == NULL || UC_ref->nx < UC_vdim ) UC_syntax("input ref not long enough for input dataset!") ; vv = (float *) malloc( sizeof(float) * UC_nvec * UC_vdim ) ; UC_vec = (float **) malloc( sizeof(float *) * UC_nvec ) ; for( kk=0 ; kk < UC_nvec ; kk++ ) UC_vec[kk] = vv + (kk*UC_vdim) ; if( !UC_be_quiet ) printf("--- reading dataset\n") ; DSET_load(UC_dset) ; CHECK_LOAD_ERROR(UC_dset) ; /* copy brick data into float storage */ if( !UC_be_quiet ) printf("--- loading vectors\n") ; bb = (float *) malloc( sizeof(float) * nxyz ) ; for( mm=0 ; mm < UC_vdim ; mm++ ){ EDIT_coerce_type( nxyz , DSET_BRICK_TYPE(UC_dset,mm) , DSET_ARRAY(UC_dset,mm) , MRI_float , bb ) ; DSET_unload_one( UC_dset , mm ) ; if( UC_mask == NULL ){ for( kk=0 ; kk < nxyz ; kk++ ) UC_vec[kk][mm] = bb[kk] ; } else { for( nn=kk=0 ; kk < nxyz ; kk++ ) if( UC_mask[kk] ) UC_vec[nn++][mm] = bb[kk] ; } } free(bb) ; DSET_unload( UC_dset ) ; /* detrend and normalize vectors */ if( !UC_be_quiet ) printf("--- normalizing vectors\n") ; for( kk=0 ; kk < UC_nvec ; kk++ ) normalize( UC_vdim , UC_vec[kk] ) ; for( kk=0 ; kk < UC_ref->ny ; kk++ ) normalize( UC_vdim , MRI_FLOAT_PTR(UC_ref) + kk*UC_ref->nx ) ; return ; }
/*! compute the overall minimum and maximum voxel values for a dataset */ int main( int argc , char * argv[] ) { THD_3dim_dataset * old_dset , * new_dset ; /* input and output datasets */ int nopt, nbriks; int slow_flag, quick_flag, min_flag, max_flag, mean_flag, automask,count_flag, sum_flag, var_flag, absolute_flag; int positive_flag, negative_flag, zero_flag, nan_flag, perc_flag, vol_flag; byte * mmm=NULL ; int mmvox=0 ; int nxyz, i; float *dvec = NULL, mmin=0.0, mmax=0.0; int N_mp; double *mpv=NULL, *perc = NULL; double mp =0.0f, mp0 = 0.0f, mps = 0.0f, mp1 = 0.0f, di =0.0f ; byte *mmf = NULL; MRI_IMAGE *anat_im = NULL; char *mask_dset_name=NULL; /*----- Read command line -----*/ mainENTRY("3dBrickStat main"); machdep(); AFNI_logger("3dBrickStat",argc,argv); nopt = 1 ; min_flag = 0; max_flag = -1; mean_flag = 0; sum_flag = 0; var_flag = 0; slow_flag = 0; quick_flag = -1; automask = 0; count_flag = 0; vol_flag = 0; positive_flag = -1; negative_flag = -1; absolute_flag = 0; zero_flag = -1; nan_flag = -1; perc_flag = 0; mmin = 1.0; mmax = -1.0; mask_dset_name = NULL; datum = MRI_float; while( nopt < argc && argv[nopt][0] == '-' ){ if( strcmp(argv[nopt],"-help") == 0 || strcmp(argv[nopt],"-h") == 0){ usage_3dBrickStat(strlen(argv[nopt])> 3 ? 2:1); exit(0); } if( strcmp(argv[nopt],"-ver") == 0 ){ PRINT_VERSION("3dBrickStat"); AUTHOR("Daniel Glen"); nopt++; continue; } if( strcmp(argv[nopt],"-quick") == 0 ){ quick_flag = 1; nopt++; continue; } if( strcmp(argv[nopt],"-percentile") == 0 ){ perc_flag = 1; ++nopt; if (nopt + 2 >= argc) { ERROR_exit( "** Error: Need 3 parameter after -percentile\n"); } mp0 = atof(argv[nopt])/100.0f; ++nopt; mps = atof(argv[nopt])/100.0f; ++nopt; mp1 = atof(argv[nopt])/100.0f; if (mps == 0.0f) { ERROR_exit( "** Error: step cannot be 0" ); } if (mp0 < 0 || mp0 > 100 || mp1 < 0 || mp1 > 100) { ERROR_exit( "** Error: p0 and p1 must be >=0 and <= 100" ); } nopt++; continue; } if( strcmp(argv[nopt],"-median") == 0 ){ perc_flag = 1; mp0 = 0.50f; mps = 0.01f; mp1 = 0.50f; nopt++; continue; } if( strcmp(argv[nopt],"-slow") == 0 ){ slow_flag = 1; nopt++; continue; } if( strcmp(argv[nopt],"-min") == 0 ){ min_flag = 1; nopt++; continue; } if( strcmp(argv[nopt],"-max") == 0 ){ max_flag = 1; nopt++; continue; } if( strcmp(argv[nopt],"-sum") == 0 ){ sum_flag = 1; nopt++; continue; } if( strcmp(argv[nopt],"-mean") == 0 ){ mean_flag = 1; nopt++; continue; } if( strcmp(argv[nopt],"-var") == 0 ){ if (var_flag) { ERROR_message("Looks like -stdev is already used.\n" "-var and -stdev are mutually exclusive"); exit (1); } var_flag = 1; nopt++; continue; } if( strcmp(argv[nopt],"-stdev") == 0 ){ if (var_flag) { ERROR_message("Looks like -var is already used.\n" "-var and -stdev are mutually exclusive"); exit (1); } var_flag = 2; nopt++; continue; } if( strcmp(argv[nopt],"-count") == 0 ){ count_flag = 1; nopt++; continue; } if( strcmp(argv[nopt],"-volume") == 0 ){ vol_flag = 1; nopt++; continue; } if( strcmp(argv[nopt],"-positive") == 0 ){ if(positive_flag!=-1) { ERROR_exit( "Can not use multiple +/-/0 options"); } positive_flag = 1; negative_flag = 0; zero_flag = 0; nopt++; continue; } if( strcmp(argv[nopt],"-negative") == 0 ){ if(positive_flag!=-1) { ERROR_exit( "Can not use multiple +/-/0 options"); } positive_flag = 0; negative_flag = 1; zero_flag = 0; nopt++; continue; } if( strcmp(argv[nopt],"-zero") == 0 ){ if(positive_flag!=-1) { ERROR_exit( "Can not use multiple +/-/0 options"); } positive_flag = 0; negative_flag = 0; zero_flag = 1; nopt++; continue; } if( strcmp(argv[nopt],"-non-positive") == 0 ){ if(positive_flag!=-1) { ERROR_exit( "Can not use multiple +/-/0 options"); } positive_flag = 0; negative_flag = 1; zero_flag = 1; nopt++; continue; } if( strcmp(argv[nopt],"-non-negative") == 0 ){ if(positive_flag!=-1) { ERROR_exit( "Can not use multiple +/-/0 options"); } positive_flag = 1; negative_flag = 0; zero_flag = 1; nopt++; continue; } if( strcmp(argv[nopt],"-non-zero") == 0 ){ if(positive_flag!=-1) { ERROR_exit( "Can not use multiple +/-/0 options"); } positive_flag = 1; negative_flag = 1; zero_flag = 0; nopt++; continue; } if( strcmp(argv[nopt],"-absolute") == 0 ){ absolute_flag = 1; nopt++; continue; } if( strcmp(argv[nopt],"-nan") == 0 ){ if(nan_flag!=-1) { ERROR_exit( "Can not use both -nan -nonan options"); } nan_flag = 1; nopt++; continue; } if( strcmp(argv[nopt],"-nonan") == 0 ){ if(nan_flag!=-1) { ERROR_exit( "Can not use both -nan -nonan options"); } nan_flag = 0; nopt++; continue; } if( strcmp(argv[nopt],"-autoclip") == 0 || strcmp(argv[nopt],"-automask") == 0 ){ if( mmm != NULL ){ ERROR_exit(" ERROR: can't use -autoclip/mask with -mask!"); } automask = 1 ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-mrange") == 0 ){ if (nopt+2 >= argc) { ERROR_exit(" ERROR: Need two values after -mrange"); } mmin = atof(argv[++nopt]); mmax = atof(argv[++nopt]); if (mmax < mmin) { ERROR_exit( "1st value in -mrange %s %s should be the smallest one", argv[nopt-1], argv[nopt]); } nopt++ ; continue ; } if( strcmp(argv[nopt],"-mvalue") == 0 ){ if (nopt+1 >= argc) { ERROR_exit(" ERROR: Need 1 value after -mvalue"); } mmin = atof(argv[++nopt]); mmax = mmin ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-mask") == 0 ){ if( mask_dset_name != NULL ) ERROR_exit(" ERROR: can't have 2 -mask options!"); mask_dset_name = argv[++nopt]; nopt++ ; continue ; } ERROR_message( " Error - unknown option %s", argv[nopt]); suggest_best_prog_option(argv[0], argv[nopt]); exit(1); } if( argc < 2 || strcmp(argv[1],"-help") == 0 ){ ERROR_message("Too few options"); usage_3dBrickStat(0); exit(1) ; } if (mask_dset_name) { int ninmask = 0; THD_3dim_dataset * mask_dset ; if( automask ){ ERROR_exit(" ERROR: can't use -mask with -automask!"); } mask_dset = THD_open_dataset(mask_dset_name) ; CHECK_OPEN_ERROR(mask_dset,mask_dset_name) ; mmm = THD_makemask( mask_dset , 0 , mmin, mmax ) ; mmvox = DSET_NVOX( mask_dset ) ; ninmask = THD_countmask (mmvox, mmm); if (!ninmask) { ERROR_exit(" No voxels in mask !"); } /* text output program, so avoid extras 26 Dec 2013 [rickr] */ /* INFO_message("%d voxels in mask\n", ninmask); */ DSET_delete(mask_dset) ; } if(((mmm!=NULL) && (quick_flag))||(automask &&quick_flag)) { if(quick_flag==1) WARNING_message( "+++ Warning - can't have quick option with mask"); quick_flag = 0; slow_flag = 1; } /* if max_flag is not set by user, check if other user options set */ if(max_flag==-1) { if(min_flag || mean_flag || count_flag || vol_flag || sum_flag || perc_flag || var_flag) max_flag = 0; else max_flag = 1; /* otherwise check only for max */ } if((var_flag==1)||(mean_flag==1)||(count_flag==1)|| (vol_flag==1)||(absolute_flag==1) || (positive_flag!=-1)||(nan_flag!=-1)|| (sum_flag == 1)||(perc_flag == 1) || (var_flag==2)) { /* mean flag or count_flag implies slow */ slow_flag = 1; } /* check slow and quick options */ if((slow_flag)&&(quick_flag!=1)) /* if user asked for slow give it to him */ quick_flag = 0; else quick_flag = 1; if((max_flag==0)&&(min_flag==0)) /* if the user only asked for mean */ quick_flag = 0; /* no need to do quick way */ if((quick_flag) && ((absolute_flag==1)||(positive_flag==1)||(negative_flag==1)||(zero_flag==1))) WARNING_message( " Warning - ignoring +/-/0/abs flags for quick computations"); if(positive_flag==-1) { /* if no +/-/0 options set, allow all voxels */ positive_flag = 1; negative_flag = 1; zero_flag = 1; } /*----- read input dataset -----*/ if( nopt >= argc ){ ERROR_exit(" No input dataset!?"); } old_dset = THD_open_dataset( argv[nopt] ) ; CHECK_OPEN_ERROR(old_dset,argv[nopt]) ; nxyz = DSET_NVOX(old_dset) ; if( mmm != NULL && mmvox != nxyz ){ ERROR_exit(" Mask and input datasets not the same size!") ; } if(automask && mmm == NULL ){ mmm = THD_automask( old_dset ) ; for(i=0;i<nxyz;i++) { if(mmm[i]!=0) ++mmvox; } } if(quick_flag) Print_Header_MinMax(min_flag, max_flag, old_dset); if(slow_flag!=1) exit(0); /* ZSS do some diddlyiddly sorting - DO not affect Daniel's function later on*/ if (perc_flag == 1) { DSET_mallocize (old_dset); DSET_load (old_dset); if (DSET_NVALS(old_dset) != 1) { ERROR_exit( "-percentile can only be used on one sub-brick only.\n" "Use sub-brick selectors '[.]' to specify sub-brick of interest.\n"); } /* prep for input and output of percentiles */ if (mp0 > mp1) { N_mp = 1; } else { /* allocate one above ceiling to prevent truncation error (and crash), N_mp is recomputed anyway 16 Mar 2009 [rickr] */ N_mp = (int)((double)(mp1-mp0)/(double)mps) + 2; } mpv = (double *)malloc(sizeof(double)*N_mp); perc = (double *)malloc(sizeof(double)*N_mp); if (!mpv || !perc) { ERROR_message("Failed to allocate for mpv or perc"); exit(1); } N_mp = 0; mp = mp0; do { mpv[N_mp] = mp; ++N_mp; mp += mps; } while (mp <= mp1+.00000001); if (!Percentate (DSET_ARRAY(old_dset, 0), mmm, nxyz, DSET_BRICK_TYPE(old_dset,0), mpv, N_mp, 0, perc, zero_flag, positive_flag, negative_flag )) { ERROR_message("Failed to compute percentiles."); exit(1); } /* take care of brick factor */ if (DSET_BRICK_FACTOR(old_dset,0)) { for (i=0; i<N_mp; ++i) { perc[i] = perc[i]*DSET_BRICK_FACTOR(old_dset,0); } } for (i=0; i<N_mp; ++i) { fprintf(stdout,"%.1f %f ", mpv[i]*100.0f, perc[i]); } free(mpv); mpv = NULL; free(perc); perc = NULL; } Max_func(min_flag, max_flag, mean_flag,count_flag, positive_flag, negative_flag, zero_flag, absolute_flag, nan_flag, sum_flag, var_flag, vol_flag,old_dset, mmm, mmvox); if(mmm!=NULL) free(mmm); exit(0); /* unused code time series method for extracting data */ #if 0 EDIT_dset_items( old_dset , ADN_ntt , DSET_NVALS(old_dset) , ADN_ttorg , 0.0 , ADN_ttdel , 1.0 , ADN_tunits , UNITS_SEC_TYPE , NULL ) ; nbriks = 1; /*------------- ready to compute new min, max -----------*/ new_dset = MAKER_4D_to_typed_fbuc( old_dset , /* input dataset */ "temp" , /* output prefix */ datum , /* output datum */ 0 , /* ignore count */ 0 , /* can't detrend in maker function KRH 12/02*/ nbriks , /* number of briks */ Max_tsfunc , /* timeseries processor */ NULL, /* data for tsfunc */ NULL, /* mask */ 0 /* Allow auto scaling of output */ ) ; if(min_flag) printf("%-13.6g ", minvalue); if(max_flag) printf("%-13.6g", maxvalue); printf("\n"); exit(0) ; #endif }
static char * BFIT_main( PLUGIN_interface * plint ) { MCW_idcode * idc ; THD_3dim_dataset * input_dset , * mask_dset = NULL ; BFIT_data * bfd ; BFIT_result * bfr ; int nvals,ival , nran,nvox , nbin , miv=0 , sqr,sqt ; float abot,atop,bbot,btop,pcut , eps,eps1 , hlast ; float *bval , *cval ; double aa,bb,xc ; double chq,ccc,cdf ; int ihqbot,ihqtop ; int mcount,mgood , ii , jj , ibot,itop ; float mask_bot=666.0 , mask_top=-666.0 , hbot,htop,dbin ; char buf[THD_MAX_NAME+128] , tbuf[THD_MAX_NAME+128] , * tag ; int * hbin , * jbin,*kbin=NULL , *jist[2] ; MRI_IMAGE * flim ; double aext=-1.0,bext=-1.0 ; /*--------------------------------------------------------------------*/ /*----- Check inputs from AFNI to see if they are reasonable-ish -----*/ if( plint == NULL ) return "************************\n" "BFIT_main: NULL input\n" "************************" ; /*-- read 1st line --*/ PLUTO_next_option(plint) ; idc = PLUTO_get_idcode(plint) ; input_dset = PLUTO_find_dset(idc) ; if( input_dset == NULL ) return "****************************\n" "BFIT_main: bad input dataset\n" "****************************" ; nvox = DSET_NVOX(input_dset) ; nvals = DSET_NVALS(input_dset) ; ival = (int) PLUTO_get_number(plint) ; if( ival < 0 || ival >= nvals ) return "**************************\n" "BFIT_main: bad Brick index\n" "**************************" ; DSET_load(input_dset) ; if( DSET_ARRAY(input_dset,0) == NULL ) return "*****************************\n" "BFIT_main: can't load dataset\n" "*****************************" ; tag = PLUTO_get_string(plint) ; sqr = PLUTO_string_index(tag,NYESNO,YESNO_strings) ; /*-- read 2nd line --*/ PLUTO_next_option(plint) ; abot = PLUTO_get_number(plint) ; atop = PLUTO_get_number(plint) ; if( atop <= abot ) return "*** atop <= abot! ***" ; PLUTO_next_option(plint) ; bbot = PLUTO_get_number(plint) ; btop = PLUTO_get_number(plint) ; if( atop <= abot ) return "*** btop <= bbot! ***" ; hlast = PLUTO_get_number(plint) ; PLUTO_next_option(plint) ; nran = (int) PLUTO_get_number(plint) ; pcut = PLUTO_get_number(plint) ; tag = PLUTO_get_string(plint) ; sqt = PLUTO_string_index(tag,NYESNO,YESNO_strings) ; /*-- read optional lines --*/ while( (tag=PLUTO_get_optiontag(plint)) != NULL ){ /*-- Mask itself --*/ if( strcmp(tag,"Mask") == 0 ){ idc = PLUTO_get_idcode(plint) ; mask_dset = PLUTO_find_dset(idc) ; if( mask_dset == NULL ){ return "******************************\n" "BFIT_main: bad mask dataset\n" "******************************" ; } if( DSET_NVOX(mask_dset) != nvox ){ return "************************************************************\n" "BFIT_main: mask input dataset doesn't match source dataset\n" "************************************************************" ; } miv = (int) PLUTO_get_number(plint) ; if( miv >= DSET_NVALS(mask_dset) || miv < 0 ){ return "****************************************************\n" "BFIT_main: mask dataset sub-brick index is illegal\n" "****************************************************" ; } DSET_load(mask_dset) ; if( DSET_ARRAY(mask_dset,miv) == NULL ){ return "*************************************\n" "BFIT_main: can't load mask dataset\n" "*************************************" ; } continue ; } /*-- Mask range of values --*/ if( strcmp(tag,"Range") == 0 ){ if( mask_dset == NULL ){ return "******************************************\n" "BFIT_main: Can't use Range without Mask\n" "******************************************" ; } mask_bot = PLUTO_get_number(plint) ; mask_top = PLUTO_get_number(plint) ; continue ; } /*-- Extra plot --*/ if( strcmp(tag,"Extra") == 0 ){ aext = PLUTO_get_number(plint) ; bext = PLUTO_get_number(plint) ; continue ; } } /*------------------------------------------------------*/ /*---------- At this point, the inputs are OK ----------*/ bfd = BFIT_prepare_dataset( input_dset , ival , sqr , mask_dset , miv , mask_bot , mask_top ) ; if( bfd == NULL ) return "*** BFIT_prepare_dataset fails ***" ; bfr = BFIT_compute( bfd , pcut , abot,atop , bbot,btop , nran,200 ) ; if( bfr == NULL ){ BFIT_free_data( bfd ) ; return "*** BFIT_compute fails! ***" ; } itop = bfr->itop ; mgood = bfr->mgood ; ibot = bfd->ibot ; bval = bfd->bval ; cval = bfd->cval ; mcount = bfd->mcount ; xc = bfr->xcut ; aa = bfr->a ; bb = bfr->b ; eps = bfr->eps ; eps1 = 1.0 - eps ; if( eps1 > 1.0 ) eps1 = 1.0 ; eps1 = (mcount-ibot) * eps1 ; /*-- compute and plot histogram --*/ /* original data was already squared (e.g., R**2 values) */ if( !sqr ){ hbot = 0.0 ; htop = 1.0 ; nbin = 200 ; if( bval[mcount-1] < 1.0 ) htop = bval[mcount-1] ; dbin = (htop-hbot)/nbin ; hbin = (int *) calloc((nbin+1),sizeof(int)) ; /* actual histogram */ jbin = (int *) calloc((nbin+1),sizeof(int)) ; /* theoretical fit */ for( ii=0 ; ii < nbin ; ii++ ){ /* beta fit */ jbin[ii] = (int)( eps1 * ( beta_t2p(hbot+ii*dbin,aa,bb) -beta_t2p(hbot+ii*dbin+dbin,aa,bb) ) ) ; } jist[0] = jbin ; flim = mri_new_vol_empty( mcount-ibot,1,1 , MRI_float ) ; mri_fix_data_pointer( bval+ibot , flim ) ; mri_histogram( flim , hbot,htop , TRUE , nbin,hbin ) ; /* "extra" histogram (nominal values?) */ if( aext > 0.0 ){ kbin = (int *) calloc((nbin+1),sizeof(int)) ; jist[1] = kbin ; for( ii=0 ; ii < nbin ; ii++ ){ /* beta fit */ kbin[ii] = (int)( eps1 * ( beta_t2p(hbot+ii*dbin,aext,bext) -beta_t2p(hbot+ii*dbin+dbin,aext,bext) ) ) ; } } } else { /* original data was not squared (e.g., correlations) */ double hb,ht ; htop = 1.0 ; nbin = 200 ; if( bval[mcount-1] < 1.0 ) htop = sqrt(bval[mcount-1]) ; hbot = -htop ; dbin = (htop-hbot)/nbin ; hbin = (int *) calloc((nbin+1),sizeof(int)) ; /* actual histogram */ jbin = (int *) calloc((nbin+1),sizeof(int)) ; /* theoretical fit */ for( ii=0 ; ii < nbin ; ii++ ){ /* beta fit */ hb = hbot+ii*dbin ; ht = hb+dbin ; hb = hb*hb ; ht = ht*ht ; if( hb > ht ){ double qq=hb ; hb=ht ; ht=qq ; } jbin[ii] = (int)( 0.5*eps1 * ( beta_t2p(hb,aa,bb) -beta_t2p(ht,aa,bb) ) ) ; } jist[0] = jbin ; flim = mri_new_vol_empty( mcount-ibot,1,1 , MRI_float ) ; mri_fix_data_pointer( cval+ibot , flim ) ; mri_histogram( flim , hbot,htop , TRUE , nbin,hbin ) ; /* nominal fit */ if( aext > 0.0 ){ kbin = (int *) calloc((nbin+1),sizeof(int)) ; jist[1] = kbin ; for( ii=0 ; ii < nbin ; ii++ ){ /* beta fit */ hb = hbot+ii*dbin ; ht = hb+dbin ; hb = hb*hb ; ht = ht*ht ; if( hb > ht ){ double qq=hb ; hb=ht ; ht=qq ; } kbin[ii] = (int)( 0.5*eps1 * ( beta_t2p(hb,aext,bext) -beta_t2p(ht,aext,bext) ) ) ; } } } sprintf(buf,"%s[%d] a=%.2f b=%.2f \\epsilon=%.2f %%=%.0f", DSET_FILECODE(input_dset),ival,aa,bb,eps,pcut ) ; ccc = bfr->q_chisq ; /* blow up histogram details by sqrt-ing, if ordered */ if( sqt ){ for( ii=0 ; ii < nbin ; ii++ ){ hbin[ii] = (int) sqrt( (double)(100*hbin[ii]+0.5) ) ; jbin[ii] = (int) sqrt( (double)(100*jbin[ii]+0.5) ) ; if( kbin!=NULL ) kbin[ii] = (int) sqrt( (double)(100*kbin[ii]+0.5) ) ; } } /* and plot */ sprintf(tbuf,"\\beta fit: cutoff=%.2f nvox=%d q(\\chi^2)=%8.2e", (sqr)?sqrt(xc):xc , mgood , ccc ) ; if( sqt ){ ii = strlen(tbuf) ; sprintf( tbuf+ii , " \\surd ogram" ) ; } if( hlast > 0.0 ){ hbin[nbin-1] = jbin[nbin-1] = hlast ; if( kbin != NULL ) kbin[nbin-1] = hlast ; } PLUTO_histoplot( nbin,hbot,htop,hbin , tbuf,NULL,buf , (kbin==NULL)?1:2 , jist ) ; /* cleanup */ mri_clear_data_pointer(flim) ; mri_free(flim) ; free(hbin) ; free(jbin) ; if( kbin != NULL ) free(kbin); BFIT_free_data(bfd) ; BFIT_free_result(bfr) ; return NULL ; }
THD_3dim_dataset * fim3d_fimmer_compute ( THD_3dim_dataset * dset_time , time_series_array * ref_ts , time_series_array * ort_ts , int itbot, char * new_prefix, float max_percent /* 19 May 1997 */ ) { THD_3dim_dataset * new_dset ; int ifim , it,iv , nvox=0 , ngood_ref , ntime , it1 , dtyp , nxyz; float * vval , * tsar , * aval , * rbest , * abest ; int * indx=NULL ; short * bar ; void * ptr ; float stataux[MAX_STAT_AUX]; float fthr , topval ; int nx_ref , ny_ref , ivec , nnow ; PCOR_references ** pc_ref ; PCOR_voxel_corr ** pc_vc ; int save_resam ; int fim_nref , nx_ort , ny_ort=0 , internal_ort ; /* 10 Dec 1996 */ static float * ref_vec = NULL ; static int nref_vec = -666 ; float * ref_ts_min = NULL, * ref_ts_max = NULL, * baseline = NULL; /* 19 May 1997 */ int i; int nupdt = 0 , /* number of updates done yet */ min_updt = 5 ; /* min number needed for display */ /*--- check for legal inputs ---*/ /* 14 Jan 1998 */ if (!DSET_GRAPHABLE(dset_time)) { fprintf (stderr, "Error: Invalid 3d+time input data file \n"); RETURN (NULL); } if (ref_ts == NULL) { fprintf (stderr, "Error: No ideal time series \n"); RETURN (NULL); } for (i = 0; i < ref_ts->num; i++) if (ref_ts->tsarr[i]->len < DSET_NUM_TIMES(dset_time)) { fprintf (stderr, "Error: ideal time series is too short: ntime=%d num_ts=%d \n", DSET_NUM_TIMES(dset_time), ref_ts->tsarr[i]->len); RETURN (NULL) ; } /** 10 Dec 1996: allow for orts **/ if( ort_ts->num > 0 ) /** 05 Sept 1997 **/ { internal_ort = 0; ny_ort = ort_ts->num; for (i = 0; i < ny_ort; i++) { nx_ort = ort_ts->tsarr[i]->len ; if (nx_ort < DSET_NUM_TIMES(dset_time)) /* 14 Jan 1998 */ { fprintf (stderr, "Error: ort time series is too short: ntime=%d ort_ts=%d \n", DSET_NUM_TIMES(dset_time), ort_ts->tsarr[i]->len); RETURN (NULL) ; } } } else { internal_ort = 1 ; } fim_nref = (internal_ort) ? 3 : (ny_ort+3) ; if( nref_vec < fim_nref ) { ref_vec = (float *) malloc (sizeof(float)*fim_nref) ; nref_vec = fim_nref; } /* arrays to store maximum change in the ideal time series */ if (max_percent > 0.0) /* 19 May 1997 */ { ref_ts_max = (float *) malloc (sizeof(float) * (ref_ts->num)); ref_ts_min = (float *) malloc (sizeof(float) * (ref_ts->num)); } nx_ref = ref_ts->tsarr[0]->len; ny_ref = ref_ts->num; ntime = DSET_NUM_TIMES(dset_time) ; ngood_ref = 0 ; it1 = -1 ; for( ivec=0 ; ivec < ny_ref ; ivec++ ){ tsar = ref_ts->tsarr[ivec]->ts; ifim = 0 ; if (max_percent > 0.0) /* 19 May 1997 */ { ref_ts_min[ivec] = (float) SO_BIG; ref_ts_max[ivec] = - (float) SO_BIG; } for( it=itbot ; it < ntime ; it++ ) { if( tsar[it] < SO_BIG ) { ifim++ ; if( it1 < 0 ) it1 = it ; if (max_percent > 0.0) /* 19 May 1997 */ { if (tsar[it] > ref_ts_max[ivec]) ref_ts_max[ivec] = tsar[it]; if (tsar[it] < ref_ts_min[ivec]) ref_ts_min[ivec] = tsar[it]; } } } if( ifim < min_updt ){ STATUS("ref_ts has too few good entries!") ; RETURN(NULL) ; } ngood_ref = MAX( ifim , ngood_ref ) ; } /** at this point, ngood_ref = max number of good reference points, and it1 = index of first point used in first reference **/ dtyp = DSET_BRICK_TYPE(dset_time,it1) ; if( ! AFNI_GOOD_FUNC_DTYPE(dtyp) ){ STATUS("illegal input data type!") ; RETURN(NULL) ; } #ifdef AFNI_DEBUG { char str[256] ; sprintf(str,"new prefix = %s",new_prefix) ; STATUS(str) ; } #endif /*--- FIM: find values above threshold to fim ---*/ DSET_load(dset_time); CHECK_LOAD_ERROR(dset_time); nxyz = dset_time->dblk->diskptr->dimsizes[0] * dset_time->dblk->diskptr->dimsizes[1] * dset_time->dblk->diskptr->dimsizes[2] ; /** find the mean of the first array, compute the threshold (fthr) from it, make indx[i] be the 3D index of the i-th voxel above threshold **/ switch( dtyp ){ case MRI_short:{ short * dar = (short *) DSET_ARRAY(dset_time,it1) ; for( iv=0,fthr=0.0 ; iv < nxyz ; iv++ ) fthr += abs(dar[iv]) ; fthr = FIM_THR * fthr / nxyz ; for( iv=0,nvox=0 ; iv < nxyz ; iv++ ) if( abs(dar[iv]) > fthr ) nvox++ ; indx = (int *) malloc( sizeof(int) * nvox ) ; if( indx == NULL ){ fprintf(stderr,"\n*** indx malloc failure in fim3d_fimmer_compute\n") ; RETURN(NULL) ; } for( iv=0,nvox=0 ; iv < nxyz ; iv++ ) if( abs(dar[iv]) > fthr ) indx[nvox++] = iv ; } break ; case MRI_float:{ float * dar = (float *) DSET_ARRAY(dset_time,it1) ; for( iv=0,fthr=0.0 ; iv < nxyz ; iv++ ) fthr += fabs(dar[iv]) ; fthr = FIM_THR * fthr / nxyz ; for( iv=0,nvox=0 ; iv < nxyz ; iv++ ) if( fabs(dar[iv]) > fthr ) nvox++ ; indx = (int *) malloc( sizeof(int) * nvox ) ; if( indx == NULL ){ fprintf(stderr,"\n*** indx malloc failure in fim3d_fimmer_compute\n") ; RETURN(NULL) ; } for( iv=0,nvox=0 ; iv < nxyz ; iv++ ) if( fabs(dar[iv]) > fthr ) indx[nvox++] = iv ; } break ; case MRI_byte:{ byte * dar = (byte *) DSET_ARRAY(dset_time,it1) ; for( iv=0,fthr=0.0 ; iv < nxyz ; iv++ ) fthr += dar[iv] ; fthr = FIM_THR * fthr / nxyz ; for( iv=0,nvox=0 ; iv < nxyz ; iv++ ) if( dar[iv] > fthr ) nvox++ ; indx = (int *) malloc( sizeof(int) * nvox ) ; if( indx == NULL ){ fprintf(stderr,"\n*** indx malloc failure in fim3d_fimmer_compute\n") ; RETURN(NULL) ; } for( iv=0,nvox=0 ; iv < nxyz ; iv++ ) if( dar[iv] > fthr ) indx[nvox++] = iv ; } break ; } /** allocate space for voxel values **/ vval = (float *) malloc( sizeof(float) * nvox) ; if( vval == NULL ){ fprintf(stderr,"\n*** vval malloc failure in fim3d_fimmer_compute\n") ; free(indx) ; RETURN(NULL) ; } /*----- allocate space for baseline values -----*/ if (max_percent > 0.0) /* 19 May 1997 */ { baseline = (float *) malloc (sizeof(float) * nvox); if (baseline == NULL) { fprintf(stderr, "\n*** baseline malloc failure in fim3d_fimmer_compute\n") ; free(indx) ; free(vval); RETURN(NULL) ; } else /* initialize baseline values to zero */ for (iv = 0; iv < nvox; iv++) baseline[iv] = 0.0; } /** allocate extra space for comparing results from multiple ref vectors **/ if( ny_ref > 1 ){ aval = (float *) malloc( sizeof(float) * nvox) ; rbest = (float *) malloc( sizeof(float) * nvox) ; abest = (float *) malloc( sizeof(float) * nvox) ; if( aval==NULL || rbest==NULL || abest==NULL ){ fprintf(stderr,"\n*** abest malloc failure in fim3d_fimmer_compute\n") ; free(vval) ; free(indx) ; if( aval != NULL ) free(aval) ; if( rbest != NULL ) free(rbest) ; if( abest != NULL ) free(abest) ; RETURN(NULL) ; } } else { aval = rbest = abest = NULL ; } #ifdef AFNI_DEBUG { char str[256] ; sprintf(str,"nxyz = %d nvox = %d",nxyz,nvox) ; STATUS(str) ; } #endif /*--- FIM: initialize recursive updates ---*/ pc_ref = (PCOR_references **) malloc( sizeof(PCOR_references *) * ny_ref ) ; pc_vc = (PCOR_voxel_corr **) malloc( sizeof(PCOR_voxel_corr *) * ny_ref ) ; if( pc_ref == NULL || pc_vc == NULL ){ free(vval) ; free(indx) ; free(pc_ref) ; free(pc_vc) ; if( aval != NULL ) free(aval) ; if( rbest != NULL ) free(rbest) ; if( abest != NULL ) free(abest) ; fprintf(stderr,"\n*** FIM initialization fails in fim3d_fimmer_compute\n") ; RETURN(NULL) ; } ifim = 0 ; for( ivec=0 ; ivec < ny_ref ; ivec++ ){ pc_ref[ivec] = new_PCOR_references( fim_nref ) ; pc_vc[ivec] = new_PCOR_voxel_corr( nvox , fim_nref ) ; if( pc_ref[ivec] == NULL || pc_vc[ivec] == NULL ) ifim++ ; } if( ifim > 0 ){ for( ivec=0 ; ivec < ny_ref ; ivec++ ){ free_PCOR_references(pc_ref[ivec]) ; free_PCOR_voxel_corr(pc_vc[ivec]) ; } free(vval) ; free(indx) ; free(pc_ref) ; free(pc_vc) ; if( aval != NULL ) free(aval) ; if( rbest != NULL ) free(rbest) ; if( abest != NULL ) free(abest) ; fprintf(stderr,"\n*** FIM initialization fails in fim3d_fimmer_compute\n") ; RETURN(NULL) ; } /*--- Make a new dataset to hold the output ---*/ new_dset = EDIT_empty_copy( dset_time ) ; it = EDIT_dset_items( new_dset , ADN_prefix , new_prefix , ADN_malloc_type , DATABLOCK_MEM_MALLOC , ADN_type , ISHEAD(dset_time) ? HEAD_FUNC_TYPE : GEN_FUNC_TYPE , ADN_func_type , FUNC_COR_TYPE , ADN_nvals , FUNC_nvals[FUNC_COR_TYPE] , ADN_datum_all , MRI_short , ADN_ntt , 0 , ADN_none ) ; if( it > 0 ){ fprintf(stderr, "\n*** EDIT_dset_items error %d in fim3d_fimmer_compute\n",it) ; THD_delete_3dim_dataset( new_dset , False ) ; for( ivec=0 ; ivec < ny_ref ; ivec++ ){ free_PCOR_references(pc_ref[ivec]) ; free_PCOR_voxel_corr(pc_vc[ivec]) ; } free(vval) ; free(indx) ; free(pc_ref) ; free(pc_vc) ; if( aval != NULL ) free(aval) ; if( rbest != NULL ) free(rbest) ; if( abest != NULL ) free(abest) ; RETURN(NULL) ; } for( iv=0 ; iv < new_dset->dblk->nvals ; iv++ ){ ptr = malloc( DSET_BRICK_BYTES(new_dset,iv) ) ; mri_fix_data_pointer( ptr , DSET_BRICK(new_dset,iv) ) ; } if( THD_count_databricks(new_dset->dblk) < new_dset->dblk->nvals ){ fprintf(stderr, "\n*** failure to malloc new bricks in fim3d_fimmer_compute\n") ; THD_delete_3dim_dataset( new_dset , False ) ; for( ivec=0 ; ivec < ny_ref ; ivec++ ){ free_PCOR_references(pc_ref[ivec]) ; free_PCOR_voxel_corr(pc_vc[ivec]) ; } free(vval) ; free(indx) ; free(pc_ref) ; free(pc_vc) ; if( aval != NULL ) free(aval) ; if( rbest != NULL ) free(rbest) ; if( abest != NULL ) free(abest) ; RETURN(NULL) ; } /*--- FIM: do recursive updates ---*/ for( it=itbot ; it < ntime ; it++ ){ nnow = 0 ; for( ivec=0 ; ivec < ny_ref ; ivec++ ){ tsar = ref_ts->tsarr[ivec]->ts ; if( tsar[it] >= SO_BIG ) continue ; /* skip this */ ref_vec[0] = 1.0 ; /* we always supply orts */ ref_vec[1] = (float) it ; /* for mean and linear trend */ if (internal_ort) /* 10 Dec 1996 */ { ref_vec[2] = tsar[it] ; } else { for( iv=0 ; iv < ny_ort ; iv++ ) ref_vec[iv+2] = ort_ts->tsarr[iv]->ts[it]; ref_vec[ny_ort+2] = tsar[it] ; } #ifdef AFNI_DEBUG { char str[256] ; sprintf(str,"time index=%d ideal[%d]=%f" , it,ivec,tsar[it] ) ; if (ivec == 0) STATUS(str) ; } #endif update_PCOR_references( ref_vec , pc_ref[ivec] ) ; switch( dtyp ){ case MRI_short:{ short * dar = (short *) DSET_ARRAY(dset_time,it) ; for( iv=0 ; iv < nvox ; iv++ ) vval[iv] = (float) dar[indx[iv]] ; } break ; case MRI_float:{ float * dar = (float *) DSET_ARRAY(dset_time,it) ; for( iv=0 ; iv < nvox ; iv++ ) vval[iv] = (float) dar[indx[iv]] ; } break ; case MRI_byte:{ byte * dar = (byte *) DSET_ARRAY(dset_time,it) ; for( iv=0 ; iv < nvox ; iv++ ) vval[iv] = (float) dar[indx[iv]] ; } break ; } PCOR_update_float( vval , pc_ref[ivec] , pc_vc[ivec] ) ; nnow++ ; /*----- update baseline value calculation -----*/ if (max_percent > 0.0) /* 19 May 1997 */ if (ivec == 0) for (iv = 0; iv < nvox; iv++) baseline[iv] += vval[iv] / ngood_ref; } if( nnow > 0 ) nupdt++ ; /*--- Load results into the dataset and redisplay it ---*/ if( nupdt == ngood_ref ) { /*--- set the statistical parameters ---*/ stataux[0] = nupdt ; /* number of points used */ stataux[1] = (ny_ref==1) ? 1 : 2 ; /* number of references */ stataux[2] = fim_nref - 1 ; /* number of orts */ /* 12 Dec 96 */ for( iv=3 ; iv < MAX_STAT_AUX ; iv++ ) stataux[iv] = 0.0 ; STATUS("setting statistical parameters") ; (void) EDIT_dset_items( new_dset , ADN_stat_aux , stataux , ADN_none ) ; /*** Compute brick arrays for new dataset ***/ if( ny_ref == 1 ){ /*** Just 1 ref vector --> load values directly into dataset ***/ /*--- get alpha (coef) into vval, find max value, scale into brick array ---*/ STATUS("getting 1 ref alpha") ; PCOR_get_coef( pc_ref[0] , pc_vc[0] , vval ) ; /*--- replace alpha with percentage change, if so requested ---*/ if (max_percent > 0.0) /* 19 May 1997 */ { for (iv = 0; iv < nvox; iv++) { vval[iv] *= 100.0 * (ref_ts_max[0] - ref_ts_min[0]); if (fabs(vval[iv]) < max_percent * fabs(baseline[iv])) vval[iv] = fabs( vval[iv] / baseline[iv] ); else vval[iv] = max_percent; } topval = max_percent; } else { topval = 0.0 ; for( iv=0 ; iv < nvox ; iv++ ) if( fabs(vval[iv]) > topval ) topval = fabs(vval[iv]) ; } bar = DSET_ARRAY( new_dset , FUNC_ival_fim[FUNC_COR_TYPE] ) ; memset( bar , 0 , sizeof(short)*nxyz ) ; if( topval > 0.0 ){ topval = MRI_TYPE_maxval[MRI_short] / topval ; for( iv=0 ; iv < nvox ; iv++ ) bar[indx[iv]] = (short)(topval * vval[iv] + 0.499) ; stataux[0] = 1.0/topval ; } else { stataux[0] = 0.0 ; } /*--- get correlation coefficient (pcor) into vval, scale into brick array (with fixed scaling factor) ---*/ STATUS("getting 1 ref pcor") ; PCOR_get_pcor( pc_ref[0] , pc_vc[0] , vval ) ; bar = DSET_ARRAY( new_dset , FUNC_ival_thr[FUNC_COR_TYPE] ) ; memset( bar , 0 , sizeof(short)*nxyz ) ; for( iv=0 ; iv < nvox ; iv++ ) bar[indx[iv]] = (short)(FUNC_COR_SCALE_SHORT * vval[iv] + 0.499) ; stataux[1] = 1.0 / FUNC_COR_SCALE_SHORT ; } else { /*** Multiple references --> find best correlation at each voxel ***/ /*--- get first ref results into abest and rbest (best so far) ---*/ PCOR_get_coef( pc_ref[0] , pc_vc[0] , abest ) ; /*--- modify alpha for percentage change calculation ---*/ if (max_percent > 0.0) /* 19 May 1997 */ for (iv = 0; iv < nvox; iv++) abest[iv] *= 100.0 * (ref_ts_max[0] - ref_ts_min[0]); PCOR_get_pcor( pc_ref[0] , pc_vc[0] , rbest ) ; /*--- for each succeeding ref vector, get results into aval and vval, if |vval| > |rbest|, then use that result instead ---*/ for( ivec=1 ; ivec < ny_ref ; ivec++ ){ PCOR_get_coef( pc_ref[ivec] , pc_vc[ivec] , aval ) ; PCOR_get_pcor( pc_ref[ivec] , pc_vc[ivec] , vval ) ; for( iv=0 ; iv < nvox ; iv++ ){ if( fabs(vval[iv]) > fabs(rbest[iv]) ){ rbest[iv] = vval[iv] ; abest[iv] = aval[iv] ; /*--- modify alpha for percentage change calculation ---*/ if (max_percent > 0.0) /* 19 May 1997 */ abest[iv] *= 100.0 * (ref_ts_max[ivec] - ref_ts_min[ivec]); } } } /*--- at this point, abest and rbest are the best results, so scale them into the dataset bricks ---*/ /*--- finish percentage change calculation, if so requested ---*/ if (max_percent > 0.0) /* 19 May 1997 */ { for (iv = 0; iv < nvox; iv++) { if (fabs(abest[iv]) < max_percent * fabs(baseline[iv])) abest[iv] = fabs( abest[iv] / baseline[iv] ); else abest[iv] = max_percent; } topval = max_percent; } else { topval = 0.0 ; for( iv=0 ; iv < nvox ; iv++ ) if( fabs(abest[iv]) > topval ) topval = fabs(abest[iv]) ; } bar = DSET_ARRAY( new_dset , FUNC_ival_fim[FUNC_COR_TYPE] ) ; memset( bar , 0 , sizeof(short)*nxyz ) ; if( topval > 0.0 ){ topval = MRI_TYPE_maxval[MRI_short] / topval ; for( iv=0 ; iv < nvox ; iv++ ) bar[indx[iv]] = (short)(topval * abest[iv] + 0.499) ; stataux[0] = 1.0/topval ; } else { stataux[0] = 0.0 ; } bar = DSET_ARRAY( new_dset , FUNC_ival_thr[FUNC_COR_TYPE] ) ; memset( bar , 0 , sizeof(short)*nxyz ) ; for( iv=0 ; iv < nvox ; iv++ ) bar[indx[iv]] = (short)(FUNC_COR_SCALE_SHORT * rbest[iv] + 0.499) ; stataux[1] = 1.0 / FUNC_COR_SCALE_SHORT ; } STATUS("setting brick_fac") ; (void) EDIT_dset_items( new_dset , ADN_brick_fac , stataux , ADN_none ) ; } } /*--- End of recursive updates; now free temporary workspaces ---*/ for( ivec=0 ; ivec < ny_ref ; ivec++ ){ free_PCOR_references(pc_ref[ivec]) ; free_PCOR_voxel_corr(pc_vc[ivec]) ; } free(vval) ; free(indx) ; free(pc_ref) ; free(pc_vc) ; if( aval != NULL ) free(aval) ; if( rbest != NULL ) free(rbest) ; if( abest != NULL ) free(abest) ; if (ref_ts_min != NULL) free (ref_ts_min); /* 19 May 1997 */ if (ref_ts_max != NULL) free (ref_ts_max); if (baseline != NULL) free (baseline); /* --- load the statistics --- */ THD_load_statistics (new_dset); /*--- Return new dataset ---*/ RETURN(new_dset) ; }
THD_3dim_dataset * MAKER_4D_to_typed_fim( THD_3dim_dataset * old_dset , char * new_prefix , int new_datum , int ignore , int detrend , generic_func * user_func , void * user_data ) { THD_3dim_dataset * new_dset ; /* output dataset */ byte ** bptr = NULL ; /* one of these will be the array of */ short ** sptr = NULL ; /* pointers to input dataset sub-bricks */ float ** fptr = NULL ; /* (depending on input datum type) */ complex ** cptr = NULL ; float * fxar = NULL ; /* array loaded from input dataset */ float * fac = NULL ; /* array of brick scaling factors */ float * fout = NULL ; /* will be array of output floats */ float * dtr = NULL ; /* will be array of detrending coeff */ float val , d0fac , d1fac , x0,x1; double tzero=0 , tdelta , ts_mean , ts_slope ; int ii , old_datum , nuse , use_fac , iz,izold, nxy,nvox , nbad ; register int kk ; void (*ufunc)(double,double,int,float *,double,double,void *,float *) = (void (*)(double,double,int,float *,double,double,void *,float *)) user_func ; /*----------------------------------------------------------*/ /*----- Check inputs to see if they are reasonable-ish -----*/ if( ! ISVALID_3DIM_DATASET(old_dset) ) return NULL ; if( new_datum >= 0 && new_datum != MRI_byte && new_datum != MRI_short && new_datum != MRI_float ) return NULL ; if( user_func == NULL ) return NULL ; if( ignore < 0 ) ignore = 0 ; /*--------- set up pointers to each sub-brick in the input dataset ---------*/ old_datum = DSET_BRICK_TYPE( old_dset , 0 ) ; /* get old dataset datum */ nuse = DSET_NUM_TIMES(old_dset) - ignore ; /* # of points on time axis */ if( nuse < 2 ) return NULL ; if( new_datum < 0 ) new_datum = old_datum ; /* output datum = input */ if( new_datum == MRI_complex ) return NULL ; /* but complex = bad news */ DSET_load( old_dset ) ; /* must be in memory before we get pointers to it */ kk = THD_count_databricks( old_dset->dblk ) ; /* check if it was */ if( kk < DSET_NVALS(old_dset) ){ /* loaded correctly */ DSET_unload( old_dset ) ; return NULL ; } switch( old_datum ){ /* pointer type depends on input datum type */ default: /** don't know what to do **/ DSET_unload( old_dset ) ; return NULL ; /** create array of pointers into old dataset sub-bricks **/ /*--------- input is bytes ----------*/ /* voxel #i at time #k is bptr[k][i] */ /* for i=0..nvox-1 and k=0..nuse-1. */ case MRI_byte: bptr = (byte **) malloc( sizeof(byte *) * nuse ) ; if( bptr == NULL ) return NULL ; for( kk=0 ; kk < nuse ; kk++ ) bptr[kk] = (byte *) DSET_ARRAY(old_dset,kk+ignore) ; break ; /*--------- input is shorts ---------*/ /* voxel #i at time #k is sptr[k][i] */ /* for i=0..nvox-1 and k=0..nuse-1. */ case MRI_short: sptr = (short **) malloc( sizeof(short *) * nuse ) ; if( sptr == NULL ) return NULL ; for( kk=0 ; kk < nuse ; kk++ ) sptr[kk] = (short *) DSET_ARRAY(old_dset,kk+ignore) ; break ; /*--------- input is floats ---------*/ /* voxel #i at time #k is fptr[k][i] */ /* for i=0..nvox-1 and k=0..nuse-1. */ case MRI_float: fptr = (float **) malloc( sizeof(float *) * nuse ) ; if( fptr == NULL ) return NULL ; for( kk=0 ; kk < nuse ; kk++ ) fptr[kk] = (float *) DSET_ARRAY(old_dset,kk+ignore) ; break ; /*--------- input is complex ---------*/ /* voxel #i at time #k is cptr[k][i] */ /* for i=0..nvox-1 and k=0..nuse-1. */ case MRI_complex: cptr = (complex **) malloc( sizeof(complex *) * nuse ) ; if( cptr == NULL ) return NULL ; for( kk=0 ; kk < nuse ; kk++ ) cptr[kk] = (complex *) DSET_ARRAY(old_dset,kk+ignore) ; break ; } /* end of switch on input type */ /*---- allocate space for 1 voxel timeseries ----*/ fxar = (float *) malloc( sizeof(float) * nuse ) ; /* voxel timeseries */ if( fxar == NULL ){ FREE_WORKSPACE ; return NULL ; } /*--- get scaling factors for sub-bricks ---*/ fac = (float *) malloc( sizeof(float) * nuse ) ; /* factors */ if( fac == NULL ){ FREE_WORKSPACE ; return NULL ; } use_fac = 0 ; for( kk=0 ; kk < nuse ; kk++ ){ fac[kk] = DSET_BRICK_FACTOR(old_dset,kk+ignore) ; if( fac[kk] != 0.0 ) use_fac++ ; else fac[kk] = 1.0 ; } if( !use_fac ) FREEUP(fac) ; /*--- setup for detrending ---*/ dtr = (float *) malloc( sizeof(float) * nuse ) ; if( dtr == NULL ){ FREE_WORKSPACE ; return NULL ; } d0fac = 1.0 / nuse ; d1fac = 12.0 / nuse / (nuse*nuse - 1.0) ; for( kk=0 ; kk < nuse ; kk++ ) dtr[kk] = kk - 0.5 * (nuse-1) ; /* linear trend, orthogonal to 1 */ /*---------------------- make a new dataset ----------------------*/ new_dset = EDIT_empty_copy( old_dset ) ; /* start with copy of old one */ /*-- edit some of its internal parameters --*/ ii = EDIT_dset_items( new_dset , ADN_prefix , new_prefix , /* filename prefix */ ADN_malloc_type , DATABLOCK_MEM_MALLOC , /* store in memory */ ADN_datum_all , new_datum , /* atomic datum */ ADN_nvals , 1 , /* # sub-bricks */ ADN_ntt , 0 , /* # time points */ ADN_type , ISHEAD(old_dset) /* dataset type */ ? HEAD_FUNC_TYPE : GEN_FUNC_TYPE , ADN_func_type , FUNC_FIM_TYPE , /* function type */ ADN_none ) ; if( ii != 0 ){ ERROR_message("Error creating dataset '%s'",new_prefix) ; THD_delete_3dim_dataset( new_dset , False ) ; /* some error above */ FREE_WORKSPACE ; return NULL ; } /*------ make floating point output brick (only at the end will scale to byte or shorts) ------*/ nvox = old_dset->daxes->nxx * old_dset->daxes->nyy * old_dset->daxes->nzz ; fout = (float *) malloc( sizeof(float) * nvox ) ; /* ptr to brick */ if( fout == NULL ){ THD_delete_3dim_dataset( new_dset , False ) ; FREE_WORKSPACE ; return NULL ; } /*----- set up to find time at each voxel -----*/ tdelta = old_dset->taxis->ttdel ; if( DSET_TIMEUNITS(old_dset) == UNITS_MSEC_TYPE ) tdelta *= 0.001 ; if( tdelta == 0.0 ) tdelta = 1.0 ; izold = -666 ; nxy = old_dset->daxes->nxx * old_dset->daxes->nyy ; /*----------------------------------------------------*/ /*----- Setup has ended. Now do some real work. -----*/ /* start notification */ #if 0 user_func( 0.0 , 0.0 , nvox , NULL,0.0,0.0 , user_data , NULL ) ; #else ufunc( 0.0 , 0.0 , nvox , NULL,0.0,0.0 , user_data , NULL ) ; #endif /***** loop over voxels *****/ for( ii=0 ; ii < nvox ; ii++ ){ /* 1 time series at a time */ /*** load data from input dataset, depending on type ***/ switch( old_datum ){ /*** input = bytes ***/ case MRI_byte: for( kk=0 ; kk < nuse ; kk++ ) fxar[kk] = bptr[kk][ii] ; break ; /*** input = shorts ***/ case MRI_short: for( kk=0 ; kk < nuse ; kk++ ) fxar[kk] = sptr[kk][ii] ; break ; /*** input = floats ***/ case MRI_float: for( kk=0 ; kk < nuse ; kk++ ) fxar[kk] = fptr[kk][ii] ; break ; /*** input = complex (note we use absolute value) ***/ case MRI_complex: for( kk=0 ; kk < nuse ; kk++ ) fxar[kk] = CABS(cptr[kk][ii]) ; break ; } /* end of switch over input type */ /*** scale? ***/ if( use_fac ) for( kk=0 ; kk < nuse ; kk++ ) fxar[kk] *= fac[kk] ; /** compute mean and slope **/ x0 = x1 = 0.0 ; for( kk=0 ; kk < nuse ; kk++ ){ x0 += fxar[kk] ; x1 += fxar[kk] * dtr[kk] ; } x0 *= d0fac ; x1 *= d1fac ; /* factors to remove mean and trend */ ts_mean = x0 ; ts_slope = x1 / tdelta ; /** detrend? **/ if( detrend ) for( kk=0 ; kk < nuse ; kk++ ) fxar[kk] -= (x0 + x1 * dtr[kk]) ; /** compute start time of this timeseries **/ iz = ii / nxy ; /* which slice am I in? */ if( iz != izold ){ /* in a new slice? */ tzero = THD_timeof( ignore , old_dset->daxes->zzorg + iz*old_dset->daxes->zzdel , old_dset->taxis ) ; izold = iz ; if( DSET_TIMEUNITS(old_dset) == UNITS_MSEC_TYPE ) tzero *= 0.001 ; } /*** compute output ***/ #if 0 user_func( tzero,tdelta , nuse,fxar,ts_mean,ts_slope , user_data , fout+ii ) ; #else ufunc( tzero,tdelta , nuse,fxar,ts_mean,ts_slope , user_data , fout+ii ) ; #endif } /* end of outer loop over 1 voxels at a time */ DSET_unload( old_dset ) ; /* don't need this no more */ /* end notification */ #if 0 user_func( 0.0 , 0.0 , 0 , NULL,0.0,0.0 , user_data , NULL ) ; #else ufunc( 0.0 , 0.0 , 0 , NULL,0.0,0.0 , user_data , NULL ) ; #endif nbad = thd_floatscan( nvox , fout ) ; /* 08 Aug 2000 */ if( nbad > 0 ) fprintf(stderr, "++ Warning: %d bad floats computed in MAKER_4D_to_typed_fim\n\a", nbad ) ; /*------------------------------------------------------------*/ /*------- The output is now in fout[ii], ii=0..nvox-1. We must now put this into the output dataset -------*/ switch( new_datum ){ /*** output is floats is the simplest: we just have to attach the fout brick to the dataset ***/ case MRI_float: EDIT_substitute_brick( new_dset , 0 , MRI_float , fout ) ; fout = NULL ; /* so it won't be freed later */ break ; /*** output is shorts: we have to create a scaled sub-brick from fout ***/ case MRI_short:{ short * bout ; float sfac ; /*-- get output sub-brick --*/ bout = (short *) malloc( sizeof(short) * nvox ) ; if( bout == NULL ){ fprintf(stderr, "\nFinal malloc error in MAKER_4D_to_fim - is memory exhausted?\n\a"); EXIT(1) ; } /*-- find scaling and then scale --*/ sfac = MCW_vol_amax( nvox,1,1 , MRI_float , fout ) ; if( sfac > 0.0 ){ sfac = 32767.0 / sfac ; EDIT_coerce_scale_type( nvox,sfac , MRI_float,fout , MRI_short,bout ) ; sfac = 1.0 / sfac ; } /*-- put output brick into dataset, and store scale factor --*/ EDIT_substitute_brick( new_dset , 0 , MRI_short , bout ) ; EDIT_dset_items( new_dset , ADN_brick_fac , &sfac , ADN_none ) ; } break ; /*** output is bytes (byte = unsigned char) we have to create a scaled sub-brick from fout ***/ case MRI_byte:{ byte * bout ; float sfac ; /*-- get output sub-brick --*/ bout = (byte *) malloc( sizeof(byte) * nvox ) ; if( bout == NULL ){ fprintf(stderr, "\nFinal malloc error in MAKER_4D_to_fim - is memory exhausted?\n\a"); EXIT(1) ; } /*-- find scaling and then scale --*/ sfac = MCW_vol_amax( nvox,1,1 , MRI_float , fout ) ; if( sfac > 0.0 ){ sfac = 255.0 / sfac ; EDIT_coerce_scale_type( nvox,sfac , MRI_float,fout , MRI_byte,bout ) ; sfac = 1.0 / sfac ; } /*-- put output brick into dataset, and store scale factor --*/ EDIT_substitute_brick( new_dset , 0 , MRI_byte , bout ) ; EDIT_dset_items( new_dset , ADN_brick_fac , &sfac , ADN_none ) ; } break ; } /* end of switch on output data type */ /*-------------- Cleanup and go home ----------------*/ FREE_WORKSPACE ; return new_dset ; }
int main(int argc, char **argv) { static char FuncName[]={"3dSeg"}; SEG_OPTS *Opt=NULL; char *atr=NULL; float *mixfrac= NULL; int i=0; double ff; SUMA_SEND_2AFNI SS2A; SUMA_Boolean LocalHead = NOPE; SUMA_STANDALONE_INIT; SUMA_mainENTRY; SUMAg_DOv = SUMA_Alloc_DisplayObject_Struct (SUMA_MAX_DISPLAYABLE_OBJECTS); Opt = Seg_Default(argv, argc); Opt = Seg_ParseInput (Opt,argv, argc); Opt->hist = tross_commandline( FuncName , argc , argv ) ; /* load the input data */ if (!(Opt->aset = Seg_load_dset( Opt->aset_name ))) { SUMA_RETURN(1); } if (!Seg_CheckOpts(Opt)) { SUMA_S_Err("Failed on option check"); SUMA_RETURN(1); } /* Load mask dataset */ if (Opt->mset_name) { if (!strncasecmp(Opt->mset_name,"auto", 4)) { byte *mm=NULL; int j; short *sb=NULL; if (!(mm = THD_automask(Opt->aset))) { SUMA_RETURN(1); } NEW_SHORTY(Opt->aset, DSET_NVALS(Opt->aset), "automask.cp", Opt->mset); sb = (short *)DSET_ARRAY(Opt->mset,0); for (j=0; j<DSET_NVOX(Opt->mset); ++j) { sb[j] = (short)mm[j]; } free(mm); mm=NULL; } else if (!(Opt->mset = Seg_load_dset( Opt->mset_name ))) { SUMA_RETURN(1); } } /* reference classes */ if (Opt->gold_name) { if (!(Opt->gold = Seg_load_dset( Opt->gold_name ))) { SUMA_RETURN(1); } } if (Opt->gold_bias_name) { if (!(Opt->gold_bias = Seg_load_dset( Opt->gold_bias_name ))) { SUMA_RETURN(1); } } if (!Opt->clss) { SUMA_S_Err("Need -classes option"); SUMA_RETURN(1); } /* Talk ? */ if (Opt->ps->cs->talk_suma) { Opt->ps->cs->istream = SUMA_BRAINWRAP_LINE; Opt->ps->cs->afni_istream = SUMA_AFNI_STREAM_INDEX2; if (!SUMA_SendToAfni (Opt->ps->cs, NULL, 0)) { SUMA_SL_Err("Failed to initialize SUMA_SendToAfni"); Opt->ps->cs->afni_Send = NOPE; Opt->ps->cs->Send = NOPE; } else { /* send in_vol to afni */ SUMA_SL_Note("Sending anat volume to AFNI"); SS2A.dset = Opt->aset; SS2A.at_sb=-1; if (!SUMA_SendToAfni(Opt->ps->cs, &SS2A, 1)) { SUMA_SL_Err("Failed to send volume to AFNI"); Opt->ps->cs->afni_Send = NOPE; } } } /* classified set ? */ if (Opt->this_cset_name) { /* user supplied initializer */ if (!(Opt->cset = Seg_load_dset( Opt->this_cset_name ))) { SUMA_RETURN(1); } } /* labeltable? */ if (Opt->labeltable_name) { Dtable *vl_dtable=NULL; char *labeltable_str=NULL; int kk=0; /* read the table */ if (!(labeltable_str = AFNI_suck_file( Opt->labeltable_name))) { ERROR_exit("Failed to read %s", Opt->labeltable_name); } if (!(vl_dtable = Dtable_from_nimlstring(labeltable_str))) { ERROR_exit("Could not parse labeltable"); } CLASS_KEYS_FROM_LT(vl_dtable); destroy_Dtable(vl_dtable); vl_dtable=NULL; } if (!Opt->keys) { Dtable *vl_dtable=NULL; if (Opt->cset && (vl_dtable = DSET_Label_Dtable(Opt->cset))) { if (Opt->debug) SUMA_S_Note("Getting keys from -cset dataset"); /* try getting keys from cset */ CLASS_KEYS_FROM_LT(vl_dtable); /* Do not delete vl_dtable, it is the same pointer in Opt->cset */ } else { /* add default keys */ if (Opt->debug) SUMA_S_Note("Keys not available, assuming defaults"); Opt->keys = (int *)calloc(Opt->clss->num, sizeof(int)); for (i=0; i<Opt->clss->num; ++i) { Opt->keys[i] = i+1; } } } /* Make sure you have no negative values and requesting bias field correction. The implementation uses log() for this so the negative values would be ill advised */ { float amin, amax; THD_subbrick_minmax(Opt->aset, 0, 1,&amin, &amax); if (amin < 0 && Opt->bias_param > 0) { SUMA_S_Err("Cannot use field bias correction on volumes with negative\n" "values. Either turn off bias field estimation with -bias_fwhm 0.0\n" "or shift the values of the input by something like:\n" " 3dcalc -a %s -expr 'a+bool(a)*%d' -prefix SHIFTED\n" "and rerun the segmentation on SHIFTED. Note the suggested shift\n" "leaves zero values unchanged.", DSET_HEADNAME(Opt->aset), (int)ceil(-amin+1.0)); exit(1); } } /* Show the match between keys and classes */ if (Opt->debug > 1) { SUMA_S_Note("Class-->key map"); SUMA_ShowClssKeys(Opt->clss->str, Opt->clss->num, Opt->keys); } if (Opt->clss->num < 2) { if (Opt->debug <= 1) { SUMA_S_Note("Class-->key map"); SUMA_ShowClssKeys(Opt->clss->str, Opt->clss->num, Opt->keys); } SUMA_S_Err("Less than 2 classes? I am out of here"); SUMA_RETURN(0); } /* Mask setup */ if (Opt->debug > 1) { SUMA_S_Note("MaskSetup"); } Opt->cmask = MaskSetup(Opt, Opt->aset, 1, &(Opt->mset), &(Opt->cmask), Opt->dimcmask, Opt->mask_bot, Opt->mask_top, &(Opt->cmask_count)); if (Opt->VoxDbg >= 0) { SUMA_S_Note("DBG setup"); fprintf(Opt->VoxDbgOut, "Command:"); for (i=0; i<argc; ++i) { fprintf(Opt->VoxDbgOut, "%s ", argv[i]); } fprintf(Opt->VoxDbgOut, "\nDebug info for voxel %d\n", Opt->VoxDbg); } Opt->cs = SUMA_New_Class_Stat(Opt->clss->str, Opt->clss->num, Opt->keys, 3, NULL); /* Load prob. of class given features */ if (Opt->priCgAname && strcmp(Opt->priCgAname, "INIT_MIXFRAC")) { if (!(Opt->priCgA = Seg_load_dset(Opt->priCgAname))) { SUMA_S_Errv("Failed to read priCgA %s\n", Opt->priCgAname); SUMA_RETURN(1); } if (GRID_MISMATCH(Opt->priCgA, Opt->aset)) { SUMA_S_Err("All input data must have same grid (-priCgA != -aset)"); SUMA_RETURN(1); } /* Make sure dset is properly formatted */ if (!SUMA_ShortizeProbDset(&Opt->priCgA, Opt->cs, Opt->cmask, Opt->cmask_count, Opt, &Opt->priCgA)) { SUMA_S_Errv("Failed to shortize priCgA %s\n", Opt->priCgAname); SUMA_RETURN(1); } /* set the floor of the input dset */ if (0) { SUMA_S_Note("Setting probability floor, USEFULNESS NOT TESTED..."); if (!set_p_floor(Opt->priCgA, 0.1, Opt->cmask)) { SUMA_S_Errv("Failed to set p floor for priCgA %s\n", Opt->priCgAname); SUMA_RETURN(1); } } } else { /* uniform probability */ } /* Load prob. of class given location */ if (Opt->priCgLname && strcmp(Opt->priCgLname, "INIT_MIXFRAC")) { if (!(Opt->priCgL = Seg_load_dset(Opt->priCgLname))) { SUMA_S_Errv("Failed to read priCgL %s\n", Opt->priCgLname); SUMA_RETURN(1); } if (GRID_MISMATCH(Opt->priCgL, Opt->aset)) { SUMA_S_Err("All input data must have same grid (-priCgL != -aset)"); SUMA_RETURN(1); } /* Make sure dset is properly formatted */ if (!SUMA_ShortizeProbDset(&Opt->priCgL, Opt->cs, Opt->cmask, Opt->cmask_count, Opt, &Opt->priCgL)) { SUMA_S_Errv("Failed to shortize priCgL %s\n", Opt->priCgLname); SUMA_RETURN(1); } } else { /* uniform probability */ } /* check on weights of priors */ if (Opt->wA >= 0.0 && Opt->wL < 0.0) { Opt->wL = 1.0 - Opt->wA; } else if (Opt->wL >= 0.0 && Opt->wA < 0.0) { Opt->wA = 1.0 - Opt->wL; } else if (Opt->wA < 0.0 && Opt->wL < 0.0) { /* defaults */ Opt->wA = 0.5; Opt->wL = 0.5; } ff = Opt->wA+Opt->wL; Opt->wA = Opt->wA/ff; Opt->wL = Opt->wL/ff; if (!Opt->cset) { if (!SUMA_SegInitCset(Opt->aset, &Opt->cset, Opt->cmask, Opt->cmask_count, Opt->mixopt, Opt->cs, Opt)) { SUMA_S_Err("Failed to get initializer"); SUMA_RETURN(1); } } if (Opt->debug > 1) { SUMA_Seg_Write_Dset(Opt->proot, "classes_init", Opt->cset, -1, Opt->hist); } /* Now add the 'OTHER' class if needed */ if (Opt->Other) { if (!SUMA_AddOther( Opt->clss, &Opt->keys, Opt->cmask, Opt->cmask_count, Opt->cset, Opt->pstCgALL, Opt->priCgA, Opt->priCgL, Opt->cs)) { SUMA_S_Err("Failed to add other"); SUMA_RETURN(0); } } /* store mixfrac in class stats */ for (i=0;i<Opt->cs->N_label; ++i) { if ((ff = SUMA_mixopt_2_mixfrac(Opt->mixopt, Opt->cs->label[i], Opt->cs->keys[i], Opt->cs->N_label, Opt->cmask, Opt->cset))<0.0) { SUMA_S_Errv("Can't get mixfrac for %s\n", Opt->mixopt); SUMA_RETURN(1); } SUMA_set_Stat(Opt->cs, Opt->cs->label[i], "init.mix", ff); SUMA_set_Stat(Opt->cs, Opt->cs->label[i], "mix", ff); } /* Now call the workhorse */ if (!SUMA_SegEngine(Opt)) { SUMA_S_Err("Failed in SUMA_SegEngine"); exit(1); } /* write output */ if (Opt->Bset && !Opt->this_fset_name) { tross_Append_History(Opt->Bset, Opt->hist); SUMA_Seg_Write_Dset(Opt->proot, "BiasField", /* DSET_PREFIX(Opt->Bset) */ Opt->Bset, -1, Opt->hist); } if (Opt->xset && !Opt->this_xset_name) { AFNI_FEED(Opt->ps->cs, "BiasCorrect", -1, Opt->xset); SUMA_Seg_Write_Dset(Opt->proot, "AnatUB", /* DSET_PREFIX(Opt->xset)*/ Opt->xset, -1, Opt->hist); } if (Opt->cset) { SUMA_Seg_Write_Dset(Opt->proot, "Classes", /* Opt->crefix */ Opt->cset, -1, Opt->hist); AFNI_FEED(Opt->ps->cs, "FinalClasses", -1, Opt->cset); } if (Opt->pstCgALL) { SUMA_Seg_Write_Dset(Opt->proot, "Posterior", /* Opt->prefix */ Opt->pstCgALL, -1, Opt->hist); AFNI_FEED(Opt->ps->cs, "pstCgALL-final", -1, Opt->pstCgALL); } if (Opt->aset) { SUMA_Seg_Write_Dset(Opt->proot, "Anat", Opt->aset, -1, Opt->hist); } if (Opt->debug) SUMA_S_Note("Writing Unmodulated output"); if (!(SUMA_pst_C_giv_ALL(Opt->xset, Opt->cmask, Opt->cmask_count, Opt->cs, NULL, NULL, Opt->B, Opt->T, 0, &Opt->pstCgALL))) { SUMA_S_Err("Failed in SUMA_pst_C_giv_ALL unmodulated"); SUMA_RETURN(1); } SUMA_Seg_Write_Dset(Opt->proot, "Unmodulated.p", Opt->pstCgALL, -1, Opt->hist); if (!(SUMA_assign_classes( Opt->pstCgALL, Opt->cs, Opt->cmask, &Opt->cset))) { SUMA_S_Err("Failed in assign_classes"); SUMA_RETURN(1); } SUMA_Seg_Write_Dset(Opt->proot, "Unmodulated.c", Opt->cset, -1, Opt->hist); /* all done, free */ Opt = free_SegOpts(Opt); PRINT_COMPILE_DATE ; SUMA_RETURN(0); }
MRI_IMAGE * FD_brick_to_mri( int kslice , int ival , FD_brick * br ) { MRI_IMAGE * im ; /* output */ register int ii,di,ei , jj,dj,ej , base , pp ; char * iar ; /* brick in the input */ MRI_TYPE typ ; /** desire a fake image **/ if( ival < 0 ){ im = mri_new( br->n1 , br->n2 , MRI_short ) ; im->dx = br->del1 ; im->dy = br->del2 ; im->dz = br->del3 ; return im ; } /** otherwise, get ready for a real image **/ if( ival >= br->dset->dblk->nvals ) return NULL ; iar = DSET_ARRAY(br->dset,ival) ; if( iar == NULL ){ /* if data needs to be loaded from disk */ (void) THD_load_datablock( br->dset->dblk ) ; iar = DSET_ARRAY(br->dset,ival) ; if( iar == NULL ) return NULL ; } typ = DSET_BRICK_TYPE(br->dset,ival) ; im = mri_new( br->n1 , br->n2 , typ ) ; im->dx = br->del1 ; im->dy = br->del2 ; im->dz = br->del3 ; switch( typ ){ default: /* don't know what to do --> return nada */ mri_free( im ) ; return NULL ; case MRI_byte:{ register byte * ar = MRI_BYTE_PTR(im) ; register byte * bar = (byte *) iar ; di = br->d1 ; dj = br->d2 ; /* strides */ ei = br->e1 ; ej = br->e2 ; /* final indices */ base = br->start + kslice * br->d3 ; pp = 0 ; for( jj=0 ; jj != ej ; jj += dj ) for( ii=0 ; ii != ei ; ii += di ) ar[pp++] = bar[ii+(jj+base)] ; } break ; case MRI_short:{ register short * ar = MRI_SHORT_PTR(im) ; register short * bar = (short *) iar ; di = br->d1 ; dj = br->d2 ; /* strides */ ei = br->e1 ; ej = br->e2 ; /* final indices */ base = br->start + kslice * br->d3 ; pp = 0 ; for( jj=0 ; jj != ej ; jj += dj ) for( ii=0 ; ii != ei ; ii += di ) ar[pp++] = bar[ii+(jj+base)] ; } break ; case MRI_float:{ register float * ar = MRI_FLOAT_PTR(im) ; register float * bar = (float *) iar ; di = br->d1 ; dj = br->d2 ; /* strides */ ei = br->e1 ; ej = br->e2 ; /* final indices */ base = br->start + kslice * br->d3 ; pp = 0 ; for( jj=0 ; jj != ej ; jj += dj ) for( ii=0 ; ii != ei ; ii += di ) ar[pp++] = bar[ii+(jj+base)] ; } break ; case MRI_int:{ register int * ar = MRI_INT_PTR(im) ; register int * bar = (int *) iar ; di = br->d1 ; dj = br->d2 ; /* strides */ ei = br->e1 ; ej = br->e2 ; /* final indices */ base = br->start + kslice * br->d3 ; pp = 0 ; for( jj=0 ; jj != ej ; jj += dj ) for( ii=0 ; ii != ei ; ii += di ) ar[pp++] = bar[ii+(jj+base)] ; } break ; case MRI_double:{ register double * ar = MRI_DOUBLE_PTR(im) ; register double * bar = (double *) iar ; di = br->d1 ; dj = br->d2 ; /* strides */ ei = br->e1 ; ej = br->e2 ; /* final indices */ base = br->start + kslice * br->d3 ; pp = 0 ; for( jj=0 ; jj != ej ; jj += dj ) for( ii=0 ; ii != ei ; ii += di ) ar[pp++] = bar[ii+(jj+base)] ; } break ; case MRI_complex:{ register complex * ar = MRI_COMPLEX_PTR(im) ; register complex * bar = (complex *) iar ; di = br->d1 ; dj = br->d2 ; /* strides */ ei = br->e1 ; ej = br->e2 ; /* final indices */ base = br->start + kslice * br->d3 ; pp = 0 ; for( jj=0 ; jj != ej ; jj += dj ) for( ii=0 ; ii != ei ; ii += di ) ar[pp++] = bar[ii+(jj+base)] ; } break ; case MRI_rgb:{ /* 15 Apr 2002 */ register rgbyte * ar = (rgbyte *) MRI_RGB_PTR(im) ; register rgbyte * bar = (rgbyte *) iar ; di = br->d1 ; dj = br->d2 ; /* strides */ ei = br->e1 ; ej = br->e2 ; /* final indices */ base = br->start + kslice * br->d3 ; pp = 0 ; for( jj=0 ; jj != ej ; jj += dj ) for( ii=0 ; ii != ei ; ii += di ) ar[pp++] = bar[ii+(jj+base)] ; } break ; } if( DSET_BRICK_FACTOR(br->dset,ival) != 0.0 ){ MRI_IMAGE * qim ; STATUS(" scaling to float"); qim = mri_scale_to_float( DSET_BRICK_FACTOR(br->dset,ival) , im ) ; mri_free(im) ; im = qim ; } return im ; }
/*---------------------------------------------------------------------- ** ** Subtract hemispheres assuming we need floats. ** **---------------------------------------------------------------------- */ static char * process_as_floats( THD_3dim_dataset * dset, hemi_s * hs ) { int count, cx, type = hs->thresh_type; int nx, ny, nz, nvox; short * sp, * sdata; float * fdata, * fp, * fp2; float factor, maxabs; nx = dset->daxes->nxx; ny = dset->daxes->nyy; nz = dset->daxes->nzz; nvox = nx * ny * nz; sdata = (short *)DSET_ARRAY( dset, 0 ); factor = DSET_BRICK_FACTOR( dset, 0 ); factor = factor == 0.0 ? 1.0 : factor; /* first get the data into a float array */ if ( ( fdata = (float *)malloc( nvox * sizeof( float ) ) ) == NULL ) return "------------------------------\n" "paf: failed allocation of floats" "------------------------------\n"; fp = fdata; sp = sdata; for ( count = 0; count < nvox; count++ ) { *fp = *sdata * factor; if ( ( type == 1 ) && ( *fp < 0 ) ) *fp = 0; else if ( ( type == 2 ) && ( *fp > 0 ) ) *fp = 0; fp++; sp++; } /* now make the subtraction as floats */ for ( count = 0; count < ny*nz; count++ ) { fp = fdata + count * nx; fp2 = fp + nx - 1; for ( cx = 0; cx < (nx+1)/2; cx++ ) { *fp = *fp - *fp2; *fp2 = -*fp; fp++; fp2--; } } /* now make a new factor */ maxabs = MCW_vol_amax( nvox, 1, 1, MRI_float, fdata ); /* result is all zero, let the user worry */ if ( maxabs != 0.0 ) { factor = MRI_TYPE_maxval[MRI_short] /maxabs; /* 32767? / maxabs */ EDIT_coerce_scale_type( nvox, factor, MRI_float, fdata, MRI_short, sdata ); DSET_BRICK_FACTOR( dset, 0 ) = factor == 0.0 ? 0.0 : 1.0 / factor; THD_load_statistics( dset ); } free(fdata); return NULL; /* success */ }
int main( int argc , char *argv[] ) { THD_3dim_dataset *inset=NULL , *outset=NULL ; MCW_cluster *nbhd=NULL ; byte *mask=NULL ; int mask_nx,mask_ny,mask_nz , automask=0 ; char *prefix="./LocalCormat" ; int iarg=1 , verb=1 , ntype=0 , kk,nx,ny,nz,nxy,nxyz,nt , xx,yy,zz, vstep ; float na,nb,nc , dx,dy,dz ; MRI_IMARR *imar=NULL ; MRI_IMAGE *pim=NULL ; int mmlag=10 , ii,jj , do_arma=0 , nvout ; MRI_IMAGE *concim=NULL ; float *concar=NULL ; if( argc < 2 || strcmp(argv[1],"-help") == 0 ){ printf( "Usage: 3dLocalCORMAT [options] inputdataset\n" "\n" "Compute the correlation matrix (in time) of the input dataset,\n" "up to lag given by -maxlag. The matrix is averaged over the\n" "neighborhood specified by the -nbhd option, and then the entries\n" "are output at each voxel in a new dataset.\n" "\n" "Normally, the input to this program would be the -errts output\n" "from 3dDeconvolve, or the equivalent residuals from some other\n" "analysis. If you input a non-residual time series file, you at\n" "least should use an appropriate -polort level for detrending!\n" "\n" "Options:\n" " -input inputdataset\n" " -prefix ppp\n" " -mask mset {these 2 options are}\n" " -automask {mutually exclusive.}\n" " -nbhd nnn [e.g., 'SPHERE(9)' for 9 mm radius]\n" " -polort ppp [default = 0, which is reasonable for -errts output]\n" " -concat ccc [as in 3dDeconvolve]\n" " -maxlag mmm [default = 10]\n" " -ARMA [estimate ARMA(1,1) parameters into last 2 sub-bricks]\n" "\n" "A quick hack for my own benignant purposes -- RWCox -- June 2008\n" ) ; PRINT_COMPILE_DATE ; exit(0) ; } /*---- official startup ---*/ PRINT_VERSION("3dLocalCormat"); mainENTRY("3dLocalCormat main"); machdep(); AFNI_logger("3dLocalCormat",argc,argv); AUTHOR("Zhark the Toeplitzer"); /*---- loop over options ----*/ while( iarg < argc && argv[iarg][0] == '-' ){ #if 0 fprintf(stderr,"argv[%d] = %s\n",iarg,argv[iarg]) ; #endif if( strcmp(argv[iarg],"-ARMA") == 0 ){ do_arma = 1 ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-polort") == 0 ){ char *cpt ; if( ++iarg >= argc ) ERROR_exit("Need argument after option %s",argv[iarg-1]) ; pport = (int)strtod(argv[iarg],&cpt) ; if( *cpt != '\0' ) WARNING_message("Illegal non-numeric value after -polort") ; if( pport > 3 ){ pport = 3 ; WARNING_message("-polort set to 3 == max implemented") ; } else if( pport < 0 ){ pport = 0 ; WARNING_message("-polort set to 0 == min implemented") ; } iarg++ ; continue ; } if( strcmp(argv[iarg],"-input") == 0 ){ if( inset != NULL ) ERROR_exit("Can't have two -input options") ; if( ++iarg >= argc ) ERROR_exit("Need argument after '-input'") ; inset = THD_open_dataset( argv[iarg] ) ; CHECK_OPEN_ERROR(inset,argv[iarg]) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-prefix") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '-prefix'") ; prefix = strdup(argv[iarg]) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-mask") == 0 ){ THD_3dim_dataset *mset ; int mmm ; if( ++iarg >= argc ) ERROR_exit("Need argument after '-mask'") ; if( mask != NULL || automask ) ERROR_exit("Can't have two mask inputs") ; mset = THD_open_dataset( argv[iarg] ) ; CHECK_OPEN_ERROR(mset,argv[iarg]) ; DSET_load(mset) ; CHECK_LOAD_ERROR(mset) ; mask_nx = DSET_NX(mset); mask_ny = DSET_NY(mset); mask_nz = DSET_NZ(mset); mask = THD_makemask( mset , 0 , 0.5f, 0.0f ) ; DSET_delete(mset) ; if( mask == NULL ) ERROR_exit("Can't make mask from dataset '%s'",argv[iarg]) ; mmm = THD_countmask( mask_nx*mask_ny*mask_nz , mask ) ; INFO_message("Number of voxels in mask = %d",mmm) ; if( mmm < 2 ) ERROR_exit("Mask is too small to process") ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-automask") == 0 ){ if( mask != NULL ) ERROR_exit("Can't have -automask and -mask") ; automask = 1 ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-nbhd") == 0 ){ char *cpt ; if( ntype > 0 ) ERROR_exit("Can't have 2 '-nbhd' options") ; if( ++iarg >= argc ) ERROR_exit("Need argument after '-nbhd'") ; cpt = argv[iarg] ; if( strncasecmp(cpt,"SPHERE",6) == 0 ){ sscanf( cpt+7 , "%f" , &na ) ; if( na == 0.0f ) ERROR_exit("Can't have a SPHERE of radius 0") ; ntype = NTYPE_SPHERE ; } else if( strncasecmp(cpt,"RECT",4) == 0 ){ sscanf( cpt+5 , "%f,%f,%f" , &na,&nb,&nc ) ; if( na == 0.0f && nb == 0.0f && nc == 0.0f ) ERROR_exit("'RECT(0,0,0)' is not a legal neighborhood") ; ntype = NTYPE_RECT ; } else if( strncasecmp(cpt,"RHDD",4) == 0 ){ sscanf( cpt+5 , "%f" , &na ) ; if( na == 0.0f ) ERROR_exit("Can't have a RHDD of radius 0") ; ntype = NTYPE_RHDD ; } else { ERROR_exit("Unknown -nbhd shape: '%s'",cpt) ; } iarg++ ; continue ; } if( strcmp(argv[iarg],"-maxlag") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after option %s",argv[iarg-1]) ; mmlag = (int)strtod(argv[iarg],NULL) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-concat") == 0 ){ if( concim != NULL ) ERROR_exit("Can't have two %s options!",argv[iarg]) ; if( ++iarg >= argc ) ERROR_exit("Need argument after option %s",argv[iarg-1]) ; concim = mri_read_1D( argv[iarg] ) ; if( concim == NULL ) ERROR_exit("Can't read -concat file '%s'",argv[iarg]) ; if( concim->nx < 2 ) ERROR_exit("-concat file '%s' must have at least 2 entries!", argv[iarg]) ; concar = MRI_FLOAT_PTR(concim) ; for( ii=1 ; ii < concim->nx ; ii++ ) if( (int)concar[ii-1] >= (int)concar[ii] ) ERROR_exit("-concat file '%s' is not ordered increasingly!", argv[iarg]) ; iarg++ ; continue ; } ERROR_exit("Unknown option '%s'",argv[iarg]) ; } /*--- end of loop over options ---*/ if( do_arma && mmlag > 0 && mmlag < 5 ) ERROR_exit("Can't do -ARMA with -maxlag %d",mmlag) ; /*---- deal with input dataset ----*/ if( inset == NULL ){ if( iarg >= argc ) ERROR_exit("No input dataset on command line?") ; inset = THD_open_dataset( argv[iarg] ) ; CHECK_OPEN_ERROR(inset,argv[iarg]) ; } ntime = DSET_NVALS(inset) ; if( ntime < 9 ) ERROR_exit("Must have at least 9 values per voxel") ; DSET_load(inset) ; CHECK_LOAD_ERROR(inset) ; if( mask != NULL ){ if( mask_nx != DSET_NX(inset) || mask_ny != DSET_NY(inset) || mask_nz != DSET_NZ(inset) ) ERROR_exit("-mask dataset grid doesn't match input dataset") ; } else if( automask ){ int mmm ; mask = THD_automask( inset ) ; if( mask == NULL ) ERROR_message("Can't create -automask from input dataset?") ; mmm = THD_countmask( DSET_NVOX(inset) , mask ) ; INFO_message("Number of voxels in automask = %d",mmm) ; if( mmm < 2 ) ERROR_exit("Automask is too small to process") ; } /*-- set up blocks of continuous time data --*/ if( DSET_IS_TCAT(inset) ){ if( concim != NULL ){ WARNING_message("Ignoring -concat, since dataset is auto-catenated") ; mri_free(concim) ; } concim = mri_new(inset->tcat_num,1,MRI_float) ; concar = MRI_FLOAT_PTR(concim) ; concar[0] = 0.0 ; for( ii=0 ; ii < inset->tcat_num-1 ; ii++ ) concar[ii+1] = concar[ii] + inset->tcat_len[ii] ; } else if( concim == NULL ){ concim = mri_new(1,1,MRI_float) ; concar = MRI_FLOAT_PTR(concim) ; concar[0] = 0 ; } nbk = concim->nx ; bk = (int *)malloc(sizeof(int)*(nbk+1)) ; for( ii=0 ; ii < nbk ; ii++ ) bk[ii] = (int)concar[ii] ; bk[nbk] = ntime ; mri_free(concim) ; mlag = DSET_NVALS(inset) ; for( ii=0 ; ii < nbk ; ii++ ){ jj = bk[ii+1]-bk[ii] ; if( jj < mlag ) mlag = jj ; if( bk[ii] < 0 || jj < 9 ) ERROR_exit("something is rotten in the dataset run lengths") ; } mlag-- ; if( mmlag > 0 && mlag > mmlag ) mlag = mmlag ; else INFO_message("Max lag set to %d",mlag) ; if( do_arma && mlag < 5 ) ERROR_exit("Can't do -ARMA with maxlag=%d",mlag) ; /*---- create neighborhood (as a cluster) -----*/ if( ntype <= 0 ){ /* default neighborhood */ ntype = NTYPE_SPHERE ; na = -1.01f ; INFO_message("Using default neighborhood = self + 6 neighbors") ; } switch( ntype ){ default: ERROR_exit("WTF? ntype=%d",ntype) ; case NTYPE_SPHERE:{ if( na < 0.0f ){ dx = dy = dz = 1.0f ; na = -na ; } else { dx = fabsf(DSET_DX(inset)) ; dy = fabsf(DSET_DY(inset)) ; dz = fabsf(DSET_DZ(inset)) ; } nbhd = MCW_spheremask( dx,dy,dz , na ) ; } break ; case NTYPE_RECT:{ if( na < 0.0f ){ dx = 1.0f; na = -na; } else dx = fabsf(DSET_DX(inset)); if( nb < 0.0f ){ dy = 1.0f; nb = -nb; } else dy = fabsf(DSET_DY(inset)); if( nc < 0.0f ){ dz = 1.0f; nc = -nc; } else dz = fabsf(DSET_DZ(inset)); nbhd = MCW_rectmask( dx,dy,dz , na,nb,nc ) ; } break ; case NTYPE_RHDD:{ if( na < 0.0f ){ dx = dy = dz = 1.0f ; na = -na ; } else { dx = fabsf(DSET_DX(inset)) ; dy = fabsf(DSET_DY(inset)) ; dz = fabsf(DSET_DZ(inset)) ; } nbhd = MCW_rhddmask( dx,dy,dz , na ) ; } break ; } MCW_radsort_cluster( nbhd , dx,dy,dz ) ; /* 26 Feb 2008 */ INFO_message("Neighborhood comprises %d voxels",nbhd->num_pt) ; /** create output dataset **/ outset = EDIT_empty_copy(inset) ; nvout = mlag ; if( do_arma ) nvout += 2 ; EDIT_dset_items( outset, ADN_prefix , prefix, ADN_brick_fac, NULL , ADN_nvals , nvout , ADN_ntt , nvout , ADN_none ); tross_Copy_History( inset , outset ) ; tross_Make_History( "3dLocalCormat" , argc,argv , outset ) ; for( kk=0 ; kk < nvout ; kk++ ) EDIT_substitute_brick( outset , kk , MRI_float , NULL ) ; nx = DSET_NX(outset) ; ny = DSET_NY(outset) ; nxy = nx*ny ; nz = DSET_NZ(outset) ; nxyz = nxy*nz ; vstep = (verb && nxyz > 999) ? nxyz/50 : 0 ; if( vstep ) fprintf(stderr,"++ voxel loop: ") ; /** actually do the long long slog through all voxels **/ for( kk=0 ; kk < nxyz ; kk++ ){ if( vstep && kk%vstep==vstep-1 ) vstep_print() ; if( !INMASK(kk) ) continue ; IJK_TO_THREE( kk , xx,yy,zz , nx,nxy ) ; imar = THD_get_dset_nbhd_array( inset , mask , xx,yy,zz , nbhd ) ; if( imar == NULL ) continue ; pim = mri_cormat_vector(imar) ; DESTROY_IMARR(imar) ; if( pim == NULL ) continue ; THD_insert_series( kk, outset, pim->nx, MRI_float, MRI_FLOAT_PTR(pim), 0 ) ; if( do_arma ){ /* estimate ARMA(1,1) params and store those, too */ float_pair ab ; float *aa=DSET_ARRAY(outset,mlag), *bb=DSET_ARRAY(outset,mlag+1) ; ab = estimate_arma11( pim->nx , MRI_FLOAT_PTR(pim) ) ; aa[kk] = ab.a ; bb[kk] = ab.b ; } mri_free(pim) ; } if( vstep ) fprintf(stderr,"\n") ; DSET_delete(inset) ; DSET_write(outset) ; WROTE_DSET(outset) ; exit(0) ; }
char * POWER_main( PLUGIN_interface * plint ) { MCW_idcode * idc ; /* input dataset idcode */ THD_3dim_dataset * old_dset , * new_dsetD3 , * new_dsetA3, * new_dsetavgD3 ; /* input and output datasets */ char * new_prefix , * str , * namestr, * filename; /* strings from user */ int new_datum , ignore , nfft , ninp , /* control parameters */ old_datum , nuse , ntaper , ktbot, image_type, scale,OutputFlag ,numT,flip; float avFac; byte ** bptr = NULL ; /* one of these will be the array of */ short ** sptr = NULL ; /* pointers to input dataset sub-bricks */ float ** fptr = NULL ; /* (depending on input datum type) */ float * this = NULL ; /* array loaded from input dataset */ float ** foutD3 = NULL ; /* will be array of output floats */ float ** foutA3 = NULL ; /* will be array of output floats */ float ** foutavgD3 = NULL ; /* will be array of output floats */ float * tarD3 = NULL ; /* will be array of taper coefficients */ float * tarA3 = NULL ; /* will be array of taper coefficients */ float * taravgD3 = NULL ; /* will be array of taper coefficients */ /*float * flip;*/ float * numAv; float dfreq , pfact , phi , xr,xi , yr,yi ; float x0,x1 , y0,y1 , d0fac,d1fac ; int nfreq , nvox , perc , new_units ; int istr , ii,iip , ibot,itop , kk , icx ; /* temp variables */ new_prefix = (char *)calloc(100, sizeof(char)); filename = (char *)calloc(100, sizeof(char)); str = (char *)calloc(100, sizeof(char)); namestr = (char *)calloc(100, sizeof(char)); OutputFlag=0; /*--------------------------------------------------------------------*/ /*----- Check inputs from AFNI to see if they are reasonable-ish -----*/ /*--------- go to first input line ---------*/ PLUTO_next_option(plint) ; idc = PLUTO_get_idcode(plint) ; /* get dataset item */ old_dset = PLUTO_find_dset(idc) ; /* get ptr to dataset */ namestr = DSET_PREFIX(old_dset) ; if( old_dset == NULL ) return "*************************\n" "Cannot find Input Dataset\n" "*************************" ; /*--------- go to second input line ---------*/ PLUTO_next_option(plint) ; filename = PLUTO_get_string(plint) ; /* get string item (the output prefix) */ sprintf(new_prefix,"%s%s",filename,"_D3"); if (strcmp(new_prefix,"_D3")==0){ OutputFlag=1; sprintf(new_prefix,"%s%s",namestr,"_D3"); } if (! PLUTO_prefix_ok(new_prefix) ){ PLUTO_popup_transient(plint,new_prefix); return "*************************\n" "Output filename already exists\n" "*************************" ; } PLUTO_popup_transient(plint,"Output file tags set automatically"); str = PLUTO_get_string(plint) ; /* get string item (the datum type) */ istr = PLUTO_string_index( str , /* find it in the list it came from */ NUM_TYPE_STRINGS , type_strings ) ; switch( istr ){ default: case 0: new_datum = MRI_float ; break ; break ; case 1: new_datum = MRI_byte ; break ; /* assign type of user's choice */ case 2: new_datum = MRI_short ; break ; case 3: new_datum = DSET_BRICK_TYPE( old_dset , 0 ) ; /* use old dataset type */ } /*--------- go to next input lines ---------*/ PLUTO_next_option(plint) ; /* skip to next line */ ignore = PLUTO_get_number(plint) ; /* get number item (ignore) */ ninp = DSET_NUM_TIMES(old_dset) ; /* number of values in input */ nuse = ninp; /* number of values to actually use */ nfreq=nuse; nfft=nuse; str = PLUTO_get_string(plint) ; /* get string item (the datum type) */ istr = PLUTO_string_index( str , /* find it in the list it came from */ NUM_TYPE_STRINGSX , type_stringsx ) ; switch( istr ){ default: case 0: image_type = 0; break; } PLUTO_next_option(plint) ; /* skip to next line */ scale = PLUTO_get_number(plint) ; /* get number item (scale) */ /*------------------------------------------------------*/ /*---------- At this point, the inputs are OK ----------*/ PLUTO_popup_meter( plint ) ; /* popup a progress meter */ /*--------- set up pointers to each sub-brick in the input dataset ---------*/ DSET_load( old_dset ) ; /* must be in memory before we get pointers to it */ old_datum = DSET_BRICK_TYPE( old_dset , 0 ) ; /* get old dataset datum type */ switch( old_datum ){ /* pointer type depends on input datum type */ default: return "******************************\n" "Illegal datum in Input Dataset\n" "******************************" ; /** create array of pointers into old dataset sub-bricks **/ /** Note that we skip the first 'ignore' sub-bricks here **/ /*--------- input is bytes ----------*/ /* voxel #i at time #k is bptr[k][i] */ /* for i=0..nvox-1 and k=0..nuse-1. */ case MRI_byte: bptr = (byte **) malloc( sizeof(byte *) * nuse ) ; if( bptr == NULL ) return "Malloc\nFailure!\n [bptr]" ; for( kk=0 ; kk < nuse ; kk++ ) bptr[kk] = (byte *) DSET_ARRAY(old_dset,kk) ; break ; /*--------- input is shorts ---------*/ /* voxel #i at time #k is sptr[k][i] */ /* for i=0..nvox-1 and k=0..nuse-1. */ case MRI_short: sptr = (short **) malloc( sizeof(short *) * nuse ) ; if( sptr == NULL ) return "Malloc\nFailure!\n [sptr]" ; for( kk=0 ; kk < nuse ; kk++ ) sptr[kk] = (short *) DSET_ARRAY(old_dset,kk) ; break ; /*--------- input is floats ---------*/ /* voxel #i at time #k is fptr[k][i] */ /* for i=0..nvox-1 and k=0..nuse-1. */ case MRI_float: fptr = (float **) malloc( sizeof(float *) * nuse ) ; if( fptr == NULL ) return "Malloc\nFailure!\n [fptr]" ; for( kk=0 ; kk < nuse ; kk++ ) fptr[kk] = (float *) DSET_ARRAY(old_dset,kk) ; break ; } /* end of switch on input type */ /*---- allocate space for 2 voxel timeseries and 1 FFT ----*/ this = (float *) malloc( sizeof(float) * nuse ) ; /* input */ tarD3 = (float *) malloc( sizeof(float) * MAX(nuse,nfreq) ) ; tarA3 = (float *) malloc( sizeof(float) * MAX(nuse,nfreq) ) ; taravgD3 = (float *) malloc( sizeof(float) * MAX(nuse,nfreq) ) ; /*flip = (float *)malloc( sizeof(float) * 1);*/ numAv = (float *)malloc( sizeof(float) * 1); numT=nuse-ignore; if (OutputFlag==1) sprintf(new_prefix,"%s%s",namestr,"_D3"); else sprintf(new_prefix,"%s%s",filename,"_D3"); new_dsetD3 = EDIT_empty_copy( old_dset ); { char * his = PLUTO_commandstring(plint) ; tross_Copy_History( old_dset , new_dsetD3 ) ; tross_Append_History( new_dsetD3 , his ) ; free(his) ; } /*-- edit some of its internal parameters --*/ ii = EDIT_dset_items( new_dsetD3 , ADN_prefix , new_prefix , /* filename prefix */ ADN_malloc_type , DATABLOCK_MEM_MALLOC , /* store in memory */ ADN_datum_all , new_datum , /* atomic datum */ ADN_nvals , numT , ADN_ntt ,numT, ADN_none ) ; if (OutputFlag==1) sprintf(new_prefix,"%s%s",namestr,"_A3"); else sprintf(new_prefix,"%s%s",filename,"_A3"); numT=nuse-ignore; new_dsetA3 = EDIT_empty_copy( old_dset ); { char * his = PLUTO_commandstring(plint) ; tross_Copy_History( old_dset , new_dsetA3 ) ; tross_Append_History( new_dsetA3 , his ) ; free(his) ; } /*-- edit some of its internal parameters --*/ ii = EDIT_dset_items( new_dsetA3 , ADN_prefix , new_prefix , /* filename prefix */ ADN_malloc_type , DATABLOCK_MEM_MALLOC , /* store in memory */ ADN_datum_all , new_datum , /* atomic datum */ ADN_nvals , numT, ADN_ntt ,numT, ADN_none ) ; if (OutputFlag==1) sprintf(new_prefix,"%s%s",namestr,"_avgD3"); else sprintf(new_prefix,"%s%s",filename,"_avgD3"); new_dsetavgD3 = EDIT_empty_copy( old_dset ); { char * his = PLUTO_commandstring(plint) ; tross_Copy_History( old_dset , new_dsetavgD3 ) ; tross_Append_History( new_dsetavgD3 , his ) ; free(his) ; } /*-- edit some of its internal parameters --*/ ii = EDIT_dset_items( new_dsetavgD3 , ADN_prefix , new_prefix , /* filename prefix */ ADN_malloc_type , DATABLOCK_MEM_MALLOC , /* store in memory */ ADN_datum_all , new_datum , /* atomic datum */ ADN_nvals , 1, ADN_ntt ,1, ADN_none ) ; /*---------------------- make a new dataset ----------------------*/ /*-------------------making a new dataset------------------------------------*/ /*------ make floating point output sub-bricks (only at the end will scale to byte or shorts) Output #ii at freq #kk will go into fout[kk][ii], for kk=0..nfreq-1, and for ii=0..nvox-1. ------*/ nvox = old_dset->daxes->nxx * old_dset->daxes->nyy * old_dset->daxes->nzz ; foutD3 = (float **) malloc( sizeof(float *) * nuse ) ; /* ptrs to sub-bricks */ foutA3 = (float **) malloc( sizeof(float *) * nuse ) ; /* ptrs to sub-bricks */ foutavgD3 = (float **) malloc( sizeof(float *) * 1 ) ; /* ptrs to sub-bricks */ if( foutD3 == NULL | foutA3 == NULL | foutavgD3 == NULL){ THD_delete_3dim_dataset( new_dsetD3 , False ) ; THD_delete_3dim_dataset( new_dsetA3 , False ) ; THD_delete_3dim_dataset( new_dsetavgD3 , False ) ; FREE_WORKSPACE ; return "Malloc\nFailure!\n [fout]" ; } for( kk=0 ; kk < nfreq ; kk++ ){ foutD3[kk] = (float *) malloc( sizeof(float) * nvox ) ; /* sub-brick # kk */ foutA3[kk] = (float *) malloc( sizeof(float) * nvox ) ; /* sub-brick # kk */ foutavgD3[0] = (float *) malloc( sizeof(float) * nvox ) ; /* sub-brick # kk */ if( foutD3[kk] == NULL ) break ; if( foutA3[kk] == NULL ) break ; if( foutavgD3[0] == NULL ) break ; } if( kk < nfreq ){ for( ; kk >= 0 ; kk-- ){ FREEUP(foutD3[kk]) ; FREEUP(foutA3[kk]) ; FREEUP(foutavgD3[0]) ; }/* free all we did get */ THD_delete_3dim_dataset( new_dsetD3 , False ) ; THD_delete_3dim_dataset( new_dsetA3 , False ) ; THD_delete_3dim_dataset( new_dsetavgD3 , False ) ; FREE_WORKSPACE ; return "Malloc\nFailure!\n [arrays]" ; } { char buf[128] ; ii = (nfreq * nvox * sizeof(float)) / (1024*1024) ; sprintf( buf , " \n" "*** 3D+time ASL a3/d3:\n" "*** Using %d MBytes of workspace,\n " "*** with # time points = %d\n" , ii,numT ) ; PLUTO_popup_transient( plint , buf ) ; } /*----------------------------------------------------*/ /*----- Setup has ended. Now do some real work. -----*/ /***** loop over voxels *****/ /* *(flip)=scale; */ *(numAv)= nuse-ignore; for( ii=0 ; ii < nvox ; ii ++ ){ /* time series */ switch( old_datum ){ case MRI_byte: for( kk=0 ; kk < nuse ; kk++ ){ this[kk] = bptr[kk][ii] ; } break ; case MRI_short: for( kk=0 ; kk < nuse ; kk++ ){ this[kk] = sptr[kk][ii] ; } break ; case MRI_float: for( kk=0 ; kk < nuse ; kk++ ){ this[kk] = fptr[kk][ii] ; } break ; } flip=scale*pow(-1,ignore+1); for( kk=0 ; kk < nuse-ignore ; kk++ ){ if (kk==nuse-1-ignore){ *(*(foutD3+kk)+ii)= flip*( *(this+kk+ignore-1)-*(this+kk+ignore) ); *(*(foutA3+kk)+ii)= 2*(*(this+kk+ignore-1)+*(this+kk+ignore)); } else if (kk==0){ /*D3 tag - control*/ *(*(foutD3+kk)+ii)= flip*( *(this+kk+ignore)-*(this+kk+ignore+1) ); *(*(foutA3+kk)+ii)= 2*(*(this+kk+ignore)+*(this+kk+ignore+1)); } else{ *(*(foutD3+kk)+ii)= flip*( 1*(*(this+kk+ignore-1))+-2*(*(this+kk+ignore))+1*(*(this+kk+ignore+1)) ); *(*(foutA3+kk)+ii)= ((*(this+kk+ignore-1))+2*(*(this+kk+ignore))+(*(this+kk+ignore+1))); flip=-1*flip; } } for( kk=0 ; kk < nuse-ignore ; kk++ ) *(*(foutavgD3)+ii)= *(*(foutavgD3)+ii)+(*(*(foutD3+kk)+ii)); *(*(foutavgD3)+ii)=*(*(foutavgD3)+ii) / (*(numAv)); } DSET_unload( old_dset ) ; /* don't need this no more */ switch( new_datum ){ /*** output is floats is the simplest: we just have to attach the fout bricks to the dataset ***/ case MRI_float: for( kk=0 ; kk < nuse-ignore ; kk++ ) EDIT_substitute_brick( new_dsetD3 , kk , MRI_float , foutD3[kk] ) ; break ; /*** output is shorts: we have to create a scaled sub-brick from fout ***/ case MRI_short:{ short * boutD3 ; float facD3 ; for( kk=0 ; kk < nuse-ignore ; kk++ ){ /* loop over sub-bricks */ /*-- get output sub-brick --*/ boutD3 = (short *) malloc( sizeof(short) * nvox ) ; if( boutD3 == NULL ){ fprintf(stderr,"\nFinal malloc error in plug_power!\n\a") ; EXIT(1) ; } /*-- find scaling and then scale --*/ facD3 = MCW_vol_amax( nvox,1,1 , MRI_float , foutD3[kk] ) ; if( facD3 > 0.0 ){ facD3 = 32767.0 / facD3 ; EDIT_coerce_scale_type( nvox,facD3 , MRI_float,foutD3[kk] , MRI_short,boutD3 ) ; facD3 = 1.0 / facD3 ; } free( foutD3[kk] ) ; /* don't need this anymore */ /*-- put output brick into dataset, and store scale factor --*/ EDIT_substitute_brick( new_dsetD3 , kk , MRI_short , boutD3 ) ; tarD3 [kk] = facD3 ; } /*-- save scale factor array into dataset --*/ EDIT_dset_items( new_dsetD3 , ADN_brick_fac , tarD3 , ADN_none ) ; } break ; /*** output is bytes (byte = unsigned char) we have to create a scaled sub-brick from fout ***/ case MRI_byte:{ byte * boutD3 ; float facD3 ; for( kk=0 ; kk < nuse-ignore ; kk++ ){ /* loop over sub-bricks */ /*-- get output sub-brick --*/ boutD3 = (byte *) malloc( sizeof(byte) * nvox ) ; if( boutD3 == NULL ){ fprintf(stderr,"\nFinal malloc error in plug_power!\n\a") ; EXIT(1) ; } /*-- find scaling and then scale --*/ facD3 = MCW_vol_amax( nvox,1,1 , MRI_float , foutD3[kk] ) ; if( facD3 > 0.0 ){ facD3 = 255.0 / facD3 ; EDIT_coerce_scale_type( nvox,facD3 , MRI_float,foutD3[kk] , MRI_byte,boutD3 ) ; facD3 = 1.0 / facD3 ; } free( foutD3[kk] ) ; /* don't need this anymore */ /*-- put output brick into dataset, and store scale factor --*/ EDIT_substitute_brick( new_dsetD3 , kk , MRI_byte , boutD3 ) ; tarD3 [kk] = facD3 ; } /*-- save scale factor array into dataset --*/ EDIT_dset_items( new_dsetD3 , ADN_brick_fac , tarD3 , ADN_none ) ; } break ; } /* end of switch on output data type */ switch( new_datum ){ /*** output is floats is the simplest: we just have to attach the fout bricks to the dataset ***/ case MRI_float: for( kk=0 ; kk < nuse-ignore ; kk++ ) EDIT_substitute_brick( new_dsetA3 , kk , MRI_float , foutA3[kk] ) ; break ; /*** output is shorts: we have to create a scaled sub-brick from fout ***/ case MRI_short:{ short * boutA3 ; float facA3 ; for( kk=0 ; kk < nuse-ignore ; kk++ ){ /* loop over sub-bricks */ /*-- get output sub-brick --*/ boutA3 = (short *) malloc( sizeof(short) * nvox ) ; if( boutA3 == NULL ){ fprintf(stderr,"\nFinal malloc error in plug_power!\n\a") ; EXIT(1) ; } /*-- find scaling and then scale --*/ facA3 = MCW_vol_amax( nvox,1,1 , MRI_float , foutA3[kk] ) ; if( facA3 > 0.0 ){ facA3 = 32767.0 / facA3 ; EDIT_coerce_scale_type( nvox,facA3 , MRI_float,foutA3[kk] , MRI_short,boutA3 ) ; facA3 = 1.0 / facA3 ; } free( foutA3[kk] ) ; /* don't need this anymore */ /*-- put output brick into dataset, and store scale factor --*/ EDIT_substitute_brick( new_dsetA3 , kk , MRI_short , boutA3 ) ; tarA3[kk] = facA3 ; } /*-- save scale factor array into dataset --*/ EDIT_dset_items( new_dsetA3 , ADN_brick_fac , tarA3 , ADN_none ) ; } break ; /*** output is bytes (byte = unsigned char) we have to create a scaled sub-brick from fout ***/ case MRI_byte:{ byte * boutA3 ; float facA3 ; for( kk=0 ; kk < nuse-ignore ; kk++ ){ /* loop over sub-bricks */ /*-- get output sub-brick --*/ boutA3 = (byte *) malloc( sizeof(byte) * nvox ) ; if( boutA3 == NULL ){ fprintf(stderr,"\nFinal malloc error in plug_power!\n\a") ; EXIT(1) ; } /*-- find scaling and then scale --*/ facA3 = MCW_vol_amax( nvox,1,1 , MRI_float , foutA3[kk] ) ; if( facA3 > 0.0 ){ facA3 = 255.0 / facA3 ; EDIT_coerce_scale_type( nvox,facA3 , MRI_float,foutA3[kk] , MRI_byte,boutA3 ) ; facA3 = 1.0 / facA3 ; } free( foutA3[kk] ) ; /* don't need this anymore */ /*-- put output brick into dataset, and store scale factor --*/ EDIT_substitute_brick( new_dsetA3 , kk , MRI_byte , boutA3 ) ; tarA3[kk]= facA3 ; } /*-- save scale factor array into dataset --*/ EDIT_dset_items( new_dsetA3 , ADN_brick_fac , tarA3 , ADN_none ) ; } break ; } /* end of switch on output data type */ switch( new_datum ){ case MRI_float:{ EDIT_substitute_brick( new_dsetavgD3 , 0 , MRI_float , foutavgD3[0] ) ; } break ; case MRI_short:{ short * boutavgD3 ; float facavgD3 ; boutavgD3 = (short *) malloc( sizeof(short) * nvox ) ; if( boutavgD3 == NULL ){ fprintf(stderr,"\nFinal malloc error in plug_power!\n\a") ; EXIT(1) ; } facavgD3 = MCW_vol_amax( nvox,1,1 , MRI_float , foutavgD3[0] ) ; if( facavgD3 > 0.0 ){ facavgD3 = 32767.0 / facavgD3 ; EDIT_coerce_scale_type( nvox,facavgD3 , MRI_float,foutavgD3[0] , MRI_short,boutavgD3 ) ; facavgD3 = 1.0 / facavgD3 ; } EDIT_substitute_brick( new_dsetavgD3 , 0 , MRI_short , boutavgD3 ) ; taravgD3[0] = facavgD3 ; EDIT_dset_items( new_dsetavgD3 , ADN_brick_fac , taravgD3 , ADN_none ) ; } break ; case MRI_byte:{ byte * boutavgD3 ; float facavgD3 ; boutavgD3 = (byte *) malloc( sizeof(byte) * nvox ) ; if( boutavgD3 == NULL ){ fprintf(stderr,"\nFinal malloc error in plug_power!\n\a") ; EXIT(1) ; } facavgD3 = MCW_vol_amax( nvox,1,1 , MRI_float , foutavgD3[0] ) ; if( facavgD3 > 0.0 ){ facavgD3 = 255.0 / facavgD3 ; EDIT_coerce_scale_type( nvox,facavgD3 , MRI_float,foutavgD3[0] , MRI_byte,boutavgD3 ) ; facavgD3 = 1.0 / facavgD3 ; } EDIT_substitute_brick( new_dsetavgD3 , 0 , MRI_byte , boutavgD3 ) ; taravgD3[0]= facavgD3 ; EDIT_dset_items( new_dsetavgD3 , ADN_brick_fac , taravgD3 , ADN_none ) ; } break ; } /* endasda of switch on output data type */ /*-------------- Cleanup and go home ----------------*/ PLUTO_add_dset( plint , new_dsetD3 , DSET_ACTION_NONE ) ; PLUTO_add_dset( plint , new_dsetA3 , DSET_ACTION_NONE ) ; PLUTO_add_dset( plint , new_dsetavgD3 , DSET_ACTION_NONE ) ; FREE_WORKSPACE ; free(numAv); return NULL ; /* null string returned means all was OK */ }
int main( int argc , char * argv[] ) { int ninp , ids , nv , iv,jv,kv , ivout , new_nvals , have_fdr = 0, nfdr = 0 ; THD_3dim_dataset * new_dset=NULL , * dset ; char buf[256] ; double angle; /*----- identify program -----*/ #if 0 printf ("\n\nProgram %s \n", PROGRAM_NAME); printf ("Last revision: %s \n\n", LAST_MOD_DATE); #endif /*** read input options ***/ mainENTRY("3dbucket main"); machdep(); PRINT_VERSION("3dbucket") ; set_obliquity_report(0); /* silence obliquity */ /*-- 20 Apr 2001: addto the arglist, if user wants to [RWCox] --*/ { int new_argc ; char ** new_argv ; addto_args( argc , argv , &new_argc , &new_argv ) ; if( new_argv != NULL ){ argc = new_argc ; argv = new_argv ; } } AFNI_logger("3dbucket",argc,argv) ; BUCK_read_opts( argc , argv ) ; /*** create new dataset (empty) ***/ ninp = BUCK_dsar->num ; if( ninp < 1 ){ fprintf(stderr,"*** No input datasets?\n") ; exit(1) ; } new_nvals = 0 ; for( ids=0 ; ids < ninp ; ids++ ) new_nvals += NSUBV(ids) ; if( BUCK_verb ) printf("-verb: output will have %d sub-bricks\n",new_nvals) ; new_dset = EDIT_empty_copy( DSUB(0) ) ; /* 23 May 2005: check for axis consistency */ /* 06 Feb 2008: and see if there are fdrcurves to perpetuate */ if( DSUB(0)->dblk->brick_fdrcurve ) have_fdr = 1 ; for( iv=1 ; iv < ninp ; iv++ ){ if( !EQUIV_DATAXES(new_dset->daxes,DSUB(iv)->daxes) ) fprintf(stderr,"++ WARNING: %s grid mismatch with %s\n", DSET_BRIKNAME(DSUB(0)) , DSET_BRIKNAME(DSUB(iv)) ) ; if( DSUB(iv)->dblk->brick_fdrcurve ) have_fdr = 1 ; angle = dset_obliquity_angle_diff(new_dset, DSUB(iv), -1.0); if (angle > 0.0) { WARNING_message( "dataset %s has an obliquity difference of %f degress with %s\n", new_dset , angle, DSUB(iv) ); } } /* if( ninp == 1 ) */ tross_Copy_History( DSUB(0) , new_dset ) ; tross_Make_History( "3dbucket" , argc,argv , new_dset ) ; EDIT_dset_items( new_dset , ADN_prefix , BUCK_output_prefix , ADN_directory_name, BUCK_session , ADN_type , BUCK_type , ADN_func_type , ISANATTYPE(BUCK_type) ? ANAT_BUCK_TYPE : FUNC_BUCK_TYPE, ADN_ntt , 0 , ADN_nvals , new_nvals , ADN_none ) ; /* can't re-write existing dataset, unless glueing is used */ if (! BUCK_glue){ if( THD_deathcon() && THD_is_file(DSET_HEADNAME(new_dset)) ){ fprintf(stderr,"*** Fatal error: file %s already exists!\n", DSET_HEADNAME(new_dset) ) ; exit(1) ; } } else { /* if glueing is used, make the 'new' dataset have the same idcode as the old one */ new_dset->idcode = DSUB(0) -> idcode ; /* copy the struct */ } THD_force_malloc_type( new_dset->dblk , DATABLOCK_MEM_MALLOC ) ; /* if there are fdr curves, allocate space 06 Feb 2008 [rickr] */ if( have_fdr ){ new_dset->dblk->brick_fdrcurve = (floatvec **)calloc(sizeof(floatvec *), new_nvals) ; if( !new_dset->dblk->brick_fdrcurve ){ fprintf(stderr,"** failed to alloc %d fdrcurves\n",new_nvals); exit(1); } if( BUCK_verb ) printf("-verb: adding fdrcurve list\n"); new_dset->dblk->brick_mdfcurve = (floatvec **)calloc(sizeof(floatvec *), /* 22 Oct 2008 */ new_nvals) ; } /*** loop over input datasets ***/ if( ninp > 1 ) myXtFree( new_dset->keywords ) ; ivout = 0 ; for( ids=0 ; ids < ninp ; ids++ ){ dset = DSUB(ids) ; nv = NSUBV(ids) ; if( ! BUCK_dry ){ DSET_load(dset) ; CHECK_LOAD_ERROR(dset) ; } /** loop over sub-bricks to output **/ for( iv=0 ; iv < nv ; iv++ ){ jv = SUBV(ids,iv) ; /* which sub-brick to use */ if( ! BUCK_dry ){ EDIT_substitute_brick( new_dset , ivout , DSET_BRICK_TYPE(dset,jv) , DSET_ARRAY(dset,jv) ) ; /*----- preserve label when one exists --- Modified March 2010 ZSS*/ if (DSET_HAS_LABEL(dset, jv) ) sprintf (buf, "%s", DSET_BRICK_LABEL(dset,jv)); else sprintf(buf,"%.12s[%d]",DSET_PREFIX(dset),jv) ; EDIT_dset_items( new_dset , ADN_brick_label_one+ivout, buf , ADN_none ) ; #if 0 sprintf(buf,"%s[%d]",DSET_FILECODE(dset),jv) ; EDIT_dset_items( new_dset, ADN_brick_keywords_replace_one+ivout, buf, ADN_none ) ; #endif EDIT_dset_items( new_dset , ADN_brick_fac_one +ivout, DSET_BRICK_FACTOR(dset,jv), #if 0 ADN_brick_keywords_append_one+ivout, DSET_BRICK_KEYWORDS(dset,jv) , #endif ADN_none ) ; /** possibly write statistical parameters for this sub-brick **/ kv = DSET_BRICK_STATCODE(dset,jv) ; if( FUNC_IS_STAT(kv) ){ /* input sub-brick has stat params */ int npar = FUNC_need_stat_aux[kv] , lv ; float * par = (float *) malloc( sizeof(float) * (npar+2) ) ; float * sax = DSET_BRICK_STATAUX(dset,jv) ; par[0] = kv ; par[1] = npar ; for( lv=0 ; lv < npar ; lv++ ) par[lv+2] = (sax != NULL) ? sax[lv] : 0.0 ; EDIT_dset_items(new_dset , ADN_brick_stataux_one+ivout , par , ADN_none ) ; free(par) ; /* 2: if the input dataset has statistical parameters */ } else if( ISFUNC(dset) && /* dset has stat */ FUNC_IS_STAT(dset->func_type) && /* params */ jv == FUNC_ival_thr[dset->func_type] ){ /* thr sub-brick */ int npar , lv ; float * par , * sax ; kv = dset->func_type ; npar = FUNC_need_stat_aux[kv] ; par = (float *) malloc( sizeof(float) * (npar+2) ) ; sax = dset->stat_aux ; par[0] = kv ; par[1] = npar ; for( lv=0 ; lv < npar ; lv++ ) par[lv+2] = (sax != NULL) ? sax[lv] : 0.0 ; EDIT_dset_items(new_dset , ADN_brick_stataux_one+ivout , par , ADN_none ) ; free(par) ; } /** append any fdrcurve **/ if( have_fdr ){ /* fixed iv->jv (ick!), noticed by dglen 16 Mar 2010 [rickr] */ if(dset->dblk->brick_fdrcurve && dset->dblk->brick_fdrcurve[jv]){ COPY_floatvec(new_dset->dblk->brick_fdrcurve[ivout], dset->dblk->brick_fdrcurve[jv]) ; nfdr++; } else new_dset->dblk->brick_fdrcurve[ivout] = NULL ; if(dset->dblk->brick_mdfcurve && dset->dblk->brick_mdfcurve[jv]){ COPY_floatvec(new_dset->dblk->brick_mdfcurve[ivout], dset->dblk->brick_mdfcurve[jv]) ; } else new_dset->dblk->brick_mdfcurve[ivout] = NULL ; } /** print a message? **/ if( BUCK_verb ) printf("-verb: copied %s[%d] into %s[%d]\n" , DSET_FILECODE(dset) , jv , DSET_FILECODE(new_dset) , ivout ) ; } else { printf("-dry: would copy %s[%d] into %s[%d]\n" , DSET_FILECODE(dset) , jv , DSET_FILECODE(new_dset) , ivout ) ; } ivout++ ; } /** loop over all bricks in input dataset and unload them if they aren't going into the output (not required, but is done to economize on memory) **/ if( ! BUCK_dry && nv < DSET_NVALS(dset) ){ for( kv=0 ; kv < DSET_NVALS(dset) ; kv++ ){ /* all input sub-bricks */ for( iv=0 ; iv < nv ; iv++ ){ /* all output sub-bricks */ jv = SUBV(ids,iv) ; if( jv == kv ) break ; /* input matches output */ } if( iv == nv ){ mri_free( DSET_BRICK(dset,kv) ) ; #if 0 if( BUCK_verb ) printf("-verb: unloaded unused %s[%d]\n" , DSET_FILECODE(dset) , kv ) ; #endif } } } } /* end of loop over input datasets */ if( ! BUCK_dry ){ if( BUCK_verb ){ if( have_fdr ) fprintf(stderr,"-verb: added %d of %d fdr curves\n", nfdr, new_nvals); fprintf(stderr,"-verb: loading statistics\n") ; } THD_load_statistics( new_dset ) ; if( BUCK_glue ) putenv("AFNI_DECONFLICT=OVERWRITE") ; if( BUCK_glue && BUCK_ccode >= 0 ) THD_set_write_compression(BUCK_ccode) ; /* 16 Mar 2010 */ THD_write_3dim_dataset( NULL,NULL , new_dset , True ) ; if( BUCK_verb ) fprintf(stderr,"-verb: wrote output: %s\n",DSET_BRIKNAME(new_dset)) ; } exit(0) ; }
int main( int argc , char *argv[] ) { THD_3dim_dataset *dset , *oset=NULL , *tset=NULL ; int nvals , iv , nxyz , ii,jj,kk , iarg , kz,kzold ; float cut1=2.5,cut2=4.0 , sq2p,sfac , fq ; MRI_IMAGE *flim ; char *prefix="despike" , *tprefix=NULL ; int corder=-1 , nref , ignore=0 , polort=2 , nuse , nomask=0 ; int nspike, nbig, nproc ; float **ref ; float c21,ic21 , pspike,pbig ; short *sar , *qar ; byte *tar , *mask=NULL ; float *zar , *yar ; int datum ; int localedit=0 ; /* 04 Apr 2007 */ int verb=1 ; int do_NEW = 0 ; /* 29 Nov 2013 */ MRI_IMAGE *NEW_psinv=NULL ; int dilate = 4 ; /* 04 Dec 2013 */ int ctim = 0 ; /*----- Read command line -----*/ AFNI_SETUP_OMP(0) ; /* 24 Jun 2013 */ if( argc < 2 || strcmp(argv[1],"-help") == 0 ){ printf("Usage: 3dDespike [options] dataset\n" "Removes 'spikes' from the 3D+time input dataset and writes\n" "a new dataset with the spike values replaced by something\n" "more pleasing to the eye.\n" "\n" "Method:\n" " * L1 fit a smooth-ish curve to each voxel time series\n" " [see -corder option for description of the curve]\n" " [see -NEW option for a different & faster fitting method]\n" " * Compute the MAD of the difference between the curve and\n" " the data time series (the residuals).\n" " * Estimate the standard deviation 'sigma' of the residuals\n" " as sqrt(PI/2)*MAD.\n" " * For each voxel value, define s = (value-curve)/sigma.\n" " * Values with s > c1 are replaced with a value that yields\n" " a modified s' = c1+(c2-c1)*tanh((s-c1)/(c2-c1)).\n" " * c1 is the threshold value of s for a 'spike' [default c1=2.5].\n" " * c2 is the upper range of the allowed deviation from the curve:\n" " s=[c1..infinity) is mapped to s'=[c1..c2) [default c2=4].\n" "\n" "Options:\n" " -ignore I = Ignore the first I points in the time series:\n" " these values will just be copied to the\n" " output dataset [default I=0].\n" " -corder L = Set the curve fit order to L:\n" " the curve that is fit to voxel data v(t) is\n" "\n" " k=L [ (2*PI*k*t) (2*PI*k*t) ]\n" " f(t) = a+b*t+c*t*t + SUM [ d * sin(--------) + e * cos(--------) ]\n" " k=1 [ k ( T ) k ( T ) ]\n" "\n" " where T = duration of time series;\n" " the a,b,c,d,e parameters are chosen to minimize\n" " the sum over t of |v(t)-f(t)| (L1 regression);\n" " this type of fitting is is insensitive to large\n" " spikes in the data. The default value of L is\n" " NT/30, where NT = number of time points.\n" "\n" " -cut c1 c2 = Alter default values for the spike cut values\n" " [default c1=2.5, c2=4.0].\n" " -prefix pp = Save de-spiked dataset with prefix 'pp'\n" " [default pp='despike']\n" " -ssave ttt = Save 'spikiness' measure s for each voxel into a\n" " 3D+time dataset with prefix 'ttt' [default=no save]\n" " -nomask = Process all voxels\n" " [default=use a mask of high-intensity voxels, ]\n" " [as created via '3dAutomask -dilate 4 dataset'].\n" " -dilate nd = Dilate 'nd' times (as in 3dAutomask). The default\n" " value of 'nd' is 4.\n" " -q[uiet] = Don't print '++' informational messages.\n" "\n" " -localedit = Change the editing process to the following:\n" " If a voxel |s| value is >= c2, then replace\n" " the voxel value with the average of the two\n" " nearest non-spike (|s| < c2) values; the first\n" " one previous and the first one after.\n" " Note that the c1 cut value is not used here.\n" "\n" " -NEW = Use the 'new' method for computing the fit, which\n" " should be faster than the L1 method for long time\n" " series (200+ time points); however, the results\n" " are similar but NOT identical. [29 Nov 2013]\n" " * You can also make the program use the 'new'\n" " method by setting the environment variable\n" " AFNI_3dDespike_NEW\n" " to the value YES; as in\n" " setenv AFNI_3dDespike_NEW YES (csh)\n" " export AFNI_3dDespike_NEW=YES (bash)\n" " * If this variable is set to YES, you can turn off\n" " the '-NEW' processing by using the '-OLD' option.\n" " -->>* For time series more than 500 points long, the\n" " '-OLD' algorithm is tremendously slow. You should\n" " use the '-NEW' algorith in such cases.\n" " ** At some indeterminate point in the future, the '-NEW'\n" " method will become the default!\n" " -->>* As of 29 Sep 2016, '-NEW' is the default if there\n" " is more than 500 points in the time series dataset.\n" "\n" " -NEW25 = A slightly more aggressive despiking approach than\n" " the '-NEW' method.\n" "\n" "Caveats:\n" "* Despiking may interfere with image registration, since head\n" " movement may produce 'spikes' at the edge of the brain, and\n" " this information would be used in the registration process.\n" " This possibility has not been explored or calibrated.\n" "* [LATER] Actually, it seems like the registration problem\n" " does NOT happen, and in fact, despiking seems to help!\n" "* Check your data visually before and after despiking and\n" " registration!\n" " [Hint: open 2 AFNI controllers, and turn Time Lock on.]\n" ) ; PRINT_AFNI_OMP_USAGE("3dDespike",NULL) ; PRINT_COMPILE_DATE ; exit(0) ; } /** AFNI package setup and logging **/ mainENTRY("3dDespike main"); machdep(); AFNI_logger("3dDespike",argc,argv); PRINT_VERSION("3dDespike") ; AUTHOR("RW Cox") ; /** parse options **/ if( AFNI_yesenv("AFNI_3dDespike_NEW") ) do_NEW = 1 ; /* 29 Nov 2013 */ iarg = 1 ; while( iarg < argc && argv[iarg][0] == '-' ){ if( strncmp(argv[iarg],"-q",2) == 0 ){ /* 04 Apr 2007 */ verb = 0 ; iarg++ ; continue ; } if( strncmp(argv[iarg],"-v",2) == 0 ){ verb++ ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-NEW") == 0 ){ /* 29 Nov 2013 */ do_NEW = 1 ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-NEW25") == 0 ){ /* 29 Sep 2016 */ do_NEW = 1 ; use_des25 = 1 ; cut1 = 2.5f ; cut2 = 3.2f ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-OLD") == 0 ){ do_NEW = 0 ; iarg++ ; continue ; } /** -localedit **/ if( strcmp(argv[iarg],"-localedit") == 0 ){ /* 04 Apr 2007 */ localedit = 1 ; iarg++ ; continue ; } /** don't use masking **/ if( strcmp(argv[iarg],"-nomask") == 0 ){ nomask = 1 ; iarg++ ; continue ; } /** dilation count [04 Dec 2013] **/ if( strcmp(argv[iarg],"-dilate") == 0 ){ dilate = (int)strtod(argv[++iarg],NULL) ; if( dilate <= 0 ) dilate = 1 ; else if( dilate > 99 ) dilate = 99 ; iarg++ ; continue ; } /** output dataset prefix **/ if( strcmp(argv[iarg],"-prefix") == 0 ){ prefix = argv[++iarg] ; if( !THD_filename_ok(prefix) ) ERROR_exit("-prefix is not good"); iarg++ ; continue ; } /** ratio dataset prefix **/ if( strcmp(argv[iarg],"-ssave") == 0 ){ tprefix = argv[++iarg] ; if( !THD_filename_ok(tprefix) ) ERROR_exit("-ssave prefix is not good"); iarg++ ; continue ; } /** trigonometric polynomial order **/ if( strcmp(argv[iarg],"-corder") == 0 ){ corder = strtol( argv[++iarg] , NULL , 10 ) ; if( corder < 0 ) ERROR_exit("Illegal value of -corder"); iarg++ ; continue ; } /** how much to ignore at start **/ if( strcmp(argv[iarg],"-ignore") == 0 ){ ignore = strtol( argv[++iarg] , NULL , 10 ) ; if( ignore < 0 ) ERROR_exit("Illegal value of -ignore"); iarg++ ; continue ; } /** thresholds for s ratio **/ if( strcmp(argv[iarg],"-cut") == 0 ){ cut1 = strtod( argv[++iarg] , NULL ) ; cut2 = strtod( argv[++iarg] , NULL ) ; if( cut1 < 1.0 || cut2 < cut1+0.5 ) ERROR_exit("Illegal values after -cut"); iarg++ ; continue ; } ERROR_exit("Unknown option: %s",argv[iarg]) ; } c21 = cut2-cut1 ; ic21 = 1.0/c21 ; /*----- read input dataset -----*/ if( iarg >= argc ) ERROR_exit("No input dataset!!??"); dset = THD_open_dataset( argv[iarg] ) ; CHECK_OPEN_ERROR(dset,argv[iarg]) ; datum = DSET_BRICK_TYPE(dset,0) ; if( (datum != MRI_short && datum != MRI_float) || !DSET_datum_constant(dset) ) ERROR_exit("Can't process non-short, non-float dataset!") ; if( verb ) INFO_message("Input data type = %s\n",MRI_TYPE_name[datum]) ; nvals = DSET_NUM_TIMES(dset) ; nuse = nvals - ignore ; if( nuse < 15 ) ERROR_exit("Can't use dataset with < 15 time points per voxel!") ; if( nuse > 500 && !do_NEW ){ INFO_message("Switching to '-NEW' method since number of time points = %d > 500",nuse) ; do_NEW = 1 ; } if( use_des25 && nuse < 99 ) use_des25 = 0 ; if( verb ) INFO_message("ignoring first %d time points, using last %d",ignore,nuse); if( corder > 0 && 4*corder+2 > nuse ){ ERROR_exit("-corder %d is too big for NT=%d",corder,nvals) ; } else if( corder < 0 ){ corder = rint(nuse/30.0) ; if( corder > 50 && !do_NEW ) corder = 50 ; if( verb ) INFO_message("using %d time points => -corder %d",nuse,corder) ; } else { if( verb ) INFO_message("-corder %d set from command line",corder) ; } nxyz = DSET_NVOX(dset) ; if( verb ) INFO_message("Loading dataset %s",argv[iarg]) ; DSET_load(dset) ; CHECK_LOAD_ERROR(dset) ; /*-- create automask --*/ if( !nomask ){ mask = THD_automask( dset ) ; if( verb ){ ii = THD_countmask( DSET_NVOX(dset) , mask ) ; INFO_message("%d voxels in the automask [out of %d in dataset]",ii,DSET_NVOX(dset)) ; } for( ii=0 ; ii < dilate ; ii++ ) THD_mask_dilate( DSET_NX(dset), DSET_NY(dset), DSET_NZ(dset), mask, 3 ) ; if( verb ){ ii = THD_countmask( DSET_NVOX(dset) , mask ) ; INFO_message("%d voxels in the dilated automask [out of %d in dataset]",ii,DSET_NVOX(dset)) ; } } else { if( verb ) INFO_message("processing all %d voxels in dataset",DSET_NVOX(dset)) ; } /*-- create empty despiked dataset --*/ oset = EDIT_empty_copy( dset ) ; EDIT_dset_items( oset , ADN_prefix , prefix , ADN_brick_fac , NULL , ADN_datum_all , datum , ADN_none ) ; if( THD_deathcon() && THD_is_file(DSET_HEADNAME(oset)) ) ERROR_exit("output dataset already exists: %s",DSET_HEADNAME(oset)); tross_Copy_History( oset , dset ) ; tross_Make_History( "3dDespike" , argc , argv , oset ) ; /* create bricks (will be filled with zeros) */ for( iv=0 ; iv < nvals ; iv++ ) EDIT_substitute_brick( oset , iv , datum , NULL ) ; /* copy the ignored bricks */ switch( datum ){ case MRI_short: for( iv=0 ; iv < ignore ; iv++ ){ sar = DSET_ARRAY(oset,iv) ; qar = DSET_ARRAY(dset,iv) ; memcpy( sar , qar , DSET_BRICK_BYTES(dset,iv) ) ; DSET_unload_one(dset,iv) ; } break ; case MRI_float: for( iv=0 ; iv < ignore ; iv++ ){ zar = DSET_ARRAY(oset,iv) ; yar = DSET_ARRAY(dset,iv) ; memcpy( zar , yar , DSET_BRICK_BYTES(dset,iv) ) ; DSET_unload_one(dset,iv) ; } break ; } /*-- setup to save a threshold statistic dataset, if desired --*/ if( tprefix != NULL ){ float *fac ; tset = EDIT_empty_copy( dset ) ; fac = (float *) malloc( sizeof(float) * nvals ) ; for( ii=0 ; ii < nvals ; ii++ ) fac[ii] = TFAC ; EDIT_dset_items( tset , ADN_prefix , tprefix , ADN_brick_fac , fac , ADN_datum_all , MRI_byte , ADN_func_type , FUNC_FIM_TYPE , ADN_none ) ; free(fac) ; tross_Copy_History( tset , dset ) ; tross_Make_History( "3dDespike" , argc , argv , tset ) ; #if 0 if( THD_is_file(DSET_HEADNAME(tset)) ) ERROR_exit("-ssave dataset already exists"); #endif tross_Copy_History( tset , dset ) ; tross_Make_History( "3dDespike" , argc , argv , tset ) ; for( iv=0 ; iv < nvals ; iv++ ) EDIT_substitute_brick( tset , iv , MRI_byte , NULL ) ; } /*-- setup to find spikes --*/ sq2p = sqrt(0.5*PI) ; sfac = sq2p / 1.4826f ; /* make ref functions */ nref = 2*corder+3 ; ref = (float **) malloc( sizeof(float *) * nref ) ; for( jj=0 ; jj < nref ; jj++ ) ref[jj] = (float *) malloc( sizeof(float) * nuse ) ; /* r(t) = 1 */ for( iv=0 ; iv < nuse ; iv++ ) ref[0][iv] = 1.0 ; jj = 1 ; /* r(t) = t - tmid */ { float tm = 0.5 * (nuse-1.0) ; float fac = 2.0 / nuse ; for( iv=0 ; iv < nuse ; iv++ ) ref[1][iv] = (iv-tm)*fac ; jj = 2 ; /* r(t) = (t-tmid)**jj */ for( ; jj <= polort ; jj++ ) for( iv=0 ; iv < nuse ; iv++ ) ref[jj][iv] = pow( (iv-tm)*fac , (double)jj ) ; } for( kk=1 ; kk <= corder ; kk++ ){ fq = (2.0*PI*kk)/nuse ; /* r(t) = sin(2*PI*k*t/N) */ for( iv=0 ; iv < nuse ; iv++ ) ref[jj][iv] = sin(fq*iv) ; jj++ ; /* r(t) = cos(2*PI*k*t/N) */ for( iv=0 ; iv < nuse ; iv++ ) ref[jj][iv] = cos(fq*iv) ; jj++ ; } /****** setup for the NEW solution method [29 Nov 2013] ******/ if( do_NEW ){ NEW_psinv = DES_get_psinv(nuse,nref,ref) ; INFO_message("Procesing time series with NEW model fit algorithm") ; } else { INFO_message("Procesing time series with OLD model fit algorithm") ; } /*--- loop over voxels and do work ---*/ #define Laplace_t2p(val) ( 1.0 - nifti_stat2cdf( (val), 15, 0.0, 1.4427 , 0.0 ) ) if( verb ){ if( !localedit ){ INFO_message("smash edit thresholds: %.1f .. %.1f MADs",cut1*sq2p,cut2*sq2p) ; ININFO_message(" [ %.3f%% .. %.3f%% of normal distribution]", 200.0*qg(cut1*sfac) , 200.0*qg(cut2*sfac) ) ; ININFO_message(" [ %.3f%% .. %.3f%% of Laplace distribution]" , 100.0*Laplace_t2p(cut1) , 100.0*Laplace_t2p(cut2) ) ; } else { INFO_message("local edit threshold: %.1f MADS",cut2*sq2p) ; ININFO_message(" [ %.3f%% of normal distribution]", 200.0*qg(cut2*sfac) ) ; ININFO_message(" [ %.3f%% of Laplace distribution]", 100.0*Laplace_t2p(cut1) ) ; } INFO_message("%d slices to process",DSET_NZ(dset)) ; } kzold = -1 ; nspike = 0 ; nbig = 0 ; nproc = 0 ; ctim = NI_clock_time() ; AFNI_OMP_START ; #pragma omp parallel if( nxyz > 6666 ) { int ii , iv , iu , id , jj ; float *far , *dar , *var , *fitar , *ssp , *fit , *zar ; short *sar , *qar ; byte *tar ; float fsig , fq , cls , snew , val ; float *NEW_wks=NULL ; #pragma omp critical (DESPIKE_malloc) { far = (float *) malloc( sizeof(float) * nvals ) ; dar = (float *) malloc( sizeof(float) * nvals ) ; var = (float *) malloc( sizeof(float) * nvals ) ; fitar = (float *) malloc( sizeof(float) * nvals ) ; ssp = (float *) malloc( sizeof(float) * nvals ) ; fit = (float *) malloc( sizeof(float) * nref ) ; if( do_NEW ) NEW_wks = (float *)malloc(sizeof(float)*DES_workspace_size(nuse,nref)) ; } #ifdef USE_OMP INFO_message("start OpenMP thread #%d",omp_get_thread_num()) ; #endif #pragma omp for for( ii=0 ; ii < nxyz ; ii++ ){ /* ii = voxel index */ if( mask != NULL && mask[ii] == 0 ) continue ; /* skip this voxel */ #ifndef USE_OMP kz = DSET_index_to_kz(dset,ii) ; /* starting a new slice */ if( kz != kzold ){ if( verb ){ fprintf(stderr, "++ start slice %2d",kz ) ; if( nproc > 0 ){ pspike = (100.0*nspike)/nproc ; pbig = (100.0*nbig )/nproc ; fprintf(stderr, "; so far %d data points, %d edits [%.3f%%], %d big edits [%.3f%%]", nproc,nspike,pspike,nbig,pbig ) ; } fprintf(stderr,"\n") ; } kzold = kz ; } #else if( verb && ii % 2345 == 1234 ) fprintf(stderr,".") ; #endif /*** extract ii-th time series into far[] ***/ switch( datum ){ case MRI_short: for( iv=0 ; iv < nuse ; iv++ ){ qar = DSET_ARRAY(dset,iv+ignore) ; /* skip ignored data */ far[iv] = (float)qar[ii] ; } break ; case MRI_float: for( iv=0 ; iv < nuse ; iv++ ){ zar = DSET_ARRAY(dset,iv+ignore) ; far[iv] = zar[ii] ; } break ; } AAmemcpy(dar,far,sizeof(float)*nuse) ; /* copy time series into dar[] */ /*** solve for L1 fit ***/ if( do_NEW ) cls = DES_solve( NEW_psinv , far , fit , NEW_wks ) ; /* 29 Nov 2013 */ else cls = cl1_solve( nuse , nref , far , ref , fit,0 ) ; /* the slow part */ if( cls < 0.0f ){ /* fit failed! */ #if 0 fprintf(stderr,"curve fit fails at voxel %d %d %d\n", DSET_index_to_ix(dset,ii) , DSET_index_to_jy(dset,ii) , DSET_index_to_kz(dset,ii) ) ; #endif continue ; /* skip this voxel */ } for( iv=0 ; iv < nuse ; iv++ ){ /* detrend */ val = fit[0] + fit[1]*ref[1][iv] /* quadratic part of curve fit */ + fit[2]*ref[2][iv] ; for( jj=3 ; jj < nref ; jj++ ) /* rest of curve fit */ val += fit[jj] * ref[jj][iv] ; fitar[iv] = val ; /* save curve fit value */ var[iv] = dar[iv]-val ; /* remove fitted value = resid */ far[iv] = fabsf(var[iv]) ; /* abs value of resid */ } /*** compute estimate standard deviation of detrended data ***/ fsig = sq2p * qmed_float(nuse,far) ; /* also mangles far array */ /*** process time series for spikes, editing data in dar[] ***/ if( fsig > 0.0f ){ /* data wasn't fit perfectly */ /* find spikiness for each point in time */ fq = 1.0f / fsig ; for( iv=0 ; iv < nuse ; iv++ ){ ssp[iv] = fq * var[iv] ; /* spikiness s = how many sigma out */ } /* save spikiness in -ssave datset */ if( tset != NULL ){ for( iv=0 ; iv < nuse ; iv++ ){ tar = DSET_ARRAY(tset,iv+ignore) ; snew = ITFAC*fabsf(ssp[iv]) ; /* scale for byte storage */ tar[ii] = BYTEIZE(snew) ; /* cf. mrilib.h */ } } /* process values of |s| > cut1, editing dar[] */ for( iv=0 ; iv < nuse ; iv++ ){ /* loop over time points */ if( !localedit ){ /** classic 'smash' edit **/ if( ssp[iv] > cut1 ){ snew = cut1 + c21*mytanh((ssp[iv]-cut1)*ic21) ; /* edit s down */ dar[iv] = fitar[iv] + snew*fsig ; #pragma omp critical (DESPIKE_counter) { nspike++ ; if( ssp[iv] > cut2 ) nbig++ ; } } else if( ssp[iv] < -cut1 ){ snew = -cut1 + c21*mytanh((ssp[iv]+cut1)*ic21) ; /* edit s up */ dar[iv] = fitar[iv] + snew*fsig ; #pragma omp critical (DESPIKE_counter) { nspike++ ; if( ssp[iv] < -cut2 ) nbig++ ; } } } else { /** local edit: 04 Apr 2007 **/ if( ssp[iv] >= cut2 || ssp[iv] <= -cut2 ){ for( iu=iv+1 ; iu < nuse ; iu++ ) /* find non-spike above */ if( ssp[iu] < cut2 && ssp[iu] > -cut2 ) break ; for( id=iv-1 ; id >= 0 ; id-- ) /* find non-spike below */ if( ssp[id] < cut2 && ssp[id] > -cut2 ) break ; switch( (id>=0) + 2*(iu<nuse) ){ /* compute replacement val */ case 3: val = 0.5*(dar[iu]+dar[id]); break; /* iu and id OK */ case 2: val = dar[iu] ; break; /* only iu OK */ case 1: val = dar[id] ; break; /* only id OK */ default: val = fitar[iv] ; break; /* shouldn't be */ } dar[iv] = val ; #pragma omp critical (DESPIKE_counter) { nspike++ ; nbig++ ; } } } } /* end of loop over time points */ #pragma omp atomic nproc += nuse ; /* number data points processed */ } /* end of processing time series when fsig is positive */ /* put dar[] time series (possibly edited above) into output bricks */ switch( datum ){ case MRI_short: for( iv=0 ; iv < nuse ; iv++ ){ sar = DSET_ARRAY(oset,iv+ignore) ; /* output brick */ sar[ii] = (short)dar[iv] ; /* original or mutated data */ } break ; case MRI_float: for( iv=0 ; iv < nuse ; iv++ ){ zar = DSET_ARRAY(oset,iv+ignore) ; /* output brick */ zar[ii] = dar[iv] ; /* original or mutated data */ } break ; } } /* end of loop over voxels #ii */ #pragma omp critical (DESPIKE_malloc) { free(fit); free(ssp); free(fitar); free(var); free(dar); free(far); if( do_NEW ) free(NEW_wks) ; } } /* end OpenMP */ AFNI_OMP_END ; #ifdef USE_OMP if( verb ) fprintf(stderr,"\n") ; #endif ctim = NI_clock_time() - ctim ; INFO_message( "Elapsed despike time = %s" , nice_time_string(ctim) ) ; if( ctim > 345678 && !do_NEW ) ININFO_message("That was SLOW -- try the '-NEW' option for a speedup") ; #ifdef USE_OMP if( verb ) fprintf(stderr,"\n") ; #endif /*--- finish up ---*/ if( do_NEW ) mri_free(NEW_psinv) ; DSET_delete(dset) ; /* delete input dataset */ if( verb ){ if( nproc > 0 ){ pspike = (100.0*nspike)/nproc ; pbig = (100.0*nbig )/nproc ; INFO_message("FINAL: %d data points, %d edits [%.3f%%], %d big edits [%.3f%%]", nproc,nspike,pspike,nbig,pbig ) ; } else { INFO_message("FINAL: no good voxels found to process!!??") ; } } /* write results */ DSET_write(oset) ; if( verb ) WROTE_DSET(oset) ; DSET_delete(oset) ; if( tset != NULL ){ DSET_write(tset) ; if( verb ) WROTE_DSET(tset) ; DSET_delete(tset) ; } exit( THD_get_write_error_count() ) ; }
static int * PLUTO_4D_to_nothing (THD_3dim_dataset * old_dset , int ignore , int detrend , generic_func * user_func, void * user_data ) { byte ** bptr = NULL ; /* one of these will be the array of */ short ** sptr = NULL ; /* pointers to input dataset sub-bricks */ float ** fptr = NULL ; /* (depending on input datum type) */ complex ** cptr = NULL ; float * fxar = NULL ; /* array loaded from input dataset */ float * fac = NULL ; /* array of brick scaling factors */ float * dtr = NULL ; /* will be array of detrending coeff */ float val , d0fac , d1fac , x0,x1; double tzero=0.0 , tdelta , ts_mean , ts_slope ; int ii , old_datum , nuse , use_fac , iz,izold, nxy,nvox ; static int retval; register int kk ; /*----------------------------------------------------------*/ /*----- Check inputs to see if they are reasonable-ish -----*/ if( ! ISVALID_3DIM_DATASET(old_dset) ) return NULL ; if( user_func == NULL ) return NULL ; if( ignore < 0 ) ignore = 0 ; /*--------- set up pointers to each sub-brick in the input dataset ---------*/ old_datum = DSET_BRICK_TYPE( old_dset , 0 ) ; /* get old dataset datum */ nuse = DSET_NUM_TIMES(old_dset) - ignore ; /* # of points on time axis */ if( nuse < 2 ) return NULL ; DSET_load( old_dset ) ; /* must be in memory before we get pointers to it */ kk = THD_count_databricks( old_dset->dblk ) ; /* check if it was */ if( kk < DSET_NVALS(old_dset) ){ /* loaded correctly */ DSET_unload( old_dset ) ; return NULL ; } switch( old_datum ){ /* pointer type depends on input datum type */ default: /** don't know what to do **/ DSET_unload( old_dset ) ; return NULL ; /** create array of pointers into old dataset sub-bricks **/ /*--------- input is bytes ----------*/ /* voxel #i at time #k is bptr[k][i] */ /* for i=0..nvox-1 and k=0..nuse-1. */ case MRI_byte: bptr = (byte **) malloc( sizeof(byte *) * nuse ) ; if( bptr == NULL ) return NULL ; for( kk=0 ; kk < nuse ; kk++ ) bptr[kk] = (byte *) DSET_ARRAY(old_dset,kk+ignore) ; break ; /*--------- input is shorts ---------*/ /* voxel #i at time #k is sptr[k][i] */ /* for i=0..nvox-1 and k=0..nuse-1. */ case MRI_short: sptr = (short **) malloc( sizeof(short *) * nuse ) ; if( sptr == NULL ) return NULL ; for( kk=0 ; kk < nuse ; kk++ ) sptr[kk] = (short *) DSET_ARRAY(old_dset,kk+ignore) ; break ; /*--------- input is floats ---------*/ /* voxel #i at time #k is fptr[k][i] */ /* for i=0..nvox-1 and k=0..nuse-1. */ case MRI_float: fptr = (float **) malloc( sizeof(float *) * nuse ) ; if( fptr == NULL ) return NULL ; for( kk=0 ; kk < nuse ; kk++ ) fptr[kk] = (float *) DSET_ARRAY(old_dset,kk+ignore) ; break ; /*--------- input is complex ---------*/ /* voxel #i at time #k is cptr[k][i] */ /* for i=0..nvox-1 and k=0..nuse-1. */ case MRI_complex: cptr = (complex **) malloc( sizeof(complex *) * nuse ) ; if( cptr == NULL ) return NULL ; for( kk=0 ; kk < nuse ; kk++ ) cptr[kk] = (complex *) DSET_ARRAY(old_dset,kk+ignore) ; break ; } /* end of switch on input type */ nvox = old_dset->daxes->nxx * old_dset->daxes->nyy * old_dset->daxes->nzz ; /*---- allocate space for 1 voxel timeseries ----*/ fxar = (float *) malloc( sizeof(float) * nuse ) ; /* voxel timeseries */ if( fxar == NULL ){ ZFREE_WORKSPACE ; return NULL ; } /*--- get scaling factors for sub-bricks ---*/ fac = (float *) malloc( sizeof(float) * nuse ) ; /* factors */ if( fac == NULL ){ ZFREE_WORKSPACE ; return NULL ; } use_fac = 0 ; for( kk=0 ; kk < nuse ; kk++ ){ fac[kk] = DSET_BRICK_FACTOR(old_dset,kk+ignore) ; if( fac[kk] != 0.0 ) use_fac++ ; else fac[kk] = 1.0 ; } if( !use_fac ) ZFREEUP(fac) ; /*--- setup for detrending ---*/ dtr = (float *) malloc( sizeof(float) * nuse ) ; if( dtr == NULL ){ ZFREE_WORKSPACE ; return NULL ; } d0fac = 1.0 / nuse ; d1fac = 12.0 / nuse / (nuse*nuse - 1.0) ; for( kk=0 ; kk < nuse ; kk++ ) dtr[kk] = kk - 0.5 * (nuse-1) ; /* linear trend, orthogonal to 1 */ /*----- set up to find time at each voxel -----*/ tdelta = old_dset->taxis->ttdel ; if( DSET_TIMEUNITS(old_dset) == UNITS_MSEC_TYPE ) tdelta *= 0.001 ; if( tdelta == 0.0 ) tdelta = 1.0 ; izold = -666 ; nxy = old_dset->daxes->nxx * old_dset->daxes->nyy ; /*----------------------------------------------------*/ /*----- Setup has ended. Now do some real work. -----*/ /* start notification */ #if 0 user_func( 0.0 , 0.0 , nvox , NULL,0.0,0.0 , user_data ) ; #else { void (*uf)(double,double,int,float *,double,double,void *) = (void (*)(double,double,int,float *,double,double,void *))(user_func) ; uf( 0.0l,0.0l , nvox , NULL , 0.0l,0.0l , user_data ) ; } #endif /***** loop over voxels *****/ for( ii=0 ; ii < nvox ; ii++ ){ /* 1 time series at a time */ /*** load data from input dataset, depending on type ***/ switch( old_datum ){ /*** input = bytes ***/ case MRI_byte: for( kk=0 ; kk < nuse ; kk++ ) fxar[kk] = bptr[kk][ii] ; break ; /*** input = shorts ***/ case MRI_short: for( kk=0 ; kk < nuse ; kk++ ) fxar[kk] = sptr[kk][ii] ; break ; /*** input = floats ***/ case MRI_float: for( kk=0 ; kk < nuse ; kk++ ) fxar[kk] = fptr[kk][ii] ; break ; /*** input = complex (note we use absolute value) ***/ case MRI_complex: for( kk=0 ; kk < nuse ; kk++ ) fxar[kk] = CABS(cptr[kk][ii]) ; break ; } /* end of switch over input type */ /*** scale? ***/ if( use_fac ) for( kk=0 ; kk < nuse ; kk++ ) fxar[kk] *= fac[kk] ; /** compute mean and slope **/ x0 = x1 = 0.0 ; for( kk=0 ; kk < nuse ; kk++ ){ x0 += fxar[kk] ; x1 += fxar[kk] * dtr[kk] ; } x0 *= d0fac ; x1 *= d1fac ; /* factors to remove mean and trend */ ts_mean = x0 ; ts_slope = x1 / tdelta ; /** detrend? **/ if( detrend ) for( kk=0 ; kk < nuse ; kk++ ) fxar[kk] -= (x0 + x1 * dtr[kk]) ; /** compute start time of this timeseries **/ /* The info computed here is not being used in this version*/ iz = ii / nxy ; /* which slice am I in? */ if( iz != izold ){ /* in a new slice? */ tzero = THD_timeof( ignore , old_dset->daxes->zzorg + iz*old_dset->daxes->zzdel , old_dset->taxis ) ; izold = iz ; if( DSET_TIMEUNITS(old_dset) == UNITS_MSEC_TYPE ) tzero *= 0.001 ; } /*** Send data to user function ***/ #if 0 user_func( tzero,tdelta , nuse,fxar,ts_mean,ts_slope , user_data) ; #else { void (*uf)(double,double,int,float *,double,double,void *) = (void (*)(double,double,int,float *,double,double,void *))(user_func) ; uf( tzero,tdelta , nuse,fxar,ts_mean,ts_slope , user_data) ; } #endif } /* end of outer loop over 1 voxels at a time */ DSET_unload( old_dset ) ; /* end notification */ #if 0 user_func( 0.0 , 0.0 , 0 , NULL,0.0,0.0 , user_data ) ; #else { void (*uf)(double,double,int,float *,double,double,void *) = (void (*)(double,double,int,float *,double,double,void *))(user_func) ; uf( 0.0l,0.0l, 0 , NULL,0.0l,0.0l, user_data ) ; } #endif /*-------------- Cleanup and go home ----------------*/ ZFREE_WORKSPACE ; retval = 0; return &retval; /* this value is not used for now .... */ }
int main( int argc , char *argv[] ) { int iarg , nerr=0 , nvals,nvox , nx,ny,nz , ii,jj,kk ; char *prefix="LSSout" , *save1D=NULL , nbuf[256] ; THD_3dim_dataset *inset=NULL , *outset ; MRI_vectim *inset_mrv=NULL ; byte *mask=NULL ; int mask_nx=0,mask_ny=0,mask_nz=0, automask=0, nmask=0 ; NI_element *nelmat=NULL ; char *matname=NULL ; char *cgl ; int Ngoodlist,*goodlist=NULL , nfull , ncmat,ntime ; NI_int_array *giar ; NI_str_array *gsar ; NI_float_array *gfar ; MRI_IMAGE *imX, *imA, *imC, *imS ; float *Xar, *Sar ; MRI_IMARR *imar ; int nS ; float *ss , *oo , *fv , sum ; int nvec , iv ; int nbstim , nst=0 , jst_bot,jst_top ; char *stlab="LSS" ; int nodata=1 ; /*--- help me if you can ---*/ if( argc < 2 || strcasecmp(argv[1],"-HELP") == 0 ) LSS_help() ; /*--- bureaucratic startup ---*/ PRINT_VERSION("3dLSS"); mainENTRY("3dLSS main"); machdep(); AFNI_logger("3dLSS",argc,argv); AUTHOR("RWCox"); (void)COX_clock_time() ; /**------- scan command line --------**/ iarg = 1 ; while( iarg < argc ){ if( strcmp(argv[iarg],"-verb") == 0 ){ verb++ ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-VERB") == 0 ){ verb+=2 ; iarg++ ; continue ; } /**========== -mask ==========**/ if( strcasecmp(argv[iarg],"-mask") == 0 ){ THD_3dim_dataset *mset ; if( ++iarg >= argc ) ERROR_exit("Need argument after '-mask'") ; if( mask != NULL || automask ) ERROR_exit("Can't have two mask inputs") ; mset = THD_open_dataset( argv[iarg] ) ; CHECK_OPEN_ERROR(mset,argv[iarg]) ; DSET_load(mset) ; CHECK_LOAD_ERROR(mset) ; mask_nx = DSET_NX(mset); mask_ny = DSET_NY(mset); mask_nz = DSET_NZ(mset); mask = THD_makemask( mset , 0 , 0.5f, 0.0f ) ; DSET_delete(mset) ; if( mask == NULL ) ERROR_exit("Can't make mask from dataset '%.33s'",argv[iarg]) ; nmask = THD_countmask( mask_nx*mask_ny*mask_nz , mask ) ; if( verb || nmask < 1 ) INFO_message("Number of voxels in mask = %d",nmask) ; if( nmask < 1 ) ERROR_exit("Mask is too small to process") ; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-automask") == 0 ){ if( mask != NULL ) ERROR_exit("Can't have -automask and -mask") ; automask = 1 ; iarg++ ; continue ; } /**========== -matrix ==========**/ if( strcasecmp(argv[iarg],"-matrix") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '%s'",argv[iarg-1]) ; if( nelmat != NULL ) ERROR_exit("More than 1 -matrix option!?"); nelmat = NI_read_element_fromfile( argv[iarg] ) ; /* read NIML file */ matname = argv[iarg]; if( nelmat == NULL || nelmat->type != NI_ELEMENT_TYPE ) ERROR_exit("Can't process -matrix file '%s'!?",matname) ; iarg++ ; continue ; } /**========== -nodata ===========**/ if( strcasecmp(argv[iarg],"-nodata") == 0 ){ nodata = 1 ; iarg++ ; continue ; } /**========== -input ==========**/ if( strcasecmp(argv[iarg],"-input") == 0 ){ if( inset != NULL ) ERROR_exit("Can't have two -input options!?") ; if( ++iarg >= argc ) ERROR_exit("Need argument after '%s'",argv[iarg-1]) ; inset = THD_open_dataset( argv[iarg] ) ; CHECK_OPEN_ERROR(inset,argv[iarg]) ; nodata = 0 ; iarg++ ; continue ; } /**========== -prefix =========**/ if( strcasecmp(argv[iarg],"-prefix") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '%s'",argv[iarg-1]) ; prefix = strdup(argv[iarg]) ; if( !THD_filename_ok(prefix) ) ERROR_exit("Illegal string after %s",argv[iarg-1]) ; if( verb && strcmp(prefix,"NULL") == 0 ) INFO_message("-prefix NULL ==> no dataset will be written") ; iarg++ ; continue ; } /**========== -save1D =========**/ if( strcasecmp(argv[iarg],"-save1D") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '%s'",argv[iarg-1]) ; save1D = strdup(argv[iarg]) ; if( !THD_filename_ok(save1D) ) ERROR_exit("Illegal string after %s",argv[iarg-1]) ; iarg++ ; continue ; } /***** Loser User *****/ ERROR_message("Unknown option: %s",argv[iarg]) ; suggest_best_prog_option(argv[0], argv[iarg]); exit(1); } /* end of loop over options */ /*----- check for errors -----*/ if( nelmat == NULL ){ ERROR_message("No -matrix option!?") ; nerr++ ; } if( nerr > 0 ) ERROR_exit("Can't continue without these inputs!") ; if( inset != NULL ){ nvals = DSET_NVALS(inset) ; nvox = DSET_NVOX(inset) ; nx = DSET_NX(inset) ; ny = DSET_NY(inset) ; nz = DSET_NZ(inset) ; } else { automask = nvals = 0 ; nvox = nx = ny = nz = nodata = 1 ; /* nodata */ mask = NULL ; } /*----- masque -----*/ if( mask != NULL ){ /* check -mask option for compatibility */ if( mask_nx != nx || mask_ny != ny || mask_nz != nz ) ERROR_exit("-mask dataset grid doesn't match input dataset :-(") ; } else if( automask ){ /* create a mask from input dataset */ mask = THD_automask( inset ) ; if( mask == NULL ) ERROR_message("Can't create -automask from input dataset :-(") ; nmask = THD_countmask( nvox , mask ) ; if( verb || nmask < 1 ) INFO_message("Number of voxels in automask = %d (out of %d = %.1f%%)", nmask, nvox, (100.0f*nmask)/nvox ) ; if( nmask < 1 ) ERROR_exit("Automask is too small to process") ; } else if( !nodata ) { /* create a 'mask' for all voxels */ if( verb ) INFO_message("No mask ==> computing for all %d voxels",nvox) ; mask = (byte *)malloc(sizeof(byte)*nvox) ; nmask = nvox ; memset( mask , 1 , sizeof(byte)*nvox ) ; } /*----- get matrix info from the NIML element -----*/ if( verb ) INFO_message("extracting matrix info") ; ncmat = nelmat->vec_num ; /* number of columns */ ntime = nelmat->vec_len ; /* number of rows */ if( ntime < ncmat+2 ) ERROR_exit("Matrix has too many columns (%d) for number of rows (%d)",ncmat,ntime) ; /*--- number of rows in the full matrix (without censoring) ---*/ cgl = NI_get_attribute( nelmat , "NRowFull" ) ; if( cgl == NULL ) ERROR_exit("Matrix is missing 'NRowFull' attribute!") ; nfull = (int)strtod(cgl,NULL) ; if( nodata ){ nvals = nfull ; } else if( nvals != nfull ){ ERROR_exit("-input dataset has %d time points, but matrix indicates %d", nvals , nfull ) ; } /*--- the goodlist = mapping from matrix row index to time index (which allows for possible time point censoring) ---*/ cgl = NI_get_attribute( nelmat , "GoodList" ) ; if( cgl == NULL ) ERROR_exit("Matrix is missing 'GoodList' attribute!") ; giar = NI_decode_int_list( cgl , ";," ) ; if( giar == NULL || giar->num < ntime ) ERROR_exit("Matrix 'GoodList' badly formatted?!") ; Ngoodlist = giar->num ; goodlist = giar->ar ; if( Ngoodlist != ntime ) ERROR_exit("Matrix 'GoodList' incorrect length?!") ; else if( verb > 1 && Ngoodlist < nfull ) ININFO_message("censoring reduces time series length from %d to %d",nfull,Ngoodlist) ; /*--- extract the matrix from the NIML element ---*/ imX = mri_new( ntime , ncmat , MRI_float ) ; Xar = MRI_FLOAT_PTR(imX) ; if( nelmat->vec_typ[0] == NI_FLOAT ){ /* from 3dDeconvolve_f */ float *cd ; for( jj=0 ; jj < ncmat ; jj++ ){ cd = (float *)nelmat->vec[jj] ; for( ii=0 ; ii < ntime ; ii++ ) Xar[ii+jj*ntime] = cd[ii] ; } } else if( nelmat->vec_typ[0] == NI_DOUBLE ){ /* from 3dDeconvolve */ double *cd ; for( jj=0 ; jj < ncmat ; jj++ ){ cd = (double *)nelmat->vec[jj] ; for( ii=0 ; ii < ntime ; ii++ ) Xar[ii+jj*ntime] = cd[ii] ; } } else { ERROR_exit("Matrix file stored with illegal data type!?") ; } /*--- find the stim_times_IM option ---*/ cgl = NI_get_attribute( nelmat , "BasisNstim") ; if( cgl == NULL ) ERROR_exit("Matrix doesn't have 'BasisNstim' attribute!") ; nbstim = (int)strtod(cgl,NULL) ; if( nbstim <= 0 ) ERROR_exit("Matrix 'BasisNstim' attribute is %d",nbstim) ; for( jj=1 ; jj <= nbstim ; jj++ ){ sprintf(nbuf,"BasisOption_%06d",jj) ; cgl = NI_get_attribute( nelmat , nbuf ) ; if( cgl == NULL || strcmp(cgl,"-stim_times_IM") != 0 ) continue ; if( nst > 0 ) ERROR_exit("More than one -stim_times_IM option was found in the matrix") ; nst = jj ; sprintf(nbuf,"BasisColumns_%06d",jj) ; cgl = NI_get_attribute( nelmat , nbuf ) ; if( cgl == NULL ) ERROR_exit("Matrix doesn't have %s attribute!",nbuf) ; jst_bot = jst_top = -1 ; sscanf(cgl,"%d:%d",&jst_bot,&jst_top) ; if( jst_bot < 0 || jst_top < 0 ) ERROR_exit("Can't decode matrix attribute %s",nbuf) ; if( jst_bot == jst_top ) ERROR_exit("Matrix attribute %s shows only 1 column for -stim_time_IM:\n" " -->> 3dLSS is meant to be used when more than one stimulus\n" " time was given, and then it computes the response beta\n" " for each stim time separately. If you have only one\n" " stim time with -stim_times_IM, you can use the output\n" " dataset from 3dDeconvolve (or 3dREMLfit) to get that\n" " single beta directly.\n" , nbuf ) ; if( jst_bot >= jst_top || jst_top >= ncmat ) ERROR_exit("Matrix attribute %s has illegal value: %d:%d (ncmat=%d)",nbuf,jst_bot,jst_top,ncmat) ; sprintf(nbuf,"BasisName_%06d",jj) ; cgl = NI_get_attribute( nelmat , nbuf ) ; if( cgl != NULL ) stlab = strdup(cgl) ; if( verb > 1 ) ININFO_message("-stim_times_IM at stim #%d; cols %d..%d",jj,jst_bot,jst_top) ; } if( nst == 0 ) ERROR_exit("Matrix doesn't have any -stim_times_IM options inside :-(") ; /*--- mangle matrix to segregate IM regressors from the rest ---*/ if( verb ) INFO_message("setting up LSS vectors") ; imar = LSS_mangle_matrix( imX , jst_bot , jst_top ) ; if( imar == NULL ) ERROR_exit("Can't compute LSS 'mangled' matrix :-(") ; /*--- setup for LSS computations ---*/ imA = IMARR_SUBIM(imar,0) ; imC = IMARR_SUBIM(imar,1) ; imS = LSS_setup( imA , imC ) ; DESTROY_IMARR(imar) ; if( imS == NULL ) ERROR_exit("Can't complete LSS setup :-((") ; nS = imS->ny ; Sar = MRI_FLOAT_PTR(imS) ; if( save1D != NULL ){ mri_write_1D( save1D , imS ) ; if( verb ) ININFO_message("saved LSS vectors into file %s",save1D) ; } else if( nodata ){ WARNING_message("-nodata used but -save1D not used ==> you get no output!") ; } if( nodata || strcmp(prefix,"NULL") == 0 ){ INFO_message("3dLSS ends since prefix is 'NULL' or -nodata was used") ; exit(0) ; } /*----- create output dataset -----*/ if( verb ) INFO_message("creating output datset in memory") ; outset = EDIT_empty_copy(inset) ; EDIT_dset_items( outset , ADN_prefix , prefix , ADN_datum_all , MRI_float , ADN_brick_fac , NULL , ADN_nvals , nS , ADN_ntt , nS , ADN_none ) ; tross_Copy_History( inset , outset ) ; tross_Make_History( "3dLSS" , argc,argv , outset ) ; for( kk=0 ; kk < nS ; kk++ ){ EDIT_substitute_brick( outset , kk , MRI_float , NULL ) ; sprintf(nbuf,"%s#%03d",stlab,kk) ; EDIT_BRICK_LABEL( outset , kk , nbuf ) ; } /*----- convert input dataset to vectim -----*/ if( verb ) INFO_message("loading input dataset into memory") ; DSET_load(inset) ; CHECK_LOAD_ERROR(inset) ; inset_mrv = THD_dset_to_vectim( inset , mask , 0 ) ; DSET_unload(inset) ; /*----- compute dot products, store results -----*/ if( verb ) INFO_message("computing away, me buckos!") ; nvec = inset_mrv->nvec ; for( kk=0 ; kk < nS ; kk++ ){ ss = Sar + kk*ntime ; oo = DSET_ARRAY(outset,kk) ; for( iv=0 ; iv < nvec ; iv++ ){ fv = VECTIM_PTR(inset_mrv,iv) ; for( sum=0.0f,ii=0 ; ii < ntime ; ii++ ) sum += ss[ii] * fv[goodlist[ii]] ; oo[inset_mrv->ivec[iv]] = sum ; } } DSET_write(outset) ; WROTE_DSET(outset) ; /*-------- Hasta la vista, baby --------*/ if( verb ) INFO_message("3dLSS finished: total CPU=%.2f Elapsed=%.2f", COX_cpu_time() , COX_clock_time() ) ; exit(0) ; }
/*! Replace a voxel's value by the value's rank in the entire set of input datasets */ int main( int argc , char * argv[] ) { THD_3dim_dataset ** dsets_in = NULL, *dset=NULL; /*input and output datasets*/ int nopt=0, nbriks=0, nsubbriks=0, ib=0, isb=0; byte *cmask=NULL; int *all_uniques=NULL, **uniques=NULL, *final_unq=NULL, *N_uniques=NULL; int N_final_unq=0, iun=0, total_unq=0; INT_HASH_DATUM *rmap=NULL, *hd=NULL; int imax=0, iunq=0, ii=0, id = 0; long int off=0; char *prefix=NULL; char stmp[THD_MAX_PREFIX+1]={""}; FILE *fout=NULL; /*----- Read command line -----*/ if( argc < 2 || strcmp(argv[1],"-help") == 0 ){ Rank_help (); exit(0) ; } mainENTRY("3dRank main"); machdep(); AFNI_logger("3dRank",argc,argv); nopt = 1 ; while( nopt < argc && argv[nopt][0] == '-' ){ if( strcmp(argv[nopt],"-ver") == 0 ){ PRINT_VERSION("3dRank"); AUTHOR("Ziad Saad"); nopt++; continue; } if( strcmp(argv[nopt],"-help") == 0 ){ Rank_help(); exit(0) ; } if( strcmp(argv[nopt],"-prefix") == 0 ){ ++nopt; if (nopt>=argc) { fprintf(stderr,"**ERROR: Need string after -prefix\n"); exit(1); } prefix = argv[nopt] ; ++nopt; continue; } if( strcmp(argv[nopt],"-input") == 0 ){ dsets_in = (THD_3dim_dataset**) calloc(argc-nopt+1, sizeof(THD_3dim_dataset*)); ++nopt; nbriks=0; while (nopt < argc ) { dsets_in[nbriks] = THD_open_dataset( argv[nopt] ); if( !ISVALID_DSET(dsets_in[nbriks]) ){ fprintf(stderr,"**ERROR: can't open dataset %s\n",argv[nopt]) ; exit(1); } ++nopt; ++nbriks; } continue; } ERROR_exit( " Error - unknown option %s", argv[nopt]); } if (nopt < argc) { ERROR_exit( " Error unexplained trailing option: %s\n", argv[nopt]); } if (!nbriks) { ERROR_exit( " Error no volumes entered on command line?"); } /* some checks and inits*/ nsubbriks = 0; for (ib = 0; ib<nbriks; ++ib) { if (!is_integral_dset(dsets_in[ib], 0)) { ERROR_exit("Dset %s is not of an integral data type.", DSET_PREFIX(dsets_in[ib])); } nsubbriks += DSET_NVALS(dsets_in[ib]); } /* Now get unique arrays */ uniques = (int **)calloc(nsubbriks, sizeof(int*)); N_uniques = (int *)calloc(nsubbriks, sizeof(int)); total_unq = 0; iun = 0; for (ib = 0; ib<nbriks; ++ib) { DSET_mallocize(dsets_in[ib]); DSET_load(dsets_in[ib]); for (isb=0; isb<DSET_NVALS(dsets_in[ib]); ++isb) { uniques[iun] = THD_unique_vals(dsets_in[ib], isb, &(N_uniques[iun]), cmask); total_unq += N_uniques[iun]; ++iun; } } /* put all the arrays together and get the unique of the uniques */ all_uniques = (int *)calloc(total_unq, sizeof(int)); off=0; for (iun=0; iun<nsubbriks; ++iun) { memcpy(all_uniques+off, uniques[iun], N_uniques[iun]*sizeof(int)); off += N_uniques[iun]; } /* free intermediate unique arrays */ for (iun=0; iun<nsubbriks; ++iun) { free(uniques[iun]); } free(uniques); uniques=NULL; free(N_uniques); N_uniques=NULL; /* get unique of catenated array */ if (!(final_unq = UniqueInt (all_uniques, total_unq, &N_final_unq, 0 ))) { ERROR_exit( " Failed to get unique list (%d, %d, %d) ", total_unq, N_final_unq, nsubbriks); } free(all_uniques); all_uniques=NULL; if (prefix) { snprintf(stmp, sizeof(char)*THD_MAX_PREFIX, "%s.rankmap.1D", prefix); } else { if (nbriks == 1) { snprintf(stmp, sizeof(char)*THD_MAX_PREFIX, "%s.rankmap.1D", DSET_PREFIX(dsets_in[0])); } else { snprintf(stmp, sizeof(char)*THD_MAX_PREFIX, "%s+.rankmap.1D", DSET_PREFIX(dsets_in[0])); } } if (stmp[0]) { if ((fout = fopen(stmp,"w"))) { fprintf(fout, "#Rank Map (%d unique values)\n", N_final_unq); fprintf(fout, "#Col. 0: Rank\n"); fprintf(fout, "#Col. 1: Input Dset Value\n"); } } /* get the maximum integer in the unique array */ imax = 0; for (iunq=0; iunq<N_final_unq; ++iunq) { if (final_unq[iunq] > imax) imax = final_unq[iunq]; if (fout) fprintf(fout, "%d %d\n", iunq, final_unq[iunq]); hd = (INT_HASH_DATUM*)calloc(1,sizeof(INT_HASH_DATUM)); hd->id = final_unq[iunq]; hd->index = iunq; HASH_ADD_INT(rmap, id, hd); } fclose(fout); fout=NULL; /* now cycle over all dsets and replace their voxel values with rank */ for (ib = 0; ib<nbriks; ++ib) { for (isb=0; isb<DSET_NVALS(dsets_in[ib]); ++isb) { EDIT_BRICK_LABEL( dsets_in[ib],isb, "rank" ) ; EDIT_BRICK_TO_NOSTAT( dsets_in[ib],isb ) ; EDIT_BRICK_FACTOR( dsets_in[ib],isb, 0.0);/* no factors for rank*/ switch (DSET_BRICK_TYPE(dsets_in[ib],isb) ){ default: fprintf(stderr, "** Bad dset type for unique operation.\n" "Only Byte, Short, and float dsets are allowed.\n"); break ; /* this should not happen here, so don't bother returning*/ case MRI_short:{ short *mar = (short *) DSET_ARRAY(dsets_in[ib],isb) ; if (imax > MRI_TYPE_maxval[MRI_short]) { WARNING_message("Maximum rank value of %d is\n" "than maximum value for dset datatype of %d\n", imax, MRI_TYPE_maxval[MRI_short]); } for( ii=0 ; ii < DSET_NVOX(dsets_in[ib]) ; ii++ ) if (!cmask || cmask[ii]) { id = (int)mar[ii]; HASH_FIND_INT(rmap,&id ,hd); if (hd) mar[ii] = (short)(hd->index); else ERROR_exit("** Failed to find key %d in hash table\n",id); } else mar[ii] = 0; } break ; case MRI_byte:{ byte *mar ; if (imax > MRI_TYPE_maxval[MRI_short]) { WARNING_message("Maximum rank value of %d is\n" "than maximum value for dset datatype of %d\n", imax, MRI_TYPE_maxval[MRI_byte]); } mar = (byte *) DSET_ARRAY(dsets_in[ib],isb) ; for( ii=0 ; ii < DSET_NVOX(dsets_in[ib]) ; ii++ ) if (!cmask || cmask[ii]) { id = (int)mar[ii]; HASH_FIND_INT(rmap,&id ,hd); if (hd) mar[ii] = (byte)(hd->index); else ERROR_exit("** Failed to find key %d in hash table\n",id); } else mar[ii] = 0; } break ; case MRI_float:{ float *mar = (float *) DSET_ARRAY(dsets_in[ib],isb) ; for( ii=0 ; ii < DSET_NVOX(dsets_in[ib]) ; ii++ ) if (!cmask || cmask[ii]) { id = (int)mar[ii]; /* Assuming float is integral valued */ HASH_FIND_INT(rmap,&id ,hd); if (hd) mar[ii] = (float)(hd->index); else ERROR_exit("** Failed to find key %d in hash table\n",id); } else mar[ii] = 0; } break ; } } /* update range, etc. */ THD_load_statistics(dsets_in[ib]); /* Now write the bricks */ if (prefix) { if (nbriks == 1) { snprintf(stmp, sizeof(char)*THD_MAX_PREFIX, "%s", prefix); } else { snprintf(stmp, sizeof(char)*THD_MAX_PREFIX, "r%02d.%s", ib, prefix); } } else { snprintf(stmp, sizeof(char)*THD_MAX_PREFIX, "rank.%s", DSET_PREFIX(dsets_in[ib])); } EDIT_dset_items( dsets_in[ib] , ADN_prefix , stmp , ADN_none ) ; /* change storage mode, this way prefix will determine format of output dset */ dsets_in[ib]->dblk->diskptr->storage_mode = STORAGE_BY_BRICK; tross_Make_History( "3dRank" , argc, argv , dsets_in[ib] ) ; if (DSET_IS_MASTERED(dsets_in[ib])) { /* THD_write_3dim_dataset won't write a mastered dude */ dset = EDIT_full_copy(dsets_in[ib],stmp); } else { dset = dsets_in[ib]; } /* New ID */ ZERO_IDCODE(dset->idcode); dset->idcode = MCW_new_idcode() ; if (!THD_write_3dim_dataset( NULL, stmp, dset,True )) { ERROR_message("Failed to write %s", stmp); exit(1); } else { WROTE_DSET(dsets_in[ib]); if (dset != dsets_in[ib]) DSET_deletepp(dset); DSET_deletepp(dsets_in[ib]); } } /* destroy hash */ while (rmap) { hd = rmap; HASH_DEL(rmap,hd); free(hd); } free(final_unq); final_unq=NULL; exit(0); }
char * MASKAVE_main( PLUGIN_interface * plint ) { MCW_idcode * idc ; THD_3dim_dataset * input_dset , * mask_dset ; int iv , mcount , nvox , ii , sigmait , nvals=0 , doall , ivbot,ivtop ; float mask_bot=666.0 , mask_top=-666.0 ; double sum=0.0 , sigma=0.0 ; float * sumar=NULL , * sigmar=NULL ; char * tag , * str , buf[64] , abuf[32],sbuf[32] ; byte * mmm ; char * cname=NULL ; /* 06 Aug 1998 */ int cdisk=0 ; /* 22 Aug 2000 */ int miv=0 ; /*--------------------------------------------------------------------*/ /*----- Check inputs from AFNI to see if they are reasonable-ish -----*/ if( plint == NULL ) return "*************************\n" "MASKAVE_main: NULL input\n" "*************************" ; /*-- read 1st line --*/ PLUTO_next_option(plint) ; idc = PLUTO_get_idcode(plint) ; input_dset = PLUTO_find_dset(idc) ; if( input_dset == NULL ) return "********************************\n" "MASKAVE_main: bad input dataset\n" "********************************" ; iv = (int) PLUTO_get_number(plint) ; if( iv >= DSET_NVALS(input_dset) ) return "**********************************\n" "MASKAVE_main: bad input sub-brick\n" "**********************************" ; doall = (iv < 0) ; if( doall ){ nvals = DSET_NVALS(input_dset) ; ivbot = 0 ; ivtop = nvals-1 ; } else { ivbot = ivtop = iv ; } DSET_load(input_dset) ; if( DSET_ARRAY(input_dset,ivbot) == NULL ) return "*********************************\n" "MASKAVE_main: can't load dataset\n" "*********************************" ; nvox = DSET_NVOX(input_dset) ; /*-- read 2nd line --*/ PLUTO_next_option(plint) ; idc = PLUTO_get_idcode(plint) ; mask_dset = PLUTO_find_dset(idc) ; if( mask_dset == NULL ) return "*******************************\n" "MASKAVE_main: bad mask dataset\n" "*******************************" ; if( DSET_NVOX(mask_dset) != nvox ) return "*************************************************************\n" "MASKAVE_main: mask input dataset doesn't match source dataset\n" "*************************************************************" ; miv = (int) PLUTO_get_number(plint) ; /* 06 Aug 1998 */ if( miv >= DSET_NVALS(mask_dset) ) return "*****************************************************\n" "MASKAVE_main: mask dataset sub-brick index is too big\n" "*****************************************************" ; DSET_load(mask_dset) ; if( DSET_ARRAY(mask_dset,0) == NULL ) return "**************************************\n" "MASKAVE_main: can't load mask dataset\n" "**************************************" ; /*-- read optional lines --*/ while( (tag=PLUTO_get_optiontag(plint)) != NULL ){ if( strcmp(tag,"Range") == 0 ){ mask_bot = PLUTO_get_number(plint) ; mask_top = PLUTO_get_number(plint) ; continue ; } if( strcmp(tag,"1D Save") == 0 ){ char * yn ; cname = PLUTO_get_string(plint) ; yn = PLUTO_get_string(plint) ; cdisk = (strcmp(yn,yesno_list[0]) == 0) ; continue ; } } /*------------------------------------------------------*/ /*---------- At this point, the inputs are OK ----------*/ /*-- build a byte mask array --*/ mmm = (byte *) malloc( sizeof(byte) * nvox ) ; if( mmm == NULL ) return "*** Can't malloc workspace! ***" ; /* separate code for each input data type */ switch( DSET_BRICK_TYPE(mask_dset,miv) ){ default: free(mmm) ; return "*** Can't use mask dataset -- illegal data type! ***" ; case MRI_short:{ short mbot , mtop ; short * mar = (short *) DSET_ARRAY(mask_dset,miv) ; float mfac = DSET_BRICK_FACTOR(mask_dset,miv) ; if( mfac == 0.0 ) mfac = 1.0 ; if( mask_bot <= mask_top ){ mbot = SHORTIZE(mask_bot/mfac) ; mtop = SHORTIZE(mask_top/mfac) ; } else { mbot = (short) -MRI_TYPE_maxval[MRI_short] ; mtop = (short) MRI_TYPE_maxval[MRI_short] ; } for( mcount=0,ii=0 ; ii < nvox ; ii++ ) if( mar[ii] >= mbot && mar[ii] <= mtop && mar[ii] != 0 ){ mmm[ii] = 1 ; mcount++ ; } else { mmm[ii] = 0 ; } } break ; case MRI_byte:{ byte mbot , mtop ; byte * mar = (byte *) DSET_ARRAY(mask_dset,miv) ; float mfac = DSET_BRICK_FACTOR(mask_dset,miv) ; if( mfac == 0.0 ) mfac = 1.0 ; if( mask_bot <= mask_top ){ mbot = BYTEIZE(mask_bot/mfac) ; mtop = BYTEIZE(mask_top/mfac) ; if( mtop == 0 ){ free(mmm) ; return "*** Illegal mask range for mask dataset of bytes. ***" ; } } else { mbot = 0 ; mtop = (byte) MRI_TYPE_maxval[MRI_short] ; } for( mcount=0,ii=0 ; ii < nvox ; ii++ ) if( mar[ii] >= mbot && mar[ii] <= mtop && mar[ii] != 0 ){ mmm[ii] = 1 ; mcount++ ; } else { mmm[ii] = 0 ; } } break ; case MRI_float:{ float mbot , mtop ; float * mar = (float *) DSET_ARRAY(mask_dset,miv) ; float mfac = DSET_BRICK_FACTOR(mask_dset,miv) ; if( mfac == 0.0 ) mfac = 1.0 ; if( mask_bot <= mask_top ){ mbot = (float) (mask_bot/mfac) ; mtop = (float) (mask_top/mfac) ; } else { mbot = -WAY_BIG ; mtop = WAY_BIG ; } for( mcount=0,ii=0 ; ii < nvox ; ii++ ) if( mar[ii] >= mbot && mar[ii] <= mtop && mar[ii] != 0 ){ mmm[ii] = 1 ; mcount++ ; } else { mmm[ii] = 0 ; } } break ; } if( mcount == 0 ){ free(mmm) ; return "*** No voxels survive the masking operations! ***" ; } sigmait = (mcount > 1) ; /*-- compute statistics --*/ if( doall ){ sumar = (float *) malloc( sizeof(float) * nvals ) ; sigmar = (float *) malloc( sizeof(float) * nvals ) ; } for( iv=ivbot ; iv <= ivtop ; iv++ ){ sum = sigma = 0.0 ; /* 13 Dec 1999 */ switch( DSET_BRICK_TYPE(input_dset,iv) ){ default: free(mmm) ; if( doall ){ free(sumar) ; free(sigmar) ; } return "*** Can't use source dataset -- illegal data type! ***" ; case MRI_short:{ short * bar = (short *) DSET_ARRAY(input_dset,iv) ; float mfac = DSET_BRICK_FACTOR(input_dset,iv) ; if( mfac == 0.0 ) mfac = 1.0 ; for( ii=0 ; ii < nvox ; ii++ ) if( mmm[ii] ) sum += bar[ii] ; sum = sum / mcount ; if( sigmait ){ for( ii=0 ; ii < nvox ; ii++ ) if( mmm[ii] ) sigma += SQR(bar[ii]-sum) ; sigma = mfac * sqrt( sigma/(mcount-1) ) ; } sum = mfac * sum ; } break ; case MRI_byte:{ byte * bar = (byte *) DSET_ARRAY(input_dset,iv) ; float mfac = DSET_BRICK_FACTOR(input_dset,iv) ; if( mfac == 0.0 ) mfac = 1.0 ; for( ii=0 ; ii < nvox ; ii++ ) if( mmm[ii] ) sum += bar[ii] ; sum = sum / mcount ; if( sigmait ){ for( ii=0 ; ii < nvox ; ii++ ) if( mmm[ii] ) sigma += SQR(bar[ii]-sum) ; sigma = mfac * sqrt( sigma/(mcount-1) ) ; } sum = mfac * sum ; } break ; case MRI_float:{ float * bar = (float *) DSET_ARRAY(input_dset,iv) ; float mfac = DSET_BRICK_FACTOR(input_dset,iv) ; if( mfac == 0.0 ) mfac = 1.0 ; for( ii=0 ; ii < nvox ; ii++ ) if( mmm[ii] ) sum += bar[ii] ; sum = sum / mcount ; if( sigmait ){ for( ii=0 ; ii < nvox ; ii++ ) if( mmm[ii] ) sigma += SQR(bar[ii]-sum) ; sigma = mfac * sqrt( sigma/(mcount-1) ) ; } sum = mfac * sum ; } break ; } if( doall ){ sumar[iv] = sum ; sigmar[iv] = sigma ; } } free(mmm) ; /*-- send report --*/ if( doall ){ str = (char *) malloc( 1024 + 64*nvals ) ; sprintf(str," ****** ROI statistics ****** \n" " Source = %s [all sub-bricks] \n" " Mask = %s [%s]" , DSET_FILECODE(input_dset) , DSET_FILECODE(mask_dset) , DSET_BRICK_LABEL(mask_dset,miv) ) ; if( mask_bot <= mask_top ){ sprintf(buf," [range %g .. %g]" , mask_bot , mask_top ) ; strcat(str,buf) ; } strcat(str," \n") ; sprintf(buf," Count = %d voxels\n",mcount) ; strcat(str,buf) ; for( iv=0 ; iv < nvals ; iv++ ){ AV_fval_to_char( sumar[iv] , abuf ) ; AV_fval_to_char( sigmar[iv] , sbuf ) ; sprintf(buf," Average = %9.9s Sigma = %9.9s [%s] \n", abuf,sbuf , DSET_BRICK_LABEL(input_dset,iv) ) ; strcat(str,buf) ; } PLUTO_popup_textwin( plint , str ) ; /* 06 Aug 1998 */ if( cname != NULL && cname[0] != '\0' ){ MRI_IMAGE * qim = mri_new_vol_empty( nvals,1,1 , MRI_float ) ; mri_fix_data_pointer( sumar , qim ) ; PLUTO_register_timeseries( cname , qim ) ; if( cdisk ){ /* 22 Aug 2000 */ if( PLUTO_prefix_ok(cname) ){ char * cn ; if( strstr(cname,".1D") == NULL ){ cn = malloc(strlen(cname)+8) ; strcpy(cn,cname) ; strcat(cn,".1D") ; } else { cn = cname ; } mri_write_1D( cn , qim ) ; if( cn != cname ) free(cn) ; } else { PLUTO_popup_transient(plint," \n" "** Illegal filename **\n" "** in 'To Disk?' !! **\n" ) ; } } mri_fix_data_pointer( NULL , qim ) ; mri_free(qim) ; } free(str) ; free(sumar) ; free(sigmar) ; } else if( mask_bot <= mask_top ){ str = (char *) malloc( 1024 ) ; sprintf( str , " *** ROI Statistics *** \n" " Source = %s [%s] \n" " Mask = %s [%s] [range %g .. %g] \n" " Count = %d voxels \n" " Average = %g \n" " Sigma = %g " , DSET_FILECODE(input_dset) , DSET_BRICK_LABEL(input_dset,ivbot) , DSET_FILECODE(mask_dset) , DSET_BRICK_LABEL(mask_dset,miv) , mask_bot , mask_top , mcount , sum , sigma ) ; PLUTO_popup_message(plint,str) ; free(str) ; } else { str = (char *) malloc( 1024 ) ; sprintf( str , " *** ROI Statistics *** \n" " Source = %s [%s] \n" " Mask = %s [%s] \n" " Count = %d voxels \n" " Average = %g \n" " Sigma = %g " , DSET_FILECODE(input_dset) , DSET_BRICK_LABEL(input_dset,ivbot) , DSET_FILECODE(mask_dset) , DSET_BRICK_LABEL(mask_dset,miv) , mcount , sum , sigma ) ; PLUTO_popup_message(plint,str) ; free(str) ; } return NULL ; }
/*-------------------------------------------------------*/ MRI_IMARR * dset_to_mri(THD_3dim_dataset * dset) /*--------------------------------------------------------*/ { int ii, kk, ntime, datum; int nvox, nx, ny, nz; int use_fac; MRI_IMARR * ims_in; MRI_IMAGE * im, *temp_im; byte ** bptr = NULL ; /* one of these will be the array of */ short ** sptr = NULL ; /* pointers to input dataset sub-bricks */ float ** fptr = NULL ; /* (depending on input datum type) */ float * fac = NULL ; /* array of brick scaling factors */ float * fout; ntime = DSET_NUM_TIMES(dset) ; nx = dset->daxes->nxx; ny = dset->daxes->nyy; nz = dset->daxes->nzz; nvox = dset->daxes->nxx * dset->daxes->nyy * dset->daxes->nzz ; datum = DSET_BRICK_TYPE( dset , 0 ) ; /* get dataset datum type */ switch( datum ){ /* pointer type depends on input datum type */ default: return NULL ; /** create array of pointers into old dataset sub-bricks **/ /*--------- input is bytes ----------*/ /* voxel #i at time #k is bptr[k][i] */ /* for i=0..nvox-1 and k=0..ntime-1. */ case MRI_byte: bptr = (byte **) malloc( sizeof(byte *) * ntime ) ; if( bptr == NULL ) return NULL ; for( kk=0 ; kk < ntime ; kk++ ) bptr[kk] = (byte *) DSET_ARRAY(dset,kk) ; break ; /*--------- input is shorts ---------*/ /* voxel #i at time #k is sptr[k][i] */ /* for i=0..nvox-1 and k=0..ntime-1. */ case MRI_short: sptr = (short **) malloc( sizeof(short *) * ntime ) ; if( sptr == NULL ) return NULL ; for( kk=0 ; kk < ntime; kk++ ) sptr[kk] = (short *) DSET_ARRAY(dset,kk) ; break ; /*--------- input is floats ---------*/ /* voxel #i at time #k is fptr[k][i] */ /* for i=0..nvox-1 and k=0..ntime-1. */ case MRI_float: fptr = (float **) malloc( sizeof(float *) * ntime) ; if( fptr == NULL ) return NULL ; for( kk=0 ; kk < ntime; kk++ ) fptr[kk] = (float *) DSET_ARRAY(dset,kk) ; break ; } /* end of switch on input type */ INIT_IMARR(ims_in) ; for( kk=0 ; kk < ntime ; kk++ ){ im = mri_new_vol_empty( nx , ny , nz , datum ) ; ADDTO_IMARR(ims_in,im) ; } for( kk=0 ; kk < ntime ; kk++ ){ im = IMARR_SUBIMAGE(ims_in,kk) ; switch( datum ){ case MRI_byte: mri_fix_data_pointer( bptr[kk], im ) ; break ; case MRI_short: mri_fix_data_pointer( sptr[kk], im ) ; break ; case MRI_float: mri_fix_data_pointer( fptr[kk], im ) ; break ; } } return(ims_in); }
THD_3dim_dataset * THD_deghoster( THD_3dim_dataset *inset , THD_3dim_dataset *filset, int pe , int fe , int se ) { MRI_IMAGE *medim=NULL , *tim=NULL , *oim=NULL ; float cval, *mar=NULL , *tar=NULL , *oar=NULL ; float *xzero_t=NULL , *thet1_t=NULL , *dparr_t=NULL , t1med,t1bmv; byte *bmask=NULL , *amask=NULL , sm ; int nvox , nx,ny,nz , dp=0,df=0,ds=0 , np=0,nf=0,ns=0,np2,nf2 ; int pp,ff,ss,nfp , ii , ppg , nsm,ism , vv,nv , iim , sskip ; THD_3dim_dataset *outset=NULL ; float iy,iyn ; float_pair mp ; /* create brain mask (bmask) */ medim = THD_median_brick(inset) ; bmask = DEG_automask_image(medim) ; /* brain mask (we hope) */ nx = medim->nx ; ny = medim->ny ; nz = medim->nz ; nvox = medim->nvox ; nv = DSET_NVALS(inset) ; /* estimate noise level from data outside the mask (crudely) */ mar = MRI_FLOAT_PTR(medim) ; cval = THD_cliplevel(medim,CLFRAC) ; for( noise_estimate=0.0f,iim=ii=0 ; ii < nvox ; ii++ ) { if( !bmask[ii] && mar[ii] < cval ) { noise_estimate += mar[ii] ; iim++ ; } } if( iim < 9 ) { FREEUP; /* should not happen */ return NULL; } noise_estimate /= iim ; /* initial estimate of noise level */ if( verb > 1 ) INFO_message("Global crude noise_estimate = %g",noise_estimate) ; /* chop out all sub-threshold voxels (amask) */ amask = (byte *)malloc(sizeof(byte)*nvox) ; /* clipped brain mask */ memcpy(amask,bmask,sizeof(byte)*nvox) ; for( ii=0 ; ii < nvox ; ii++ ) if( amask[ii] && mar[ii] < cval ) amask[ii] = 0 ; /* setting up slice coordinates f,p,s */ if( pe == 1 ) { dp = 1 ; np = nx ; } else if( pe == 2 ) { dp = nx ; np = ny ; } else if( pe == 3 ) { dp = nx*ny ; np = ns ; } if( fe == 1 ) { df = 1 ; nf = nx ; } else if( fe == 2 ) { df = nx ; nf = ny ; } else if( fe == 3 ) { df = nx*ny ; nf = nz ; } if( se == 1 ) { ds = 1 ; ns = nx ; } else if( se == 2 ) { ds = nx ; ns = ny ; } else if( se == 3 ) { ds = nx*ny ; ns = nz ; } #undef IJK #define IJK(f,p,s) ((f)*df+(p)*dp+(s)*ds) nvim = nfp = nf * np ; np2 = np / 2 ; nf2 = nf / 2 ; smask = (byte * )malloc(sizeof(byte) *nfp) ; bvec = (float *)malloc(sizeof(float)*nfp) ; gvec = (float *)malloc(sizeof(float)*nfp) ; xvec = (float *)malloc(sizeof(float)*nfp) ; yvec = (float *)malloc(sizeof(float)*nfp) ; ctvec = (float *)malloc(sizeof(float)*nfp) ; stvec = (float *)malloc(sizeof(float)*nfp) ; bvim = (float *)malloc(sizeof(float)*nvim) ; gvim = (float *)malloc(sizeof(float)*nvim) ; xvim = (float *)malloc(sizeof(float)*nvim) ; yvim = (float *)malloc(sizeof(float)*nvim) ; ctvim = (float *)malloc(sizeof(float)*nvim) ; stvim = (float *)malloc(sizeof(float)*nvim) ; xzero_t = (float *)malloc(sizeof(float)*nv) ; thet1_t = (float *)malloc(sizeof(float)*nv) ; dparr_t = (float *)malloc(sizeof(float)*nv) ; /* copy input to output (will be ghost edited later) */ outset = EDIT_empty_copy(inset) ; for( vv=0 ; vv < nv ; vv++ ) { oim = THD_extract_float_brick(vv,inset) ; oar = MRI_FLOAT_PTR(oim) ; EDIT_BRICK_FACTOR( outset , vv , 0.0f ) ; EDIT_substitute_brick( outset , vv , MRI_float , oar ) ; mri_clear_and_free(oim) ; } /* loop over slices */ for( ss=0 ; ss < ns ; ss++ ) { /* make copy of brain mask in this slice, then edit it down to voxels in the brain whose N/2 point is outside the brain (smask) */ for( iim=nsm=pp=0 ; pp < np ; pp++ ) { if( pp >= np2 ) ppg = pp-np2 ; else ppg = pp+np2 ; for( ff=0 ; ff < nf ; ff++,iim++ ) { smask[iim] = sm = amask[IJK(ff,pp,ss)] && !bmask[IJK(ff,ppg,ss)] ; xvim[iim] = ff-nf2 ; yvim[iim] = pp-np2 ; if( sm ) { xvec[nsm] = xvim[iim]; yvec[nsm] = yvim[iim]; nsm++; } } } if( nsm < nfp/20 ) { /* skip this slice */ if( verb ) INFO_message("deghost: skipping slice #%d -- too few points in smask",ss) ; continue ; } nvec = nsm ; if( verb ) INFO_message("deghost: processing slice #%d",ss) ; /* smask is now the mask of brain voxels whose Nyquist ghost locations are NOT in the brain mask */ /* loop over time points, estimate the ghost correction parameters */ for( vv=0 ; vv < nv ; vv++ ) { tim = THD_extract_float_brick(vv,filset) ; tar = MRI_FLOAT_PTR(tim) ; /* extract the vector of image values in smask, and the vector of image values at the ghost locations */ for( iim=ism=pp=0 ; pp < np ; pp++ ) { if( pp >= np2 ) ppg = pp-np2 ; else ppg = pp+np2 ; for( ff=0 ; ff < nf ; ff++,iim++ ) { bvim[iim] = tar[IJK(ff,pp,ss)] ; gvim[iim] = tar[IJK(ff,ppg,ss)] ; if( smask[iim] ) { bvec[ism] = bvim[iim]; gvec[ism++] = gvim[iim]; } } } /* fit the theta parameters from the smask region and save them */ optimize_theta() ; xzero_t[vv] = theta_par[0] ; thet1_t[vv] = theta_par[1] ; dparr_t[vv] = d_par ; mri_free(tim) ; tim = NULL ; } /* now check the slice parameters for reasonability */ sskip = 0 ; if( nv > 4 ) { orfilt_len = 3 ; orfilt_vector(nv,xzero_t) ; orfilt_vector(nv,thet1_t) ; orfilt_vector(nv,dparr_t) ; qmedmadbmv_float(nv,thet1_t,&t1med,NULL,&t1bmv) ; if( verb ) ININFO_message(" slice #%d -- median(theta1)=%g stdev=%g ratio=%g", ss,t1med,t1bmv,(t1bmv>0.0f)?t1med/t1bmv:0.0f) ; if( t1med == 0.0f || fabsf(t1med) <= 0.111f*t1bmv ) { sskip = 1 ; ININFO_message(" skipping slice #%d -- theta1 too small",ss) ; } } if( sskip ) continue ; /* skip processing this slice */ /* loop over time points, estimate the un-ghosted image */ for( vv=0 ; vv < nv ; vv++ ) { tim = THD_extract_float_brick(vv,inset) ; /* input data for slice */ tar = MRI_FLOAT_PTR(tim) ; oar = DSET_ARRAY(outset,vv) ; /* output data for volume */ /* compute theta at each voxel */ if( thet1_t[vv] == 0.0f ) continue ; /* ghost amplitude is 0 ==> skip this time point */ if( verb > 1 ) ININFO_message(" slice=%d index=%d theta = %g %g %g", ss,vv,xzero_t[vv],thet1_t[vv],dparr_t[vv]) ; theta_par[0] = xzero_t[vv]; theta_par[1] = thet1_t[vv]; d_par = dparr_t[vv]; compute_thvim() ; /* compute output values at each voxel: (a) inside the smask == voxel in brain, N/2 ghost isn't (b) not in the smask but in the bmask == voxel && N/2 ghost are in brain (c) otherwise == voxel is unimportant effluvium */ for( iim=pp=0 ; pp < np ; pp++ ) { if( pp >= np2 ) ppg = pp-np2 ; else ppg = pp+np2 ; for( ff=0 ; ff < nf ; ff++,iim++ ) { iy = tar[IJK(ff,pp,ss)] ; iyn = tar[IJK(ff,ppg,ss)] ; if( smask[iim] ) { oar[IJK(ff,pp,ss)] = find_mhat( iy,iyn , ctvim[iim],stvim[iim] , d_par ) ; oar[IJK(ff,ppg,ss)] = 0.0f ; } else if( bmask[IJK(ff,pp,ss)] && bmask[IJK(ff,ppg,ss)] ) { if( ppg > pp ) { mp = find_mpair( iy,iyn , ctvim[iim],stvim[iim] , d_par ) ; oar[IJK(ff,pp,ss)] = mp.a ; oar[IJK(ff,ppg,ss)] = mp.b ; } } else { /* nada: output is already a copy of input */ } } } } } /* end of loop over slices */ FREEUP ; return outset ; }