/* * 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); }
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); }
SEXP R_SUMA_HistString (SEXP SCallingFunc, SEXP Sarg, SEXP Shold) { char *CallingFunc=NULL; SEXP Rname = R_NilValue; char *fname = NULL, *hold=NULL, **arg=NULL, *res=NULL; int debug=0, nprot=0, narg=0, i= 0; if (!debug) debug = get_odebug(); if (isNull(SCallingFunc) || isNull(Sarg)) { ERROR_message("Null input to R_SUMA_HistString"); return(Rname); } /* get the executable name */ PROTECT(SCallingFunc = AS_CHARACTER(SCallingFunc)); ++nprot; fname = R_alloc(strlen(CHAR(STRING_ELT(SCallingFunc,0)))+1, sizeof(char)); strcpy(fname, CHAR(STRING_ELT(SCallingFunc,0))); if (debug) INFO_message("filename %s\n", fname); /* get the arg */ PROTECT(Sarg = AS_CHARACTER(Sarg)); ++nprot; narg = (LENGTH(Sarg)); arg = (char **)calloc(narg+1, sizeof(char *)); if (fname) arg[0] = strdup(fname); else arg[0] = strdup("UnChevalSansNom"); for (i=1; i<=narg; ++i) { arg[i] = (char *)calloc(strlen(CHAR(STRING_ELT(Sarg,i-1)))+1, sizeof(char)); strcpy(arg[i], CHAR(STRING_ELT(Sarg,i-1))); if (debug) INFO_message("arg %d/%d %s\t", i, narg, arg[i]); } /* any old history ? */ if (!isNull(Shold)) { PROTECT(Shold = AS_CHARACTER(Shold)); ++nprot; hold = R_alloc(strlen(CHAR(STRING_ELT(Shold,0)))+1, sizeof(char)); strcpy(hold, CHAR(STRING_ELT(Shold,0))); if (debug) INFO_message("hold %s\n", hold); } if (( res = SUMA_HistString (fname, narg+1, arg, hold))) { PROTECT(Rname = allocVector(STRSXP, 1)); ++nprot; SET_STRING_ELT(Rname, 0, mkChar(res)); if (debug) INFO_message("hist is %s\n", res); SUMA_free(res); res=NULL; } else { ERROR_message("Call to SUMA_HistString %s failed", fname); } for (i=0; i<=narg; ++i) { if (arg[i]) free(arg[i]); } free(arg); arg=NULL; UNPROTECT(nprot); return(Rname); }
SEXP R_SUMA_ParseModifyName(SEXP Sfname, SEXP Swhat, SEXP Sval, SEXP Scwd) { SEXP Rname = R_NilValue; char *fname = NULL, *what=NULL, *val=NULL, *cwd=NULL, *res=NULL; int debug=0, nprot=0; if (!debug) debug = get_odebug(); if (isNull(Sfname) || isNull(Swhat) || isNull(Sval)) { ERROR_message("Null input to R_SUMA_ModifyName"); return(Rname); } /* get the filename */ PROTECT(Sfname = AS_CHARACTER(Sfname)); ++nprot; fname = R_alloc(strlen(CHAR(STRING_ELT(Sfname,0)))+1, sizeof(char)); strcpy(fname, CHAR(STRING_ELT(Sfname,0))); if (debug) INFO_message("filename %s\n", fname); /* get the what */ PROTECT(Swhat = AS_CHARACTER(Swhat)); ++nprot; what = R_alloc(strlen(CHAR(STRING_ELT(Swhat,0)))+1, sizeof(char)); strcpy(what, CHAR(STRING_ELT(Swhat,0))); if (debug) INFO_message("what %s\n", what); /* get the val */ PROTECT(Sval = AS_CHARACTER(Sval)); ++nprot; val = R_alloc(strlen(CHAR(STRING_ELT(Sval,0)))+1, sizeof(char)); strcpy(val, CHAR(STRING_ELT(Sval,0))); if (debug) INFO_message("val %s\n", val); /* get the cwd */ if (!isNull(Scwd)) { PROTECT(Scwd = AS_CHARACTER(Scwd)); ++nprot; cwd = R_alloc(strlen(CHAR(STRING_ELT(Scwd,0)))+1, sizeof(char)); strcpy(cwd, CHAR(STRING_ELT(Scwd,0))); if (debug) INFO_message("cwd %s\n", cwd); } if (debug) INFO_message("Modifying %s\n", fname); if ((res = SUMA_ModifyName(fname, what, val, cwd))) { PROTECT(Rname = allocVector(STRSXP, 1)); ++nprot; SET_STRING_ELT(Rname, 0, mkChar(res)); SUMA_free(res); res=NULL; } else { ERROR_message("Call to SUMA_ModifyName %s %s %s failed", fname, what, val); } UNPROTECT(nprot); return(Rname); }
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); }
/* * A hole is defined as a connected set of zero voxels that does * not reach an edge. * * The core functionality was added to libmri.a in THD_mask_fill_holes. */ int fill_holes(THD_3dim_dataset * dset, int verb) { short * sptr; /* to for filling holes */ byte * bmask; /* computed result */ int nfilled; int nx, ny, nz, nvox, index, fill=0; ENTRY("fill_holes"); bmask = THD_makemask(dset, 0, 1, 0); /* copy input as byte mask */ nx = DSET_NX(dset); ny = DSET_NY(dset); nz = DSET_NZ(dset); nvox = DSET_NVOX(dset); /* created filled mask */ nfilled = THD_mask_fill_holes(nx,ny,nz, bmask, verb); if( nfilled < 0 ) { ERROR_message("failed to fill holes"); RETURN(1); } /* apply to short volume */ sptr = DBLK_ARRAY(dset->dblk, 0); for( index = 0; index < nvox; index++ ) if( !sptr[index] && bmask[index] ) { fill++; sptr[index] = 1; } if(verb>2) INFO_message("final check: fill=%d, nfilled=%d", fill, nfilled); 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) ; }
void AFNI_coord_filer_setup( Three_D_View *im3d ) { char ename[32] , *eval ; int ic ; ENTRY("AFNI_coord_filer_setup") ; if( !IM3D_OPEN(im3d) ) EXRETURN ; ic = AFNI_controller_index(im3d) ; if( ic < 0 || ic >= MAX_CONTROLLERS || fpc[ic] != NULL ) EXRETURN ; sprintf(ename,"AFNI_FILE_COORDS_%c",abet[ic]) ; eval = my_getenv(ename) ; if( eval == NULL || *eval == '\0' ){ fpc[ic] = NULL ; EXRETURN ; } if( strcmp(eval,"-") == 0 || strncmp(eval,"stdout",6) == 0 ) fpc[ic] = stdout ; else { fpc[ic] = fopen( eval , "w" ) ; if( fpc[ic] == NULL ){ ERROR_message("Unable to open file %s from %s",eval,ename) ; EXRETURN ; } } AFNI_receive_init( im3d , RECEIVE_VIEWPOINT_MASK , AFNI_filer_viewpoint_CB , im3d , "AFNI_filer_viewpoint_CB" ) ; INFO_message("Logging [%c] viewpoint changes to '%s'",abet[ic],eval) ; EXRETURN ; }
int main( int argc , char *argv[] ) { int ndset=0 , ii ; THD_3dim_dataset **dset ; if( argc < 3 || strcasecmp(argv[1],"-help") == 0 ){ printf( "** Program 3dConformist reads in a collection of datasets and\n" " zero pads them to the same size.\n" "** The output volume size is the smallest region that includes\n" " all datasets (i.e., the minimal covering box).\n" "** If the datasets cannot be processed (e.g., different grid\n" " spacings), then nothing will happen except for error messages.\n" "** The purpose of this program is to be used in scripts that\n" " process lots of datasets and needs to make them all conform\n" " to the same size for collective voxel-wise analyses.\n" "** The input datasets ARE ALTERED (embiggened)! <<<<<<------******\n" " Therefore, don't use this program casually.\n" ) ; exit(0) ; } mainENTRY("3dConformist") ; machdep() ; PRINT_VERSION("3dConformist") ; ndset = argc-1 ; dset = (THD_3dim_dataset **)malloc(sizeof(THD_3dim_dataset *)*ndset) ; for( ii=0 ; ii < ndset ; ii++ ){ dset[ii] = THD_open_dataset(argv[ii+1]) ; CHECK_OPEN_ERROR(dset[ii],argv[ii+1]) ; } ii = THD_conformist(ndset,dset,CONFORM_REWRITE,NULL) ; switch(ii){ default: INFO_message ("3dConformist: Re-wrote %d datasets",ii) ; break ; case 0: INFO_message ("3dConformist: all datasets matched OK") ; break ; case -1: ERROR_message("3dConformist: bad input") ; break ; case -2: ERROR_message("3dConformist: bad inputs") ; break ; case -3: ERROR_message("3dConformist: can't match grids") ; break ; } exit(0) ; }
int write_results(options_t * opts) { FILE * fp; int c; ENTRY("write_results"); if( ! opts->result ) { ERROR_message("no results to write!"); RETURN(1); } if( ! opts->prefix ) fp = stdout; else if ( !strcmp(opts->prefix, "-") ) fp = stdout; else if ( !strcmp(opts->prefix, "stdout") ) fp = stdout; else if ( !strcmp(opts->prefix, "stderr") ) fp = stderr; else { fp = fopen(opts->prefix, "w"); if( ! fp ) { ERROR_message("failed to open '%s' for writing", opts->prefix); RETURN(1); } } if( opts->verb ) { if ( fp == stdout ) INFO_message("writing to stdout..."); else if( fp == stdout ) INFO_message("writing to stderr..."); else if( opts->prefix ) INFO_message("writing to '%s'...", opts->prefix); else INFO_message("writing to unknown?!?"); } /* actually write results */ for( c=0; c < opts->nt; c++ ) fprintf(fp, "%f\n", opts->result[c]); if( fp != stdout && fp != stderr ) fclose(fp); RETURN(0); }
/*--------------- main routine ---------------*/ int main( int argc, char *argv[] ) { THD_3dim_dataset * countset=NULL; param_t * params = &g_params; int rv, limit; if( argc < 1 ) { show_help(); return 0; } /* general stuff */ mainENTRY("3dmask_tool"); machdep(); AFNI_logger("3dmask_tool",argc,argv); enable_mcw_malloc(); /* process options: a negative return is considered an error */ rv = process_opts(params, argc, argv); if( rv ) RETURN(rv < 0); /* open, convert to byte, zeropad, dilate, unzeropad */ if( process_input_dsets(params) ) RETURN(1); /* create mask count dataset and return num volumes (delete old dsets) */ if( count_masks(params->dsets, params->ndsets, params->verb, &countset, ¶ms->nvols) ) RETURN(1); /* limit to frac of nvols (if not counting, convert to 0/1 mask) */ limit = ceil((params->frac>1) ? params->frac : params->nvols*params->frac ); if( params->verb ) INFO_message("frac %g over %d volumes gives min count %d\n", params->frac, params->nvols, limit); if( limit <= 0 ) limit = 1; /* if not counting, result is binary 0/1 */ if( limit_to_frac(countset, limit, params->count, params->verb) ) RETURN(1); /* maybe apply dilations to output */ if( params->RESD.num > 0 ) { countset = apply_dilations(countset, ¶ms->RESD, 0, params->verb); if( !countset ) RETURN(1); } /* maybe fill any remaining holes */ if( params->fill ) if ( fill_holes(countset, params->verb) ) RETURN(1); /* create output */ if( write_result(params, countset, argc, argv) ) RETURN(1); /* clean up a little memory */ DSET_delete(countset); free(params->dsets); RETURN(0); }
/* * check count against limit * - clear small values * - if not count, set large values to 1 */ int limit_to_frac(THD_3dim_dataset * cset, int limit, int count, int verb) { short * dptr; int index, nsub, nsuper; ENTRY("limit_to_frac"); if( ! ISVALID_3DIM_DATASET(cset) ) { ERROR_message("invalid count dataset"); RETURN(1); } else if( DSET_BRICK_TYPE(cset, 0) != MRI_short ) { ERROR_message("count dataset not of type short"); RETURN(1); } if(verb > 1) INFO_message("limiting to %d (count = %d)\n",limit,count); /* note how many voxels are affected, just for kicks */ dptr = DBLK_ARRAY(cset->dblk, 0); nsub = nsuper = 0; for(index = 0; index < DSET_NVOX(cset); index++, dptr++) { if( ! *dptr ) continue; /* 0, so skip */ else if( *dptr < limit ) { /* small, so clear */ *dptr = 0; nsub++; } else { /* big enough */ if ( ! count ) *dptr = 1; nsuper++; } } /* entertain the user */ if( verb ) INFO_message("voxel limits: %d clipped, %d survived, %d were zero\n", nsub, nsuper, DSET_NVOX(cset)-nsub-nsuper); RETURN(0); }
static void toy_tsfunc( double tzero, double tdelta , int npts, float ts[], double ts_mean , double ts_slope , void *ud, int nbriks, float *val ) { static complex *comp_array=NULL; float mag=0, pow=0, pow6=0; int jj; TOY_UD *rpud = (TOY_UD *)ud; if( val == NULL ){ INFO_message("toy_tsfunc: %s notification call, npts=%d\n", npts?"Start":"End", npts); if( npts > 0 ){ /* the "start notification" */ /* This is when you perform any setup you don't want to repeat each time the function is called for a new voxel. Such a setup typically involves allocating for temporary arrays */ /* allocate for fft array */ comp_array = (complex *) calloc( sizeof(complex) , rpud->nfft); } else { /* the "end notification" */ /* Last call, meant for cleanup */ if (comp_array) free(comp_array); comp_array = NULL; } return ; } /* if we get here then we have data to process */ /* Load time series */ for( jj=0 ; jj < npts ; jj++ ) { comp_array[jj].r = ts[jj]; comp_array[jj].i = 0.0f ; } /* zero pad */ for( jj=npts ; jj < rpud->nfft ; jj++ ) comp_array[jj].r = comp_array[jj].i = 0.0f ; csfft_cox( -1 , rpud->nfft, comp_array ) ; /* DFT */ for( jj=0 ; jj < rpud->nfft ; jj++ ) { mag = CABS(comp_array[jj]) ; pow += mag*mag; if (jj<rpud->nfft/6) pow6 += mag*mag ; } val[0] = pow; val[1] = pow6; return ; }
void AFNI_pbar_lock_carryout( Three_D_View *im3d ) { Three_D_View *qq3d ; static int busy = 0 ; /* !=0 if this routine is "busy" */ int glock , cc,ii ; ENTRY("AFNI_pbar_lock_carryout") ; /* first, determine if there is anything to do */ glock = GLOBAL_library.controller_lock ; /* not a handgun */ if( busy ) EXRETURN; /* routine already busy */ if( glock == 0 ) EXRETURN; /* nothing to do */ if( !IM3D_OPEN(im3d) ) EXRETURN; /* bad input */ if( GLOBAL_library.ignore_lock ) EXRETURN; /* ordered not to do anything */ if( !AFNI_check_pbar_lock() ) EXRETURN; /* not locked? */ ii = AFNI_controller_index(im3d) ; /* which one am I? */ if( ii < 0 ) EXRETURN ; /* nobody? bad input! */ if( ((1<<ii) & glock) == 0 ) EXRETURN ; /* input not locked */ #if 0 INFO_message("AFNI_pbar_lock_carryout( %d ) ******************* ",ii) ; TRACEBACK ; #endif /* something to do? */ busy = 1 ; /* don't let this routine be called recursively */ /* loop through other controllers: for those that ARE open, ARE NOT the current one, and ARE locked */ for( cc=0 ; cc < MAX_CONTROLLERS ; cc++ ){ qq3d = GLOBAL_library.controllers[cc] ; /* controller */ if( IM3D_OPEN(qq3d) && qq3d != im3d && ((1<<cc) & glock) != 0 ){ #if 0 ININFO_message(" equate_pbars( %d )",cc) ; #endif AFNI_equate_pbars( qq3d , im3d ) ; } } busy = 0 ; /* OK, let this routine be activated again */ EXRETURN ; }
/* convert by hand, since no scaling will be done * (byte seems inappropriate and float does not need it) */ int write_result(param_t * params, THD_3dim_dataset * oset, int argc, char * argv[]) { short * sptr; int nvox = DSET_NVOX(oset), ind; ENTRY("write_results"); EDIT_dset_items(oset, ADN_prefix, params->prefix, ADN_none); if( params->verb ) INFO_message("writing result %s...\n", DSET_PREFIX(oset)); switch( params->datum ) { default: ERROR_exit("invalid datum for result: %d", params->datum); case MRI_short: break; /* nothing to do */ case MRI_float: { float * data = (float *)malloc(nvox*sizeof(float)); sptr = DBLK_ARRAY(oset->dblk, 0); if( ! data ) ERROR_exit("failed to alloc %d output floats\n", nvox); for( ind = 0; ind < nvox; ind++ ) data[ind] = (float)sptr[ind]; EDIT_substitute_brick(oset, 0, params->datum, data); } break; case MRI_byte: { byte * data = (byte *)malloc(nvox*sizeof(byte)); int errs = 0; sptr = DBLK_ARRAY(oset->dblk, 0); if( ! data ) ERROR_exit("failed to alloc %d output bytes\n", nvox); for( ind = 0; ind < nvox; ind++ ) { if( sptr[ind] > 255 ) { /* watch for overflow */ data[ind] = (byte)255; errs++; } else data[ind] = (byte)sptr[ind]; } EDIT_substitute_brick(oset, 0, params->datum, data); if(errs) WARNING_message("convert to byte: %d truncated voxels",errs); } break; } tross_Make_History( "3dmask_tool", argc, argv, oset ); DSET_write(oset); WROTE_DSET(oset); RETURN(0); }
SEXP getListElement(SEXP list, const char *str) { int debug=0; R_len_t i; SEXP elmt = R_NilValue, names = getAttrib(list, R_NamesSymbol); if (!debug) debug = get_odebug(); for ( i = 0; i < length(list); i++) { if (debug) INFO_message("Element %d/%d: named %s\n", i, length(list), CHAR(STRING_ELT(names, i))); if(strcmp(CHAR(STRING_ELT(names, i)), str) == 0) { elmt = VECTOR_ELT(list, i); break; } } return elmt; }
void AFNI_all_locks_carryout( Three_D_View *im3d ) { static int busy = 0 ; /* !=0 if this routine is "busy" */ ENTRY("AFNI_all_locks_carryout") ; if( busy || !IM3D_VALID(im3d) ) EXRETURN ; if( GLOBAL_library.ignore_lock ) EXRETURN ; #if 0 INFO_message("AFNI_all_locks_carryout: im3d index = %d",AFNI_controller_index(im3d)) ; #endif AFNI_lock_carryout ( im3d ) ; AFNI_time_lock_carryout ( im3d ) ; AFNI_thresh_lock_carryout( im3d ) ; AFNI_pbar_lock_carryout ( im3d ) ; AFNI_range_lock_carryout ( im3d ) ; AFNI_sleep(1) ; busy = 0 ; EXRETURN ; }
void EDIT_misfit_report( char *name, int ib, int nxyz, float fac, short *sar, float *far ) { float mf ; int im ; static char *msg[5] = { "* Caution" , "** Take Care" , "*** Beware" , "**** Red Alert ****" , "***** Purple Alert! *****" } ; static int first=1 ; mf = 100.0f * EDIT_scale_misfit( nxyz , fac , sar , far ) ; if( mf <= 9.0f ) return ; /* OK */ if( mf <= 13.0f ) im = 0 ; else if( mf <= 19.0f ) im = 1 ; else if( mf <= 27.0f ) im = 2 ; else if( mf <= 39.0f ) im = 3 ; else im = 4 ; if( first ) WARNING_message("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); WARNING_message("%s[%d] scale to shorts mean misfit error = %.1f%% -- %s", name , ib , mf , msg[im] ) ; if( first ) { ININFO_message("a) Numerical precision has been lost when truncating results\n" " from 32-bit floating point to 16-bit integers (shorts)." ); ININFO_message("b) Consider writing datasets out in float format.\n" " In most AFNI programs, use the '-float' option."); ININFO_message("c) This warning is a new message, but is an old issue\n" " that arises when storing results in an integer format." ); ININFO_message("d) Don't panic! These messages likely originate in peripheral\n" " or unimportant voxels. They mean that you must examine your output.\n" " \"Assess the situation and keep a calm head about you,\n" " because it doesn't do anybody any good to panic.\"\n" ) ; INFO_message("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); first = 0 ; } return ; }
void RT_test_callback(void *junk) { RT_status *rts = GLOBAL_library.realtime_status ; int cc , nval,nbr ; if( rts == NULL ){ ERROR_message("bad call to RT_test_callback"); return; } INFO_message("RT_test_callback: numchan=%d status=%d numdset=%d", rts->numchan , rts->status , rts->numdset ) ; for( cc=0 ; cc < rts->numdset ; cc++ ){ /* print out some dataset info */ if( !ISVALID_DSET(rts->dset[cc]) ){ ININFO_message(" dset[%d] invalid!",cc) ; /* should never happen */ } else { nval = DSET_NVALS(rts->dset[cc]) ; /* number of bricks */ nbr = THD_count_databricks(rts->dset[cc]->dblk) ; /* number with data */ ININFO_message(" dset[%d] '%s': nvals=%d nbr=%d", cc , DSET_HEADNAME(rts->dset[cc]) , nval,nbr ) ; } } return ; }
/* * create empty count dataset * for each input dataset and each sub-volume * for each voxel, if set: increment * close datasets as they are processed */ int count_masks(THD_3dim_dataset * dsets[], int ndsets, int verb, /* inputs */ THD_3dim_dataset ** cset, int * nvol) /* outputs */ { THD_3dim_dataset * dset; short * counts = NULL; /* will become data for returned cset */ byte * bptr; /* always points to mask volumes */ int nxyz, iset, ivol, ixyz; ENTRY("count_masks"); if( !dsets || !cset || !nvol ) ERROR_exit("NULL inputs to count_masks"); if( ndsets <= 0 ) { ERROR_message("count_masks: no input datasets"); RETURN(1); } *nvol = 0; nxyz = DSET_NVOX(dsets[0]); /* allocate memory for the counts */ counts = (short *)calloc(nxyz, sizeof(short)); if( !counts ) ERROR_exit("failed to malloc %d shorts", nxyz); /* for each volume of each dataset, count set voxels */ for( iset=0; iset < ndsets; iset++ ) { dset = dsets[iset]; *nvol += DSET_NVALS(dset); /* accumulate num volumes */ /* for each volume in this dataset, count set voxels */ for( ivol=0; ivol < DSET_NVALS(dset); ivol++ ) { if( DSET_BRICK_TYPE(dset, ivol) != MRI_byte ) ERROR_exit("in count_masks with non-byte data (set %d, vol %d)", iset, ivol); bptr = DBLK_ARRAY(dset->dblk, ivol); for( ixyz = 0; ixyz < nxyz; ixyz++ ) if( bptr[ixyz] ) counts[ixyz]++; } if( iset > 0 ) DSET_delete(dset); /* close the first one at end */ } /* dataset */ if( verb > 1 ) { int maxval; for( maxval=counts[0], ixyz=1; ixyz < nxyz; ixyz++ ) if( counts[ixyz] > maxval ) maxval = counts[ixyz]; INFO_message("counted %d mask volumes in %d datasets (%d voxels)\n", *nvol, ndsets, nxyz); INFO_message(" (maximum overlap = %d)\n", maxval); } if( *nvol >= (1<<15) ) WARNING_message("too many volumes to count as shorts: %d", *nvol); /* create output dataset */ *cset = EDIT_empty_copy(dsets[0]); EDIT_dset_items(*cset, ADN_nvals, 1, ADN_ntt, 0, ADN_none); EDIT_substitute_brick(*cset, 0, MRI_short, counts); DSET_delete(dsets[0]); /* now finished with first dataset */ RETURN(0); }
/* * 1. zeropad (if needed for dilations) * 2. make byte copy of dataset (if not already) * 3. dilate (using binary mask) * 4. if not converting, modify original data * 5. undo any zeropad * 6. return new dataset (might be same as old) * * dilations are passed as a list of +/- integers (- means erode) * * convert: flag specifying whether dset should be converted to MRI_byte * * note: the dilations list should not be long (does more than 2 even * make any sense?), but here they will be treated generically * - foreach dilation: dilate or erode, as specified by sign */ THD_3dim_dataset * apply_dilations(THD_3dim_dataset * dset, int_list * D, int convert, int verb) { THD_3dim_dataset * dnew = NULL; byte * bdata = NULL; int index, ivol, id, dsize, datum, pad; int nx, ny, nz, nvox; ENTRY("apply_dilations"); if( !dset || !D ) ERROR_exit("missing inputs to apply_dilations"); /* note and apply any needed zeropadding */ pad = needed_padding(D); if(verb > 3 && pad) INFO_message("padding by %d (for dilations)", pad); if( pad ) dnew = THD_zeropad(dset, pad, pad, pad, pad, pad, pad, "pad", 0); else dnew = dset; /* note geometry */ nx = DSET_NX(dnew); ny = DSET_NY(dnew); nz = DSET_NZ(dnew); nvox = nx*ny*nz; /* now apply the actual dilations */ if(verb>1) INFO_message("applying dilation list to dataset"); for( ivol=0; ivol < DSET_NVALS(dnew); ivol++ ) { datum = DSET_BRICK_TYPE(dnew, ivol); /* if non-byte data (short/float), make byte mask of volume */ if( datum == MRI_byte ) bdata = DBLK_ARRAY(dnew->dblk, ivol); else if ( datum == MRI_float || datum == MRI_short ) bdata = THD_makemask(dnew, ivol, 1, 0); else { ERROR_message("invalid datum for result: %d", datum); RETURN(NULL); } if( !bdata ) { ERROR_message("failed to make as mask"); RETURN(NULL); } for( index=0; index < D->num; index++ ) { dsize = D->list[index]; if(verb>2) INFO_message("... dilating vol %d by %d\n", ivol, dsize); if( dsize > 0 ) { for( id=0; id < dsize; id++ ) THD_mask_dilate(nx, ny, nz, bdata, 1); } else if( dsize < 0 ) { for( id=0; id > dsize; id-- ) THD_mask_erode_sym(nx, ny, nz, bdata, 1); } } /* if we are converting, just replace the old data */ if( convert && (datum == MRI_short || datum == MRI_float) ) { if( verb > 2 ) INFO_message("applying byte result from dilate"); EDIT_substitute_brick(dnew, ivol, MRI_byte, bdata); /* explicit set needed on an Fedora 8 system? 5 Jun 2012 */ DSET_BRICK_TYPE(dnew, ivol) = MRI_byte; continue; /* so nothing more to do */ } /* if short or float data, apply mask changes to data */ if( datum == MRI_short ) { short * dptr = DBLK_ARRAY(dnew->dblk, ivol); int nfill=0; if( verb > 2 ) INFO_message("applying dilate result to short data"); for( index = 0; index < nvox; index++ ) if( ! dptr[index] && bdata[index] ){ dptr[index] = 1; nfill++; } if( verb > 1 ) INFO_message("AD: filled %d voxels", nfill); free(bdata); } else if( datum == MRI_float ) { float * dptr = DBLK_ARRAY(dnew->dblk, ivol); if( verb > 2 ) INFO_message("applying dilate result to float data"); for( index = 0; index < nvox; index++ ) if( ! dptr[index] && bdata[index] ) dptr[index] = 1.0; free(bdata); } } /* undo any zeropadding (delete original and temporary datasets) */ if( pad ) { DSET_delete(dset); dset = THD_zeropad(dnew, -pad, -pad, -pad, -pad, -pad, -pad, "pad", 0); DSET_delete(dnew); dnew = dset; } RETURN(dnew); }
MRI_shindss * GRINCOR_read_input( char *fname ) { NI_element *nel=NULL ; char *dfname=NULL , *atr ; NI_float_array *facar ; NI_int_array *nvar, *nnode=NULL, *ninmask=NULL; MRI_shindss *shd ; long long nbytes_needed , nbytes_dfname=0 ; int fdes ; void *var ; int ids , nvmax , nvtot ; int datum , datum_size ; char *geometry_string=NULL ; THD_3dim_dataset *tdset=NULL; int nvox; int no_ivec=0 , *ivec=NULL , *nvals=NULL , nvec,ndset ; float *fac=NULL ; NI_str_array *slabar=NULL ; if( fname == NULL || *fname == '\0' ) GQUIT(NULL) ; /* get data element */ if (!THD_is_ondisk(fname)) GQUIT("not on disk") ; nelshd = nel = NI_read_element_fromfile(fname) ; if( nel == NULL || nel->type != NI_ELEMENT_TYPE ) GQUIT("not properly formatted") ; if( strcmp(nel->name,"3dGroupInCorr") != 0 ) GQUIT("data element name is not '3dGroupInCorr'") ; /* no data vector ==> using all voxels */ no_ivec = ( nel->vec_num < 1 || nel->vec_len < 1 || nel->vec_typ[0] != NI_INT ) ; /* number of vectors in each dataset */ atr = NI_get_attribute(nel,"nvec"); if( atr == NULL ) GQUIT("nvec attribute missing?") ; nvec = (int)strtod(atr,NULL) ; if( nvec < 2 || (!no_ivec && nel->vec_len != nvec) ) GQUIT("nvec attribute has illegal value") ; /* number of datasets */ atr = NI_get_attribute(nel,"ndset"); if( atr == NULL ) GQUIT("ndset attribute missing") ; ndset = (int)strtod(atr,NULL) ; if( ndset < 1 ) GQUIT("ndset attribute has illegal value") ; /* number of time points in each dataset (varies with dataset) */ atr = NI_get_attribute(nel,"nvals"); if( atr == NULL ) GQUIT("nvals attribute missing") ; nvar = NI_decode_int_list(atr,",") ; if( nvar == NULL || nvar->num < ndset ) GQUIT("nvals attribute doesn't match ndset") ; nvals = nvar->ar ; nvar->ar = NULL ; NI_delete_int_array(nvar) ; nvmax = nvtot = nvals[0] ; for( ids=1 ; ids < ndset ; ids++ ){ /* Feb 2011 */ nvtot += nvals[ids] ; if( nvals[ids] > nvmax ) nvmax = nvals[ids] ; } /* dataset labels [23 May 2010] */ atr = NI_get_attribute(nel,"dset_labels") ; if( atr != NULL ){ slabar = NI_decode_string_list(atr,";,") ; if( slabar == NULL || slabar->num < ndset ) GQUIT("dset_labels attribute invalid") ; } /* datum of datasets */ atr = NI_get_attribute(nel,"datum") ; if( atr != NULL && strcasecmp(atr,"byte") == 0 ){ datum = 1 ; datum_size = sizeof(sbyte) ; } else { datum = 2 ; datum_size = sizeof(short) ; } /* number of bytes needed: sizeof(datum) * number of vectors per dataset * number of datasets * sum of per dataset vector lengths */ nbytes_needed = 0 ; for( ids=0 ; ids < ndset ; ids++ ) nbytes_needed += nvals[ids] ; nbytes_needed *= ((long long)nvec) * datum_size ; if( nbytes_needed >= twogig && ( sizeof(void *) < 8 || sizeof(size_t) < 8 ) ) /* too much for 32-bit */ GQUIT("datafile size exceeds 2 GB -- you need a 64-bit computer!") ; /* scale factor for each dataset */ atr = NI_get_attribute(nel,"fac") ; if( atr == NULL ) GQUIT("fac attribute missing") ; facar = NI_decode_float_list(atr,",") ; if( facar == NULL || facar->num < ndset ) GQUIT("can't decode fac attribute") ; fac = facar->ar ; facar->ar = NULL ; NI_delete_float_array(facar) ; for( ids=0 ; ids < ndset ; ids++ ) if( fac[ids] <= 0.0f ) fac[ids] = 1.0f ; /* grid definition */ atr = NI_get_attribute(nel,"geometry") ; if( atr == NULL ) GQUIT("geometry attribute missing") ; geometry_string = strdup(atr) ; tdset = EDIT_geometry_constructor( geometry_string , "GrpInCorr" ) ; if( tdset == NULL ) GQUIT("can't decode geometry attribute") ; nvox = DSET_NVOX(tdset) ; if( no_ivec && nvox != nvec ) GQUIT("geometry attribute doesn't match nvec attribute") ; if( !no_ivec && nvox < nvec ) GQUIT("geometry attribute specifies too few voxels") ; /* name of data file: check its size against what's needed */ #if 0 atr = NI_get_attribute(nel,"datafile") ; if( atr != NULL ){ dfname = strdup(atr) ; nbytes_dfname = THD_filesize(dfname) ; if( nbytes_dfname <= 0 && strstr(dfname,"/") != NULL ){ char *tnam = THD_trailname(atr,0) ; nbytes_dfname = THD_filesize(tnam) ; if( nbytes_dfname > 0 ){ free(dfname); dfname = strdup(tnam); } } } #endif if( nbytes_dfname <= 0 && strstr(fname,".niml") != NULL ){ if( dfname != NULL ) free(dfname) ; dfname = strdup(fname) ; strcpy(dfname+strlen(dfname)-5,".data") ; nbytes_dfname = THD_filesize(dfname) ; } if( nbytes_dfname <= 0 ){ char mess[THD_MAX_NAME+256] ; sprintf(mess,"datafile is missing (%s)",dfname) ; GQUIT(mess) ; } else if( nbytes_dfname < nbytes_needed ){ char mess[THD_MAX_NAME+1024] ; sprintf(mess,"datafile %s has %s bytes but needs at least %s", dfname , commaized_integer_string(nbytes_dfname) , commaized_integer_string(nbytes_needed) ) ; GQUIT(mess) ; } else { INFO_message("EIC: data file %s found with %s bytes of data", dfname , commaized_integer_string(nbytes_dfname) ) ; } fdes = open( dfname , O_RDWR ) ; if( fdes < 0 ){ char mess[THD_MAX_NAME+256] ; sprintf(mess,"can't open datafile (%s)",dfname) ; GQUIT(mess) ; } NI_set_attribute( nelshd , "datafile" , dfname ) ; /* ivec[i] is the voxel spatial index of the i-th vector */ if( no_ivec ){ ivec = NULL ; /* means all voxels: ivec[i] == i */ } else { ivec = (int *)nel->vec[0] ; /* copy pointer */ nel->vec[0] = NULL ; /* NULL out in element so won't be free-ed */ } /* And stuff for LR surface pairs ZSS Jan 09*/ if ((atr=NI_get_attribute(nel,"LRpair_nnode"))) { nnode = NI_decode_int_list(atr,",") ; } if ((atr=NI_get_attribute(nel,"LRpair_ninmask"))) { ninmask = NI_decode_int_list(atr,",") ; } /* create output struct */ shd = (MRI_shindss *)malloc(sizeof(MRI_shindss)) ; shd->nvals = nvals ; shd->nvals_max = nvmax ; shd->nvals_tot = nvtot ; shd->nvec = nvec ; shd->ndset = ndset ; shd->geometry_string = geometry_string ; shd->tdset = tdset ; shd->dfname = dfname ; shd->nvox = nvox ; shd->nx = DSET_NX(tdset); shd->ny = DSET_NY(tdset); shd->nz = DSET_NZ(tdset); shd->ivec = ivec ; shd->fac = fac ; /* and surface fields... ZSS Jan 09 */ if (nnode) { if (nnode->num != 2) GQUIT("LRpair_nnode must have 2 values"); shd->nnode[0] = nnode->ar[0]; shd->nnode[1] = nnode->ar[1]; NI_delete_int_array(nnode); nnode=NULL; } else { shd->nnode[0] = shd->nnode[1] = -1 ; } if (ninmask) { if (ninmask->num != 2) GQUIT("LRpair_ninmask must have 2 values"); shd->ninmask[0] = ninmask->ar[0]; shd->ninmask[1] = ninmask->ar[1]; NI_delete_int_array(ninmask); ninmask=NULL; } else { shd->ninmask[0] = shd->ninmask[1] = -1 ; } /*--- 07 Apr 2010: setup default use list (all of them) ---*/ shd->nuse = ndset ; shd->use = (int *)malloc(sizeof(int)*ndset) ; for( ids=0 ; ids < ndset ; ids++ ) shd->use[ids] = ids ; shd->dslab = (slabar != NULL) ? slabar->str : NULL ; /* 23 May 2010 */ /*--- now have to map data from disk ---*/ var = mmap( 0 , (size_t)nbytes_needed , PROT_WRITE , THD_MMAP_FLAG , fdes , 0 ) ; close(fdes) ; /* close file descriptor does not unmap data */ if( var == (void *)(-1) ){ /* this is bad */ ERROR_message( "EIC: file %s: can't mmap() datafile -- memory space exhausted?" , dfname ) ; free(shd) ; return NULL ; } /*-- create array of pointers to each dataset's data array --*/ shd->datum = datum ; if( datum == 2 ){ /* shorts */ shd->sv = (short **)malloc(sizeof(short *)*ndset) ; shd->bv = NULL ; shd->sv[0] = (short *)var ; for( ids=1 ; ids < ndset ; ids++ ) shd->sv[ids] = shd->sv[ids-1] + nvals[ids-1]*nvec ; } else { /* sbytes */ shd->sv = NULL ; shd->bv = (sbyte **)malloc(sizeof(sbyte *)*ndset) ; shd->bv[0] = (sbyte *)var ; for( ids=1 ; ids < ndset ; ids++ ) shd->bv[ids] = shd->bv[ids-1] + nvals[ids-1]*nvec ; } shd->nbytes = nbytes_needed ; return shd ; }
int main( int argc , char *argv[] ) { MRI_shindss *shd ; int ids , nopt , kk ; char *prefix = "EIC" ; char *fname=NULL , *buf ; MRI_vectim *mv ; THD_3dim_dataset *dset ; /*--- official AFNI startup stuff ---*/ mainENTRY("3dExtractGroupInCorr"); machdep(); AFNI_logger("3dExtractGroupInCorr",argc,argv); PRINT_VERSION("3dExtractGroupInCorr"); AUTHOR("RW Cox"); /*-- process options --*/ nopt = 1 ; while( nopt < argc && argv[nopt][0] == '-' ){ if( strcasecmp(argv[nopt],"-prefix") == 0 ){ nopt++ ; if( strcasecmp(argv[nopt],"NULL") == 0 ) prefix = NULL ; else prefix = strdup(argv[nopt]) ; nopt++ ; continue ; } ERROR_message("Unknown option: '%s'",argv[nopt]) ; suggest_best_prog_option(argv[0], argv[nopt]); exit(1); } if( argc < 2 ){ usage_3dExtractGroupInCorr(2) ; exit(0) ; } /* check for errors */ if( nopt >= argc ) ERROR_exit("No input filename on command line?!") ; /*-- read input file --*/ fname = strdup(argv[nopt]) ; if( STRING_HAS_SUFFIX(fname,".data") ){ strcpy(fname+strlen(fname)-5,".niml") ; WARNING_message("EIC: Replaced '.data' with '.niml' in filename") ; } else if( STRING_HAS_SUFFIX(fname,".grpincorr") ){ fname = (char *)realloc(fname,strlen(fname)+16) ; strcat(fname,".niml") ; INFO_message("EIC: Added '.niml' to end of filename") ; } else if( STRING_HAS_SUFFIX(fname,".grpincorr.") ){ fname = (char *)realloc(fname,strlen(fname)+16) ; strcat(fname,"niml") ; INFO_message("EIC: Added 'niml' to end of filename") ; } shd = GRINCOR_read_input( fname ) ; if( shd == NULL ) ERROR_exit("EIC: Cannot continue after input error") ; INFO_message("EIC: file opened, contains %d datasets, %d time series, %s bytes", shd->ndset , shd->nvec , commaized_integer_string(shd->nbytes) ) ; /*-- process input file --*/ fprintf(stderr,"++ %d datasets: ",shd->ndset) ; for( ids=0 ; ids < shd->ndset ; ids++ ){ fprintf(stderr,"%d",ids+1) ; dset = GRINCOR_extract_dataset( shd, ids, prefix ) ; fprintf(stderr,".") ; DSET_write(dset) ; DSET_delete(dset) ; } fprintf(stderr,"\n") ; exit(0) ; }
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) ; }
/* ---------------------------------------------------------------------- * fill the param_t struct * return 1 on (acceptable) termination * 0 on continue * -1 on error */ int process_opts(param_t * params, int argc, char * argv[] ) { int ac, ival; ENTRY("process_opts"); memset(params, 0, sizeof(param_t)); /* init everything to 0 */ params->inputs = NULL; params->prefix = "combined_mask"; init_int_list(¶ms->IND, 0); init_int_list(¶ms->RESD, 0); params->frac = -1.0; params->datum = MRI_byte; params->verb = 1; params->ndsets = 0; if( argc < 2 ) { show_help(); RETURN(1); } ac = 1; while( ac < argc ) { /* check for terminal options */ if( strcmp(argv[ac],"-help") == 0 ) { show_help(); RETURN(1); } else if( strcmp(argv[ac],"-hist") == 0 ) { int c, len = sizeof(g_history)/sizeof(char *); for( c = 0; c < len; c++) fputs(g_history[c], stdout); putchar('\n'); RETURN(1); } else if( strcmp(argv[ac],"-ver") == 0 ) { puts(g_version); RETURN(1); } /* the remaining options are alphabetical */ else if( strcmp(argv[ac],"-count") == 0 ) { params->count = 1; ac++; continue; } else if( strcmp(argv[ac],"-datum") == 0 ) { if( ++ac >= argc ) ERROR_exit("need argument after '-datum'"); /* output datum can be byte, short or float */ if ( ! strcmp(argv[ac],"byte") ) params->datum = MRI_byte; else if( ! strcmp(argv[ac],"short") ) params->datum = MRI_short; else if( ! strcmp(argv[ac],"float") ) params->datum = MRI_float; else ERROR_exit("-datum '%s' is not supported", argv[ac]); ac++; continue; } /* read in a list of dilations (negatives are erosions) */ else if( strncmp(argv[ac],"-dilate_in", 10) == 0 ) { char * rptr; /* return pointer for strtol */ int ndilates = 0; if( ++ac >= argc ) ERROR_exit("need argument after '-dilate_inputs'"); ival = strtol(argv[ac], &rptr, 10); while( ac < argc && rptr > argv[ac] ) { if( ! add_to_int_list(¶ms->IND, ival, 1) ) RETURN(-1); ndilates++; if( ++ac >= argc ) break; ival = strtol(argv[ac], &rptr, 10); } if( ndilates == 0 ) ERROR_exit("no integral dilations found after -dilate_inputs"); /* ac is already past last number */ continue; } /* read in a list of dilations (negatives are erosions) */ else if( strncmp(argv[ac],"-dilate_result", 11) == 0 ) { char * rptr; /* return pointer for strtol */ int ndilates = 0; if( ++ac >= argc ) ERROR_exit("need argument after '-dilate_result'"); ival = strtol(argv[ac], &rptr, 10); while( ac < argc && rptr > argv[ac] ) { if( ! add_to_int_list(¶ms->RESD, ival, 1) ) RETURN(-1); ndilates++; if( ++ac >= argc ) break; ival = strtol(argv[ac], &rptr, 10); } if( ndilates == 0 ) ERROR_exit("no integral dilations found after -dilate_result"); /* ac is already past last number */ continue; } /* overlap: -frac, -inter, -union */ else if( strncmp(argv[ac],"-frac", 5) == 0 ) { if( ++ac >= argc ) ERROR_exit("need argument after '-frac'"); params->frac = atof(argv[ac]); if( params->frac < 0.0 ) ERROR_exit("have -frac < 0 (from %s)", argv[ac]); ac++; continue; } else if( strncmp(argv[ac],"-inter", 6) == 0 ) { params->frac = 1.0; ac++; continue; } else if( strcmp(argv[ac],"-union") == 0 ) { params->frac = 0.0; ac++; continue; } else if( strcmp(argv[ac],"-fill_holes") == 0 ) { params->fill = 1; ac++; continue; } else if( strncmp(argv[ac],"-inputs", 4) == 0 ) { /* store list of names from argv */ ac++; params->inputs = argv+ac; /* pointer to first name */ params->ndsets = 0; /* number of datasets */ while( ac < argc && argv[ac][0] != '-' ){ params->ndsets++; ac++; } if( params->ndsets == 0 ) ERROR_exit("need datasets after '-inputs'"); /* already incremented: ac++; */ continue; } else if( strcmp(argv[ac],"-prefix") == 0 ) { if( ++ac >= argc ) ERROR_exit("need argument after '-prefix'"); params->prefix = argv[ac]; if( !THD_filename_ok(params->prefix) ) ERROR_exit("Illegal name after -prefix: %s", argv[ac]); ac++; continue; } else if( strcmp(argv[ac],"-quiet") == 0 ) { /* -quiet means -verb 0 */ params->verb = 0; ac++; continue; } else if( strcmp(argv[ac],"-verb") == 0 ) { if( ++ac >= argc ) ERROR_exit("need argument after '-verb'"); params->verb = atoi(argv[ac]); ac++; continue; } ERROR_message("** unknown option '%s'\n",argv[ac]); RETURN(-1); } if( !dilations_are_valid(& params->IND) || !dilations_are_valid(& params->RESD) ) RETURN(-1); if( params->ndsets <= 0 ) ERROR_exit("missing -input dataset list"); if( !params->prefix ) ERROR_exit("missing -prefix option"); if( params->frac < 0.0 ) { if( params->verb ) INFO_message("no -frac option: defaulting to -union"); params->frac = 0.0; } if( params->verb > 1 ) INFO_message("%d datasets, frac = %g, %d IN dilation(s), %d OUT D(s)\n", params->ndsets, params->frac, params->IND.num, params->RESD.num); RETURN(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) ; }
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 powell_newuoa_constrained( int ndim, double *x, double *cost , double *xbot, double *xtop , int nrand, int nkeep, int ntry , double rstart , double rend , int maxcall , double (*ufunc)(int,double *) ) { integer n , npt , icode , maxfun ; doublereal rhobeg , rhoend , *w ; int ii,tt , tbest , ntot=0 , nx01 ; double **x01 , *x01val , vbest ; /*--- check inputs for stupidity ---*/ if( ndim < 1 ) return -2 ; if( x == NULL ) return -3 ; if( ufunc == NULL ) return -5 ; if( xbot == NULL || xtop == NULL ) return -6 ; /*--- edit inputs for idiocy ---*/ if( rstart <= rend || rstart <= 1.e-4 || rstart > 0.333 ){ rstart = 0.1 ; rend = 1.e-4 ; } /* if this call is totally vanilla, then call the older function */ if( nrand == 0 && nkeep == 0 && ntry < 2 ) return powell_newuoa_con( ndim , x,xbot,xtop , 0 , rstart,rend , maxcall , ufunc ) ; if( maxcall < 10+5*ndim ) maxcall = 10+5*ndim ; if( ntry < 1 ) ntry = 1 ; if( nkeep < 1 && nrand > 0 ) nkeep = 1 ; if( nkeep > 0 && nrand <= 2*nkeep ) nrand = 2*nkeep+1 ; /*--- set up newuoa parameters and workspace ---*/ n = ndim ; npt = (int)(mfac*n+afac) ; if( npt < n+2 ) npt = n+2 ; icode = (n+1)*(n+2)/2 ; if( npt > icode ) npt = icode ; maxfun = maxcall ; rhobeg = (doublereal)rstart ; rhoend = (doublereal)rend ; icode = (npt+14)*(npt+n) + 3*n*(n+3)/2 + 666 ; w = (doublereal *)malloc(sizeof(doublereal)*icode) ; /* workspace */ userfun = ufunc ; /* store pointer to user's function in global variable */ /*-- To enforce constraints: (a) scale each variable to be in the range 0..1, in x01[] array; (b) in calfun_(), if an input variable drifts outside the 0..1 range, bring it back into that range with the PRED01() macro; (c) then scale that 0..1 value back to the 'true' value before calling ufunc() to evaluate objective function. -------*/ scalx = 1 ; /* signal to calfun_() to apply scaling */ sxmin = (double *)malloc(sizeof(double)*ndim) ; /* copy xbot for calfun_ */ sxsiz = (double *)malloc(sizeof(double)*ndim) ; /* = xtop - xbot */ sx = (double *)malloc(sizeof(double)*ndim) ; /* workspace for calfun_ */ for( ii=0 ; ii < ndim ; ii++ ){ sxmin[ii] = xbot[ii] ; sxsiz[ii] = xtop[ii] - xbot[ii]; if( sxsiz[ii] <= 0.0 ) sxsiz[ii] = 1.0 ; } /*-- set up the first starting vector from x[] array --*/ nx01 = nkeep+2 ; x01 = (double **)malloc(sizeof(double *)*nx01) ; /* array of vectors */ for( tt=0 ; tt < nx01 ; tt++ ) x01[tt] = (double *)malloc(sizeof(double)*ndim) ; /* tt-th keeper vector */ x01val = (double *)malloc(sizeof(double)*nx01) ; /* cost func values */ for( tt=0 ; tt < nx01 ; tt++ ) x01val[tt] = BIGVAL; /* mark as unready */ /* copy x[] into x01[0], scaling to 0..1 range */ for( ii=0 ; ii < ndim ; ii++ ){ x01[0][ii] = (x[ii] - sxmin[ii]) / sxsiz[ii] ; x01[0][ii] = PRED01(x01[0][ii]) ; /* make sure is in range 0..1 */ } (void)calfun_(&n,x01[0],x01val+0) ; /* value of keeper #0 = input vector */ ntot++ ; /* number of times calfun_() is called */ /*-- do a random search for the best starting vector? --*/ if( nrand > 0 ){ double *xtest , *qpar,*cpar , ftest , rb,re , dist ; int qq,jj ; integer mf ; static int seed=1 ; if( seed ){ srand48((long)time(NULL)+(long)getpid()); seed=0; } xtest = (double *)malloc(sizeof(double)*ndim) ; /* Step 1: search nrand start vectors, keeping the nkeep-th best values we find on the way. N.B.: we do NOT displace the input vector in x01[0]; therefore, there are nkeep+1 vectors being kept */ if( verb ) INFO_message("Powell: random search of %d vectors in %d-dim space",nrand,ndim); for( qq=0 ; qq < nrand ; qq++ ){ for( ii=0 ; ii < ndim ; ii++ ) xtest[ii] = drand48() ; /* random pt */ (void)calfun_(&n,xtest,&ftest) ; ntot++ ; /* eval cost func */ for( tt=1 ; tt <= nkeep ; tt++ ){ /* is this better than what */ if( ftest < x01val[tt] ){ /* we've seen thus far? */ for( jj=nkeep-1 ; jj >= tt ; jj-- ){ /* push those above #tt up */ memcpy( x01[jj+1] , x01[jj] , sizeof(double)*ndim ) ; /* in list */ x01val[jj+1] = x01val[jj] ; } memcpy( x01[tt] , xtest , sizeof(double)*ndim ) ; /* save in list */ x01val[tt] = ftest ; break ; /* breaking out of 'tt' loop, having put xtest in list */ } } } /* end of random search loop */ free((void *)xtest) ; /* don't need this no more */ /* count number that have valid cost function results */ for( tt=0 ; tt <= nkeep && x01val[tt] < BIGVAL ; tt++ ) ; /* nada */ nkeep = tt ; /** from now on, nkeep = actual number of keepers **/ /* Step 2a: do a little first round optimization on each of the keepers */ if( verb ) INFO_message("Powell: 1st round optimization on %d vectors",nkeep); rb = 0.05 ; re = 0.005 ; mf = 9*ndim+7 ; tbest = 0 ; vbest = BIGVAL ; for( tt=0 ; tt < nkeep ; tt++ ){ (void)newuoa_( &n, &npt, (doublereal *)x01[tt], &rb,&re,&mf,w,&icode ) ; for( ii=0 ; ii < ndim ; ii++ ) x01[tt][ii] = PRED01(x01[tt][ii]) ; (void)calfun_(&n,x01[tt],x01val+tt) ; ntot += icode+1 ; if( x01val[tt] < vbest ){ vbest = x01val[tt]; tbest = tt; } if( verb > 1 ) ININFO_message("%2d: cost = %g %c nfunc=%d",tt,x01val[tt],(tbest==tt)?'*':' ',icode) ; } /* Step 2b: sort results by new x01val costs */ qsort_doublestuff( nkeep , x01val , (void **)x01 ) ; /* Step 2c: cast out those that are too close to better vectors in the max-norm (we always keep the best vector in x01[0]) */ #undef DTHRESH #define DTHRESH 0.05 /* max-norm distance threshold for vector reject */ for( tt=1 ; tt < nkeep ; tt++ ){ qpar = x01[tt] ; /* do we keep this vector? */ for( jj=0 ; jj < tt ; jj++ ){ /* loop over previous keepers */ if( x01val[jj] >= BIGVAL ) continue ; /* already rejected */ cpar = x01[jj] ; /* compare qpar to cpar */ for( dist=0.0,ii=0 ; ii < ndim ; ii++ ){ re = fabs(cpar[ii]-qpar[ii]) ; dist = MAX(dist,re) ; } if( dist < DTHRESH ){ /* qpar is too close to cpar */ x01val[tt] = BIGVAL ; break ; /* reject qpar vector */ } } } /* Step 2d: sort again (so that the rejected ones rise to the top) */ qsort_doublestuff( nkeep , x01val , (void **)x01 ) ; for( tt=0 ; tt <= nkeep && x01val[tt] < BIGVAL ; tt++ ) ; /* nada */ nkeep = tt ; /* number of keepers that weren't rejected above */ if( ntry > nkeep ) ntry = nkeep ; } else { /*------ didn't do random search -----*/ ntry = 1 ; /* can only try the input x[] vector! */ } /****** fully optimize each of the first ntry-th vectors in x01[] ******/ if( verb ) INFO_message("Powell: 2nd round optimization on %d vectors",ntry) ; tbest = 0 ; vbest = BIGVAL ; for( tt=0 ; tt < ntry ; tt++ ){ (void)newuoa_( &n , &npt , (doublereal *)x01[tt] , &rhobeg , &rhoend , &maxfun , w , &icode ) ; for( ii=0 ; ii < ndim ; ii++ ) x01[tt][ii] = PRED01(x01[tt][ii]) ; (void)calfun_(&n,x01[tt],x01val+tt) ; ntot += icode+1 ; if( x01val[tt] < vbest ){ vbest = x01val[tt]; tbest = tt; } if( verb > 1 ) ININFO_message("%2d: cost = %g %c nfunc=%d",tt,x01val[tt],(tbest==tt)?'*':' ',icode) ; } /*-- Rescale bestest output vector back to 'true' range --*/ for( ii=0 ; ii < ndim ; ii++ ) x[ii] = sxmin[ii] + x01[tbest][ii] * sxsiz[ii] ; if( cost != NULL ) *cost = vbest ; /* save cost func */ /*-- toss the trash, and vamoose the ranch --*/ free((void *)sx); free((void *)sxsiz); free((void *)sxmin); sx = sxmin = sxsiz = NULL ; scalx = 0 ; for( tt=0 ; tt < nx01 ; tt++ ) free((void *)x01[tt]) ; free((void *)x01val); free((void *)x01); free((void *)w) ; return ntot ; }
int WB_netw_corr(int Do_r, int Do_Z, int HAVE_ROIS, char *prefix, int NIFTI_OUT, int *NROI_REF, int *Dim, double ***ROI_AVE_TS, int **ROI_LABELS_REF, THD_3dim_dataset *insetTIME, byte *mskd2, int Nmask, int argc, char *argv[]) { int i,j,k; float **AVE_TS_fl=NULL; // not great, but another format of TS char OUT_indiv0[300]; char OUT_indiv[300]; char OUT_indivZ[300]; MRI_IMAGE *mri=NULL; THD_3dim_dataset *OUT_CORR_MAP=NULL; THD_3dim_dataset *OUT_Z_MAP=NULL; float *zscores=NULL; int Nvox; Nvox = Dim[0]*Dim[1]*Dim[2]; // make average time series per voxel AVE_TS_fl = calloc( 1,sizeof(AVE_TS_fl)); for(i=0 ; i<1 ; i++) AVE_TS_fl[i] = calloc(Dim[3],sizeof(float)); if( (AVE_TS_fl == NULL) ) { fprintf(stderr, "\n\n MemAlloc failure (time series out).\n\n"); exit(123); } fprintf(stderr,"\nHAVE_ROIS=%d",HAVE_ROIS); for( k=0 ; k<HAVE_ROIS ; k++) { // each netw gets own file sprintf(OUT_indiv0,"%s_%03d_INDIV", prefix, k); mkdir(OUT_indiv0, 0777); for( i=0 ; i<NROI_REF[k] ; i++ ) { fprintf(stderr,"\nNROI_REF[%d]= %d",k,NROI_REF[k]); for( j=0 ; j<Dim[3] ; j++) AVE_TS_fl[0][j] = (float) ROI_AVE_TS[k][i][j]; if( NIFTI_OUT ) sprintf(OUT_indiv,"%s/WB_CORR_ROI_%03d.nii.gz", OUT_indiv0,ROI_LABELS_REF[k][i+1]); else sprintf(OUT_indiv,"%s/WB_CORR_ROI_%03d", OUT_indiv0,ROI_LABELS_REF[k][i+1]); mri = mri_float_arrays_to_image(AVE_TS_fl,Dim[3],1); OUT_CORR_MAP = THD_Tcorr1D(insetTIME, mskd2, Nmask, mri, "pearson", OUT_indiv); if(Do_r){ THD_load_statistics(OUT_CORR_MAP); tross_Copy_History( insetTIME , OUT_CORR_MAP ) ; tross_Make_History( "3dNetcorr", argc, argv, OUT_CORR_MAP ); if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(OUT_CORR_MAP)) ) ERROR_exit("Can't overwrite existing dataset '%s'", DSET_HEADNAME(OUT_CORR_MAP)); THD_write_3dim_dataset(NULL, NULL, OUT_CORR_MAP, True); INFO_message("Wrote dataset: %s\n",DSET_BRIKNAME(OUT_CORR_MAP)); } if(Do_Z){ if( NIFTI_OUT ) sprintf(OUT_indivZ,"%s/WB_Z_ROI_%03d.nii.gz", OUT_indiv0,ROI_LABELS_REF[k][i+1]); else sprintf(OUT_indivZ,"%s/WB_Z_ROI_%03d", OUT_indiv0,ROI_LABELS_REF[k][i+1]); OUT_Z_MAP = EDIT_empty_copy(OUT_CORR_MAP); EDIT_dset_items( OUT_Z_MAP, ADN_nvals, 1, ADN_datum_all , MRI_float , ADN_prefix , OUT_indivZ, ADN_none ) ; if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(OUT_Z_MAP)) ) ERROR_exit("Can't overwrite existing dataset '%s'", DSET_HEADNAME(OUT_Z_MAP)); zscores = (float *)calloc(Nvox,sizeof(float)); if( (zscores == NULL) ) { fprintf(stderr, "\n\n MemAlloc failure (zscores).\n\n"); exit(123); } for( j=0 ; j<Nvox ; j++ ) if( mskd2[j] ) // control for r ==1 BOBatanhf( THD_get_voxel(OUT_CORR_MAP, j, 0) ); /* if( THD_get_voxel(OUT_CORR_MAP, j, 0) > MAX_R ) zscores[j] = (float) atanh(MAX_R); else if ( THD_get_voxel(OUT_CORR_MAP, j, 0) < -MAX_R ) zscores[j] = (float) atanh(-MAX_R); else zscores[j] = (float) atanh(THD_get_voxel(OUT_CORR_MAP, j, 0));*/ EDIT_substitute_brick(OUT_Z_MAP, 0, MRI_float, zscores); zscores=NULL; THD_load_statistics(OUT_Z_MAP); tross_Copy_History(insetTIME, OUT_Z_MAP); tross_Make_History("3dNetcorr", argc, argv, OUT_Z_MAP); THD_write_3dim_dataset(NULL, NULL, OUT_Z_MAP, True); INFO_message("Wrote dataset: %s\n",DSET_BRIKNAME(OUT_Z_MAP)); DSET_delete(OUT_Z_MAP); free(OUT_Z_MAP); OUT_Z_MAP=NULL; } DSET_delete(OUT_CORR_MAP); free(OUT_CORR_MAP); OUT_CORR_MAP=NULL; } } free(zscores); mri_free(mri); for( i=0 ; i<1 ; i++) free(AVE_TS_fl[i]); free(AVE_TS_fl); RETURN(1); }
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) ; }