int THD_bandpass_remain_dim(int nx, float dt, float fbot, float ftop, int verb) { int nfft , jbot,jtop ; float df ; if( nx < 9 ) { if( verb ) WARNING_message("length %d too short for bandpassing", nx); return 0 ; } if( dt <= 0.0f ) dt = 1.0f ; if( fbot < 0.0f ) fbot = 0.0f ; if( ftop <= fbot ){ if( verb ) WARNING_message("bad bandpass frequencies (ftop<=fbot)"); return 0; } if( verb && dt > 60.0f ){ WARNING_message("Your bandpass timestep (%f) is high.\n" " Make sure units are 'sec', not 'msec'.\n" " This warning will not be repeated." , dt); } nfft = (nfft_fixed >= nx) ? nfft_fixed : csfft_nextup_even(nx) ; df = 1.0f / (nfft * dt) ; /* freq step */ jbot = (int)rint(fbot/df) ; /* band bot index */ jtop = (int)rint(ftop/df) ; /* band top index */ if( jtop >= nfft/2 ) jtop = nfft/2-1 ; if( jbot+1 >= jtop ){ if( verb ) WARNING_message("bandpass: fbot=%g and ftop=%g too close" " ==> jbot=%d jtop=%d [nfft=%d dt=%g]", fbot,ftop,jbot,jtop,nfft,dt) ; return 0 ; } return 2*(jtop-jbot+1); }
/* * for each input dataset name * open (check dims, etc.) * dilate (zeropad, make binary, dilate, unpad, apply) * fill list of bytemask datasets * * also, count total volumes */ int process_input_dsets(param_t * params) { THD_3dim_dataset * dset, * dfirst=NULL; int iset, nxyz; ENTRY("process_input_dsets"); if( !params ) ERROR_exit("NULL inputs to PID"); if( params->ndsets <= 0 ) { ERROR_message("process_input_dsets: no input datasets"); RETURN(1); } /* allocate space for dsets array */ params->dsets = (THD_3dim_dataset **)malloc(params->ndsets* sizeof(THD_3dim_dataset*)); if( !params->dsets ) ERROR_exit("failed to allocate dset pointers"); if( params->verb ) INFO_message("processing %d input datasets...", params->ndsets); /* warn user of dilations */ if(params->verb && params->ndsets) { int pad = needed_padding(¶ms->IND); INFO_message("padding all datasets by %d (for dilations)", pad); } /* process the datasets */ nxyz = 0; for( iset=0; iset < params->ndsets; iset++ ) { /* open and verify dataset */ dset = THD_open_dataset(params->inputs[iset]); if( !dset ) ERROR_exit("failed to open mask dataset '%s'", params->inputs[iset]); DSET_load(dset); CHECK_LOAD_ERROR(dset); if( params->verb>1 ) INFO_message("loaded dset %s, with %d volumes", DSET_PREFIX(dset), DSET_NVALS(dset)); if( nxyz == 0 ) { /* make an empty copy of the first dataset */ nxyz = DSET_NVOX(dset); dfirst = EDIT_empty_copy(dset); } /* check for consistency in voxels and grid */ if( DSET_NVOX(dset) != nxyz ) ERROR_exit("nvoxel mis-match"); if( ! EQUIV_GRIDS(dset, dfirst) ) WARNING_message("grid from dset %s does not match that of dset %s", DSET_PREFIX(dset), DSET_PREFIX(dfirst)); /* apply dilations to all volumes, returning bytemask datasets */ params->dsets[iset] = apply_dilations(dset, ¶ms->IND,1,params->verb); if( ! params->dsets[iset] ) RETURN(1); } DSET_delete(dfirst); /* and nuke */ RETURN(0); }
int mri_write_raw( char *fname , MRI_IMAGE *im ) { FILE *imfile ; void *data ; int dsize ; ENTRY("mri_write_raw") ; if( im == NULL || fname == NULL || fname[0] == '\0' ) RETURN( 0 ); dsize = im->pixel_size * im->nvox ; data = mri_data_pointer( im ) ; if( dsize <= 0 || data == NULL ) RETURN( 0 ); if( THD_is_file(fname) ) WARNING_message("Over-writing file %s",fname) ; imfile = fopen_maybe(fname) ; if( imfile == NULL ) RETURN(0) ; fwrite( data , 1 , dsize , imfile ) ; fclose_maybe( imfile ) ; RETURN( 1 ); }
// take a len=6 matr and an empt len =3 grad file, calc grads from matr int GradConv_Gsign_from_BmatA( float *grad, float *matr ) { int i; int signum[3] = {1,1,1}; if( (matr[0]<0) || (matr[1]<0) || (matr[2]<0) ) ERROR_exit("Matrices don't appear to be correct format-- check again") ; // get signs for grads for( i=0 ; i<3 ; i++) if( matr[3+i] < 0 ) signum[2-i] = -1; // if all neg, then same as having all pos because of symmetry still for( i=0 ; i<3 ; i++) if ( matr[i] >= 0 ) { grad[i] = (float) sqrt(matr[i]); grad[i]*= signum[i]; } else { WARNING_message("matrices don't appear to be correct format-- check again") ; grad[i] = 0; } return 1; }
void THD_vectim_localpv( MRI_vectim *mrv , float rad ) { unsigned short xran[3] = { 32701 , 22013 , 0x330e } ; MCW_cluster *nbhd ; int iv,kk,nn,nx,ny,nz,nxy , nind , *ind , xx,yy,zz , aa,bb,cc ; float *pv , *fv ; MRI_vectim *qrv ; /* workspace to hold results */ nbhd = MCW_spheremask( mrv->dx,mrv->dy,mrv->dz , rad ) ; if( nbhd->num_pt <= 1 ){ THD_vectim_normalize(mrv); return; } ind = (int *)malloc(sizeof(int)*nbhd->num_pt) ; pv = (float *)malloc(sizeof(float)*mrv->nvals) ; kk = thd_floatscan( mrv->nvec*mrv->nvals , mrv->fvec ) ; if( kk > 0 ) WARNING_message("fixed %d float error%s before localPV",kk,(kk==1)?"\0":"s"); qrv = THD_vectim_copy(mrv) ; /* 08 Apr 2010: workspace */ nx = mrv->nx ; ny = mrv->ny ; nz = mrv->nz ; nxy = nx*ny ; for( iv=0 ; iv < mrv->nvec ; iv++ ){ ind[0] = kk = mrv->ivec[iv] ; IJK_TO_THREE(kk,aa,bb,cc,nx,nxy) ; for( nind=nn=1 ; nn < nbhd->num_pt ; nn++ ){ xx = aa + nbhd->i[nn] ; if( xx < 0 || xx >= nx ) continue ; yy = bb + nbhd->j[nn] ; if( yy < 0 || yy >= ny ) continue ; zz = cc + nbhd->k[nn] ; if( zz < 0 || zz >= nz ) continue ; ind[nind] = THREE_TO_IJK(xx,yy,zz,nx,nxy) ; nind++ ; } nn = THD_vectim_subset_pv( mrv , nind,ind , pv , xran ) ; fv = VECTIM_PTR(qrv,iv) ; /* 08 Apr 2010: result goes in here, not mrv! */ if( nn > 0 ){ for( kk=0 ; kk < mrv->nvals ; kk++ ) fv[kk] = pv[kk] ; } else { /* should not happen */ THD_normalize( mrv->nvals , fv ) ; } } memcpy( mrv->fvec , qrv->fvec , sizeof(float)*mrv->nvec*mrv->nvals ) ; VECTIM_destroy(qrv) ; kk = thd_floatscan( mrv->nvec*mrv->nvals , mrv->fvec ) ; if( kk > 0 ) WARNING_message("fixed %d float error%s after localPV",kk,(kk==1)?"\0":"s"); KILL_CLUSTER(nbhd) ; free(ind) ; free(pv) ; return ; }
char *form_C_progopt_string(char *prog, char **ws, int N_ws) { char *sout=NULL, sbuf[128]; int maxch=0, i, jj, N_opts=0; NI_str_array *nisa=NULL; if (!prog || !ws) { return(NULL); } maxch = 256; for (i=0; i<N_ws; ++i) { if (ws[i]) { maxch+=strlen(ws[i])+10; if (strlen(ws[i]) > 127) { WARNING_message("Truncating atrocious option %s\n", ws[i]); ws[127] = '\0'; } } } if (!(sout = (char *)calloc((maxch+1), sizeof(char)))) { ERROR_message("Failed to allocate for %d chars!", maxch+1); return(NULL); } sout[0]='\0'; strncat(sout,"{ \"", maxch-1); strncat(sout,prog, maxch-strlen(sout)-1); strncat(sout,"\", \"", maxch-strlen(sout)-1); N_opts = 0; for (i=0; i<N_ws; ++i) { if (ws[i] && (nisa = NI_strict_decode_string_list(ws[i] ,"/"))) { for (jj=0; jj<nisa->num; ++jj) { if (ws[i][0]=='-' && nisa->str[jj][0] != '-') { snprintf(sbuf,127,"-%s; ", nisa->str[jj]); } else { snprintf(sbuf,127,"%s; ", nisa->str[jj]); } ++N_opts; strncat(sout,sbuf, maxch-strlen(sout)-1); NI_free(nisa->str[jj]); } if (nisa->str) NI_free(nisa->str); NI_free(nisa); nisa=NULL; } } sprintf(sbuf,"\", %d", N_opts); strncat(sout,sbuf, maxch-strlen(sout)-1); strncat(sout,"}", maxch-strlen(sout)-1); if (strlen(sout)>=maxch-1) { ERROR_message("Truncated complete string possible"); free(sout); sout=NULL; return(sout); } return(sout); }
// little dot product float CalcInnerProdAngle( float *A, float *B, int N ) { float out = 0., d1 = 0., d2 = 0; int i; int NEG = 0; out = SimpleDP(A,B,N); d1 = SimpleDP(A,A,N); d2 = SimpleDP(B,B,N); if( (d1<=0.0001) || (d2<=0.0001) ) { WARNING_message("It looks like there might be a b=0 gradient which got" "misclassified?? Near- (or equal-) zero magnitude."); out/= 1.; } else{ out/= sqrt(d1) * sqrt(d2); } if( out<0 ) { NEG = 1; out*=-1; } if( out>1.01 ) { WARNING_message("It looks like there might be a problem in the grads?\n" "\tOne has large magnitude (%f>1): setting to unity."); } if( out>1) out = 1; out = (float) acos(out); out*= 180./PI; if(NEG) WARNING_message("Gradient is 180 out of phase with matched partner.\n" "\tMight still be ok -> checking abs ang diff: %5f", out); return out; }
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 ; }
/* 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); }
static FILE * fopen_maybe( char *fname ) /* 05 Feb 2008 */ { FILE *imfile ; char *tname = NULL; int tlen; if( fname == NULL || *fname == '\0' ) return NULL ; /* bad input */ /* special case -- be sure not to fclose() stdout! */ /* ------------------------------------------------------------- */ /* test file streams with tname, where any .1D has been stripped */ /* note: the .1D suffix might come from EDIT_dset_items() */ /* problem noted by I Schwabacher 13 Nov 2012 [rickr] */ tlen = strlen(fname); if( tlen > 3 && !strcmp(fname+tlen-3, ".1D") ) { tname = strdup(fname); tname[tlen-3] = '\0'; } else tname = fname; if( strcmp(tname,"-") == 0 || strcmp(tname,"stdout") == 0 || strcmp(tname,"stdout:") == 0 ) return stdout ; if( strcmp(tname,"stderr" ) == 0 || strcmp(tname,"stderr:") == 0 ) return stderr ; if( tname != fname ) free(tname); /* done with tname */ /* ------------------------------------------------------------- */ if( THD_is_ondisk(fname) ){ /* check for existing file */ if( !THD_ok_overwrite() ){ /* if not allowed to overwrite */ ERROR_message("(FAILED) attempt to over-write file %s",fname) ; return NULL ; } else { WARNING_message("over-writing file %s",fname) ; /* tell the user */ } } imfile = fopen(fname,"w") ; if( imfile == NULL ) ERROR_message("Can't open for output: %s",fname) ; return imfile ; }
char * THD_zzprintf( char *sss , char *fmt , ... ) { static char *sbuf = NULL ; /* workspace */ char *zz ; int nzz , nsbuf ; va_list vararg_ptr ; ENTRY("THD_zzprintf") ; va_start( vararg_ptr , fmt ) ; /* first time in ==> create workspace */ if( sbuf == NULL ) sbuf = malloc(sizeof(char)*(ZMAX+90)) ; /* write current stuff into workspace */ sbuf[0] = '\0' ; vsnprintf( sbuf , sizeof(char)*(ZMAX+89) , fmt , vararg_ptr ) ; nsbuf = strlen(sbuf) ; if( nsbuf == 0 ) RETURN(sss) ; /* nothing happened */ if( nsbuf >= ZMAX ){ /* too much happened */ WARNING_message("THD_zzprintf() long string truncation = the ZSS syndrome") ; strcpy(sbuf+ZMAX-4,"...") ; nsbuf = strlen(sbuf) ; } /* make new space, copy input string sss, append new stuff, return result */ if( sss == NULL || *sss == '\0' ){ /* no input string ==> copy new stuff */ zz = (char *) malloc( sizeof(char)*(nsbuf+2) ) ; strcpy(zz,sbuf) ; } else { /* the full Monty: copy old then new */ nzz = strlen(sss) + nsbuf + 2 ; zz = (char *) malloc( sizeof(char) * nzz ) ; strcpy(zz,sss) ; strcat(zz,sbuf) ; free(sss) ; /* don't need input copy any more */ } RETURN(zz) ; }
int THD_bandpass_OK( int nx , float dt , float fbot , float ftop , int verb ) { int nfft , jbot,jtop ; float df ; if( ftop > ICOR_MAX_FTOP ) return 1 ; /* 26 Feb 2010 */ if( nx < 9 ) return 0 ; if( dt <= 0.0f ) dt = 1.0f ; if( fbot < 0.0f ) fbot = 0.0f ; if( ftop <= fbot ){ ERROR_message("bad bandpass frequencies?"); return 0; } if( bpwrn && dt > 60.0f ){ WARNING_message("Your bandpass timestep (%f) is high.\n" " Make sure units are 'sec', not 'msec'.\n" " This warning will not be repeated." , dt); bpwrn = 0; } nfft = (nfft_fixed >= nx) ? nfft_fixed : csfft_nextup_even(nx) ; df = 1.0f / (nfft * dt) ; /* freq step */ jbot = (int)rint(fbot/df) ; /* band bot index */ jtop = (int)rint(ftop/df) ; /* band top index */ if( jtop >= nfft/2 ) jtop = nfft/2-1 ; if( jbot+1 >= jtop ){ ERROR_message( "bandpass: fbot=%g and ftop=%g too close ==> jbot=%d jtop=%d [nfft=%d dt=%g]", fbot,ftop,jbot,jtop,nfft,dt) ; return 0 ; } if( verb ) ININFO_message( "bandpass: ntime=%d nFFT=%d dt=%.6g dFreq=%.6g Nyquist=%.6g passband indexes=%d..%d", nx, nfft, dt, df, (nfft/2)*df, jbot, jtop) ; return 1 ; }
THD_3dim_dataset * THD_open_tcat( char *dlist ) { THD_3dim_dataset *dset_out , **dset_in ; int ndset_in , dd , nerr , new_nvals, sb=0 ; NI_str_array *sar ; double angle=0.0; char *dp, *dlocal = dlist; /* local dlist, in case it is altered */ ENTRY("THD_open_tcat") ; if( dlocal == NULL || *dlocal == '\0' ) RETURN(NULL) ; /* allow file list to be read from a file 23 Jul 2012 [rickr] */ if( ! strncmp(dlocal, "filelist:", 9) ) { dlocal = AFNI_suck_file(dlocal+9) ; if ( ! dlocal ) { ERROR_message("THD_open_tcat: failed to open '%s' as filelist", dlocal+9); RETURN(NULL) ; } /* make it look more like expected */ for( dd=0, dp=dlocal; dd < strlen(dlocal); dd++, dp++ ) if( *dp == '\n' || *dp == '\r' ) *dp = ' '; } if( strchr(dlocal,' ') == NULL ){ dset_out = THD_open_dataset(dlocal) ; RETURN(dset_out) ; } sar = NI_decode_string_list( dlocal , "~" ) ; if( sar == NULL ) RETURN(NULL) ; ndset_in = sar->num ; dset_in = (THD_3dim_dataset **)malloc(sizeof(THD_3dim_dataset *)*sar->num) ; for( nerr=dd=0 ; dd < ndset_in ; dd++ ){ dset_in[dd] = THD_open_dataset( sar->str[dd] ) ; if( dset_in[dd] == NULL ){ fprintf(stderr,"** THD_open_tcat: can't open dataset %s\n",sar->str[dd]) ; nerr++ ; } } if( nerr > 0 ){ for( dd=0 ; dd < ndset_in ; dd++ ) if( dset_in[dd] != NULL ) DSET_delete(dset_in[dd]) ; free((void *)dset_in) ; NI_delete_str_array(sar) ; RETURN(NULL) ; } if( ndset_in == 1 ){ dset_out = dset_in[0] ; free((void *)dset_in) ; NI_delete_str_array(sar) ; RETURN(dset_out) ; } (void)THD_check_for_duplicates( sar->num , sar->str , 1 ) ; /* 31 May 2007 */ for( nerr=0,dd=1 ; dd < ndset_in ; dd++ ){ if( DSET_NX(dset_in[0]) != DSET_NX(dset_in[dd]) || DSET_NY(dset_in[0]) != DSET_NY(dset_in[dd]) || DSET_NZ(dset_in[0]) != DSET_NZ(dset_in[dd]) ){ ERROR_message( "THD_open_tcat: %s [%dx%dx%d] doesn't match %s [%dx%dx%d]\n", sar->str[0] ,DSET_NX(dset_in[0]) , DSET_NY(dset_in[0]) ,DSET_NZ(dset_in[0]) , sar->str[dd],DSET_NX(dset_in[dd]), DSET_NY(dset_in[dd]),DSET_NZ(dset_in[dd]) ) ; nerr++ ; } else { if( !EQUIV_DATAXES(dset_in[dd]->daxes,dset_in[0]->daxes) ){ WARNING_message( "THD_open_tcat: %s grid mismatch with %s\n", sar->str[0] , sar->str[dd] ) ; /* don't increment nerr! */ } angle = dset_obliquity_angle_diff(dset_in[dd], dset_in[0], -1.0); if (angle > 0.0) { WARNING_message( "dataset %s has an obliquity difference of %f degress with %s\n", dset_in[dd] , angle, dset_in[0] ); } } } if( nerr > 0 ){ for( dd=0 ; dd < ndset_in ; dd++ ) if( dset_in[dd] != NULL ) DSET_delete(dset_in[dd]) ; free((void *)dset_in) ; NI_delete_str_array(sar) ; RETURN(NULL) ; } /*-- Check for type problems ZSS: Aug 27 2012 --*/ for (nerr=0,dd=0; dd < ndset_in ; dd++) { for (sb=0; sb < DSET_NVALS(dset_in[dd]); ++sb) { if ( DSET_BRICK_TYPE(dset_in[0],0) != DSET_BRICK_TYPE(dset_in[dd],sb) ) { ++nerr; } } } if (nerr > 0) { /* don't die, just complain */ WARNING_message( "Command-line catenated dataset has %d sub-bricks that differ \n" " in data type from the first sub-brick of the first set.\n" " Mme Irma sees potential for grief if you go down that path. \n" " Use 3dinfo -datum on each input to understand why this is happening.\n" " You can use 3dcalc's -datum option to rewrite the dataset with \n" " all sub-bricks set to the same type then start over.\n\n", nerr); nerr=0; } /*-- OK, start making new dataset --*/ new_nvals = 0 ; for( dd=0 ; dd < ndset_in ; dd++ ) new_nvals += DSET_NVALS(dset_in[dd]) ; for( dd=0 ; dd < ndset_in ; dd++ ) if( DSET_TIMESTEP(dset_in[dd]) > 0.0 ) break ; /* 1st 3D+time */ if( dd == ndset_in ) dd = 0 ; dset_out = EDIT_empty_copy( dset_in[dd] ) ; /* since this is basically an input dataset, set the storage_mode * to match 27 Jul 2010 [rickr] */ if( DSET_ONDISK(dset_out) && IS_VALID_NON_AFNI_DSET(dset_in[dd]) ) THD_set_storage_mode(dset_out, dset_in[dd]->dblk->diskptr->storage_mode); EDIT_dset_items( dset_out , ADN_prefix , "tcat" , ADN_func_type , ISANAT(dset_in[dd]) ? ANAT_EPI_TYPE : FUNC_FIM_TYPE , ADN_ntt , new_nvals , ADN_nvals , new_nvals , ADN_none ) ; DSET_mallocize( dset_out ) ; /* check if we have a valid time axis; if not, make one up */ if( DSET_TIMESTEP(dset_out) <= 0.0f ){ float TR=1.0f , torg=0.0f , tdur=0.0f ; int tunits=UNITS_SEC_TYPE ; EDIT_dset_items( dset_out , ADN_tunits , tunits , ADN_ttdel , TR , ADN_ttorg , torg , ADN_ttdur , tdur , ADN_none ) ; } dset_out->tcat_list = strdup( dlocal ) ; dset_out->tcat_num = ndset_in ; dset_out->tcat_len = (int *)malloc(sizeof(int)*ndset_in) ; for( dd=0 ; dd < ndset_in ; dd++ ){ dset_out->tcat_len[dd] = DSET_NVALS(dset_in[dd]) ; DSET_delete(dset_in[dd]) ; } free((void *)dset_in) ; NI_delete_str_array(sar) ; #if 0 fprintf(stderr,"THD_open_tcat('%s'):",dset_out->tcat_list); for(dd=0;dd<ndset_in;dd++)fprintf(stderr," %d",dset_out->tcat_len[dd]); fprintf(stderr,"\n"); #endif RETURN(dset_out) ; }
Boolean THD_write_datablock( THD_datablock *blk , Boolean write_brick ) { THD_diskptr *dkptr ; Boolean good ; int id , nx , ny , nz , nv , nxy , nxyz , ibr ; int atrank[ATRSIZE_DATASET_RANK] , atdims[ATRSIZE_DATASET_DIMENSIONS] ; MRI_IMAGE *im ; int save_order ; int64_t nb , idone ; int do_mripurge ; /*-- sanity checks --*/ if( ! ISVALID_DATABLOCK(blk) ) return False ; if( DBLK_IS_MASTERED(blk) ) return False ; /* 11 Jan 1999 */ if( DBLK_IS_MINC(blk) ) WRITE_ERR("MINC with bad name extension?") ; /* 29 Oct 2001 */ if( DBLK_IS_ANALYZE(blk) ) WRITE_ERR("ANALYZE but bad name extension?") ; /* 27 Aug 2002 */ if( DBLK_IS_NIFTI(blk) ) WRITE_ERR("NIFTI but bad name extension?") ; /* 28 Aug 2003 */ dkptr = blk->diskptr ; if( ! ISVALID_DISKPTR(dkptr) ) WRITE_ERR("illegal file type") ; if( strlen(dkptr->directory_name) == 0 || strlen(dkptr->header_name) == 0 || strlen(dkptr->filecode) == 0 ) WRITE_ERR("illegal file names stored in dataset") ; if( dkptr->rank != 3 ) WRITE_ERR("cannot write non-3D datablock") ; /*-- create directory if necessary --*/ if( ! THD_is_directory(dkptr->directory_name) ){ id = mkdir( dkptr->directory_name , THD_MKDIR_MODE ) ; if( id != 0 ){ fprintf(stderr, "\n" "*** cannot mkdir new directory: %s\n" " - Do you have permission to write to this disk?\n" " - Is the disk full?\n" , dkptr->directory_name) ; return False ; } } /* 25 April 1998: deal with byte order issues */ if( native_order < 0 ){ /* initialization */ native_order = mri_short_order() ; if( output_order < 0 ) THD_enviro_write_order() ; } if( dkptr->byte_order <= 0 ) dkptr->byte_order = native_order ; save_order = (output_order > 0) ? output_order : dkptr->byte_order ; #if 0 fprintf(stderr,"THD_write_datablock: save_order=%d dkptr->byte_order=%d\n", save_order, dkptr->byte_order ) ; #endif if( save_order != LSB_FIRST && save_order != MSB_FIRST ) save_order = native_order ; if( save_order == LSB_FIRST ) THD_set_string_atr( blk , ATRNAME_BYTEORDER , LSB_FIRST_STRING ) ; else if( save_order == MSB_FIRST ) THD_set_string_atr( blk , ATRNAME_BYTEORDER , MSB_FIRST_STRING ) ; /*-- actually write attributes to disk --*/ good = THD_write_atr( blk ) ; if( good == False ) WRITE_ERR( "failure to write attributes - is disk full? do you have write permission?"); /*-- if not writing data, can exit --*/ if( write_brick == False || blk->brick == NULL || dkptr->storage_mode == STORAGE_UNDEFINED ) return True ; if( dkptr->storage_mode == STORAGE_BY_VOLUMES ){ /* 20 Jun 2002 */ fprintf(stderr,"** Writing dataset by VOLUMES not yet supported.\n") ; return False ; } /*-- check each brick for existence: if none exist, cannot write, but is OK if some but not all exist, cannot write, and is an error --*/ id = THD_count_potential_databricks( blk ) ; if( id <= 0 ) return True ; if( id < blk->nvals ){ ERROR_message("Write dataset error: only %d out of %d bricks in memory", id,blk->nvals) ; return False ; } if( blk->malloc_type == DATABLOCK_MEM_UNDEFINED ) WRITE_ERR("undefined data exists in memory") ; /*-- 13 Mar 2006: check for free disk space --*/ { int mm = THD_freemegabytes( dkptr->header_name ) ; int rr = blk->total_bytes / (1024l * 1024l) ; if( mm >= 0 && mm <= rr ) WARNING_message("Disk space: writing file %s (%d MB)," " but only %d free MB on disk" , dkptr->brick_name , rr , mm ) ; } /*-- write data out in whatever format is ordered --*/ nx = dkptr->dimsizes[0] ; ny = dkptr->dimsizes[1] ; nxy = nx * ny ; nz = dkptr->dimsizes[2] ; nxyz = nxy * nz ; nv = dkptr->nvals ; nb = blk->total_bytes ; switch( dkptr->storage_mode ){ default: WRITE_ERR("illegal storage_mode!") ; break ; case STORAGE_BY_BRICK:{ FILE *far ; Boolean purge_when_done = False , ok ; int force_gzip=0 , csave=COMPRESS_NONE ; /** if we have a mmap-ed file, copy into RAM (ugh) **/ if( blk->malloc_type == DATABLOCK_MEM_MMAP ){ char *bnew , *bold ; int offset ; bnew = (char *) malloc( (size_t)nb ) ; /* work space */ bold = DBLK_ARRAY(blk,0) ; /* start of mapped file */ if( bnew == NULL ) WRITE_ERR("cannot rewrite due to malloc failure - is memory exhausted?") ; memcpy( bnew , bold , (size_t)nb ) ; /* make a copy, */ munmap( (void *) bold , (size_t)nb ) ; /* then unmap file */ /* fix sub-brick pointers */ offset = 0 ; for( ibr=0 ; ibr < nv ; ibr++ ){ mri_fix_data_pointer( (void *)(bnew+offset) , DBLK_BRICK(blk,ibr) ) ; offset += DBLK_BRICK_BYTES(blk,ibr) ; DBLK_BRICK(blk,ibr)->fondisk = 0 ; /* 31 Jan 2007 */ } purge_when_done = True ; } /** fall thru to here if have a malloc-ed dataset **/ if( save_order != native_order ) purge_when_done = True ; /** delete old file, if any **/ COMPRESS_unlink( dkptr->brick_name ) ; /* Feb 1998 */ /** create new file **/ id = strlen(dkptr->directory_name) ; ok = ( dkptr->directory_name[id-1] == '/' ) ; if( ok ) sprintf( dkptr->brick_name , "%s%s.%s", dkptr->directory_name , dkptr->filecode , DATASET_BRICK_SUFFIX ); else sprintf( dkptr->brick_name , "%s/%s.%s", dkptr->directory_name , dkptr->filecode , DATASET_BRICK_SUFFIX ); /** COMPRESS for output added Feb 1998 */ if( compress_mode == COMPRESS_NOFILE ) THD_enviro_write_compression() ; #ifdef COMPRESS_GZIP /*-- 02 Mar 2001: check if we will force gzip --*/ if( compress_mode == COMPRESS_NONE && AFNI_yesenv("AFNI_AUTOGZIP") ){ double entrop = ENTROPY_datablock(blk) ; force_gzip = (entrop < 2.7) ; #if 0 fprintf(stderr,"Entropy=%g ==> forcing write gzip on %s\n",entrop,dkptr->brick_name) ; #endif } else { force_gzip = 0 ; } if( force_gzip ){ csave = compress_mode ; compress_mode = COMPRESS_GZIP ; } #endif far = COMPRESS_fopen_write( dkptr->brick_name , compress_mode ) ; if( far == NULL ){ if( compress_mode != COMPRESS_NONE ){ compress_mode = COMPRESS_NONE ; force_gzip = 0 ; far = COMPRESS_fopen_write( dkptr->brick_name , compress_mode ) ; } } if( far == NULL ) WRITE_ERR("cannot open output brick file - do you have write permission?") ; /** write each brick out in a separate operation **/ idone = 0 ; for( ibr=0 ; ibr < nv ; ibr++ ){ do_mripurge = MRI_IS_PURGED( DBLK_BRICK(blk,ibr) ) ; if( do_mripurge ) mri_unpurge( DBLK_BRICK(blk,ibr) ) ; if( save_order != native_order ){ /* 25 April 1998 */ switch( DBLK_BRICK_TYPE(blk,ibr) ){ default: break ; case MRI_short: mri_swap2( DBLK_BRICK_NVOX(blk,ibr) , DBLK_ARRAY(blk,ibr) ) ; break ; case MRI_complex: /* 23 Nov 1999 */ mri_swap4( 2*DBLK_BRICK_NVOX(blk,ibr), DBLK_ARRAY(blk,ibr)) ; break ; case MRI_float: /* 23 Nov 1999 */ case MRI_int: mri_swap4( DBLK_BRICK_NVOX(blk,ibr) , DBLK_ARRAY(blk,ibr) ) ; break ; } } idone += fwrite( DBLK_ARRAY(blk,ibr), 1, DBLK_BRICK_BYTES(blk,ibr), far ); if( do_mripurge ){ /* 31 Jan 2007 */ if( !purge_when_done ) mri_purge( DBLK_BRICK(blk,ibr) ) ; else mri_clear( DBLK_BRICK(blk,ibr) ) ; } } /* end of loop over sub-bricks */ COMPRESS_fclose(far) ; if( purge_when_done ){ if( blk->malloc_type == DATABLOCK_MEM_MMAP ){ free( DBLK_ARRAY(blk,0) ) ; for( ibr=0 ; ibr < nv ; ibr++ ) mri_clear_data_pointer( DBLK_BRICK(blk,ibr) ) ; } else { THD_purge_datablock( blk , DATABLOCK_MEM_MALLOC ) ; } } if( compress_mode >= 0 || save_order != native_order ){ blk->malloc_type = DATABLOCK_MEM_MALLOC ; } DBLK_mmapfix(blk) ; /* 28 Mar 2005 */ if( force_gzip ) compress_mode = csave ; /* 02 Mar 2001 */ if( idone != blk->total_bytes ) WRITE_ERR("Write error in brick file: Is disk full, or write_protected?") ; dkptr->byte_order = save_order ; /* 23 Nov 1999 */ return True ; } break ; } /* end of switch over data storage mode */ return False ; /* should NEVER be reached */ }
int main( int argc , char *argv[] ) { THD_3dim_dataset *inset=NULL ; byte *mask=NULL ; int mask_nx=0,mask_ny=0,mask_nz=0 , automask=0 , masknum=0 ; int iarg=1 , verb=1 , ntype=0 , nev,kk,ii,nxyz,nt ; float na,nb,nc , dx,dy,dz ; MRI_IMARR *imar=NULL ; int *ivox ; MRI_IMAGE *pim ; int do_vmean=0 , do_vnorm=0 , sval_itop=0 ; int polort=-1 ; float *ev ; MRI_IMARR *ortar ; MRI_IMAGE *ortim ; int nyort=0 ; float bpass_L=0.0f , bpass_H=0.0f , dtime ; int do_bpass=0 ; if( argc < 2 || strcmp(argv[1],"-help") == 0 ){ printf( "Usage: 3dmaskSVD [options] inputdataset\n" "Author: Zhark the Gloriously Singular\n" "\n" "* Computes the principal singular vector of the time series\n" " vectors extracted from the input dataset over the input mask.\n" " ++ You can use the '-sval' option to change which singular\n" " vectors are output.\n" "* The sign of the output vector is chosen so that the average\n" " of arctanh(correlation coefficient) over all input data\n" " vectors (from the mask) is positive.\n" "* The output vector is normalized: the sum of its components\n" " squared is 1.\n" "* You probably want to use 3dDetrend (or something similar) first,\n" " to get rid of annoying artifacts, such as motion, breathing,\n" " dark matter interactions with the brain, etc.\n" " ++ If you are lazy scum like Zhark, you might be able to get\n" " away with using the '-polort' option.\n" " ++ In particular, if your data time series has a nonzero mean,\n" " then you probably want at least '-polort 0' to remove the\n" " mean, otherwise you'll pretty much just get a constant\n" " time series as the principal singular vector!\n" "* An alternative to this program would be 3dmaskdump followed\n" " by 1dsvd, which could give you all the singular vectors you\n" " could ever want, and much more -- enough to confuse you for days.\n" " ++ In particular, although you COULD input a 1D file into\n" " 3dmaskSVD, the 1dsvd program would make much more sense.\n" "* This program will be pretty slow if there are over about 2000\n" " voxels in the mask. It could be made more efficient for\n" " such cases, but you'll have to give Zhark some 'incentive'.\n" "* Result vector goes to stdout. Redirect per your pleasures and needs.\n" "* Also see program 3dLocalSVD if you want to compute the principal\n" " singular time series vector from a neighborhood of EACH voxel.\n" " ++ (Which is a pretty slow operation!)\n" "* http://en.wikipedia.org/wiki/Singular_value_decomposition\n" "\n" "-------\n" "Options:\n" "-------\n" " -vnorm = L2 normalize all time series before SVD [recommended!]\n" " -sval a = output singular vectors 0 .. a [default a=0 = first one only]\n" " -mask mset = define the mask [default is entire dataset == slow!]\n" " -automask = you'll have to guess what this option does\n" " -polort p = if you are lazy and didn't run 3dDetrend (like Zhark)\n" " -bpass L H = bandpass [mutually exclusive with -polort]\n" " -ort xx.1D = time series to remove from the data before SVD-ization\n" " ++ You can give more than 1 '-ort' option\n" " ++ 'xx.1D' can contain more than 1 column\n" " -input ddd = alternative way to give the input dataset name\n" "\n" "-------\n" "Example:\n" "-------\n" " You have a mask dataset with discrete values 1, 2, ... 77 indicating\n" " some ROIs; you want to get the SVD from each ROI's time series separately,\n" " and then put these into 1 big 77 column .1D file. You can do this using\n" " a csh shell script like the one below:\n" "\n" " # Compute the individual SVD vectors\n" " foreach mm ( `count 1 77` )\n" " 3dmaskSVD -vnorm -mask mymask+orig\"<${mm}..${mm}>\" epi+orig > qvec${mm}.1D\n" " end\n" " # Glue them together into 1 big file, then delete the individual files\n" " 1dcat qvec*.1D > allvec.1D\n" " /bin/rm -f qvec*.1D\n" " # Plot the results to a JPEG file, then compute their correlation matrix\n" " 1dplot -one -nopush -jpg allvec.jpg allvec.1D\n" " 1ddot -terse allvec.1D > allvec_COR.1D\n" "\n" " [[ If you use the bash shell, you'll have to figure out the syntax ]]\n" " [[ yourself. Zhark has no sympathy for you bash shell infidels, and ]]\n" " [[ considers you only slightly better than those lowly Emacs users. ]]\n" " [[ And do NOT ever even mention 'nedit' in Zhark's august presence! ]]\n" ) ; PRINT_COMPILE_DATE ; exit(0) ; } /*---- official startup ---*/ PRINT_VERSION("3dmaskSVD"); mainENTRY("3dmaskSVD main"); machdep(); AFNI_logger("3dmaskSVD",argc,argv); AUTHOR("Zhark the Singular"); /*---- loop over options ----*/ INIT_IMARR(ortar) ; mpv_sign_meth = AFNI_yesenv("AFNI_3dmaskSVD_meansign") ; while( iarg < argc && argv[iarg][0] == '-' ){ if( strcasecmp(argv[iarg],"-bpass") == 0 ){ if( iarg+2 >= argc ) ERROR_exit("need 2 args after -bpass") ; bpass_L = (float)strtod(argv[++iarg],NULL) ; bpass_H = (float)strtod(argv[++iarg],NULL) ; if( bpass_L < 0.0f || bpass_H <= bpass_L ) ERROR_exit("Illegal values after -bpass: %g %g",bpass_L,bpass_H) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-ort") == 0 ){ /* 01 Oct 2009 */ int nx,ny ; if( ++iarg >= argc ) ERROR_exit("Need argument after '-ort'") ; ortim = mri_read_1D( argv[iarg] ) ; if( ortim == NULL ) ERROR_exit("-ort '%s': Can't read 1D file",argv[iarg]) ; nx = ortim->nx ; ny = ortim->ny ; if( nx == 1 && ny > 1 ){ MRI_IMAGE *tim=mri_transpose(ortim); mri_free(ortim); ortim = tim; ny = 1; } mri_add_name(argv[iarg],ortim) ; ADDTO_IMARR(ortar,ortim) ; nyort += ny ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-polort") == 0 ){ char *qpt ; if( ++iarg >= argc ) ERROR_exit("Need argument after '-polort'") ; polort = (int)strtod(argv[iarg],&qpt) ; if( *qpt != '\0' ) WARNING_message("Illegal non-numeric value after -polort") ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-vnorm") == 0 ){ do_vnorm = 1 ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-input") == 0 ){ if( inset != NULL ) ERROR_exit("Can't have two -input options") ; if( ++iarg >= argc ) ERROR_exit("Need argument after '-input'") ; inset = THD_open_dataset( argv[iarg] ) ; CHECK_OPEN_ERROR(inset,argv[iarg]) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-sval") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '-sval'") ; sval_itop = (int)strtod(argv[iarg],NULL) ; if( sval_itop < 0 ){ sval_itop = 0 ; WARNING_message("'-sval' reset to 0") ; } iarg++ ; continue ; } if( strcmp(argv[iarg],"-mask") == 0 ){ THD_3dim_dataset *mset ; int mmm ; if( ++iarg >= argc ) ERROR_exit("Need argument after '-mask'") ; if( mask != NULL || automask ) ERROR_exit("Can't have two mask inputs") ; mset = THD_open_dataset( argv[iarg] ) ; CHECK_OPEN_ERROR(mset,argv[iarg]) ; DSET_load(mset) ; CHECK_LOAD_ERROR(mset) ; mask_nx = DSET_NX(mset); mask_ny = DSET_NY(mset); mask_nz = DSET_NZ(mset); mask = THD_makemask( mset , 0 , 0.5f, 0.0f ) ; DSET_delete(mset) ; if( mask == NULL ) ERROR_exit("Can't make mask from dataset '%s'",argv[iarg]) ; masknum = mmm = THD_countmask( mask_nx*mask_ny*mask_nz , mask ) ; INFO_message("Number of voxels in mask = %d",mmm) ; if( mmm < 2 ) ERROR_exit("Mask is too small to process") ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-automask") == 0 ){ if( mask != NULL ) ERROR_exit("Can't have two mask inputs!") ; automask = 1 ; iarg++ ; continue ; } ERROR_exit("Unknown option '%s'",argv[iarg]) ; } /*--- end of loop over options ---*/ /*---- deal with input dataset ----*/ if( inset == NULL ){ if( iarg >= argc ) ERROR_exit("No input dataset on command line?") ; inset = THD_open_dataset( argv[iarg] ) ; CHECK_OPEN_ERROR(inset,argv[iarg]) ; } nt = DSET_NVALS(inset) ; /* vector lengths */ if( nt < 9 ) ERROR_exit("Must have at least 9 values per voxel") ; if( polort+1 >= nt ) ERROR_exit("'-polort %d' too big for time series length = %d",polort,nt) ; DSET_load(inset) ; CHECK_LOAD_ERROR(inset) ; nxyz = DSET_NVOX(inset) ; DSET_UNMSEC(inset) ; dtime = DSET_TR(inset) ; if( dtime <= 0.0f ) dtime = 1.0f ; do_bpass = (bpass_L < bpass_H) ; if( do_bpass ){ kk = THD_bandpass_OK( nt , dtime , bpass_L , bpass_H , 1 ) ; if( kk <= 0 ) ERROR_exit("Can't continue since -bpass setup is illegal") ; polort = -1 ; } /*--- deal with the masking ---*/ if( mask != NULL ){ if( mask_nx != DSET_NX(inset) || mask_ny != DSET_NY(inset) || mask_nz != DSET_NZ(inset) ) ERROR_exit("-mask dataset grid doesn't match input dataset") ; } else if( automask ){ int mmm ; mask = THD_automask( inset ) ; if( mask == NULL ) ERROR_message("Can't create -automask from input dataset?") ; masknum = mmm = THD_countmask( DSET_NVOX(inset) , mask ) ; INFO_message("Number of voxels in automask = %d",mmm) ; if( mmm < 9 ) ERROR_exit("Automask is too small to process") ; } else { mask = (byte *)malloc(sizeof(byte)*nxyz) ; masknum = nxyz ; memset( mask , 1 , sizeof(byte)*nxyz ) ; INFO_message("Using all %d voxels in dataset",nxyz) ; } nev = MIN(nt,masknum) ; /* max possible number of eigenvalues */ if( sval_itop >= nev ){ sval_itop = nev-1 ; WARNING_message("'-sval' reset to '%d'",sval_itop) ; } mri_principal_vector_params( 0 , do_vnorm , sval_itop ) ; mri_principal_setev(nev) ; /*-- get data vectors --*/ ivox = (int *)malloc(sizeof(int)*masknum) ; for( kk=ii=0 ; ii < nxyz ; ii++ ) if( mask[ii] ) ivox[kk++] = ii ; INFO_message("Extracting data vectors") ; imar = THD_extract_many_series( masknum, ivox, inset ) ; DSET_unload(inset) ; if( imar == NULL ) ERROR_exit("Can't get data vector?!") ; /*-- detrending --*/ if( polort >= 0 || nyort > 0 || do_bpass ){ float **polref=NULL ; float *tsar ; int nort=IMARR_COUNT(ortar) , nref=0 ; if( polort >= 0 ){ /* polynomials */ nref = polort+1 ; polref = THD_build_polyref(nref,nt) ; } if( nort > 0 ){ /* other orts */ float *oar , *par ; int nx,ny , qq,tt ; for( kk=0 ; kk < nort ; kk++ ){ /* loop over input -ort files */ ortim = IMARR_SUBIM(ortar,kk) ; nx = ortim->nx ; ny = ortim->ny ; if( nx < nt ) ERROR_exit("-ort '%s' length %d shorter than dataset length %d" , ortim->name , nx , nt ) ; polref = (float **)realloc(polref,(nref+ny)*sizeof(float *)) ; oar = MRI_FLOAT_PTR(ortim) ; for( qq=0 ; qq < ny ; qq++,oar+=nx ){ par = polref[nref+qq] = (float *)malloc(sizeof(float)*nt) ; for( tt=0 ; tt < nt ; tt++ ) par[tt] = oar[tt] ; if( polort == 0 ) THD_const_detrend (nt,par,NULL) ; else if( polort > 0 ) THD_linear_detrend(nt,par,NULL,NULL) ; } nref += ny ; } DESTROY_IMARR(ortar) ; } if( !do_bpass ){ /* old style ort-ification */ MRI_IMAGE *imq , *imp ; float *qar ; INFO_message("Detrending data vectors") ; #if 1 imq = mri_new( nt , nref , MRI_float) ; qar = MRI_FLOAT_PTR(imq) ; for( kk=0 ; kk < nref ; kk++ ) memcpy( qar+kk*nt , polref[kk] , sizeof(float)*nt ) ; imp = mri_matrix_psinv( imq , NULL , 1.e-8 ) ; for( kk=0 ; kk < IMARR_COUNT(imar) ; kk++ ){ mri_matrix_detrend( IMARR_SUBIM(imar,kk) , imq , imp ) ; } mri_free(imp) ; mri_free(imq) ; #else for( kk=0 ; kk < IMARR_COUNT(imar) ; kk++ ){ tsar = MRI_FLOAT_PTR(IMARR_SUBIM(imar,kk)) ; THD_generic_detrend_LSQ( nt , tsar , -1 , nref , polref , NULL ) ; } #endif } else { /* bandpass plus (maybe) orts */ float **vec = (float **)malloc(sizeof(float *)*IMARR_COUNT(imar)) ; INFO_message("Bandpassing data vectors") ; for( kk=0 ; kk < IMARR_COUNT(imar) ; kk++ ) vec[kk] = MRI_FLOAT_PTR(IMARR_SUBIM(imar,kk)) ; (void)THD_bandpass_vectors( nt , IMARR_COUNT(imar) , vec , dtime , bpass_L , bpass_H , 2 , nref , polref ) ; free(vec) ; } for( kk=0 ; kk < nref; kk++ ) free(polref[kk]) ; free(polref) ; } /* end of detrendization */ /*--- the actual work ---*/ INFO_message("Computing SVD") ; pim = mri_principal_vector( imar ) ; DESTROY_IMARR(imar) ; if( pim == NULL ) ERROR_exit("SVD failure!?!") ; ev = mri_principal_getev() ; switch(sval_itop+1){ case 1: INFO_message("First singular value: %g",ev[0]) ; break ; case 2: INFO_message("First 2 singular values: %g %g",ev[0],ev[1]) ; break ; case 3: INFO_message("First 3 singular values: %g %g %g",ev[0],ev[1],ev[2]) ; break ; case 4: INFO_message("First 4 singular values: %g %g %g %g",ev[0],ev[1],ev[2],ev[3]) ; break ; default: case 5: INFO_message("First 5 singular values: %g %g %g %g %g",ev[0],ev[1],ev[2],ev[3],ev[4]) ; break ; } mri_write_1D(NULL,pim) ; exit(0) ; }
int AFNI_process_environ( char *fname ) { int nbuf , nused , ii ; char *fbuf , *fptr ; char str[NSBUF] , left[NSBUF] , middle[NSBUF] , right[NSBUF], fname_str[NSBUF] = {"not_set"}; int nenv=0 , senv=0 ; static int first=1 ; /* 13 Mar 2008 */ ENTRY("AFNI_process_environ") ; bloced = 1 ; if( fname != NULL ){ strcpy(str,fname) ; } else { char *home ; if( afni_env_done ) RETURN(nenv) ; home = getenv("HOME") ; if( home != NULL ){ strcpy(str,home) ; strcat(str,"/.afnirc") ; } else { strcpy(str,".afnirc") ; } if( !THD_is_file(str) ){ /* 19 Sep 2007 */ if( home != NULL ){ strcpy(str,home) ; strcat(str,"/AFNI.afnirc") ; } else { strcpy(str,"AFNI.afnirc") ; } } afni_env_done = 1 ; } strcpy(fname_str,str) ; /* ZSS: Nov. 25 08 */ fbuf = AFNI_suck_file( str ) ; if( fbuf == NULL ){ bloced=0; if(fname==NULL)afni_env_done=0; RETURN(nenv); } nbuf = strlen(fbuf) ; if( nbuf == 0 ){ bloced=0; if(fname==NULL)afni_env_done=0; RETURN(nenv); } fptr = fbuf ; nused = 0 ; /** scan for section strings, which start with "***" **/ str[0] = '\0' ; /* initialize string */ while( nused < nbuf ){ /**----------------------------------------**/ /**-- skip ahead to next section keyword --**/ SkipSection: while( ! ISTARRED(str) ){ GETSTR; } /*- 04 Jun 1999 -*/ if( strcmp(str,"***END") == 0 ) break ; /* exit main loop */ if( strcmp(str,"***ENVIRONMENT") != 0 ){ GETSTR ; goto SkipSection ; } /**---------------------------------------**/ /**-- ENVIRONMENT section [04 Jun 1999] --**/ if( strcmp(str,"***ENVIRONMENT") == 0 ){ /* loop: find environment eqns */ char *enveqn , *eee; int nl , nr , allow_reset ; senv = 1 ; eee = getenv("AFNI_ENVIRON_RESET") ; allow_reset = YESSISH(eee) ; while(1){ /* loop, looking for 'name = value' */ GETEQN ; if( !THD_filename_pure(left) ) continue ; nl = strlen(left) ; nr = strlen(right) ; enveqn = (char *) malloc(nl+nr+4) ; strcpy(enveqn,left) ; strcat(enveqn,"=") ; strcat(enveqn,right) ; if( !(eee = getenv(left)) || allow_reset ){ /* ZSS Nov 25 2008 */ putenv(enveqn) ; } else if( !AFNI_noenv("AFNI_ENVIRON_WARNINGS") && strcmp(right, eee)){ INFO_message( "Environment variable %s already set to '%s'. " "Value of '%s' from %s is ignored. \n" "To kill such warnings Set AFNI_ENVIRON_WARNINGS to NO", left, eee, right, fname_str); } nenv++ ; } continue ; /* to end of outer while */ } /* end of ENVIRONMENT */ } /* end of while loop */ Done: if( fname == NULL && first ){ if( senv == 0 ) WARNING_message("didn't find '***ENVIRONMENT' line in ~/.afnirc") ; else if( nenv == 0 ) WARNING_message("didn't find any environment equations in ~/.afnirc") ; } first = 0 ; free(fbuf) ; bloced = 0 ; RETURN(nenv) ; }
int mri_write_ascii( char *fname, MRI_IMAGE *im ) { int ii , jj , nx , ny ; FILE *imfile ; ENTRY("mri_write_ascii") ; if( im == NULL || im->nz > 1 ) RETURN( 0 ) ; /* stoopid user */ if( fname == NULL || *fname == '\0' ) fname = "-" ; /* to stdout */ imfile = fopen_maybe(fname) ; if( imfile == NULL ) RETURN(0) ; ii = mri_floatscan( im ) ; /* 05 Apr 2010 */ if( ii > 0 ) WARNING_message("Zeroed %d float error%s while writing 1D file %s", ii , (ii > 1) ? "s" : "\0" , fname ) ; nx = im->nx ; ny = im->ny ; for( jj=0 ; jj < ny ; jj++ ){ switch( im->kind ){ default: break ; case MRI_float:{ float *iar = MRI_FLOAT_PTR(im) + (jj*nx) ; for( ii=0 ; ii < nx ; ii++ ) fprintf(imfile," %14g",iar[ii]) ; } break ; case MRI_short:{ short *iar = MRI_SHORT_PTR(im) + (jj*nx) ; for( ii=0 ; ii < nx ; ii++ ) fprintf(imfile," %6d",iar[ii]) ; } break ; case MRI_byte:{ byte *iar = MRI_BYTE_PTR(im) + (jj*nx) ; for( ii=0 ; ii < nx ; ii++ ) fprintf(imfile," %3d",iar[ii]) ; } break ; case MRI_int:{ int *iar = MRI_INT_PTR(im) + (jj*nx) ; for( ii=0 ; ii < nx ; ii++ ) fprintf(imfile," %6d",iar[ii]) ; } break ; case MRI_double:{ double *iar = MRI_DOUBLE_PTR(im) + (jj*nx) ; for( ii=0 ; ii < nx ; ii++ ) fprintf(imfile," %16g",iar[ii]) ; } break ; case MRI_complex:{ complex *iar = MRI_COMPLEX_PTR(im) + (jj*nx) ; for( ii=0 ; ii < nx ; ii++ ) fprintf(imfile," %-1.7g;%-1.7g",iar[ii].r,iar[ii].i) ; } break ; case MRI_rgb:{ byte *iar = MRI_RGB_PTR(im) + (3*jj*nx) ; for( ii=0 ; ii < nx ; ii++ ) fprintf(imfile," %3d %3d %3d",iar[3*ii],iar[3*ii+1],iar[3*ii+2]) ; } break ; } fprintf(imfile,"\n") ; } fclose_maybe(imfile) ; RETURN( 1 ); }
void TT_read_opts( int argc , char * argv[] ) { int nopt = 1 ; int ival , kk ; INIT_EDOPT( &TT_edopt ) ; while( nopt < argc && argv[nopt][0] == '-' ){ /**** editing option? ****/ ival = EDIT_check_argv( argc , argv , nopt , &TT_edopt ) ; if( ival > 0 ){ TT_use_editor = 1 ; nopt += ival ; continue ; } /**** -quiet ****/ if( strncmp(argv[nopt],"-quiet",6) == 0 ){ DUMP1 ; TT_be_quiet = 1 ; nopt++ ; continue ; } /**** -workmem megabytes ****/ if( strncmp(argv[nopt],"-workmem",6) == 0 ){ nopt++ ; if( nopt >= argc ) TT_syntax("need argument after -workmem!") ; ival = strtol( argv[nopt] , NULL , 10 ) ; if( ival <= 0 ) TT_syntax("illegal argument after -workmem!") ; TT_workmem = ival ; INFO_message("-workmem option is now obsolete\n") ; nopt++ ; continue ; } /**** -datum type ****/ if( strncmp(argv[nopt],"-datum",6) == 0 ){ if( ++nopt >= argc ) TT_syntax("need an argument after -datum!") ; if( strcmp(argv[nopt],"short") == 0 ){ TT_datum = MRI_short ; } else if( strcmp(argv[nopt],"float") == 0 ){ TT_datum = MRI_float ; } else { char buf[256] ; sprintf(buf,"-datum of type '%s' is not supported in 3dttest!", argv[nopt] ) ; TT_syntax(buf) ; } nopt++ ; continue ; /* go to next arg */ } /**** -voxel voxel ****/ if( strncmp(argv[nopt],"-voxel",6) == 0 ){ /* 14 Dec 2005 [rickr] */ if( ++nopt >= argc ) TT_syntax("need an argument after -voxel!") ; TT_voxel = atoi(argv[nopt]) - 1 ; /* make zero-based */ nopt++ ; continue ; /* go to next arg */ } /**** -session dirname ****/ if( strncmp(argv[nopt],"-session",6) == 0 ){ DUMP2 ; nopt++ ; if( nopt >= argc ) TT_syntax("need argument after -session!") ; MCW_strncpy( TT_session , argv[nopt++] , THD_MAX_NAME ) ; continue ; } /**** -prefix prefix ****/ if( strncmp(argv[nopt],"-prefix",6) == 0 ){ DUMP2 ; nopt++ ; if( nopt >= argc ) TT_syntax("need argument after -prefix!") ; MCW_strncpy( TT_prefix , argv[nopt++] , THD_MAX_PREFIX ) ; continue ; } #if 0 /**** -label string ****/ if( strncmp(argv[nopt],"-label",6) == 0 ){ DUMP2 ; nopt++ ; if( nopt >= argc ) TT_syntax("need argument after -label!") ; MCW_strncpy( TT_label , argv[nopt++] , THD_MAX_LABEL ) ; continue ; } #endif /** -paired **/ if( strncmp(argv[nopt],"-paired",6) == 0 ){ TT_paired = 1 ; nopt++ ; continue ; /* skip to next arg */ } /** -unpooled **/ if( strncmp(argv[nopt],"-unpooled",6) == 0 ){ TT_pooled = 0 ; nopt++ ; continue ; /* skip to next arg */ } /** -dof_prefix **/ if( strncmp(argv[nopt],"-dof_prefix",6) == 0 ){ /* 27 Dec 2002 */ DUMP2 ; nopt++ ; if( nopt >= argc ) TT_syntax("need argument after -dof_prefix!") ; MCW_strncpy( TT_dof_prefix , argv[nopt++] , THD_MAX_PREFIX ) ; continue ; } #ifdef USE_PTHRESH /** -pthresh pval **/ if( strncmp(argv[nopt],"-pthresh",6) == 0 ){ char * ch ; if( ++nopt >= argc ) TT_syntax("-pthresh needs a value!"); TT_pthresh = strtod( argv[nopt] , &ch ) ; if( *ch != '\0' || TT_pthresh <= 0.0 || TT_pthresh > 0.99999 ) TT_syntax("value after -pthresh is illegal!") ; WARNING_message( "-pthresh not implemented yet, will ignore!") ; TT_pthresh = 0.0 ; nopt++ ; continue ; /* skip to next arg */ } #endif /**** after this point, the options are no longer 'free floating' ****/ /** -base1_dset dset : similar to -base1, but bval differs by voxel **/ /** for M Beauchamp 23 Jul 2008 [rickr] **/ if( strncmp(argv[nopt],"-base1_dset",8) == 0 ){ char *ch ; if( ++nopt >= argc ) TT_syntax("-base1_dset needs a dastaset!"); if( TT_use_bval == -1 ) TT_syntax("-base1_dset with -set1 illegal!"); if( TT_use_bval == 1 ) TT_syntax("-base1_dset with -base1 illegal!"); TT_base_dname = argv[nopt] ; TT_use_bval = 1 ; nopt++ ; continue ; /* skip to next arg */ } /** -base1 bval **/ if( strncmp(argv[nopt],"-base1",6) == 0 ){ char *ch ; if( ++nopt >= argc ) TT_syntax("-base1 needs a value!"); if( TT_use_bval == -1 ) TT_syntax("-base1 with -set1 illegal!"); if( TT_use_bval == 1 ) TT_syntax("-base1 with -base1_dset illegal!"); TT_bval = strtod( argv[nopt] , &ch ) ; if( *ch != '\0' ) TT_syntax("value after -base1 is illegal!") ; TT_use_bval = 1 ; nopt++ ; continue ; /* skip to next arg */ } /** [10 Oct 2007] -sdn1 sd1 n1 **/ if( strncmp(argv[nopt],"-sdn1",5) == 0 ){ if( ++nopt >= argc-1 ) TT_syntax("-sdn1 needs 2 values!") ; if( TT_use_bval == -1 ) TT_syntax("-sdn1 with -set1 illegal!") ; TT_sd1 = strtod( argv[nopt] , NULL ) ; TT_n1 = strtod( argv[++nopt] , NULL ) ; if( TT_sd1 <= 0.0 ) TT_syntax("Illegal sigma after -sdn1!") ; if( TT_n1 < 2 ) TT_syntax("Illegal n1 after -sdn1!") ; nopt++ ; continue ; } /** -set1 file file ... **/ if( strncmp(argv[nopt],"-set1",6) == 0 ){ int eee=0 ; if( TT_use_bval == 1 ) TT_syntax("-set1 with -base1 illegal!"); TT_use_bval = -1 ; INIT_SARR( TT_set1 ) ; for( kk=nopt+1 ; kk < argc ; kk++ ){ #if 1 if( argv[kk][0] == '-' ) break ; #else if( strncmp(argv[kk],"-set2",6) == 0 ) break ; #endif if( strstr(argv[kk],"[") == NULL ){ ADDTO_SARR( TT_set1 , argv[kk] ) ; } else { THD_string_array *ss = THD_multiplex_dataset(argv[kk]); int qq; if( ss == NULL ) ERROR_exit("Can't deal with '%s'",argv[kk]) ; for( qq=0 ; qq < SARR_NUM(ss) ; qq++ ) ADDTO_SARR(TT_set1,SARR_STRING(ss,qq)) ; DESTROY_SARR(ss) ; eee++ ; } } if( kk >= argc ) TT_syntax("-set1 not followed by -set2") ; if( kk-1-nopt <= 0 ) TT_syntax("-set1 has no datasets after it") ; if( TT_set1->num < 2 ) TT_syntax("-set1 doesn't have enough datasets") ; if( eee ) PRINTF_SARR(TT_set1,"++ Expanded -set1:") ; nopt = kk ; continue ; /* skip to arg that matched -set2 */ } /** -set2 file file ... */ if( strncmp(argv[nopt],"-set2",6) == 0 ){ int eee=0 ; INIT_SARR( TT_set2 ) ; for( kk=nopt+1 ; kk < argc ; kk++ ){ #if 1 /* if -set2 must be last, warn the user about trailing args */ if( argv[kk][0] == '-' ) { fprintf(stderr,"** have trailing arg #%d = '%s'\n", kk, argv[kk]); TT_syntax("-set2 must be the last option (see: 3dttest -help)"); } #endif if( strstr(argv[kk],"[") == NULL ){ ADDTO_SARR( TT_set2 , argv[kk] ) ; } else { THD_string_array *ss = THD_multiplex_dataset(argv[kk]); int qq; if( ss == NULL ) ERROR_exit("Can't deal with '%s'",argv[kk]) ; for( qq=0 ; qq < SARR_NUM(ss) ; qq++ ) ADDTO_SARR(TT_set2,SARR_STRING(ss,qq)) ; DESTROY_SARR(ss) ; eee++ ; } } if( TT_set2->num < 2 ) TT_syntax("-set2 doesn't have enough datasets") ; if( eee ) PRINTF_SARR(TT_set2,"++ Expanded -set2:") ; break ; /* end of possible inputs */ } /**** unknown switch ****/ ERROR_exit("unrecognized option %s",argv[nopt]) ; } /* end of loop over options */ if( strlen(TT_label) == 0 ){ MCW_strncpy(TT_label,TT_prefix,THD_MAX_LABEL) ; } /*--- 30 May 2007: check TT_set? for .HEAD / .BRIK duplicates ---*/ if( TT_set1 != NULL ){ kk = THD_check_for_duplicates( TT_set1->num , TT_set1->ar , 1 ) ; if( kk > 0 ) fprintf(stderr,"\n") ; } if( TT_set2 != NULL ){ kk = THD_check_for_duplicates( TT_set2->num , TT_set2->ar , 1 ) ; if( kk > 0 ) fprintf(stderr,"\n") ; } /*--- check arguments for consistency ---*/ if( TT_use_bval == 0 ) TT_syntax("neither -base1 nor -set1 is present!") ; if( TT_use_bval == -1 && TT_n1 > 0 ) TT_syntax("-sdn1 used with -set1 is illegal!") ; /* 10 Oct 2007 */ if( TT_use_bval == -1 && ( TT_set1 == NULL || TT_set1->num < 2 ) ) TT_syntax("-set1 has too few datasets in it!") ; if( TT_set2 == NULL || TT_set2->num < 2 ) TT_syntax("-set2 has too few datasets in it!") ; if( TT_use_bval == 1 && TT_paired == 1 ) TT_syntax("-paired and -base1 are mutually exclusive!") ; if( TT_paired == 1 && TT_set1 == NULL ) TT_syntax("-paired requires presence of -set1!") ; if( TT_paired == 1 && TT_set1->num != TT_set2->num ){ char str[256] ; sprintf(str,"-paired requires equal size dataset collections,\n" "but -set1 has %d datasets and -set2 has %d datasets" , TT_set1->num , TT_set2->num ) ; TT_syntax(str) ; } if( TT_pooled == 0 && TT_paired == 1 ) TT_syntax("-paired and -unpooled are mutually exclusive!") ; if( TT_pooled == 0 && TT_use_bval == 1 ) TT_syntax("-base1 and -unpooled are mutually exclusive!") ; #if 0 if( TT_pooled == 0 && TT_n1 > 0 ) TT_syntax("-unpooled and -sdn1 are mutually exclusive!") ; #endif if( TT_pooled == 1 && TT_dof_prefix[0] != '\0' ) /* 27 Dec 2002 */ WARNING_message("-dof_prefix is used only with -unpooled!"); #ifdef TTDEBUG printf("*** finished with options\n") ; #endif return ; }
/*! Replace a voxel's value by the value's rank in the entire set of input datasets */ int main( int argc , char * argv[] ) { THD_3dim_dataset ** dsets_in = NULL, *dset=NULL; /*input and output datasets*/ int nopt=0, nbriks=0, nsubbriks=0, ib=0, isb=0; byte *cmask=NULL; int *all_uniques=NULL, **uniques=NULL, *final_unq=NULL, *N_uniques=NULL; int N_final_unq=0, iun=0, total_unq=0; INT_HASH_DATUM *rmap=NULL, *hd=NULL; int imax=0, iunq=0, ii=0, id = 0; long int off=0; char *prefix=NULL; char stmp[THD_MAX_PREFIX+1]={""}; FILE *fout=NULL; /*----- Read command line -----*/ if( argc < 2 || strcmp(argv[1],"-help") == 0 ){ Rank_help (); exit(0) ; } mainENTRY("3dRank main"); machdep(); AFNI_logger("3dRank",argc,argv); nopt = 1 ; while( nopt < argc && argv[nopt][0] == '-' ){ if( strcmp(argv[nopt],"-ver") == 0 ){ PRINT_VERSION("3dRank"); AUTHOR("Ziad Saad"); nopt++; continue; } if( strcmp(argv[nopt],"-help") == 0 ){ Rank_help(); exit(0) ; } if( strcmp(argv[nopt],"-prefix") == 0 ){ ++nopt; if (nopt>=argc) { fprintf(stderr,"**ERROR: Need string after -prefix\n"); exit(1); } prefix = argv[nopt] ; ++nopt; continue; } if( strcmp(argv[nopt],"-input") == 0 ){ dsets_in = (THD_3dim_dataset**) calloc(argc-nopt+1, sizeof(THD_3dim_dataset*)); ++nopt; nbriks=0; while (nopt < argc ) { dsets_in[nbriks] = THD_open_dataset( argv[nopt] ); if( !ISVALID_DSET(dsets_in[nbriks]) ){ fprintf(stderr,"**ERROR: can't open dataset %s\n",argv[nopt]) ; exit(1); } ++nopt; ++nbriks; } continue; } ERROR_exit( " Error - unknown option %s", argv[nopt]); } if (nopt < argc) { ERROR_exit( " Error unexplained trailing option: %s\n", argv[nopt]); } if (!nbriks) { ERROR_exit( " Error no volumes entered on command line?"); } /* some checks and inits*/ nsubbriks = 0; for (ib = 0; ib<nbriks; ++ib) { if (!is_integral_dset(dsets_in[ib], 0)) { ERROR_exit("Dset %s is not of an integral data type.", DSET_PREFIX(dsets_in[ib])); } nsubbriks += DSET_NVALS(dsets_in[ib]); } /* Now get unique arrays */ uniques = (int **)calloc(nsubbriks, sizeof(int*)); N_uniques = (int *)calloc(nsubbriks, sizeof(int)); total_unq = 0; iun = 0; for (ib = 0; ib<nbriks; ++ib) { DSET_mallocize(dsets_in[ib]); DSET_load(dsets_in[ib]); for (isb=0; isb<DSET_NVALS(dsets_in[ib]); ++isb) { uniques[iun] = THD_unique_vals(dsets_in[ib], isb, &(N_uniques[iun]), cmask); total_unq += N_uniques[iun]; ++iun; } } /* put all the arrays together and get the unique of the uniques */ all_uniques = (int *)calloc(total_unq, sizeof(int)); off=0; for (iun=0; iun<nsubbriks; ++iun) { memcpy(all_uniques+off, uniques[iun], N_uniques[iun]*sizeof(int)); off += N_uniques[iun]; } /* free intermediate unique arrays */ for (iun=0; iun<nsubbriks; ++iun) { free(uniques[iun]); } free(uniques); uniques=NULL; free(N_uniques); N_uniques=NULL; /* get unique of catenated array */ if (!(final_unq = UniqueInt (all_uniques, total_unq, &N_final_unq, 0 ))) { ERROR_exit( " Failed to get unique list (%d, %d, %d) ", total_unq, N_final_unq, nsubbriks); } free(all_uniques); all_uniques=NULL; if (prefix) { snprintf(stmp, sizeof(char)*THD_MAX_PREFIX, "%s.rankmap.1D", prefix); } else { if (nbriks == 1) { snprintf(stmp, sizeof(char)*THD_MAX_PREFIX, "%s.rankmap.1D", DSET_PREFIX(dsets_in[0])); } else { snprintf(stmp, sizeof(char)*THD_MAX_PREFIX, "%s+.rankmap.1D", DSET_PREFIX(dsets_in[0])); } } if (stmp[0]) { if ((fout = fopen(stmp,"w"))) { fprintf(fout, "#Rank Map (%d unique values)\n", N_final_unq); fprintf(fout, "#Col. 0: Rank\n"); fprintf(fout, "#Col. 1: Input Dset Value\n"); } } /* get the maximum integer in the unique array */ imax = 0; for (iunq=0; iunq<N_final_unq; ++iunq) { if (final_unq[iunq] > imax) imax = final_unq[iunq]; if (fout) fprintf(fout, "%d %d\n", iunq, final_unq[iunq]); hd = (INT_HASH_DATUM*)calloc(1,sizeof(INT_HASH_DATUM)); hd->id = final_unq[iunq]; hd->index = iunq; HASH_ADD_INT(rmap, id, hd); } fclose(fout); fout=NULL; /* now cycle over all dsets and replace their voxel values with rank */ for (ib = 0; ib<nbriks; ++ib) { for (isb=0; isb<DSET_NVALS(dsets_in[ib]); ++isb) { EDIT_BRICK_LABEL( dsets_in[ib],isb, "rank" ) ; EDIT_BRICK_TO_NOSTAT( dsets_in[ib],isb ) ; EDIT_BRICK_FACTOR( dsets_in[ib],isb, 0.0);/* no factors for rank*/ switch (DSET_BRICK_TYPE(dsets_in[ib],isb) ){ default: fprintf(stderr, "** Bad dset type for unique operation.\n" "Only Byte, Short, and float dsets are allowed.\n"); break ; /* this should not happen here, so don't bother returning*/ case MRI_short:{ short *mar = (short *) DSET_ARRAY(dsets_in[ib],isb) ; if (imax > MRI_TYPE_maxval[MRI_short]) { WARNING_message("Maximum rank value of %d is\n" "than maximum value for dset datatype of %d\n", imax, MRI_TYPE_maxval[MRI_short]); } for( ii=0 ; ii < DSET_NVOX(dsets_in[ib]) ; ii++ ) if (!cmask || cmask[ii]) { id = (int)mar[ii]; HASH_FIND_INT(rmap,&id ,hd); if (hd) mar[ii] = (short)(hd->index); else ERROR_exit("** Failed to find key %d in hash table\n",id); } else mar[ii] = 0; } break ; case MRI_byte:{ byte *mar ; if (imax > MRI_TYPE_maxval[MRI_short]) { WARNING_message("Maximum rank value of %d is\n" "than maximum value for dset datatype of %d\n", imax, MRI_TYPE_maxval[MRI_byte]); } mar = (byte *) DSET_ARRAY(dsets_in[ib],isb) ; for( ii=0 ; ii < DSET_NVOX(dsets_in[ib]) ; ii++ ) if (!cmask || cmask[ii]) { id = (int)mar[ii]; HASH_FIND_INT(rmap,&id ,hd); if (hd) mar[ii] = (byte)(hd->index); else ERROR_exit("** Failed to find key %d in hash table\n",id); } else mar[ii] = 0; } break ; case MRI_float:{ float *mar = (float *) DSET_ARRAY(dsets_in[ib],isb) ; for( ii=0 ; ii < DSET_NVOX(dsets_in[ib]) ; ii++ ) if (!cmask || cmask[ii]) { id = (int)mar[ii]; /* Assuming float is integral valued */ HASH_FIND_INT(rmap,&id ,hd); if (hd) mar[ii] = (float)(hd->index); else ERROR_exit("** Failed to find key %d in hash table\n",id); } else mar[ii] = 0; } break ; } } /* update range, etc. */ THD_load_statistics(dsets_in[ib]); /* Now write the bricks */ if (prefix) { if (nbriks == 1) { snprintf(stmp, sizeof(char)*THD_MAX_PREFIX, "%s", prefix); } else { snprintf(stmp, sizeof(char)*THD_MAX_PREFIX, "r%02d.%s", ib, prefix); } } else { snprintf(stmp, sizeof(char)*THD_MAX_PREFIX, "rank.%s", DSET_PREFIX(dsets_in[ib])); } EDIT_dset_items( dsets_in[ib] , ADN_prefix , stmp , ADN_none ) ; /* change storage mode, this way prefix will determine format of output dset */ dsets_in[ib]->dblk->diskptr->storage_mode = STORAGE_BY_BRICK; tross_Make_History( "3dRank" , argc, argv , dsets_in[ib] ) ; if (DSET_IS_MASTERED(dsets_in[ib])) { /* THD_write_3dim_dataset won't write a mastered dude */ dset = EDIT_full_copy(dsets_in[ib],stmp); } else { dset = dsets_in[ib]; } /* New ID */ ZERO_IDCODE(dset->idcode); dset->idcode = MCW_new_idcode() ; if (!THD_write_3dim_dataset( NULL, stmp, dset,True )) { ERROR_message("Failed to write %s", stmp); exit(1); } else { WROTE_DSET(dsets_in[ib]); if (dset != dsets_in[ib]) DSET_deletepp(dset); DSET_deletepp(dsets_in[ib]); } } /* destroy hash */ while (rmap) { hd = rmap; HASH_DEL(rmap,hd); free(hd); } free(final_unq); final_unq=NULL; exit(0); }
int main( int argc , char *argv[] ) { int iarg=1 , ii , do_iwarp=0 ; char *prefix = "NwarpCat" ; mat44 wmat , smat , qmat ; THD_3dim_dataset *oset=NULL ; char *cwarp_all=NULL ; int ntot=0 ; AFNI_SETUP_OMP(0) ; /* 24 Jun 2013 */ if( argc < 2 || strcasecmp(argv[1],"-help") == 0 ) NWC_help() ; /*-- bureaucracy --*/ mainENTRY("3dNwarpCat"); machdep(); AFNI_logger("3dNwarpCat",argc,argv); PRINT_VERSION("3dNwarpCat"); AUTHOR("Zhark the Warper"); (void)COX_clock_time() ; putenv("AFNI_WSINC5_SILENT=YES") ; /*-- initialization --*/ CW_no_expad = 1 ; /* don't allow automatic padding of input warp */ Hverb = 0 ; /* don't be verbose inside mri_nwarp.c */ for( ii=0 ; ii < NWMAX ; ii++ ) cwarp[ii] = NULL ; /*-- scan args --*/ while( iarg < argc && argv[iarg][0] == '-' ){ /*---------------*/ if( strcasecmp(argv[iarg],"-iwarp") == 0 ){ do_iwarp = 1 ; iarg++ ; continue ; } /*---------------*/ if( strcasecmp(argv[iarg],"-space") == 0 ){ sname = strdup(argv[++iarg]) ; iarg++ ; continue ; } /*---------------*/ if( strcasecmp(argv[iarg],"-NN") == 0 || strncasecmp(argv[iarg],"-nearest",6) == 0 ){ WARNING_message("NN interpolation not legal here -- switched to linear") ; interp_code = MRI_LINEAR ; iarg++ ; continue ; } if( strncasecmp(argv[iarg],"-linear",4)==0 || strncasecmp(argv[iarg],"-trilinear",6)==0 ){ interp_code = MRI_LINEAR ; iarg++ ; continue ; } if( strncasecmp(argv[iarg],"-cubic",4)==0 || strncasecmp(argv[iarg],"-tricubic",6)==0 ){ WARNING_message("cubic interplation not legal here -- switched to quintic") ; interp_code = MRI_QUINTIC ; iarg++ ; continue ; } if( strncasecmp(argv[iarg],"-quintic",4)==0 || strncasecmp(argv[iarg],"-triquintic",6)==0 ){ interp_code = MRI_QUINTIC ; iarg++ ; continue ; } if( strncasecmp(argv[iarg],"-wsinc",5) == 0 ){ interp_code = MRI_WSINC5 ; iarg++ ; continue ; } /*---------------*/ if( strcasecmp(argv[iarg],"-expad") == 0 ){ int expad ; if( ++iarg >= argc ) ERROR_exit("no argument after '%s' :-(",argv[iarg-1]) ; expad = (int)strtod(argv[iarg],NULL) ; if( expad < 0 ){ WARNING_message("-expad %d is illegal and is set to zero",expad) ; expad = 0 ; } CW_extra_pad = expad ; /* this is how we force extra padding */ iarg++ ; continue ; } /*---------------*/ if( strncasecmp(argv[iarg],"-interp",5)==0 ){ char *inam ; if( ++iarg >= argc ) ERROR_exit("no argument after '%s' :-(",argv[iarg-1]) ; inam = argv[iarg] ; if( *inam == '-' ) inam++ ; if( strcasecmp(inam,"NN")==0 || strncasecmp(inam,"nearest",5)==0 ){ WARNING_message("NN interpolation not legal here -- changed to linear") ; interp_code = MRI_LINEAR ; } else if( strncasecmp(inam,"linear",3)==0 || strncasecmp(inam,"trilinear",5)==0 ){ interp_code = MRI_LINEAR ; } else if( strncasecmp(inam,"cubic",3)==0 || strncasecmp(inam,"tricubic",5)==0 ){ WARNING_message("cubic interplation not legal here -- changed to quintic") ; interp_code = MRI_QUINTIC ; } else if( strncasecmp(inam,"quintic",3)==0 || strncasecmp(inam,"triquintic",5)==0 ){ interp_code = MRI_QUINTIC ; } else if( strncasecmp(inam,"wsinc",4)==0 ){ interp_code = MRI_WSINC5 ; } else { ERROR_exit("Unknown code '%s' after '%s' :-(",argv[iarg],argv[iarg-1]) ; } iarg++ ; continue ; } /*---------------*/ if( strcasecmp(argv[iarg],"-verb") == 0 ){ verb++ ; NwarpCalcRPN_verb(verb) ; iarg++ ; continue ; } /*---------------*/ if( strcasecmp(argv[iarg],"-prefix") == 0 ){ if( ++iarg >= argc ) ERROR_exit("no argument after '%s' :-(",argv[iarg-1]) ; prefix = argv[iarg] ; if( !THD_filename_ok(prefix) ) ERROR_exit("Illegal name after '%s'",argv[iarg-1]) ; iarg++ ; continue ; } /*---------------*/ if( strncasecmp(argv[iarg],"-warp",5) == 0 ){ int nn ; if( iarg >= argc-1 ) ERROR_exit("no argument after '%s' :-(",argv[iarg]) ; if( !isdigit(argv[iarg][5]) ) ERROR_exit("illegal format for '%s' :-(",argv[iarg]) ; nn = (int)strtod(argv[iarg]+5,NULL) ; if( nn <= 0 || nn > NWMAX ) ERROR_exit("illegal warp index in '%s' :-(",argv[iarg]) ; if( cwarp[nn-1] != NULL ) ERROR_exit("'%s': you can't specify warp #%d more than once :-(",argv[iarg],nn) ; cwarp[nn-1] = strdup(argv[++iarg]) ; if( nn > nwtop ) nwtop = nn ; iarg++ ; continue ; } /*---------------*/ ERROR_message("Confusingly Unknown option '%s' :-(",argv[iarg]) ; suggest_best_prog_option(argv[0],argv[iarg]) ; exit(1) ; } /*-- load any warps left on the command line, after options --*/ for( ; iarg < argc && nwtop < NWMAX-1 ; iarg++ ) cwarp[nwtop++] = strdup(argv[iarg]) ; /*-- check if all warp strings are affine matrices --*/ #undef AFFINE_WARP_STRING #define AFFINE_WARP_STRING(ss) \ ( strstr((ss)," ") == NULL && \ ( strcasestr((ss),".1D") != NULL || strcasestr((ss),".txt") != NULL ) ) for( ntot=ii=0 ; ii < nwtop ; ii++ ){ if( cwarp[ii] == NULL ) continue ; ntot += strlen(cwarp[ii]) ; if( ! AFFINE_WARP_STRING(cwarp[ii]) ) break ; /* not affine */ } if( ntot == 0 ) ERROR_exit("No warps on command line?!") ; if( ii == nwtop ){ /* all are affine (this is for Ziad) */ char *fname = malloc(sizeof(char)*(strlen(prefix)+16)) ; FILE *fp ; float a11,a12,a13,a14,a21,a22,a23,a24,a31,a32,a33,a34 ; LOAD_IDENT_MAT44(wmat) ; for( ii=0 ; ii < nwtop ; ii++ ){ if( cwarp[ii] == NULL ) continue ; smat = CW_read_affine_warp_OLD(cwarp[ii]) ; qmat = MAT44_MUL(smat,wmat) ; wmat = qmat ; } if( strcmp(prefix,"-") == 0 || strncmp(prefix,"stdout",6) == 0 ){ fp = stdout ; strcpy(fname,"stdout") ; } else { strcpy(fname,prefix) ; if( strstr(fname,".1D") == NULL ) strcat(fname,".aff12.1D") ; fp = fopen(fname,"w") ; if( fp == NULL ) ERROR_exit("Can't open output matrix file %s",fname) ; } if( do_iwarp ){ qmat = MAT44_INV(wmat) ; wmat = qmat ; } UNLOAD_MAT44(wmat,a11,a12,a13,a14,a21,a22,a23,a24,a31,a32,a33,a34) ; fprintf(fp, " %13.6g %13.6g %13.6g %13.6g %13.6g %13.6g %13.6g %13.6g %13.6g %13.6g %13.6g %13.6g\n", a11,a12,a13,a14,a21,a22,a23,a24,a31,a32,a33,a34 ) ; if( verb && fp != stdout ) INFO_message("Wrote matrix to %s",fname) ; if( fp != stdout ) fclose(fp) ; exit(0) ; } /*** at least one nonlinear warp ==> cat all strings, use library function to read ***/ cwarp_all = (char *)calloc(sizeof(char),(ntot+NWMAX)*2) ; for( ii=0 ; ii < nwtop ; ii++ ){ if( cwarp[ii] != NULL ){ strcat(cwarp_all,cwarp[ii]) ; strcat(cwarp_all," ") ; } } oset = IW3D_read_catenated_warp( cwarp_all ) ; /* process all of them at once */ if( do_iwarp ){ /* 18 Jul 2014 */ THD_3dim_dataset *qwarp ; if( verb ) fprintf(stderr,"Applying -iwarp option") ; qwarp = THD_nwarp_invert(oset) ; DSET_delete(oset) ; oset = qwarp ; if( verb ) fprintf(stderr,"\n") ; } tross_Make_History( "3dNwarpCat" , argc,argv , oset ) ; if( sname != NULL ) MCW_strncpy( oset->atlas_space , sname , THD_MAX_NAME ) ; EDIT_dset_items( oset , ADN_prefix,prefix , ADN_none ) ; DSET_write(oset) ; WROTE_DSET(oset) ; /*--- run away screaming into the night, never to be seen again ---*/ INFO_message("total CPU time = %.1f sec Elapsed = %.1f\n", COX_cpu_time() , COX_clock_time() ) ; exit(0) ; }
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[] ) { THD_3dim_dataset *inset=NULL , *outset=NULL ; MCW_cluster *nbhd=NULL ; byte *mask=NULL ; int mask_nx,mask_ny,mask_nz , automask=0 ; char *prefix="./LocalCormat" ; int iarg=1 , verb=1 , ntype=0 , kk,nx,ny,nz,nxy,nxyz,nt , xx,yy,zz, vstep ; float na,nb,nc , dx,dy,dz ; MRI_IMARR *imar=NULL ; MRI_IMAGE *pim=NULL ; int mmlag=10 , ii,jj , do_arma=0 , nvout ; MRI_IMAGE *concim=NULL ; float *concar=NULL ; if( argc < 2 || strcmp(argv[1],"-help") == 0 ){ printf( "Usage: 3dLocalCORMAT [options] inputdataset\n" "\n" "Compute the correlation matrix (in time) of the input dataset,\n" "up to lag given by -maxlag. The matrix is averaged over the\n" "neighborhood specified by the -nbhd option, and then the entries\n" "are output at each voxel in a new dataset.\n" "\n" "Normally, the input to this program would be the -errts output\n" "from 3dDeconvolve, or the equivalent residuals from some other\n" "analysis. If you input a non-residual time series file, you at\n" "least should use an appropriate -polort level for detrending!\n" "\n" "Options:\n" " -input inputdataset\n" " -prefix ppp\n" " -mask mset {these 2 options are}\n" " -automask {mutually exclusive.}\n" " -nbhd nnn [e.g., 'SPHERE(9)' for 9 mm radius]\n" " -polort ppp [default = 0, which is reasonable for -errts output]\n" " -concat ccc [as in 3dDeconvolve]\n" " -maxlag mmm [default = 10]\n" " -ARMA [estimate ARMA(1,1) parameters into last 2 sub-bricks]\n" "\n" "A quick hack for my own benignant purposes -- RWCox -- June 2008\n" ) ; PRINT_COMPILE_DATE ; exit(0) ; } /*---- official startup ---*/ PRINT_VERSION("3dLocalCormat"); mainENTRY("3dLocalCormat main"); machdep(); AFNI_logger("3dLocalCormat",argc,argv); AUTHOR("Zhark the Toeplitzer"); /*---- loop over options ----*/ while( iarg < argc && argv[iarg][0] == '-' ){ #if 0 fprintf(stderr,"argv[%d] = %s\n",iarg,argv[iarg]) ; #endif if( strcmp(argv[iarg],"-ARMA") == 0 ){ do_arma = 1 ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-polort") == 0 ){ char *cpt ; if( ++iarg >= argc ) ERROR_exit("Need argument after option %s",argv[iarg-1]) ; pport = (int)strtod(argv[iarg],&cpt) ; if( *cpt != '\0' ) WARNING_message("Illegal non-numeric value after -polort") ; if( pport > 3 ){ pport = 3 ; WARNING_message("-polort set to 3 == max implemented") ; } else if( pport < 0 ){ pport = 0 ; WARNING_message("-polort set to 0 == min implemented") ; } iarg++ ; continue ; } if( strcmp(argv[iarg],"-input") == 0 ){ if( inset != NULL ) ERROR_exit("Can't have two -input options") ; if( ++iarg >= argc ) ERROR_exit("Need argument after '-input'") ; inset = THD_open_dataset( argv[iarg] ) ; CHECK_OPEN_ERROR(inset,argv[iarg]) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-prefix") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '-prefix'") ; prefix = strdup(argv[iarg]) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-mask") == 0 ){ THD_3dim_dataset *mset ; int mmm ; if( ++iarg >= argc ) ERROR_exit("Need argument after '-mask'") ; if( mask != NULL || automask ) ERROR_exit("Can't have two mask inputs") ; mset = THD_open_dataset( argv[iarg] ) ; CHECK_OPEN_ERROR(mset,argv[iarg]) ; DSET_load(mset) ; CHECK_LOAD_ERROR(mset) ; mask_nx = DSET_NX(mset); mask_ny = DSET_NY(mset); mask_nz = DSET_NZ(mset); mask = THD_makemask( mset , 0 , 0.5f, 0.0f ) ; DSET_delete(mset) ; if( mask == NULL ) ERROR_exit("Can't make mask from dataset '%s'",argv[iarg]) ; mmm = THD_countmask( mask_nx*mask_ny*mask_nz , mask ) ; INFO_message("Number of voxels in mask = %d",mmm) ; if( mmm < 2 ) ERROR_exit("Mask is too small to process") ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-automask") == 0 ){ if( mask != NULL ) ERROR_exit("Can't have -automask and -mask") ; automask = 1 ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-nbhd") == 0 ){ char *cpt ; if( ntype > 0 ) ERROR_exit("Can't have 2 '-nbhd' options") ; if( ++iarg >= argc ) ERROR_exit("Need argument after '-nbhd'") ; cpt = argv[iarg] ; if( strncasecmp(cpt,"SPHERE",6) == 0 ){ sscanf( cpt+7 , "%f" , &na ) ; if( na == 0.0f ) ERROR_exit("Can't have a SPHERE of radius 0") ; ntype = NTYPE_SPHERE ; } else if( strncasecmp(cpt,"RECT",4) == 0 ){ sscanf( cpt+5 , "%f,%f,%f" , &na,&nb,&nc ) ; if( na == 0.0f && nb == 0.0f && nc == 0.0f ) ERROR_exit("'RECT(0,0,0)' is not a legal neighborhood") ; ntype = NTYPE_RECT ; } else if( strncasecmp(cpt,"RHDD",4) == 0 ){ sscanf( cpt+5 , "%f" , &na ) ; if( na == 0.0f ) ERROR_exit("Can't have a RHDD of radius 0") ; ntype = NTYPE_RHDD ; } else { ERROR_exit("Unknown -nbhd shape: '%s'",cpt) ; } iarg++ ; continue ; } if( strcmp(argv[iarg],"-maxlag") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after option %s",argv[iarg-1]) ; mmlag = (int)strtod(argv[iarg],NULL) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-concat") == 0 ){ if( concim != NULL ) ERROR_exit("Can't have two %s options!",argv[iarg]) ; if( ++iarg >= argc ) ERROR_exit("Need argument after option %s",argv[iarg-1]) ; concim = mri_read_1D( argv[iarg] ) ; if( concim == NULL ) ERROR_exit("Can't read -concat file '%s'",argv[iarg]) ; if( concim->nx < 2 ) ERROR_exit("-concat file '%s' must have at least 2 entries!", argv[iarg]) ; concar = MRI_FLOAT_PTR(concim) ; for( ii=1 ; ii < concim->nx ; ii++ ) if( (int)concar[ii-1] >= (int)concar[ii] ) ERROR_exit("-concat file '%s' is not ordered increasingly!", argv[iarg]) ; iarg++ ; continue ; } ERROR_exit("Unknown option '%s'",argv[iarg]) ; } /*--- end of loop over options ---*/ if( do_arma && mmlag > 0 && mmlag < 5 ) ERROR_exit("Can't do -ARMA with -maxlag %d",mmlag) ; /*---- deal with input dataset ----*/ if( inset == NULL ){ if( iarg >= argc ) ERROR_exit("No input dataset on command line?") ; inset = THD_open_dataset( argv[iarg] ) ; CHECK_OPEN_ERROR(inset,argv[iarg]) ; } ntime = DSET_NVALS(inset) ; if( ntime < 9 ) ERROR_exit("Must have at least 9 values per voxel") ; DSET_load(inset) ; CHECK_LOAD_ERROR(inset) ; if( mask != NULL ){ if( mask_nx != DSET_NX(inset) || mask_ny != DSET_NY(inset) || mask_nz != DSET_NZ(inset) ) ERROR_exit("-mask dataset grid doesn't match input dataset") ; } else if( automask ){ int mmm ; mask = THD_automask( inset ) ; if( mask == NULL ) ERROR_message("Can't create -automask from input dataset?") ; mmm = THD_countmask( DSET_NVOX(inset) , mask ) ; INFO_message("Number of voxels in automask = %d",mmm) ; if( mmm < 2 ) ERROR_exit("Automask is too small to process") ; } /*-- set up blocks of continuous time data --*/ if( DSET_IS_TCAT(inset) ){ if( concim != NULL ){ WARNING_message("Ignoring -concat, since dataset is auto-catenated") ; mri_free(concim) ; } concim = mri_new(inset->tcat_num,1,MRI_float) ; concar = MRI_FLOAT_PTR(concim) ; concar[0] = 0.0 ; for( ii=0 ; ii < inset->tcat_num-1 ; ii++ ) concar[ii+1] = concar[ii] + inset->tcat_len[ii] ; } else if( concim == NULL ){ concim = mri_new(1,1,MRI_float) ; concar = MRI_FLOAT_PTR(concim) ; concar[0] = 0 ; } nbk = concim->nx ; bk = (int *)malloc(sizeof(int)*(nbk+1)) ; for( ii=0 ; ii < nbk ; ii++ ) bk[ii] = (int)concar[ii] ; bk[nbk] = ntime ; mri_free(concim) ; mlag = DSET_NVALS(inset) ; for( ii=0 ; ii < nbk ; ii++ ){ jj = bk[ii+1]-bk[ii] ; if( jj < mlag ) mlag = jj ; if( bk[ii] < 0 || jj < 9 ) ERROR_exit("something is rotten in the dataset run lengths") ; } mlag-- ; if( mmlag > 0 && mlag > mmlag ) mlag = mmlag ; else INFO_message("Max lag set to %d",mlag) ; if( do_arma && mlag < 5 ) ERROR_exit("Can't do -ARMA with maxlag=%d",mlag) ; /*---- create neighborhood (as a cluster) -----*/ if( ntype <= 0 ){ /* default neighborhood */ ntype = NTYPE_SPHERE ; na = -1.01f ; INFO_message("Using default neighborhood = self + 6 neighbors") ; } switch( ntype ){ default: ERROR_exit("WTF? ntype=%d",ntype) ; case NTYPE_SPHERE:{ if( na < 0.0f ){ dx = dy = dz = 1.0f ; na = -na ; } else { dx = fabsf(DSET_DX(inset)) ; dy = fabsf(DSET_DY(inset)) ; dz = fabsf(DSET_DZ(inset)) ; } nbhd = MCW_spheremask( dx,dy,dz , na ) ; } break ; case NTYPE_RECT:{ if( na < 0.0f ){ dx = 1.0f; na = -na; } else dx = fabsf(DSET_DX(inset)); if( nb < 0.0f ){ dy = 1.0f; nb = -nb; } else dy = fabsf(DSET_DY(inset)); if( nc < 0.0f ){ dz = 1.0f; nc = -nc; } else dz = fabsf(DSET_DZ(inset)); nbhd = MCW_rectmask( dx,dy,dz , na,nb,nc ) ; } break ; case NTYPE_RHDD:{ if( na < 0.0f ){ dx = dy = dz = 1.0f ; na = -na ; } else { dx = fabsf(DSET_DX(inset)) ; dy = fabsf(DSET_DY(inset)) ; dz = fabsf(DSET_DZ(inset)) ; } nbhd = MCW_rhddmask( dx,dy,dz , na ) ; } break ; } MCW_radsort_cluster( nbhd , dx,dy,dz ) ; /* 26 Feb 2008 */ INFO_message("Neighborhood comprises %d voxels",nbhd->num_pt) ; /** create output dataset **/ outset = EDIT_empty_copy(inset) ; nvout = mlag ; if( do_arma ) nvout += 2 ; EDIT_dset_items( outset, ADN_prefix , prefix, ADN_brick_fac, NULL , ADN_nvals , nvout , ADN_ntt , nvout , ADN_none ); tross_Copy_History( inset , outset ) ; tross_Make_History( "3dLocalCormat" , argc,argv , outset ) ; for( kk=0 ; kk < nvout ; kk++ ) EDIT_substitute_brick( outset , kk , MRI_float , NULL ) ; nx = DSET_NX(outset) ; ny = DSET_NY(outset) ; nxy = nx*ny ; nz = DSET_NZ(outset) ; nxyz = nxy*nz ; vstep = (verb && nxyz > 999) ? nxyz/50 : 0 ; if( vstep ) fprintf(stderr,"++ voxel loop: ") ; /** actually do the long long slog through all voxels **/ for( kk=0 ; kk < nxyz ; kk++ ){ if( vstep && kk%vstep==vstep-1 ) vstep_print() ; if( !INMASK(kk) ) continue ; IJK_TO_THREE( kk , xx,yy,zz , nx,nxy ) ; imar = THD_get_dset_nbhd_array( inset , mask , xx,yy,zz , nbhd ) ; if( imar == NULL ) continue ; pim = mri_cormat_vector(imar) ; DESTROY_IMARR(imar) ; if( pim == NULL ) continue ; THD_insert_series( kk, outset, pim->nx, MRI_float, MRI_FLOAT_PTR(pim), 0 ) ; if( do_arma ){ /* estimate ARMA(1,1) params and store those, too */ float_pair ab ; float *aa=DSET_ARRAY(outset,mlag), *bb=DSET_ARRAY(outset,mlag+1) ; ab = estimate_arma11( pim->nx , MRI_FLOAT_PTR(pim) ) ; aa[kk] = ab.a ; bb[kk] = ab.b ; } mri_free(pim) ; } if( vstep ) fprintf(stderr,"\n") ; DSET_delete(inset) ; DSET_write(outset) ; WROTE_DSET(outset) ; exit(0) ; }
/* * 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); }
/*! Turn float arrays into sub-bricks of a preset type (based on code in 3dMean) dset (THD_3dim_dataset *) new dset to which arrays will be added far (float **) each far[i] is to become one sub-brick in dset nval (int) the number of arrays in far otype (int) the sub-brick type. Supported options are: MRI_float (so far scaleopt (char) scaling options: 'A' scale if needed 'F' do scale each sub-brick 'G' scale all sub-bricks with the same factor 'N' Do not scale verb (int) loquaciousness returns 1 if all is well 0 all hell broke loose */ int EDIT_add_bricks_from_far(THD_3dim_dataset *dset, float **far, int nval, int otype, char scaleopt, int verb) { int ii=0, kk=0, nxyz; ENTRY("EDIT_add_bricks_from_far"); if (scaleopt != 'A' && scaleopt != 'F' && scaleopt != 'G' && scaleopt != 'N'){ ERROR_message("Bad scaleopt value of %c", scaleopt); RETURN(0); } if (!dset) { ERROR_message("NULL input"); RETURN(0); } nxyz = DSET_NVOX(dset); switch( otype ){ default: ERROR_message("Somehow ended up with otype = %d\n",otype) ; RETURN(0) ; case MRI_float:{ for( kk=0 ; kk < nval ; kk++ ){ EDIT_substitute_brick(dset, kk, MRI_float, far[kk]); DSET_BRICK_FACTOR(dset, kk) = 0.0; far[kk] = NULL; } } break ; case MRI_byte: case MRI_short:{ void ** dfim ; float gtop=0.0 , fimfac , gtemp ; if( verb ) fprintf(stderr," ++ Scaling output to type %s brick(s)\n", MRI_TYPE_name[otype] ) ; dfim = (void **) malloc(sizeof(void *)*nval) ; if( scaleopt == 'G' ){ /* allow global scaling */ gtop = 0.0 ; for( kk=0 ; kk < nval ; kk++ ){ gtemp = MCW_vol_amax( nxyz , 1 , 1 , MRI_float, far[kk] ) ; gtop = MAX( gtop , gtemp ) ; if( gtemp == 0.0 ) WARNING_message("output sub-brick %d is all zeros!\n",kk) ; } } for (kk = 0 ; kk < nval ; kk ++ ) { if( scaleopt != 'G' && scaleopt != 'N'){ /* compute max value in this sub-brick */ gtop = MCW_vol_amax( nxyz , 1 , 1 , MRI_float, far[kk] ) ; if( gtop == 0.0 ) WARNING_message("output sub-brick %d is all zeros!\n",kk) ; } if( scaleopt == 'F' || scaleopt == 'G'){ /* scaling needed */ fimfac = (gtop > 0.0) ? MRI_TYPE_maxval[otype] / gtop : 0.0 ; } else if( scaleopt == 'A' ){ /* only if needed */ fimfac = ( gtop > MRI_TYPE_maxval[otype] || (gtop > 0.0 && gtop < 1.0) ) ? MRI_TYPE_maxval[otype]/ gtop : 0.0 ; if( fimfac == 0.0 && gtop > 0.0 ){ /* 14 May 2010 */ float fv,iv ; /* force scaling if */ for( ii=0 ; ii < nxyz ; ii++ ){ /* non-integers are inside */ fv = far[kk][ii] ; iv = rint(fv) ; if( fabsf(fv-iv) >= 0.01 ){ fimfac = MRI_TYPE_maxval[otype] / gtop ; break ; } } } } else if( scaleopt == 'N') { /* no scaling allowed */ fimfac = 0.0 ; } else { ERROR_message("Should not see this one"); RETURN(0); } if( verb ){ if( fimfac != 0.0 ) INFO_message("Sub-brick %d scale factor = %f\n",kk,fimfac) ; else INFO_message("Sub-brick %d: no scale factor\n" ,kk) ; } dfim[kk] = (void *) malloc( mri_datum_size(otype) * nxyz ) ; if( dfim[kk] == NULL ){ ERROR_message("malloc fails at output\n"); exit(1); } EDIT_coerce_scale_type( nxyz , fimfac , MRI_float, far[kk] , otype,dfim[kk] ) ; if( otype == MRI_short ) EDIT_misfit_report( DSET_FILECODE(dset) , kk , nxyz , (fimfac != 0.0f) ? 1.0f/fimfac : 0.0f , dfim[kk] , far[kk] ) ; free( far[kk] ) ; far[kk] = NULL; EDIT_substitute_brick(dset, kk, otype, dfim[kk] ); DSET_BRICK_FACTOR(dset,kk) = (fimfac != 0.0) ? 1.0/fimfac : 0.0 ; dfim[kk]=NULL; } free(dfim); dfim = NULL; } break ; } RETURN(1); }
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) ; }
/* function for creating a sparse array from the thresholded correlation matrix of a vectim. This approach uses a histogram approach to implement a sparsity threshold if it is so desired. inputs: xvectim: the input time courses that will be correlated sparsity: the percentage of the top correlations that should be retained threshold: a threshold that should be applied to determine if a correlation should be retained. For sparsity thresholding this value will be used as an initial guess to speed calculation and a higher threshold may ultimately be calculated through the adaptive process. output: sparse_array_node: the list of remaining correlation values, or NULL if there was an error note: this function can use a _lot_ of memory if you the sparsity is too high, we tell the user how much memory we anticipate using, but this doesn't work for threshold only!*/ sparse_array_head_node* create_sparse_corr_array( MRI_vectim* xvectim, double sparsity, double thresh, double (*corfun)(long,float*,float*), long mem_allowance ) { /* random counters etc... */ long kout = 0; /* variables for histogram */ hist_node_head* histogram=NULL; sparse_array_head_node* sparse_array=NULL; sparse_array_node* recycled_nodes=NULL; long bottom_node_idx = 0; long totNumCor = 0; long totPosCor = 0; long ngoal = 0; long nretain = 0; float binwidth = 0.0; long nhistbins = 10000; long mem_budget = 0; /* retain the original threshold*/ double othresh = thresh; /* set the memory budget from the allowance */ mem_budget = mem_allowance; INFO_message( "Starting create_sparse_corr_array with a memory allowance of %ld", mem_budget); /* calculate the total number of possible correlations */ totPosCor = .5 * ( xvectim->nvec -1 ) * ( xvectim->nvec ); /* create a head node for the sparse array */ sparse_array = (sparse_array_head_node*)calloc(1,sizeof(sparse_array_head_node)); if( sparse_array == NULL ) { ERROR_message( "Could not allocate header for sparse array\n" ); return(NULL); } /* decrement the memory budget to account for the sparse array header */ mem_budget = mem_budget - sizeof(sparse_array_head_node); /* check if we can do what is asked of us with the budget provided */ if( sparsity < 100.0 ) { /* figure the cost of the histogram into the memory budget */ mem_budget = mem_budget - nhistbins*sizeof(hist_node_head); /* and the number of desired correlations */ ngoal = nretain = (long)ceil(((double)totPosCor)*((double)sparsity) / 100.0); /* check to see if we want to use more memory than would be used by the full correlation matrix, if so, the we should probably just use full correlation - or min memory func */ if((ngoal * sizeof( sparse_array_node )) > mem_budget) { WARNING_message( "The sparse array with %3.2lf%% of the %ld total" " would exceed the memory budget (%3.2lf MB) refusing to proceed\n", sparsity, totPosCor,((double)mem_budget)/(1024.0*1024.0)); return( NULL ); } else { INFO_message( "The sparse array with %ld values will take %3.2lf" " MB of memory (budget = %3.2lf MB)\n", ngoal, (double)(ngoal * sizeof(sparse_array_node)) /(1024.0*1024.0), ((double)mem_budget)/(1024.0*1024.0)); } } else { WARNING_message( "Cannot pre-calculate the memory required for a sparse" " matrix when only a correlation threshold is used. " "Instead the mem is tracked and if we exceed what " "would be used by the non-sparse array, the operation" " will be aborted."); } INFO_message( "Extracting sparse correlation array with threshold = %f and" " sparsity = %3.2f%% (%d)\n", thresh, sparsity, nretain); /* if we are using a sparsity threshold, setup the histogram to sort the values */ if ( sparsity < 100.0 ) { /* make sure that there is a bin for correlation values that == 1.0 */ binwidth = (1.005-thresh)/nhistbins; /* allocate memory for the histogram bins */ if(( histogram = (hist_node_head*)malloc(nhistbins*sizeof(hist_node_head))) == NULL ) { /* if the allocation fails, free all memory and exit */ ERROR_message( "Could not allocate %d byte array for histogram\n", nhistbins*sizeof(hist_node_head)); return( NULL ); } /* initialize history bins */ for( kout = 0; kout < nhistbins; kout++ ) { histogram[ kout ].bin_low = thresh+kout*binwidth; histogram[ kout ].bin_high = histogram[ kout ].bin_low+binwidth; histogram[ kout ].nbin = 0; histogram[ kout ].nodes = NULL; histogram[ kout ].tail = NULL; /* INFO_message("Hist bin %d [%3.3f, %3.3f) [%d, %p]\n", kout, histogram[ kout ].bin_low, histogram[ kout ].bin_high, histogram[ kout ].nbin, histogram[ kout ].nodes ); */ } } /*---------- loop over mask voxels, correlate ----------*/ AFNI_OMP_START ; #pragma omp parallel if( xvectim->nvec > 999 ) { int lii,ljj,lin,lout,ithr,nthr,vstep,vii ; float *xsar , *ysar ; sparse_array_node* new_node = NULL ; int new_node_idx = 0; double car = 0.0 ; /*-- get information about who we are --*/ #ifdef USE_OMP ithr = omp_get_thread_num() ; nthr = omp_get_num_threads() ; if( ithr == 0 ) INFO_message("%d OpenMP threads started",nthr) ; #else ithr = 0 ; nthr = 1 ; #endif /*-- For the progress tracker, we want to print out 50 numbers, figure out a number of loop iterations that will make this easy */ vstep = (int)( xvectim->nvec / (nthr*50.0f) + 0.901f ) ; vii = 0 ; if(ithr == 0 ) fprintf(stderr,"Looping:") ; #pragma omp for schedule(static, 1) for( lout=0 ; lout < xvectim->nvec ; lout++ ) { /*----- outer voxel loop -----*/ if( ithr == 0 && vstep > 2 ) /* allow small dsets 16 Jun 2011 [rickr] */ { vii++; if( vii%vstep == vstep/2 ) { vstep_print(); } } /* if the amount of memory exceeds budget, dont do anything more */ if ( mem_budget >= 0 ) { /* get ref time series from this voxel */ xsar = VECTIM_PTR(xvectim,lout); /* try to make calculation more efficient by only calculating the unique correlations */ for( lin=(lout+1) ; lin < xvectim->nvec ; lin++ ) { /*----- inner loop over voxels -----*/ if ( mem_budget >= 0 ) { /* extract the voxel time series */ ysar = VECTIM_PTR(xvectim,lin); /* now correlate the time series */ car = (double)(corfun(xvectim->nvals,xsar,ysar)); if ( car < thresh ) { continue; } #pragma omp critical(dataupdate) { /* the threshold might have changed while we were waiting, so check it again */ if (car >= thresh ) { /* create a node to add to the histogram, try to use a recycled node to save time and memory */ if ( recycled_nodes == NULL ) { mem_budget = mem_budget - sizeof(sparse_array_node); if( mem_budget >= 0 ) { new_node = (sparse_array_node*)calloc(1,sizeof(sparse_array_node)); } else { new_node = NULL; } } else { new_node = recycled_nodes; recycled_nodes = recycled_nodes->next; new_node->next = NULL; } if( new_node == NULL ) { /* allocate memory for this node, rather than fiddling with error handling here, lets just move on */ WARNING_message("Could not allocate a new node!"); } else { new_node->weight = car; new_node->row = lout; new_node->column = lin; totNumCor += 1; /* if keeping all connections, just add to linked list */ if ( sparsity >= 100.0 ) { new_node->next = sparse_array->nodes; sparse_array->nodes = new_node; sparse_array->num_nodes = sparse_array->num_nodes + 1; new_node = NULL; } /* otherwise, populate to proper bin of histogram */ else { /* determine the index in the histogram to add the node */ new_node_idx = (int)floor((double)(car-othresh)/(double)binwidth); if ((new_node_idx > nhistbins) || (new_node_idx < bottom_node_idx)) { /* this error should indicate a programming error and should not happen */ /*WARNING_message("Node index %d (%3.4lf >= %3.4lf) is out of range [%d,%d)" " {[%3.4lf, %3.4lf)}!",new_node_idx, car, thresh, bottom_node_idx, nhistbins, histogram[bottom_node_idx].bin_low, histogram[bottom_node_idx].bin_high ); */ } else { /* populate histogram node */ new_node->row = lout; new_node->column = lin; new_node->weight = car; new_node->next = NULL; /* update histogram bin linked-list */ new_node->next = histogram[new_node_idx].nodes; histogram[new_node_idx].nodes = new_node; /* if first node in bin, point tail to node */ if (histogram[new_node_idx].tail == NULL) { histogram[new_node_idx].tail = new_node; } /* increment bin count */ histogram[new_node_idx].nbin++; /* see if there are enough correlations in the histogram for the sparsity - prune un-needed hist bins*/ while ((totNumCor - histogram[bottom_node_idx].nbin) > nretain) { /* push the histogram nodes onto the list of recycled nodes, it could be that this hist bin is empty, in which case we have nothing to add */ if( histogram[bottom_node_idx].tail != NULL ) { histogram[bottom_node_idx].tail->next = recycled_nodes; recycled_nodes = histogram[bottom_node_idx].nodes; } else { if( histogram[bottom_node_idx].nbin != 0 ) { WARNING_message("Trying to remove histogram bin that contains" " %d values, but whose tail pointer is NULL\n", histogram[bottom_node_idx].nbin); } } /* bookkeeping */ histogram[bottom_node_idx].nodes = NULL; histogram[bottom_node_idx].tail = NULL; totNumCor -= histogram[bottom_node_idx].nbin; histogram[bottom_node_idx].nbin = 0; /* get the new threshold */ thresh = (double)histogram[++bottom_node_idx].bin_low; /*INFO_message("Increasing threshold to %3.2f (%d)\n", thresh,bottom_node_idx); */ } /* while */ } /* else, new_node_idx in range */ } /* else, sparsity >= 100.0 */ } /* else, new_node != NULL */ } /* if (car >= thresh ) */ } /* this is the end of the critical section */ } /* if ( mem_budget >= 0 ) */ } /* end of inner loop over voxels */ } /* if ( mem_budget >= 0 ) */ } /* end of outer loop over ref voxels */ if( ithr == 0 ) fprintf(stderr,".\n") ; } /* end OpenMP */ AFNI_OMP_END ; /* check to see if we exceeded memory or didn't get any correlations > threshold */ if (( mem_budget < 0 ) || ( totNumCor == 0 )) { if ( mem_budget < 0 ) { ERROR_message( "Memory budget (%lf MB) exceeded, consider using a" "higher correlation or lower sparsity threshold", ((double)mem_allowance/(1024.0*1024.0))); } else { ERROR_message( "No correlations exceeded threshold, consider using" " a lower correlation threshold"); } sparse_array = free_sparse_array( sparse_array ); } else { /* if using sparsity threshold, construct sparse array from the histogram */ if ( sparsity < 100.0 ) { /* pull the requested number of nodes off of the histogram */ for ( kout = (nhistbins-1); kout >= bottom_node_idx; kout-- ) { if((histogram[ kout ].nodes != NULL ) && (histogram[ kout ].nbin > 0)) { if( histogram[ kout ].tail == NULL ) { ERROR_message("Head is not null, but tail is?? (%ld)\n", kout); } /* push the list onto sparse array */ histogram[ kout ].tail->next = sparse_array->nodes; sparse_array->nodes = histogram[ kout ].nodes; /* increment the number of nodes */ sparse_array->num_nodes = sparse_array->num_nodes + histogram[ kout ].nbin; /* remove the references from the histogram, this is super important considering we don't want to accidently free any nodes that are on the sparse_array when we free the histogram later */ histogram[ kout ].nodes = NULL; histogram[ kout ].tail = NULL; histogram[ kout ].nbin = 0; } /* dont take more than we want */ if ( sparse_array->num_nodes > nretain ) break; } INFO_message( "Sparsity requested %ld and received %ld correlations" " (%3.2lf%% sparsity) final threshold = %3.4lf.\n", nretain, sparse_array->num_nodes, 100.0*((double)sparse_array->num_nodes)/((double)totPosCor), thresh); if( sparse_array->num_nodes < nretain ) { INFO_message( "Consider lowering the initial correlation" "threshold (%3.2lf) to retain more correlations.\n", othresh); } } else { INFO_message( "Correlation threshold (%3.2lf) resulted in %ld" " correlations (%3.2lf%% sparsity).\n", thresh, sparse_array->num_nodes, 100.0*((double)sparse_array->num_nodes)/((double)totPosCor)); } } /* free residual mem */ histogram = free_histogram( histogram, nhistbins ); recycled_nodes = free_sparse_list( recycled_nodes ); return( sparse_array ); }
int CalcPartCorrMatr( float **OUT, float **OUTB, float **IN, int M) { int BAD=0, BADB=0; // in case of badness in inversion int i,j,k; float aa,bb; gsl_matrix *PC = gsl_matrix_alloc(M,M); // part corr gsl_matrix *CC = gsl_matrix_alloc(M,M); // input corr gsl_permutation *P = gsl_permutation_alloc(M); // Initialize gsl_matrix_set_zero(PC); for( i=0 ; i<M ; i++) for( j=0 ; j<M ; j++) gsl_matrix_set(CC, i, j, IN[i][j]); // perform the LU decomp + inversion j = gsl_linalg_LU_decomp(CC, P, &k); j = gsl_linalg_LU_invert(CC, P, PC); for( i=0 ; i<M ; i++) for( j=0 ; j<M ; j++) { OUT[i][j] = OUTB[i][j] = - ((float) gsl_matrix_get(PC, i, j)); bb = (float) gsl_matrix_get(PC, i, i); if( bb ) OUTB[i][j]/= bb; else { WARNING_message("Badness in partial correlation beta calculation.\n" "\tNormalizing factor is =0 (how to divide?)!\n" "\t-> making all zeros."); BADB = 1; } aa = (float) gsl_matrix_get(PC, i, i) * (float) gsl_matrix_get(PC, j, j); if(aa>0) OUT[i][j]/= sqrt(aa); else { WARNING_message("Badness in partial correlation calculation.\n" "\tNormalizing factor is <=0 (how to take sqrt?)!\n" "\t-> making all zeros."); BAD = 1; } } if(BAD) for( i=0 ; i<M ; i++) for( j=0 ; j<M ; j++) OUT[i][j] = 0.; if(BADB) for( i=0 ; i<M ; i++) for( j=0 ; j<M ; j++) OUTB[i][j] = 0.; // free gsl_matrix_free(PC); gsl_matrix_free(CC); gsl_permutation_free(P); RETURN(1); }
int main( int argc , char *argv[] ) { THD_3dim_dataset *xset , *cset, *mset=NULL ; int nopt=1 , method=PEARSON , do_autoclip=0 ; int nvox , nvals , ii, jj, kout, kin, polort=1 ; int ix1,jy1,kz1, ix2, jy2, kz2 ; char *prefix = "degree_centrality" ; byte *mask=NULL; int nmask , abuc=1 ; int all_source=0; /* output all source voxels 25 Jun 2010 [rickr] */ char str[32] , *cpt ; int *imap = NULL ; MRI_vectim *xvectim ; float (*corfun)(int,float *,float*) = NULL ; /* djc - add 1d file output for similarity matrix */ FILE *fout1D=NULL; /* CC - we will have two subbricks: binary and weighted centrality */ int nsubbriks = 2; int subbrik = 0; float * bodset; float * wodset; int nb_ctr = 0; /* CC - added flags for thresholding correlations */ double thresh = 0.0; double othresh = 0.0; int dothresh = 0; double sparsity = 0.0; int dosparsity = 0; /* variables for calculating degree centrality */ long * binaryDC = NULL; double * weightedDC = NULL; /* variables for histogram */ hist_node_head* histogram=NULL; hist_node* hptr=NULL; hist_node* pptr=NULL; int bottom_node_idx = 0; int totNumCor = 0; long totPosCor = 0; int ngoal = 0; int nretain = 0; float binwidth = 0.0; int nhistnodes = 50; /*----*/ AFNI_SETUP_OMP(0) ; /* 24 Jun 2013 */ if( argc < 2 || strcmp(argv[1],"-help") == 0 ){ printf( "Usage: 3dDegreeCentrality [options] dset\n" " Computes voxelwise weighted and binary degree centrality and\n" " stores the result in a new 3D bucket dataset as floats to\n" " preserve their values. Degree centrality reflects the strength and\n" " extent of the correlation of a voxel with every other voxel in\n" " the brain.\n\n" " Conceptually the process involves: \n" " 1. Calculating the correlation between voxel time series for\n" " every pair of voxels in the brain (as determined by masking)\n" " 2. Applying a threshold to the resulting correlations to exclude\n" " those that might have arisen by chance, or to sparsify the\n" " connectivity graph.\n" " 3. At each voxel, summarizing its correlation with other voxels\n" " in the brain, by either counting the number of voxels correlated\n" " with the seed voxel (binary) or by summing the correlation \n" " coefficients (weighted).\n" " Practically the algorithm is ordered differently to optimize for\n" " computational time and memory usage.\n\n" " The threshold can be supplied as a correlation coefficient, \n" " or a sparsity threshold. The sparsity threshold reflects the fraction\n" " of connections that should be retained after the threshold has been\n" " applied. To minimize resource consumption, using a sparsity threshold\n" " involves a two-step procedure. In the first step, a correlation\n" " coefficient threshold is applied to substantially reduce the number\n" " of correlations. Next, the remaining correlations are sorted and a\n" " threshold is calculated so that only the specified fraction of \n" " possible correlations are above threshold. Due to ties between\n" " correlations, the fraction of correlations that pass the sparsity\n" " threshold might be slightly more than the number specified.\n\n" " Regardless of the thresholding procedure employed, negative \n" " correlations are excluded from the calculations.\n" "\n" "Options:\n" " -pearson = Correlation is the normal Pearson (product moment)\n" " correlation coefficient [default].\n" #if 0 " -spearman = Correlation is the Spearman (rank) correlation\n" " coefficient.\n" " -quadrant = Correlation is the quadrant correlation coefficient.\n" #else " -spearman AND -quadrant are disabled at this time :-(\n" #endif "\n" " -thresh r = exclude correlations <= r from calculations\n" " -sparsity s = only use top s percent of correlations in calculations\n" " s should be an integer between 0 and 100. Uses an\n" " an adaptive thresholding procedure to reduce memory.\n" " The speed of determining the adaptive threshold can\n" " be improved by specifying an initial threshold with\n" " the -thresh flag.\n" "\n" " -polort m = Remove polynomical trend of order 'm', for m=-1..3.\n" " [default is m=1; removal is by least squares].\n" " Using m=-1 means no detrending; this is only useful\n" " for data/information that has been pre-processed.\n" "\n" " -autoclip = Clip off low-intensity regions in the dataset,\n" " -automask = so that the correlation is only computed between\n" " high-intensity (presumably brain) voxels. The\n" " mask is determined the same way that 3dAutomask works.\n" "\n" " -mask mmm = Mask to define 'in-brain' voxels. Reducing the number\n" " the number of voxels included in the calculation will\n" " significantly speedup the calculation. Consider using\n" " a mask to constrain the calculations to the grey matter\n" " rather than the whole brain. This is also preferrable\n" " to using -autoclip or -automask.\n" "\n" " -prefix p = Save output into dataset with prefix 'p', this file will\n" " contain bricks for both 'weighted' or 'degree' centrality\n" " [default prefix is 'deg_centrality'].\n" "\n" " -out1D f = Save information about the above threshold correlations to\n" " 1D file 'f'. Each row of this file will contain:\n" " Voxel1 Voxel2 i1 j1 k1 i2 j2 k2 Corr\n" " Where voxel1 and voxel2 are the 1D indices of the pair of\n" " voxels, i j k correspond to their 3D coordinates, and Corr\n" " is the value of the correlation between the voxel time courses.\n" "\n" "Notes:\n" " * The output dataset is a bucket type of floats.\n" " * The program prints out an estimate of its memory used\n" " when it ends. It also prints out a progress 'meter'\n" " to keep you pacified.\n" "\n" "-- RWCox - 31 Jan 2002 and 16 Jul 2010\n" "-- Cameron Craddock - 26 Sept 2015 \n" ) ; PRINT_AFNI_OMP_USAGE("3dDegreeCentrality",NULL) ; PRINT_COMPILE_DATE ; exit(0) ; } mainENTRY("3dDegreeCentrality main"); machdep(); PRINT_VERSION("3dDegreeCentrality"); AFNI_logger("3dDegreeCentrality",argc,argv); /*-- option processing --*/ while( nopt < argc && argv[nopt][0] == '-' ){ if( strcmp(argv[nopt],"-time") == 0 ){ abuc = 0 ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-autoclip") == 0 || strcmp(argv[nopt],"-automask") == 0 ){ do_autoclip = 1 ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-mask") == 0 ){ mset = THD_open_dataset(argv[++nopt]); CHECK_OPEN_ERROR(mset,argv[nopt]); nopt++ ; continue ; } if( strcmp(argv[nopt],"-pearson") == 0 ){ method = PEARSON ; nopt++ ; continue ; } #if 0 if( strcmp(argv[nopt],"-spearman") == 0 ){ method = SPEARMAN ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-quadrant") == 0 ){ method = QUADRANT ; nopt++ ; continue ; } #endif if( strcmp(argv[nopt],"-eta2") == 0 ){ method = ETA2 ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-prefix") == 0 ){ prefix = strdup(argv[++nopt]) ; if( !THD_filename_ok(prefix) ){ ERROR_exit("Illegal value after -prefix!") ; } nopt++ ; continue ; } if( strcmp(argv[nopt],"-thresh") == 0 ){ double val = (double)strtod(argv[++nopt],&cpt) ; if( *cpt != '\0' || val >= 1.0 || val < 0.0 ){ ERROR_exit("Illegal value (%f) after -thresh!", val) ; } dothresh = 1; thresh = val ; othresh = val ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-sparsity") == 0 ){ double val = (double)strtod(argv[++nopt],&cpt) ; if( *cpt != '\0' || val > 100 || val <= 0 ){ ERROR_exit("Illegal value (%f) after -sparsity!", val) ; } if( val > 5.0 ) { WARNING_message("Sparsity %3.2f%% is large and will require alot of memory and time, consider using a smaller value. ", val); } dosparsity = 1 ; sparsity = val ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-polort") == 0 ){ int val = (int)strtod(argv[++nopt],&cpt) ; if( *cpt != '\0' || val < -1 || val > 3 ){ ERROR_exit("Illegal value after -polort!") ; } polort = val ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-mem_stat") == 0 ){ MEM_STAT = 1 ; nopt++ ; continue ; } if( strncmp(argv[nopt],"-mem_profile",8) == 0 ){ MEM_PROF = 1 ; nopt++ ; continue ; } /* check for 1d argument */ if ( strcmp(argv[nopt],"-out1D") == 0 ){ if (!(fout1D = fopen(argv[++nopt], "w"))) { ERROR_message("Failed to open %s for writing", argv[nopt]); exit(1); } nopt++ ; continue ; } ERROR_exit("Illegal option: %s",argv[nopt]) ; } /*-- open dataset, check for legality --*/ if( nopt >= argc ) ERROR_exit("Need a dataset on command line!?") ; xset = THD_open_dataset(argv[nopt]); CHECK_OPEN_ERROR(xset,argv[nopt]); if( DSET_NVALS(xset) < 3 ) ERROR_exit("Input dataset %s does not have 3 or more sub-bricks!",argv[nopt]) ; DSET_load(xset) ; CHECK_LOAD_ERROR(xset) ; /*-- compute mask array, if desired --*/ nvox = DSET_NVOX(xset) ; nvals = DSET_NVALS(xset) ; INC_MEM_STATS((nvox * nvals * sizeof(double)), "input dset"); PRINT_MEM_STATS("inset"); /* if a mask was specified make sure it is appropriate */ if( mset ){ if( DSET_NVOX(mset) != nvox ) ERROR_exit("Input and mask dataset differ in number of voxels!") ; mask = THD_makemask(mset, 0, 1.0, 0.0) ; /* update running memory statistics to reflect loading the image */ INC_MEM_STATS( mset->dblk->total_bytes, "mask dset" ); PRINT_MEM_STATS( "mset load" ); nmask = THD_countmask( nvox , mask ) ; INC_MEM_STATS( nmask * sizeof(byte), "mask array" ); PRINT_MEM_STATS( "mask" ); INFO_message("%d voxels in -mask dataset",nmask) ; if( nmask < 2 ) ERROR_exit("Only %d voxels in -mask, exiting...",nmask); /* update running memory statistics to reflect loading the image */ DEC_MEM_STATS( mset->dblk->total_bytes, "mask dset" ); DSET_unload(mset) ; PRINT_MEM_STATS( "mset unload" ); } /* if automasking is requested, handle that now */ else if( do_autoclip ){ mask = THD_automask( xset ) ; nmask = THD_countmask( nvox , mask ) ; INFO_message("%d voxels survive -autoclip",nmask) ; if( nmask < 2 ) ERROR_exit("Only %d voxels in -automask!",nmask); } /* otherwise we use all of the voxels in the image */ else { nmask = nvox ; INFO_message("computing for all %d voxels",nmask) ; } if( method == ETA2 && polort >= 0 ) WARNING_message("Polort for -eta2 should probably be -1..."); /* djc - 1d file out init */ if (fout1D != NULL) { /* define affine matrix */ mat44 affine_mat = xset->daxes->ijk_to_dicom; /* print command line statement */ fprintf(fout1D,"#Similarity matrix from command:\n#"); for(ii=0; ii<argc; ++ii) fprintf(fout1D,"%s ", argv[ii]); /* Print affine matrix */ fprintf(fout1D,"\n"); fprintf(fout1D,"#[ "); int mi, mj; for(mi = 0; mi < 4; mi++) { for(mj = 0; mj < 4; mj++) { fprintf(fout1D, "%.6f ", affine_mat.m[mi][mj]); } } fprintf(fout1D, "]\n"); /* Print image extents*/ THD_dataxes *xset_daxes = xset->daxes; fprintf(fout1D, "#Image dimensions:\n"); fprintf(fout1D, "#[%d, %d, %d]\n", xset_daxes->nxx, xset_daxes->nyy, xset_daxes->nzz); /* Similarity matrix headers */ fprintf(fout1D,"#Voxel1 Voxel2 i1 j1 k1 i2 j2 k2 Corr\n"); } /* CC calculate the total number of possible correlations, will be usefule down the road */ totPosCor = (.5*((float)nmask))*((float)(nmask-1)); /** For the case of Pearson correlation, we make sure the **/ /** data time series have their mean removed (polort >= 0) **/ /** and are normalized, so that correlation = dot product, **/ /** and we can use function zm_THD_pearson_corr for speed. **/ switch( method ){ default: case PEARSON: corfun = zm_THD_pearson_corr ; break ; case ETA2: corfun = my_THD_eta_squared ; break ; } /*-- create vectim from input dataset --*/ INFO_message("vectim-izing input dataset") ; /*-- CC added in mask to reduce the size of xvectim -- */ xvectim = THD_dset_to_vectim( xset , mask , 0 ) ; if( xvectim == NULL ) ERROR_exit("Can't create vectim?!") ; /*-- CC update our memory stats to reflect vectim -- */ INC_MEM_STATS((xvectim->nvec*sizeof(int)) + ((xvectim->nvec)*(xvectim->nvals))*sizeof(float) + sizeof(MRI_vectim), "vectim"); PRINT_MEM_STATS( "vectim" ); /*--- CC the vectim contains a mapping between voxel index and mask index, tap into that here to avoid duplicating memory usage ---*/ if( mask != NULL ) { imap = xvectim->ivec; /* --- CC free the mask */ DEC_MEM_STATS( nmask*sizeof(byte), "mask array" ); free(mask); mask=NULL; PRINT_MEM_STATS( "mask unload" ); } /* -- CC unloading the dataset to reduce memory usage ?? -- */ DEC_MEM_STATS((DSET_NVOX(xset) * DSET_NVALS(xset) * sizeof(double)), "input dset"); DSET_unload(xset) ; PRINT_MEM_STATS("inset unload"); /* -- CC configure detrending --*/ if( polort < 0 && method == PEARSON ){ polort = 0; WARNING_message("Pearson correlation always uses polort >= 0"); } if( polort >= 0 ){ for( ii=0 ; ii < xvectim->nvec ; ii++ ){ /* remove polynomial trend */ DETREND_polort(polort,nvals,VECTIM_PTR(xvectim,ii)) ; } } /* -- this procedure does not change time series that have zero variance -- */ if( method == PEARSON ) THD_vectim_normalize(xvectim) ; /* L2 norm = 1 */ /* -- CC create arrays to hold degree and weighted centrality while they are being calculated -- */ if( dosparsity == 0 ) { if( ( binaryDC = (long*)calloc( nmask, sizeof(long) )) == NULL ) { ERROR_message( "Could not allocate %d byte array for binary DC calculation\n", nmask*sizeof(long)); } /* -- update running memory estimate to reflect memory allocation */ INC_MEM_STATS( nmask*sizeof(long), "binary DC array" ); PRINT_MEM_STATS( "binaryDC" ); if( ( weightedDC = (double*)calloc( nmask, sizeof(double) )) == NULL ) { if (binaryDC){ free(binaryDC); binaryDC = NULL; } ERROR_message( "Could not allocate %d byte array for weighted DC calculation\n", nmask*sizeof(double)); } /* -- update running memory estimate to reflect memory allocation */ INC_MEM_STATS( nmask*sizeof(double), "weighted DC array" ); PRINT_MEM_STATS( "weightedDC" ); } /* -- CC if we are using a sparsity threshold, build a histogram to calculate the threshold */ if (dosparsity == 1) { /* make sure that there is a bin for correlation values that == 1.0 */ binwidth = (1.005-thresh)/nhistnodes; /* calculate the number of correlations we wish to retain */ ngoal = nretain = (int)(((double)totPosCor)*((double)sparsity) / 100.0); /* allocate memory for the histogram bins */ if(( histogram = (hist_node_head*)malloc(nhistnodes*sizeof(hist_node_head))) == NULL ) { /* if the allocation fails, free all memory and exit */ if (binaryDC){ free(binaryDC); binaryDC = NULL; } if (weightedDC){ free(weightedDC); weightedDC = NULL; } ERROR_message( "Could not allocate %d byte array for histogram\n", nhistnodes*sizeof(hist_node_head)); } else { /* -- update running memory estimate to reflect memory allocation */ INC_MEM_STATS( nhistnodes*sizeof(hist_node_head), "hist bins" ); PRINT_MEM_STATS( "hist1" ); } /* initialize history bins */ for( kout = 0; kout < nhistnodes; kout++ ) { histogram[ kout ].bin_low = thresh+kout*binwidth; histogram[ kout ].bin_high = histogram[ kout ].bin_low+binwidth; histogram[ kout ].nbin = 0; histogram[ kout ].nodes = NULL; /*INFO_message("Hist bin %d [%3.3f, %3.3f) [%d, %p]\n", kout, histogram[ kout ].bin_low, histogram[ kout ].bin_high, histogram[ kout ].nbin, histogram[ kout ].nodes );*/ } } /*-- tell the user what we are about to do --*/ if (dosparsity == 0 ) { INFO_message( "Calculating degree centrality with threshold = %f.\n", thresh); } else { INFO_message( "Calculating degree centrality with threshold = %f and sparsity = %3.2f%% (%d)\n", thresh, sparsity, nretain); } /*---------- loop over mask voxels, correlate ----------*/ AFNI_OMP_START ; #pragma omp parallel if( nmask > 999 ) { int lii,ljj,lin,lout,ithr,nthr,vstep,vii ; float *xsar , *ysar ; hist_node* new_node = NULL ; hist_node* tptr = NULL ; hist_node* rptr = NULL ; int new_node_idx = 0; double car = 0.0 ; /*-- get information about who we are --*/ #ifdef USE_OMP ithr = omp_get_thread_num() ; nthr = omp_get_num_threads() ; if( ithr == 0 ) INFO_message("%d OpenMP threads started",nthr) ; #else ithr = 0 ; nthr = 1 ; #endif /*-- For the progress tracker, we want to print out 50 numbers, figure out a number of loop iterations that will make this easy */ vstep = (int)( nmask / (nthr*50.0f) + 0.901f ) ; vii = 0 ; if((MEM_STAT==0) && (ithr == 0 )) fprintf(stderr,"Looping:") ; #pragma omp for schedule(static, 1) for( lout=0 ; lout < xvectim->nvec ; lout++ ){ /*----- outer voxel loop -----*/ if( ithr == 0 && vstep > 2 ) /* allow small dsets 16 Jun 2011 [rickr] */ { vii++ ; if( vii%vstep == vstep/2 && MEM_STAT == 0 ) vstep_print(); } /* get ref time series from this voxel */ xsar = VECTIM_PTR(xvectim,lout) ; /* try to make calculation more efficient by only calculating the unique correlations */ for( lin=(lout+1) ; lin < xvectim->nvec ; lin++ ){ /*----- inner loop over voxels -----*/ /* extract the voxel time series */ ysar = VECTIM_PTR(xvectim,lin) ; /* now correlate the time series */ car = (double)(corfun(nvals,xsar,ysar)) ; if ( car <= thresh ) { continue ; } /* update degree centrality values, hopefully the pragma will handle mutual exclusion */ #pragma omp critical(dataupdate) { /* if the correlation is less than threshold, ignore it */ if ( car > thresh ) { totNumCor += 1; if ( dosparsity == 0 ) { binaryDC[lout] += 1; binaryDC[lin] += 1; weightedDC[lout] += car; weightedDC[lin] += car; /* print correlation out to the 1D file */ if ( fout1D != NULL ) { /* determine the i,j,k coords */ ix1 = DSET_index_to_ix(xset,lii) ; jy1 = DSET_index_to_jy(xset,lii) ; kz1 = DSET_index_to_kz(xset,lii) ; ix2 = DSET_index_to_ix(xset,ljj) ; jy2 = DSET_index_to_jy(xset,ljj) ; kz2 = DSET_index_to_kz(xset,ljj) ; /* add source, dest, correlation to 1D file */ fprintf(fout1D, "%d %d %d %d %d %d %d %d %.6f\n", lii, ljj, ix1, jy1, kz1, ix2, jy2, kz2, car); } } else { /* determine the index in the histogram to add the node */ new_node_idx = (int)floor((double)(car-othresh)/(double)binwidth); if ((new_node_idx > nhistnodes) || (new_node_idx < bottom_node_idx)) { /* this error should indicate a programming error and should not happen */ WARNING_message("Node index %d is out of range [%d,%d)!",new_node_idx, bottom_node_idx, nhistnodes); } else { /* create a node to add to the histogram */ new_node = (hist_node*)calloc(1,sizeof(hist_node)); if( new_node == NULL ) { /* allocate memory for this node, rather than fiddling with error handling here, lets just move on */ WARNING_message("Could not allocate a new node!"); } else { /* populate histogram node */ new_node->i = lout; new_node->j = lin; new_node->corr = car; new_node->next = NULL; /* -- update running memory estimate to reflect memory allocation */ INC_MEM_STATS( sizeof(hist_node), "hist nodes" ); if ((totNumCor % (1024*1024)) == 0) PRINT_MEM_STATS( "hist nodes" ); /* populate histogram */ new_node->next = histogram[new_node_idx].nodes; histogram[new_node_idx].nodes = new_node; histogram[new_node_idx].nbin++; /* see if there are enough correlations in the histogram for the sparsity */ if ((totNumCor - histogram[bottom_node_idx].nbin) > nretain) { /* delete the list of nodes */ rptr = histogram[bottom_node_idx].nodes; while(rptr != NULL) { tptr = rptr; rptr = rptr->next; /* check that the ptr is not null before freeing it*/ if(tptr!= NULL) { DEC_MEM_STATS( sizeof(hist_node), "hist nodes" ); free(tptr); } } PRINT_MEM_STATS( "unloaded hist nodes - thresh increase" ); histogram[bottom_node_idx].nodes = NULL; totNumCor -= histogram[bottom_node_idx].nbin; histogram[bottom_node_idx].nbin=0; /* get the new threshold */ thresh = (double)histogram[++bottom_node_idx].bin_low; if(MEM_STAT == 1) INFO_message("Increasing threshold to %3.2f (%d)\n", thresh,bottom_node_idx); } } /* else, newptr != NULL */ } /* else, new_node_idx in range */ } /* else, do_sparsity == 1 */ } /* car > thresh */ } /* this is the end of the critical section */ } /* end of inner loop over voxels */ } /* end of outer loop over ref voxels */ if( ithr == 0 ) fprintf(stderr,".\n") ; } /* end OpenMP */ AFNI_OMP_END ; /* update the user so that they know what we are up to */ INFO_message ("AFNI_OMP finished\n"); INFO_message ("Found %d (%3.2f%%) correlations above threshold (%f)\n", totNumCor, 100.0*((float)totNumCor)/((float)totPosCor), thresh); /*---------- Finish up ---------*/ /*if( dosparsity == 1 ) { for( kout = 0; kout < nhistnodes; kout++ ) { INFO_message("Hist bin %d [%3.3f, %3.3f) [%d, %p]\n", kout, histogram[ kout ].bin_low, histogram[ kout ].bin_high, histogram[ kout ].nbin, histogram[ kout ].nodes ); } }*/ /*-- create output dataset --*/ cset = EDIT_empty_copy( xset ) ; /*-- configure the output dataset */ if( abuc ){ EDIT_dset_items( cset , ADN_prefix , prefix , ADN_nvals , nsubbriks , /* 2 subbricks, degree and weighted centrality */ ADN_ntt , 0 , /* no time axis */ ADN_type , HEAD_ANAT_TYPE , ADN_func_type , ANAT_BUCK_TYPE , ADN_datum_all , MRI_float , ADN_none ) ; } else { EDIT_dset_items( cset , ADN_prefix , prefix , ADN_nvals , nsubbriks , /* 2 subbricks, degree and weighted centrality */ ADN_ntt , nsubbriks , /* num times */ ADN_ttdel , 1.0 , /* fake TR */ ADN_nsl , 0 , /* no slice offsets */ ADN_type , HEAD_ANAT_TYPE , ADN_func_type , ANAT_EPI_TYPE , ADN_datum_all , MRI_float , ADN_none ) ; } /* add history information to the hearder */ tross_Make_History( "3dDegreeCentrality" , argc,argv , cset ) ; ININFO_message("creating output dataset in memory") ; /* -- Configure the subbriks: Binary Degree Centrality */ subbrik = 0; EDIT_BRICK_TO_NOSTAT(cset,subbrik) ; /* stat params */ /* CC this sets the subbrik scaling factor, which we will probably want to do again after we calculate the voxel values */ EDIT_BRICK_FACTOR(cset,subbrik,1.0) ; /* scale factor */ sprintf(str,"Binary Degree Centrality") ; EDIT_BRICK_LABEL(cset,subbrik,str) ; EDIT_substitute_brick(cset,subbrik,MRI_float,NULL) ; /* make array */ /* copy measure data into the subbrik */ bodset = DSET_ARRAY(cset,subbrik); /* -- Configure the subbriks: Weighted Degree Centrality */ subbrik = 1; EDIT_BRICK_TO_NOSTAT(cset,subbrik) ; /* stat params */ /* CC this sets the subbrik scaling factor, which we will probably want to do again after we calculate the voxel values */ EDIT_BRICK_FACTOR(cset,subbrik,1.0) ; /* scale factor */ sprintf(str,"Weighted Degree Centrality") ; EDIT_BRICK_LABEL(cset,subbrik,str) ; EDIT_substitute_brick(cset,subbrik,MRI_float,NULL) ; /* make array */ /* copy measure data into the subbrik */ wodset = DSET_ARRAY(cset,subbrik); /* increment memory stats */ INC_MEM_STATS( (DSET_NVOX(cset)*DSET_NVALS(cset)*sizeof(float)), "output dset"); PRINT_MEM_STATS( "outset" ); /* pull the values out of the histogram */ if( dosparsity == 0 ) { for( kout = 0; kout < nmask; kout++ ) { if ( imap != NULL ) { ii = imap[kout] ; /* ii= source voxel (we know that ii is in the mask) */ } else { ii = kout ; } if( ii >= DSET_NVOX(cset) ) { WARNING_message("Avoiding bodset, wodset overflow %d > %d (%s,%d)\n", ii,DSET_NVOX(cset),__FILE__,__LINE__ ); } else { bodset[ ii ] = (float)(binaryDC[kout]); wodset[ ii ] = (float)(weightedDC[kout]); } } /* we are done with this memory, and can kill it now*/ if(binaryDC) { free(binaryDC); binaryDC=NULL; /* -- update running memory estimate to reflect memory allocation */ DEC_MEM_STATS( nmask*sizeof(long), "binary DC array" ); PRINT_MEM_STATS( "binaryDC" ); } if(weightedDC) { free(weightedDC); weightedDC=NULL; /* -- update running memory estimate to reflect memory allocation */ DEC_MEM_STATS( nmask*sizeof(double), "weighted DC array" ); PRINT_MEM_STATS( "weightedDC" ); } } else { /* add in the values from the histogram, this is a two stage procedure: at first we add in values a whole bin at the time until we get to a point where we need to add in a partial bin, then we create a new histogram to sort the values in the bin and then add those bins at a time */ kout = nhistnodes - 1; while (( histogram[kout].nbin < nretain ) && ( kout >= 0 )) { hptr = pptr = histogram[kout].nodes; while( hptr != NULL ) { /* determine the indices corresponding to this node */ if ( imap != NULL ) { ii = imap[hptr->i] ; /* ii= source voxel (we know that ii is in the mask) */ } else { ii = hptr->i ; } if ( imap != NULL ) { jj = imap[hptr->j] ; /* ii= source voxel (we know that ii is in the mask) */ } else { jj = hptr->j ; } /* add in the values */ if(( ii >= DSET_NVOX(cset) ) || ( jj >= DSET_NVOX(cset))) { if( ii >= DSET_NVOX(cset)) { WARNING_message("Avoiding bodset, wodset overflow (ii) %d > %d\n (%s,%d)\n", ii,DSET_NVOX(cset),__FILE__,__LINE__ ); } if( jj >= DSET_NVOX(cset)) { WARNING_message("Avoiding bodset, wodset overflow (jj) %d > %d\n (%s,%d)\n", jj,DSET_NVOX(cset),__FILE__,__LINE__ ); } } else { bodset[ ii ] += 1.0 ; wodset[ ii ] += (float)(hptr->corr); bodset[ jj ] += 1.0 ; wodset[ jj ] += (float)(hptr->corr); } if( fout1D != NULL ) { /* add source, dest, correlation to 1D file */ ix1 = DSET_index_to_ix(cset,ii) ; jy1 = DSET_index_to_jy(cset,ii) ; kz1 = DSET_index_to_kz(cset,ii) ; ix2 = DSET_index_to_ix(cset,jj) ; jy2 = DSET_index_to_jy(cset,jj) ; kz2 = DSET_index_to_kz(cset,jj) ; fprintf(fout1D, "%d %d %d %d %d %d %d %d %.6f\n", ii, jj, ix1, jy1, kz1, ix2, jy2, kz2, (float)(hptr->corr)); } /* increment node pointers */ pptr = hptr; hptr = hptr->next; /* delete the node */ if(pptr) { /* -- update running memory estimate to reflect memory allocation */ DEC_MEM_STATS(sizeof( hist_node ), "hist nodes" ); /* free the mem */ free(pptr); pptr=NULL; } } /* decrement the number of correlations we wish to retain */ nretain -= histogram[kout].nbin; histogram[kout].nodes = NULL; /* go on to the next bin */ kout--; } PRINT_MEM_STATS( "hist1 bins free - inc into output" ); /* if we haven't used all of the correlations that are available, go through and add a subset of the voxels from the remaining bin */ if(( nretain > 0 ) && (kout >= 0)) { hist_node_head* histogram2 = NULL; hist_node_head* histogram2_save = NULL; int h2nbins = 100; float h2binwidth = 0.0; int h2ndx=0; h2binwidth = (((1.0+binwidth/((float)h2nbins))*histogram[kout].bin_high) - histogram[kout].bin_low) / ((float)h2nbins); /* allocate the bins */ if(( histogram2 = (hist_node_head*)malloc(h2nbins*sizeof(hist_node_head))) == NULL ) { if (binaryDC){ free(binaryDC); binaryDC = NULL; } if (weightedDC){ free(weightedDC); weightedDC = NULL; } if (histogram){ histogram = free_histogram(histogram, nhistnodes); } ERROR_message( "Could not allocate %d byte array for histogram2\n", h2nbins*sizeof(hist_node_head)); } else { /* -- update running memory estimate to reflect memory allocation */ histogram2_save = histogram2; INC_MEM_STATS(( h2nbins*sizeof(hist_node_head )), "hist bins"); PRINT_MEM_STATS( "hist2" ); } /* initiatize the bins */ for( kin = 0; kin < h2nbins; kin++ ) { histogram2[ kin ].bin_low = histogram[kout].bin_low + kin*h2binwidth; histogram2[ kin ].bin_high = histogram2[ kin ].bin_low + h2binwidth; histogram2[ kin ].nbin = 0; histogram2[ kin ].nodes = NULL; /*INFO_message("Hist2 bin %d [%3.3f, %3.3f) [%d, %p]\n", kin, histogram2[ kin ].bin_low, histogram2[ kin ].bin_high, histogram2[ kin ].nbin, histogram2[ kin ].nodes );*/ } /* move correlations from histogram to histgram2 */ INFO_message ("Adding %d nodes from histogram to histogram2",histogram[kout].nbin); while ( histogram[kout].nodes != NULL ) { hptr = histogram[kout].nodes; h2ndx = (int)floor((double)(hptr->corr - histogram[kout].bin_low)/(double)h2binwidth); if(( h2ndx < h2nbins ) && ( h2ndx >= 0 )) { histogram[kout].nodes = hptr->next; hptr->next = histogram2[h2ndx].nodes; histogram2[h2ndx].nodes = hptr; histogram2[h2ndx].nbin++; histogram[kout].nbin--; } else { WARNING_message("h2ndx %d is not in range [0,%d) :: %.10f,%.10f\n",h2ndx,h2nbins,hptr->corr, histogram[kout].bin_low); } } /* free the remainder of histogram */ { int nbins_rem = 0; for(ii = 0; ii < nhistnodes; ii++) nbins_rem+=histogram[ii].nbin; histogram = free_histogram(histogram, nhistnodes); PRINT_MEM_STATS( "free remainder of histogram1" ); } kin = h2nbins - 1; while (( nretain > 0 ) && ( kin >= 0 )) { hptr = pptr = histogram2[kin].nodes; while( hptr != NULL ) { /* determine the indices corresponding to this node */ if ( imap != NULL ) { ii = imap[hptr->i] ; } else { ii = hptr->i ; } if ( imap != NULL ) { jj = imap[hptr->j] ; } else { jj = hptr->j ; } /* add in the values */ if(( ii >= DSET_NVOX(cset) ) || ( jj >= DSET_NVOX(cset))) { if( ii >= DSET_NVOX(cset)) { WARNING_message("Avoiding bodset, wodset overflow (ii) %d > %d\n (%s,%d)\n", ii,DSET_NVOX(cset),__FILE__,__LINE__ ); } if( jj >= DSET_NVOX(cset)) { WARNING_message("Avoiding bodset, wodset overflow (jj) %d > %d\n (%s,%d)\n", jj,DSET_NVOX(cset),__FILE__,__LINE__ ); } } else { bodset[ ii ] += 1.0 ; wodset[ ii ] += (float)(hptr->corr); bodset[ jj ] += 1.0 ; wodset[ jj ] += (float)(hptr->corr); } if( fout1D != NULL ) { /* add source, dest, correlation to 1D file */ ix1 = DSET_index_to_ix(cset,ii) ; jy1 = DSET_index_to_jy(cset,ii) ; kz1 = DSET_index_to_kz(cset,ii) ; ix2 = DSET_index_to_ix(cset,jj) ; jy2 = DSET_index_to_jy(cset,jj) ; kz2 = DSET_index_to_kz(cset,jj) ; fprintf(fout1D, "%d %d %d %d %d %d %d %d %.6f\n", ii, jj, ix1, jy1, kz1, ix2, jy2, kz2, (float)(hptr->corr)); } /* increment node pointers */ pptr = hptr; hptr = hptr->next; /* delete the node */ if(pptr) { free(pptr); DEC_MEM_STATS(( sizeof(hist_node) ), "hist nodes"); pptr=NULL; } } /* decrement the number of correlations we wish to retain */ nretain -= histogram2[kin].nbin; histogram2[kin].nodes = NULL; /* go on to the next bin */ kin--; } PRINT_MEM_STATS("hist2 nodes free - incorporated into output"); /* we are finished with histogram2 */ { histogram2 = free_histogram(histogram2, h2nbins); /* -- update running memory estimate to reflect memory allocation */ PRINT_MEM_STATS( "free hist2" ); } if (nretain < 0 ) { WARNING_message( "Went over sparsity goal %d by %d, with a resolution of %f", ngoal, -1*nretain, h2binwidth); } } if (nretain > 0 ) { WARNING_message( "Was not able to meet goal of %d (%3.2f%%) correlations, %d (%3.2f%%) correlations passed the threshold of %3.2f, maybe you need to change the threshold or the desired sparsity?", ngoal, 100.0*((float)ngoal)/((float)totPosCor), totNumCor, 100.0*((float)totNumCor)/((float)totPosCor), thresh); } } INFO_message("Done..\n") ; /* update running memory statistics to reflect freeing the vectim */ DEC_MEM_STATS(((xvectim->nvec*sizeof(int)) + ((xvectim->nvec)*(xvectim->nvals))*sizeof(float) + sizeof(MRI_vectim)), "vectim"); /* toss some trash */ VECTIM_destroy(xvectim) ; DSET_delete(xset) ; if(fout1D!=NULL)fclose(fout1D); PRINT_MEM_STATS( "vectim unload" ); if (weightedDC) free(weightedDC) ; weightedDC = NULL; if (binaryDC) free(binaryDC) ; binaryDC = NULL; /* finito */ INFO_message("Writing output dataset to disk [%s bytes]", commaized_integer_string(cset->dblk->total_bytes)) ; /* write the dataset */ DSET_write(cset) ; WROTE_DSET(cset) ; /* increment our memory stats, since we are relying on the header for this information, we update the stats before actually freeing the memory */ DEC_MEM_STATS( (DSET_NVOX(cset)*DSET_NVALS(cset)*sizeof(float)), "output dset"); /* free up the output dataset memory */ DSET_unload(cset) ; DSET_delete(cset) ; /* force a print */ MEM_STAT = 1; PRINT_MEM_STATS( "Fin" ); exit(0) ; }
THD_session * THD_init_session( char *sessname ) { THD_session *sess ; XtPointer_array *dblk_arrarr ; THD_datablock_array *dblk_arr ; THD_3dim_dataset *dset=NULL , *temp_dset; THD_3dim_dataset_array *dset_arr ; int ibar , idset , iview , nds , qview=-666 ; ENTRY("THD_init_session") ; /*-- sanity check --*/ if( sessname == NULL || strlen(sessname) == 0 || !THD_is_directory(sessname) ) RETURN( NULL ) ; /*-- initialize session --*/ sess = myXtNew( THD_session ) ; sess->type = SESSION_TYPE ; sess->parent = NULL ; #ifdef DEBUG_SESSIONS fprintf(stderr, "blanking session\n"); #endif BLANK_SESSION(sess) ; /* null out all entries */ /* save directory name, with a trailing slash */ MCW_strncpy( sess->sessname , sessname , THD_MAX_NAME ) ; iview = strlen(sess->sessname) ; if( sess->sessname[iview-1] != '/' ) { /* tack trailing / onto sessname */ sess->sessname[iview] = '/' ; sess->sessname[iview+1] = '\0' ; } else { iview-- ; /* iview now points to last non-NUL character in string */ } /* save last name from sessname */ #if 1 { char *env = my_getenv( "AFNI_SESSTRAIL" ) ; int tt = 0 ; if( env != NULL ) tt = strtol(env,NULL,10) ; env = THD_trailname(sess->sessname,tt) ; tt = 1+strlen(env) - THD_MAX_NAME ; if( tt < 0 ) tt = 0 ; strcpy( sess->lastname , env+tt ) ; } #else for( iview-- ; iview >= 0 ; iview-- ) if( sess->sessname[iview] == '/' ) break ; MCW_strncpy( sess->lastname, &(sess->sessname[iview+1]), THD_MAX_NAME ) ; #endif /*-- override dataset 'view'?? [30 May 2013] --*/ { char *env = my_getenv("AFNI_OVERRIDE_VIEW") ; if( env != NULL ) { if( toupper(*env) == 'T' ) qview = VIEW_TALAIRACH_TYPE ; else if( toupper(*env) == 'O' ) qview = VIEW_ORIGINAL_TYPE ; else WARNING_message("AFNI_OVERRIDE_VIEW=%s is not understood",env) ; } } /*-- read all datablocks --*/ dblk_arrarr = THD_init_alldir_datablocks( sess->sessname ) ; /*-- for each datablock array ... --*/ for( ibar=0 ; ibar < dblk_arrarr->num ; ibar++ ) { /*-- get the current array of datablocks --*/ dblk_arr = (THD_datablock_array *) dblk_arrarr->ar[ibar] ; if( dblk_arr == NULL || dblk_arr->num <= 0 ) continue ; /* huh? */ /*-- convert it into an array of datasets --*/ dset_arr = THD_array_3dim_from_block( dblk_arr ) ; if( dset_arr == NULL || dset_arr->num <= 0 ) continue ; /*-- place it into the next row of the THD_session [28 Jul 2003] --*/ nds = sess->num_dsset ; if( nds >= THD_MAX_SESSION_SIZE ) { /* bad! */ fprintf(stderr, "\n*** Session %s table overflow with dataset %s ***\n", sessname , dset_arr->ar[0]->self_name) ; for( idset=0 ; idset < dset_arr->num ; idset++ ) THD_delete_3dim_dataset( dset_arr->ar[idset] , False ) ; FREE_3DARR(dset_arr) ; continue ; /* skip to next dblk_arr (ibar loop) */ } /*-- put each dataset into this row in its view place --*/ for( idset=0 ; idset < dset_arr->num ; idset++ ) { dset = dset_arr->ar[idset] ; iview = dset->view_type ; if( qview >= 0 ) iview = qview ; /* 30 May 2013 */ if( GET_SESSION_DSET(sess,nds,iview) != NULL ) { /* should never happen */ fprintf(stderr, "\n*** Session %s has duplicate dataset views of %s ***\n", sessname , dset->self_name) ; THD_delete_3dim_dataset( dset , False ) ; } else { #ifdef DEBUG_SESSIONS fprintf(stderr,"\nputting datasets into initial view \n"); #endif SET_SESSION_DSET(dset, sess, nds, iview); /* should always happen */ /* sess->dsset_xform_table[nds][iview] = dset ; */ /* should always happen */ } } sess->num_dsset ++ ; /* one more row */ FREE_3DARR(dset_arr) ; } /* end of loop over each datablock array (ibar) */ /*-- throw away the datablock arrays at this point --*/ STATUS("trashing dblk_arrarr") ; for( ibar=0 ; ibar < dblk_arrarr->num ; ibar++ ) { dblk_arr = (THD_datablock_array *) dblk_arrarr->ar[ibar] ; FREE_DBARR( dblk_arr ) ; } FREE_XTARR( dblk_arrarr ) ; /*-- 29 Oct 2001: try to read .mnc "datasets" --*/ if( !AFNI_noenv("AFNI_MINC_DATASETS") ) { char ename[THD_MAX_NAME] , **fn_minc , *eee ; int num_minc , ii ; STATUS("looking for MINC files") ; strcpy(ename,sess->sessname) ; strcat(ename,"*.mnc") ; eee = ename ; MCW_file_expand( 1,&eee , &num_minc,&fn_minc ) ; /* find files */ if( num_minc > 0 ) { /* got some! */ STATUS("opening MINC files") ; for( ii=0 ; ii < num_minc ; ii++ ) { /* loop over files */ dset = THD_open_minc( fn_minc[ii] ) ; /* try it on */ if( !ISVALID_DSET(dset) ) continue ; /* doesn't fit? */ nds = sess->num_dsset ; if( nds >= THD_MAX_SESSION_SIZE ) { fprintf(stderr, "\n*** Session %s table overflow with MINC dataset %s ***\n", sessname , fn_minc[ii] ) ; THD_delete_3dim_dataset( dset , False ) ; break ; /* out of for loop */ } iview = dset->view_type ; SET_SESSION_DSET(dset, sess, nds, iview); /* sess->dsset_xform_table[nds][iview] = dset ;*/ sess->num_dsset ++ ; } /* end of loop over files */ MCW_free_expand( num_minc , fn_minc ) ; } /* end of if we found MINC files */ } /*-- 06 Apr 2005: try to read NIfTI-1 files [KRH and RWC] --*/ if( !AFNI_noenv("AFNI_NIFTI_DATASETS") ) { char *ename[2] , **fn_nifti ; int num_nifti , ii ; STATUS("looking for NIFTI files") ; ename[0] = AFMALL(char, THD_MAX_NAME) ; ename[1] = AFMALL(char, THD_MAX_NAME) ; strcpy(ename[0],sess->sessname) ; strcat(ename[0],"*.nii") ; strcpy(ename[1],sess->sessname) ; strcat(ename[1],"*.nii.gz") ; MCW_file_expand( 2,ename , &num_nifti,&fn_nifti ) ; /* find files */ free(ename[0]) ; free(ename[1]) ; if( num_nifti > 0 ) { /* got some! */ STATUS("opening NIFTI files") ; for( ii=0 ; ii < num_nifti ; ii++ ) { /* loop over files */ dset = THD_open_nifti( fn_nifti[ii] ) ; /* try it on */ if( !ISVALID_DSET(dset) ) continue ; /* doesn't fit? */ nds = sess->num_dsset ; if( nds >= THD_MAX_SESSION_SIZE ) { fprintf(stderr, "\n*** Session %s table overflow with NIfTI dataset %s ***\n", sessname , fn_nifti[ii] ) ; THD_delete_3dim_dataset( dset , False ) ; break ; /* out of for loop */ } iview = dset->view_type ; SET_SESSION_DSET(dset, sess, nds, iview); /* sess->dsset_xform_table[nds][iview] = dset ;*/ sess->num_dsset ++ ; } /* end of loop over files */ MCW_free_expand( num_nifti , fn_nifti ) ; } /* end of if we found NIFTI files */ }
void initialize_program ( int * im1, /* index of 1st image in time series for analysis */ char ** nname, /* noise model name */ char ** sname, /* signal model name */ vfp * nmodel, /* pointer to noise model */ vfp * smodel, /* pointer to signal model */ int * r, /* number of parameters in the noise model */ int * p, /* number of parameters in the signal model */ char *** npname, /* noise parameter names */ char *** spname, /* signal parameter names */ float ** min_nconstr, /* minimum parameter constraints for noise model */ float ** max_nconstr, /* maximum parameter constraints for noise model */ float ** min_sconstr, /* minimum parameter constraints for signal model */ float ** max_sconstr, /* maximum parameter constraints for signal model */ int * nabs, /* use absolute constraints for noise parameters */ int * nrand, /* number of random vectors to generate */ int * nbest, /* number of random vectors to keep */ float * rms_min, /* minimum rms error to reject reduced model */ float ** par_rdcd, /* estimated parameters for the reduced model */ float ** par_full, /* estimated parameters for the full model */ float ** tpar_full, /* t-statistic of parameters in the full model */ int ts_length, /* length of time series data */ char ** tfilename, /* file name for time point series */ float *** x_array, /* independent variable matrix */ float ** fit ) { int dimension; /* dimension of full model */ int ip; /* parameter index */ int it; /* time index */ MRI_IMAGE * im, * flim; /* pointers to image structures -- used to read 1D ASCII */ int nt; /* number of points in 1D x data file */ float * tar; /*----- intialize options -----*/ initialize_options (im1, nname, sname, nmodel, smodel, r, p, npname, spname, min_nconstr, max_nconstr, min_sconstr, max_sconstr, nabs, nrand, nbest, rms_min, tfilename); /*----- check for valid inputs -----*/ check_for_valid_inputs (); /*----- allocate space for independent variable matrix -----*/ *x_array = (float **) malloc (sizeof(float *) * ts_length); if (*x_array == NULL) NLfit_error ("Unable to allocate memory for x_array"); for (it = 0; it < ts_length; it++) { (*x_array)[it] = (float *) malloc (sizeof(float) * 3); if ((*x_array)[it] == NULL) NLfit_error ("Unable to allocate memory for x_array[it]"); } /*----- initialize independent variable matrix -----*/ if (!plug_timeref) { static float old_DELT = -1.0 ; DELT = (inTR && dsTR > 0.0) ? dsTR : 1.0 ; /* 22 July 1998 */ if( DELT != old_DELT ) { old_DELT = DELT ; printf("NLfit: switch to TR = %g\n",DELT) ; } for (it = 0; it < ts_length; it++) { (*x_array)[it][0] = 1.0; (*x_array)[it][1] = it * DELT; (*x_array)[it][2] = (it * DELT) * (it * DELT); } } else { flim = mri_read_1D (*tfilename); if (flim == NULL) NLfit_error ("Unable to read time reference file \n"); nt = flim -> nx; if (nt < ts_length) NLfit_error ("Time reference array is too short"); tar = MRI_FLOAT_PTR(flim) ; for (it = 0; it < ts_length; it++) { (*x_array)[it][0] = 1.0; (*x_array)[it][1] = tar[it] ; (*x_array)[it][2] = tar[it] * tar[it]; } mri_free (flim); } /*--- 24 Jul 2006: special change to x_array[][2] for Linear+Ort [RWCox] ---*/ if( strcmp(*nname,"Linear+Ort") == 0 ) { char *fname=NULL; MRI_IMAGE *fim=NULL; int nx; float *far; static int nwarn=0; fname = my_getenv("AFNI_ORTMODEL_REF") ; if( fname == NULL ) { ERROR_message("Linear+Ort model: 'AFNI_ORTMODEL_REF' not set") ; goto PLO_done ; } fim = mri_read_1D(fname) ; if( fim == NULL || fim->nx < 2 ) { ERROR_message( "Linear+Ort model: can't read AFNI_ORTMODEL_REF='%s'",fname) ; goto PLO_done ; } if( fim->ny > 1 && nwarn < 2 ) { WARNING_message( "Linear+Ort model: file AFNI_ORTMODEL_REF='%s' has more than 1 column", fname ) ; nwarn++ ; } nx = fim->nx ; far = MRI_FLOAT_PTR(fim) ; if( nx != ts_length && nwarn ) { WARNING_message("Linear+Ort: length(%s)=%d but length(dataset)=%d", fname , nx , ts_length ) ; nwarn++ ; } for( it=0 ; it < ts_length; it++) (*x_array)[it][2] = (it < nx) ? far[it] : 0.0f ; PLO_done: ; /* nada */ } dimension = (*r) + (*p); /*----- allocate memory space -----*/ *par_rdcd = (float *) malloc (sizeof(float) * dimension); if (*par_rdcd == NULL) NLfit_error ("Unable to allocate memory for par_rdcd"); *par_full = (float *) malloc (sizeof(float) * dimension); if (*par_full == NULL) NLfit_error ("Unable to allocate memory for par_full"); *tpar_full = (float *) malloc (sizeof(float) * dimension); if (*tpar_full == NULL) NLfit_error ("Unable to allocate memory for tpar_full"); *fit = (float *) malloc (sizeof(float) * (ts_length)); if (*fit == NULL) NLfit_error ("Unable to allocate memory for fit"); }