/*--------------------------------------------------------------------- 23 Feb 2012: Return the absolute value of the difference between two volumes, divided by the number of voxels and the number of sub-bricks. Voxels that are zero in both sets are not counted. Comparisons are done after conversion of data to double return = -1.0 ERROR = 0.0 Exactly the same -----------------------------------------------------------------------*/ double THD_diff_vol_vals(THD_3dim_dataset *d1, THD_3dim_dataset *d2, int scl) { double dd=0.0, denom=0.0; int i=0, k=0; double *a1=NULL, *a2=NULL; MRI_IMAGE *b1 = NULL , *b2 = NULL; ENTRY("THD_diff_vol_vals"); if (!d1 && !d2) RETURN(dd); if (!d1 || !d2) RETURN(-1.0); if (!EQUIV_GRIDS(d1,d2)) RETURN(-1.0); if (DSET_NVALS(d1) != DSET_NVALS(d2)) RETURN(-1.0); DSET_mallocize(d1) ; DSET_load(d1) ; DSET_mallocize(d2) ; DSET_load(d2) ; dd = 0.0; denom = 0; for (i=0; i<DSET_NVALS(d1); ++i) { b1 = THD_extract_double_brick(i, d1); b2 = THD_extract_double_brick(i, d2); a1 = MRI_DOUBLE_PTR(b1); a2 = MRI_DOUBLE_PTR(b2); for (k=0; k<DSET_NVOX(d1); ++k) { dd += ABS(a1[k]-a2[k]); if (a1[k]!=0.0 || a2[k]!=0.0) ++denom; } mri_clear_data_pointer(b1); mri_free(b1) ; mri_clear_data_pointer(b2); mri_free(b2) ; } if (scl && denom>0.0) dd /= denom; RETURN(dd); }
/* * for each input dataset name * open (check dims, etc.) * dilate (zeropad, make binary, dilate, unpad, apply) * fill list of bytemask datasets * * also, count total volumes */ int process_input_dsets(param_t * params) { THD_3dim_dataset * dset, * dfirst=NULL; int iset, nxyz; ENTRY("process_input_dsets"); if( !params ) ERROR_exit("NULL inputs to PID"); if( params->ndsets <= 0 ) { ERROR_message("process_input_dsets: no input datasets"); RETURN(1); } /* allocate space for dsets array */ params->dsets = (THD_3dim_dataset **)malloc(params->ndsets* sizeof(THD_3dim_dataset*)); if( !params->dsets ) ERROR_exit("failed to allocate dset pointers"); if( params->verb ) INFO_message("processing %d input datasets...", params->ndsets); /* warn user of dilations */ if(params->verb && params->ndsets) { int pad = needed_padding(¶ms->IND); INFO_message("padding all datasets by %d (for dilations)", pad); } /* process the datasets */ nxyz = 0; for( iset=0; iset < params->ndsets; iset++ ) { /* open and verify dataset */ dset = THD_open_dataset(params->inputs[iset]); if( !dset ) ERROR_exit("failed to open mask dataset '%s'", params->inputs[iset]); DSET_load(dset); CHECK_LOAD_ERROR(dset); if( params->verb>1 ) INFO_message("loaded dset %s, with %d volumes", DSET_PREFIX(dset), DSET_NVALS(dset)); if( nxyz == 0 ) { /* make an empty copy of the first dataset */ nxyz = DSET_NVOX(dset); dfirst = EDIT_empty_copy(dset); } /* check for consistency in voxels and grid */ if( DSET_NVOX(dset) != nxyz ) ERROR_exit("nvoxel mis-match"); if( ! EQUIV_GRIDS(dset, dfirst) ) WARNING_message("grid from dset %s does not match that of dset %s", DSET_PREFIX(dset), DSET_PREFIX(dfirst)); /* apply dilations to all volumes, returning bytemask datasets */ params->dsets[iset] = apply_dilations(dset, ¶ms->IND,1,params->verb); if( ! params->dsets[iset] ) RETURN(1); } DSET_delete(dfirst); /* and nuke */ RETURN(0); }
int main( int argc , char *argv[] ) { THD_3dim_dataset *dset ; int aa,ll ; char *cpt ; float val ; if( argc < 2 ){ printf("Usage: 3dSatCheck dataset [...]\n" "\n" "Prints the 'raw' initial transient (saturation) check\n" "value for each dataset on the command line. Round this\n" "number to the nearest integer to get an estimate of\n" "how many non-saturated time points start a dataset.\n" ) ; exit(0) ; } for( aa=1 ; aa < argc ; aa++ ){ dset = THD_open_dataset( argv[aa] ) ; if( !ISVALID_DSET(dset) ) continue ; if( DSET_NVALS(dset) < 9 ) continue ; DSET_load(dset) ; if( !DSET_LOADED(dset) ) continue ; val = THD_saturation_check( dset , NULL , 0,0 ) ; ll = strlen(argv[aa]) ; cpt = (ll <= 50) ? argv[aa] : argv[aa]+(ll-50) ; INFO_message("%-50.50s = %.3f",cpt,val) ; DSET_delete(dset) ; } exit(0) ; }
/*---------------------------------------------------------------------- ** ** Main routine for this plugin (will be called from AFNI). ** **---------------------------------------------------------------------- */ char * HEMISUB_main( PLUGIN_interface * plint ) { THD_3dim_dataset * dset, * new_dset; MCW_idcode * idc; hemi_s hs = { 0 }; char * new_prefix; char * ret_string = NULL; char * tag; if ( plint == NULL ) return "------------------------\n" "HEMISUB_main: NULL input\n" "------------------------\n"; PLUTO_next_option( plint ); idc = PLUTO_get_idcode( plint ); dset = PLUTO_find_dset( idc ); if( dset == NULL ) return "-------------------------------\n" "HEMISUB_main: bad input dataset\n" "-------------------------------"; DSET_load( dset ); PLUTO_next_option( plint ); new_prefix = PLUTO_get_string( plint ); if ( ! PLUTO_prefix_ok( new_prefix ) ) return "------------------------\n" "HEMISUB_main: bad prefix\n" "------------------------\n"; if ( ( new_dset = PLUTO_copy_dset( dset, new_prefix ) ) == NULL ) return "------------------------------------------\n" "HEMISUB_main: failed to copy input dataset\n" "------------------------------------------\n"; tag = PLUTO_get_optiontag( plint ); if ( tag && ! strcmp( tag, "Thresh Type" ) ) { tag = PLUTO_get_string( plint ); if ( tag != NULL ) hs.thresh_type = PLUTO_string_index( tag, NUM_T_OPTS, thresh_opts ); } if ( ret_string = process_data( new_dset, &hs ) ) return ret_string; if ( PLUTO_add_dset( plint, new_dset, DSET_ACTION_MAKE_CURRENT ) ) { THD_delete_3dim_dataset( new_dset, False ); return "---------------------------------------\n" "HEMISUB_main: failed to add new dataset\n" "---------------------------------------\n"; } return NULL; }
/* - moved from 3dhistog.c 18 Dec 2012 [rickr] */ int THD_slow_minmax_dset(THD_3dim_dataset *dset, float *dmin, float *dmax, int iv_bot, int iv_top) { int iv_fim; float fimfac; float vbot , vtop, temp_fbot=1.0, temp_ftop=0.0 ; DSET_load(dset); for( iv_fim=iv_bot ; iv_fim <= iv_top ; iv_fim++ ){ /* minimum and maximum for sub-brick */ vbot = mri_min( DSET_BRICK(dset,iv_fim) ) ; vtop = mri_max( DSET_BRICK(dset,iv_fim) ) ; fimfac = DSET_BRICK_FACTOR(dset,iv_fim) ; if (fimfac == 0.0) fimfac = 1.0; vbot *= fimfac ; vtop *= fimfac ; /* update global min and max */ if ( temp_fbot > temp_ftop ) { /* first time, just copy */ temp_fbot = vbot; temp_ftop = vtop; } else { if( vbot < temp_fbot ) temp_fbot = vbot; if( vtop > temp_ftop ) temp_ftop = vtop; } } *dmin = temp_fbot; *dmax = temp_ftop; return(0); }
int main( int argc , char *argv[] ) { THD_3dim_dataset *dset ; MRI_IMAGE *im ; int iarg=1 ; if( strcmp(argv[1],"-nper") == 0 ){ nper = strtol( argv[2] , NULL , 10 ) ; iarg = 3 ; } for( ; iarg < argc ; iarg++ ){ printf("======= dataset %s nper=%d ========\n",argv[iarg],nper) ; dset = THD_open_dataset(argv[iarg]) ; if( dset == NULL ) continue ; DSET_load(dset) ; im = DSET_BRICK(dset,0) ; im->dx = DSET_DX(dset) ; im->dy = DSET_DY(dset) ; im->dz = DSET_DZ(dset) ; (void) THD_orient_guess( im ) ; printf( "Data Axes Orientation:\n" " first (x) = %s\n" " second (y) = %s\n" " third (z) = %s\n" , ORIENT_typestr[dset->daxes->xxorient] , ORIENT_typestr[dset->daxes->yyorient] , ORIENT_typestr[dset->daxes->zzorient] ) ; DSET_delete(dset) ; } exit(0) ; }
MRI_IMAGE * THD_median_brick( THD_3dim_dataset *dset ) { int nvox , nvals , ii ; MRI_IMAGE *tsim , *medim ; float *medar ; float *tsar ; /* 05 Nov 2001 */ ENTRY("THD_median_brick") ; if( !ISVALID_DSET(dset) ) RETURN(NULL) ; DSET_load(dset) ; if( !DSET_LOADED(dset) ) RETURN(NULL) ; nvals = DSET_NVALS(dset) ; tsim = DSET_BRICK(dset,0) ; if( nvals == 1 ){ medim = mri_scale_to_float( DSET_BRICK_FACTOR(dset,0), tsim ) ; RETURN(medim) ; } medim = mri_new_conforming( tsim , MRI_float ) ; medar = MRI_FLOAT_PTR(medim) ; nvox = DSET_NVOX(dset) ; tsar = (float *) calloc( sizeof(float),nvals+1 ) ; /* 05 Nov 2001 */ for( ii=0 ; ii < nvox ; ii++ ){ THD_extract_array( ii , dset , 0 , tsar ) ; /* 05 Nov 2001 */ medar[ii] = qmed_float( nvals , tsar ) ; } free(tsar) ; RETURN(medim) ; }
MRI_IMARR * THD_medmad_bricks( THD_3dim_dataset *dset ) { int nvox , nvals , ii ; MRI_IMAGE *tsim , *madim, *medim ; float *madar, *medar ; MRI_IMARR *imar ; float *tsar ; ENTRY("THD_medmad_bricks") ; if( !ISVALID_DSET(dset) ) RETURN(NULL) ; nvals = DSET_NVALS(dset) ; if( nvals == 1 ) RETURN(NULL) ; DSET_load(dset) ; if( !DSET_LOADED(dset) ) RETURN(NULL) ; tsim = DSET_BRICK(dset,0) ; madim = mri_new_conforming( tsim , MRI_float ) ; madar = MRI_FLOAT_PTR(madim) ; medim = mri_new_conforming( tsim , MRI_float ) ; medar = MRI_FLOAT_PTR(medim) ; nvox = DSET_NVOX(dset) ; tsar = (float *) calloc( sizeof(float),nvals+1 ) ; for( ii=0 ; ii < nvox ; ii++ ){ THD_extract_array( ii , dset , 0 , tsar ) ; qmedmad_float( nvals , tsar , medar+ii , madar+ii ) ; } free(tsar) ; INIT_IMARR(imar) ; ADDTO_IMARR(imar,medim) ; ADDTO_IMARR(imar,madim) ; RETURN(imar) ; }
MRI_IMAGE * THD_rms_brick( THD_3dim_dataset *dset ) { int nvox , nvals , ii , jj ; MRI_IMAGE *tsim , *medim ; float *medar , sum,fac ; float *tsar ; ENTRY("THD_rms_brick") ; if( !ISVALID_DSET(dset) ) RETURN(NULL) ; DSET_load(dset) ; if( !DSET_LOADED(dset) ) RETURN(NULL) ; nvals = DSET_NVALS(dset) ; fac = 1.0 / nvals ; tsim = DSET_BRICK(dset,0) ; if( nvals == 1 ){ medim = mri_scale_to_float( DSET_BRICK_FACTOR(dset,0), tsim ) ; RETURN(medim) ; } medim = mri_new_conforming( tsim , MRI_float ) ; medar = MRI_FLOAT_PTR(medim) ; nvox = DSET_NVOX(dset) ; tsar = (float *) calloc( sizeof(float),nvals+1 ) ; for( ii=0 ; ii < nvox ; ii++ ){ THD_extract_array( ii , dset , 0 , tsar ) ; for( sum=0.0,jj=0 ; jj < nvals ; jj++ ) sum += tsar[jj]*tsar[jj] ; medar[ii] = sqrtf(fac * sum) ; } free(tsar) ; RETURN(medim) ; }
double ENTROPY_dataset( THD_3dim_dataset *dset ) { if( !ISVALID_DSET(dset) ) return(0.0) ; DSET_load(dset) ; if( !DSET_LOADED(dset) ) return(0.0) ; return ENTROPY_datablock( dset->dblk ) ; }
/* Calculates the average value for each voxel in dset across all timepoints. PRE: dset is a valid 3D+T dataset with at least 1 timepoint; ignore is the number of timepoints to ignore at the beginning of dset; 0 <= ignore < number of timepoints in dset; POST: return value is NULL on error, else, return value is an array of floats with the same dimensions as the subbricks of dset, containing the voxel value averages; Note: The caller is responsible for free()ing the returned block of memory when done. Note2: The complex datatype is not supported, and any such bricks will result in an error (NULL return value). */ double * RIC_CalcVoxelMeans(const THD_3dim_dataset * dset, int ignore) { double * avg; /* The voxel averages to be returned */ float scalefactor; /* Current dset brick scaling factor */ int ival, nvals; /* Current, number of dset timepoints */ int ivox, nvoxs; /* Current, number of dset brick voxels */ /* Quick check of arguments */ if (!ISVALID_3DIM_DATASET(dset) || DSET_NVALS(dset) < 1 || ignore < 0 || ignore >= DSET_NVALS(dset)) { return NULL; } /* Initialize */ DSET_load(dset); nvals = DSET_NVALS(dset); nvoxs = dset->daxes->nxx * dset->daxes->nyy * dset->daxes->nzz; avg = malloc(sizeof(double) * nvoxs); if (avg == NULL) { return NULL; } /* Calculate the voxel averages; treat matrices as 1-D arrays */ /* Zero the voxel sums */ for (ivox = 0; ivox < nvoxs; ivox += 1) { avg[ivox] = 0.0; } /* Sum each voxel across time (and hope there are not too many points) */ for (ival = ignore; ival < nvals; ival += 1) { scalefactor = DSET_BRICK_FACTOR(dset, ival); switch (DSET_BRICK_TYPE(dset, ival)) { case MRI_short: RIC_CALCVOXELMEANS__DO_VOXSUM(short); break; case MRI_byte: RIC_CALCVOXELMEANS__DO_VOXSUM(byte); break; case MRI_float: RIC_CALCVOXELMEANS__DO_VOXSUM(float); break; default: /* Unsupported datatype */ free(avg); return NULL; } } /* Divide by number of timepoints to get average */ nvals -= ignore; /* We do not average over the ignored timepoints */ for (ivox = 0; ivox < nvoxs; ivox += 1) { avg[ivox] /= nvals; } return avg; }
THD_3dim_dataset *Seg_load_dset_eng( char *set_name, char *view ) { static char FuncName[]={"Seg_load_dset_eng"}; THD_3dim_dataset *dset=NULL, *sdset=NULL; int i=0; byte make_cp=0; int verb=0; char sprefix[THD_MAX_PREFIX+10], *stmp=NULL; SUMA_ENTRY; dset = THD_open_dataset( set_name ); if( !ISVALID_DSET(dset) ){ fprintf(stderr,"**ERROR: can't open dataset %s\n",set_name) ; SUMA_RETURN(NULL); } DSET_mallocize(dset) ; DSET_load(dset); for (i=0; i<DSET_NVALS(dset); ++i) { if (DSET_BRICK_TYPE(dset,i) != MRI_short) { if (verb) INFO_message("Sub-brick %d in %s not of type short.\n" "Creating new short copy of dset ", i, DSET_PREFIX(dset)); make_cp=1; break; } } if (make_cp) { if (!SUMA_ShortizeDset(&dset, -1.0)) { SUMA_S_Err("**ERROR: Failed to shortize"); SUMA_RETURN(NULL); } } if (DSET_IS_MASTERED(dset)) { if (verb) INFO_message("Dset is mastered, making copy..."); stmp = SUMA_ModifyName(set_name, "append", ".cp", NULL); sdset = dset; dset = EDIT_full_copy(sdset, stmp); free(stmp); DSET_delete(sdset); sdset = NULL; } if (view) { if (view) { if (!strstr(view,"orig")) EDIT_dset_items(dset,ADN_view_type, VIEW_ORIGINAL_TYPE, ADN_none); else if (!strstr(view,"acpc")) EDIT_dset_items(dset,ADN_view_type, VIEW_ACPCALIGNED_TYPE, ADN_none); else if (!strstr(view,"tlrc")) EDIT_dset_items(dset ,ADN_view_type, VIEW_TALAIRACH_TYPE, ADN_none); else SUMA_S_Errv("View of %s is rubbish", view); } } SUMA_RETURN(dset); }
void get_options ( int argc, /* number of input arguments */ char ** argv /* array of input arguments */ ) { int nopt = 1; /* input option argument counter */ int ival, index; /* integer input */ float fval; /* float input */ char message[MAX_STRING_LENGTH]; /* error message */ /*----- does user request help menu? -----*/ if (argc < 2 || strncmp(argv[1], "-help", 5) == 0) display_help_menu(); /*----- main loop over input options -----*/ while (nopt < argc ) { /*----- -anat filename -----*/ if (strncmp(argv[nopt], "-anat", 5) == 0) { nopt++; if (nopt >= argc) estPDF_error ("need argument after -anat "); anat_filename = malloc (sizeof(char) * MAX_STRING_LENGTH); MTEST (anat_filename); strcpy (anat_filename, argv[nopt]); anat = THD_open_one_dataset (anat_filename); if (!ISVALID_3DIM_DATASET (anat)) { sprintf (message, "Can't open dataset: %s\n", anat_filename); estPDF_error (message); } DSET_load(anat); CHECK_LOAD_ERROR(anat); nopt++; continue; } /*----- unknown command -----*/ sprintf(message,"Unrecognized command line option: %s\n", argv[nopt]); estPDF_error (message); } }
int fill_mask(options_t * opts) { THD_3dim_dataset * mset; int nvox; ENTRY("fill_mask"); if( opts->automask ) { if( opts->verb ) INFO_message("creating automask..."); opts->mask = THD_automask(opts->inset); if( ! opts->mask ) { ERROR_message("failed to apply -automask"); RETURN(1); } RETURN(0); } if( opts->mask_name ) { if( opts->verb ) INFO_message("reading mask dset from %s...", opts->mask_name); mset = THD_open_dataset( opts->mask_name ); if( ! mset ) ERROR_exit("cannot open mask dset '%s'", opts->mask_name); nvox = DSET_NVOX(opts->inset); if( DSET_NVOX(mset) != nvox ) { ERROR_message("mask does not have the same voxel count as input"); RETURN(1); } /* fill mask array and mask_nxyz, remove mask dset */ DSET_load(mset); CHECK_LOAD_ERROR(mset); opts->mask = THD_makemask(mset, 0, 1, 0); DSET_delete(mset); if( ! opts->mask ) { ERROR_message("cannot make mask from '%s'", opts->mask_name); RETURN(1); } if( opts->verb > 1 ) INFO_message("have mask with %d voxels", nvox); } RETURN(0); }
MRI_vectim * THD_dset_to_vectim_byslice( THD_3dim_dataset *dset, byte *mask , int ignore , int kzbot , int kztop ) { byte *mmm ; MRI_vectim *mrv=NULL ; int kk,iv , nvals , nvox , nmask , nxy , nz ; ENTRY("THD_dset_to_vectim_byslice") ; if( !ISVALID_DSET(dset) ) RETURN(NULL) ; DSET_load(dset) ; if( !DSET_LOADED(dset) ) RETURN(NULL) ; nvals = DSET_NVALS(dset) ; if( nvals <= 0 ) RETURN(NULL) ; nvox = DSET_NVOX(dset) ; nxy = DSET_NX(dset) * DSET_NY(dset) ; nz = DSET_NZ(dset) ; if( kzbot < 0 ) kzbot = 0 ; if( kztop >= nz ) kztop = nz-1 ; if( kztop < kzbot ) RETURN(NULL) ; if( kzbot == 0 && kztop == nz-1 ){ mrv = THD_dset_to_vectim( dset , mask, ignore ) ; RETURN(mrv) ; } /* make a mask that includes cutting out un-desirable slices */ { int ibot , itop , ii ; #pragma omp critical (MALLOC) mmm = (byte *)malloc(sizeof(byte)*nvox) ; if( mask == NULL ) AAmemset( mmm , 1 , sizeof(byte)*nvox ) ; else AAmemcpy( mmm , mask , sizeof(byte)*nvox ) ; if( kzbot > 0 ) AAmemset( mmm , 0 , sizeof(byte)*kzbot *nxy ) ; if( kztop < nz-1 ) AAmemset( mmm+(kztop+1)*nxy , 0 , sizeof(byte)*(nz-1-kztop)*nxy ) ; } /* and make the vectim using the standard function */ mrv = THD_dset_to_vectim( dset , mmm , ignore ) ; free(mmm) ; RETURN(mrv) ; }
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 * THD_dset_to_1Dmri( THD_3dim_dataset *dset ) { MRI_IMAGE *im ; float *far ; int nx , ny , ii ; ENTRY("THD_dset_to_1D") ; if( !ISVALID_DSET(dset) ) RETURN(NULL) ; DSET_load(dset) ; if( !DSET_LOADED(dset) ) RETURN(NULL) ; nx = DSET_NVALS(dset) ; ny = DSET_NVOX(dset) ; im = mri_new( nx , ny , MRI_float ) ; far = MRI_FLOAT_PTR(im) ; for( ii=0 ; ii < ny ; ii++ ) THD_extract_array( ii , dset , 0 , far + ii*nx ) ; RETURN(im) ; }
int main( int argc , char *argv[] ) { int vstep=0 , ii,nvox , ntin , ntout , do_one=0 , nup=-1 ; THD_3dim_dataset *inset=NULL , *outset ; char *prefix="Upsam", *dsetname=NULL ; int verb=0 , iarg=1, datum = MRI_float; float *ivec , *ovec , trin , trout, *fac=NULL, *ofac=NULL, top=0.0, maxtop=0.0; /*------- help the pitifully ignorant user? -------*/ if( argc < 2 || strcmp(argv[1],"-help") == 0 ){ printf( "Usage: 3dUpsample [options] n dataset\n" "\n" "* Upsamples a 3D+time dataset, in the time direction,\n" " by a factor of 'n'.\n" "* The value of 'n' must be between 2 and 320 (inclusive).\n" "* The output dataset is in float format by default.\n" "\n" "Options:\n" "--------\n" " -1 or -one = Use linear interpolation. Otherwise,\n" " or -linear 7th order polynomial interpolation is used.\n" "\n" " -prefix pp = Define the prefix name of the output dataset.\n" " [default prefix is 'Upsam']\n" "\n" " -verb = Be eloquently and mellifluosly verbose.\n" "\n" " -n n = An alternate way to specify n\n" " -input dataset = An alternate way to specify dataset\n" "\n" " -datum ddd = Use datatype ddd at output. Choose from\n" " float (default), short, byte.\n" "Example:\n" "--------\n" " 3dUpsample -prefix LongFred 5 Fred+orig\n" "\n" "Nota Bene:\n" "----------\n" "* You should not use this for files that were 3dTcat-ed across\n" " imaging run boundaries, since that will result in interpolating\n" " between non-contiguous time samples!\n" "* If the input has M time points, the output will have n*M time\n" " points. The last n-1 of them will be past the end of the original\n" " time series.\n" "* This program gobbles up memory and diskspace as a function of n.\n" " You can reduce output file size with -datum option.\n" "\n" "--- RW Cox - April 2008\n" ) ; PRINT_COMPILE_DATE ; exit(0) ; } mainENTRY("3dUpsample"); machdep(); PRINT_VERSION("3dUpsample"); AUTHOR("RWCox") ; AFNI_logger("3dUpsample",argc,argv); /*------- read command line args -------*/ datum = MRI_float; iarg = 1 ; while( iarg < argc && argv[iarg][0] == '-' ){ if( strncasecmp(argv[iarg],"-prefix",5) == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '%s'",argv[iarg-1]); prefix = argv[iarg] ; if( !THD_filename_ok(prefix) ) ERROR_exit("Illegal string after -prefix: '%s'",prefix) ; iarg++ ; continue ; } if( strncasecmp(argv[iarg],"-one",4) == 0 || strcmp (argv[iarg],"-1" ) == 0 || strncasecmp(argv[iarg],"-lin",4) == 0 ){ do_one = 1 ; iarg++ ; continue ; } if( strncasecmp(argv[iarg],"-verb",3) == 0 ){ verb = 1 ; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-n") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '%s'",argv[iarg-1]); nup = (int)strtod(argv[iarg],NULL) ; if( nup < 2 || nup > 320 ) ERROR_exit("3dUpsample rate '%d' is outside range 2..320",nup) ; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-input") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '%s'",argv[iarg-1]); dsetname = argv[iarg]; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-datum") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '%s'",argv[iarg-1]); if( strcmp(argv[iarg],"short") == 0 ){ datum = MRI_short ; } else if( strcmp(argv[iarg],"float") == 0 ){ datum = MRI_float ; } else if( strcmp(argv[iarg],"byte") == 0 ){ datum = MRI_byte ; } else { ERROR_message("-datum of type '%s' not supported in 3dUpsample!\n", argv[iarg] ) ; exit(1) ; } iarg++ ; continue ; } ERROR_message("Unknown argument on command line: '%s'",argv[iarg]) ; suggest_best_prog_option(argv[0], argv[iarg]); exit (1); } /*------- check options for completeness and consistency -----*/ if (nup == -1) { if( iarg+1 >= argc ) ERROR_exit("need 'n' and 'dataset' on command line!") ; nup = (int)strtod(argv[iarg++],NULL) ; if( nup < 2 || nup > 320 ) ERROR_exit("3dUpsample rate '%d' is outside range 2..320",nup) ; } if (!dsetname) { if( iarg >= argc ) ERROR_exit("need 'dataset' on command line!") ; dsetname = argv[iarg]; } inset = THD_open_dataset(dsetname) ; if( !ISVALID_DSET(inset) ) ERROR_exit("3dUpsample can't open dataset '%s'", dsetname) ; ntin = DSET_NVALS(inset) ; trin = DSET_TR(inset) ; if( ntin < 2 ) ERROR_exit("dataset '%s' has only 1 value per voxel?!",dsetname) ; nvox = DSET_NVOX(inset) ; if( verb ) INFO_message("loading input dataset into memory") ; DSET_load(inset) ; CHECK_LOAD_ERROR(inset) ; /*------ create output dataset ------*/ ntout = ntin * nup ; trout = trin / nup ; /* scaling factor for output */ fac = NULL; maxtop = 0.0; if (MRI_IS_INT_TYPE(datum)) { fac = (float *)calloc(DSET_NVALS(inset), sizeof(float)); ofac = (float *)calloc(ntout, sizeof(float)); for (ii=0; ii<DSET_NVALS(inset); ++ii) { top = MCW_vol_amax( DSET_NVOX(inset),1,1 , DSET_BRICK_TYPE(inset,ii), DSET_BRICK_ARRAY(inset,ii) ) ; if (DSET_BRICK_FACTOR(inset, ii)) top = top * DSET_BRICK_FACTOR(inset,ii); fac[ii] = (top > MRI_TYPE_maxval[datum]) ? top/MRI_TYPE_maxval[datum] : 0.0 ; if (top > maxtop) maxtop = top; } if (storage_mode_from_filename(prefix) != STORAGE_BY_BRICK) { fac[0] = (maxtop > MRI_TYPE_maxval[datum]) ? maxtop/MRI_TYPE_maxval[datum] : 0.0 ; for (ii=0; ii<ntout; ++ii) ofac[ii] = fac[0]; if (verb) INFO_message("Forcing global scaling, Max = %f, fac = %f\n", maxtop, fac[0]); } else { if (verb) INFO_message("Reusing scaling factors of input dset\n"); upsample_1( nup, DSET_NVALS(inset), fac, ofac); } } free(fac); fac = NULL; outset = EDIT_empty_copy(inset) ; EDIT_dset_items( outset , ADN_nvals , ntout , ADN_ntt , DSET_NUM_TIMES(inset) > 1 ? ntout : 0 , ADN_datum_all , datum , ADN_brick_fac , ofac , ADN_prefix , prefix , ADN_none ) ; tross_Copy_History( inset , outset ) ; tross_Make_History( "3dUpsample" , argc,argv , outset ) ; free(ofac); ofac = NULL; if( outset->taxis != NULL ){ outset->taxis->ttdel /= nup ; outset->taxis->ttdur /= nup ; if( outset->taxis->toff_sl != NULL ){ for( ii=0 ; ii < outset->taxis->nsl ; ii++ ) outset->taxis->toff_sl[ii] /= nup ; } } for( ii=0 ; ii < ntout ; ii++ ){ /* create empty bricks to be filled below */ EDIT_substitute_brick( outset , ii , datum , NULL ) ; } /*------- loop over voxels and process them one at a time ---------*/ if( verb ) INFO_message("Upsampling time series from %d to %d: %s interpolation", ntin , ntout , (do_one) ? "linear" : "heptic" ) ; if( verb && nvox > 499 ) vstep = nvox / 50 ; if( vstep > 0 ) fprintf(stderr,"++ voxel loop: ") ; ivec = (float *)malloc(sizeof(float)*ntin) ; ovec = (float *)malloc(sizeof(float)*ntout) ; for( ii=0 ; ii < nvox ; ii++ ){ if( vstep > 0 && ii%vstep==vstep-1 ) vstep_print() ; THD_extract_array( ii , inset , 0 , ivec ) ; if( do_one ) upsample_1( nup , ntin , ivec , ovec ) ; else upsample_7( nup , ntin , ivec , ovec ) ; THD_insert_series( ii , outset , ntout , MRI_float , ovec , datum==MRI_float ? 1:0 ) ; } /* end of loop over voxels */ if( vstep > 0 ) fprintf(stderr," Done!\n") ; /*----- clean up and go away -----*/ DSET_write(outset) ; if( verb ) WROTE_DSET(outset) ; if( verb ) INFO_message("Total CPU time = %.1f s",COX_cpu_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); }
int main( int argc , char * argv[] ) { THD_3dim_dataset *dset ; int iarg=1 ; char *cc1="x",*cc2="y",*cc3="z" ; float th1=0.0, th2=0.0, th3=0.0 ; float thx,thy,thz ; int axx,ayy,azz ; char *fname="testcox.ppm" , fn[128] ; void * rhand ; int bot=1 , ii , nim=0 ; float omap[128] , bfac ; MRI_IMAGE * im , * brim ; int hbr[256] , nperc,ibot,itop,sum ; byte * bar ; double ctim ; int imode=CREN_TWOSTEP ; int pmode=CREN_SUM_VOX ; if( argc < 2 || strcmp(argv[1],"-help") == 0 ){ printf("Usage: testcox [-rotate a b c] [-mip|-MIP] [-out f] [-bot b] [-nn|-ts|-li] dset\n") ; exit(0) ; } enable_mcw_malloc() ; while( iarg < argc && argv[iarg][0] == '-' ){ if( strcmp(argv[iarg],"-MIP") == 0 ){ pmode = CREN_MIP_VOX ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-mip") == 0 ){ pmode = CREN_MINIP_VOX ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-nn") == 0 ){ imode = CREN_NN ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-ts") == 0 ){ imode = CREN_TWOSTEP ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-li") == 0 ){ imode = CREN_LINEAR ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-bot") == 0 ){ bot = strtod( argv[++iarg] , NULL ) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-rotate") == 0 ){ th1 = (PI/180.0) * strtod( argv[++iarg] , &cc1 ) ; th2 = (PI/180.0) * strtod( argv[++iarg] , &cc2 ) ; th3 = (PI/180.0) * strtod( argv[++iarg] , &cc3 ) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-out") == 0 ){ fname = argv[++iarg] ; iarg++ ; continue ; } fprintf(stderr,"Illegal option: %s\n",argv[iarg]); exit(1); } if( iarg >= argc ){fprintf(stderr,"No dataset?\n"); exit(1); } dset = THD_open_dataset( argv[iarg] ) ; if( dset == NULL ){fprintf(stderr,"Can't open dataset!\n");exit(1);} if( DSET_BRICK_TYPE(dset,0) != MRI_byte ){ fprintf(stderr,"Non-byte dataset input!\n");exit(1); } DSET_mallocize(dset) ; DSET_load(dset) ; if( !DSET_LOADED(dset) ){ fprintf(stderr,"Can't load dataset!\n");exit(1); } rhand = new_CREN_renderer() ; #if 0 THD_rotangle_user_to_dset( dset , th1,*cc1 , th2,*cc2 , th3,*cc3 , &thx,&axx , &thy,&ayy , &thz,&azz ) ; CREN_set_viewpoint( rhand , axx,thx,ayy,thy,azz,thz ) ; #else CREN_set_angles( rhand , th1,th2,th3 ) ; #endif for( ii=0 ; ii < 128 ; ii++ ) omap[ii] = (ii <= bot) ? 0.0 : (ii-bot)/(127.0-bot) ; CREN_set_opamap( rhand , omap , 1.0 ) ; brim = DSET_BRICK(dset,0) ; bar = MRI_BYTE_PTR(brim) ; mri_histobyte( brim , hbr ) ; nperc = 0.02 * brim->nvox ; for( sum=0,ibot=0 ; ibot < 128 && sum < nperc ; ibot++ ) sum += hbr[ibot] ; for( sum=0,itop=255 ; itop > ibot && sum < nperc ; itop-- ) sum += hbr[itop] ; if( ibot >= itop ){ ibot = 64 ; itop = 192 ; } bfac = 127.5 / (itop-ibot) ; for( ii=0 ; ii < brim->nvox ; ii++ ) if( bar[ii] <= ibot ) bar[ii] = 0 ; else if( bar[ii] >= itop ) bar[ii] = 127 ; else bar[ii] = bfac * (bar[ii]-ibot) ; ctim = COX_cpu_time() ; CREN_set_databytes( rhand , brim->nx,brim->ny,brim->nz , bar ) ; CREN_dset_axes( rhand , dset ) ; CREN_set_render_mode( rhand , pmode ) ; CREN_set_interp( rhand , imode ) ; for( th3=0 ; th3 < 360.0 ; th3+=5.0 ){ CREN_set_angles( rhand , th1,th2,(PI/180.0)*th3 ) ; im = CREN_render( rhand, NULL ) ; /* added NULL 2002.08.28 - rickr */ if( im == NULL ){ fprintf(stderr,"renderer fails!\n") ; exit(1) ; } sprintf(fn,"tc%03d.jpg",(int)rint(th3)) ; mri_write_pnm( fn, im ) ; fprintf(stderr,"+++ Output to file %s\n",fn); mri_free(im) ; nim++ ; } ctim = COX_cpu_time() - ctim ; fprintf(stderr,"+++ Rendering CPU time = %g s = %g/im\n",ctim,ctim/nim) ; exit(0) ; }
THD_3dim_dataset * THD_localhistog( int nsar , THD_3dim_dataset **insar , int numval , int *rlist , MCW_cluster *nbhd , int do_prob , int verb ) { THD_3dim_dataset *outset=NULL , *inset ; int nvox=DSET_NVOX(insar[0]) ; int ids, iv, bb, nnpt=nbhd->num_pt ; MRI_IMAGE *bbim ; int btyp ; float **outar , **listar ; ENTRY("THD_localhistog") ; /*---- create output dataset ----*/ outset = EDIT_empty_copy(insar[0]) ; EDIT_dset_items( outset , ADN_nvals , numval , ADN_datum_all , MRI_float , ADN_nsl , 0 , ADN_brick_fac , NULL , ADN_none ) ; outar = (float **)malloc(sizeof(float *)*numval) ; for( bb=0 ; bb < numval ; bb++ ){ EDIT_substitute_brick( outset , bb , MRI_float , NULL ) ; outar[bb] = DSET_BRICK_ARRAY(outset,bb) ; } /*---- make mapping between values and arrays to get those values ----*/ listar = (float **)malloc(sizeof(float *)*TWO16) ; for( bb=0 ; bb < TWO16 ; bb++ ) listar[bb] = outar[0] ; for( bb=1 ; bb < numval ; bb++ ){ listar[ rlist[bb] + TWO15 ] = outar[bb] ; } /*----------- loop over datasets, add in counts for all voxels -----------*/ for( ids=0 ; ids < nsar ; ids++ ){ /* dataset loop */ inset = insar[ids] ; DSET_load(inset) ; for( iv=0 ; iv < DSET_NVALS(inset) ; iv++ ){ /* sub-brick loop */ if( verb ) fprintf(stderr,".") ; bbim = DSET_BRICK(inset,iv) ; btyp = bbim->kind ; if( nnpt == 1 ){ /* only 1 voxel in nbhd */ int qq,ii,jj,kk,ib,nb ; switch( bbim->kind ){ case MRI_short:{ short *sar = MRI_SHORT_PTR(bbim) ; for( qq=0 ; qq < nvox ; qq++ ) listar[sar[qq]+TWO15][qq]++ ; } break ; case MRI_byte:{ byte *bar = MRI_BYTE_PTR(bbim) ; for( qq=0 ; qq < nvox ; qq++ ) listar[bar[qq]+TWO15][qq]++ ; } break ; case MRI_float:{ float *far = MRI_FLOAT_PTR(bbim) ; short ss ; for( qq=0 ; qq < nvox ; qq++ ){ ss = SHORTIZE(far[qq]); listar[ss+TWO15][qq]++; } } break ; } } else { /* multiple voxels in nbhd */ AFNI_OMP_START ; #pragma omp parallel { int qq,ii,jj,kk,ib,nb ; void *nar ; short *sar,ss ; byte *bar ; float *far ; nar = malloc(sizeof(float)*nnpt) ; sar = (short *)nar ; bar = (byte *)nar ; far = (float *)nar ; #pragma omp for for( qq=0 ; qq < nvox ; qq++ ){ /* qq=voxel index */ ii = DSET_index_to_ix(inset,qq) ; jj = DSET_index_to_jy(inset,qq) ; kk = DSET_index_to_kz(inset,qq) ; nb = mri_get_nbhd_array( bbim , NULL , ii,jj,kk , nbhd , nar ) ; if( nb == 0 ) continue ; switch( btyp ){ case MRI_short: for( ib=0 ; ib < nb ; ib++ ) listar[sar[ib]+TWO15][qq]++ ; break ; case MRI_byte: for( ib=0 ; ib < nb ; ib++ ) listar[bar[ib]+TWO15][qq]++ ; break ; case MRI_float: for( ib=0 ; ib < nb ; ib++ ){ ss = SHORTIZE(far[ib]); listar[ss+TWO15][qq]++; } break ; } } /* end of voxel loop */ free(nar) ; } /* end of OpenMP */ AFNI_OMP_END ; } } /* end of sub-brick loop */ DSET_unload(inset) ; } /* end of dataset loop */ if( verb ) fprintf(stderr,"\n") ; free(listar) ; /*---- post-process output ---*/ if( do_prob ){ byte **bbar ; int pp ; if( verb ) INFO_message("Conversion to probabilities") ; AFNI_OMP_START ; #pragma omp parallel { int qq , ib ; float pfac , val ; byte **bbar ; #pragma omp for for( qq=0 ; qq < nvox ; qq++ ){ pfac = 0.0001f ; for( ib=0 ; ib < numval ; ib++ ) pfac += outar[ib][qq] ; pfac = 250.0f / pfac ; for( ib=0 ; ib < numval ; ib++ ){ val = outar[ib][qq]*pfac ; outar[ib][qq] = BYTEIZE(val) ; } } } /* end OpenMP */ AFNI_OMP_END ; bbar = (byte **)malloc(sizeof(byte *)*numval) ; for( bb=0 ; bb < numval ; bb++ ){ bbar[bb] = (byte *)malloc(sizeof(byte)*nvox) ; for( pp=0 ; pp < nvox ; pp++ ) bbar[bb][pp] = (byte)outar[bb][pp] ; EDIT_substitute_brick(outset,bb,MRI_byte,bbar[bb]) ; EDIT_BRICK_FACTOR(outset,bb,0.004f) ; } free(bbar) ; } /* end of do_prob */ free(outar) ; RETURN(outset) ; }
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[] ) { THD_3dim_dataset *inset=NULL , *outset ; THD_3dim_dataset **insar=NULL ; int nsar=0 ; int iarg=1 , ii,kk , ids ; MCW_cluster *nbhd=NULL ; char *prefix="./localhistog" ; int ntype=0 ; float na=0.0f,nb=0.0f,nc=0.0f ; int verb=1 , do_prob=0 ; int nx=0,ny=0,nz=0,nvox=0, rbot,rtop ; char *labfile=NULL ; NI_element *labnel=NULL ; int nlab=0 , *labval=NULL ; char **lablab=NULL ; char buf[THD_MAX_SBLABEL] ; UINT32 *ohist , *mhist=NULL ; char *ohist_name=NULL ; int ohzadd=0 ; int *rlist , numval ; float mincount=0.0f ; int mcc ; int *exlist=NULL, numex=0 ; int do_excNONLAB=0 ; /*---- for the clueless who wish to become clued-in ----*/ if( argc == 1 ){ usage_3dLocalHistog(1); exit(0); } /* Bob's help shortcut */ /*---- official startup ---*/ #if defined(USING_MCW_MALLOC) && !defined(USE_OMP) enable_mcw_malloc() ; #endif PRINT_VERSION("3dLocalHistog"); mainENTRY("3dLocalHistog main"); machdep(); AFNI_logger("3dLocalHistog",argc,argv); if( getpid()%2 ) AUTHOR("Bilbo Baggins"); else AUTHOR("Thorin Oakenshield"); AFNI_SETUP_OMP(0) ; /* 24 Jun 2013 */ /*---- loop over options ----*/ while( iarg < argc && argv[iarg][0] == '-' ){ if( strcmp(argv[iarg],"-help") == 0 || strcmp(argv[iarg],"-h") == 0){ usage_3dLocalHistog(strlen(argv[iarg])>3 ? 2:1); exit(0); } if( strncmp(argv[iarg],"-qu",3) == 0 ){ verb = 0 ; iarg++ ; continue ; } if( strncmp(argv[iarg],"-verb",5) == 0 ){ verb++ ; iarg++ ; continue ; } #ifdef ALLOW_PROB if( strncmp(argv[iarg],"-prob",5) == 0 ){ do_prob = 1 ; iarg++ ; continue ; } #endif if( strcmp(argv[iarg],"-exclude") == 0 ){ int ebot=-6666666,etop=-6666666 , ee ; if( ++iarg >= argc ) ERROR_exit("Need argument after '-exclude'") ; sscanf(argv[iarg],"%d..%d",&ebot,&etop) ; if( ebot >= -TWO15 && ebot <= TWO15 ){ if( etop < -TWO15 || etop > TWO15 || etop < ebot ) etop = ebot ; exlist = (int *)realloc(exlist,sizeof(int)*(etop-ebot+1+numex+1)) ; for( ee=ebot ; ee <= etop ; ee++ ){ if( ee != 0 ) exlist[numex++] = ee ; } } iarg++ ; continue ; } if( strcmp(argv[iarg],"-excNONLAB") == 0 ){ do_excNONLAB = 1 ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-prefix") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '-prefix'") ; prefix = strdup(argv[iarg]) ; if( !THD_filename_ok(prefix) ) ERROR_exit("Bad -prefix!") ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-hsave") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '-hsave'") ; ohist_name = strdup(argv[iarg]) ; if( !THD_filename_ok(ohist_name) ) ERROR_exit("Bad -hsave!") ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-mincount") == 0 ){ char *cpt ; if( ++iarg >= argc ) ERROR_exit("Need argument after '-mincount'") ; mincount = (float)strtod(argv[iarg],&cpt) ; #if 0 if( mincount > 0.0f && mincount < 50.0f && *cpt == '%' ) /* percentage */ mincount = -0.01f*mincount ; #endif 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 ) ; 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 if( strncasecmp(cpt,"TOHD",4) == 0 ){ sscanf( cpt+5 , "%f" , &na ) ; if( na == 0.0f ) ERROR_exit("Can't have a TOHD of radius 0") ; ntype = NTYPE_TOHD ; } else { ERROR_exit("Unknown -nbhd shape: '%s'",cpt) ; } iarg++ ; continue ; } if( strcmp(argv[iarg],"-lab_file") == 0 || strcmp(argv[iarg],"-labfile") == 0 ){ char **labnum ; int nbad=0 ; if( ++iarg >= argc ) ERROR_exit("Need argument after '%s'",argv[iarg-1]) ; if( labfile != NULL ) ERROR_exit("Can't use '%s' twice!",argv[iarg-1]) ; labfile = strdup(argv[iarg]) ; labnel = THD_string_table_read(labfile,0) ; if( labnel == NULL || labnel->vec_num < 2 ) ERROR_exit("Can't read label file '%s'",labfile) ; nlab = labnel->vec_len ; labnum = (char **)labnel->vec[0] ; lablab = (char **)labnel->vec[1] ; labval = (int *)calloc(sizeof(int),nlab) ; for( ii=0 ; ii < nlab ; ii++ ){ if( labnum[ii] != NULL ){ labval[ii] = (int)strtod(labnum[ii],NULL) ; if( labval[ii] < -TWO15 || labval[ii] > TWO15 ){ labval[ii] = 0; nbad++; } } } if( nbad > 0 ) ERROR_message("%d label values are outside the range %d..%d :-(" , nbad , -TWO15 , TWO15 ) ; iarg++ ; continue ; } ERROR_message("** 3dLocalHistog: Illegal option: '%s'",argv[iarg]) ; suggest_best_prog_option(argv[0], argv[iarg]); exit(1) ; } /*--- end of loop over options ---*/ /*---- check for stupid user inputs ----*/ if( iarg >= argc ) ERROR_exit("No datasets on command line?") ; if( ohist_name == NULL && strcmp(prefix,"NULL") == 0 ) ERROR_exit("-prefix NULL is only meaningful if you also use -hsave :-(") ; /*------------ scan input datasets, built overall histogram ------------*/ nsar = argc - iarg ; insar = (THD_3dim_dataset **)malloc(sizeof(THD_3dim_dataset *)*nsar) ; if( verb ) fprintf(stderr,"Scanning %d datasets ",nsar) ; ohist = (UINT32 *)calloc(sizeof(UINT32),TWO16) ; for( ids=iarg ; ids < argc ; ids++ ){ /* dataset loop */ insar[ids-iarg] = inset = THD_open_dataset(argv[ids]) ; CHECK_OPEN_ERROR(inset,argv[ids]) ; if( ids == iarg ){ nx = DSET_NX(inset); ny = DSET_NY(inset); nz = DSET_NZ(inset); nvox = nx*ny*nz; } else if( nx != DSET_NX(inset) || ny != DSET_NY(inset) || nz != DSET_NZ(inset) ){ ERROR_exit("Dataset %s grid doesn't match!",argv[ids]) ; } if( !THD_datum_constant(inset->dblk) ) ERROR_exit("Dataset %s doesn't have a fixed data type! :-(",argv[ids]) ; if( THD_need_brick_factor(inset) ) ERROR_exit("Dataset %s has scale factors! :-(",argv[ids]) ; if( DSET_BRICK_TYPE(inset,0) != MRI_byte && DSET_BRICK_TYPE(inset,0) != MRI_short && DSET_BRICK_TYPE(inset,0) != MRI_float ) ERROR_exit("Dataset %s is not byte- or short-valued! :-(",argv[ids]) ; DSET_load(inset) ; CHECK_LOAD_ERROR(inset) ; for( ii=0 ; ii < DSET_NVALS(inset) ; ii++ ){ /* add to overall histogram */ if( verb ) fprintf(stderr,".") ; switch( DSET_BRICK_TYPE(inset,ii) ){ case MRI_short:{ short *sar = (short *)DSET_BRICK_ARRAY(inset,ii) ; for( kk=0 ; kk < nvox ; kk++ ) ohist[ sar[kk]+TWO15 ]++ ; } break ; case MRI_byte:{ byte *bar = (byte *)DSET_BRICK_ARRAY(inset,ii) ; for( kk=0 ; kk < nvox ; kk++ ) ohist[ bar[kk]+TWO15 ]++ ; } break ; case MRI_float:{ float *far = (float *)DSET_BRICK_ARRAY(inset,ii) ; short ss ; for( kk=0 ; kk < nvox ; kk++ ){ ss = SHORTIZE(far[kk]); ohist[ss+TWO15]++; } } break ; } } /* end of sub-brick loop */ DSET_unload(inset) ; /* will re-load later, as needed */ } /* end of dataset loop */ if( verb ) fprintf(stderr,"\n") ; /*-------------- process overall histogram for fun and profit -------------*/ /* if we didn't actually find 0, put it in the histogram now */ if( ohist[0+TWO15] == 0 ){ ohist[0+TWO15] = 1 ; ohzadd = 1 ; } /* excNONLAB? */ if( nlab > 0 && do_excNONLAB ){ byte *klist = (byte *)calloc(sizeof(byte),TWO16) ; int nee ; for( ii=0 ; ii < nlab ; ii++ ){ if( labval[ii] != 0 ) klist[labval[ii]+TWO15] = 1 ; } for( nee=ii=0 ; ii < TWO16 ; ii++ ){ if( !klist[ii] ) nee++ ; } exlist = (int *)realloc(exlist,sizeof(int)*(numex+nee+1)) ; for( ii=0 ; ii < TWO16 ; ii++ ){ if( ii != TWO15 && !klist[ii] ) exlist[numex++] = ii-TWO15 ; } free(klist) ; } /* make a copy of ohist and edit it for mincount, etc */ mhist = (UINT32 *)malloc(sizeof(UINT32)*TWO16) ; memcpy(mhist,ohist,sizeof(UINT32)*TWO16) ; mcc = (mincount < 0.0f) ? (int)(-mincount*nvox) : (int)mincount ; if( mcc > 1 ){ for( ids=ii=0 ; ii < TWO16 ; ii++ ){ if( ii != TWO15 && mhist[ii] > 0 && mhist[ii] < mcc ){ mhist[ii] = 0; ids++; } } if( ids > 0 && verb ) INFO_message("Edited out %d values with overall histogram counts less than %d",ids,mcc) ; } if( numex > 0 ){ int ee ; for( ids=0,ii=0 ; ii < numex ; ii++ ){ ee = exlist[ii] ; if( mhist[ee+TWO15] > 0 ){ mhist[ee+TWO15] = 0; ids++; } } free(exlist) ; if( ids > 0 && verb ) INFO_message("Edited out %d values from the exclude list",ids) ; } /* count number of values with nonzero (edited) counts */ numval = 0 ; for( ii=0 ; ii < TWO16 ; ii++ ) if( mhist[ii] != 0 ) numval++ ; if( numval == 0 ) ERROR_exit("Nothing found! WTF?") ; /* should not happen */ /* make list of all values with nonzero (edited) count */ rlist = (int *)malloc(sizeof(int)*numval) ; if( verb > 1 ) fprintf(stderr,"++ Include list:") ; for( ii=kk=0 ; ii < TWO16 ; ii++ ){ if( mhist[ii] != 0 ){ rlist[kk++] = ii-TWO15 ; if( verb > 1 ) fprintf(stderr," %d[%u]",ii-TWO15,mhist[ii]) ; } } if( verb > 1 ) fprintf(stderr,"\n") ; rbot = rlist[0] ; rtop = rlist[numval-1] ; /* smallest and largest values found */ if( rbot == rtop ) ERROR_exit("Only one value (%d) found in all inputs!",rbot) ; /* if 0 isn't first in rlist, then put it in first place and move negative values up by one spot */ if( rbot < 0 ){ for( kk=0 ; kk < numval && rlist[kk] != 0 ; kk++ ) ; /*nada*/ if( kk < numval ){ /* should always be true */ for( ii=kk-1 ; ii >= 0 ; ii-- ) rlist[ii+1] = rlist[ii] ; rlist[0] = 0 ; } } if( verb ) INFO_message("Value range = %d..%d (%d distinct values)",rbot,rtop,numval ); /* save overall histogram? */ if( ohist_name != NULL ){ FILE *fp = fopen(ohist_name,"w") ; int nl=0 ; if( fp == NULL ) ERROR_exit("Can't open -hsave '%s' for output!",ohist_name) ; if( ohzadd ) ohist[0+TWO15] = 0 ; for( ii=0 ; ii < TWO16 ; ii++ ){ if( ohist[ii] != 0 ){ fprintf(fp,"%6d %u\n",ii-TWO15,ohist[ii]); nl++; } } fclose(fp) ; if( verb ) INFO_message("Wrote %d lines to -hsave file %s",nl,ohist_name) ; } free(ohist) ; free(mhist) ; mhist = ohist = NULL ; /* done with this */ if( strcmp(prefix,"NULL") == 0 ) exit(0) ; /* special case */ /*----------- build the neighborhood mask -----------*/ if( ntype <= 0 ){ /* default neighborhood */ ntype = NTYPE_SPHERE ; na = 0.0f ; if( verb ) INFO_message("Using default neighborhood = self") ; } switch( ntype ){ default: ERROR_exit("WTF? ntype=%d",ntype) ; /* should not happen */ case NTYPE_SPHERE:{ float dx , dy , dz ; if( na < 0.0f ){ dx = dy = dz = 1.0f ; na = -na ; } else { dx = fabsf(DSET_DX(insar[0])) ; dy = fabsf(DSET_DY(insar[0])) ; dz = fabsf(DSET_DZ(insar[0])) ; } nbhd = MCW_spheremask( dx,dy,dz , na ) ; } break ; case NTYPE_RECT:{ float dx , dy , dz ; if( na < 0.0f ){ dx = 1.0f; na = -na; } else dx = fabsf(DSET_DX(insar[0])); if( nb < 0.0f ){ dy = 1.0f; nb = -nb; } else dy = fabsf(DSET_DY(insar[0])); if( nc < 0.0f ){ dz = 1.0f; nc = -nc; } else dz = fabsf(DSET_DZ(insar[0])); nbhd = MCW_rectmask( dx,dy,dz , na,nb,nc ) ; } break ; case NTYPE_RHDD:{ float dx , dy , dz ; if( na < 0.0f ){ dx = dy = dz = 1.0f ; na = -na ; } else { dx = fabsf(DSET_DX(insar[0])) ; dy = fabsf(DSET_DY(insar[0])) ; dz = fabsf(DSET_DZ(insar[0])) ; } nbhd = MCW_rhddmask( dx,dy,dz , na ) ; } break ; case NTYPE_TOHD:{ float dx , dy , dz ; if( na < 0.0f ){ dx = dy = dz = 1.0f ; na = -na ; } else { dx = fabsf(DSET_DX(insar[0])) ; dy = fabsf(DSET_DY(insar[0])) ; dz = fabsf(DSET_DZ(insar[0])) ; } nbhd = MCW_tohdmask( dx,dy,dz , na ) ; } break ; } if( verb ) INFO_message("Neighborhood comprises %d voxels",nbhd->num_pt) ; /*------- actually do some work for a change (is it lunchtime yet?) -------*/ if( verb ) fprintf(stderr,"Voxel-wise histograms ") ; outset = THD_localhistog( nsar,insar , numval,rlist , nbhd , do_prob,verb ) ; if( outset == NULL ) ERROR_exit("Function THD_localhistog() fails?!") ; /*---- save resulting dataset ----*/ EDIT_dset_items( outset , ADN_prefix,prefix , ADN_none ) ; tross_Copy_History( insar[0] , outset ) ; tross_Make_History( "3dLocalHistog" , argc,argv , outset ) ; /* but first attach labels to sub-bricks */ EDIT_BRICK_LABEL(outset,0,"0:Other") ; for( kk=1 ; kk < numval ; kk++ ){ sprintf(buf,"%d:",rlist[kk]) ; for( ii=0 ; ii < nlab ; ii++ ){ if( labval[ii] == rlist[kk] && lablab[ii] != NULL ){ ids = strlen(buf) ; MCW_strncpy(buf+ids,lablab[ii],THD_MAX_SBLABEL-ids) ; break ; } } EDIT_BRICK_LABEL(outset,kk,buf) ; } DSET_write( outset ) ; if( verb ) WROTE_DSET( outset ) ; exit(0) ; }
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 do_norm=0 , qdet=2 , have_freq=0 , do_automask=0 ; float dt=0.0f , fbot=0.0f,ftop=999999.9f , blur=0.0f ; MRI_IMARR *ortar=NULL ; MRI_IMAGE *ortim=NULL ; THD_3dim_dataset **ortset=NULL ; int nortset=0 ; THD_3dim_dataset *inset=NULL , *outset=NULL; char *prefix="RSFC" ; byte *mask=NULL ; int mask_nx=0,mask_ny=0,mask_nz=0,nmask , verb=1 , nx,ny,nz,nvox , nfft=0 , kk ; float **vec , **ort=NULL ; int nort=0 , vv , nopt , ntime ; MRI_vectim *mrv ; float pvrad=0.0f ; int nosat=0 ; int do_despike=0 ; // @@ non-BP variables float fbotALL=0.0f, ftopALL=999999.9f; // do full range version int NumDen = 0; // switch for doing numerator or denom THD_3dim_dataset *outsetALL=NULL ; int m, mm; float delf; // harmonics int ind_low,ind_high,N_ny, ctr; float sqnt,nt_fac; gsl_fft_real_wavetable *real1, *real2; // GSL stuff gsl_fft_real_workspace *work; double *series1, *series2; double *xx1,*xx2; float numer,denom,val; float *alff=NULL,*malff=NULL,*falff=NULL, *rsfa=NULL,*mrsfa=NULL,*frsfa=NULL; // values float meanALFF=0.0f,meanRSFA=0.0f; // will be for mean in brain region THD_3dim_dataset *outsetALFF=NULL; THD_3dim_dataset *outsetmALFF=NULL; THD_3dim_dataset *outsetfALFF=NULL; THD_3dim_dataset *outsetRSFA=NULL; THD_3dim_dataset *outsetmRSFA=NULL; THD_3dim_dataset *outsetfRSFA=NULL; char out_lff[300]; char out_alff[300]; char out_malff[300]; char out_falff[300]; char out_rsfa[300]; char out_mrsfa[300]; char out_frsfa[300]; char out_unBP[300]; int SERIES_OUT = 1; int UNBP_OUT = 0; int DO_RSFA = 1; int BP_LAST = 0; // option for only doing filter to LFFs at very end of proc float de_rsfa=0.0f,nu_rsfa=0.0f; double pow1=0.0,pow2=0.0; /*-- help? --*/ if( argc < 2 || strcmp(argv[1],"-help") == 0 ){ printf( "\n Program to calculate common resting state functional connectivity (RSFC)\n" " parameters (ALFF, mALFF, fALFF, RSFA, etc.) for resting state time\n" " series. This program is **heavily** based on the existing\n" " 3dBandPass by RW Cox, with the amendments to calculate RSFC\n" " parameters written by PA Taylor (July, 2012).\n" " This program is part of FATCAT (Taylor & Saad, 2013) in AFNI. Importantly,\n" " its functionality can be included in the `afni_proc.py' processing-script \n" " generator; see that program's help file for an example including RSFC\n" " and spectral parameter calculation via the `-regress_RSFC' option.\n" "\n" "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n" "\n" " All options of 3dBandPass may be used here (with a couple other\n" " parameter options, as well): essentially, the motivation of this\n" " program is to produce ALFF, etc. values of the actual RSFC time\n" " series that you calculate. Therefore, all the 3dBandPass processing\n" " you normally do en route to making your final `resting state time\n" " series' is done here to generate your LFFs, from which the\n" " amplitudes in the LFF band are calculated at the end. In order to\n" " calculate fALFF, the same initial time series are put through the\n" " same processing steps which you have chosen but *without* the\n" " bandpass part; the spectrum of this second time series is used to\n" " calculate the fALFF denominator.\n" " \n" " For more information about each RSFC parameter, see, e.g.: \n" " ALFF/mALFF -- Zang et al. (2007),\n" " fALFF -- Zou et al. (2008),\n" " RSFA -- Kannurpatti & Biswal (2008).\n" "\n" "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n" "\n" " + USAGE: 3dRSFC [options] fbot ftop dataset\n" "\n" "* One function of this program is to prepare datasets for input\n" " to 3dSetupGroupInCorr. Other uses are left to your imagination.\n" "\n" "* 'dataset' is a 3D+time sequence of volumes\n" " ++ This must be a single imaging run -- that is, no discontinuities\n" " in time from 3dTcat-ing multiple datasets together.\n" "\n" "* fbot = lowest frequency in the passband, in Hz\n" " ++ fbot can be 0 if you want to do a lowpass filter only;\n" " HOWEVER, the mean and Nyquist freq are always removed.\n" "\n" "* ftop = highest frequency in the passband (must be > fbot)\n" " ++ if ftop > Nyquist freq, then it's a highpass filter only.\n" "\n" "* Set fbot=0 and ftop=99999 to do an 'allpass' filter.\n" " ++ Except for removal of the 0 and Nyquist frequencies, that is.\n" "\n" "* You cannot construct a 'notch' filter with this program!\n" " ++ You could use 3dRSFC followed by 3dcalc to get the same effect.\n" " ++ If you are understand what you are doing, that is.\n" " ++ Of course, that is the AFNI way -- if you don't want to\n" " understand what you are doing, use Some other PrograM, and\n" " you can still get Fine StatisticaL maps.\n" "\n" "* 3dRSFC will fail if fbot and ftop are too close for comfort.\n" " ++ Which means closer than one frequency grid step df,\n" " where df = 1 / (nfft * dt) [of course]\n" "\n" "* The actual FFT length used will be printed, and may be larger\n" " than the input time series length for the sake of efficiency.\n" " ++ The program will use a power-of-2, possibly multiplied by\n" " a power of 3 and/or 5 (up to and including the 3rd power of\n" " each of these: 3, 9, 27, and 5, 25, 125).\n" "\n" "* Note that the results of combining 3dDetrend and 3dRSFC will\n" " depend on the order in which you run these programs. That's why\n" " 3dRSFC has the '-ort' and '-dsort' options, so that the\n" " time series filtering can be done properly, in one place.\n" "\n" "* The output dataset is stored in float format.\n" "\n" "* The order of processing steps is the following (most are optional), and\n" " for the LFFs, the bandpass is done between the specified fbot and ftop,\n" " while for the `whole spectrum' (i.e., fALFF denominator) the bandpass is:\n" " done only to exclude the time series mean and the Nyquist frequency:\n" " (0) Check time series for initial transients [does not alter data]\n" " (1) Despiking of each time series\n" " (2) Removal of a constant+linear+quadratic trend in each time series\n" " (3) Bandpass of data time series\n" " (4) Bandpass of -ort time series, then detrending of data\n" " with respect to the -ort time series\n" " (5) Bandpass and de-orting of the -dsort dataset,\n" " then detrending of the data with respect to -dsort\n" " (6) Blurring inside the mask [might be slow]\n" " (7) Local PV calculation [WILL be slow!]\n" " (8) L2 normalization [will be fast.]\n" " (9) Calculate spectrum and amplitudes, for RSFC parameters.\n" "\n" "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n" "--------\n" "OPTIONS:\n" "--------\n" " -despike = Despike each time series before other processing.\n" " ++ Hopefully, you don't actually need to do this,\n" " which is why it is optional.\n" " -ort f.1D = Also orthogonalize input to columns in f.1D\n" " ++ Multiple '-ort' options are allowed.\n" " -dsort fset = Orthogonalize each voxel to the corresponding\n" " voxel time series in dataset 'fset', which must\n" " have the same spatial and temporal grid structure\n" " as the main input dataset.\n" " ++ At present, only one '-dsort' option is allowed.\n" " -nodetrend = Skip the quadratic detrending of the input that\n" " occurs before the FFT-based bandpassing.\n" " ++ You would only want to do this if the dataset\n" " had been detrended already in some other program.\n" " -dt dd = set time step to 'dd' sec [default=from dataset header]\n" " -nfft N = set the FFT length to 'N' [must be a legal value]\n" " -norm = Make all output time series have L2 norm = 1\n" " ++ i.e., sum of squares = 1\n" " -mask mset = Mask dataset\n" " -automask = Create a mask from the input dataset\n" " -blur fff = Blur (inside the mask only) with a filter\n" " width (FWHM) of 'fff' millimeters.\n" " -localPV rrr = Replace each vector by the local Principal Vector\n" " (AKA first singular vector) from a neighborhood\n" " of radius 'rrr' millimiters.\n" " ++ Note that the PV time series is L2 normalized.\n" " ++ This option is mostly for Bob Cox to have fun with.\n" "\n" " -input dataset = Alternative way to specify input dataset.\n" " -band fbot ftop = Alternative way to specify passband frequencies.\n" "\n" " -prefix ppp = Set prefix name of output dataset. Name of filtered time\n" " series would be, e.g., ppp_LFF+orig.*, and the parameter\n" " outputs are named with obvious suffices.\n" " -quiet = Turn off the fun and informative messages. (Why?)\n" " -no_rs_out = Don't output processed time series-- just output\n" " parameters (not recommended, since the point of\n" " calculating RSFC params here is to have them be quite\n" " related to the time series themselves which are used for\n" " further analysis)." " -un_bp_out = Output the un-bandpassed series as well (default is not \n" " to). Name would be, e.g., ppp_unBP+orig.* .\n" " with suffix `_unBP'.\n" " -no_rsfa = If you don't want RSFA output (default is to do so).\n" " -bp_at_end = A (probably unnecessary) switch to have bandpassing be \n" " the very last processing step that is done in the\n" " sequence of steps listed above; at Step 3 above, only \n" " the time series mean and nyquist are BP'ed out, and then\n" " the LFF series is created only after Step 9. NB: this \n" " probably makes only very small changes for most\n" " processing sequences (but maybe not, depending usage).\n" "\n" " -notrans = Don't check for initial positive transients in the data:\n" " *OR* ++ The test is a little slow, so skipping it is OK,\n" " -nosat if you KNOW the data time series are transient-free.\n" " ++ Or set AFNI_SKIP_SATCHECK to YES.\n" " ++ Initial transients won't be handled well by the\n" " bandpassing algorithm, and in addition may seriously\n" " contaminate any further processing, such as inter-\n" " voxel correlations via InstaCorr.\n" " ++ No other tests are made [yet] for non-stationary \n" " behavior in the time series data.\n" "\n" "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n" "\n" " If you use this program, please reference the introductory/description\n" " paper for the FATCAT toolbox:\n" " Taylor PA, Saad ZS (2013). FATCAT: (An Efficient) Functional\n" " And Tractographic Connectivity Analysis Toolbox. Brain \n" " Connectivity 3(5):523-535.\n" "____________________________________________________________________________\n" ); PRINT_AFNI_OMP_USAGE( " 3dRSFC" , " * At present, the only part of 3dRSFC that is parallelized is the\n" " '-blur' option, which processes each sub-brick independently.\n" ) ; PRINT_COMPILE_DATE ; exit(0) ; } /*-- startup --*/ mainENTRY("3dRSFC"); machdep(); AFNI_logger("3dRSFC",argc,argv); PRINT_VERSION("3dRSFC (from 3dBandpass by RW Cox): version THETA"); AUTHOR("PA Taylor"); nosat = AFNI_yesenv("AFNI_SKIP_SATCHECK") ; nopt = 1 ; while( nopt < argc && argv[nopt][0] == '-' ){ if( strcmp(argv[nopt],"-despike") == 0 ){ /* 08 Oct 2010 */ do_despike++ ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-nfft") == 0 ){ int nnup ; if( ++nopt >= argc ) ERROR_exit("need an argument after -nfft!") ; nfft = (int)strtod(argv[nopt],NULL) ; nnup = csfft_nextup_even(nfft) ; if( nfft < 16 || nfft != nnup ) ERROR_exit("value %d after -nfft is illegal! Next legal value = %d",nfft,nnup) ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-blur") == 0 ){ if( ++nopt >= argc ) ERROR_exit("need an argument after -blur!") ; blur = strtod(argv[nopt],NULL) ; if( blur <= 0.0f ) WARNING_message("non-positive blur?!") ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-localPV") == 0 ){ if( ++nopt >= argc ) ERROR_exit("need an argument after -localpv!") ; pvrad = strtod(argv[nopt],NULL) ; if( pvrad <= 0.0f ) WARNING_message("non-positive -localpv?!") ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-prefix") == 0 ){ if( ++nopt >= argc ) ERROR_exit("need an argument after -prefix!") ; prefix = strdup(argv[nopt]) ; if( !THD_filename_ok(prefix) ) ERROR_exit("bad -prefix option!") ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-automask") == 0 ){ if( mask != NULL ) ERROR_exit("Can't use -mask AND -automask!") ; do_automask = 1 ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-mask") == 0 ){ THD_3dim_dataset *mset ; if( ++nopt >= argc ) ERROR_exit("Need argument after '-mask'") ; if( mask != NULL || do_automask ) ERROR_exit("Can't have two mask inputs") ; mset = THD_open_dataset( argv[nopt] ) ; CHECK_OPEN_ERROR(mset,argv[nopt]) ; 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[nopt]) ; nmask = THD_countmask( mask_nx*mask_ny*mask_nz , mask ) ; if( verb ) INFO_message("Number of voxels in mask = %d",nmask) ; if( nmask < 1 ) ERROR_exit("Mask is too small to process") ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-norm") == 0 ){ do_norm = 1 ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-quiet") == 0 ){ verb = 0 ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-no_rs_out") == 0 ){ // @@ SERIES_OUT = 0 ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-un_bp_out") == 0 ){ // @@ UNBP_OUT = 1 ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-no_rsfa") == 0 ){ // @@ DO_RSFA = 0 ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-bp_at_end") == 0 ){ // @@ BP_LAST = 1 ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-notrans") == 0 || strcmp(argv[nopt],"-nosat") == 0 ){ nosat = 1 ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-ort") == 0 ){ if( ++nopt >= argc ) ERROR_exit("need an argument after -ort!") ; if( ortar == NULL ) INIT_IMARR(ortar) ; ortim = mri_read_1D( argv[nopt] ) ; if( ortim == NULL ) ERROR_exit("can't read from -ort '%s'",argv[nopt]) ; mri_add_name(argv[nopt],ortim) ; ADDTO_IMARR(ortar,ortim) ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-dsort") == 0 ){ THD_3dim_dataset *qset ; if( ++nopt >= argc ) ERROR_exit("need an argument after -dsort!") ; if( nortset > 0 ) ERROR_exit("only 1 -dsort option is allowed!") ; qset = THD_open_dataset(argv[nopt]) ; CHECK_OPEN_ERROR(qset,argv[nopt]) ; ortset = (THD_3dim_dataset **)realloc(ortset, sizeof(THD_3dim_dataset *)*(nortset+1)) ; ortset[nortset++] = qset ; nopt++ ; continue ; } if( strncmp(argv[nopt],"-nodetrend",6) == 0 ){ qdet = 0 ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-dt") == 0 ){ if( ++nopt >= argc ) ERROR_exit("need an argument after -dt!") ; dt = (float)strtod(argv[nopt],NULL) ; if( dt <= 0.0f ) WARNING_message("value after -dt illegal!") ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-input") == 0 ){ if( inset != NULL ) ERROR_exit("Can't have 2 -input options!") ; if( ++nopt >= argc ) ERROR_exit("need an argument after -input!") ; inset = THD_open_dataset(argv[nopt]) ; CHECK_OPEN_ERROR(inset,argv[nopt]) ; nopt++ ; continue ; } if( strncmp(argv[nopt],"-band",5) == 0 ){ if( ++nopt >= argc-1 ) ERROR_exit("need 2 arguments after -band!") ; if( have_freq ) WARNING_message("second -band option replaces first one!") ; fbot = strtod(argv[nopt++],NULL) ; ftop = strtod(argv[nopt++],NULL) ; have_freq = 1 ; continue ; } ERROR_exit("Unknown option: '%s'",argv[nopt]) ; } /** check inputs for reasonablositiness **/ if( !have_freq ){ if( nopt+1 >= argc ) ERROR_exit("Need frequencies on command line after options!") ; fbot = (float)strtod(argv[nopt++],NULL) ; ftop = (float)strtod(argv[nopt++],NULL) ; } if( inset == NULL ){ if( nopt >= argc ) ERROR_exit("Need input dataset name on command line after options!") ; inset = THD_open_dataset(argv[nopt]) ; CHECK_OPEN_ERROR(inset,argv[nopt]) ; nopt++ ; } DSET_UNMSEC(inset) ; if( fbot < 0.0f ) ERROR_exit("fbot value can't be negative!") ; if( ftop <= fbot ) ERROR_exit("ftop value %g must be greater than fbot value %g!",ftop,fbot) ; ntime = DSET_NVALS(inset) ; if( ntime < 9 ) ERROR_exit("Input dataset is too short!") ; if( nfft <= 0 ){ nfft = csfft_nextup_even(ntime) ; if( verb ) INFO_message("Data length = %d FFT length = %d",ntime,nfft) ; (void)THD_bandpass_set_nfft(nfft) ; } else if( nfft < ntime ){ ERROR_exit("-nfft %d is less than data length = %d",nfft,ntime) ; } else { kk = THD_bandpass_set_nfft(nfft) ; if( kk != nfft && verb ) INFO_message("Data length = %d FFT length = %d",ntime,kk) ; } if( dt <= 0.0f ){ dt = DSET_TR(inset) ; if( dt <= 0.0f ){ WARNING_message("Setting dt=1.0 since input dataset lacks a time axis!") ; dt = 1.0f ; } } ftopALL = 1./dt ;// Aug,2016: should solve problem of a too-large // value for THD_bandpass_vectors(), while still // being >f_{Nyquist} if( !THD_bandpass_OK(ntime,dt,fbot,ftop,1) ) ERROR_exit("Can't continue!") ; nx = DSET_NX(inset); ny = DSET_NY(inset); nz = DSET_NZ(inset); nvox = nx*ny*nz; /* check mask, or create it */ if( verb ) INFO_message("Loading input dataset time series" ) ; DSET_load(inset) ; if( mask != NULL ){ if( mask_nx != nx || mask_ny != ny || mask_nz != nz ) ERROR_exit("-mask dataset grid doesn't match input dataset") ; } else if( do_automask ){ mask = THD_automask( inset ) ; if( mask == NULL ) ERROR_message("Can't create -automask from input dataset?") ; nmask = THD_countmask( DSET_NVOX(inset) , mask ) ; if( verb ) INFO_message("Number of voxels in automask = %d",nmask); if( nmask < 1 ) ERROR_exit("Automask is too small to process") ; } else { mask = (byte *)malloc(sizeof(byte)*nvox) ; nmask = nvox ; memset(mask,1,sizeof(byte)*nvox) ; // if( verb ) // @@ alert if aaaalllllll vox are going to be analyzed! INFO_message("No mask ==> processing all %d voxels",nvox); } /* A simple check of dataset quality [08 Feb 2010] */ if( !nosat ){ float val ; INFO_message( "Checking dataset for initial transients [use '-notrans' to skip this test]") ; val = THD_saturation_check(inset,mask,0,0) ; kk = (int)(val+0.54321f) ; if( kk > 0 ) ININFO_message( "Looks like there %s %d non-steady-state initial time point%s :-(" , ((kk==1) ? "is" : "are") , kk , ((kk==1) ? " " : "s") ) ; else if( val > 0.3210f ) /* don't ask where this threshold comes from! */ ININFO_message( "MAYBE there's an initial positive transient of 1 point, but it's hard to tell\n") ; else ININFO_message("No widespread initial positive transient detected :-)") ; } /* check -dsort inputs for match to inset */ for( kk=0 ; kk < nortset ; kk++ ){ if( DSET_NX(ortset[kk]) != nx || DSET_NY(ortset[kk]) != ny || DSET_NZ(ortset[kk]) != nz || DSET_NVALS(ortset[kk]) != ntime ) ERROR_exit("-dsort %s doesn't match input dataset grid" , DSET_BRIKNAME(ortset[kk]) ) ; } /* convert input dataset to a vectim, which is more fun */ // @@ convert BP'ing ftop/bot into indices for the DFT (below) delf = 1.0/(ntime*dt); ind_low = (int) rint(fbot/delf); ind_high = (int) rint(ftop/delf); if( ntime % 2 ) // nyquist number N_ny = (ntime-1)/2; else N_ny = ntime/2; sqnt = sqrt(ntime); nt_fac = sqrt(ntime*(ntime-1)); // @@ if BP_LAST==0: // now we go through twice, doing LFF bandpass for NumDen==0 and // `full spectrum' processing for NumDen==1. // if BP_LAST==1: // now we go through once, doing only `full spectrum' processing for( NumDen=0 ; NumDen<2 ; NumDen++) { //if( NumDen==1 ){ // full spectrum // fbot = fbotALL; // ftop = ftopALL; //} // essentially, just doesn't BP here, and the perfect filtering at end // is used for both still; this makes the final output spectrum // contain only frequencies in range of 0.01-0.08 if( BP_LAST==1 ) INFO_message("Only doing filtering to LFFs at end!"); mrv = THD_dset_to_vectim( inset , mask , 0 ) ; if( mrv == NULL ) ERROR_exit("Can't load time series data!?") ; if( NumDen==1 ) DSET_unload(inset) ; // @@ only unload on 2nd pass /* similarly for the ort vectors */ if( ortar != NULL ){ for( kk=0 ; kk < IMARR_COUNT(ortar) ; kk++ ){ ortim = IMARR_SUBIM(ortar,kk) ; if( ortim->nx < ntime ) ERROR_exit("-ort file %s is shorter than input dataset time series", ortim->name ) ; ort = (float **)realloc( ort , sizeof(float *)*(nort+ortim->ny) ) ; for( vv=0 ; vv < ortim->ny ; vv++ ) ort[nort++] = MRI_FLOAT_PTR(ortim) + ortim->nx * vv ; } } /* all the real work now */ if( do_despike ){ int_pair nsp ; if( verb ) INFO_message("Testing data time series for spikes") ; nsp = THD_vectim_despike9( mrv ) ; if( verb ) ININFO_message(" -- Squashed %d spikes from %d voxels",nsp.j,nsp.i) ; } if( verb ) INFO_message("Bandpassing data time series") ; if( (BP_LAST==0) && (NumDen==0) ) (void)THD_bandpass_vectim( mrv , dt,fbot,ftop , qdet , nort,ort ) ; else (void)THD_bandpass_vectim( mrv , dt,fbotALL,ftopALL, qdet,nort,ort ) ; /* OK, maybe a little more work */ if( nortset == 1 ){ MRI_vectim *orv ; orv = THD_dset_to_vectim( ortset[0] , mask , 0 ) ; if( orv == NULL ){ ERROR_message("Can't load -dsort %s",DSET_BRIKNAME(ortset[0])) ; } else { float *dp , *mvv , *ovv , ff ; if( verb ) INFO_message("Orthogonalizing to bandpassed -dsort") ; //(void)THD_bandpass_vectim( orv , dt,fbot,ftop , qdet , nort,ort ) ; //@@ if( (BP_LAST==0) && (NumDen==0) ) (void)THD_bandpass_vectim(orv,dt,fbot,ftop,qdet,nort,ort); else (void)THD_bandpass_vectim(orv,dt,fbotALL,ftopALL,qdet,nort,ort); THD_vectim_normalize( orv ) ; dp = malloc(sizeof(float)*mrv->nvec) ; THD_vectim_vectim_dot( mrv , orv , dp ) ; for( vv=0 ; vv < mrv->nvec ; vv++ ){ ff = dp[vv] ; if( ff != 0.0f ){ mvv = VECTIM_PTR(mrv,vv) ; ovv = VECTIM_PTR(orv,vv) ; for( kk=0 ; kk < ntime ; kk++ ) mvv[kk] -= ff*ovv[kk] ; } } VECTIM_destroy(orv) ; free(dp) ; } } if( blur > 0.0f ){ if( verb ) INFO_message("Blurring time series data spatially; FWHM=%.2f",blur) ; mri_blur3D_vectim( mrv , blur ) ; } if( pvrad > 0.0f ){ if( verb ) INFO_message("Local PV-ing time series data spatially; radius=%.2f",pvrad) ; THD_vectim_normalize( mrv ) ; THD_vectim_localpv( mrv , pvrad ) ; } if( do_norm && pvrad <= 0.0f ){ if( verb ) INFO_message("L2 normalizing time series data") ; THD_vectim_normalize( mrv ) ; } /* create output dataset, populate it, write it, then quit */ if( (NumDen==0) ) { // @@ BP'ed version; will do filt if BP_LAST if(BP_LAST) // do bandpass here for BP_LAST (void)THD_bandpass_vectim(mrv,dt,fbot,ftop,qdet,0,NULL); if( verb ) INFO_message("Creating output dataset in memory, then writing it") ; outset = EDIT_empty_copy(inset) ; if(SERIES_OUT){ sprintf(out_lff,"%s_LFF",prefix); EDIT_dset_items( outset , ADN_prefix,out_lff , ADN_none ) ; tross_Copy_History( inset , outset ) ; tross_Make_History( "3dBandpass" , argc,argv , outset ) ; } for( vv=0 ; vv < ntime ; vv++ ) EDIT_substitute_brick( outset , vv , MRI_float , NULL ) ; #if 1 THD_vectim_to_dset( mrv , outset ) ; #else AFNI_OMP_START ; #pragma omp parallel { float *far , *var ; int *ivec=mrv->ivec ; int vv,kk ; #pragma omp for for( vv=0 ; vv < ntime ; vv++ ){ far = DSET_BRICK_ARRAY(outset,vv) ; var = mrv->fvec + vv ; for( kk=0 ; kk < nmask ; kk++ ) far[ivec[kk]] = var[kk*ntime] ; } } AFNI_OMP_END ; #endif VECTIM_destroy(mrv) ; if(SERIES_OUT){ // @@ DSET_write(outset) ; if( verb ) WROTE_DSET(outset) ; } } else{ // @@ non-BP'ed version if( verb ) INFO_message("Creating output dataset 2 in memory") ; // do this here because LFF version was also BP'ed at end. if(BP_LAST) // do bandpass here for BP_LAST (void)THD_bandpass_vectim(mrv,dt,fbotALL,ftopALL,qdet,0,NULL); outsetALL = EDIT_empty_copy(inset) ; if(UNBP_OUT){ sprintf(out_unBP,"%s_unBP",prefix); EDIT_dset_items( outsetALL, ADN_prefix, out_unBP, ADN_none ); tross_Copy_History( inset , outsetALL ) ; tross_Make_History( "3dRSFC" , argc,argv , outsetALL ) ; } for( vv=0 ; vv < ntime ; vv++ ) EDIT_substitute_brick( outsetALL , vv , MRI_float , NULL ) ; #if 1 THD_vectim_to_dset( mrv , outsetALL ) ; #else AFNI_OMP_START ; #pragma omp parallel { float *far , *var ; int *ivec=mrv->ivec ; int vv,kk ; #pragma omp for for( vv=0 ; vv < ntime ; vv++ ){ far = DSET_BRICK_ARRAY(outsetALL,vv) ; var = mrv->fvec + vv ; for( kk=0 ; kk < nmask ; kk++ ) far[ivec[kk]] = var[kk*ntime] ; } } AFNI_OMP_END ; #endif VECTIM_destroy(mrv) ; if(UNBP_OUT){ DSET_write(outsetALL) ; if( verb ) WROTE_DSET(outsetALL) ; } } }// end of NumDen loop // @@ INFO_message("Starting the (f)ALaFFel calcs") ; // allocations series1 = (double *)calloc(ntime,sizeof(double)); series2 = (double *)calloc(ntime,sizeof(double)); xx1 = (double *)calloc(2*ntime,sizeof(double)); xx2 = (double *)calloc(2*ntime,sizeof(double)); alff = (float *)calloc(nvox,sizeof(float)); malff = (float *)calloc(nvox,sizeof(float)); falff = (float *)calloc(nvox,sizeof(float)); if( (series1 == NULL) || (series2 == NULL) || (xx1 == NULL) || (xx2 == NULL) || (alff == NULL) || (malff == NULL) || (falff == NULL)) { fprintf(stderr, "\n\n MemAlloc failure.\n\n"); exit(122); } if(DO_RSFA) { rsfa = (float *)calloc(nvox,sizeof(float)); mrsfa = (float *)calloc(nvox,sizeof(float)); frsfa = (float *)calloc(nvox,sizeof(float)); if( (rsfa == NULL) || (mrsfa == NULL) || (frsfa == NULL)) { fprintf(stderr, "\n\n MemAlloc failure.\n\n"); exit(123); } } work = gsl_fft_real_workspace_alloc (ntime); real1 = gsl_fft_real_wavetable_alloc (ntime); real2 = gsl_fft_real_wavetable_alloc (ntime); gsl_complex_packed_array compl_freqs1 = xx1; gsl_complex_packed_array compl_freqs2 = xx2; // ********************************************************************* // ********************************************************************* // ************** Falafelling = ALFF/fALFF calcs ***************** // ********************************************************************* // ********************************************************************* // Be now have the BP'ed data set (outset) and the non-BP'ed one // (outsetALL). now we'll FFT both, get amplitudes in appropriate // ranges, and calculate: ALFF, mALFF, fALFF, ctr = 0; for( kk=0; kk<nvox ; kk++) { if(mask[kk]) { // BP one, and unBP one, either for BP_LAST or !BP_LAST for( m=0 ; m<ntime ; m++ ) { series1[m] = THD_get_voxel(outset,kk,m); series2[m] = THD_get_voxel(outsetALL,kk,m); } mm = gsl_fft_real_transform(series1, 1, ntime, real1, work); mm = gsl_fft_halfcomplex_unpack(series1, compl_freqs1, 1, ntime); mm = gsl_fft_real_transform(series2, 1, ntime, real2, work); mm = gsl_fft_halfcomplex_unpack(series2, compl_freqs2, 1, ntime); numer = 0.0f; denom = 0.0f; de_rsfa = 0.0f; nu_rsfa = 0.0f; for( m=1 ; m<N_ny ; m++ ) { mm = 2*m; pow2 = compl_freqs2[mm]*compl_freqs2[mm] + compl_freqs2[mm+1]*compl_freqs2[mm+1]; // power //pow2*=2;// factor of 2 since ampls are even funcs denom+= (float) sqrt(pow2); // amplitude de_rsfa+= (float) pow2; if( ( m>=ind_low ) && ( m<=ind_high ) ){ pow1 = compl_freqs1[mm]*compl_freqs1[mm]+ compl_freqs1[mm+1]*compl_freqs1[mm+1]; //pow1*=2; numer+= (float) sqrt(pow1); nu_rsfa+= (float) pow1; } } if( denom>0.000001 ) falff[kk] = numer/denom; else falff[kk] = 0.; alff[kk] = 2*numer/sqnt;// factor of 2 since ampl is even funct meanALFF+= alff[kk]; if(DO_RSFA){ nu_rsfa = sqrt(2*nu_rsfa); // factor of 2 since ampls de_rsfa = sqrt(2*de_rsfa); // are even funcs if( de_rsfa>0.000001 ) frsfa[kk] = nu_rsfa/de_rsfa; else frsfa[kk]=0.; rsfa[kk] = nu_rsfa/nt_fac; meanRSFA+= rsfa[kk]; } ctr+=1; } } meanALFF/= ctr; meanRSFA/= ctr; gsl_fft_real_wavetable_free(real1); gsl_fft_real_wavetable_free(real2); gsl_fft_real_workspace_free(work); // ALFFs divided by mean of brain value for( kk=0 ; kk<nvox ; kk++ ) if(mask[kk]){ malff[kk] = alff[kk]/meanALFF; if(DO_RSFA) mrsfa[kk] = rsfa[kk]/meanRSFA; } // ************************************************************** // ************************************************************** // Store and output // ************************************************************** // ************************************************************** outsetALFF = EDIT_empty_copy( inset ) ; sprintf(out_alff,"%s_ALFF",prefix); EDIT_dset_items( outsetALFF, ADN_nvals, 1, ADN_datum_all , MRI_float , ADN_prefix , out_alff, ADN_none ) ; if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetALFF)) ) ERROR_exit("Can't overwrite existing dataset '%s'", DSET_HEADNAME(outsetALFF)); EDIT_substitute_brick(outsetALFF, 0, MRI_float, alff); alff=NULL; THD_load_statistics(outsetALFF); tross_Make_History("3dRSFC", argc, argv, outsetALFF); THD_write_3dim_dataset(NULL, NULL, outsetALFF, True); outsetfALFF = EDIT_empty_copy( inset ) ; sprintf(out_falff,"%s_fALFF",prefix); EDIT_dset_items( outsetfALFF, ADN_nvals, 1, ADN_datum_all , MRI_float , ADN_prefix , out_falff, ADN_none ) ; if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetfALFF)) ) ERROR_exit("Can't overwrite existing dataset '%s'", DSET_HEADNAME(outsetfALFF)); EDIT_substitute_brick(outsetfALFF, 0, MRI_float, falff); falff=NULL; THD_load_statistics(outsetfALFF); tross_Make_History("3dRSFC", argc, argv, outsetfALFF); THD_write_3dim_dataset(NULL, NULL, outsetfALFF, True); outsetmALFF = EDIT_empty_copy( inset ) ; sprintf(out_malff,"%s_mALFF",prefix); EDIT_dset_items( outsetmALFF, ADN_nvals, 1, ADN_datum_all , MRI_float , ADN_prefix , out_malff, ADN_none ) ; if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetmALFF)) ) ERROR_exit("Can't overwrite existing dataset '%s'", DSET_HEADNAME(outsetmALFF)); EDIT_substitute_brick(outsetmALFF, 0, MRI_float, malff); malff=NULL; THD_load_statistics(outsetmALFF); tross_Make_History("3dRSFC", argc, argv, outsetmALFF); THD_write_3dim_dataset(NULL, NULL, outsetmALFF, True); if(DO_RSFA){ outsetRSFA = EDIT_empty_copy( inset ) ; sprintf(out_rsfa,"%s_RSFA",prefix); EDIT_dset_items( outsetRSFA, ADN_nvals, 1, ADN_datum_all , MRI_float , ADN_prefix , out_rsfa, ADN_none ) ; if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetRSFA)) ) ERROR_exit("Can't overwrite existing dataset '%s'", DSET_HEADNAME(outsetRSFA)); EDIT_substitute_brick(outsetRSFA, 0, MRI_float, rsfa); rsfa=NULL; THD_load_statistics(outsetRSFA); tross_Make_History("3dRSFC", argc, argv, outsetRSFA); THD_write_3dim_dataset(NULL, NULL, outsetRSFA, True); outsetfRSFA = EDIT_empty_copy( inset ) ; sprintf(out_frsfa,"%s_fRSFA",prefix); EDIT_dset_items( outsetfRSFA, ADN_nvals, 1, ADN_datum_all , MRI_float , ADN_prefix , out_frsfa, ADN_none ) ; if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetfRSFA)) ) ERROR_exit("Can't overwrite existing dataset '%s'", DSET_HEADNAME(outsetfRSFA)); EDIT_substitute_brick(outsetfRSFA, 0, MRI_float, frsfa); frsfa=NULL; THD_load_statistics(outsetfRSFA); tross_Make_History("3dRSFC", argc, argv, outsetfRSFA); THD_write_3dim_dataset(NULL, NULL, outsetfRSFA, True); outsetmRSFA = EDIT_empty_copy( inset ) ; sprintf(out_mrsfa,"%s_mRSFA",prefix); EDIT_dset_items( outsetmRSFA, ADN_nvals, 1, ADN_datum_all , MRI_float , ADN_prefix , out_mrsfa, ADN_none ) ; if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetmRSFA)) ) ERROR_exit("Can't overwrite existing dataset '%s'", DSET_HEADNAME(outsetmRSFA)); EDIT_substitute_brick(outsetmRSFA, 0, MRI_float, mrsfa); mrsfa=NULL; THD_load_statistics(outsetmRSFA); tross_Make_History("3dRSFC", argc, argv, outsetmRSFA); THD_write_3dim_dataset(NULL, NULL, outsetmRSFA, True); } // ************************************************************ // ************************************************************ // Freeing // ************************************************************ // ************************************************************ DSET_delete(inset); DSET_delete(outsetALL); DSET_delete(outset); DSET_delete(outsetALFF); DSET_delete(outsetmALFF); DSET_delete(outsetfALFF); DSET_delete(outsetRSFA); DSET_delete(outsetmRSFA); DSET_delete(outsetfRSFA); free(inset); free(outsetALL); free(outset); free(outsetALFF); free(outsetmALFF); free(outsetfALFF); free(outsetRSFA); free(outsetmRSFA); free(outsetfRSFA); free(rsfa); free(mrsfa); free(frsfa); free(alff); free(malff); free(falff); free(mask); free(series1); free(series2); free(xx1); free(xx2); exit(0) ; }
int main(int argc, char *argv[]) { int i,j,k,m,n,aa,ii,jj,kk,mm,rr; int iarg; int nmask1=0; int nmask2=0; THD_3dim_dataset *insetFA = NULL, *insetV1 = NULL, *insetMD = NULL, *insetL1 = NULL; THD_3dim_dataset *insetEXTRA=NULL; THD_3dim_dataset *mset2=NULL; THD_3dim_dataset *mset1=NULL; THD_3dim_dataset *outsetMAP=NULL, *outsetMASK=NULL; char *prefix="tracky"; int LOG_TYPE=0; char in_FA[300]; char in_V1[300]; char in_MD[300]; char in_L1[300]; int EXTRAFILE=0; // switch for whether other file is input as WM map char OUT_bin[300]; char OUT_tracstat[300]; char prefix_mask[300]; char prefix_map[300]; // FACT algopts FILE *fout0; float MinFA=0.2,MaxAngDeg=45,MinL=20.0; float MaxAng; int SeedPerV[3]={2,2,2}; int ArrMax=0; float tempvmagn; int Nvox=-1; // tot number vox int Dim[3]={0,0,0}; // dim in each dir int Nseed=0,M=30,bval=1000; int DimSeed[3]; // number of seeds there will be float Ledge[3]; // voxel edge lengths int *ROI1, *ROI2; short int *temp_arr; char *temp_byte; int **Tforw, **Tback; int **Ttot; float **flTforw, **flTback; float ****coorded; int ****INDEX; int len_forw, len_back; // int count of num of squares through float phys_forw[1], phys_back[1]; int idx; float ave_tract_len, ave_tract_len_phys; int inroi1, inroi2, KEEPIT; // switches for detecting int in[3]; // to pass to trackit float physin[3]; // also for trackit, physical loc, int totlen; float totlen_phys; int Numtract; int READS_in; float READS_fl; int end[2][3]; int test_ind[2][3]; int roi3_ct=0, id=0; float roi3_mu_MD = 0.,roi3_mu_RD = 0.,roi3_mu_L1 = 0.,roi3_mu_FA = 0.; float roi3_sd_MD = 0.,roi3_sd_RD = 0.,roi3_sd_L1 = 0.,roi3_sd_FA = 0.; float tempMD,tempFA,tempRD,tempL1; char dset_or[4] = "RAI"; THD_3dim_dataset *dsetn; int TV_switch[3] = {0,0,0}; TAYLOR_BUNDLE *tb=NULL; TAYLOR_TRACT *tt=NULL; char *mode = "NI_fast_binary"; NI_element *nel=NULL; int dump_opts=0; tv_io_header header1 = {.id_string = "TRACK\0", .origin = {0,0,0}, .n_scalars = 3, .scal_n[0] = "FA", .scal_n[1] = "MD", .scal_n[2] = "L1", .n_properties = 0, .vox_to_ras = {{0.,0.,0.,0.},{0.,0.,0.,0.}, {0.,0.,0.,0.},{0.,0.,0.,0.}}, // reset this later based on actual data set .voxel_order = "RAI\0", .invert_x = 0, .invert_y = 0, .invert_z = 0, .swap_xy = 0, .swap_yz = 0, .swap_zx = 0, .n_count = 0, .version = 2, .hdr_size = 1000}; // for testing names... char *postfix[4]={"+orig.HEAD\0",".nii.gz\0",".nii\0","+tlrc.HEAD\0"}; int FOUND =-1; int RECORD_ORIG = 0; float Orig[3] = {0.0,0.0,0.0}; mainENTRY("3dTrackID"); machdep(); // **************************************************************** // **************************************************************** // load AFNI stuff // **************************************************************** // **************************************************************** INFO_message("version: MU"); /** scan args **/ if (argc == 1) { usage_TrackID(1); exit(0); } iarg = 1; while( iarg < argc && argv[iarg][0] == '-' ){ if( strcmp(argv[iarg],"-help") == 0 || strcmp(argv[iarg],"-h") == 0 ) { usage_TrackID(strlen(argv[iarg])>3 ? 2:1); exit(0); } if( strcmp(argv[iarg],"-verb") == 0) { if( ++iarg >= argc ) ERROR_exit("Need argument after '-verb'") ; set_tract_verb(atoi(argv[iarg])); iarg++ ; continue ; } if( strcmp(argv[iarg],"-write_opts") == 0) { dump_opts=1; iarg++ ; continue ; } if( strcmp(argv[iarg],"-rec_orig") == 0) { RECORD_ORIG=1; iarg++ ; continue ; } if( strcmp(argv[iarg],"-tract_out_mode") == 0) { if( ++iarg >= argc ) ERROR_exit("Need argument after '-tract_out_mode'") ; if (strcmp(argv[iarg], "NI_fast_binary") && strcmp(argv[iarg], "NI_fast_text") && strcmp(argv[iarg], "NI_slow_binary") && strcmp(argv[iarg], "NI_slow_text") ) { ERROR_message("Bad value (%s) for -tract_out_mode",argv[iarg]); exit(1); } mode = argv[iarg]; iarg++ ; continue ; } if( strcmp(argv[iarg],"-mask1") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '-mask1'") ; mset1 = THD_open_dataset( argv[iarg] ) ; if( mset1 == NULL ) ERROR_exit("Can't open mask1 dataset '%s'", argv[iarg]) ; DSET_load(mset1) ; CHECK_LOAD_ERROR(mset1) ; nmask1 = DSET_NVOX(mset1) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-mask2") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '-mask2'") ; mset2 = THD_open_dataset( argv[iarg] ) ; if( mset2 == NULL ) ERROR_exit("Can't open mask2 dataset '%s'", argv[iarg]) ; DSET_load(mset2) ; CHECK_LOAD_ERROR(mset2) ; nmask2 = DSET_NVOX(mset2) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-prefix") == 0 ){ iarg++ ; if( iarg >= argc ) ERROR_exit("Need argument after '-prefix'"); prefix = strdup(argv[iarg]) ; if( !THD_filename_ok(prefix) ) ERROR_exit("Illegal name after '-prefix'"); iarg++ ; continue ; } if( strcmp(argv[iarg],"-input") == 0 ){ iarg++ ; if( iarg >= argc ) ERROR_exit("Need argument after '-input'"); for( i=0 ; i<4 ; i++) { sprintf(in_FA,"%s_FA%s", argv[iarg],postfix[i]); if(THD_is_ondisk(in_FA)) { FOUND = i; break; } } insetFA = THD_open_dataset(in_FA) ; if( (insetFA == NULL ) || (FOUND==-1)) ERROR_exit("Can't open dataset '%s': for FA.",in_FA); DSET_load(insetFA) ; CHECK_LOAD_ERROR(insetFA) ; Nvox = DSET_NVOX(insetFA) ; Dim[0] = DSET_NX(insetFA); Dim[1] = DSET_NY(insetFA); Dim[2] = DSET_NZ(insetFA); Ledge[0] = fabs(DSET_DX(insetFA)); Ledge[1] = fabs(DSET_DY(insetFA)); Ledge[2] = fabs(DSET_DZ(insetFA)); Orig[0] = DSET_XORG(insetFA); Orig[1] = DSET_YORG(insetFA); Orig[2] = DSET_ZORG(insetFA); // check tot num vox match (as proxy for dims...) if( (Nvox != nmask1) || (Nvox != nmask2) ) ERROR_exit("Input dataset does not match both mask volumes!"); // this stores the original data file orientation for later use, // as well since we convert everything to RAI temporarily, as // described below header1.voxel_order[0]=ORIENT_typestr[insetFA->daxes->xxorient][0]; header1.voxel_order[1]=ORIENT_typestr[insetFA->daxes->yyorient][0]; header1.voxel_order[2]=ORIENT_typestr[insetFA->daxes->zzorient][0]; for( i=0 ; i<3 ; i++) { header1.dim[i] = Dim[i]; header1.voxel_size[i] = Ledge[i]; // will want this when outputting file later for TrackVis. TV_switch[i] = !(dset_or[i]==header1.voxel_order[i]); } dset_or[3]='\0'; FOUND = -1; for( i=0 ; i<4 ; i++) { sprintf(in_V1,"%s_V1%s", argv[iarg],postfix[i]); if(THD_is_ondisk(in_V1)) { FOUND = i; break; } } insetV1 = THD_open_dataset(in_V1); if( insetV1 == NULL ) ERROR_exit("Can't open dataset '%s':V1",in_V1); DSET_load(insetV1) ; CHECK_LOAD_ERROR(insetV1) ; FOUND = -1; for( i=0 ; i<4 ; i++) { sprintf(in_L1,"%s_L1%s", argv[iarg],postfix[i]); if(THD_is_ondisk(in_L1)) { FOUND = i; break; } } insetL1 = THD_open_dataset(in_L1); if( insetL1 == NULL ) ERROR_exit("Can't open dataset '%s':L1",in_L1); DSET_load(insetL1) ; CHECK_LOAD_ERROR(insetL1) ; FOUND = -1; for( i=0 ; i<4 ; i++) { sprintf(in_MD,"%s_MD%s", argv[iarg],postfix[i]); if(THD_is_ondisk(in_MD)) { FOUND = i; break; } } insetMD = THD_open_dataset(in_MD); if( insetMD == NULL ) ERROR_exit("Can't open dataset '%s':MD",in_MD); DSET_load(insetMD) ; CHECK_LOAD_ERROR(insetMD) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-algopt") == 0 ){ iarg++ ; if( iarg >= argc ) ERROR_exit("Need argument after '-algopt'"); if (!(nel = ReadTractAlgOpts(argv[iarg]))) { ERROR_message("Failed to read options in %s\n", argv[iarg]); exit(19); } if (NI_getTractAlgOpts(nel, &MinFA, &MaxAngDeg, &MinL, SeedPerV, &M, &bval)) { ERROR_message("Failed to get options"); exit(1); } NI_free_element(nel); nel=NULL; iarg++ ; continue ; } if( strcmp(argv[iarg],"-logic") == 0 ){ iarg++ ; if( iarg >= argc ) ERROR_exit("Need argument after '-logic'"); INFO_message("ROI logic type is: %s",argv[iarg]); if( strcmp(argv[iarg],"AND") == 0 ) LOG_TYPE = 1; else if( strcmp(argv[iarg],"OR") == 0 ) LOG_TYPE = 0; else if( strcmp(argv[iarg],"ALL") == 0 ) LOG_TYPE = -1; else ERROR_exit("Illegal after '-logic': need 'OR' or 'AND'"); iarg++ ; continue ; } //@@ if( strcmp(argv[iarg],"-extra_set") == 0) { if( ++iarg >= argc ) ERROR_exit("Need argument after '-extra_set'"); EXTRAFILE = 1; // switch on insetEXTRA = THD_open_dataset(argv[iarg]); if( (insetEXTRA == NULL ) ) ERROR_exit("Can't open dataset '%s': for extra set.",argv[iarg]); DSET_load(insetEXTRA) ; CHECK_LOAD_ERROR(insetEXTRA) ; if( !((Dim[0] == DSET_NX(insetEXTRA)) && (Dim[1] == DSET_NY(insetEXTRA)) && (Dim[2] == DSET_NZ(insetEXTRA)))) ERROR_exit("Dimensions of extra set '%s' don't match those of the DTI prop ones ('%s', etc.).",argv[iarg], in_FA); iarg++ ; continue ; } ERROR_message("Bad option '%s'\n",argv[iarg]) ; suggest_best_prog_option(argv[0], argv[iarg]); exit(1); } if (iarg < 4) { ERROR_message("Too few options. Try -help for details.\n"); exit(1); } if (dump_opts) { nel = NI_setTractAlgOpts(NULL, &MinFA, &MaxAngDeg, &MinL, SeedPerV, &M, &bval); WriteTractAlgOpts(prefix, nel); NI_free_element(nel); nel=NULL; } // Process the options a little for( i=0 ; i<3 ; i++) DimSeed[i] = Dim[i]*SeedPerV[i]; Nseed = Nvox*SeedPerV[0]*SeedPerV[1]*SeedPerV[2]; // convert to cos of rad value for comparisons, instead of using acos() MaxAng = cos(CONV*MaxAngDeg); // switch to add header-- option for now, added Sept. 2012 // for use with map_TrackID to map tracks to different space if(RECORD_ORIG) { for( i=0 ; i<3 ; i++) header1.origin[i] = Orig[i]; } // at some point, we will have to convert indices into // pseudo-locations; being forced into this choice means that // different data set orientations would be represented differently // and incorrectly in some instances... so, for now, we'll resample // everything to RAI, and then resample back later. guess this will // just slow things down slightly. // have all be RAI for processing here if(TV_switch[0] || TV_switch[1] || TV_switch[2]) { dsetn = r_new_resam_dset(insetFA, NULL, 0.0, 0.0, 0.0, dset_or, RESAM_NN_TYPE, NULL, 1, 0); DSET_delete(insetFA); insetFA=dsetn; dsetn=NULL; dsetn = r_new_resam_dset(insetMD, NULL, 0.0, 0.0, 0.0, dset_or, RESAM_NN_TYPE, NULL, 1, 0); DSET_delete(insetMD); insetMD=dsetn; dsetn=NULL; dsetn = r_new_resam_dset(insetV1, NULL, 0.0, 0.0, 0.0, dset_or, RESAM_NN_TYPE, NULL, 1, 0); DSET_delete(insetV1); insetV1=dsetn; dsetn=NULL; dsetn = r_new_resam_dset(insetL1, NULL, 0.0, 0.0, 0.0, dset_or, RESAM_NN_TYPE, NULL, 1, 0); DSET_delete(insetL1); insetL1=dsetn; dsetn=NULL; dsetn = r_new_resam_dset(mset1, NULL, 0.0, 0.0, 0.0, dset_or, RESAM_NN_TYPE, NULL, 1, 0); DSET_delete(mset1); mset1=dsetn; dsetn=NULL; dsetn = r_new_resam_dset(mset2, NULL, 0.0, 0.0, 0.0, dset_or, RESAM_NN_TYPE, NULL, 1, 0); DSET_delete(mset2); mset2=dsetn; dsetn=NULL; if(EXTRAFILE) { dsetn = r_new_resam_dset(insetEXTRA, NULL, 0.0, 0.0, 0.0, dset_or, RESAM_NN_TYPE, NULL, 1, 0); DSET_delete(insetEXTRA); insetEXTRA=dsetn; dsetn=NULL; } } // **************************************************************** // **************************************************************** // make arrays for tracking // **************************************************************** // **************************************************************** // for temp storage array, just a multiple of longest dimension! if(Dim[0] > Dim[1]) ArrMax = Dim[0] * 4; else ArrMax = Dim[1] * 4; if(4*Dim[2] > ArrMax) ArrMax = Dim[2] * 4; ROI1 = (int *)calloc(Nvox, sizeof(int)); ROI2 = (int *)calloc(Nvox, sizeof(int)); temp_arr = (short int *)calloc(Nvox, sizeof(short int)); temp_byte = (char *)calloc(Nvox, sizeof(char)); // temp storage whilst tracking Tforw = calloc(ArrMax, sizeof(Tforw)); for(i=0 ; i<ArrMax ; i++) Tforw[i] = calloc(3, sizeof(int)); Ttot = calloc(2*ArrMax , sizeof(Ttot)); for(i=0 ; i<2*ArrMax ; i++) Ttot[i] = calloc(3, sizeof(int)); Tback = calloc(ArrMax, sizeof(Tback)); for(i=0 ; i<ArrMax ; i++) Tback[i] = calloc(3, sizeof(int)); // temp storage whilst tracking, physical loc flTforw = calloc(ArrMax, sizeof(flTforw)); for(i=0 ; i<ArrMax ; i++) flTforw[i] = calloc(3, sizeof(int)); flTback = calloc(ArrMax,sizeof(flTback)); for(i=0 ; i<ArrMax ; i++) flTback[i] = calloc(3, sizeof(int)); if( (ROI1 == NULL) || (ROI2 == NULL) || (temp_arr == NULL) || (Tforw == NULL) || (Tback == NULL) || (flTforw == NULL) || (flTback == NULL) || (Ttot == NULL)) { fprintf(stderr, "\n\n MemAlloc failure.\n\n"); exit(12); } coorded = (float ****) calloc( Dim[0], sizeof(float ***) ); for ( i = 0 ; i < Dim[0] ; i++ ) coorded[i] = (float ***) calloc( Dim[1], sizeof(float **) ); for ( i = 0 ; i < Dim[0] ; i++ ) for ( j = 0 ; j < Dim[1] ; j++ ) coorded[i][j] = (float **) calloc( Dim[2], sizeof(float *) ); for ( i=0 ; i<Dim[0] ; i++ ) for ( j=0 ; j<Dim[1] ; j++ ) for ( k= 0 ; k<Dim[2] ; k++ ) //3 comp of V1 and FA coorded[i][j][k] = (float *) calloc( 4, sizeof(float) ); INDEX = (int ****) calloc( Dim[0], sizeof(int ***) ); for ( i = 0 ; i < Dim[0] ; i++ ) INDEX[i] = (int ***) calloc( Dim[1], sizeof(int **) ); for ( i = 0 ; i < Dim[0] ; i++ ) for ( j = 0 ; j < Dim[1] ; j++ ) INDEX[i][j] = (int **) calloc( Dim[2], sizeof(int *) ); for ( i=0 ; i<Dim[0] ; i++ ) for ( j=0 ; j<Dim[1] ; j++ ) for ( k= 0 ; k<Dim[2] ; k++ ) INDEX[i][j][k] = (int *) calloc( 4, sizeof(int) ); // this statement will never be executed if allocation fails above if( (INDEX == NULL) || (coorded == NULL) ) { fprintf(stderr, "\n\n MemAlloc failure.\n\n"); exit(122); } for(i=0 ; i<Nvox ; i++) { if(THD_get_voxel( mset1, i, 0) >0.5){ ROI1[i] = 1; } if(THD_get_voxel( mset2, i, 0) >0.5) ROI2[i] = 1; } // set up eigvecs in 3D coord sys, // mark off where ROIs are and keep index handy idx=0; for( k=0 ; k<Dim[2] ; k++ ) for( j=0 ; j<Dim[1] ; j++ ) for( i=0 ; i<Dim[0] ; i++ ) { for( m=0 ; m<3 ; m++ ) coorded[i][j][k][m] = THD_get_voxel(insetV1, idx, m); if(EXTRAFILE) coorded[i][j][k][3] = THD_get_voxel(insetEXTRA, idx, 0); else coorded[i][j][k][3] = THD_get_voxel(insetFA, idx, 0); // make sure that |V1| == 1 for all eigenvects, otherwise it's /// a problem in the tractography; currently, some from // 3dDWItoDT do not have this property... tempvmagn = sqrt(coorded[i][j][k][0]*coorded[i][j][k][0]+ coorded[i][j][k][1]*coorded[i][j][k][1]+ coorded[i][j][k][2]*coorded[i][j][k][2]); if( tempvmagn<0.99 ) for( m=0 ; m<3 ; m++ ) coorded[i][j][k][m]/= tempvmagn; INDEX[i][j][k][0] =idx; // first value is the index itself if( ROI1[idx]==1 ) INDEX[i][j][k][1]=1; // second value identifies ROI1 mask else INDEX[i][j][k][1]=0; if( ROI2[idx]==1 ) INDEX[i][j][k][2]=1; // third value identifies ROI2 mask else INDEX[i][j][k][2]=0; // fourth value will be counter for number of kept tracks // passing through INDEX[i][j][k][3] = 0; idx+= 1; } // ************************************************************* // ************************************************************* // Beginning of main loop // ************************************************************* // ************************************************************* Numtract = 0; ave_tract_len = 0.; ave_tract_len_phys = 0.; sprintf(OUT_bin,"%s.trk",prefix); if( (fout0 = fopen(OUT_bin, "w")) == NULL) { fprintf(stderr, "Error opening file %s.",OUT_bin); exit(16); } fwrite(&header1,sizeof(tv_io_header),1,fout0); if (get_tract_verb()) { INFO_message("Begin tracking..."); } tb = AppCreateBundle(NULL, 0, NULL, insetFA); // start bundle id = 0; for( k=0 ; k<Dim[2] ; k++ ) for( j=0 ; j<Dim[1] ; j++ ) for( i=0 ; i<Dim[0] ; i++ ) if(coorded[i][j][k][3] >= MinFA) { for( ii=0 ; ii<SeedPerV[0] ; ii++ ) for( jj=0 ; jj<SeedPerV[1] ; jj++ ) for( kk=0 ; kk<SeedPerV[2] ; kk++ ) { in[0] = i; in[1] = j; in[2] = k; physin[0] = ((float) in[0] + (0.5 + (float) ii)/SeedPerV[0])*Ledge[0]; physin[1] = ((float) in[1] + (0.5 + (float) jj)/SeedPerV[1])*Ledge[1]; physin[2] = ((float) in[2] + (0.5 + (float) kk)/SeedPerV[2])*Ledge[2]; len_forw = TrackIt(coorded, in, physin, Ledge, Dim, MinFA, MaxAng, ArrMax, Tforw, flTforw, 1, phys_forw); // reset, because it's changed in TrackIt func in[0] = i; in[1] = j; in[2] = k; physin[0] = ((float) in[0] + (0.5 + (float) ii)/SeedPerV[0])*Ledge[0]; physin[1] = ((float) in[1] + (0.5 + (float) jj)/SeedPerV[1])*Ledge[1]; physin[2] = ((float) in[2] + (0.5 + (float) kk)/SeedPerV[2])*Ledge[2]; len_back = TrackIt(coorded, in, physin, Ledge, Dim, MinFA, MaxAng, ArrMax, Tback, flTback, -1, phys_back); KEEPIT = 0; // a simple switch totlen = len_forw+len_back-1; // NB: overlap of starts totlen_phys = phys_forw[0] + phys_back[0]; if( totlen_phys >= MinL ) { // glue together for simpler notation later for( n=0 ; n<len_back ; n++) { // all of this rr = len_back-n-1; // read in backward for(m=0;m<3;m++) Ttot[rr][m] = Tback[n][m]; } for( n=1 ; n<len_forw ; n++){// skip first->overlap rr = n+len_back-1; // put after for(m=0;m<3;m++) Ttot[rr][m] = Tforw[n][m]; } // <<So close and orthogonal condition>>: // test projecting ends, to see if they abut ROI. for(m=0;m<3;m++) { //actual projected ends end[1][m] = 2*Ttot[totlen-1][m]-Ttot[totlen-2][m]; end[0][m] = 2*Ttot[0][m]-Ttot[1][m]; // default choice, just retest known ends // as default test_ind[1][m] = test_ind[0][m] = Ttot[0][m]; } tt = Create_Tract(len_back, flTback, len_forw, flTforw, id, insetFA); ++id; if (LOG_TYPE == -1) { KEEPIT = 1; } else { inroi1 = 0; // check forw for( n=0 ; n<len_forw ; n++) { if(INDEX[Tforw[n][0]][Tforw[n][1]][Tforw[n][2]][1]==1){ inroi1 = 1; break; } else continue; } if( inroi1==0 ){// after 1st half, check 2nd half for( m=0 ; m<len_back ; m++) { if(INDEX[Tback[m][0]][Tback[m][1]][Tback[m][2]][1]==1){ inroi1 = 1; break; } else continue; } } // after 1st&2nd halves, check bound/neigh if( inroi1==0 ) { if(INDEX[test_ind[1][0]][test_ind[1][1]][test_ind[1][2]][1]==1) inroi1 = 1; if(INDEX[test_ind[0][0]][test_ind[0][1]][test_ind[0][2]][1]==1) inroi1 = 1; } if( ((LOG_TYPE ==0) && (inroi1 ==0)) || ((LOG_TYPE ==1) && (inroi1 ==1))) { // have to check in ROI2 inroi2 = 0; // check forw for( n=0 ; n<len_forw ; n++) { if(INDEX[Tforw[n][0]][Tforw[n][1]][Tforw[n][2]][2]==1){ inroi2 = 1; break; } else continue; } //after 1st half, check 2nd half if( inroi2==0 ) { for( m=0 ; m<len_back ; m++) { if(INDEX[Tback[m][0]][Tback[m][1]][Tback[m][2]][2]==1){ inroi2 = 1; break; } else continue; } } // after 1st&2nd halves, check bound/neigh if( inroi2==0 ) { if(INDEX[test_ind[1][0]][test_ind[1][1]][test_ind[1][2]][2]==1) inroi2 = 1; if(INDEX[test_ind[0][0]][test_ind[0][1]][test_ind[0][2]][2]==1) inroi2 = 1; } // for both cases, need to see it here to keep if( inroi2 ==1 ) KEEPIT = 1; // otherwise, it's gone } else if((LOG_TYPE ==0) && (inroi1 ==1)) KEEPIT = 1; } } // by now, we *know* if we're keeping this or not. if( KEEPIT == 1 ) { tb = AppCreateBundle(tb, 1, tt, NULL); tt = Free_Tracts(tt, 1); READS_in = totlen; fwrite(&READS_in,sizeof(READS_in),1,fout0); for( n=0 ; n<len_back ; n++) { //put this one in backwords, to make it connect m = len_back - 1 - n; for(aa=0 ; aa<3 ; aa++) { // recenter phys loc for trackvis, if nec... // just works this way (where they define // origin) READS_fl = flTback[m][aa]; if(!TV_switch[aa]) READS_fl = Ledge[aa]*Dim[aa]-READS_fl; fwrite(&READS_fl,sizeof(READS_fl),1,fout0); } mm = INDEX[Tback[m][0]][Tback[m][1]][Tback[m][2]][0]; READS_fl =THD_get_voxel(insetFA, mm, 0); // FA fwrite(&READS_fl,sizeof(READS_fl),1,fout0); READS_fl =THD_get_voxel(insetMD, mm, 0); // MD fwrite(&READS_fl,sizeof(READS_fl),1,fout0); READS_fl =THD_get_voxel(insetL1, mm, 0); // L1 fwrite(&READS_fl,sizeof(READS_fl),1,fout0); // count this voxel for having a tract INDEX[Tback[m][0]][Tback[m][1]][Tback[m][2]][3]+= 1; } for( m=1 ; m<len_forw ; m++) { for(aa=0 ; aa<3 ; aa++) { // recenter phys loc for trackvis, if nec... READS_fl = flTforw[m][aa]; if(!TV_switch[aa]) READS_fl = Ledge[aa]*Dim[aa]-READS_fl; fwrite(&READS_fl,sizeof(READS_fl),1,fout0); } mm = INDEX[Tforw[m][0]][Tforw[m][1]][Tforw[m][2]][0]; READS_fl =THD_get_voxel(insetFA, mm, 0); // FA fwrite(&READS_fl,sizeof(READS_fl),1,fout0); READS_fl =THD_get_voxel(insetMD, mm, 0); // MD fwrite(&READS_fl,sizeof(READS_fl),1,fout0); READS_fl =THD_get_voxel(insetL1, mm, 0); // L1 fwrite(&READS_fl,sizeof(READS_fl),1,fout0); // count this voxel for having a tract INDEX[Tforw[m][0]][Tforw[m][1]][Tforw[m][2]][3]+= 1; } ave_tract_len+= totlen; ave_tract_len_phys+= totlen_phys; Numtract+=1; } } } fclose(fout0); if (get_tract_verb()) { INFO_message("Done tracking, have %d tracks.", tb->N_tracts); Show_Taylor_Bundle(tb, NULL, 3); } if (!Write_Bundle(tb,prefix,mode)) { ERROR_message("Failed to write the bundle"); } // ************************************************************** // ************************************************************** // Some simple stats on ROIs and outputs // ************************************************************** // ************************************************************** for( k=0 ; k<Dim[2] ; k++ ) for( j=0 ; j<Dim[1] ; j++ ) for( i=0 ; i<Dim[0] ; i++ ) { if( INDEX[i][j][k][3]>=1 ) { tempMD = THD_get_voxel(insetMD,INDEX[i][j][k][0],0); tempFA = THD_get_voxel(insetFA,INDEX[i][j][k][0],0); tempL1 = THD_get_voxel(insetL1,INDEX[i][j][k][0],0); tempRD = 0.5*(3*tempMD-tempL1); roi3_mu_MD+= tempMD; roi3_mu_FA+= tempFA; roi3_mu_L1+= tempL1; roi3_mu_RD+= tempRD; roi3_sd_MD+= tempMD*tempMD; roi3_sd_FA+= tempFA*tempFA; roi3_sd_L1+= tempL1*tempL1; roi3_sd_RD+= tempRD*tempRD; roi3_ct+= 1; } } if(roi3_ct > 0 ) { // !!!! make into afni file roi3_mu_MD/= (float) roi3_ct; roi3_mu_FA/= (float) roi3_ct; roi3_mu_L1/= (float) roi3_ct; roi3_mu_RD/= (float) roi3_ct; roi3_sd_MD-= roi3_ct*roi3_mu_MD*roi3_mu_MD; roi3_sd_FA-= roi3_ct*roi3_mu_FA*roi3_mu_FA; roi3_sd_L1-= roi3_ct*roi3_mu_L1*roi3_mu_L1; roi3_sd_RD-= roi3_ct*roi3_mu_RD*roi3_mu_RD; roi3_sd_MD/= (float) roi3_ct-1; roi3_sd_FA/= (float) roi3_ct-1; roi3_sd_L1/= (float) roi3_ct-1; roi3_sd_RD/= (float) roi3_ct-1; roi3_sd_MD = sqrt(roi3_sd_MD); roi3_sd_FA = sqrt(roi3_sd_FA); roi3_sd_L1 = sqrt(roi3_sd_L1); roi3_sd_RD = sqrt(roi3_sd_RD); sprintf(OUT_tracstat,"%s.stats",prefix); if( (fout0 = fopen(OUT_tracstat, "w")) == NULL) { fprintf(stderr, "Error opening file %s.",OUT_tracstat); exit(19); } fprintf(fout0,"%d\t%d\n",Numtract,roi3_ct); fprintf(fout0,"%.3f\t%.3f\n",ave_tract_len/Numtract, ave_tract_len_phys/Numtract); // as usual, these next values would have to be divided by the // bval to get their actual value in standard phys units fprintf(fout0,"%.4f\t%.4f\n",roi3_mu_FA,roi3_sd_FA); fprintf(fout0,"%.4f\t%.4f\n",roi3_mu_MD,roi3_sd_MD); fprintf(fout0,"%.4f\t%.4f\n",roi3_mu_RD,roi3_sd_RD); fprintf(fout0,"%.4f\t%.4f\n",roi3_mu_L1,roi3_sd_L1); fclose(fout0); sprintf(prefix_map,"%s_MAP",prefix); sprintf(prefix_mask,"%s_MASK",prefix); outsetMAP = EDIT_empty_copy( mset1 ) ; EDIT_dset_items( outsetMAP , ADN_datum_all , MRI_short , ADN_prefix , prefix_map , ADN_none ) ; if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetMAP)) ) ERROR_exit("Can't overwrite existing dataset '%s'", DSET_HEADNAME(outsetMAP)); outsetMASK = EDIT_empty_copy( mset1 ) ; EDIT_dset_items( outsetMASK , ADN_datum_all , MRI_byte , ADN_prefix , prefix_mask , ADN_none ) ; if(!THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetMASK)) ) ERROR_exit("Can't overwrite existing dataset '%s'", DSET_HEADNAME(outsetMASK)); m=0; for( k=0 ; k<Dim[2] ; k++ ) for( j=0 ; j<Dim[1] ; j++ ) for( i=0 ; i<Dim[0] ; i++ ) { temp_arr[m]=INDEX[i][j][k][3]; if(temp_arr[m]>0.5) temp_byte[m]=1; else temp_byte[m]=0; m++; } // re-orient the data as original inputs // (this function copies the pointer) EDIT_substitute_brick(outsetMAP, 0, MRI_short, temp_arr); temp_arr=NULL; if(TV_switch[0] || TV_switch[1] || TV_switch[2]) { dsetn = r_new_resam_dset(outsetMAP, NULL, 0.0, 0.0, 0.0, header1.voxel_order, RESAM_NN_TYPE, NULL, 1, 0); DSET_delete(outsetMAP); outsetMAP=dsetn; dsetn=NULL; } EDIT_dset_items( outsetMAP , ADN_prefix , prefix_map , ADN_none ) ; THD_load_statistics(outsetMAP ); if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetMAP)) ) ERROR_exit("Can't overwrite existing dataset '%s'", DSET_HEADNAME(outsetMAP)); tross_Make_History( "3dTrackID" , argc , argv , outsetMAP) ; THD_write_3dim_dataset(NULL, NULL, outsetMAP, True); // re-orient the data as original inputs EDIT_substitute_brick(outsetMASK, 0, MRI_byte, temp_byte); temp_byte=NULL; if(TV_switch[0] || TV_switch[1] || TV_switch[2]) { dsetn = r_new_resam_dset(outsetMASK, NULL, 0.0, 0.0, 0.0, header1.voxel_order, RESAM_NN_TYPE, NULL, 1, 0); DSET_delete(outsetMASK); outsetMASK=dsetn; dsetn=NULL; } EDIT_dset_items( outsetMASK , ADN_prefix , prefix_mask , ADN_none ) ; THD_load_statistics(outsetMASK); if(!THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetMASK)) ) ERROR_exit("Can't overwrite existing dataset '%s'", DSET_HEADNAME(outsetMASK)); tross_Make_History( "3dTrackID" , argc , argv , outsetMASK) ; THD_write_3dim_dataset(NULL, NULL, outsetMASK, True); INFO_message("Number of tracts found = %d",Numtract) ; } else INFO_message("\n No Tracts Found!!!\n"); // ************************************************************ // ************************************************************ // Freeing // ************************************************************ // ************************************************************ // !!! need to free afni-sets? DSET_delete(insetFA); DSET_delete(insetMD); DSET_delete(insetL1); DSET_delete(insetV1); DSET_delete(insetEXTRA); //DSET_delete(outsetMAP); //DSET_delete(outsetMASK); DSET_delete(mset2); DSET_delete(mset1); free(prefix); free(insetV1); free(insetFA); free(mset1); free(mset2); free(insetEXTRA); free(ROI1); free(ROI2); free(temp_byte); for( i=0 ; i<ArrMax ; i++) { free(Tforw[i]); free(Tback[i]); free(flTforw[i]); free(flTback[i]); } free(Tforw); free(Tback); free(flTforw); free(flTback); for( i=0 ; i<Dim[0] ; i++) for( j=0 ; j<Dim[1] ; j++) for( k=0 ; k<Dim[2] ; k++) free(coorded[i][j][k]); for( i=0 ; i<Dim[0] ; i++) for( j=0 ; j<Dim[1] ; j++) free(coorded[i][j]); for( i=0 ; i<Dim[0] ; i++) free(coorded[i]); free(coorded); for( i=0 ; i<Dim[0] ; i++) for( j=0 ; j<Dim[1] ; j++) for( k=0 ; k<Dim[2] ; k++) free(INDEX[i][j][k]); for( i=0 ; i<Dim[0] ; i++) for( j=0 ; j<Dim[1] ; j++) free(INDEX[i][j]); for( i=0 ; i<Dim[0] ; i++) free(INDEX[i]); free(INDEX); free(temp_arr); // need to free for( i=0 ; i<2*ArrMax ; i++) free(Ttot[i]); free(Ttot); //free(mode); return 0; }
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[] ) { int iarg=1 , dcode=0 , maxgap=2 , nftot=0 ; char * prefix="zfillin" , * dstr=NULL; THD_3dim_dataset * inset , * outset ; MRI_IMAGE * brim ; int verb=0 ; if( argc < 2 || strcmp(argv[1],"-help") == 0 ){ printf("Usage: 3dZFillin [options] dataset\n" "Extracts 1D rows in the given direction from a 3D dataset,\n" "searches for zeros that are 'close' to nonzero values in the row,\n" "and replaces the zeros with the closest nonzero neighbor.\n" "\n" "OPTIONS:\n" " -maxstep N = set the maximum distance to a neighbor\n" " [default=2].\n" " -dir D = set the direction of fill to 'D', which can\n" " be one of the following:\n" " A-P, P-A, I-S, S-I, L-R, R-L, x, y, z\n" " The first 6 are anatomical directions;\n" " the last 3 are reference to the dataset\n" " internal axes [no default value].\n" " -prefix P = set the prefix to 'P' for the output dataset.\n" "\n" "N.B.: * If the input dataset has more than one sub-brick,\n" " only the first one will be processed.\n" " * At this time, 3dZFillin only works on byte-valued datasets\n" "\n" "This program's only purpose is to fill up the Talairach Daemon\n" "bricks obtained from the UT San Antonio database.\n" "\n" ) ; PRINT_COMPILE_DATE ; exit(0) ; } mainENTRY("3dZFillin main") ; machdep() ; AFNI_logger("3dZfillin",argc,argv) ; PRINT_VERSION(3dZFillin") ; /*-- scan args --*/ while( iarg < argc && argv[iarg][0] == '-' ){ if( strncmp(argv[iarg],"-verb",5) == 0 ){ verb++ ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-prefix") == 0 ){ prefix = argv[++iarg] ; if( !THD_filename_ok(prefix) ){ fprintf(stderr,"*** Illegal string after -prefix!\n"); exit(1) ; } iarg++ ; continue ; } if( strcmp(argv[iarg],"-maxstep") == 0 ){ maxgap = strtol( argv[++iarg] , NULL , 10 ) ; if( maxgap < 1 ){ fprintf(stderr,"*** Illegal value after -maxgap!\n"); exit(1); } iarg++ ; continue ; } if( strcmp(argv[iarg],"-dir") == 0 ){ dstr = argv[++iarg] ; iarg++ ; continue ; } fprintf(stderr,"*** Illegal option: %s\n",argv[iarg]) ; exit(1) ; } if( dstr == NULL ){ fprintf(stderr,"*** No -dir option on command line!\n"); exit(1); } if( iarg >= argc ){ fprintf(stderr,"*** No input dataset on command line!\n"); exit(1); } inset = THD_open_dataset( argv[iarg] ) ; if( inset == NULL ){ fprintf(stderr,"*** Can't open dataset %s\n",argv[iarg]); exit(1); } outset = EDIT_empty_copy( inset ) ; EDIT_dset_items( outset , ADN_prefix , prefix , ADN_none ) ; if( THD_deathcon() && THD_is_file( DSET_HEADNAME(outset) ) ){ fprintf(stderr,"** Output file %s exists -- cannot overwrite!\n", DSET_HEADNAME(outset) ) ; exit(1) ; } tross_Copy_History( inset , outset ) ; tross_Make_History( "3dZFillin" , argc,argv , outset ) ; if( DSET_NVALS(inset) > 1 ){ fprintf(stderr,"++ WARNING: input dataset has more than one sub-brick!\n"); EDIT_dset_items( outset , ADN_ntt , 0 , ADN_nvals , 1 , ADN_none ) ; } if( DSET_BRICK_TYPE(outset,0) != MRI_byte ){ fprintf(stderr,"*** This program only works on byte datasets!\n"); exit(1) ; } switch( *dstr ){ case 'x': dcode = 1 ; break ; case 'y': dcode = 2 ; break ; case 'z': dcode = 3 ; break ; default: if( *dstr == ORIENT_tinystr[outset->daxes->xxorient][0] || *dstr == ORIENT_tinystr[outset->daxes->xxorient][1] ) dcode = 1 ; if( *dstr == ORIENT_tinystr[outset->daxes->yyorient][0] || *dstr == ORIENT_tinystr[outset->daxes->yyorient][1] ) dcode = 2 ; if( *dstr == ORIENT_tinystr[outset->daxes->zzorient][0] || *dstr == ORIENT_tinystr[outset->daxes->zzorient][1] ) dcode = 3 ; break ; } if( dcode == 0 ){ fprintf(stderr,"*** Illegal -dir direction!\n") ; exit(1) ; } if( verb ) fprintf(stderr,"++ Direction = axis %d in dataset\n",dcode) ; DSET_load(inset) ; CHECK_LOAD_ERROR(inset) ; brim = mri_copy( DSET_BRICK(inset,0) ) ; DSET_unload(inset) ; EDIT_substitute_brick( outset , 0 , brim->kind , mri_data_pointer(brim) ) ; nftot = THD_dataset_zfillin( outset , 0 , dcode , maxgap ) ; fprintf(stderr,"++ Number of voxels filled = %d\n",nftot) ; if (DSET_write(outset) != False) { fprintf(stderr,"++ output dataset: %s\n",DSET_BRIKNAME(outset)) ; exit(0) ; } else { fprintf(stderr, "** 3dZFillin: Failed to write output!\n" ) ; exit(1) ; } }
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) ; }