float * read_time_series ( char * ts_filename, /* time series file name (plus column index) */ int * ts_length /* output value for time series length */ ) { char message[THD_MAX_NAME]; /* error message */ char * cpt; /* pointer to column suffix */ char filename[THD_MAX_NAME]; /* time series file name w/o column index */ char subv[THD_MAX_NAME]; /* string containing column index */ MRI_IMAGE * im, * flim; /* pointers to image structures -- used to read 1D ASCII */ float * far; /* pointer to MRI_IMAGE floating point data */ int nx; /* number of time points in time series */ int ny; /* number of columns in time series file */ int iy; /* time series file column index */ int ipt; /* time point index */ float * ts_data = NULL; /* input time series data */ /*----- First, check for empty filename -----*/ if (ts_filename == NULL) FDR_error ("Missing input time series file name"); /*----- Read the time series file -----*/ flim = mri_read_1D(ts_filename) ; if (flim == NULL) { sprintf (message, "Unable to read time series file: %s", ts_filename); FDR_error (message); } far = MRI_FLOAT_PTR(flim); nx = flim->nx; ny = flim->ny; iy = 0 ; if( ny > 1 ){ fprintf(stderr,"WARNING: time series %s has more than 1 column\n",ts_filename); } /*----- Save the time series data -----*/ *ts_length = nx; ts_data = (float *) malloc (sizeof(float) * nx); MTEST (ts_data); for (ipt = 0; ipt < nx; ipt++) ts_data[ipt] = far[ipt + iy*nx]; mri_free (flim); flim = NULL; return (ts_data); }
void conv_set_ref( int num , float * ref ) { if( num > 0 && ref != NULL ){ /*** if have inputs, make space & copy in ***/ int ii ; /* get rid of old data */ if(refts != NULL){ free(refts); refts = NULL; free(refin); refin = NULL; } refnum = num ; refts = (float *) malloc( sizeof(float) * num ) ; refin = (int *) malloc( sizeof(int) * num ) ; memcpy( refts , ref , sizeof(float) * num ) ; for( ii=0,refnz=0 ; ii < num ; ii++ ) /* build list of nonzero */ if( refts[ii] != 0 ) refin[refnz++] = ii ; /* points in refts */ if( refnz == 0 ) ERREX("model_conv_diffgamma: All zero reference timeseries!") ; if( g_debug ) { fprintf(stderr,"+d conv_set_ref: num=%d nonzero=%d\n",num,refnz) ; if( g_debug > 1 ) { fprintf(stderr," TR locked stimuli :"); for( ii = 0; ii < refnz; ii++ ) fprintf(stderr," %d", refin[ii]); fputc('\n',stderr); } } return ; } else { /*** if no inputs, read it from AFNI_CONVMODEL_REF 1D file ***/ char * cp ; MRI_IMAGE * flim ; float one = 1.0 ; cp = my_getenv("AFNI_CONVMODEL_REF") ; /* get name of reference file */ if( cp == NULL ) ERREX("model_conv_diffgamma: need ref file as AFNI_CONVMODEL_REF") ; flim = mri_read_1D(cp) ; /* 16 Nov 1999: replaces mri_read_ascii */ if( flim == NULL ){ char buf[256] ; sprintf(buf,"model_conv_diffgamma: Can't read timeseries file %s",cp) ; ERREX(buf) ; } if( g_debug ) fprintf(stderr,"+d conv_set_ref: refts=%s nx=%d\n",cp,flim->ny) ; conv_set_ref( flim->nx , MRI_FLOAT_PTR(flim) ) ; /* recursion! */ mri_free(flim) ; } return ; }
float * custom_filter( int dummy ) { MRI_IMAGE * filter_data=NULL; float * filter_coefficients = NULL; filter_data = mri_read_1D(custom_file); if MRI_IS_1D(filter_data) { custom_ntaps = filter_data->nx; if (custom_ntaps % 2) { filter_coefficients = MRI_FLOAT_PTR(filter_data); } else { /*ERROR, EVEN NUMBER OF FILTER TAPS */ } } return filter_coefficients ; }
int main( int argc , char * argv[] ) { int nim , ii , jj , kk , nx ; MRI_IMAGE ** inim ; float * far ; int ncol , ic ; float * csum ; int nn_ignore=0 , mm_use=0 , iarg=1 ; /*-- help? --*/ if( argc < 2 || strcmp(argv[1],"-help") == 0 ){ printf("Usage: 1dsum [options] a.1D b.1D ...\n" "where each file a.1D, b.1D, etc. is an ASCII file of numbers arranged\n" "in rows and columns. The sum of each column is written to stdout.\n" "\n" "Options:\n" " -ignore nn = skip the first nn rows of each file\n" " -use mm = use only mm rows from each file\n" ) ; PRINT_COMPILE_DATE ; exit(0) ; } machdep() ; /* parse options */ while( iarg < argc && argv[iarg][0] == '-' ){ if( strncmp(argv[iarg],"-ignore",4) == 0 ){ nn_ignore = (int) strtod(argv[++iarg],NULL) ; if( nn_ignore < 0 ){fprintf(stderr,"** Illegal -ignore value!\n");exit(1);} iarg++ ; continue ; } if( strncmp(argv[iarg],"-use",4) == 0 ){ mm_use = (int) strtod(argv[++iarg],NULL) ; if( mm_use < 0 ){fprintf(stderr,"** Illegal -use value!\n");exit(1);} iarg++ ; continue ; } fprintf(stderr,"** Unknown option: %s\n",argv[iarg]) ; exit(1) ; } /* read input files */ nim = argc-iarg ; inim = (MRI_IMAGE **) malloc( sizeof(MRI_IMAGE *) * nim ) ; ncol = 0 ; for( jj=0 ; jj < nim ; jj++ ){ inim[jj] = mri_read_1D( argv[jj+iarg] ) ; if( inim[jj] == NULL ){ fprintf(stderr,"** Can't read input file %s\n",argv[jj+iarg]) ; exit(1) ; } if( jj > 0 && inim[jj]->nx != inim[0]->nx ){ fprintf(stderr, "** Input file %s doesn't match first file %s in length!\n", argv[jj+iarg],argv[iarg]) ; exit(1) ; } ncol += inim[jj]->ny ; } if( mm_use == 0 ){ mm_use = inim[0]->nx - nn_ignore ; if( mm_use < 0 ){fprintf(stderr,"** -ignore is too big for these files!\n");exit(1);} } if( nn_ignore + mm_use > inim[0]->nx ){ fprintf(stderr,"** -ignore + -use is too big for these files!\n");exit(1); } csum = (float *) malloc(sizeof(float)*ncol) ; for( ic=0 ; ic < ncol ; ic++ ) csum[ic] = 0.0 ; nx = inim[0]->nx ; for( ii=nn_ignore ; ii < nn_ignore+mm_use ; ii++ ){ for( ic=jj=0 ; jj < nim ; jj++ ){ far = MRI_FLOAT_PTR(inim[jj]) ; for( kk=0 ; kk < inim[jj]->ny ; kk++ ) csum[ic++] += far[ii+kk*nx] ; } } for( ic=0 ; ic < ncol ; ic++ ) printf("%g ",csum[ic]) ; printf("\n"); exit(0) ; }
int main( int argc , char *argv[] ) { int iarg , ii,jj,kk,mm , nvec , nx=0,ny , ff , vlen=4 ; MRI_IMAGE *tim , *vsim=NULL ; MRI_IMARR *tar ; char **vecnam , *tnam ; float *far , **tvec , *vsig=NULL , xsig,ysig ; float_quad qcor ; float_pair pci ; float corst, cor025, cor500, cor975 ; char fmt[256] ; int cormeth=0 ; /* 0=Pearson, 1=Spearman, 2=Quadrant, 3=Kendall tau_b */ float (*corfun)(int,float *,float *) ; /*-- start the AFNI machinery --*/ mainENTRY("1dCorrelate main") ; machdep() ; /* check for options */ iarg = 1 ; nvec = 0 ; while( iarg < argc && argv[iarg][0] == '-' ){ /* I get by with a little help from my friends? */ if( strcmp(argv[iarg],"-help") == 0 || strcmp(argv[iarg],"-h") == 0){ usage_1dCorrelate(strlen(argv[iarg])>3 ? 2:1); exit(0) ; } /*--- methods ---*/ if( toupper(argv[iarg][1]) == 'P' ){ cormeth = 0 ; iarg++ ; continue ; } if( toupper(argv[iarg][1]) == 'S' ){ cormeth = 1 ; iarg++ ; continue ; } if( toupper(argv[iarg][1]) == 'Q' ){ cormeth = 2 ; iarg++ ; continue ; } if( toupper(argv[iarg][1]) == 'K' ){ cormeth = 3 ; iarg++ ; continue ; } if( toupper(argv[iarg][1]) == 'T' ){ cormeth = 4 ; iarg++ ; continue ; } if( toupper(argv[iarg][1]) == 'U' ){ cormeth = 5 ; iarg++ ; continue ; } /*--- set nboot ---*/ if( strcasecmp(argv[iarg],"-nboot") == 0 || strcasecmp(argv[iarg],"-num") == 0 ){ iarg++ ; if( iarg >= argc ) ERROR_exit("Need argument after '-nboot'") ; nboot = (int)strtod(argv[iarg],NULL) ; if( nboot < NBMIN ){ WARNING_message("Replacing -nboot %d with %d",nboot,NBMIN) ; nboot = NBMIN ; } iarg++ ; continue ; } /*--- set alpha ---*/ if( strcasecmp(argv[iarg],"-alpha") == 0 ){ iarg++ ; if( iarg >= argc ) ERROR_exit("Need argument after '-alpha'") ; alpha = (float)strtod(argv[iarg],NULL) ; if( alpha < 1.0f ){ WARNING_message("Replacing -alpha %.1f with 1",alpha) ; alpha = 0.01f ; } else if( alpha > 20.0f ){ WARNING_message("Replacing -alpha %.1f with 20",alpha) ; alpha = 0.20f ; } else { alpha *= 0.01f ; /* convert from percent to fraction */ } iarg++ ; continue ; } /*--- block resampling ---*/ if( strcasecmp(argv[iarg],"-blk") == 0 || strcasecmp(argv[iarg],"-block") == 0 ){ doblk = 1 ; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-vsig") == 0 ){ if( vsim != NULL ) ERROR_exit("Can't use -vsig twice!") ; if( ++iarg >= argc ) ERROR_exit("Need argument after -vsig") ; vsim = mri_read_1D(argv[iarg]) ; if( vsim == NULL ) ERROR_exit("Can't read -vsig file '%s'",argv[iarg]) ; iarg++ ; continue ; } /*--- user should be flogged ---*/ ERROR_message("Monstrously illegal option '%s'",argv[iarg]) ; suggest_best_prog_option(argv[0], argv[iarg]); exit(1); } /*--- user should be flogged twice ---*/ if( argc < 2 ){ usage_1dCorrelate(1) ; exit(0) ; } if( iarg == argc ) ERROR_exit("No 1D files on command line!?\n") ; /* the function to compute the correlation */ corfun = cor_func[cormeth] ; /* check and assemble list of input 1D files */ ff = iarg ; INIT_IMARR(tar) ; for( ; iarg < argc ; iarg++ ){ tim = mri_read_1D( argv[iarg] ) ; if( tim == NULL ) ERROR_exit("Can't read 1D file '%s'",argv[iarg]) ; if( nx == 0 ){ nx = tim->nx ; if( nx < 3 ) ERROR_exit("1D file '%.77s' length=%d is less than 3",argv[iarg],nx) ; else if( nx < 7 ) WARNING_message("1D file '%.77s' length=%d is less than 7",argv[iarg],nx) ; } else if( tim->nx != nx ){ ERROR_exit("Length of 1D file '%.77s' [%d] doesn't match first file [%d]", argv[iarg] , tim->nx , nx ); } nvec += tim->ny ; ADDTO_IMARR(tar,tim) ; } /* user is really an idiot -- flogging's too good for him */ if( nvec < 2 ) ERROR_exit("Must have at least 2 input columns!") ; if( nx < 20 && doblk ){ doblk = 0 ; WARNING_message("Column length %d < 20 ==> cannot use block resampling",nx) ; } if( vsim != NULL ){ if( vsim->nvox < nvec ) ERROR_exit("-vsig file only has %d entries, but needs at least %d",vsim->nvox,nvec) ; vsig = MRI_FLOAT_PTR(vsim) ; } /* create vectors from 1D files */ tvec = (float **)malloc( sizeof(float *)*nvec ) ; vecnam = (char **)malloc( sizeof(char *)*nvec ) ; for( jj=0 ; jj < nvec ; jj++ ){ tvec[jj] = (float *)malloc( sizeof(float)*nx ) ; vecnam[jj] = (char *)malloc(sizeof(char)*THD_MAX_NAME) ; } /* copy data into new space, create output labels, check for stoopiditees */ for( kk=mm=0 ; mm < IMARR_COUNT(tar) ; mm++ ){ tim = IMARR_SUBIM(tar,mm) ; far = MRI_FLOAT_PTR(tim) ; tnam = tim->name ; if( tnam == NULL ) tnam = "File" ; for( jj=0 ; jj < tim->ny ; jj++,kk++ ){ for( ii=0 ; ii < nx ; ii++ ) tvec[kk][ii] = far[ii+jj*nx] ; sprintf(vecnam[kk],"%s[%d]",THD_trailname(tnam,0),jj) ; /* vector name */ iarg = strlen(vecnam[kk]) ; vlen = MAX(vlen,iarg) ; if( THD_is_constant(nx,tvec[kk]) ) ERROR_exit("Column %s is constant!",vecnam[kk]) ; } } DESTROY_IMARR(tar) ; /*--- Print a beeyootiful header ---*/ printf("# %s correlation [n=%d #col=%d]\n",cor_name[cormeth],nx,nvec) ; sprintf(fmt,"# %%-%ds %%-%ds",vlen,vlen) ; printf(fmt,"Name","Name") ; printf(" Value BiasCorr %5.2f%% %5.2f%%",50.0f*alpha,100.0f-50.0f*alpha) ; if( cormeth == 0 ) /* Pearson */ printf(" N:%5.2f%% N:%5.2f%%",50.0f*alpha,100.0f-50.0f*alpha) ; printf("\n") ; printf("# ") ; for( ii=0 ; ii < vlen ; ii++ ) printf("-") ; printf(" ") ; for( ii=0 ; ii < vlen ; ii++ ) printf("-") ; printf(" ") ; printf(" --------") ; printf(" --------") ; printf(" --------") ; printf(" --------") ; if( cormeth == 0 ){ printf(" --------") ; printf(" --------") ; } printf("\n") ; if( cormeth != 0 ) /* non-Pearson */ sprintf(fmt," %%-%ds %%-%ds %%+8.5f %%+8.5f %%+8.5f %%+8.5f\n",vlen,vlen) ; else /* Pearson */ sprintf(fmt," %%-%ds %%-%ds %%+8.5f %%+8.5f %%+8.5f %%+8.5f %%+8.5f %%+8.5f\n",vlen,vlen) ; /*--- Do some actual work for a suprising change ---*/ for( jj=0 ; jj < nvec ; jj++ ){ /* loops over column pairs */ for( kk=jj+1 ; kk < nvec ; kk++ ){ if( vsig != NULL ){ xsig = vsig[jj]; ysig = vsig[kk]; } else { xsig = ysig = 0.0f; } qcor = Corrboot( nx, tvec[jj], tvec[kk], xsig, ysig, corfun ) ; /* outsourced */ corst = qcor.a ; cor025 = qcor.b ; cor500 = qcor.c ; cor975 = qcor.d ; if( cormeth == 0 ){ /* Pearson */ pci = PCorrCI( nx , corst , alpha ) ; printf(fmt, vecnam[jj], vecnam[kk], corst, cor500, cor025, cor975, pci.a,pci.b ) ; } else { /* all other methods */ printf(fmt, vecnam[jj], vecnam[kk], corst, cor500, cor025, cor975 ) ; } } } /* Finished -- go back to watching Star Trek reruns -- Tribbles ahoy, Cap'n! */ exit(0) ; }
int main (int argc, char *argv[]) { THD_3dim_dataset *old_dset, *new_dset, *I0_dset; /* input and output datasets */ int nopt, nbriks, nvox; int i; MRI_IMAGE *grad1Dptr = NULL; MRI_IMAGE *anat_im = NULL; MRI_IMAGE *data_im = NULL; double fac; short *sar = NULL, *tempsptr = NULL, tempval; byte *maskptr = NULL, *tempbptr = NULL; char tempstr[25]; /*----- Read command line -----*/ if (argc < 2 || strcmp (argv[1], "-help") == 0) { printf ("Usage: 3dDTtoDWI [options] gradient-file I0-dataset DT-dataset\n" "Computes multiple gradient images from 6 principle direction tensors and\n" " corresponding gradient vector coordinates applied to the I0-dataset.\n" " The program takes three parameters as input : \n" " a 1D file of the gradient vectors with lines of ASCII floats Gxi,Gyi,Gzi.\n" " Only the non-zero gradient vectors are included in this file (no G0 line).\n" " The I0 dataset is a volume without any gradient applied.\n" " The DT dataset is the 6-sub-brick dataset containing the diffusion tensor data,\n" " Dxx, Dxy, Dyy, Dxz, Dyz, Dzz (lower triangular row-wise order)\n" " Options:\n" " -prefix pname = Use 'pname' for the output dataset prefix name.\n" " [default='DWI']\n" " -automask = mask dataset so that the gradient images are computed only for\n" " high-intensity (presumably brain) voxels. The intensity level is\n" " determined the same way that 3dClipLevel works.\n\n" " -datum type = output dataset type [float/short/byte] (default is float).\n" " -help = show this help screen.\n" " Example:\n" " 3dDTtoDWI -prefix DWI -automask tensor25.1D 'DT+orig[26]' DT+orig.\n\n" " The output is a n sub-brick bucket dataset containing computed DWI images.\n" " where n is the number of vectors in the gradient file + 1\n" "\n"); printf ("\n" MASTER_SHORTHELP_STRING); exit (0); } mainENTRY ("3dDTtoDWI main"); machdep (); AFNI_logger ("3dDTtoDWI", argc, argv); PRINT_VERSION("3dDTtoDWI") ; nopt = 1; datum = MRI_float; while (nopt < argc && argv[nopt][0] == '-') { /*-- prefix --*/ if (strcmp (argv[nopt], "-prefix") == 0) { if (++nopt >= argc) { fprintf (stderr, "*** Error - prefix needs an argument!\n"); exit (1); } MCW_strncpy (prefix, argv[nopt], THD_MAX_PREFIX); /* change name from default prefix */ /* check file name to be sure not to overwrite - mod drg 12/9/2004 */ if (!THD_filename_ok (prefix)) { fprintf (stderr, "*** Error - %s is not a valid prefix!\n", prefix); exit (1); } nopt++; continue; } /*-- datum --*/ if (strcmp (argv[nopt], "-datum") == 0) { if (++nopt >= argc) { fprintf (stderr, "*** Error - datum needs an argument!\n"); exit (1); } if (strcmp (argv[nopt], "short") == 0) { datum = MRI_short; } else if (strcmp (argv[nopt], "float") == 0) { datum = MRI_float; } else if (strcmp (argv[nopt], "byte") == 0) { datum = MRI_byte; } else { fprintf (stderr, "-datum of type '%s' is not supported!\n", argv[nopt]); exit (1); } nopt++; continue; } if (strcmp (argv[nopt], "-automask") == 0) { automask = 1; nopt++; continue; } fprintf(stderr, "*** Error - unknown option %s\n", argv[nopt]); exit(1); } /*----- read input datasets -----*/ if (nopt >= argc) { fprintf (stderr, "*** Error - No input dataset!?\n"); exit (1); } /* first input dataset - should be gradient vector file of ascii floats Gx,Gy,Gz */ /* read gradient vector 1D file */ grad1Dptr = mri_read_1D (argv[nopt]); if (grad1Dptr == NULL) { fprintf (stderr, "*** Error reading gradient vector file\n"); exit (1); } if (grad1Dptr->ny != 3) { fprintf (stderr, "*** Error - Only 3 columns of gradient vectors allowed\n"); fprintf (stderr, "%d columns found\n", grad1Dptr->nx); mri_free (grad1Dptr); exit (1); } if (grad1Dptr->nx < 6) { fprintf (stderr, "*** Error - Must have at least 6 gradient vectors\n"); fprintf (stderr, "%d columns found\n", grad1Dptr->nx); mri_free (grad1Dptr); exit (1); } nbriks = grad1Dptr->nx + 1; /* number of gradients specified here from file */ nopt++; /* open I0 dataset - idealized no gradient image */ I0_dset = THD_open_dataset (argv[nopt]); CHECK_OPEN_ERROR(I0_dset,argv[nopt]) ; DSET_mallocize (I0_dset); DSET_load (I0_dset); /* load dataset */ data_im = DSET_BRICK (I0_dset, 0); /* set pointer to the 0th sub-brik of the dataset */ fac = DSET_BRICK_FACTOR(I0_dset, 0); /* get scale factor for each sub-brik*/ if(fac==0.0) fac=1.0; if((data_im->kind != MRI_float)) { fprintf (stderr, "*** Error - Can only open float datasets. Use 3dcalc to convert.\n"); mri_free (grad1Dptr); mri_free (data_im); exit (1); } I0_ptr = mri_data_pointer(data_im) ; /* pointer to I0 data */ nopt++; /* Now read in all the MRI volumes for each gradient vector */ /* assumes first one is no gradient */ old_dset = THD_open_dataset (argv[nopt]); CHECK_OPEN_ERROR(old_dset,argv[nopt]) ; /* expect at least 6 values per voxel - 6 sub-briks as input dataset */ if (DSET_NVALS (old_dset) <6) { fprintf (stderr, "*** Error - Dataset must have at least 6 sub-briks to describe the diffusion tensor\n"); mri_free (grad1Dptr); mri_free (data_im); exit (1); } InitGlobals (grad1Dptr->nx + 1); /* initialize all the matrices and vectors */ Computebmatrix (grad1Dptr, BMAT_NZ); /* compute bij=GiGj */ INFO_message("The maximum magnitude of the bmatrix appears to be: %.2f", MAX_BVAL); if (automask) { DSET_mallocize (old_dset); DSET_load (old_dset); /* get B0 (anatomical image) from dataset */ /*anat_im = THD_extract_float_brick( 0, old_dset ); */ anat_im = DSET_BRICK (old_dset, 0); /* set pointer to the 0th sub-brik of the dataset */ maskptr = mri_automask_image (anat_im); /* maskptr is a byte pointer for volume */ /* convert byte mask to same format type as dataset */ nvox = DSET_NVOX (old_dset); sar = (short *) calloc (nvox, sizeof (short)); /* copy maskptr values to far ptr */ tempsptr = sar; tempbptr = maskptr; for (i = 0; i < nvox; i++) { *tempsptr++ = (short) *tempbptr++; tempval = *(tempsptr - 1); } free (maskptr); /*old_dset->dblk->malloc_type = DATABLOCK_MEM_MALLOC; *//* had to set this? */ EDIT_add_brick (old_dset, MRI_short, 0.0, sar); /* add sub-brik to end */ } /* temporarily set artificial timing to 1 second interval */ EDIT_dset_items (old_dset, ADN_ntt, DSET_NVALS (old_dset), ADN_ttorg, 0.0, ADN_ttdel, 1.0, ADN_tunits, UNITS_SEC_TYPE, NULL); /*------------- ready to compute new dataset -----------*/ new_dset = MAKER_4D_to_typed_fbuc (old_dset, /* input dataset */ prefix, /* output prefix */ datum, /* output datum */ 0, /* ignore count */ 0, /* can't detrend in maker function KRH 12/02 */ nbriks, /* number of briks */ DTtoDWI_tsfunc, /* timeseries processor */ NULL, /* data for tsfunc */ NULL, /* mask */ 0 /* Allow auto scaling of output */ ); FreeGlobals (); mri_free (grad1Dptr); if (automask) { mri_free (anat_im); DSET_unload_one (old_dset, 0); sar = NULL; } if (new_dset != NULL) { tross_Copy_History (old_dset, new_dset); for(i=0;i<nbriks;i++) { sprintf(tempstr,"grad%3.3d", i); EDIT_dset_items (new_dset, ADN_brick_label_one + i, tempstr, ADN_none); } tross_Make_History ("3dDTtoDWI", argc, argv, new_dset); DSET_write (new_dset); fprintf(stderr,"--- Output dataset %s\n", DSET_BRIKNAME(new_dset)); } else { fprintf (stderr, "*** Error - Unable to compute output dataset!\n"); exit (1); } exit (0); }
int main(int argc, char *argv[]) { int CHECK = 0; int iarg; char *Fname_input = NULL; char *Fname_output = NULL; char *Fname_outputBV = NULL; char *Fname_bval = NULL; int opt; FILE *fin=NULL, *fout=NULL, *finbv=NULL, *foutBV=NULL; int i,j,k; int BZER=0,idx=0,idx2=0; MRI_IMAGE *flim=NULL; MRI_IMAGE *preREADIN=NULL; MRI_IMAGE *preREADBVAL=NULL; float *READIN=NULL; float *READBVAL=NULL; float OUT_MATR[MAXGRADS][7]; // b- or g-matrix float OUT_GRAD[MAXGRADS][4]; // b- or g-matrix int INV[3] = {1,1,1}; // if needing to switch int FLAG[MAXGRADS]; float temp; int YES_B = 0; int EXTRA_ZEROS=0; int HAVE_BVAL = 0; int BVAL_OUT = 0; int BVAL_OUT_SEP = 0; float BMAX_REF = 1; // i.e., essentially zero int IN_FORM = 0; // 0 for row, 1 for col int OUT_FORM = 1; // 1 for col, 2 for bmatr int HAVE_BMAX_REF=0 ; // referring to user input value int count_in=0, count_out=0; THD_3dim_dataset *dwset=NULL, *dwout=NULL; int Nbrik = 0; char *prefix=NULL ; float **temp_arr=NULL, **temp_grad=NULL; int Ndwi = 0, dwi=0, Ndwout = 0, Ndwi_final = 0, Ndwout_final = 0; int Nvox = 0; int DWI_COMP_FAC = 0; int ct_dwi = 0; float MaxDP = 0; mainENTRY("1dDW_Grad_o_Mat"); machdep(); if (argc == 1) { usage_1dDW_Grad_o_Mat(1); exit(0); } iarg = 1; while( iarg < argc && argv[iarg][0] == '-' ){ if( strcmp(argv[iarg],"-help") == 0 || strcmp(argv[iarg],"-h") == 0 ) { usage_1dDW_Grad_o_Mat(strlen(argv[iarg])>3 ? 2:1); exit(0); } if( strcmp(argv[iarg],"-flip_x") == 0) { INV[0] = -1; iarg++ ; continue ; } if( strcmp(argv[iarg],"-flip_y") == 0) { INV[1] = -1; iarg++ ; continue ; } if( strcmp(argv[iarg],"-flip_z") == 0) { INV[2] = -1; iarg++ ; continue ; } if( strcmp(argv[iarg],"-keep_b0s") == 0) { YES_B = 1; iarg++ ; continue ; } if( strcmp(argv[iarg],"-put_zeros_top") == 0) { EXTRA_ZEROS = 1; iarg++ ; continue ; } if( strcmp(argv[iarg],"-in_grad_rows") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '-in_grad_rows'\n") ; Fname_input = argv[iarg]; count_in++; iarg++ ; continue ; } if( strcmp(argv[iarg],"-in_grad_cols") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '-in_grad_cols'\n") ; Fname_input = argv[iarg]; count_in++; IN_FORM = 1; iarg++ ; continue ; } if( strcmp(argv[iarg],"-in_gmatT_cols") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '-in_matT_cols'\n") ; Fname_input = argv[iarg]; count_in++; IN_FORM = 2; iarg++ ; continue ; } if( strcmp(argv[iarg],"-in_gmatA_cols") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '-in_matA_cols'\n") ; Fname_input = argv[iarg]; count_in++; IN_FORM = 3; iarg++ ; continue ; } if( strcmp(argv[iarg],"-in_bmatT_cols") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '-in_matT_cols'\n") ; Fname_input = argv[iarg]; count_in++; IN_FORM = 4; iarg++ ; continue ; } if( strcmp(argv[iarg],"-in_bmatA_cols") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '-in_matA_cols'\n") ; Fname_input = argv[iarg]; count_in++; IN_FORM = 5; iarg++ ; continue ; } if( strcmp(argv[iarg],"-out_grad_rows") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '-out_grad_cols'\n") ; Fname_output = argv[iarg]; count_out++; OUT_FORM = 0; iarg++ ; continue ; } if( strcmp(argv[iarg],"-out_grad_cols") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '-out_grad_cols'\n") ; Fname_output = argv[iarg]; count_out++; OUT_FORM = 1; iarg++ ; continue ; } if( strcmp(argv[iarg],"-out_gmatT_cols") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '-out_gmatT_cols'\n") ; Fname_output = argv[iarg]; count_out++; OUT_FORM = 2; iarg++ ; continue ; } if( strcmp(argv[iarg],"-out_gmatA_cols") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '-out_gmatA_cols'\n") ; Fname_output = argv[iarg]; count_out++; OUT_FORM = 3; iarg++ ; continue ; } if( strcmp(argv[iarg],"-out_bmatT_cols") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '-out_bmatT_cols'\n") ; Fname_output = argv[iarg]; count_out++; OUT_FORM = 4; iarg++ ; continue ; } if( strcmp(argv[iarg],"-out_bmatA_cols") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '-out_bmatA_cols'\n") ; Fname_output = argv[iarg]; count_out++; OUT_FORM = 5; iarg++ ; continue ; } if( strcmp(argv[iarg],"-in_bvals") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '-in_bvals'\n") ; Fname_bval = argv[iarg]; HAVE_BVAL = 1; iarg++ ; continue ; } if( strcmp(argv[iarg],"-bmax_ref") == 0) { iarg++ ; if( iarg >= argc ) ERROR_exit("Need argument after '-bmax_ref'\n"); BMAX_REF = atof(argv[iarg]); HAVE_BMAX_REF = 1; iarg++ ; continue ; } if( strcmp(argv[iarg],"-out_bval_col") == 0) { BVAL_OUT = 1; iarg++ ; continue ; } // May,2015 if( strcmp(argv[iarg],"-out_bval_row_sep") == 0) { if( ++iarg >= argc ) ERROR_exit("Need argument after '-out_bval_row_sep'\n") ; Fname_outputBV = argv[iarg]; BVAL_OUT_SEP = 1; iarg++ ; continue ; } if( strcmp(argv[iarg],"-proc_dset") == 0 ){ // in DWIs if( ++iarg >= argc ) ERROR_exit("Need argument after '-proc_dset'") ; dwset = THD_open_dataset( argv[iarg] ) ; if( dwset == NULL ) ERROR_exit("Can't open DWI dataset '%s'", argv[iarg]) ; DSET_load(dwset) ; CHECK_LOAD_ERROR(dwset) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-pref_dset") == 0 ){ // will be output iarg++ ; if( iarg >= argc ) ERROR_exit("Need argument after '-pref_dset'"); prefix = strdup(argv[iarg]) ; if( !THD_filename_ok(prefix) ) ERROR_exit("Illegal name after '-pref_dset'"); iarg++ ; continue ; } if( strcmp(argv[iarg],"-dwi_comp_fac") == 0) { iarg++ ; if( iarg >= argc ) ERROR_exit("Need argument after '-dwi_comp_fac'\n"); DWI_COMP_FAC = atoi(argv[iarg]); if (DWI_COMP_FAC <=1) ERROR_exit("The compression factor after '-dwi_comp_fac'" "must be >1!"); iarg++ ; continue ; } ERROR_message("Bad option '%s'\n",argv[iarg]) ; suggest_best_prog_option(argv[0], argv[iarg]); exit(1); } // * * * * * * * * * * * * * * * * * * * * * * * * * * * if( (Fname_input == NULL) ) { fprintf(stderr, "\n\tBad Command-lining! Option '-in_*' requires argument.\n"); exit(1); } if( (Fname_output == NULL) ) { fprintf(stderr, "\n\tBad Command-lining! Option '-out_*' requires arg.\n"); exit(2); } if( count_in > 1 ) { fprintf(stderr, "\n\tBad Command-lining! Can't have >1 vec file input.\n"); exit(3); } if( count_out > 1 ) { fprintf(stderr, "\n\tBad Command-lining! Can't have >1 output file opt.\n"); exit(4); } if(YES_B && dwset) { fprintf(stderr, "\n** Bad Command-lining! " "Can't have '-keep_b0s' and '-proc_dset' together.\n"); exit(5); } if( !prefix && dwset) { fprintf(stderr, "\n** Bad Command-lining! " "Need an output '-pref_dset' when using '-proc_dset'.\n"); exit(6); } if(YES_B && DWI_COMP_FAC) { fprintf(stderr, "\n** Bad Command-lining! " "Can't have '-keep_b0s' and '-dwi_comp_fac' together.\n"); exit(7); } if(!HAVE_BVAL && (BVAL_OUT || BVAL_OUT_SEP)) { fprintf(stderr, "\n** Bad Command-lining! " "Can't have ask for outputting bvals with no '-in_bvals FILE'.\n"); exit(8); } // ******************************************************************** // ************************* start reading **************************** // ******************************************************************** flim = mri_read_1D (Fname_input); if (flim == NULL) { ERROR_exit("Error reading gradient vector file"); } if( IN_FORM ) preREADIN = mri_transpose(flim); // effectively *undoes* autotranspose else preREADIN = mri_copy(flim); mri_free(flim); idx = preREADIN->ny; if( HAVE_BVAL ) { flim = mri_read_1D (Fname_bval); if (flim == NULL) { ERROR_exit("Error reading b-value file"); } if( flim->ny == 1) preREADBVAL = mri_transpose(flim); // effectively *undoes* autotransp else preREADBVAL = mri_copy(flim); mri_free(flim); idx2 = preREADBVAL->ny; } if(idx>= MAXGRADS ) { printf("Error, too many input grads.\n"); mri_free (preREADIN); if( HAVE_BVAL ) mri_free (preREADBVAL); exit(4); } if( ( (preREADIN->nx != 3 ) && (preREADIN->ny != 3 )) && (preREADIN->nx != 6 ) ) printf("Probably an error, " "because there aren't 3 or 6 numbers in columns!\n"); if( HAVE_BVAL && ( idx != idx2 ) ) { printf("Error, because the number of bvecs (%d)\n" "and bvals (%d) don't appear to match!\n", idx, idx2); mri_free (preREADIN); mri_free (preREADBVAL); exit(3); } if(dwset) { Nbrik = DSET_NVALS(dwset); if( idx != Nbrik ) { fprintf(stderr, "\n** ERROR: the number of bvecs (%d) does not match the " "number of briks in '-proc_dset' (%d).\n", idx, Nbrik); exit(4); } } READIN = MRI_FLOAT_PTR( preREADIN ); if( HAVE_BVAL ) READBVAL = MRI_FLOAT_PTR( preREADBVAL ); // 0 is grad row; // 1 is grad col; // 2 is gmatrRow col T; // 3 is gmatrDiag col A; // 4 is bmatrRow col T; // 5 is bmatrDiag col A; //if( IN_FORM == 0 ) // grad rows, no binfo // for( i=0; i<idx ; i++ ) // for ( j=0; j<3 ; j++ ) // OUT_GRAD[i][j+1] = *(READIN +j*idx +i) ; //else if ( IN_FORM <= 1 ) // grad cols, no binfo for( i=0; i<idx ; i++ ) for ( j=0; j<3 ; j++ ) OUT_GRAD[i][j+1] = *(READIN + 3*i+j); // A/row/3dDWItoDT: Bxx, Byy, Bzz, Bxy, Bxz, Byz // T/diag/TORTOISE: b_xx 2b_xy 2b_xz b_yy 2b_yz b_zz else if ( (IN_FORM == 3) || (IN_FORM ==5 ) ) { // diag matr for( i=0; i<idx ; i++ ) { for( j=0; j<3 ; j++ ) { OUT_MATR[i][j+1] = *(READIN+6*i+j); OUT_MATR[i][3+j+1] = *(READIN+6*i+3+j); } for( j=0; j<3 ; j++ ) if(OUT_MATR[i][j] < 0 ) CHECK++; } if(CHECK > 0) INFO_message("Warning: you *said* you input a mat'T'," " but the matr diagonals don't appear to be uniformly" " positive. If input cols 0, 3 and 5 are positive," " then you might have meant mat'A'?"); } else if ( (IN_FORM ==2 ) || (IN_FORM ==4 ) ) { // row matr CHECK = 0; for( i=0; i<idx ; i++ ) { OUT_MATR[i][1] = *(READIN +6*i); OUT_MATR[i][2] = *(READIN +6*i+3); OUT_MATR[i][3] = *(READIN +6*i+5); OUT_MATR[i][4] = *(READIN +6*i+1)/2.; OUT_MATR[i][5] = *(READIN +6*i+2)/2.; OUT_MATR[i][6] = *(READIN +6*i+4)/2.; } for( i=0; i<idx ; i++ ) for( j=0; j<3 ; j++ ) if(OUT_MATR[i][j] < 0 ) CHECK++; if(CHECK > 0) INFO_message("Warning: you *said* you input a mat'A'," " but the matr diagonals don't appear to be uniformly" " positive. If input cols 0, 1 and 2 are positive," " then you might have meant mat'T'?"); } else{ fprintf(stderr, "Coding error with format number (%d), not allowed.\n", IN_FORM); exit(2); } // get bval info if( ( (IN_FORM ==4 ) || (IN_FORM ==5 ) ) ) { //bval for( i=0; i<idx ; i++ ) { OUT_MATR[i][0] = OUT_GRAD[i][0] = OUT_MATR[i][1] + OUT_MATR[i][2] + OUT_MATR[i][3]; if( OUT_MATR[i][0] > 0.000001) for( j=1 ; j<7 ; j++ ) OUT_MATR[i][j]/= OUT_MATR[i][0]; } } else if ( HAVE_BVAL ) for( i=0; i<idx ; i++ ) { OUT_MATR[i][0] = OUT_GRAD[i][0] = *(READBVAL + i); } else if ( OUT_FORM > 3 || BVAL_OUT || BVAL_OUT_SEP || HAVE_BMAX_REF ) { fprintf(stderr, "ERROR: you asked for b-value dependent output, " "but gave me no bvals to work with.\n"); exit(2); } // * * * ** * * * * * * * * ** ** * * ** * * ** * ** * ** * * * // at this point, all IN_FORM >1 cases which need bval have led to: // + grad[0] has bval // + matr[0] has bval // + matr file normalized and in diagonal form // * * * ** * * * * * * * * ** ** * * ** * * ** * ** * ** * * * for( i=0; i<idx ; i++ ) if( IN_FORM > 1) j = GradConv_Gsign_from_BmatA( OUT_GRAD[i]+1, OUT_MATR[i]+1); else j = GradConv_BmatA_from_Gsign( OUT_MATR[i]+1, OUT_GRAD[i]+1); // flip if necessary for( i=0 ; i<idx ; i++) { for( j=0 ; j<3 ; j++) OUT_GRAD[i][j+1]*= INV[j]; OUT_MATR[i][4]*= INV[0]*INV[1]; OUT_MATR[i][5]*= INV[0]*INV[2]; OUT_MATR[i][6]*= INV[1]*INV[2]; } BZER=0; for( i=0 ; i<idx ; i++) { if( HAVE_BVAL || (IN_FORM ==4) || (IN_FORM ==5) ) if( OUT_GRAD[i][0] >= BMAX_REF ) FLAG[i] = 1; else{ if( YES_B ) FLAG[i] = 1; BZER++; } else { temp = 0.; for( j=1 ; j<4 ; j++) temp+= pow(OUT_GRAD[i][j],2); if( temp > 0.1 ) FLAG[i] = 1; else{ if( YES_B ) FLAG[i] = 1; BZER++; } } } if(YES_B) { printf("\tChose to *keep* %d b0s,\tas well as \t%d grads\n", BZER,idx-BZER); BZER=0; } else { printf("\tGetting rid of %d b0s,\tleaving the %d grads\n", BZER,idx-BZER); Ndwi = idx-BZER; } Ndwi_final = idx-BZER; // default: all DWIs if( DWI_COMP_FAC ) { if( Ndwi % DWI_COMP_FAC != 0 ) { fprintf(stderr, "\n** ERROR can't compress: " "Ndwi=%d, and %d/%d has a nonzero remainder (=%d).\n", Ndwi,Ndwi,DWI_COMP_FAC, Ndwi % DWI_COMP_FAC ); exit(1); } else { Ndwi_final = Ndwi/DWI_COMP_FAC; INFO_message("You have chosen a compression factor of %d, " "with %d DWIs,\n" "\tso that afterward there will be %d DWIs.", DWI_COMP_FAC, Ndwi, Ndwi_final); } } if(BVAL_OUT_SEP) if( (foutBV = fopen(Fname_outputBV, "w")) == NULL) { fprintf(stderr, "\n\nError opening file %s.\n",Fname_outputBV); exit(1); } if( (fout = fopen(Fname_output, "w")) == NULL) { fprintf(stderr, "\n\nError opening file %s.\n",Fname_output); exit(1); } // 0 is grad row; // 1 is grad col; // 2 is gmatrRow col T; // 3 is gmatrDiag col A; // 4 is bmatrRow col T; // 5 is bmatrDiag col A; if( OUT_FORM>0) { if( EXTRA_ZEROS ) { if( BVAL_OUT ) fprintf(fout,"%8d ", 0); if( BVAL_OUT_SEP ) fprintf(foutBV,"%8d ", 0); if( OUT_FORM == 1 ) for( k=1 ; k<4 ; k++ ) fprintf(fout,"%11.5f ", 0.0); else if ( OUT_FORM > 1 ) // bit superfluous at this point for( k=1 ; k<7 ; k++ ) fprintf(fout,"%11.5f ", 0.0); fprintf(fout,"\n"); } ct_dwi = 0; for(i=0 ; i<idx ; i++){ if(FLAG[i]) { if( BVAL_OUT ) fprintf(fout,"%8d ", (int) OUT_GRAD[i][0]); if( BVAL_OUT_SEP ) fprintf(foutBV,"%8d ", (int) OUT_GRAD[i][0]); if( (OUT_FORM == 4) || (OUT_FORM ==5) ) for( k=1 ; k<7 ; k++ ) OUT_MATR[i][k]*= OUT_MATR[i][0]; if( OUT_FORM == 1 ) // grad col for( k=1 ; k<4 ; k++ ) fprintf(fout,"%11.5f ", OUT_GRAD[i][k]); else if( (OUT_FORM == 3) || (OUT_FORM == 5) ) { // gmat for( k=1 ; k<6 ; k++ ) fprintf(fout,"%11.5f ", OUT_MATR[i][k]); fprintf(fout,"%11.5f", OUT_MATR[i][k]); } else if ( (OUT_FORM == 2 ) || (OUT_FORM ==4)) { // bmat fprintf(fout,"%11.5f ", OUT_MATR[i][1]); fprintf(fout,"%11.5f ", 2*OUT_MATR[i][4]); fprintf(fout,"%11.5f ", 2*OUT_MATR[i][5]); fprintf(fout,"%11.5f ", OUT_MATR[i][2]); fprintf(fout,"%11.5f ", 2*OUT_MATR[i][6]); fprintf(fout,"%11.5f", OUT_MATR[i][3]); } fprintf(fout,"\n"); ct_dwi++; } if( (ct_dwi == Ndwi_final) && DWI_COMP_FAC ) { INFO_message("Reached compression level: DWI number %d", Ndwi_final); break; } } } else if(OUT_FORM ==0) { if(BVAL_OUT) WARNING_message("Ignoring '-out_bval_col' option, since " " you are outputting in rows."); for( k=1 ; k<4 ; k++ ) { if(EXTRA_ZEROS){ fprintf(fout,"% -11.5f ", 0.0); if( (k==1) && BVAL_OUT_SEP ) // only output 1 zeroin bval file fprintf(foutBV,"%8d ", 0); } ct_dwi = 0; for(i=0 ; i<idx ; i++) { if(FLAG[i]) { fprintf(fout,"% -11.5f ", OUT_GRAD[i][k]); if( (k==1) && BVAL_OUT_SEP )// only output 1 zeroin bval file fprintf(foutBV,"%8d ", (int) OUT_GRAD[i][0]); ct_dwi++; } if( (ct_dwi == Ndwi_final) && DWI_COMP_FAC ) { INFO_message("Reached compression level: DWI number %d", Ndwi_final); break; } } fprintf(fout,"\n"); } } fclose(fout); if( BVAL_OUT_SEP ) { fprintf(foutBV,"\n"); fclose(foutBV); } if(dwset) { INFO_message("Processing the B0+DWI file now."); if(!BZER) { fprintf(stderr, "\n** Error in processing data set: " "no b=0 values from bvecs/bval info!\n"); exit(5); } // FLAG marks where DWIs are if not using '-keep_b0s'! Nvox = DSET_NVOX(dwset); Ndwout = Ndwi+1; temp_arr = calloc( Ndwout,sizeof(temp_arr)); for( i=0 ; i<Ndwout ; i++) temp_arr[i] = calloc( Nvox,sizeof(float)); temp_grad = calloc( Ndwi,sizeof(temp_grad)); for( i=0 ; i<Ndwi ; i++) temp_grad[i] = calloc( 3,sizeof(float)); if( (temp_arr == NULL) || (temp_grad == NULL) ) { fprintf(stderr, "\n\n MemAlloc failure.\n\n"); exit(123); } dwi = 0; // keep track of DWI contraction for( i=0 ; i<Nbrik ; i++) if( !FLAG[i] ) // b=0 for( j=0 ; j<Nvox ; j++) temp_arr[0][j]+= THD_get_voxel(dwset,j,i); else { for( j=0 ; j<3 ; j++) temp_grad[dwi][j]= OUT_GRAD[i][j+1]; dwi++; for( j=0 ; j<Nvox ; j++) temp_arr[dwi][j]+= THD_get_voxel(dwset,j,i); } if( dwi != Ndwi ) { fprintf(stderr, "\n** Mismatch in internal DWI counting!\n"); exit(6); } // average the values for( j=0 ; j<Nvox ; j++) temp_arr[0][j]/= BZER; // can't be zero here. if( DWI_COMP_FAC ) { INFO_message("Compressing DWI file"); for( k=1 ; k<DWI_COMP_FAC ; k++) for( i=0 ; i<Ndwi_final ; i++) for( j=0 ; j<Nvox ; j++) temp_arr[1+i][j]+= temp_arr[1+k*Ndwi_final+i][j]; for( i=0 ; i<Ndwi_final ; i++) for( j=0 ; j<Nvox ; j++) temp_arr[1+i][j]/= DWI_COMP_FAC; INFO_message("Checking closeness of compressed gradient values"); MaxDP = GradCloseness(temp_grad, Ndwi, DWI_COMP_FAC); INFO_message("The max angular difference between matched/compressed\n" "\tgradients is: %f", MaxDP); if( MaxDP > 2) WARNING_message("The max angular difference seem kinda big-- you\n" " sure about the compression factor?"); } Ndwout_final = Ndwi_final + 1; INFO_message("Writing the processed data set."); dwout = EDIT_empty_copy( dwset ); EDIT_dset_items(dwout, ADN_nvals, Ndwout_final, ADN_ntt, 0, ADN_datum_all, MRI_float , ADN_prefix, prefix, ADN_none ); for( i=0; i<Ndwout_final ; i++) { EDIT_substitute_brick(dwout, i, MRI_float, temp_arr[i]); temp_arr[i]=NULL; } // if necessary for( i=Ndwout_final ; i<Ndwout ; i++) temp_arr[i]=NULL; THD_load_statistics( dwout ); if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(dwout)) ) ERROR_exit("Can't overwrite existing dataset '%s'", DSET_HEADNAME(dwout)); tross_Make_History("1dDW_Grad_o_Mat", argc, argv, dwout); THD_write_3dim_dataset(NULL, NULL, dwout, True); DSET_delete(dwout); free(dwout); DSET_delete(dwset); free(dwset); for( i=0 ; i<Ndwout_final ; i++) free(temp_arr[i]); free(temp_arr); } mri_free(preREADIN); if( HAVE_BVAL ) mri_free(preREADBVAL); if(prefix) free(prefix); printf("\n\tDone. Check output file '%s' for results",Fname_output); if(dwset) { printf("\n\t-> as well as the data_set '%s'",DSET_FILECODE(dwout)); } if(BVAL_OUT_SEP) printf("\n\t-> and even the b-value rows '%s'",Fname_outputBV); printf("\n\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) ; }
void conv_set_ref( int num , float ** ref ) { int jv ; if( num > 0 && ref != NULL ){ /*** if have inputs, make space & copy in ***/ int ii ; for( jv=0 ; jv < NREF ; jv++ ){ /* get rid of old data? */ if( refts[jv] != NULL ){ free(refts[jv]); refts[jv] = NULL; free(refin[jv]); refin[jv] = NULL; } /* copy new data */ refnum[jv] = num ; refts[jv] = (float *) malloc( sizeof(float) * num ) ; refin[jv] = (int *) malloc( sizeof(int) * num ) ; memcpy( refts[jv] , ref[jv] , sizeof(float) * num ) ; /* build a list of nonzero entries in this column */ for( ii=0,refnz[jv]=0 ; ii < num ; ii++ ) if( refts[jv][ii] != 0.0 ) refin[jv][refnz[jv]++] = ii ; if( refnz[jv] == 0 ) ERREX(__FILE__ ": All zero reference timeseries column!") ; } return ; } else { /*** if no inputs, do something special ***/ char * cp ; MRI_IMAGE * flim ; int jv , nx ; float * ref[NREF] ; cp = my_getenv("AFNI_CONVMODEL_REF") ; /* get name of reference file */ if( cp == NULL ) ERREX(__FILE__ ": Can't read AFNI_CONVMODEL_REF from environment") ; flim = mri_read_1D(cp) ; /* 16 Nov 1999: replaces mri_read_ascii */ if( flim == NULL ){ char buf[256] ; sprintf(buf,__FILE__ ": Can't read timeseries file %s",cp) ; ERREX(buf) ; } else { fprintf(stderr,__FILE__ ": Read reference file %s\n",cp) ; } if( flim->ny < NREF ) ERREX(__FILE__ ": reference file has too few columns!") ; else if( flim->nv > NREF ) fprintf(stderr,__FILE__ " WARNING: reference file has too many columns!\n") ; nx = flim->nx ; for( jv=0 ; jv < NREF ; jv++ ) ref[jv] = MRI_FLOAT_PTR(flim) + jv*nx ; conv_set_ref( nx , ref ) ; /* recursion! */ mri_free(flim) ; } return ; }
int main( int argc , char *argv[] ) { MRI_IMAGE *inim , *outim ; float *iv ; int iarg , ii,jj , nreg , ntime , *tau=NULL , rnum ; NI_element *nelmat=NULL ; char *matname=NULL ; MTYPE rhomax=0.7 , bmax=0.7 ; int rhonum=7 , bnum=14 ; char *cgl , *rst ; matrix X ; vector y ; float cput ; reml_collection *rrcol ; if( argc < 2 || strcmp(argv[1],"-help") == 0 ){ printf( "Usage: 1dREMLfit [option] file.1D\n" "Least squares fit with REML estimation of the ARMA(1,1) noise.\n" "\n" "Options (the first one is mandatory)\n" "------------------------------------\n" " -matrix mmm = Read the matrix 'mmm', which should have been\n" " output from 3dDeconvolve via the '-x1D' option.\n" " -MAXrho rm = Set the max allowed rho parameter to 'rm' (default=0.7).\n" " -Nrho nr = Use 'nr' values for the rho parameter (default=7).\n" " -MAXb bm = Set max allow MA b parameter to 'bm' (default=0.7).\n" " -Nb nb = Use 'nb' values for the b parameter (default=7).\n" ) ; PRINT_COMPILE_DATE ; exit(0) ; } iarg = 1 ; while( iarg < argc && argv[iarg][0] == '-' ){ /** rho and del params **/ if( strcmp(argv[iarg],"-MAXrho") == 0 ){ rhomax = (MTYPE)strtod(argv[++iarg],NULL) ; if( rhomax < 0.3 ) rhomax = 0.3 ; else if( rhomax > 0.9 ) rhomax = 0.9 ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-Nrho") == 0 ){ rhonum = (int)strtod(argv[++iarg],NULL) ; if( rhonum < 2 ) rhonum = 2 ; else if( rhonum > 20 ) rhonum = 20 ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-MAXb") == 0 ){ bmax = (MTYPE)strtod(argv[++iarg],NULL) ; if( bmax < 0.3 ) bmax = 0.3 ; else if( bmax > 0.9 ) bmax = 0.9 ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-Nb") == 0 ){ bnum = (int)strtod(argv[++iarg],NULL) ; if( bnum < 2 ) bnum = 2 ; else if( bnum > 20 ) bnum = 20 ; iarg++ ; continue ; } /** -matrix **/ if( strcmp(argv[iarg],"-matrix") == 0 ){ if( nelmat != NULL ) ERROR_exit("More than 1 -matrix option!"); nelmat = NI_read_element_fromfile( argv[++iarg] ) ; /* read NIML file */ matname = argv[iarg]; if( nelmat == NULL ){ /* try to read as a 1D file */ MRI_IMAGE *nim ; float *nar ; nim = mri_read_1D(argv[iarg]) ; if( nim != NULL ){ /* construct a minimal NIML element */ nelmat = NI_new_data_element( "matrix" , nim->nx ) ; nar = MRI_FLOAT_PTR(nim) ; for( jj=0 ; jj < nim->ny ; jj++ ) NI_add_column( nelmat , NI_FLOAT , nar + nim->nx*jj ) ; mri_free(nim) ; } } if( nelmat == NULL || nelmat->type != NI_ELEMENT_TYPE ) ERROR_exit("Can't process -matrix file!"); iarg++ ; continue ; } ERROR_exit("Unknown option '%s'",argv[iarg]) ; } if( iarg >= argc ) ERROR_exit("No 1D file on command line?!") ; inim = mri_read_1D( argv[iarg] ) ; if( inim == NULL ) ERROR_exit("Can't read 1D file %s",argv[iarg]) ; nreg = nelmat->vec_num ; ntime = nelmat->vec_len ; if( ntime != inim->nx ) ERROR_exit("matrix vectors are %d long but input 1D file is %d long", ntime,inim->nx) ; cgl = NI_get_attribute( nelmat , "GoodList" ) ; if( cgl != NULL ){ int Ngoodlist,*goodlist , Nruns,*runs ; NI_int_array *giar ; giar = NI_decode_int_list( cgl , ";," ) ; if( giar == NULL || giar->num < ntime ) ERROR_exit("-matrix 'GoodList' badly formatted?") ; Ngoodlist = giar->num ; goodlist = giar->ar ; rst = NI_get_attribute( nelmat , "RunStart" ) ; if( rst != NULL ){ NI_int_array *riar = NI_decode_int_list( rst , ";,") ; if( riar == NULL ) ERROR_exit("-matrix 'RunStart' badly formatted?") ; Nruns = riar->num ; runs = riar->ar ; } else { Nruns = 1 ; runs = calloc(sizeof(int),1) ; } rnum = 0 ; tau = (int *)malloc(sizeof(int)*ntime) ; for( ii=0 ; ii < ntime ; ii++ ){ jj = goodlist[ii] ; for( ; rnum+1 < Nruns && jj >= runs[rnum+1] ; rnum++ ) ; /*nada*/ tau[ii] = jj + 10000*rnum ; } } matrix_initialize( &X ) ; matrix_create( ntime , nreg , &X ) ; if( nelmat->vec_typ[0] == NI_FLOAT ){ float *cd ; for( jj=0 ; jj < nreg ; jj++ ){ cd = (float *)nelmat->vec[jj] ; for( ii=0 ; ii < ntime ; ii++ ) X.elts[ii][jj] = (MTYPE)cd[ii] ; } } else if( nelmat->vec_typ[0] == NI_DOUBLE ){ double *cd ; for( jj=0 ; jj < nreg ; jj++ ){ cd = (double *)nelmat->vec[jj] ; for( ii=0 ; ii < ntime ; ii++ ) X.elts[ii][jj] = (MTYPE)cd[ii] ; } } else { ERROR_exit("-matrix file stored will illegal data type!?") ; } cput = COX_cpu_time() ; rrcol = REML_setup( &X , tau , rhonum,rhomax,bnum,bmax ) ; if( rrcol == NULL ) ERROR_exit("REML setup fails?" ) ; cput = COX_cpu_time() - cput ; INFO_message("REML setup: rows=%d cols=%d %d cases CPU=%.2f", ntime,nreg,rrcol->nset,cput) ; cput = COX_cpu_time() ; vector_initialize( &y ) ; vector_create_noinit( ntime , &y ) ; for( jj=0 ; jj < inim->ny ; jj++ ){ iv = MRI_FLOAT_PTR(inim) + ntime*jj ; for( ii=0 ; ii < ntime ; ii++ ) y.elts[ii] = (MTYPE)iv[ii] ; (void)REML_find_best_case( &y , rrcol ) ; INFO_message( "Vector #%d: best_rho=%.2f best_b=%.2f best_lam=%.2f best_ssq=%g olsq_ssq=%g", jj, REML_best_rho, REML_best_bb, REML_best_lam, REML_best_ssq, REML_olsq_ssq ) ; } cput = COX_cpu_time() - cput ; INFO_message("REML fitting: CPU=%.2f",cput) ; exit(0) ; }
int main( int argc , char *argv[] ) { int iarg , ii,jj,kk,mm , nvec , do_one=0 , nx=0,ny , ff, doterse = 0 ; MRI_IMAGE *tim ; MRI_IMARR *tar ; double sum , *eval , *amat , **tvec , *bmat , *svec ; float *far ; int demean=0 , docov=0 ; char *matname ; int okzero = 0; mainENTRY("1ddot main"); machdep(); /* options */ iarg = 1 ; nvec = 0 ; while( iarg < argc && argv[iarg][0] == '-' ){ if (strcmp(argv[iarg],"-help") == 0 || strcmp(argv[iarg],"-h") == 0){ usage_1ddot(strlen(argv[iarg])>3 ? 2:1); exit(0); } if( strcmp(argv[iarg],"-one") == 0 ){ demean = 0 ; do_one = 1 ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-okzero") == 0 ){ okzero = 1 ; iarg++ ; continue ; } if( strncmp(argv[iarg],"-dem",4) == 0 ){ demean = 1 ; do_one = 0 ; iarg++ ; continue ; } if( strncmp(argv[iarg],"-cov",4) == 0 ){ docov = 1 ; iarg++ ; continue ; } if( strncmp(argv[iarg],"-inn",4) == 0 ){ docov = 2 ; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-rank") == 0 || strcasecmp(argv[iarg],"-spearman") == 0 ){ do_one = 0; docov = 3; demean = 0; doterse = 1; iarg++; continue; } if( strncmp(argv[iarg],"-terse",4) == 0 ){ doterse = 1 ; iarg++ ; continue ; } fprintf(stderr,"** Unknown option: %s\n",argv[iarg]); suggest_best_prog_option(argv[0], argv[iarg]); exit(1); } if( argc < 2 ){ usage_1ddot(1); exit(0) ; } if( iarg == argc ) ERROR_exit("No 1D files on command line!?") ; /* input 1D files */ ff = iarg ; INIT_IMARR(tar) ; if( do_one ) nvec = 1 ; for( ; iarg < argc ; iarg++ ){ tim = mri_read_1D( argv[iarg] ) ; if( tim == NULL ){ fprintf(stderr,"** Can't read 1D file %s\n",argv[iarg]); exit(1); } if( nx == 0 ){ nx = tim->nx ; } else if( tim->nx != nx ){ fprintf(stderr,"** 1D file %s doesn't match first file in length!\n", argv[iarg]); exit(1); } nvec += tim->ny ; ADDTO_IMARR(tar,tim) ; } if (!doterse) { printf("\n") ; printf("++ 1ddot input vectors:\n") ; } jj = 0 ; if( do_one ){ if (!doterse) printf("00..00: all ones\n") ; jj = 1 ; } for( mm=0 ; mm < IMARR_COUNT(tar) ; mm++ ){ tim = IMARR_SUBIM(tar,mm) ; if (!doterse) printf("%02d..%02d: %s\n", jj,jj+tim->ny-1, argv[ff+mm] ) ; jj += tim->ny ; } /* create vectors from 1D files */ tvec = (double **) malloc( sizeof(double *)*nvec ) ; svec = (double * ) malloc( sizeof(double )*nvec ) ; for( jj=0 ; jj < nvec ; jj++ ) tvec[jj] = (double *) malloc( sizeof(double)*nx ) ; kk = 0 ; if( do_one ){ svec[0] = 1.0 / sqrt((double)nx) ; for( ii=0 ; ii < nx ; ii++ ) tvec[0][ii] = 1.0 ; kk = 1 ; } for( mm=0 ; mm < IMARR_COUNT(tar) ; mm++ ){ tim = IMARR_SUBIM(tar,mm) ; far = MRI_FLOAT_PTR(tim) ; for( jj=0 ; jj < tim->ny ; jj++,kk++ ){ for( ii=0 ; ii < nx ; ii++ ) tvec[kk][ii] = far[ii+jj*nx] ; if( demean ){ sum = 0.0 ; for( ii=0 ; ii < nx ; ii++ ) sum += tvec[kk][ii] ; sum /= nx ; for( ii=0 ; ii < nx ; ii++ ) tvec[kk][ii] -= sum ; } sum = 0.0 ; for( ii=0 ; ii < nx ; ii++ ) sum += tvec[kk][ii] * tvec[kk][ii] ; if( sum == 0.0 ) { if (okzero) svec[kk] = 0.0; else ERROR_exit("Input column %02d is all zero!",kk) ; } else { svec[kk] = 1.0 / sqrt(sum) ; } } } DESTROY_IMARR(tar) ; /* normalize vectors? (for ordinary correlation) */ if( !docov ){ for( kk=0 ; kk < nvec ; kk++ ){ sum = svec[kk] ; for( ii=0 ; ii < nx ; ii++ ) tvec[kk][ii] *= sum ; } } switch(docov){ default: case 3: matname = "Spearman" ; break ; case 2: matname = "InnerProduct" ; break ; case 1: matname = "Covariance" ; break ; case 0: matname = "Correlation" ; break ; } /* create matrix from dot product of vectors */ amat = (double *) calloc( sizeof(double) , nvec*nvec ) ; if( docov != 3 ){ for( kk=0 ; kk < nvec ; kk++ ){ for( jj=0 ; jj <= kk ; jj++ ){ sum = 0.0 ; for( ii=0 ; ii < nx ; ii++ ) sum += tvec[jj][ii] * tvec[kk][ii] ; amat[jj+nvec*kk] = sum ; if( jj < kk ) amat[kk+nvec*jj] = sum ; } } } else { /* Spearman */ for( kk=0 ; kk < nvec ; kk++ ){ for( jj=0 ; jj <= kk ; jj++ ){ amat[jj+nvec*kk] = THD_spearman_corr_dble( nx , tvec[jj] , tvec[kk] ) ; if( jj < kk ) amat[kk+nvec*jj] = amat[jj+nvec*kk] ; } } } /* normalize */ if (docov==1) { for( kk=0 ; kk < nvec ; kk++ ){ for( jj=0 ; jj <= kk ; jj++ ){ sum = amat[jj+nvec*kk] / (double) (nx-1); amat[jj+nvec*kk] = sum; if( jj < kk ) amat[kk+nvec*jj] = sum ; } } } /* print matrix out */ if (!doterse) { printf("\n" "++ %s Matrix:\n ",matname) ; for( jj=0 ; jj < nvec ; jj++ ) printf(" %02d ",jj) ; printf("\n ") ; for( jj=0 ; jj < nvec ; jj++ ) printf(" ---------") ; printf("\n") ; } for( kk=0 ; kk < nvec ; kk++ ){ if (!doterse) printf("%02d:",kk) ; for( jj=0 ; jj < nvec ; jj++ ) printf(" %9.5f",amat[jj+kk*nvec]) ; printf("\n") ; } if (doterse) exit(0) ; /* au revoir */ /* compute eigendecomposition */ eval = (double *) malloc( sizeof(double)*nvec ) ; symeig_double( nvec , amat , eval ) ; printf("\n" "++ Eigensolution of %s Matrix:\n " , matname ) ; for( jj=0 ; jj < nvec ; jj++ ) printf(" %9.5f",eval[jj]) ; printf("\n ") ; for( jj=0 ; jj < nvec ; jj++ ) printf(" ---------") ; printf("\n") ; for( kk=0 ; kk < nvec ; kk++ ){ printf("%02d:",kk) ; for( jj=0 ; jj < nvec ; jj++ ) printf(" %9.5f",amat[kk+jj*nvec]) ; printf("\n") ; } /* compute matrix inverse */ if ( eval[0]/eval[nvec-1] < 1.0e-10) { printf("\n" "-- WARNING: Matrix is near singular,\n" " rubbish likely for inverses ahead.\n"); } for( jj=0 ; jj < nvec ; jj++ ) eval[jj] = 1.0 / eval[jj] ; bmat = (double *) calloc( sizeof(double) , nvec*nvec ) ; for( ii=0 ; ii < nvec ; ii++ ){ for( jj=0 ; jj < nvec ; jj++ ){ sum = 0.0 ; for( kk=0 ; kk < nvec ; kk++ ) sum += amat[ii+kk*nvec] * amat[jj+kk*nvec] * eval[kk] ; bmat[ii+jj*nvec] = sum ; } } printf("\n") ; printf("++ %s Matrix Inverse:\n " , matname ) ; for( jj=0 ; jj < nvec ; jj++ ) printf(" %02d ",jj) ; printf("\n ") ; for( jj=0 ; jj < nvec ; jj++ ) printf(" ---------") ; printf("\n") ; for( kk=0 ; kk < nvec ; kk++ ){ printf("%02d:",kk) ; for( jj=0 ; jj < nvec ; jj++ ) printf(" %9.5f",bmat[jj+kk*nvec]) ; printf("\n") ; } /* square roots of diagonals of the above */ printf("\n") ; printf("++ %s sqrt(diagonal)\n ",matname) ; for( jj=0 ; jj < nvec ; jj++ ) printf(" %9.5f",sqrt(bmat[jj+jj*nvec])) ; printf("\n") ; /* normalize matrix inverse */ for( ii=0 ; ii < nvec ; ii++ ){ for( jj=0 ; jj < nvec ; jj++ ){ sum = bmat[ii+ii*nvec] * bmat[jj+jj*nvec] ; if( sum > 0.0 ) amat[ii+jj*nvec] = bmat[ii+jj*nvec] / sqrt(sum) ; else amat[ii+jj*nvec] = 0.0 ; } } printf("\n") ; printf("++ %s Matrix Inverse Normalized:\n " , matname ) ; for( jj=0 ; jj < nvec ; jj++ ) printf(" %02d ",jj) ; printf("\n ") ; for( jj=0 ; jj < nvec ; jj++ ) printf(" ---------") ; printf("\n") ; for( kk=0 ; kk < nvec ; kk++ ){ printf("%02d:",kk) ; for( jj=0 ; jj < nvec ; jj++ ) printf(" %9.5f",amat[jj+kk*nvec]) ; printf("\n") ; } /* done */ exit(0) ; }
int main (int argc,char *argv[]) {/* Main */ static char FuncName[]={"SurfPatch"}; SUMA_GETPATCH_OPTIONS *Opt; char *ppref=NULL, ext[5]; float *far=NULL; MRI_IMAGE *im = NULL; int SO_read = -1; int *NodePatch=NULL, N_NodePatch=-1, *FaceSetList=NULL , N_FaceSet = -1, N_Node = -1, N_Spec=0; int i, inodeoff=-1, ilabeloff=-1, nvec, ncol, cnt; SUMA_SurfaceObject *SO = NULL; SUMA_PATCH *ptch = NULL; SUMA_SurfSpecFile *Spec; SUMA_INDEXING_ORDER d_order; void *SO_name = NULL; SUMA_Boolean exists = NOPE; SUMA_SO_File_Type typetmp; SUMA_SurfaceObject *SOnew = NULL; float *NodeList = NULL; SUMA_GENERIC_ARGV_PARSE *ps=NULL; SUMA_Boolean LocalHead = NOPE; SUMA_STANDALONE_INIT; SUMA_mainENTRY; ps = SUMA_Parse_IO_Args(argc, argv, "-i;-t;-spec;-s;-sv;"); /* Allocate space for DO structure */ SUMAg_DOv = SUMA_Alloc_DisplayObject_Struct (SUMA_MAX_DISPLAYABLE_OBJECTS); Opt = SUMA_GetPatch_ParseInput (argv, argc, ps); if (argc < 2) { SUMA_S_Err("Too few options"); usage_SUMA_getPatch(ps, 0); exit (1); } /* read all surfaces */ Spec = SUMA_IO_args_2_spec(ps, &N_Spec); if (N_Spec == 0) { SUMA_S_Err("No surfaces found."); exit(1); } if (N_Spec > 1 ) { SUMA_S_Err( "Mike, you cannot mix -spec with -i or -t options " "for specifying surfaces."); exit(1); } if (Spec->N_Surfs < 1) { SUMA_S_Err("No surfaces"); exit(1); } if (Opt->DoVol && Spec->N_Surfs != 2) { SUMA_S_Errv("Must specify 2 and only 2 surfaces with -vol options\n" "Have %d from the command line\n",Spec->N_Surfs); exit(1); } if (Opt->oType != SUMA_FT_NOT_SPECIFIED && !Opt->VolOnly) { for (i=0; i < Spec->N_Surfs; ++i) { if (Spec->N_Surfs > 1) { sprintf(ext, "_%c", 65+i); ppref = SUMA_append_string(Opt->out_prefix, ext); } else { ppref = SUMA_copy_string(Opt->out_prefix); } SO_name = SUMA_Prefix2SurfaceName(ppref, NULL, NULL, Opt->oType, &exists); if (exists && !THD_ok_overwrite()) { fprintf(SUMA_STDERR, "Error %s:\nOutput file(s) %s* on disk.\n" "Will not overwrite.\n", FuncName, ppref); exit(1); } if (ppref) SUMA_free(ppref); ppref = NULL; if (SO_name) SUMA_free(SO_name); SO_name = NULL; } } /* read in the file containing the node information */ im = mri_read_1D (Opt->in_name); if (!im) { SUMA_S_Errv("Failed to read 1D file '%s'\n", Opt->in_name); exit(1); } far = MRI_FLOAT_PTR(im); nvec = im->nx; ncol = im->ny; if (Opt->nodecol >= ncol || Opt->labelcol >= ncol) { fprintf(SUMA_STDERR, "\n" "Error %s: Input file has a total of %d columns.\n" "One or both user-specified node (%d) and \n" "label (%d) columns are too high. Maximum usable\n" "column index is %d.\n" , FuncName, ncol, Opt->nodecol, Opt->labelcol, ncol -1 ); exit(1); } d_order = SUMA_COLUMN_MAJOR; if (!nvec) { SUMA_SL_Err("Empty file"); exit(1); } /* form the node vector */ NodePatch = (int *)SUMA_malloc(sizeof(int)*nvec); if (!NodePatch) { SUMA_SL_Crit("Failed to allocate."); exit(1); } inodeoff = Opt->nodecol*nvec; if (Opt->labelcol < 0) { /* all listed nodes */ for (i=0; i<nvec; ++i) { NodePatch[i] = far[i+inodeoff]; } N_NodePatch = nvec; } else { ilabeloff = Opt->labelcol*nvec; if (Opt->thislabel < 0) { /* all nodes with non zero labels */ cnt = 0; for (i=0; i<nvec; ++i) { if (far[i+ilabeloff]) { NodePatch[cnt] = far[i+inodeoff]; ++cnt; } } N_NodePatch = cnt; } else { /* select labels */ cnt = 0; for (i=0; i<nvec; ++i) { if (far[i+ilabeloff] == Opt->thislabel) { NodePatch[cnt] = far[i+inodeoff]; ++cnt; } } N_NodePatch = cnt; } NodePatch = (int *) SUMA_realloc(NodePatch , sizeof(int)*N_NodePatch); } /* done with im, free it */ mri_free(im); im = NULL; if (Opt->DoVol) { SUMA_SurfaceObject *SO1 = SUMA_Load_Spec_Surf_with_Metrics(Spec, 0, ps->sv[0], 0); SUMA_SurfaceObject *SO2 = SUMA_Load_Spec_Surf_with_Metrics(Spec, 1, ps->sv[0], 0); double Vol = 0.0; SUMA_SurfaceObject *SOp = SUMA_Alloc_SurfObject_Struct(1); byte *adj_N=NULL; if (Opt->adjust_contour) adj_N = SUMA_calloc(SO1->N_Node, sizeof(byte)); if (!SO1 || !SO2) { SUMA_SL_Err("Failed to load surfaces."); exit(1); } /* a chunk used to test SUMA_Pattie_Volume */ Vol = SUMA_Pattie_Volume(SO1, SO2, NodePatch, N_NodePatch, SOp, Opt->minhits, Opt->FixBowTie, Opt->adjust_contour, adj_N, Opt->verb); fprintf (SUMA_STDOUT,"Volume = %f\n", fabs(Vol)); if (Opt->out_volprefix) { if (Opt->oType != SUMA_FT_NOT_SPECIFIED) SOp->FileType = Opt->oType; if (Opt->flip) { if (Opt->verb > 1) SUMA_S_Note("Flipping stitched surf's triangles\n"); SUMA_FlipSOTriangles (SOp); } if (!(SUMA_Save_Surface_Object_Wrap ( Opt->out_volprefix, NULL, SOp, SUMA_PLY, SUMA_ASCII, NULL))) { fprintf (SUMA_STDERR, "Error %s: Failed to write surface object.\n", FuncName); } if (Opt->adjust_contour && adj_N) { Opt->out_volprefix = SUMA_append_replace_string(Opt->out_volprefix, ".adjneighb","",1); ppref = SUMA_Extension(Opt->out_volprefix, ".1D.dset", NOPE); SUMA_WRITE_IND_ARRAY_1D(adj_N, NULL, SO1->N_Node, 1, ppref); SUMA_free(ppref); ppref=NULL; } } if (SOp) SUMA_Free_Surface_Object(SOp); SOp = NULL; } if (!Opt->VolOnly) { FaceSetList = NULL; N_FaceSet = -1; for (i=0; i < Spec->N_Surfs; ++i) {/* loop to read in surfaces */ /* now identify surface needed */ if (!(SO = SUMA_Load_Spec_Surf_with_Metrics(Spec, i, ps->sv[0], 0))) { SUMA_S_Err("Failed to load surface .\n"); exit(1); } if (SO->aSO) { /* otherwise, when you reset the number of FaceSets for example, and you still write in GIFTI, the old contents of aSO will prevail */ SO->aSO = SUMA_FreeAfniSurfaceObject(SO->aSO); } /* extract the patch */ ptch = SUMA_getPatch (NodePatch, N_NodePatch, SO->N_Node, SO->FaceSetList, SO->N_FaceSet, SO->MF, Opt->minhits, Opt->FixBowTie, (!i && !Opt->DoVol)); /* verbose only for first patch, and if no volume computation was required This is to keep the warnings to a minimum*/ if (!ptch) { SUMA_SL_Err("Failed to form patch."); exit(1); } if (LocalHead) SUMA_ShowPatch(ptch, NULL); /* Now create a surface with that patch */ if (Spec->N_Surfs > 1) { sprintf(ext, "_%c", 65+i); ppref = SUMA_append_string(Opt->out_prefix, ext); } else { ppref = SUMA_copy_string(Opt->out_prefix); } /* save the original type */ typetmp = SO->FileType; if (Opt->oType != SUMA_FT_NOT_SPECIFIED) SO->FileType = Opt->oType; SO_name = SUMA_Prefix2SurfaceName(ppref, NULL, NULL, SO->FileType, &exists); if (ppref) SUMA_free(ppref); ppref = NULL; /* save the original pointers to the facesets and their number */ FaceSetList = SO->FaceSetList; N_FaceSet = SO->N_FaceSet; NodeList = SO->NodeList; N_Node = SO->N_Node; /* replace with Patch */ SO->FaceSetList = ptch->FaceSetList; SO->N_FaceSet = ptch->N_FaceSet; if (Opt->Do_p2s) { if (LocalHead) fprintf (SUMA_STDERR, "%s: Changing patch to surface...\n", FuncName); SOnew = SUMA_Patch2Surf(SO->NodeList, SO->N_Node, SO->FaceSetList, SO->N_FaceSet, 3); if (!SOnew) { SUMA_S_Err("Failed to change patch to surface."); exit(1); } SO->FaceSetList = SOnew->FaceSetList; SO->N_FaceSet = SOnew->N_FaceSet; SO->N_Node = SOnew->N_Node; SO->NodeList = SOnew->NodeList; } if (SO->N_FaceSet <= 0) { SUMA_S_Warn("The patch is empty.\n" " Non existing surface not written to disk.\n"); } else { /* Is the gain wanted? */ if (Opt->coordgain) { SUMA_SL_Note("Applying coord gain to surface nodes!"); for (cnt=0; cnt < SO->NodeDim*SO->N_Node; ++cnt) SO->NodeList[cnt] *= Opt->coordgain; } if (Opt->flip) { if (Opt->verb > 1) SUMA_S_Note("Flipping triangles\n"); SUMA_FlipTriangles (SO->FaceSetList, SO->N_FaceSet); SUMA_RECOMPUTE_NORMALS(SO); } if (!SUMA_Save_Surface_Object (SO_name, SO, SO->FileType, SUMA_ASCII, NULL)) { fprintf (SUMA_STDERR, "Error %s: Failed to write surface object.\n", FuncName); exit (1); } } /* bring SO back to shape */ SO->FileType = typetmp; SO->FaceSetList = FaceSetList; FaceSetList = NULL; SO->N_FaceSet = N_FaceSet; N_FaceSet = -1; SO->NodeList = NodeList; NodeList = NULL; SO->N_Node = N_Node; N_Node = -1; if (SO_name) SUMA_free(SO_name); SO_name = NULL; if (ptch) SUMA_freePatch(ptch); ptch = NULL; if (SOnew) SUMA_Free_Surface_Object(SOnew); SOnew = NULL; /* get rid of old surface object */ } } SUMA_LH("clean up"); if (!SUMA_FreeSpecFields(Spec)) { SUMA_S_Err("Failed to free spec fields"); } SUMA_free(Spec); Spec = NULL; if (Opt->out_prefix) SUMA_free(Opt->out_prefix); Opt->out_prefix = NULL; if (Opt->out_volprefix) SUMA_free(Opt->out_volprefix); Opt->out_volprefix = NULL; if (Opt) SUMA_free(Opt); if (!SUMA_Free_Displayable_Object_Vect (SUMAg_DOv, SUMAg_N_DOv)) { SUMA_SL_Err("DO Cleanup Failed!"); } if (!SUMA_Free_CommonFields(SUMAg_CF)) { SUMA_SL_Err("SUMAg_CF Cleanup Failed!"); } SUMA_RETURN(0); }
int main( int argc , char *argv[] ) { THD_3dim_dataset *xset=NULL , *cset ; int nopt=1, datum=MRI_float, nvals, ii; MRI_IMAGE *ysim=NULL ; char *prefix = "Tcorr1D", *smethod="pearson"; char *xnam=NULL , *ynam=NULL ; byte *mask=NULL ; int mask_nx,mask_ny,mask_nz , nmask=0 ; int do_atanh = 0 ; /* 12 Jan 2018 */ /*----*/ AFNI_SETUP_OMP(0) ; /* 24 Jun 2013 */ if( argc < 2 || strcmp(argv[1],"-help") == 0 ){ printf("Usage: 3dTcorr1D [options] xset y1D\n" "Computes the correlation coefficient between each voxel time series\n" "in the input 3D+time dataset 'xset' and each column in the 1D time\n" "series file 'y1D', and stores the output values in a new dataset.\n" "\n" "OPTIONS:\n" " -pearson = Correlation is the normal Pearson (product moment)\n" " correlation coefficient [this is the default method].\n" " -spearman = Correlation is the Spearman (rank) correlation\n" " coefficient.\n" " -quadrant = Correlation is the quadrant correlation coefficient.\n" " -ktaub = Correlation is Kendall's tau_b coefficient.\n" " ++ For 'continuous' or finely-discretized data, tau_b and\n" " rank correlation are nearly equivalent (but not equal).\n" " -dot = Doesn't actually compute a correlation coefficient; just\n" " calculates the dot product between the y1D vector(s)\n" " and the dataset time series.\n" "\n" " -Fisher = Apply the 'Fisher' (inverse hyperbolic tangent) transformation\n" " to the results.\n" " ++ It does not make sense to use this with '-ktaub', but if\n" " you want to do it, the program will not stop you.\n" " ++ Cannot be used with '-dot'!\n" "\n" " -prefix p = Save output into dataset with prefix 'p'\n" " [default prefix is 'Tcorr1D'].\n" "\n" " -mask mmm = Only process voxels from 'xset' that are nonzero\n" " in the 3D mask dataset 'mmm'.\n" " ++ Other voxels in the output will be set to zero.\n" "\n" " -float = Save results in float format [the default format].\n" " -short = Save results in scaled short format [to save disk space].\n" " ++ Cannot be used with '-dot'!\n" "\n" "NOTES:\n" "* The output dataset is functional bucket type, with one sub-brick\n" " per column of the input y1D file.\n" "* No detrending, blurring, or other pre-processing options are available;\n" " if you want these things, see 3dDetrend or 3dTproject or 3dcalc.\n" " [In other words, this program presumes you know what you are doing!]\n" "* Also see 3dTcorrelate to do voxel-by-voxel correlation of TWO\n" " 3D+time datasets' time series, with similar options.\n" "* You can extract the time series from a single voxel with given\n" " spatial indexes using 3dmaskave, and then run it with 3dTcorr1D:\n" " 3dmaskave -quiet -ibox 40 30 20 epi_r1+orig > r1_40_30_20.1D\n" " 3dTcorr1D -pearson -Fisher -prefix c_40_30_20 epi_r1+orig r1_40_30_20.1D\n" "* http://en.wikipedia.org/wiki/Correlation\n" "* http://en.wikipedia.org/wiki/Pearson_product-moment_correlation_coefficient\n" "* http://en.wikipedia.org/wiki/Spearman%%27s_rank_correlation_coefficient\n" "* http://en.wikipedia.org/wiki/Kendall_tau_rank_correlation_coefficient\n" "\n" "-- RWCox - Apr 2010\n" " - Jun 2010: Multiple y1D columns; OpenMP; -short; -mask.\n" ) ; PRINT_AFNI_OMP_USAGE("3dTcorr1D",NULL) ; PRINT_COMPILE_DATE ; exit(0) ; } mainENTRY("3dTcorr1D main"); machdep(); AFNI_logger("3dTcorr1D",argc,argv); PRINT_VERSION("3dTcorr1D") ; THD_check_AFNI_version("3dTcorr1D") ; /*-- option processing --*/ while( nopt < argc && argv[nopt][0] == '-' ){ if( strcmp(argv[nopt],"-mask") == 0 ){ /* 28 Jun 2010 */ THD_3dim_dataset *mset ; if( ++nopt >= argc ) ERROR_exit("Need argument after '-mask'") ; if( mask != NULL ) 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 ) ; INFO_message("Number of voxels in mask = %d",nmask) ; if( nmask < 2 ) ERROR_exit("Mask is too small to process") ; nopt++ ; continue ; } if( strcasecmp(argv[nopt],"-float") == 0 ){ /* 27 Jun 2010 */ datum = MRI_float ; nopt++ ; continue ; } if( strcasecmp(argv[nopt],"-short") == 0 ){ datum = MRI_short ; nopt++ ; continue ; } if( strcasecmp(argv[nopt],"-pearson") == 0 ){ smethod = "pearson" ; nopt++ ; continue ; } if( strcasecmp(argv[nopt],"-dot") == 0 ){ smethod = "dot" ; nopt++ ; continue ; } if( strcasecmp(argv[nopt],"-spearman") == 0 || strcasecmp(argv[nopt],"-rank") == 0 ){ smethod = "spearman" ; nopt++ ; continue ; } if( strcasecmp(argv[nopt],"-quadrant") == 0 ){ smethod = "quadrant" ; nopt++ ; continue ; } if( strcasecmp(argv[nopt],"-ktaub") == 0 || strcasecmp(argv[nopt],"-taub") == 0 ){ smethod = "ktaub" ; nopt++ ; continue ; } if( strcasecmp(argv[nopt],"-fisher") == 0 ){ /* 12 Jan 2018 */ do_atanh = 1 ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-prefix") == 0 ){ prefix = argv[++nopt] ; if( !THD_filename_ok(prefix) ) ERROR_exit("Illegal value after -prefix!") ; nopt++ ; continue ; } ERROR_exit("Unknown option: %s",argv[nopt]) ; } /*------------ open datasets, check for legality ------------*/ if( nopt+1 >= argc ) ERROR_exit("Need 2 non-option arguments on command line!?") ; /* despite what the help says, if the 1D file is first, that's OK */ if( STRING_HAS_SUFFIX(argv[nopt],"1D") ){ ININFO_message("reading 1D file %s",argv[nopt]) ; ysim = mri_read_1D( argv[nopt] ) ; ynam = argv[nopt] ; if( ysim == NULL ) ERROR_exit("Can't read 1D file %s",argv[nopt]) ; } else { ININFO_message("reading dataset file %s",argv[nopt]) ; xset = THD_open_dataset( argv[nopt] ) ; xnam = argv[nopt] ; if( xset == NULL ) ERROR_exit("Can't open dataset %s",argv[nopt]) ; } /* read whatever type of file (3D or 1D) we don't already have */ nopt++ ; if( xset != NULL ){ ININFO_message("reading 1D file %s",argv[nopt]) ; ysim = mri_read_1D( argv[nopt] ) ; ynam = argv[nopt] ; if( ysim == NULL ) ERROR_exit("Can't read 1D file %s",argv[nopt]) ; } else { ININFO_message("reading dataset file %s",argv[nopt]) ; xset = THD_open_dataset( argv[nopt] ) ; xnam = argv[nopt] ; if( xset == NULL ) ERROR_exit("Can't open dataset %s",argv[nopt]) ; } nvals = DSET_NVALS(xset) ; /* number of time points */ ii = (strcmp(smethod,"dot")==0) ? 2 : 3 ; if( nvals < ii ) ERROR_exit("Input dataset %s length is less than ii?!",xnam,ii) ; if( ysim->nx < nvals ) ERROR_exit("1D file %s has %d time points, but dataset has %d values", ynam,ysim->nx,nvals) ; else if( ysim->nx > nvals ) WARNING_message("1D file %s has %d time points, dataset has %d", ynam,ysim->nx,nvals) ; if( mri_allzero(ysim) ) ERROR_exit("1D file %s is all zero!",ynam) ; if( ysim->ny > 1 ) INFO_message("1D file %s has %d columns: correlating with ALL of them!", ynam,ysim->ny) ; if( strcmp(smethod,"dot") == 0 && do_atanh ){ WARNING_message("'-dot' turns off '-Fisher'") ; do_atanh = 0 ; } if( strcmp(smethod,"dot") == 0 && datum == MRI_short ){ WARNING_message("'-dot' turns off '-short'") ; datum = MRI_float ; } cset = THD_Tcorr1D( xset, mask, nmask, ysim, smethod, prefix, (datum==MRI_short) , do_atanh ); tross_Make_History( "3dTcorr1D" , argc,argv , cset ) ; DSET_unload(xset) ; /* no longer needful */ /* finito */ DSET_write(cset) ; INFO_message("Wrote dataset: %s\n",DSET_BRIKNAME(cset)) ; exit(0) ; }
int main( int argc , char * argv[] ) { int iarg , ii , ny , ignore=0 , use=0 , install=0 ; char * tsfile , * cpt ; char dname[THD_MAX_NAME] , subv[THD_MAX_NAME] ; MRI_IMAGE * flim ; float * far ; XtAppContext app ; Widget shell ; int cxx=0 , cyy=1 , cxsig=2 , cysig=3 , crho=4 ; /*-- help? --*/ if( argc < 2 || strcmp(argv[1],"-help") == 0 ){ printf("Usage: 1dsigplot [options] infile\n" "Scatterplots a 5 column *.1D file to the screen.\n" "The columns of the input file must be\n" " x y sigma_x sigma_y rho_xy\n" "\n" "Options:\n" " -install = Install a new X11 colormap.\n" " -ignore nn = Skip first 'nn' rows in the input file\n" " [default = 0]\n" " -use mm = Plot 'mm' points [default = all of them]\n" " -xlabel aa = Put string 'aa' below the x-axis\n" " [default = no axis label]\n" " -ylabel aa = Put string 'aa' to the left of the y-axis\n" " [default = no axis label]\n" " -pell p = Set CDF probability contour level for ellipses.\n" " -col abcde = 'abcde' is a permutation of '01234', and\n" " specifies the column order for the data,\n" " where a=column index for x\n" " b=column index for y\n" " c=column index for sigma_x\n" " d=column index for sigma_y\n" " e=column index for rho_xy\n" " [default = 01234]\n" "\n" " -xrange x1 x2 = Range of x-axis\n" " -yrange y1 y2 = Range of y-axis\n" ) ; PRINT_COMPILE_DATE ; exit(0) ; } machdep() ; /* open X11 */ shell = XtVaAppInitialize( &app , "AFNI" , NULL , 0 , &argc , argv , NULL , NULL ) ; if( shell == NULL ){ fprintf(stderr,"** Cannot initialize X11!\n") ; exit(1) ; } cpt = my_getenv("TMPDIR") ; /* just for fun */ /*-- scan arguments that X11 didn't eat --*/ iarg = 1 ; while( iarg < argc && argv[iarg][0] == '-' ){ if( strcmp(argv[iarg],"-xrange") == 0 ){ xlo = strtod(argv[++iarg],NULL) ; xhi = strtod(argv[++iarg],NULL) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-yrange") == 0 ){ ylo = strtod(argv[++iarg],NULL) ; yhi = strtod(argv[++iarg],NULL) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-pell") == 0 ){ pell = strtod(argv[++iarg],NULL) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-col") == 0 ){ int ierr=0 ; iarg++ ; cxx = argv[iarg][0] - '0' ; if( cxx < 0 || cxx > 4 ) ierr++ ; cyy = argv[iarg][1] - '0' ; if( cyy < 0 || cyy > 4 ) ierr++ ; cxsig = argv[iarg][2] - '0' ; if( cxsig < 0 || cxsig > 4 ) ierr++ ; cysig = argv[iarg][3] - '0' ; if( cysig < 0 || cysig > 4 ) ierr++ ; crho = argv[iarg][4] - '0' ; if( crho < 0 || crho > 4 ) ierr++ ; if( ierr || cxx+cyy+cxsig+cysig+crho != 10 ){ fprintf(stderr,"*** Illegal argument after -ord!\n");exit(1); } iarg++ ; continue ; } if( strcmp(argv[iarg],"-install") == 0 ){ install++ ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-") == 0 ){ /* skip */ iarg++ ; continue ; } if( strcmp(argv[iarg],"-title") == 0 ){ title = argv[++iarg] ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-xlabel") == 0 ){ xlabel = argv[++iarg] ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-ylabel") == 0 ){ ylabel = argv[++iarg] ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-ignore") == 0 ){ ignore = strtod( argv[++iarg] , NULL ) ; if( ignore < 0 ){fprintf(stderr,"** Illegal -ignore value!\n");exit(1);} iarg++ ; continue ; } if( strcmp(argv[iarg],"-use") == 0 ){ use = strtod( argv[++iarg] , NULL ) ; if( use < 2 ){fprintf(stderr,"** Illegal -use value!\n");exit(1);} iarg++ ; continue ; } fprintf(stderr,"** Unknown option: %s\n",argv[iarg]) ; exit(1) ; } if( iarg >= argc ){ fprintf(stderr,"** No tsfile on command line!\n") ; exit(1) ; } dc = MCW_new_DC( shell , 16 , DEFAULT_NCOLOVR , INIT_colovr , INIT_labovr , 1.0 , install ) ; flim = mri_read_1D( argv[iarg] ) ; if( flim == NULL ){ fprintf(stderr,"** Can't read input file %s\n",argv[iarg]) ; exit(1); } if( flim->ny != 5 ){ fprintf(stderr,"** Input file doesn't have exactly 5 columns!\n") ; exit(1) ; } far = MRI_FLOAT_PTR(flim) ; nx = flim->nx ; xx = far + cxx *nx ; yy = far + cyy *nx ; xsig = far + cxsig*nx ; ysig = far + cysig*nx ; xycor = far + crho *nx ; nx = nx - ignore ; /* cut off the ignored points */ if( use > 1 && nx > use ) nx = use ; /* start X11 */ (void) XtAppAddTimeOut( app , 123 , startup_timeout_CB , NULL ) ; XtAppMainLoop(app) ; exit(0) ; }
int main(int argc, char * argv[]) { char cphase1d[256] = "\0", rphase1d[256] = "\0"; char new_prefix[THD_MAX_PREFIX] = TRIC_O_DEF_NEWPREFIX; MCW_idcode * idc ; THD_3dim_dataset * dset , * new_dset; double * avg = NULL; double * ca , * cb, * ra, * rb; MRI_IMAGE * card = NULL, * resp = NULL; MRI_IMAGE * cardphase = NULL, * respphase = NULL; float threshold = TRIC_C_DEF_THRESHOLD; int ignore = TRIC_I_DEF_IGNORE; int M = TRIC_M_DEF_ORDER; int winsize = TRIC_R_DEF_WINSIZE; float tr; int ival, nvals; FILE * fp; float * cpdata, * rpdata; int argi = 1; /*-------------------------------------------------------------*/ /*----- Check arguments to see if they are reasonable-ish -----*/ if (argc < 2 || strcmp(argv[1], "-help") == 0) { TRIC_printhelp(); exit(-1); } mainENTRY("3dretroicor main"); PRINT_VERSION("3dretroicor") ; machdep(); AFNI_logger("3dretroicor", argc, argv); /* Iterate over commandline args */ while (argi < argc && argv[argi][0] == '-') { /*-- ignore --*/ if (strcmp(argv[argi], "-ignore") == 0) { if (argi + 1 >= argc) { fprintf(stderr, "*** -ignore needs an argument!\n"); exit(1); } argi += 1; ignore = atoi(argv[argi]); if (ignore < 0) { fprintf(stderr, "*** %i is not a valid number to ignore!\n", ignore); exit(1); } argi += 1; continue; /* Skip the rest of the loop and go to the next arg */ } /*-- prefix --*/ if (strcmp(argv[argi], "-prefix") == 0) { if (argi + 1 >= argc) { fprintf(stderr, "*** -prefix needs an argument!\n"); exit(1); } argi += 1; MCW_strncpy(new_prefix, argv[argi], THD_MAX_PREFIX); if (! THD_filename_ok(new_prefix)) { fprintf(stderr, "*** %s is not a valid prefix!\n", new_prefix); exit(1); } argi += 1; continue; /* Skip the rest of the loop and go to the next arg */ } /*-- card --*/ if (strcmp(argv[argi], "-card") == 0) { if (argi + 1 >= argc) { fprintf(stderr, "*** -card needs an argument!\n"); exit(1); } argi += 1; card = mri_read_1D(argv[argi]); if (card == NULL) { fprintf(stderr, "*** Can't read -card %s\n", argv[argi]); exit(1); } argi += 1; continue; /* Skip the rest of the loop and go to the next arg */ } /*-- cardphase --*/ if (strcmp(argv[argi], "-cardphase") == 0) { if (argi + 1 >= argc) { fprintf(stderr, "*** -cardphase needs an argument!\n"); exit(1); } argi += 1; MCW_strncpy(cphase1d, argv[argi], 256); if (! THD_filename_ok(cphase1d)) { fprintf(stderr, "*** Bad name argument for -cardphase\n"); exit(1); } argi += 1; continue; /* Skip the rest of the loop and go to the next arg */ } /*-- threshold --*/ if (strcmp(argv[argi], "-threshold") == 0) { if (argi + 1 >= argc) { fprintf(stderr, "*** -threshold needs an argument!\n"); exit(1); } argi += 1; threshold = atof(argv[argi]); argi += 1; continue; /* Skip the rest of the loop and go to the next arg */ } /*-- resp --*/ if (strcmp(argv[argi], "-resp") == 0) { if (argi + 1 >= argc) { fprintf(stderr, "*** -resp needs an argument!\n"); exit(1); } argi += 1; resp = mri_read_1D(argv[argi]); if (resp == NULL) { fprintf(stderr, "*** Can't read -resp %s\n", argv[argi]); exit(1); } argi += 1; continue; /* Skip the rest of the loop and go to the next arg */ } /*-- respphase --*/ if (strcmp(argv[argi], "-respphase") == 0) { if (argi + 1 >= argc) { fprintf(stderr, "*** -respphase needs an argument!\n"); exit(1); } argi += 1; MCW_strncpy(rphase1d, argv[argi], 256); if (! THD_filename_ok(rphase1d)) { fprintf(stderr, "*** Bad name argument for -respphase\n"); exit(1); } argi += 1; continue; /* Skip the rest of the loop and go to the next arg */ } /*-- window --*/ /*-- removed winsize ui --*/ #if 0 if (strcmp(argv[argi], "-window") == 0) { if (argi + 1 >= argc) { fprintf(stderr, "*** -window needs an argument!\n"); exit(1); } argi += 1; winsize = atoi(argv[argi]); argi += 1; continue; /* Skip the rest of the loop and go to the next arg */ } #endif /*-- removed winsize ui --*/ /*-- order --*/ if (strcmp(argv[argi], "-order") == 0) { if (argi + 1 >= argc) { fprintf(stderr, "*** -order needs an argument!\n"); exit(1); } argi += 1; M = atoi(argv[argi]); if (M < 1) { fprintf(stderr, "*** %i is not a valid order number\n", M); exit(1); } argi += 1; continue; /* Skip the rest of the loop and go to the next arg */ } } /* End iterating over commandline args */ /* Check that at least one of Cardiac and Resp were selected */ if (card == NULL && resp == NULL) { fprintf(stderr, "*** Need at least one correction (-card, -resp)\n"); exit(1); } /*-- Open and check input dataset --*/ if (argi >= argc) { fprintf(stderr, "*** No input dataset!?\n"); exit(1); } else if (argi < argc - 1) { fprintf(stderr, "*** Too many input datasets?!\n"); exit(1); } dset = THD_open_dataset(argv[argi]); if (! ISVALID_3DIM_DATASET(dset)) { fprintf(stderr, "*** Can't open dataset %s\n", argv[argi]); exit(1); } if (DSET_NUM_TIMES(dset) < 2) { fprintf(stderr, "*** Input dataset is not 3D+time!\n"); exit(1); } /*----------------------------------------------------------*/ /*---------- At this point, the inputs are OK-ish ----------*/ /*-- copy the image data for editing in place --*/ new_dset = EDIT_full_copy( dset , new_prefix ); if( new_dset == NULL ) { fprintf(stderr, "*** Error copying dataset\n"); exit(1); } tross_Copy_History(dset, new_dset); /* Copy and add to new_dset history */ tross_Make_History("3dretroicor", argc, argv, new_dset); DSET_unload( dset ) ; /* We won't need the old dataset anymore */ /*-- calculate cardiac correction coefficients if requested --*/ if (card != NULL) { /*-- convert cardiac waveform to phase --*/ cardphase = RIC_ToCardiacPhase(card, threshold) ; if (cardphase == NULL) { THD_delete_3dim_dataset( new_dset , False ) ; fprintf(stderr, "*** Error transforming cardiac data\n"); exit(2); } /*-- calculate dataset voxel means --*/ avg = RIC_CalcVoxelMeans(new_dset, ignore); if (avg == NULL) { THD_delete_3dim_dataset( new_dset , False ) ; mri_free(cardphase); fprintf(stderr, "*** Error calculating dataset voxel means\n"); exit(2); } /*-- calculate coefficients for each voxel --*/ if (RIC_CalcCoeffAB(new_dset, cardphase, avg, &ca, &cb, M, ignore) != 0) { THD_delete_3dim_dataset( new_dset , False ) ; mri_free(cardphase); fprintf(stderr, "*** Error calculating cardiac a b coefficients\n"); exit(2); } } /*-- calculate respiratory correction coefficients if requested --*/ if (resp != NULL) { /*-- Set winsize to 1/2 sampling rate of resp in Hz --*/ tr = new_dset->taxis->ttdel; switch (new_dset->taxis->units_type) { case UNITS_MSEC_TYPE: tr /= 1000; break; case UNITS_SEC_TYPE: break; case UNITS_HZ_TYPE: tr = 1 / tr; break; default: THD_delete_3dim_dataset( new_dset , False ) ; fprintf(stderr, "*** Bad time units type in dataset\n"); exit(2); } winsize = ceil(resp->nx / (tr * DSET_NVALS(new_dset)) / 2.0); /*-- convert respiratory waveform to phase --*/ respphase = RIC_ToRespPhase(resp, winsize) ; if (respphase == NULL) { THD_delete_3dim_dataset( new_dset , False ) ; fprintf(stderr, "*** Error transforming resp data\n"); exit(2); } /*-- calculate dataset voxel means if not already done --*/ if (avg == NULL) { avg = RIC_CalcVoxelMeans(new_dset, ignore); if (avg == NULL) { THD_delete_3dim_dataset( new_dset , False ) ; mri_free(respphase); fprintf(stderr, "*** Error calculating dataset voxel means2\n"); exit(2); } } /*-- calculate coefficients for each voxel --*/ if (RIC_CalcCoeffAB(new_dset, respphase, avg, &ra, &rb, M, ignore) != 0) { THD_delete_3dim_dataset( new_dset , False ) ; mri_free(respphase); fprintf(stderr, "*** Error calculating resp a, b coefficients\n"); exit(2); } } /*-- do cardiac correction if requested --*/ if (card != NULL) { /*-- correct the image data --*/ if (RIC_CorrectDataset(new_dset, cardphase, ca, cb, M, ignore) != 0) { THD_delete_3dim_dataset( new_dset , False ) ; mri_free(cardphase); free(ca); free(cb); fprintf(stderr, "*** Error applying cardiac correction\n"); exit(3); } /*-- if requested, write phase data to file and pass to AFNI --*/ if ( THD_filename_ok(cphase1d) ) { /* Write the file */ fp = fopen(cphase1d, "w"); nvals = cardphase->nx; cpdata = MRI_FLOAT_PTR(cardphase); for (ival = 0; ival < nvals; ival += 1) { fprintf(fp, "%f\n", cpdata[ival]); } fclose(fp); } mri_free(cardphase); free(ca); free(cb); free(avg); avg = NULL; } /*-- do resp correction if requested --*/ if (resp != NULL) { /*-- correct the image data --*/ if (RIC_CorrectDataset(new_dset, respphase, ra, rb, M, ignore) != 0) { THD_delete_3dim_dataset( new_dset , False ) ; mri_free(respphase); free(ra); free(rb); fprintf(stderr, "*** Error applying resp correction\n"); exit(3); } /*-- if requested, write phase data to file and pass to AFNI --*/ if ( THD_filename_ok(rphase1d) ) { /* Write the file */ fp = fopen(rphase1d, "w"); nvals = respphase->nx; rpdata = MRI_FLOAT_PTR(respphase); for (ival = 0; ival < nvals; ival += 1) { fprintf(fp, "%f\n", rpdata[ival]); } fclose(fp); } mri_free(respphase); free(ra); free(rb); if (avg != NULL) free(avg); } /*-- write out new dataset --*/ if (DSET_write(new_dset) != False) { fprintf(stderr,"++ output dataset: %s\n",DSET_BRIKNAME(new_dset)) ; exit(0) ; } else { fprintf(stderr, "** 3dretroicor: Failed to write output!\n" ) ; exit(1) ; } /*-- done successfully!!! --*/ exit(0); }
int main( int argc , char * argv[] ) { THD_dfvec3 *xx , *yy , dv ; int nvec=0 , ii,jj, iarg ; THD_dvecmat rt , rtinv ; THD_dmat33 pp,ppt , rr ; THD_dfvec3 tt ; THD_3dim_dataset *mset=NULL , *dset=NULL ; double *ww=NULL ; int nww=0 ; int keeptags=1 , wtval=0 , verb=0 , dummy=0 ; char * prefix = "tagalign" , *mfile=NULL ; float *fvol , cbot,ctop , dsum ; int nval , nvox , clipit , ival, RMETH=MRI_CUBIC; float matar[12] ; int use_3dWarp=1 , matrix_type=ROTATION ; mainENTRY("3dTagalign main"); /*--- help? ---*/ /*- scan args -*/ iarg = 1 ; RMETH=MRI_CUBIC; while( iarg < argc && argv[iarg][0] == '-' ){ /*-----*/ if( strcmp(argv[iarg],"-h") == 0 || strcmp(argv[iarg],"-help") == 0){ /* 22 Apr 2003 */ usage_3dTagalign(strlen(argv[iarg]) > 3 ? 2:1); exit(0); } /*-----*/ if( strcmp(argv[iarg],"-NN") == 0 ){ RMETH = MRI_NN ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-linear") == 0 ){ RMETH = MRI_LINEAR ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-cubic") == 0 ){ RMETH = MRI_CUBIC ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-quintic") == 0 ){ RMETH = MRI_QUINTIC ; iarg++ ; continue ; } /*-----*/ if( strcmp(argv[iarg],"-rotate") == 0 ){ /* 22 Apr 2003 */ matrix_type = ROTATION ; use_3dWarp = 1 ; iarg++ ; continue ; } /*-----*/ if( strcmp(argv[iarg],"-affine") == 0 ){ /* 21 Apr 2003 */ matrix_type = AFFINE ; use_3dWarp = 1 ; iarg++ ; continue ; } /*-----*/ if( strcmp(argv[iarg],"-rotscl") == 0 ){ /* 22 Apr 2003 */ matrix_type = ROTSCL ; use_3dWarp = 1 ; iarg++ ; continue ; } #if 0 /*-----*/ if( strcmp(argv[iarg],"-3dWarp") == 0 ){ /* 21 Apr 2003 */ use_3dWarp = 1 ; iarg++ ; continue ; } #endif /*-----*/ if( strcmp(argv[iarg],"-master") == 0 ){ if( mset != NULL ) ERREX("Can only have one -master option") ; if( ++iarg >= argc ) ERREX("Need an argument after -master") ; mset = THD_open_dataset( argv[iarg] ) ; if( mset == NULL ) ERREX("Can't open -master dataset") ; if( mset->tagset == NULL ) ERREX("No tags in -master dataset") ; if( TAGLIST_COUNT(mset->tagset) < 3 ) ERREX("Not enough tags in -master dataset") ; for( nvec=ii=0 ; ii < TAGLIST_COUNT(mset->tagset) ; ii++ ) if( TAG_SET(TAGLIST_SUBTAG(mset->tagset,ii)) ) nvec++ ; if( nvec < 3 ) ERREX("Not enough tags set in -master dataset") ; if( nvec < TAGLIST_COUNT(mset->tagset) ) fprintf(stderr,"++ WARNING: not all tags are set in -master dataset\n") ; if( verb ) fprintf(stderr,"++ Found %d tags in -master dataset\n",nvec) ; iarg++ ; continue ; } #if 0 /*-----*/ if( strcmp(argv[iarg],"-wtval") == 0 ){ if( ww != NULL ) ERREX("Can't have -wtval after -wt1D") ; wtval++ ; iarg++ ; continue ; } /*-----*/ if( strcmp(argv[iarg],"-wt1D") == 0 ){ MRI_IMAGE * wtim ; float * wtar ; if( wtval ) ERREX("Can't have -wt1D after -wtval") ; if( ww != NULL ) ERREX("Can't have two -wt1D options!") ; if( ++iarg >= argc ) ERREX("Need an argument after -wt1D") ; wtim = mri_read_1D( argv[iarg] ) ; if( wtim == NULL ) ERREX("Can't read -wtim file") ; if( wtim->ny > 1 ) ERREX("-wtim file has more than one columm") ; wtar = MRI_FLOAT_PTR(wtim) ; ww = (double *) malloc(sizeof(double)*wtim->nx) ; nww = wtim->nx ; for( ii=0 ; ii < nww ; ii++ ){ ww[ii] = (double) wtar[ii] ; if( ww[ii] < 0.0 ) ERREX("Negative value found in -wt1D file") ; } mri_free(wtim) ; iarg++ ; continue ; } #endif /*-----*/ if( strcmp(argv[iarg],"-nokeeptags") == 0 ){ keeptags = 0 ; iarg++ ; continue ; } /*-----*/ if( strncmp(argv[iarg],"-verb",5) == 0 ){ verb++ ; iarg++ ; continue ; } /*-----*/ if( strcmp(argv[iarg],"-dummy") == 0 ){ dummy++ ; iarg++ ; continue ; } /*-----*/ if( strcmp(argv[iarg],"-prefix") == 0 ){ if( ++iarg >= argc ) ERREX("Need an argument after -prefix") ; prefix = argv[iarg] ; if( !THD_filename_ok(prefix) ) ERREX("-prefix string is illegal") ; iarg++ ; continue ; } /*-----*/ if( strcmp(argv[iarg],"-matvec") == 0 ){ if( ++iarg >= argc ) ERREX("Need an argument after -matvec") ; mfile = argv[iarg] ; if( !THD_filename_ok(mfile) ) ERREX("-matvec string is illegal") ; iarg++ ; continue ; } /*-----*/ fprintf(stderr,"** Unknown option: %s\n",argv[iarg]) ; suggest_best_prog_option(argv[0], argv[iarg]); exit(1) ; } /* end of scanning command line for options */ if( argc < 2 ){ ERROR_message("Too few options"); usage_3dTagalign(0); exit(1) ; } if( mset == NULL ) ERREX("No -master option found on command line") ; #if 0 if( ww != NULL && nww < nvec ) ERREX("Not enough weights found in -wt1D file") ; /*-- if -wtval, setup weights from master tag values --*/ if( wtval ){ ww = (double *) malloc(sizeof(double)*nvec) ; nww = nvec ; for( ii=jj=0 ; ii < TAGLIST_COUNT(mset->tagset) ; ii++ ){ if( TAG_SET(TAGLIST_SUBTAG(mset->tagset,ii)) ){ ww[jj] = (double) TAG_VAL(TAGLIST_SUBTAG(mset->tagset,ii)) ; if( ww[jj] < 0.0 ) ERREX("Negative value found in -master tag values") ; jj++ ; } } } #endif /*-- read input dataset (to match to master dataset) --*/ if( iarg >= argc ) ERREX("No input dataset?") ; dset = THD_open_dataset( argv[iarg] ) ; if( dset == NULL ) ERREX("Can't open input dataset") ; if( dset->tagset == NULL ) ERREX("No tags in input dataset") ; if( TAGLIST_COUNT(dset->tagset) != TAGLIST_COUNT(mset->tagset) ) ERREX("Tag counts don't match in -master and input") ; /* check if set tags match exactly */ for( ii=0 ; ii < TAGLIST_COUNT(mset->tagset) ; ii++ ){ if( TAG_SET(TAGLIST_SUBTAG(mset->tagset,ii)) != TAG_SET(TAGLIST_SUBTAG(dset->tagset,ii)) ) ERREX("Set tags don't match in -master and input") ; } /*-- load vector lists: xx=master, yy=input --*/ xx = (THD_dfvec3 *) malloc( sizeof(THD_dfvec3) * nvec ) ; yy = (THD_dfvec3 *) malloc( sizeof(THD_dfvec3) * nvec ) ; dsum = 0.0 ; for( ii=jj=0 ; ii < nvec ; ii++ ){ if( TAG_SET(TAGLIST_SUBTAG(mset->tagset,ii)) ){ LOAD_DFVEC3( xx[jj] , /* N.B.: */ TAG_X( TAGLIST_SUBTAG(mset->tagset,ii) ) , /* these are */ TAG_Y( TAGLIST_SUBTAG(mset->tagset,ii) ) , /* in Dicom */ TAG_Z( TAGLIST_SUBTAG(mset->tagset,ii) ) ) ; /* order now */ LOAD_DFVEC3( yy[jj] , TAG_X( TAGLIST_SUBTAG(dset->tagset,ii) ) , TAG_Y( TAGLIST_SUBTAG(dset->tagset,ii) ) , TAG_Z( TAGLIST_SUBTAG(dset->tagset,ii) ) ) ; dv = SUB_DFVEC3( xx[jj] , yy[jj] ) ; dsum += dv.xyz[0]*dv.xyz[0] + dv.xyz[1]*dv.xyz[1] + dv.xyz[2]*dv.xyz[2] ; jj++ ; } } dsum = sqrt(dsum/nvec) ; fprintf(stderr,"++ RMS distance between tags before = %.2f mm\n" , dsum ) ; /*-- compute best transformation from mset to dset coords --*/ switch( matrix_type ){ default: case ROTATION: rt = DLSQ_rot_trans( nvec , yy , xx , ww ) ; /* in thd_rot3d.c */ break ; case AFFINE: rt = DLSQ_affine ( nvec , yy , xx ) ; /* 21 Apr 2003 */ break ; case ROTSCL: rt = DLSQ_rotscl ( nvec , yy , xx , (DSET_NZ(dset)==1) ? 2 : 3 ) ; break ; } rtinv = INV_DVECMAT(rt) ; /*-- check for floating point legality --*/ nval = 0 ; for( ii=0 ; ii < 3 ; ii++ ){ dsum = rt.vv.xyz[ii] ; nval += thd_floatscan(1,&dsum) ; for( jj=0 ; jj < 3 ; jj++ ){ dsum = rt.mm.mat[ii][jj] ; nval += thd_floatscan(1,&dsum) ; } } if( nval > 0 ){ fprintf(stderr,"** Floating point errors during calculation\n" "** of transform matrix and translation vector\n" ) ; exit(1) ; } /*-- check for rotation matrix legality --*/ dsum = DMAT_DET(rt.mm) ; if( dsum == 0.0 || (matrix_type == ROTATION && fabs(dsum-1.0) > 0.01) ){ fprintf(stderr,"** Invalid transform matrix computed: tags dependent?\n" "** computed [matrix] and [vector] follow:\n" ) ; for( ii=0 ; ii < 3 ; ii++ ) fprintf(stderr," [ %10.5f %10.5f %10.5f ] [ %10.5f ] \n", rt.mm.mat[ii][0],rt.mm.mat[ii][1],rt.mm.mat[ii][2],rt.vv.xyz[ii] ); exit(1) ; } /*-- print summary --*/ if( verb ){ fprintf(stderr,"++ Matrix & Vector [Dicom: x=R-L; y=A-P; z=I-S]\n") ; for( ii=0 ; ii < 3 ; ii++ ) fprintf(stderr," %10.5f %10.5f %10.5f %10.5f\n", rt.mm.mat[ii][0],rt.mm.mat[ii][1],rt.mm.mat[ii][2],rt.vv.xyz[ii] ); } if( matrix_type == ROTATION || matrix_type == ROTSCL ){ double theta, costheta , dist , fac=1.0 ; if( matrix_type == ROTSCL ){ fac = DMAT_DET(rt.mm); fac = fabs(fac); if( DSET_NZ(dset) == 1 ) fac = sqrt(fac) ; else fac = cbrt(fac) ; } costheta = 0.5 * sqrt(1.0 + DMAT_TRACE(rt.mm)/fac ) ; theta = 2.0 * acos(costheta) * 180/3.14159265 ; dist = SIZE_DFVEC3(rt.vv) ; fprintf(stderr,"++ Total rotation=%.2f degrees; translation=%.2f mm; scaling=%.2f\n", theta,dist,fac) ; } if( mfile ){ FILE * mp ; if( THD_is_file(mfile) ) fprintf(stderr,"++ Warning: -matvec will overwrite file %s\n",mfile) ; mp = fopen(mfile,"w") ; if( mp == NULL ){ fprintf(stderr,"** Can't write to -matvec %s\n",mfile) ; } else { for( ii=0 ; ii < 3 ; ii++ ) fprintf(mp," %10.5f %10.5f %10.5f %10.5f\n", rt.mm.mat[ii][0],rt.mm.mat[ii][1],rt.mm.mat[ii][2],rt.vv.xyz[ii] ); fclose(mp) ; if( verb ) fprintf(stderr,"++ Wrote matrix+vector to %s\n",mfile) ; } } if( dummy ){ fprintf(stderr,"++ This was a -dummy run: no output dataset\n") ; exit(0) ; } /*-- 21 Apr 2003: transformation can be done the old way (a la 3drotate), or the new way (a la 3dWarp). --*/ #if 0 if( !use_3dWarp ){ /**** the old way ****/ /*-- now must scramble the rotation matrix and translation vector from Dicom coordinate order to dataset brick order --*/ pp = DBLE_mat_to_dicomm( dset ) ; ppt = TRANSPOSE_DMAT(pp) ; rr = DMAT_MUL(ppt,rt.mm) ; rr = DMAT_MUL(rr,pp) ; tt = DMATVEC(ppt,rt.vv) ; /*-- now create the output dataset by screwing with the input dataset (this code is adapted from 3drotate.c) --*/ DSET_mallocize(dset) ; DSET_load( dset ) ; CHECK_LOAD_ERROR(dset) ; dset->idcode = MCW_new_idcode() ; dset->dblk->diskptr->storage_mode = STORAGE_BY_BRICK ; /* 14 Jan 2004 */ EDIT_dset_items( dset , ADN_prefix , prefix , ADN_label1 , prefix , ADN_none ) ; if( !THD_ok_overwrite() && (THD_deathcon() && THD_is_file(dset->dblk->diskptr->header_name) )){ fprintf(stderr, "** Output file %s already exists -- cannot continue!\n", dset->dblk->diskptr->header_name ) ; exit(1) ; } tross_Make_History( "3dTagalign" , argc,argv , dset ) ; /*-- if desired, keep old tagset --*/ if( keeptags ){ THD_dfvec3 rv ; dsum = 0.0 ; for( jj=ii=0 ; ii < TAGLIST_COUNT(dset->tagset) ; ii++ ){ if( TAG_SET(TAGLIST_SUBTAG(dset->tagset,ii)) ){ rv = DMATVEC( rt.mm , yy[jj] ) ; /* operating on */ rv = ADD_DFVEC3( rt.vv , rv ) ; /* Dicom order */ dv = SUB_DFVEC3( xx[jj] , rv ) ; dsum += dv.xyz[0]*dv.xyz[0] + dv.xyz[1]*dv.xyz[1] + dv.xyz[2]*dv.xyz[2] ; UNLOAD_DFVEC3( rv , TAG_X( TAGLIST_SUBTAG(dset->tagset,ii) ) , TAG_Y( TAGLIST_SUBTAG(dset->tagset,ii) ) , TAG_Z( TAGLIST_SUBTAG(dset->tagset,ii) ) ) ; jj++ ; } } dsum = sqrt(dsum/nvec) ; fprintf(stderr,"++ RMS distance between tags after = %.2f mm\n" , dsum ) ; } else { myXtFree(dset->tagset) ; /* send it to the dustbin */ } /*-- rotate sub-bricks --*/ if( verb ) fprintf(stderr,"++ computing output BRIK") ; nvox = DSET_NVOX(dset) ; nval = DSET_NVALS(dset) ; fvol = (float *) malloc( sizeof(float) * nvox ) ; THD_rota_method( MRI_HEPTIC ) ; clipit = 1 ; for( ival=0 ; ival < nval ; ival++ ){ /*- get sub-brick out of dataset -*/ EDIT_coerce_type( nvox , DSET_BRICK_TYPE(dset,ival),DSET_ARRAY(dset,ival) , MRI_float,fvol ) ; if( clipit ){ register int ii ; register float bb,tt ; bb = tt = fvol[0] ; for( ii=1 ; ii < nvox ; ii++ ){ if( fvol[ii] < bb ) bb = fvol[ii] ; else if( fvol[ii] > tt ) tt = fvol[ii] ; } cbot = bb ; ctop = tt ; } if( verb && nval < 5 ) fprintf(stderr,".") ; /*- rotate it -*/ THD_rota_vol_matvec( DSET_NX(dset) , DSET_NY(dset) , DSET_NZ(dset) , fabs(DSET_DX(dset)) , fabs(DSET_DY(dset)) , fabs(DSET_DZ(dset)) , fvol , rr , tt ) ; if( verb ) fprintf(stderr,".") ; if( clipit ){ register int ii ; register float bb,tt ; bb = cbot ; tt = ctop ; for( ii=0 ; ii < nvox ; ii++ ){ if( fvol[ii] < bb ) fvol[ii] = bb ; else if( fvol[ii] > tt ) fvol[ii] = tt ; } } if( verb && nval < 5 ) fprintf(stderr,".") ; /*- put it back into dataset -*/ EDIT_coerce_type( nvox, MRI_float,fvol , DSET_BRICK_TYPE(dset,ival),DSET_ARRAY(dset,ival) ); } /* end of loop over sub-brick index */ if( verb ) fprintf(stderr,":") ; /* save matrix+vector into dataset, too */ UNLOAD_DMAT(rt.mm,matar[0],matar[1],matar[2], matar[4],matar[5],matar[6], matar[8],matar[9],matar[10] ) ; UNLOAD_DFVEC3(rt.vv,matar[3],matar[7],matar[11]) ; THD_set_atr( dset->dblk, "TAGALIGN_MATVEC", ATR_FLOAT_TYPE, 12, matar ) ; /* write dataset to disk */ dset->dblk->master_nvals = 0 ; /* in case this was a mastered dataset */ DSET_write(dset) ; if( verb ) fprintf(stderr,"\n") ; } else #endif { /**** the new way: use 3dWarp type transformation ****/ THD_3dim_dataset *oset ; THD_vecmat tran ; #if 0 DFVEC3_TO_FVEC3( rt.vv , tran.vv ) ; DMAT_TO_MAT ( rt.mm , tran.mm ) ; #else DFVEC3_TO_FVEC3( rtinv.vv , tran.vv ) ; DMAT_TO_MAT ( rtinv.mm , tran.mm ) ; #endif mri_warp3D_method( RMETH ) ; oset = THD_warp3D_affine( dset, tran, mset, prefix, 0, WARP3D_NEWDSET ) ; if( oset == NULL ){ fprintf(stderr,"** ERROR: THD_warp3D() fails!\n"); exit(1); } tross_Copy_History( dset , oset ) ; tross_Make_History( "3dTagalign" , argc,argv , oset ) ; UNLOAD_DMAT(rt.mm,matar[0],matar[1],matar[2], matar[4],matar[5],matar[6], matar[8],matar[9],matar[10] ) ; UNLOAD_DFVEC3(rt.vv,matar[3],matar[7],matar[11]) ; THD_set_atr( oset->dblk, "TAGALIGN_MATVEC", ATR_FLOAT_TYPE, 12, matar ) ; /*-- if desired, keep old tagset --*/ if( keeptags ){ THD_dfvec3 rv ; oset->tagset = myXtNew(THD_usertaglist) ; *(oset->tagset) = *(dset->tagset) ; dsum = 0.0 ; for( jj=ii=0 ; ii < TAGLIST_COUNT(oset->tagset) ; ii++ ){ if( TAG_SET(TAGLIST_SUBTAG(oset->tagset,ii)) ){ rv = DMATVEC( rt.mm , yy[jj] ) ; rv = ADD_DFVEC3( rt.vv , rv ) ; dv = SUB_DFVEC3( xx[jj] , rv ) ; dsum += dv.xyz[0]*dv.xyz[0] + dv.xyz[1]*dv.xyz[1] + dv.xyz[2]*dv.xyz[2] ; UNLOAD_DFVEC3( rv , TAG_X( TAGLIST_SUBTAG(oset->tagset,ii) ) , TAG_Y( TAGLIST_SUBTAG(oset->tagset,ii) ) , TAG_Z( TAGLIST_SUBTAG(oset->tagset,ii) ) ) ; jj++ ; } } dsum = sqrt(dsum/nvec) ; fprintf(stderr,"++ RMS distance between tags after = %.2f mm\n" , dsum ) ; } DSET_write(oset) ; } /* end of 3dWarp-like work */ exit(0) ; }
/* if maxval >= 0, values may not exceed it */ int * get_1dcat_intlist ( char *sin , int *nret, int maxval) { int ipos , slen, *ret=NULL, ii=0; MRI_IMAGE *aim = NULL; float *far=NULL; char *str = NULL; int op = 0; *nret = -1; if (!sin || !strstr(sin,"1dcat ") || strlen (sin) < 8) { fprintf(stderr, "NULL input or string does not have '1dcat '" " or a 1D filename not present after '1dcat '\n"); return (NULL); } str = strdup(sin); /* move past count */ slen = strlen(str) ; ipos = strlen("1dcat "); /* find ending square */ for (ii=ipos; ii<slen; ++ii) { if (str[ii]=='[') ++op; if (str[ii]==']') { --op; } if (op < 0) { str[ii] = '\0'; break; } } /* read the filename */ deblank_name(str+ipos); if (!(aim = mri_read_1D(str+ipos))) { ERROR_message("Can't read 1D file '%s'", str+ipos) ; free(str); str=NULL; return(NULL); } /* return the indices */ far = MRI_FLOAT_PTR(aim); *nret = aim->nx*aim->ny; ret = (int *)malloc(sizeof(int)*(*nret+1)); ret[0] = *nret; for (ii=0; ii<*nret; ++ii) { ret[ii+1] = (int)far[ii]; /* was #if 0: leave error handling for elsewhere, 4 Jan 2016 [rickr] */ if ( (!allow_negative && ret[ii+1]<0) || (maxval >= 0 && ret[ii+1] > maxval) ) { ERROR_message( "Bad 1dcat brick selection value in 1D file '%s'\n" " value %d is %g (max=%d)\n", str+ipos, ii, far[ii], maxval); mri_free(aim); aim = NULL; far=NULL; free(str); str=NULL; free(ret); ret=NULL; return(NULL); } } mri_free(aim); aim = NULL; far=NULL; #if 0 fprintf(stderr,"ZSS: Selecting %d values from '%s':\n", *nret, str+ipos); for (ii=1; ii<=*nret; ++ii) { fprintf(stderr,"%d,",ret[ii]); } fprintf(stderr,"\n"); #endif free(str); str=NULL; return(ret); }
int main( int argc , char *argv[] ) { THD_3dim_dataset *yset=NULL , *aset=NULL , *mset=NULL , *wset=NULL ; MRI_IMAGE *fim=NULL, *qim,*tim, *pfim=NULL , *vim , *wim=NULL ; float *flar , *qar,*tar, *par=NULL , *var , *war=NULL ; MRI_IMARR *fimar=NULL ; MRI_IMAGE *aim , *yim ; float *aar , *yar ; int nt=0 , nxyz=0 , nvox=0 , nparam=0 , nqbase , polort=0 , ii,jj,kk,bb ; byte *mask=NULL ; int nmask=0 , iarg ; char *fname_out="-" ; /** equiv to stdout **/ float alpha=0.0f ; int nfir =0 ; float firwt[5]={0.09f,0.25f,0.32f,0.25f,0.09f} ; int nmed =0 ; int nwt =0 ; #define METHOD_C 3 #define METHOD_K 11 int method = METHOD_C ; /**--- help the pitiful user? ---**/ if( argc < 2 || strcmp(argv[1],"-help") == 0 ){ printf( "Usage: 3dInvFMRI [options]\n" "Program to compute stimulus time series, given a 3D+time dataset\n" "and an activation map (the inverse of the usual FMRI analysis problem).\n" "-------------------------------------------------------------------\n" "OPTIONS:\n" "\n" " -data yyy =\n" " *OR* = Defines input 3D+time dataset [a non-optional option].\n" " -input yyy =\n" "\n" " -map aaa = Defines activation map; 'aaa' should be a bucket dataset,\n" " each sub-brick of which defines the beta weight map for\n" " an unknown stimulus time series [also non-optional].\n" "\n" " -mapwt www = Defines a weighting factor to use for each element of\n" " the map. The dataset 'www' can have either 1 sub-brick,\n" " or the same number as in the -map dataset. In the\n" " first case, in each voxel, each sub-brick of the map\n" " gets the same weight in the least squares equations.\n" " [default: all weights are 1]\n" "\n" " -mask mmm = Defines a mask dataset, to restrict input voxels from\n" " -data and -map. [default: all voxels are used]\n" "\n" " -base fff = Each column of the 1D file 'fff' defines a baseline time\n" " series; these columns should be the same length as\n" " number of time points in 'yyy'. Multiple -base options\n" " can be given.\n" " -polort pp = Adds polynomials of order 'pp' to the baseline collection.\n" " The default baseline model is '-polort 0' (constant).\n" " To specify no baseline model at all, use '-polort -1'.\n" "\n" " -out vvv = Name of 1D output file will be 'vvv'.\n" " [default = '-', which is stdout; probably not good]\n" "\n" " -method M = Determines the method to use. 'M' is a single letter:\n" " -method C = least squares fit to data matrix Y [default]\n" " -method K = least squares fit to activation matrix A\n" "\n" " -alpha aa = Set the 'alpha' factor to 'aa'; alpha is used to penalize\n" " large values of the output vectors. Default is 0.\n" " A large-ish value for alpha would be 0.1.\n" "\n" " -fir5 = Smooth the results with a 5 point lowpass FIR filter.\n" " -median5 = Smooth the results with a 5 point median filter.\n" " [default: no smoothing; only 1 of these can be used]\n" "-------------------------------------------------------------------\n" "METHODS:\n" " Formulate the problem as\n" " Y = V A' + F C' + errors\n" " where Y = data matrix (N x M) [from -data]\n" " V = stimulus (N x p) [to -out]\n" " A = map matrix (M x p) [from -map]\n" " F = baseline matrix (N x q) [from -base and -polort]\n" " C = baseline weights (M x q) [not computed]\n" " N = time series length = length of -data file\n" " M = number of voxels in mask\n" " p = number of stimulus time series to estimate\n" " = number of parameters in -map file\n" " q = number of baseline parameters\n" " and ' = matrix transpose operator\n" " Next, define matrix Z (Y detrended relative to columns of F) by\n" " -1\n" " Z = [I - F(F'F) F'] Y\n" "-------------------------------------------------------------------\n" " The method C solution is given by\n" " -1\n" " V0 = Z A [A'A]\n" "\n" " This solution minimizes the sum of squares over the N*M elements\n" " of the matrix Y - V A' + F C' (N.B.: A' means A-transpose).\n" "-------------------------------------------------------------------\n" " The method K solution is given by\n" " -1 -1\n" " W = [Z Z'] Z A and then V = W [W'W]\n" "\n" " This solution minimizes the sum of squares of the difference between\n" " the A(V) predicted from V and the input A, where A(V) is given by\n" " -1\n" " A(V) = Z' V [V'V] = Z'W\n" "-------------------------------------------------------------------\n" " Technically, the solution is unidentfiable up to an arbitrary\n" " multiple of the columns of F (i.e., V = V0 + F G, where G is\n" " an arbitrary q x p matrix); the solution above is the solution\n" " that is orthogonal to the columns of F.\n" "\n" "-- RWCox - March 2006 - purely for experimental purposes!\n" ) ; printf("\n" "===================== EXAMPLE USAGE =====================================\n" "** Step 1: From a training dataset, generate activation map.\n" " The input dataset has 4 runs, each 108 time points long. 3dDeconvolve\n" " is used on the first 3 runs (time points 0..323) to generate the\n" " activation map. There are two visual stimuli (Complex and Simple).\n" "\n" " 3dDeconvolve -x1D xout_short_two.1D -input rall_vr+orig'[0..323]' \\\n" " -num_stimts 2 \\\n" " -stim_file 1 hrf_complex.1D -stim_label 1 Complex \\\n" " -stim_file 2 hrf_simple.1D -stim_label 2 Simple \\\n" " -concat '1D:0,108,216' \\\n" " -full_first -fout -tout \\\n" " -bucket func_ht2_short_two -cbucket cbuc_ht2_short_two\n" "\n" " N.B.: You may want to de-spike, smooth, and register the 3D+time\n" " dataset prior to the analysis (as usual). These steps are not\n" " shown here -- I'm presuming you know how to use AFNI already.\n" "\n" "** Step 2: Create a mask of highly activated voxels.\n" " The F statistic threshold is set to 30, corresponding to a voxel-wise\n" " p = 1e-12 = very significant. The mask is also lightly clustered, and\n" " restricted to brain voxels.\n" "\n" " 3dAutomask -prefix Amask rall_vr+orig\n" " 3dcalc -a 'func_ht2_short+orig[0]' -b Amask+orig -datum byte \\\n" " -nscale -expr 'step(a-30)*b' -prefix STmask300\n" " 3dmerge -dxyz=1 -1clust 1.1 5 -prefix STmask300c STmask300+orig\n" "\n" "** Step 3: Run 3dInvFMRI to estimate the stimulus functions in run #4.\n" " Run #4 is time points 324..431 of the 3D+time dataset (the -data\n" " input below). The -map input is the beta weights extracted from\n" " the -cbucket output of 3dDeconvolve.\n" "\n" " 3dInvFMRI -mask STmask300c+orig \\\n" " -data rall_vr+orig'[324..431]' \\\n" " -map cbuc_ht2_short_two+orig'[6..7]' \\\n" " -polort 1 -alpha 0.01 -median5 -method K \\\n" " -out ii300K_short_two.1D\n" "\n" " 3dInvFMRI -mask STmask300c+orig \\\n" " -data rall_vr+orig'[324..431]' \\\n" " -map cbuc_ht2_short_two+orig'[6..7]' \\\n" " -polort 1 -alpha 0.01 -median5 -method C \\\n" " -out ii300C_short_two.1D\n" "\n" "** Step 4: Plot the results, and get confused.\n" "\n" " 1dplot -ynames VV KK CC -xlabel Run#4 -ylabel ComplexStim \\\n" " hrf_complex.1D'{324..432}' \\\n" " ii300K_short_two.1D'[0]' \\\n" " ii300C_short_two.1D'[0]'\n" "\n" " 1dplot -ynames VV KK CC -xlabel Run#4 -ylabel SimpleStim \\\n" " hrf_simple.1D'{324..432}' \\\n" " ii300K_short_two.1D'[1]' \\\n" " ii300C_short_two.1D'[1]'\n" "\n" " N.B.: I've found that method K works better if MORE voxels are\n" " included in the mask (lower threshold) and method C if\n" " FEWER voxels are included. The above threshold gave 945\n" " voxels being used to determine the 2 output time series.\n" "=========================================================================\n" ) ; PRINT_COMPILE_DATE ; exit(0) ; } /**--- bureaucracy ---**/ mainENTRY("3dInvFMRI main"); machdep(); PRINT_VERSION("3dInvFMRI"); AUTHOR("Zhark"); AFNI_logger("3dInvFMRI",argc,argv) ; /**--- scan command line ---**/ iarg = 1 ; while( iarg < argc ){ if( strcmp(argv[iarg],"-method") == 0 ){ switch( argv[++iarg][0] ){ default: WARNING_message("Ignoring illegal -method '%s'",argv[iarg]) ; break ; case 'C': method = METHOD_C ; break ; case 'K': method = METHOD_K ; break ; } iarg++ ; continue ; } if( strcmp(argv[iarg],"-fir5") == 0 ){ if( nmed > 0 ) WARNING_message("Ignoring -fir5 in favor of -median5") ; else nfir = 5 ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-median5") == 0 ){ if( nfir > 0 ) WARNING_message("Ignoring -median5 in favor of -fir5") ; else nmed = 5 ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-alpha") == 0 ){ alpha = (float)strtod(argv[++iarg],NULL) ; if( alpha <= 0.0f ){ alpha = 0.0f ; WARNING_message("-alpha '%s' ignored!",argv[iarg]) ; } iarg++ ; continue ; } if( strcmp(argv[iarg],"-data") == 0 || strcmp(argv[iarg],"-input") == 0 ){ if( yset != NULL ) ERROR_exit("Can't input 2 3D+time datasets") ; yset = THD_open_dataset(argv[++iarg]) ; CHECK_OPEN_ERROR(yset,argv[iarg]) ; nt = DSET_NVALS(yset) ; if( nt < 2 ) ERROR_exit("Only 1 sub-brick in dataset %s",argv[iarg]) ; nxyz = DSET_NVOX(yset) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-map") == 0 ){ if( aset != NULL ) ERROR_exit("Can't input 2 -map datasets") ; aset = THD_open_dataset(argv[++iarg]) ; CHECK_OPEN_ERROR(aset,argv[iarg]) ; nparam = DSET_NVALS(aset) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-mapwt") == 0 ){ if( wset != NULL ) ERROR_exit("Can't input 2 -mapwt datasets") ; wset = THD_open_dataset(argv[++iarg]) ; CHECK_OPEN_ERROR(wset,argv[iarg]) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-mask") == 0 ){ if( mset != NULL ) ERROR_exit("Can't input 2 -mask datasets") ; mset = THD_open_dataset(argv[++iarg]) ; CHECK_OPEN_ERROR(mset,argv[iarg]) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-polort") == 0 ){ char *cpt ; polort = (int)strtod(argv[++iarg],&cpt) ; if( *cpt != '\0' ) WARNING_message("Illegal non-numeric value after -polort") ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-out") == 0 ){ fname_out = strdup(argv[++iarg]) ; if( !THD_filename_ok(fname_out) ) ERROR_exit("Bad -out filename '%s'",fname_out) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-base") == 0 ){ if( fimar == NULL ) INIT_IMARR(fimar) ; qim = mri_read_1D( argv[++iarg] ) ; if( qim == NULL ) ERROR_exit("Can't read 1D file %s",argv[iarg]) ; ADDTO_IMARR(fimar,qim) ; iarg++ ; continue ; } ERROR_exit("Unrecognized option '%s'",argv[iarg]) ; } /**--- finish up processing options ---**/ if( yset == NULL ) ERROR_exit("No input 3D+time dataset?!") ; if( aset == NULL ) ERROR_exit("No input FMRI -map dataset?!") ; if( DSET_NVOX(aset) != nxyz ) ERROR_exit("Grid mismatch between -data and -map") ; INFO_message("Loading dataset for Y") ; DSET_load(yset); CHECK_LOAD_ERROR(yset) ; INFO_message("Loading dataset for A") ; DSET_load(aset); CHECK_LOAD_ERROR(aset) ; if( wset != NULL ){ if( DSET_NVOX(wset) != nxyz ) ERROR_exit("Grid mismatch between -data and -mapwt") ; nwt = DSET_NVALS(wset) ; if( nwt > 1 && nwt != nparam ) ERROR_exit("Wrong number of values=%d in -mapwt; should be 1 or %d", nwt , nparam ) ; INFO_message("Loading dataset for mapwt") ; DSET_load(wset); CHECK_LOAD_ERROR(wset) ; } if( mset != NULL ){ if( DSET_NVOX(mset) != nxyz ) ERROR_exit("Grid mismatch between -data and -mask") ; INFO_message("Loading dataset for mask") ; DSET_load(mset); CHECK_LOAD_ERROR(mset) ; mask = THD_makemask( mset , 0 , 1.0f,-1.0f ); DSET_delete(mset); nmask = THD_countmask( nxyz , mask ) ; if( nmask < 3 ){ WARNING_message("Mask has %d voxels -- ignoring!",nmask) ; free(mask) ; mask = NULL ; nmask = 0 ; } } nvox = (nmask > 0) ? nmask : nxyz ; INFO_message("N = time series length = %d",nt ) ; INFO_message("M = number of voxels = %d",nvox ) ; INFO_message("p = number of params = %d",nparam) ; /**--- set up baseline funcs in one array ---*/ nqbase = (polort >= 0 ) ? polort+1 : 0 ; if( fimar != NULL ){ for( kk=0 ; kk < IMARR_COUNT(fimar) ; kk++ ){ qim = IMARR_SUBIMAGE(fimar,kk) ; if( qim != NULL && qim->nx != nt ) WARNING_message("-base #%d length=%d; data length=%d",kk+1,qim->nx,nt) ; nqbase += qim->ny ; } } INFO_message("q = number of baselines = %d",nqbase) ; #undef F #define F(i,j) flar[(i)+(j)*nt] /* nt X nqbase */ if( nqbase > 0 ){ fim = mri_new( nt , nqbase , MRI_float ) ; /* F matrix */ flar = MRI_FLOAT_PTR(fim) ; bb = 0 ; if( polort >= 0 ){ /** load polynomial baseline **/ double a = 2.0/(nt-1.0) ; for( jj=0 ; jj <= polort ; jj++ ){ for( ii=0 ; ii < nt ; ii++ ) F(ii,jj) = (float)Plegendre( a*ii-1.0 , jj ) ; } bb = polort+1 ; } #undef Q #define Q(i,j) qar[(i)+(j)*qim->nx] /* qim->nx X qim->ny */ if( fimar != NULL ){ /** load -base baseline columns **/ for( kk=0 ; kk < IMARR_COUNT(fimar) ; kk++ ){ qim = IMARR_SUBIMAGE(fimar,kk) ; qar = MRI_FLOAT_PTR(qim) ; for( jj=0 ; jj < qim->ny ; jj++ ){ for( ii=0 ; ii < nt ; ii++ ) F(ii,bb+jj) = (ii < qim->nx) ? Q(ii,jj) : 0.0f ; } bb += qim->ny ; } DESTROY_IMARR(fimar) ; fimar=NULL ; } /* remove mean from each column after first? */ if( polort >= 0 && nqbase > 1 ){ float sum ; for( jj=1 ; jj < nqbase ; jj++ ){ sum = 0.0f ; for( ii=0 ; ii < nt ; ii++ ) sum += F(ii,jj) ; sum /= nt ; for( ii=0 ; ii < nt ; ii++ ) F(ii,jj) -= sum ; } } /* compute pseudo-inverse of baseline matrix, so we can project it out from the data time series */ /* -1 */ /* (F'F) F' matrix */ INFO_message("Computing pseudo-inverse of baseline matrix F") ; pfim = mri_matrix_psinv(fim,NULL,0.0f) ; par = MRI_FLOAT_PTR(pfim) ; #undef P #define P(i,j) par[(i)+(j)*nqbase] /* nqbase X nt */ #if 0 qim = mri_matrix_transpose(pfim) ; /** save to disk? **/ mri_write_1D( "Fpsinv.1D" , qim ) ; mri_free(qim) ; #endif } /**--- set up map image into aim/aar = A matrix ---**/ #undef GOOD #define GOOD(i) (mask==NULL || mask[i]) #undef A #define A(i,j) aar[(i)+(j)*nvox] /* nvox X nparam */ INFO_message("Loading map matrix A") ; aim = mri_new( nvox , nparam , MRI_float ); aar = MRI_FLOAT_PTR(aim); for( jj=0 ; jj < nparam ; jj++ ){ for( ii=kk=0 ; ii < nxyz ; ii++ ){ if( GOOD(ii) ){ A(kk,jj) = THD_get_voxel(aset,ii,jj); kk++; } }} DSET_unload(aset) ; /**--- set up map weight into wim/war ---**/ #undef WT #define WT(i,j) war[(i)+(j)*nvox] /* nvox X nparam */ if( wset != NULL ){ int numneg=0 , numpos=0 ; float fac ; INFO_message("Loading map weight matrix") ; wim = mri_new( nvox , nwt , MRI_float ) ; war = MRI_FLOAT_PTR(wim) ; for( jj=0 ; jj < nwt ; jj++ ){ for( ii=kk=0 ; ii < nxyz ; ii++ ){ if( GOOD(ii) ){ WT(kk,jj) = THD_get_voxel(wset,ii,jj); if( WT(kk,jj) > 0.0f ){ numpos++; WT(kk,jj) = sqrt(WT(kk,jj)); } else if( WT(kk,jj) < 0.0f ){ numneg++; WT(kk,jj) = 0.0f; } kk++; } }} DSET_unload(wset) ; if( numpos <= nparam ) WARNING_message("Only %d positive weights found in -wtmap!",numpos) ; if( numneg > 0 ) WARNING_message("%d negative weights found in -wtmap!",numneg) ; for( jj=0 ; jj < nwt ; jj++ ){ fac = 0.0f ; for( kk=0 ; kk < nvox ; kk++ ) if( WT(kk,jj) > fac ) fac = WT(kk,jj) ; if( fac > 0.0f ){ fac = 1.0f / fac ; for( kk=0 ; kk < nvox ; kk++ ) WT(kk,jj) *= fac ; } } } /**--- set up data image into yim/yar = Y matrix ---**/ #undef Y #define Y(i,j) yar[(i)+(j)*nt] /* nt X nvox */ INFO_message("Loading data matrix Y") ; yim = mri_new( nt , nvox , MRI_float ); yar = MRI_FLOAT_PTR(yim); for( ii=0 ; ii < nt ; ii++ ){ for( jj=kk=0 ; jj < nxyz ; jj++ ){ if( GOOD(jj) ){ Y(ii,kk) = THD_get_voxel(yset,jj,ii); kk++; } }} DSET_unload(yset) ; /**--- project baseline out of data image = Z matrix ---**/ if( pfim != NULL ){ #undef T #define T(i,j) tar[(i)+(j)*nt] /* nt X nvox */ INFO_message("Projecting baseline out of Y") ; qim = mri_matrix_mult( pfim , yim ) ; /* nqbase X nvox */ tim = mri_matrix_mult( fim , qim ) ; /* nt X nvox */ tar = MRI_FLOAT_PTR(tim) ; /* Y projected onto baseline */ for( jj=0 ; jj < nvox ; jj++ ) for( ii=0 ; ii < nt ; ii++ ) Y(ii,jj) -= T(ii,jj) ; mri_free(tim); mri_free(qim); mri_free(pfim); mri_free(fim); } /***** At this point: matrix A is in aim, matrix Z is in yim. Solve for V into vim, using the chosen method *****/ switch( method ){ default: ERROR_exit("Illegal method code! WTF?") ; /* Huh? */ /*.....................................................................*/ case METHOD_C: /**--- compute pseudo-inverse of A map ---**/ INFO_message("Method C: Computing pseudo-inverse of A") ; if( wim != NULL ) WARNING_message("Ignoring -mapwt dataset") ; pfim = mri_matrix_psinv(aim,NULL,alpha) ; /* nparam X nvox */ if( pfim == NULL ) ERROR_exit("mri_matrix_psinv() fails") ; mri_free(aim) ; /**--- and apply to data to get results ---*/ INFO_message("Computing result V") ; vim = mri_matrix_multranB( yim , pfim ) ; /* nt x nparam */ mri_free(pfim) ; mri_free(yim) ; break ; /*.....................................................................*/ case METHOD_K: /**--- compute pseudo-inverse of transposed Z ---*/ INFO_message("Method K: Computing pseudo-inverse of Z'") ; if( nwt > 1 ){ WARNING_message("Ignoring -mapwt dataset: more than 1 sub-brick") ; nwt = 0 ; mri_free(wim) ; wim = NULL ; war = NULL ; } if( nwt == 1 ){ float fac ; for( kk=0 ; kk < nvox ; kk++ ){ fac = war[kk] ; for( ii=0 ; ii < nt ; ii++ ) Y(ii,kk) *= fac ; for( ii=0 ; ii < nparam ; ii++ ) A(kk,ii) *= fac ; } } tim = mri_matrix_transpose(yim) ; mri_free(yim) ; pfim = mri_matrix_psinv(tim,NULL,alpha) ; mri_free(tim) ; if( pfim == NULL ) ERROR_exit("mri_matrix_psinv() fails") ; INFO_message("Computing W") ; tim = mri_matrix_mult( pfim , aim ) ; mri_free(aim) ; mri_free(pfim) ; INFO_message("Computing result V") ; pfim = mri_matrix_psinv(tim,NULL,0.0f) ; mri_free(tim) ; vim = mri_matrix_transpose(pfim) ; mri_free(pfim); break ; } /* end of switch on method */ if( wim != NULL ) mri_free(wim) ; /**--- smooth? ---**/ if( nfir > 0 && vim->nx > nfir ){ INFO_message("FIR-5-ing result") ; var = MRI_FLOAT_PTR(vim) ; for( jj=0 ; jj < vim->ny ; jj++ ) linear_filter_reflect( nfir,firwt , vim->nx , var + (jj*vim->nx) ) ; } if( nmed > 0 && vim->nx > nmed ){ INFO_message("Median-5-ing result") ; var = MRI_FLOAT_PTR(vim) ; for( jj=0 ; jj < vim->ny ; jj++ ) median5_filter_reflect( vim->nx , var + (jj*vim->nx) ) ; } /**--- write results ---**/ INFO_message("Writing result to '%s'",fname_out) ; mri_write_1D( fname_out , vim ) ; exit(0) ; }
MRI_IMARR * THD_get_all_timeseries( char * dname ) { THD_string_array * flist , * rlist ; int ir , ll , ii ; char * fname , * tname ; float * far ; MRI_IMARR * outar ; MRI_IMAGE * outim , * flim ; #ifdef NEWWAY char * pat ; #endif unsigned long max_fsize ; /* 20 Jul 2004: max 1D file size to load */ max_fsize = (unsigned long) AFNI_numenv( "AFNI_MAX_1DSIZE" ) ; if( max_fsize == 0 ) max_fsize = 123*1024 ; /*----- sanity check and initialize -----*/ if( dname == NULL || strlen(dname) == 0 ) return NULL ; INIT_IMARR( outar ) ; /*----- find all *.1D files -----*/ #ifdef NEWWAY ii = strlen(dname) ; pat = (char *) malloc(sizeof(char)*(ii+8)) ; strcpy(pat,dname) ; if( pat[ii-1] != '/' ) strcat(pat,"/") ; strcat(pat,"*.1D*") ; flist = THD_get_wildcard_filenames( pat ) ; free(pat) ; #else flist = THD_get_all_filenames( dname ) ; #endif if( flist == NULL || flist->num <= 0 ){ DESTROY_SARR(flist) ; DESTROY_IMARR(outar) ; return NULL ; } rlist = THD_extract_regular_files( flist ) ; DESTROY_SARR(flist) ; if( rlist == NULL || rlist->num <= 0 ){ DESTROY_SARR(rlist) ; DESTROY_IMARR(outar) ; return NULL ; } for( ir=0 ; ir < rlist->num ; ir++ ){ fname = rlist->ar[ir] ; if( fname == NULL ) continue ; ll = strlen(fname) - 3 ; if( ll < 1 ) continue ; if( strcmp(fname+ll,".1D")==0 || strcmp(fname+ll,"1Dx")==0 || strcmp(fname+ll,"1Dv")==0 ){ if( THD_filesize(fname) > max_fsize ) continue ; /* 20 Jul 2004 */ flim = mri_read_1D( fname ) ; if( flim != NULL ){ far = MRI_FLOAT_PTR(flim) ; for( ii=0 ; ii < flim->nvox ; ii++ ) if( fabs(far[ii]) >= 33333.0 ) far[ii] = WAY_BIG ; tname = THD_trailname(fname,1) ; mri_add_name( tname , flim ) ; ADDTO_IMARR( outar , flim ) ; } } } DESTROY_SARR(rlist) ; if( IMARR_COUNT(outar) == 0 ) DESTROY_IMARR(outar) ; return outar ; }
int main( int argc , char *argv[] ) { THD_3dim_dataset *dset=NULL , *oset=NULL ; MRI_IMAGE *thim=NULL ; float *thar ; int nthar ; byte *mask=NULL ; int nmask=0 ; MRI_IMAGE *datim=NULL, *thrim=NULL , *outim=NULL ; int iarg , dind=0 , tind=1 , ith , nnlev=1 ; int scode ; float *spar=NULL ; char *prefix = "ETC.nii" ; /*-- some pitiful help --*/ if( argc < 2 || strcasecmp(argv[1],"-help") == 0 ){ printf("\n" "Usage: 3dETC [options] inputdataset\n" "\n" "Options:\n" "========\n" " -input dset = alternative way to input the dataset\n" " -prefix ppp = output prefix\n" " -thresh ttt = 1D file with\n" " column #1 = p-value\n" " column #2 = cluster threshold\n" " -mask mmm = dataset with mask\n" " -1dindex ii = output comes from sub-brick #ii\n" " -1tindex jj = threshold on sub-brick #jj\n" " -NN nn = nn is 1 or 2 or 3 [default 1]\n" "\n" "-- Experimental - RWCox - 24 Dec 2015\n" ) ; exit(0) ; } /*-- scan options --*/ iarg = 1 ; while( iarg < argc && argv[iarg][0] == '-' ){ if( strcasecmp(argv[iarg],"-input") == 0 ){ if( dset != NULL ) ERROR_exit("You can't use option '%s' twice!",argv[iarg]) ; if( ++iarg >= argc ) ERROR_exit("Option '%s' needs an argument to follow!",argv[iarg-1]) ; dset = THD_open_dataset( argv[iarg] ) ; CHECK_OPEN_ERROR(dset,argv[iarg]) ; DSET_load(dset) ; CHECK_LOAD_ERROR(dset) ; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-mask") == 0 ){ bytevec *bvec ; int nmask_hits ; if( mask != NULL ) ERROR_exit("Can't use '-mask' twice!") ; if( ++iarg >= argc ) ERROR_exit("Need argument after '%s'",argv[iarg-1]) ; bvec = THD_create_mask_from_string(argv[iarg]) ; if( bvec == NULL ) ERROR_exit("Can't create mask from '-mask' option") ; mask = bvec->ar ; nmask = bvec->nar ; nmask_hits = THD_countmask( nmask , mask ) ; if( nmask_hits > 0 ) INFO_message("%d voxels in -mask definition (out of %d total)", nmask_hits,nmask) ; else ERROR_exit("no nonzero voxels in -mask dataset") ; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-prefix") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Option '%s' needs an argument to follow!",argv[iarg-1]) ; prefix = strdup(argv[iarg]) ; if( ! THD_filename_ok(prefix) ) ERROR_exit("-prefix '%s' is not a good filename prefix",prefix) ; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-1tindex") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Option '%s' needs an argument to follow!",argv[iarg-1]) ; tind = (int)strtod(argv[iarg],NULL) ; if( tind < 0 ) ERROR_exit("-tind '%s' is illegal!",argv[iarg]) ; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-1dindex") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Option '%s' needs an argument to follow!",argv[iarg-1]) ; dind = (int)strtod(argv[iarg],NULL) ; if( dind < 0 ) ERROR_exit("-dind '%s' is illegal!",argv[iarg]) ; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-NN") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Option '%s' needs an argument to follow!",argv[iarg-1]) ; nnlev = (int)strtod(argv[iarg],NULL) ; if( nnlev < 1 || nnlev > 3 ) ERROR_exit("-nnlev '%s' is illegal!",argv[iarg]) ; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-NN1") == 0 ){ nnlev = 1 ; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-NN2") == 0 ){ nnlev = 2 ; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-NN3") == 0 ){ nnlev = 3 ; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-thresh") == 0 ){ int nbad=0 ; if( thim != NULL ) ERROR_exit("You can't use option '%s' twice!",argv[iarg]) ; if( ++iarg >= argc ) ERROR_exit("Option '%s' needs an argument to follow!",argv[iarg-1]) ; thim = mri_read_1D( argv[iarg] ) ; if( thim == NULL ) ERROR_exit("Cannot read file from option -thresh '%s'",argv[iarg]) ; if( thim->ny < 2 ) ERROR_exit("-thresh '%s' doesn't have at least 2 columns!",argv[iarg]) ; nthar = thim->nx ; thar = MRI_FLOAT_PTR(thim) ; for( ith=0 ; ith < nthar ; ith++ ){ if( thar[ith] <= 0.0f || thar[ith] > 0.10f ) nbad++ ; } if( nbad > 0 ) ERROR_exit("Some value%s in -thresh '%s' Column #1 %s outside 0 < p <= 0.1 :-(", (nbad==1)?"\0":"s" , argv[iarg] , (nbad==1)?"is":"are" ) ; for( ith=0 ; ith < nthar ; ith++ ){ if( thar[ith+nthar] < 1.0f ) nbad++ ; } if( nbad > 0 ) ERROR_exit("Some value%s in -thresh '%s' Column #2 %s less than 1 :-(", (nbad==1)?"\0":"s" , argv[iarg] , (nbad==1)?"is":"are" ) ; INFO_message("-thresh table has %d levels of thresholding",nthar) ; iarg++ ; continue ; } ERROR_exit("Unknown option '%s' :-(",argv[iarg] ) ; exit(1) ; } /*-- did we get the input dataset yet? --*/ if( dset == NULL ){ if( iarg >= argc ) ERROR_exit("no input dataset?!") ; dset = THD_open_dataset( argv[iarg] ) ; CHECK_OPEN_ERROR(dset,argv[iarg]) ; DSET_load(dset) ; CHECK_LOAD_ERROR(dset) ; iarg++ ; } /*-- check things --*/ if( nmask > 0 && DSET_NVOX(dset) != nmask ) ERROR_exit("mask and input datasets don't match in number of voxels") ; if( thim == NULL ) ERROR_exit("no -thresh option was given!?") ; if( dind >= DSET_NVALS(dset) ) ERROR_exit("data index %d is beyond end of input dataset!",dind) ; if( tind >= DSET_NVALS(dset) ) ERROR_exit("threshold index %d is beyond end of input dataset!",tind) ; /*-- record things for posterity, et cetera --*/ mainENTRY("3dETC main"); machdep(); AFNI_logger("3dETC",argc,argv); PRINT_VERSION("3dETC") ; AUTHOR("Bob the Equable") ; /*-- get the data and threshold volumes --*/ datim = THD_extract_float_brick( dind , dset ) ; thrim = THD_extract_float_brick( tind , dset ) ; if( datim == NULL || thrim == NULL ) /* should be impossible */ ERROR_exit("Can't get data and/or thresh data from input dataset???") ; DSET_unload(dset) ; scode = DSET_BRICK_STATCODE(dset,tind) ; if( scode < 0 ) ERROR_exit("thresh sub-brick index %d is NOT a statistical volume!?",tind) ; spar = DSET_BRICK_STATAUX(dset,tind) ; #if 1 INFO_message("value range in thrim = %g .. %g",mri_min(thrim),mri_max(thrim)) ; #endif outim = mri_multi_threshold_clusterize( datim , scode,spar,thrim , mask , nthar , thar , thar+nthar , nnlev , 0 ) ; oset = EDIT_empty_copy(dset) ; EDIT_dset_items( oset , ADN_prefix , prefix , ADN_nvals , 1 , ADN_ntt , 0 , ADN_brick_fac , NULL , ADN_type , HEAD_FUNC_TYPE , ADN_func_type , FUNC_BUCK_TYPE , ADN_none ) ; EDIT_substitute_brick( oset , 0 , MRI_float , MRI_FLOAT_PTR(outim) ) ; DSET_write(oset) ; WROTE_DSET(oset) ; INFO_message("# nonzero voxels = %d",mri_nonzero_count(outim)) ; exit(0) ; }
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 main(int argc, char *argv[]) { int i, k, ii; int iarg; char *prefix=NULL; char *maskname=NULL; char *gradsname=NULL; char *dtsname=NULL; THD_3dim_dataset *MASK=NULL; THD_3dim_dataset *DTS=NULL; MRI_IMAGE *GRADS=NULL, *GRADS_IN=NULL; int Ngrads=0, Nfull=0; int Nvox=-1; // tot number vox int Dim[3]={0,0,0}; // dim in each dir float NOISESCALE_DWI = -1.; float NOISESCALE_B0 = -1; float S0 = 1000.; float bval = 1.; int NOISE_IN_S0 = 0; byte *mskd2=NULL; // not great, but another format of mask float **dwi=NULL; THD_3dim_dataset *DWI_OUT=NULL; const gsl_rng_type * T; gsl_rng *r; long seed; srand(time(0)); seed = time(NULL) ; gsl_rng_env_setup(); T = gsl_rng_default; r = gsl_rng_alloc (T); gsl_rng_set (r, seed); // ################################################################### // ######################### load ################################## // ################################################################### mainENTRY("3dDTtoNoisyDWI"); machdep(); if (argc == 1) { usage_DTtoNoisyDWI(1); exit(0); } iarg = 1; while( iarg < argc && argv[iarg][0] == '-' ){ if( strcmp(argv[iarg],"-help") == 0 || strcmp(argv[iarg],"-h") == 0 ) { usage_DTtoNoisyDWI(strlen(argv[iarg])>3 ? 2:1); exit(0); } if( strcmp(argv[iarg],"-dt_in") == 0) { iarg++ ; if( iarg >= argc ) ERROR_exit("Need argument after '-eig_vecs'"); dtsname = strdup(argv[iarg]) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-prefix") == 0 ){ iarg++ ; if( iarg >= argc ) ERROR_exit("Need argument after '-prefix'"); prefix = strdup(argv[iarg]) ; if( !THD_filename_ok(prefix) ) ERROR_exit("Illegal name after '-prefix'"); iarg++ ; continue ; } if( strcmp(argv[iarg],"-mask") == 0) { iarg++ ; if( iarg >= argc ) ERROR_exit("Need argument after '-mask'"); maskname = strdup(argv[iarg]) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-grads") == 0) { iarg++ ; if( iarg >= argc ) ERROR_exit("Need argument after '-mask'"); gradsname = strdup(argv[iarg]) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-noise_DWI") == 0) { if( ++iarg >= argc ) ERROR_exit("Need numerical argument after '-noise_DWI'"); NOISESCALE_DWI = atof(argv[iarg]); iarg++ ; continue ; } if( strcmp(argv[iarg],"-noise_B0") == 0) { if( ++iarg >= argc ) ERROR_exit("Need numerical argument after '-noise_B0'"); NOISESCALE_B0 = atof(argv[iarg]); iarg++ ; continue ; } if( strcmp(argv[iarg],"-S0") == 0) { if( ++iarg >= argc ) ERROR_exit("Need numerical argument after '-S0'"); S0 = atof(argv[iarg]); if(S0 <= 0 ) ERROR_exit("The '-S0' value must be >0."); iarg++ ; continue ; } if( strcmp(argv[iarg],"-bval") == 0) { if( ++iarg >= argc ) ERROR_exit("Need numerical argument after '-bval'"); bval = atof(argv[iarg]); if(bval <= 0 ) ERROR_exit("The '-bval' value must be >0."); iarg++ ; continue ; } ERROR_message("Bad option '%s'\n",argv[iarg]) ; suggest_best_prog_option(argv[0], argv[iarg]); exit(1); } // ################################################################### // #################### some checks ############################### // ################################################################### if(!prefix) ERROR_exit("Need to give a '-prefix'."); if(!dtsname) ERROR_exit("Need to input diffusion tensor file after '-dt_in'."); if(!gradsname) ERROR_exit("Need to input gradient file after '-grads'."); if( NOISESCALE_DWI<0 ) ERROR_exit("Fractional noise value after '-snr0' needs to be >0. " "It sets the noise scale of ref signal S0."); if(NOISESCALE_DWI > 0) INFO_message("You have chosen an SNR0 of approximately %.2f for DWIs", 1./NOISESCALE_DWI); else INFO_message("You have noiseless (i.e., infinite SNR) set of DWIs"); if( NOISESCALE_B0 < 0 ) NOISESCALE_B0 = NOISESCALE_DWI; if(NOISESCALE_B0 > 0) INFO_message("You have chosen an SNR0 of approximately %.2f for the B0", 1./NOISESCALE_B0); else INFO_message("You have noiseless (i.e., infinite SNR) reference B0."); // ################################################################### if(dtsname) { DTS = THD_open_dataset(dtsname); DSET_load(DTS); CHECK_LOAD_ERROR(DTS); if( 6 != DSET_NVALS(DTS) ) ERROR_exit("DT file '%s' must have 6 bricks-- " "it has %d bricks!", dtsname, DSET_NVALS(DTS)); } Nvox = DSET_NVOX(DTS); Dim[0] = DSET_NX(DTS); Dim[1] = DSET_NY(DTS); Dim[2] = DSET_NZ(DTS); if(Nvox<0) ERROR_exit("Error reading Nvox from eigenvalue file."); mskd2 = (byte *)calloc(Nvox,sizeof(byte)); if( (mskd2 == NULL)) { fprintf(stderr, "\n\n MemAlloc failure (masks).\n\n"); exit(122); } if(maskname) { MASK = THD_open_dataset(maskname); DSET_load(MASK); CHECK_LOAD_ERROR(MASK); if( 1 != DSET_NVALS(MASK) ) ERROR_exit("Mask file '%s' is not scalar-- " "it has %d bricks!", maskname, DSET_NVALS(MASK)); for( k=0 ; k<Nvox ; k++ ) if (THD_get_voxel(MASK, k, 0) > 0 ) mskd2[k] = 1; DSET_delete(MASK); free(MASK); free(maskname); } else { for( k=0 ; k<Nvox ; k++ ) if( fabs(THD_get_voxel(DTS,k,0) > EPS_V) ) mskd2[k] = 1; } GRADS_IN = mri_read_1D (gradsname); GRADS = mri_transpose(GRADS_IN); // get rid of autotranspose... if (GRADS == NULL) ERROR_exit("Error reading gradient vector file"); mri_free(GRADS_IN); Ngrads = GRADS->ny; if(Ngrads < 6) ERROR_exit("Too few grads (there appear to be only %d).",Ngrads); if(GRADS->nx !=3 ) ERROR_exit("Wrong number of columns in the grad file: " " am reading %d instead of 3.",GRADS->nx); Nfull = Ngrads+1; INFO_message("Have surmised there are %d total grads; " "output file will have %d bricks", Ngrads,Nfull); dwi = calloc(Nfull,sizeof(dwi)); for(i=0 ; i<Nfull ; i++) dwi[i] = calloc( Nvox,sizeof(float)); INFO_message("Calculating the DWIs."); i = RicianNoiseDWIs( dwi, Nvox, Ngrads, DTS, NOISESCALE_DWI, NOISESCALE_B0, GRADS, mskd2, S0, bval, r); INFO_message("Writing the DWIs."); DWI_OUT = EDIT_empty_copy( DTS ); EDIT_dset_items(DWI_OUT, ADN_nvals, Nfull, ADN_datum_all, MRI_float , ADN_prefix, prefix, ADN_none ); for( i=0; i<Nfull ; i++) { EDIT_substitute_brick(DWI_OUT, i, MRI_float, dwi[i]); dwi[i]=NULL; } THD_load_statistics( DWI_OUT ); if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(DWI_OUT)) ) ERROR_exit("Can't overwrite existing dataset '%s'", DSET_HEADNAME(DWI_OUT)); tross_Make_History("3dDTtoNoisyDWI", argc, argv, DWI_OUT); THD_write_3dim_dataset(NULL, NULL, DWI_OUT, True); DSET_delete(DWI_OUT); free(DWI_OUT); // ################################################################# // ########################## free ############################### // ################################################################# DSET_delete(DTS); free(DTS); for( i=0 ; i<Nfull ; i++) free(dwi[i]); free(dwi); free(prefix); free(gradsname); free(dtsname); mri_free(GRADS); return 0; }
int main (int argc,char *argv[]) {/* Main */ static char FuncName[]={"ScaleToMap"}; char *IntName = NULL, *Prfx, h[9], *CmapFileName = NULL, *dbfile = NULL, *MapName=NULL; MRI_IMAGE *im = NULL; float *far=NULL; int N_V, N_Int, kar, k, ii, i, icol=-1, vcol=-1, Sgn, interpmode, k3; int Vminloc, Vmaxloc, *iV = NULL; float Vmin, Vmax, brfact; float *V = NULL, *Vsort = NULL; float IntRange[2], MaskColor[3], MaskRange[2]={0.0, 0.0}, arange; SUMA_Boolean ApplyClip, ApplyMask, setMaskCol, ApplyPercClip, Vopt; SUMA_Boolean iVopt, inopt, NoMaskCol, MapSpecified, alaAFNI, MaskZero; SUMA_Boolean brk, frf, ShowMap, ShowMapdb; SUMA_COLOR_MAP *CM; SUMA_SCALE_TO_MAP_OPT * OptScl; int MapType, freecm = 1; SUMA_COLOR_SCALED_VECT * SV; SUMA_AFNI_COLORS *SAC=NULL; SUMA_Boolean FromAFNI = NOPE; int imap, isPmap, isNmap; SUMA_Boolean LocalHead = NOPE; SUMA_STANDALONE_INIT; SUMAg_CF->isGraphical = YUP; SUMA_mainENTRY; /* this is placed down here to */ /* if (argc < 3) { SUMA_ScaleToMap_usage(); exit (1); } */ kar = 1; brfact = 1; /* the brightness factor */ MaskColor[0] = MaskColor[1] = MaskColor[2] = 0.3; ApplyClip = NOPE; ApplyPercClip = NOPE; ApplyMask = NOPE; NoMaskCol = NOPE; MaskZero = NOPE; setMaskCol = NOPE; Vopt = NOPE; iVopt = NOPE; inopt = NOPE; MapType = SUMA_CMAP_RGYBR20; brk = NOPE; MapSpecified = NOPE; CmapFileName = NULL; interpmode = SUMA_UNDEFINED_MODE; ShowMap = NOPE; alaAFNI = NOPE; /* applying the alaAFNI mapping */ frf = NOPE; arange = -1.0; /* afni range specified */ Sgn = 0; ShowMapdb = NOPE; while (kar < argc) { /* loop accross command ine options */ /*fprintf(stdout, "%s verbose: Parsing command line...\n", FuncName);*/ if (strcmp(argv[kar], "-h") == 0 || strcmp(argv[kar], "-help") == 0) { SUMA_ScaleToMap_usage(); exit (1); } SUMA_SKIP_COMMON_OPTIONS(brk, kar); if (!brk && strcmp(argv[kar], "-verb") == 0) { LocalHead = NOPE; brk = YUP; } if (!brk && strcmp(argv[kar], "-ionot") == 0) { SUMA_SL_Err("-ionot is obsolete. \n" "Use -trace option."); exit (1); SUMA_INOUT_NOTIFY_ON; brk = YUP; } if (!brk && strcmp(argv[kar], "-msk_zero") == 0) { MaskZero = YUP; brk = YUP; } if (!brk && (strcmp(argv[kar], "-input") == 0)) { kar ++; if (kar+2 >= argc) { fprintf (SUMA_STDERR, "need 3 arguments after -input \n"); exit (1); } IntName = argv[kar]; kar ++; icol = atoi(argv[kar]); kar ++; vcol = atoi(argv[kar]); inopt = YUP; brk = YUP; } if (!brk && (strcmp(argv[kar], "-apr") == 0)) { if (arange >= 0) { fprintf (SUMA_STDERR, "range has already been specified.\n"); exit (1); } kar ++; if (kar >= argc) { fprintf (SUMA_STDERR, "need argument after -apr \n"); exit (1); } arange = atof(argv[kar]); if (arange < 0) { fprintf (SUMA_STDERR, "range must be positive.\n"); exit (1); } Sgn = 1; alaAFNI = YUP; brk = YUP; } if (!brk && (strcmp(argv[kar], "-anr") == 0)) { if (arange >= 0) { fprintf (SUMA_STDERR, "range has already been specified.\n"); exit (1); } kar ++; if (kar >= argc) { fprintf (SUMA_STDERR, "need argument after -anr \n"); exit (1); } arange = atof(argv[kar]); if (arange < 0) { fprintf (SUMA_STDERR, "range must be positive.\n"); exit (1); } Sgn = -1; alaAFNI = YUP; brk = YUP; } if (!brk && (strcmp(argv[kar], "-v") == 0)) { fprintf (SUMA_STDERR, "\n -v option is now obsolete.\nUse -input option instead.\n"); exit (1); kar ++; if (kar >= argc) { fprintf (SUMA_STDERR, "need argument after -v \n"); exit (1); } IntName = argv[kar]; Vopt = YUP; brk = YUP; } if (!brk && (strcmp(argv[kar], "-iv") == 0)) { fprintf (SUMA_STDERR, "\n -iv option is now obsolete.\nUse -input option instead.\n"); exit (1); kar ++; if (kar >= argc) { fprintf (SUMA_STDERR, "need argument after -iv \n"); exit (1); } IntName = argv[kar]; iVopt = YUP; brk = YUP; } if (!brk && (strcmp(argv[kar], "-br") == 0)) { kar ++; if (kar >= argc) { fprintf (SUMA_STDERR, "need argument after -br \n"); exit (1); } brfact = atof(argv[kar]); brk = YUP; } if (!brk && (strcmp(argv[kar], "-frf") == 0)) { frf = YUP; brk = YUP; } if (!brk && (strcmp(argv[kar], "-showmap") == 0)) { ShowMap = YUP; brk = YUP; } if (!brk && (strcmp(argv[kar], "-showdb") == 0)) { ShowMapdb = YUP; brk = YUP; } if (!brk && (strcmp(argv[kar], "-nointerp") == 0)) { if (interpmode != SUMA_UNDEFINED_MODE) { fprintf (SUMA_STDERR, "Color interpolation mode already set.\n"); } interpmode = SUMA_NO_INTERP; brk = YUP; } if (!brk && (strcmp(argv[kar], "-direct") == 0)) { if (interpmode != SUMA_UNDEFINED_MODE) { fprintf (SUMA_STDERR, "Color interpolation mode already set.\n"); } interpmode = SUMA_DIRECT; brk = YUP; } if (!brk && (strcmp(argv[kar], "-interp") == 0)) { if (interpmode != SUMA_UNDEFINED_MODE) { fprintf (SUMA_STDERR, "Color interpolation mode already set.\n(-nointerp, -direct and -interp are mutually exclusive.\n"); } interpmode = SUMA_INTERP; brk = YUP; } if (!brk && (strcmp(argv[kar], "-clp") == 0)) { kar ++; if (kar+1 >= argc) { fprintf (SUMA_STDERR, "need 2 arguments after -clp \n"); exit (1); } ApplyClip = YUP; IntRange[0] = atof(argv[kar]); kar ++; IntRange[1] = atof(argv[kar]); brk = YUP; } if (!brk && (strcmp(argv[kar], "-perc_clp") == 0)) { kar ++; if (kar+1 >= argc) { fprintf (SUMA_STDERR, "need 2 arguments after -perc_clp "); exit (1); } ApplyPercClip = YUP; IntRange[0] = atof(argv[kar]); kar ++; IntRange[1] = atof(argv[kar]); brk = YUP; } if (!brk && (strcmp(argv[kar], "-msk") == 0)) { kar ++; if (kar+1 >= argc) { fprintf (SUMA_STDERR, "need 2 arguments after -msk "); exit (1); } ApplyMask = YUP; MaskRange[0] = atof(argv[kar]); kar ++; MaskRange[1] = atof(argv[kar]); brk = YUP; } if (!brk && (strcmp(argv[kar], "-nomsk_col") == 0)) { NoMaskCol = YUP; brk = YUP; } if (!brk && (strcmp(argv[kar], "-msk_col") == 0)) { kar ++; if (kar+2 >= argc) { fprintf (SUMA_STDERR, "need 3 arguments after -msk_col "); exit (1); } setMaskCol = YUP; MaskColor[0] = atof(argv[kar]); kar ++; MaskColor[1] = atof(argv[kar]); kar ++; MaskColor[2] = atof(argv[kar]); brk = YUP; } if (!brk && (strcmp(argv[kar], "-cmapfile") ==0)) { if (MapSpecified) { fprintf (SUMA_STDERR, "Color map already specified.\n-cmap and -cmapfile are mutually exclusive\n"); exit (1); } MapSpecified = YUP; kar ++; if (kar >= argc) { fprintf (SUMA_STDERR, "need 1 arguments after -cmapfile "); exit (1); } CmapFileName = argv[kar]; brk = YUP; } if (!brk && (strcmp(argv[kar], "-cmapdb") ==0)) { kar ++; if (kar >= argc) { fprintf (SUMA_STDERR, "need 1 arguments after -cmapdb "); exit (1); } dbfile = argv[kar]; brk = YUP; } if (!brk && (strcmp(argv[kar], "-cmap") ==0)) { if (MapSpecified) { fprintf (SUMA_STDERR, "Color map already specified.\n-cmap and -cmapfile are mutually exclusive\n"); exit (1); } MapSpecified = YUP; kar ++; if (kar >= argc) { fprintf (SUMA_STDERR, "need 1 arguments after -cmap "); exit (1); } MapName = argv[kar]; brk = YUP; } if (!brk) { fprintf (SUMA_STDERR,"Error %s: Option %s not understood. Try -help for usage\n", FuncName, argv[kar]); exit (1); } else { brk = NOPE; kar ++; } }/* loop accross command ine options */ /* Get your colors straightened out */ if (!SUMAg_CF->scm) { SUMAg_CF->scm = SUMA_Build_Color_maps(); if (!SUMAg_CF->scm) { SUMA_SL_Err("Failed to build color maps.\n"); exit(1); } } SAC = SUMAg_CF->scm; /* are there database files to read */ if (dbfile) { SUMA_LH("Now trying to read db file"); if (SUMA_AFNI_Extract_Colors ( dbfile, SAC ) < 0) { SUMA_S_Errv("Failed to read %s colormap file.\n", dbfile); exit(1); } } FromAFNI = NOPE; /* assume colormap is not coming from SAC (the colormap database structure) */ if (CmapFileName) { /* load the color map */ CM = SUMA_Read_Color_Map_1D (CmapFileName); if (CM == NULL) { SUMA_S_Err("Could not load colormap.\n"); exit (1); } if (frf) { SUMA_LH("Flipping colormap"); SUMA_Flip_Color_Map (CM); } if (!CM->Sgn) CM->Sgn = Sgn; }else{ /* dunno what kind of map yet. Try default first */ if (MapName) { CM = SUMA_FindNamedColMap (MapName); freecm = 0; if (CM) { /* good, sign it and out you go */ CM->Sgn = Sgn; } else { SUMA_S_Err("Could not get standard colormap.\n"); exit (1); } } else { SUMA_LH("An AFNI color map "); /* a color from AFNI's maps */ FromAFNI = YUP; imap = SUMA_Find_ColorMap ( MapName, SAC->CMv, SAC->N_maps, -2); if (imap < 0) { SUMA_S_Errv("Could not find colormap %s.\n", MapName); exit (1); } CM = SAC->CMv[imap]; } } /* show the colromap on STDERR */ if (ShowMap) { fprintf (SUMA_STDERR, "%s: Colormap used:\n", FuncName); SUMA_Show_ColorMapVec (&CM, 1, NULL, 2); { SUMA_SurfaceObject *SO = NULL; float orig[3] = { SUMA_CMAP_ORIGIN }; float topright[3] = { SUMA_CMAP_TOPLEFT }; SO = SUMA_Cmap_To_SO (CM, orig, topright, 2); if (SO) SUMA_Free_Surface_Object(SO); } exit(0); } /* show all the colors and colormaps in SAC on STDERR */ if (ShowMapdb) { fprintf (SUMA_STDERR, "%s: AFNI colormaps found in db:\n", FuncName); SUMA_Show_ColorVec (SAC->Cv, SAC->N_cols, NULL); SUMA_Show_ColorMapVec (SAC->CMv, SAC->N_maps, NULL, 2); exit(0); } if (!IntName) { fprintf (SUMA_STDERR,"Error %s: No input file specified.\n", FuncName); exit(1); } /* default interpolation mode */ if (interpmode == SUMA_UNDEFINED_MODE) interpmode = SUMA_INTERP; /* check input */ if (!SUMA_filexists (IntName)) { fprintf (SUMA_STDERR,"Error %s: File %s could not be found.\n", FuncName, IntName); exit(1); } if (frf && !CmapFileName) { fprintf (SUMA_STDERR,"Error %s: -frf option is only valid with -cmapfile.\n", FuncName); exit(1); } if (ApplyPercClip && ApplyClip) { fprintf (SUMA_STDERR,"Error %s: Simultaneous use of -clp and -perc_clp. You should be punished.\n", FuncName); exit(1); } if ((ApplyPercClip || ApplyClip) && arange >= 0.0) { fprintf (SUMA_STDERR,"Error %s: Simultaneous use of -clp/-perc_clp and -apr/anr.\n Read the help.\n", FuncName); exit(1); } if (iVopt || Vopt) { fprintf (SUMA_STDERR,"Error %s: -v and -iv are obsolete.\n Use -input option instead.\n", FuncName); exit(1); } if (!inopt) { fprintf (SUMA_STDERR,"Error %s: -input option must be specified.\n", FuncName); exit(1); } im = mri_read_1D (IntName); if (!im) { SUMA_S_Err("Failed to read file"); exit (1); } if (vcol < 0) { fprintf (SUMA_STDERR,"Error %s: vcol must be > 0\n", FuncName); exit(1); } far = MRI_FLOAT_PTR(im); if (icol < 0 && icol != -1) { fprintf (SUMA_STDERR,"Error %s: icol(%d) can only have -1 for a negative value\n", FuncName, icol); exit(1); } if (icol >= im->ny || vcol >= im->ny) { fprintf (SUMA_STDERR,"Error %s: icol(%d) and vcol(%d) must be < %d\nwhich is the number of columns in %s\n", FuncName, icol, vcol, im->ny, IntName); exit(1); } if (brfact <=0 || brfact > 1) { fprintf (SUMA_STDERR,"Error %s: BrightFact must be > 0 and <= 1.\n", FuncName); exit (1); } if (MaskColor[0] < 0 || MaskColor[0] > 1 || MaskColor[1] < 0 || MaskColor[1] > 1 || MaskColor[2] < 0 || MaskColor[2] > 1) { fprintf (SUMA_STDERR,"Error %s: MaskColor values must be >=0 <=1.\n", FuncName); exit(1); } N_V = im->nx; V = (float *) SUMA_calloc (N_V, sizeof(float)); iV = (int *) SUMA_calloc (N_V, sizeof(int)); if (!V || !iV) { fprintf (SUMA_STDERR,"Error %s: Could not allocate for V or iV.\n", FuncName); exit(1); } if (icol < 0) { for (ii=0; ii < N_V; ++ii) { iV[ii] = ii; V[ii] = far[vcol*N_V+ii]; } } else { for (ii=0; ii < N_V; ++ii) { iV[ii] = (int)far[icol*N_V+ii]; V[ii] = far[vcol*N_V+ii]; } } mri_free(im); im = NULL; /* read values per node */ /* SUMA_disp_vect (V, 3); */ /* find the min/max of V */ SUMA_MIN_MAX_VEC(V, N_V, Vmin, Vmax, Vminloc, Vmaxloc) /* fprintf (SUMA_STDERR,"%s: Vmin=%f, Vmax = %f\n", FuncName, Vmin, Vmax);*/ if (arange == 0.0) { if (fabs((double)Vmin) > fabs((double)Vmax)) arange = (float)fabs((double)Vmin); else arange = (float)fabs((double)Vmax); } /* figure out the range if PercRange is used */ if (ApplyPercClip) { fprintf (SUMA_STDERR,"%s: Percentile range [%f..%f] is equivalent to ", FuncName, IntRange[0], IntRange[1]); Vsort = SUMA_PercRange (V, NULL, N_V, IntRange, IntRange, NULL); fprintf (SUMA_STDERR,"[%f..%f]\n", IntRange[0], IntRange[1]); ApplyClip = YUP; if (Vsort) SUMA_free(Vsort); else { fprintf (SUMA_STDERR,"Error %s: Error in SUMA_PercRange.\n", FuncName); exit(1); } } /* get the options for creating the scaled color mapping */ OptScl = SUMA_ScaleToMapOptInit(); if (!OptScl) { fprintf (SUMA_STDERR, "Error %s: Could not get scaling option structure.\n", FuncName); exit (1); } /* work the options a bit */ if (ApplyMask) { OptScl->ApplyMask = ApplyMask; OptScl->MaskRange[0] = MaskRange[0]; OptScl->MaskRange[1] = MaskRange[1]; OptScl->MaskColor[0] = MaskColor[0]; OptScl->MaskColor[1] = MaskColor[1]; OptScl->MaskColor[2] = MaskColor[2]; } if (ApplyClip) { OptScl->ApplyClip = YUP; OptScl->IntRange[0] = IntRange[0]; OptScl->IntRange[1] = IntRange[1]; } OptScl->interpmode = interpmode; OptScl->BrightFact = brfact; if (MaskZero) OptScl->MaskZero = YUP; /* map the values in V to the colormap */ /* allocate space for the result */ SV = SUMA_Create_ColorScaledVect(N_V, 0); if (!SV) { fprintf (SUMA_STDERR, "Error %s: Could not allocate for SV.\n", FuncName); exit(1); } /* finally ! */ if (alaAFNI) { if (LocalHead) { fprintf (SUMA_STDERR, "%s: Calling SUMA_ScaleToMap_alaAFNI\n", FuncName); fprintf (SUMA_STDERR,"%s: arange = %f\n", FuncName, arange); } if (CM->frac) { if (CM->frac[0] > 0 && CM->Sgn == -1) { SUMA_S_Err ("Color map fractions positive with -anr option"); exit(1); } if (CM->frac[0] < 0 && CM->Sgn == 1) { SUMA_S_Err ("Color map fractions negative with -apr option"); exit(1); } } if (Sgn) { if (Sgn != CM->Sgn) { SUMA_S_Warn ("Mixing positive maps (all fractions > 0) " "with -anr option\n" "or vice versa. That is allowed but know what" " you're doing.\n"); } } if (!SUMA_ScaleToMap_alaAFNI (V, N_V, arange, CM, OptScl, SV)) { fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_ScaleToMap_alaAFNI.\n", FuncName); exit(1); } } else { if (LocalHead) fprintf (SUMA_STDERR,"%s: Calling SUMA_ScaleToMap\n", FuncName); if (!SUMA_ScaleToMap (V, N_V, Vmin, Vmax, CM, OptScl, SV)) { fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_ScaleToMap.\n", FuncName); exit(1); } } /* Now write the colored vector back to disk */ if (NoMaskCol) { for (k=0; k < N_V; ++k) { k3 = 3*k; if (!SV->isMasked[k]) fprintf (SUMA_STDOUT, "%d %f %f %f\n", iV[k], SV->cV[k3 ], SV->cV[k3+1], SV->cV[k3+2]); } } else { for (k=0; k < N_V; ++k) { k3 = 3*k; fprintf (SUMA_STDOUT, "%d %f %f %f\n", iV[k], SV->cV[k3 ], SV->cV[k3+1], SV->cV[k3+2]); } } /* freeing time */ if (V) SUMA_free(V); if (iV) SUMA_free(iV); if (!FromAFNI && freecm) if (CM) SUMA_Free_ColorMap (CM); /* only free CM if it was a pointer copy from a map in SAC */ if (OptScl) SUMA_free(OptScl); if (SV) SUMA_Free_ColorScaledVect (SV); #if 0 if (SAC) SAC = SUMA_DestroyAfniColors(SAC); /* destroy SAC */ #else SAC = NULL; /* freeing is done in SUMAg_CF */ #endif SUMA_Free_CommonFields(SUMAg_CF); SUMA_RETURN (0); }
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"); }
/* get and read rate file, and get computational time delta */ int get_init_data( float ** rtime, float ** rates, int * len, float * dt ) { MRI_IMAGE * im; char * rate_file; char * dt_text; if( !rtime || !rates || !len || !dt ) { fprintf(stderr,"** get_init_data: bad params %p,%p,%p,%p\n", rtime, rates, len, dt); return 1; } /* get rate file name, and then try to read it */ rate_file = my_getenv("AFNI_MM_MODEL_RATE_FILE"); if( !rate_file ) { fprintf(stderr,"\n** NLfim: need env var AFNI_MM_MODEL_RATE_FILE\n"); fprintf(stderr," (might also want AFNI_MM_MODEL_DT)\n"); return 1; } im = mri_read_1D(rate_file); if( !im ) { fprintf(stderr,"** failed to open rate file %s\n",rate_file); return 1; } /* set the pointers and let the image dangle... rates is second row */ /* (should add cleanup function to MODEL_interface...) */ *rtime = MRI_FLOAT_PTR(im); *rates = *rtime + im->nx; *len = im->nx; /* check to see if the rate times are in seconds */ dt_text = my_getenv("AFNI_MM_MODEL_RATE_IN_SECS"); if( dt_text && (*dt_text == 'y' || *dt_text == 'Y') ) { int c; fprintf(stderr,"NLfim: rate times are taken in seconds\n"); /* so convert to minutes */ for( c = 0; c < *len; c++ ) (*rtime)[c] /= 60.0; } /* get dt from another env var */ dt_text = my_getenv("AFNI_MM_MODEL_DT"); if( dt_text ) *dt = atof(dt_text); else /* if user did not provide it... */ { fprintf(stderr,"NLfim: MM: using default dt of %.3f s\n", NL_MM_DEF_DT); fprintf(stderr," (use env var AFNI_MM_MODEL_DT to override)\n"); *dt = NL_MM_DEF_DT; } /* get debug level (abuse now unneeded dt_text variable) */ dt_text = my_getenv("AFNI_MM_MODEL_DEBUG"); if( dt_text ) debug = atoi( dt_text ); if( dt_text && debug ) { int c; fprintf(stderr,"+d NLfim: debug level set to %d\n", debug); fprintf(stderr," dt = %f, rate file = %s\n", *dt, rate_file); if( debug > 1 ) { fprintf(stderr," time rate\n -------- --------\n"); for( c = 0; c < *len; c++ ) fprintf(stderr, " %8f %8f\n", (*rtime)[c], (*rates)[c]); } } return 0; }
int main( int argc , char * argv[] ) { int do_norm=0 , qdet=2 , have_freq=0 , do_automask=0 ; float dt=0.0f , fbot=0.0f,ftop=999999.9f , blur=0.0f ; MRI_IMARR *ortar=NULL ; MRI_IMAGE *ortim=NULL ; THD_3dim_dataset **ortset=NULL ; int nortset=0 ; THD_3dim_dataset *inset=NULL , *outset=NULL; char *prefix="RSFC" ; byte *mask=NULL ; int mask_nx=0,mask_ny=0,mask_nz=0,nmask , verb=1 , nx,ny,nz,nvox , nfft=0 , kk ; float **vec , **ort=NULL ; int nort=0 , vv , nopt , ntime ; MRI_vectim *mrv ; float pvrad=0.0f ; int nosat=0 ; int do_despike=0 ; // @@ non-BP variables float fbotALL=0.0f, ftopALL=999999.9f; // do full range version int NumDen = 0; // switch for doing numerator or denom THD_3dim_dataset *outsetALL=NULL ; int m, mm; float delf; // harmonics int ind_low,ind_high,N_ny, ctr; float sqnt,nt_fac; gsl_fft_real_wavetable *real1, *real2; // GSL stuff gsl_fft_real_workspace *work; double *series1, *series2; double *xx1,*xx2; float numer,denom,val; float *alff=NULL,*malff=NULL,*falff=NULL, *rsfa=NULL,*mrsfa=NULL,*frsfa=NULL; // values float meanALFF=0.0f,meanRSFA=0.0f; // will be for mean in brain region THD_3dim_dataset *outsetALFF=NULL; THD_3dim_dataset *outsetmALFF=NULL; THD_3dim_dataset *outsetfALFF=NULL; THD_3dim_dataset *outsetRSFA=NULL; THD_3dim_dataset *outsetmRSFA=NULL; THD_3dim_dataset *outsetfRSFA=NULL; char out_lff[300]; char out_alff[300]; char out_malff[300]; char out_falff[300]; char out_rsfa[300]; char out_mrsfa[300]; char out_frsfa[300]; char out_unBP[300]; int SERIES_OUT = 1; int UNBP_OUT = 0; int DO_RSFA = 1; int BP_LAST = 0; // option for only doing filter to LFFs at very end of proc float de_rsfa=0.0f,nu_rsfa=0.0f; double pow1=0.0,pow2=0.0; /*-- help? --*/ if( argc < 2 || strcmp(argv[1],"-help") == 0 ){ printf( "\n Program to calculate common resting state functional connectivity (RSFC)\n" " parameters (ALFF, mALFF, fALFF, RSFA, etc.) for resting state time\n" " series. This program is **heavily** based on the existing\n" " 3dBandPass by RW Cox, with the amendments to calculate RSFC\n" " parameters written by PA Taylor (July, 2012).\n" " This program is part of FATCAT (Taylor & Saad, 2013) in AFNI. Importantly,\n" " its functionality can be included in the `afni_proc.py' processing-script \n" " generator; see that program's help file for an example including RSFC\n" " and spectral parameter calculation via the `-regress_RSFC' option.\n" "\n" "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n" "\n" " All options of 3dBandPass may be used here (with a couple other\n" " parameter options, as well): essentially, the motivation of this\n" " program is to produce ALFF, etc. values of the actual RSFC time\n" " series that you calculate. Therefore, all the 3dBandPass processing\n" " you normally do en route to making your final `resting state time\n" " series' is done here to generate your LFFs, from which the\n" " amplitudes in the LFF band are calculated at the end. In order to\n" " calculate fALFF, the same initial time series are put through the\n" " same processing steps which you have chosen but *without* the\n" " bandpass part; the spectrum of this second time series is used to\n" " calculate the fALFF denominator.\n" " \n" " For more information about each RSFC parameter, see, e.g.: \n" " ALFF/mALFF -- Zang et al. (2007),\n" " fALFF -- Zou et al. (2008),\n" " RSFA -- Kannurpatti & Biswal (2008).\n" "\n" "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n" "\n" " + USAGE: 3dRSFC [options] fbot ftop dataset\n" "\n" "* One function of this program is to prepare datasets for input\n" " to 3dSetupGroupInCorr. Other uses are left to your imagination.\n" "\n" "* 'dataset' is a 3D+time sequence of volumes\n" " ++ This must be a single imaging run -- that is, no discontinuities\n" " in time from 3dTcat-ing multiple datasets together.\n" "\n" "* fbot = lowest frequency in the passband, in Hz\n" " ++ fbot can be 0 if you want to do a lowpass filter only;\n" " HOWEVER, the mean and Nyquist freq are always removed.\n" "\n" "* ftop = highest frequency in the passband (must be > fbot)\n" " ++ if ftop > Nyquist freq, then it's a highpass filter only.\n" "\n" "* Set fbot=0 and ftop=99999 to do an 'allpass' filter.\n" " ++ Except for removal of the 0 and Nyquist frequencies, that is.\n" "\n" "* You cannot construct a 'notch' filter with this program!\n" " ++ You could use 3dRSFC followed by 3dcalc to get the same effect.\n" " ++ If you are understand what you are doing, that is.\n" " ++ Of course, that is the AFNI way -- if you don't want to\n" " understand what you are doing, use Some other PrograM, and\n" " you can still get Fine StatisticaL maps.\n" "\n" "* 3dRSFC will fail if fbot and ftop are too close for comfort.\n" " ++ Which means closer than one frequency grid step df,\n" " where df = 1 / (nfft * dt) [of course]\n" "\n" "* The actual FFT length used will be printed, and may be larger\n" " than the input time series length for the sake of efficiency.\n" " ++ The program will use a power-of-2, possibly multiplied by\n" " a power of 3 and/or 5 (up to and including the 3rd power of\n" " each of these: 3, 9, 27, and 5, 25, 125).\n" "\n" "* Note that the results of combining 3dDetrend and 3dRSFC will\n" " depend on the order in which you run these programs. That's why\n" " 3dRSFC has the '-ort' and '-dsort' options, so that the\n" " time series filtering can be done properly, in one place.\n" "\n" "* The output dataset is stored in float format.\n" "\n" "* The order of processing steps is the following (most are optional), and\n" " for the LFFs, the bandpass is done between the specified fbot and ftop,\n" " while for the `whole spectrum' (i.e., fALFF denominator) the bandpass is:\n" " done only to exclude the time series mean and the Nyquist frequency:\n" " (0) Check time series for initial transients [does not alter data]\n" " (1) Despiking of each time series\n" " (2) Removal of a constant+linear+quadratic trend in each time series\n" " (3) Bandpass of data time series\n" " (4) Bandpass of -ort time series, then detrending of data\n" " with respect to the -ort time series\n" " (5) Bandpass and de-orting of the -dsort dataset,\n" " then detrending of the data with respect to -dsort\n" " (6) Blurring inside the mask [might be slow]\n" " (7) Local PV calculation [WILL be slow!]\n" " (8) L2 normalization [will be fast.]\n" " (9) Calculate spectrum and amplitudes, for RSFC parameters.\n" "\n" "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n" "--------\n" "OPTIONS:\n" "--------\n" " -despike = Despike each time series before other processing.\n" " ++ Hopefully, you don't actually need to do this,\n" " which is why it is optional.\n" " -ort f.1D = Also orthogonalize input to columns in f.1D\n" " ++ Multiple '-ort' options are allowed.\n" " -dsort fset = Orthogonalize each voxel to the corresponding\n" " voxel time series in dataset 'fset', which must\n" " have the same spatial and temporal grid structure\n" " as the main input dataset.\n" " ++ At present, only one '-dsort' option is allowed.\n" " -nodetrend = Skip the quadratic detrending of the input that\n" " occurs before the FFT-based bandpassing.\n" " ++ You would only want to do this if the dataset\n" " had been detrended already in some other program.\n" " -dt dd = set time step to 'dd' sec [default=from dataset header]\n" " -nfft N = set the FFT length to 'N' [must be a legal value]\n" " -norm = Make all output time series have L2 norm = 1\n" " ++ i.e., sum of squares = 1\n" " -mask mset = Mask dataset\n" " -automask = Create a mask from the input dataset\n" " -blur fff = Blur (inside the mask only) with a filter\n" " width (FWHM) of 'fff' millimeters.\n" " -localPV rrr = Replace each vector by the local Principal Vector\n" " (AKA first singular vector) from a neighborhood\n" " of radius 'rrr' millimiters.\n" " ++ Note that the PV time series is L2 normalized.\n" " ++ This option is mostly for Bob Cox to have fun with.\n" "\n" " -input dataset = Alternative way to specify input dataset.\n" " -band fbot ftop = Alternative way to specify passband frequencies.\n" "\n" " -prefix ppp = Set prefix name of output dataset. Name of filtered time\n" " series would be, e.g., ppp_LFF+orig.*, and the parameter\n" " outputs are named with obvious suffices.\n" " -quiet = Turn off the fun and informative messages. (Why?)\n" " -no_rs_out = Don't output processed time series-- just output\n" " parameters (not recommended, since the point of\n" " calculating RSFC params here is to have them be quite\n" " related to the time series themselves which are used for\n" " further analysis)." " -un_bp_out = Output the un-bandpassed series as well (default is not \n" " to). Name would be, e.g., ppp_unBP+orig.* .\n" " with suffix `_unBP'.\n" " -no_rsfa = If you don't want RSFA output (default is to do so).\n" " -bp_at_end = A (probably unnecessary) switch to have bandpassing be \n" " the very last processing step that is done in the\n" " sequence of steps listed above; at Step 3 above, only \n" " the time series mean and nyquist are BP'ed out, and then\n" " the LFF series is created only after Step 9. NB: this \n" " probably makes only very small changes for most\n" " processing sequences (but maybe not, depending usage).\n" "\n" " -notrans = Don't check for initial positive transients in the data:\n" " *OR* ++ The test is a little slow, so skipping it is OK,\n" " -nosat if you KNOW the data time series are transient-free.\n" " ++ Or set AFNI_SKIP_SATCHECK to YES.\n" " ++ Initial transients won't be handled well by the\n" " bandpassing algorithm, and in addition may seriously\n" " contaminate any further processing, such as inter-\n" " voxel correlations via InstaCorr.\n" " ++ No other tests are made [yet] for non-stationary \n" " behavior in the time series data.\n" "\n" "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n" "\n" " If you use this program, please reference the introductory/description\n" " paper for the FATCAT toolbox:\n" " Taylor PA, Saad ZS (2013). FATCAT: (An Efficient) Functional\n" " And Tractographic Connectivity Analysis Toolbox. Brain \n" " Connectivity 3(5):523-535.\n" "____________________________________________________________________________\n" ); PRINT_AFNI_OMP_USAGE( " 3dRSFC" , " * At present, the only part of 3dRSFC that is parallelized is the\n" " '-blur' option, which processes each sub-brick independently.\n" ) ; PRINT_COMPILE_DATE ; exit(0) ; } /*-- startup --*/ mainENTRY("3dRSFC"); machdep(); AFNI_logger("3dRSFC",argc,argv); PRINT_VERSION("3dRSFC (from 3dBandpass by RW Cox): version THETA"); AUTHOR("PA Taylor"); nosat = AFNI_yesenv("AFNI_SKIP_SATCHECK") ; nopt = 1 ; while( nopt < argc && argv[nopt][0] == '-' ){ if( strcmp(argv[nopt],"-despike") == 0 ){ /* 08 Oct 2010 */ do_despike++ ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-nfft") == 0 ){ int nnup ; if( ++nopt >= argc ) ERROR_exit("need an argument after -nfft!") ; nfft = (int)strtod(argv[nopt],NULL) ; nnup = csfft_nextup_even(nfft) ; if( nfft < 16 || nfft != nnup ) ERROR_exit("value %d after -nfft is illegal! Next legal value = %d",nfft,nnup) ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-blur") == 0 ){ if( ++nopt >= argc ) ERROR_exit("need an argument after -blur!") ; blur = strtod(argv[nopt],NULL) ; if( blur <= 0.0f ) WARNING_message("non-positive blur?!") ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-localPV") == 0 ){ if( ++nopt >= argc ) ERROR_exit("need an argument after -localpv!") ; pvrad = strtod(argv[nopt],NULL) ; if( pvrad <= 0.0f ) WARNING_message("non-positive -localpv?!") ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-prefix") == 0 ){ if( ++nopt >= argc ) ERROR_exit("need an argument after -prefix!") ; prefix = strdup(argv[nopt]) ; if( !THD_filename_ok(prefix) ) ERROR_exit("bad -prefix option!") ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-automask") == 0 ){ if( mask != NULL ) ERROR_exit("Can't use -mask AND -automask!") ; do_automask = 1 ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-mask") == 0 ){ THD_3dim_dataset *mset ; if( ++nopt >= argc ) ERROR_exit("Need argument after '-mask'") ; if( mask != NULL || do_automask ) ERROR_exit("Can't have two mask inputs") ; mset = THD_open_dataset( argv[nopt] ) ; CHECK_OPEN_ERROR(mset,argv[nopt]) ; DSET_load(mset) ; CHECK_LOAD_ERROR(mset) ; mask_nx = DSET_NX(mset); mask_ny = DSET_NY(mset); mask_nz = DSET_NZ(mset); mask = THD_makemask( mset , 0 , 0.5f, 0.0f ) ; DSET_delete(mset) ; if( mask == NULL ) ERROR_exit("Can't make mask from dataset '%s'",argv[nopt]) ; nmask = THD_countmask( mask_nx*mask_ny*mask_nz , mask ) ; if( verb ) INFO_message("Number of voxels in mask = %d",nmask) ; if( nmask < 1 ) ERROR_exit("Mask is too small to process") ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-norm") == 0 ){ do_norm = 1 ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-quiet") == 0 ){ verb = 0 ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-no_rs_out") == 0 ){ // @@ SERIES_OUT = 0 ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-un_bp_out") == 0 ){ // @@ UNBP_OUT = 1 ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-no_rsfa") == 0 ){ // @@ DO_RSFA = 0 ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-bp_at_end") == 0 ){ // @@ BP_LAST = 1 ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-notrans") == 0 || strcmp(argv[nopt],"-nosat") == 0 ){ nosat = 1 ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-ort") == 0 ){ if( ++nopt >= argc ) ERROR_exit("need an argument after -ort!") ; if( ortar == NULL ) INIT_IMARR(ortar) ; ortim = mri_read_1D( argv[nopt] ) ; if( ortim == NULL ) ERROR_exit("can't read from -ort '%s'",argv[nopt]) ; mri_add_name(argv[nopt],ortim) ; ADDTO_IMARR(ortar,ortim) ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-dsort") == 0 ){ THD_3dim_dataset *qset ; if( ++nopt >= argc ) ERROR_exit("need an argument after -dsort!") ; if( nortset > 0 ) ERROR_exit("only 1 -dsort option is allowed!") ; qset = THD_open_dataset(argv[nopt]) ; CHECK_OPEN_ERROR(qset,argv[nopt]) ; ortset = (THD_3dim_dataset **)realloc(ortset, sizeof(THD_3dim_dataset *)*(nortset+1)) ; ortset[nortset++] = qset ; nopt++ ; continue ; } if( strncmp(argv[nopt],"-nodetrend",6) == 0 ){ qdet = 0 ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-dt") == 0 ){ if( ++nopt >= argc ) ERROR_exit("need an argument after -dt!") ; dt = (float)strtod(argv[nopt],NULL) ; if( dt <= 0.0f ) WARNING_message("value after -dt illegal!") ; nopt++ ; continue ; } if( strcmp(argv[nopt],"-input") == 0 ){ if( inset != NULL ) ERROR_exit("Can't have 2 -input options!") ; if( ++nopt >= argc ) ERROR_exit("need an argument after -input!") ; inset = THD_open_dataset(argv[nopt]) ; CHECK_OPEN_ERROR(inset,argv[nopt]) ; nopt++ ; continue ; } if( strncmp(argv[nopt],"-band",5) == 0 ){ if( ++nopt >= argc-1 ) ERROR_exit("need 2 arguments after -band!") ; if( have_freq ) WARNING_message("second -band option replaces first one!") ; fbot = strtod(argv[nopt++],NULL) ; ftop = strtod(argv[nopt++],NULL) ; have_freq = 1 ; continue ; } ERROR_exit("Unknown option: '%s'",argv[nopt]) ; } /** check inputs for reasonablositiness **/ if( !have_freq ){ if( nopt+1 >= argc ) ERROR_exit("Need frequencies on command line after options!") ; fbot = (float)strtod(argv[nopt++],NULL) ; ftop = (float)strtod(argv[nopt++],NULL) ; } if( inset == NULL ){ if( nopt >= argc ) ERROR_exit("Need input dataset name on command line after options!") ; inset = THD_open_dataset(argv[nopt]) ; CHECK_OPEN_ERROR(inset,argv[nopt]) ; nopt++ ; } DSET_UNMSEC(inset) ; if( fbot < 0.0f ) ERROR_exit("fbot value can't be negative!") ; if( ftop <= fbot ) ERROR_exit("ftop value %g must be greater than fbot value %g!",ftop,fbot) ; ntime = DSET_NVALS(inset) ; if( ntime < 9 ) ERROR_exit("Input dataset is too short!") ; if( nfft <= 0 ){ nfft = csfft_nextup_even(ntime) ; if( verb ) INFO_message("Data length = %d FFT length = %d",ntime,nfft) ; (void)THD_bandpass_set_nfft(nfft) ; } else if( nfft < ntime ){ ERROR_exit("-nfft %d is less than data length = %d",nfft,ntime) ; } else { kk = THD_bandpass_set_nfft(nfft) ; if( kk != nfft && verb ) INFO_message("Data length = %d FFT length = %d",ntime,kk) ; } if( dt <= 0.0f ){ dt = DSET_TR(inset) ; if( dt <= 0.0f ){ WARNING_message("Setting dt=1.0 since input dataset lacks a time axis!") ; dt = 1.0f ; } } ftopALL = 1./dt ;// Aug,2016: should solve problem of a too-large // value for THD_bandpass_vectors(), while still // being >f_{Nyquist} if( !THD_bandpass_OK(ntime,dt,fbot,ftop,1) ) ERROR_exit("Can't continue!") ; nx = DSET_NX(inset); ny = DSET_NY(inset); nz = DSET_NZ(inset); nvox = nx*ny*nz; /* check mask, or create it */ if( verb ) INFO_message("Loading input dataset time series" ) ; DSET_load(inset) ; if( mask != NULL ){ if( mask_nx != nx || mask_ny != ny || mask_nz != nz ) ERROR_exit("-mask dataset grid doesn't match input dataset") ; } else if( do_automask ){ mask = THD_automask( inset ) ; if( mask == NULL ) ERROR_message("Can't create -automask from input dataset?") ; nmask = THD_countmask( DSET_NVOX(inset) , mask ) ; if( verb ) INFO_message("Number of voxels in automask = %d",nmask); if( nmask < 1 ) ERROR_exit("Automask is too small to process") ; } else { mask = (byte *)malloc(sizeof(byte)*nvox) ; nmask = nvox ; memset(mask,1,sizeof(byte)*nvox) ; // if( verb ) // @@ alert if aaaalllllll vox are going to be analyzed! INFO_message("No mask ==> processing all %d voxels",nvox); } /* A simple check of dataset quality [08 Feb 2010] */ if( !nosat ){ float val ; INFO_message( "Checking dataset for initial transients [use '-notrans' to skip this test]") ; val = THD_saturation_check(inset,mask,0,0) ; kk = (int)(val+0.54321f) ; if( kk > 0 ) ININFO_message( "Looks like there %s %d non-steady-state initial time point%s :-(" , ((kk==1) ? "is" : "are") , kk , ((kk==1) ? " " : "s") ) ; else if( val > 0.3210f ) /* don't ask where this threshold comes from! */ ININFO_message( "MAYBE there's an initial positive transient of 1 point, but it's hard to tell\n") ; else ININFO_message("No widespread initial positive transient detected :-)") ; } /* check -dsort inputs for match to inset */ for( kk=0 ; kk < nortset ; kk++ ){ if( DSET_NX(ortset[kk]) != nx || DSET_NY(ortset[kk]) != ny || DSET_NZ(ortset[kk]) != nz || DSET_NVALS(ortset[kk]) != ntime ) ERROR_exit("-dsort %s doesn't match input dataset grid" , DSET_BRIKNAME(ortset[kk]) ) ; } /* convert input dataset to a vectim, which is more fun */ // @@ convert BP'ing ftop/bot into indices for the DFT (below) delf = 1.0/(ntime*dt); ind_low = (int) rint(fbot/delf); ind_high = (int) rint(ftop/delf); if( ntime % 2 ) // nyquist number N_ny = (ntime-1)/2; else N_ny = ntime/2; sqnt = sqrt(ntime); nt_fac = sqrt(ntime*(ntime-1)); // @@ if BP_LAST==0: // now we go through twice, doing LFF bandpass for NumDen==0 and // `full spectrum' processing for NumDen==1. // if BP_LAST==1: // now we go through once, doing only `full spectrum' processing for( NumDen=0 ; NumDen<2 ; NumDen++) { //if( NumDen==1 ){ // full spectrum // fbot = fbotALL; // ftop = ftopALL; //} // essentially, just doesn't BP here, and the perfect filtering at end // is used for both still; this makes the final output spectrum // contain only frequencies in range of 0.01-0.08 if( BP_LAST==1 ) INFO_message("Only doing filtering to LFFs at end!"); mrv = THD_dset_to_vectim( inset , mask , 0 ) ; if( mrv == NULL ) ERROR_exit("Can't load time series data!?") ; if( NumDen==1 ) DSET_unload(inset) ; // @@ only unload on 2nd pass /* similarly for the ort vectors */ if( ortar != NULL ){ for( kk=0 ; kk < IMARR_COUNT(ortar) ; kk++ ){ ortim = IMARR_SUBIM(ortar,kk) ; if( ortim->nx < ntime ) ERROR_exit("-ort file %s is shorter than input dataset time series", ortim->name ) ; ort = (float **)realloc( ort , sizeof(float *)*(nort+ortim->ny) ) ; for( vv=0 ; vv < ortim->ny ; vv++ ) ort[nort++] = MRI_FLOAT_PTR(ortim) + ortim->nx * vv ; } } /* all the real work now */ if( do_despike ){ int_pair nsp ; if( verb ) INFO_message("Testing data time series for spikes") ; nsp = THD_vectim_despike9( mrv ) ; if( verb ) ININFO_message(" -- Squashed %d spikes from %d voxels",nsp.j,nsp.i) ; } if( verb ) INFO_message("Bandpassing data time series") ; if( (BP_LAST==0) && (NumDen==0) ) (void)THD_bandpass_vectim( mrv , dt,fbot,ftop , qdet , nort,ort ) ; else (void)THD_bandpass_vectim( mrv , dt,fbotALL,ftopALL, qdet,nort,ort ) ; /* OK, maybe a little more work */ if( nortset == 1 ){ MRI_vectim *orv ; orv = THD_dset_to_vectim( ortset[0] , mask , 0 ) ; if( orv == NULL ){ ERROR_message("Can't load -dsort %s",DSET_BRIKNAME(ortset[0])) ; } else { float *dp , *mvv , *ovv , ff ; if( verb ) INFO_message("Orthogonalizing to bandpassed -dsort") ; //(void)THD_bandpass_vectim( orv , dt,fbot,ftop , qdet , nort,ort ) ; //@@ if( (BP_LAST==0) && (NumDen==0) ) (void)THD_bandpass_vectim(orv,dt,fbot,ftop,qdet,nort,ort); else (void)THD_bandpass_vectim(orv,dt,fbotALL,ftopALL,qdet,nort,ort); THD_vectim_normalize( orv ) ; dp = malloc(sizeof(float)*mrv->nvec) ; THD_vectim_vectim_dot( mrv , orv , dp ) ; for( vv=0 ; vv < mrv->nvec ; vv++ ){ ff = dp[vv] ; if( ff != 0.0f ){ mvv = VECTIM_PTR(mrv,vv) ; ovv = VECTIM_PTR(orv,vv) ; for( kk=0 ; kk < ntime ; kk++ ) mvv[kk] -= ff*ovv[kk] ; } } VECTIM_destroy(orv) ; free(dp) ; } } if( blur > 0.0f ){ if( verb ) INFO_message("Blurring time series data spatially; FWHM=%.2f",blur) ; mri_blur3D_vectim( mrv , blur ) ; } if( pvrad > 0.0f ){ if( verb ) INFO_message("Local PV-ing time series data spatially; radius=%.2f",pvrad) ; THD_vectim_normalize( mrv ) ; THD_vectim_localpv( mrv , pvrad ) ; } if( do_norm && pvrad <= 0.0f ){ if( verb ) INFO_message("L2 normalizing time series data") ; THD_vectim_normalize( mrv ) ; } /* create output dataset, populate it, write it, then quit */ if( (NumDen==0) ) { // @@ BP'ed version; will do filt if BP_LAST if(BP_LAST) // do bandpass here for BP_LAST (void)THD_bandpass_vectim(mrv,dt,fbot,ftop,qdet,0,NULL); if( verb ) INFO_message("Creating output dataset in memory, then writing it") ; outset = EDIT_empty_copy(inset) ; if(SERIES_OUT){ sprintf(out_lff,"%s_LFF",prefix); EDIT_dset_items( outset , ADN_prefix,out_lff , ADN_none ) ; tross_Copy_History( inset , outset ) ; tross_Make_History( "3dBandpass" , argc,argv , outset ) ; } for( vv=0 ; vv < ntime ; vv++ ) EDIT_substitute_brick( outset , vv , MRI_float , NULL ) ; #if 1 THD_vectim_to_dset( mrv , outset ) ; #else AFNI_OMP_START ; #pragma omp parallel { float *far , *var ; int *ivec=mrv->ivec ; int vv,kk ; #pragma omp for for( vv=0 ; vv < ntime ; vv++ ){ far = DSET_BRICK_ARRAY(outset,vv) ; var = mrv->fvec + vv ; for( kk=0 ; kk < nmask ; kk++ ) far[ivec[kk]] = var[kk*ntime] ; } } AFNI_OMP_END ; #endif VECTIM_destroy(mrv) ; if(SERIES_OUT){ // @@ DSET_write(outset) ; if( verb ) WROTE_DSET(outset) ; } } else{ // @@ non-BP'ed version if( verb ) INFO_message("Creating output dataset 2 in memory") ; // do this here because LFF version was also BP'ed at end. if(BP_LAST) // do bandpass here for BP_LAST (void)THD_bandpass_vectim(mrv,dt,fbotALL,ftopALL,qdet,0,NULL); outsetALL = EDIT_empty_copy(inset) ; if(UNBP_OUT){ sprintf(out_unBP,"%s_unBP",prefix); EDIT_dset_items( outsetALL, ADN_prefix, out_unBP, ADN_none ); tross_Copy_History( inset , outsetALL ) ; tross_Make_History( "3dRSFC" , argc,argv , outsetALL ) ; } for( vv=0 ; vv < ntime ; vv++ ) EDIT_substitute_brick( outsetALL , vv , MRI_float , NULL ) ; #if 1 THD_vectim_to_dset( mrv , outsetALL ) ; #else AFNI_OMP_START ; #pragma omp parallel { float *far , *var ; int *ivec=mrv->ivec ; int vv,kk ; #pragma omp for for( vv=0 ; vv < ntime ; vv++ ){ far = DSET_BRICK_ARRAY(outsetALL,vv) ; var = mrv->fvec + vv ; for( kk=0 ; kk < nmask ; kk++ ) far[ivec[kk]] = var[kk*ntime] ; } } AFNI_OMP_END ; #endif VECTIM_destroy(mrv) ; if(UNBP_OUT){ DSET_write(outsetALL) ; if( verb ) WROTE_DSET(outsetALL) ; } } }// end of NumDen loop // @@ INFO_message("Starting the (f)ALaFFel calcs") ; // allocations series1 = (double *)calloc(ntime,sizeof(double)); series2 = (double *)calloc(ntime,sizeof(double)); xx1 = (double *)calloc(2*ntime,sizeof(double)); xx2 = (double *)calloc(2*ntime,sizeof(double)); alff = (float *)calloc(nvox,sizeof(float)); malff = (float *)calloc(nvox,sizeof(float)); falff = (float *)calloc(nvox,sizeof(float)); if( (series1 == NULL) || (series2 == NULL) || (xx1 == NULL) || (xx2 == NULL) || (alff == NULL) || (malff == NULL) || (falff == NULL)) { fprintf(stderr, "\n\n MemAlloc failure.\n\n"); exit(122); } if(DO_RSFA) { rsfa = (float *)calloc(nvox,sizeof(float)); mrsfa = (float *)calloc(nvox,sizeof(float)); frsfa = (float *)calloc(nvox,sizeof(float)); if( (rsfa == NULL) || (mrsfa == NULL) || (frsfa == NULL)) { fprintf(stderr, "\n\n MemAlloc failure.\n\n"); exit(123); } } work = gsl_fft_real_workspace_alloc (ntime); real1 = gsl_fft_real_wavetable_alloc (ntime); real2 = gsl_fft_real_wavetable_alloc (ntime); gsl_complex_packed_array compl_freqs1 = xx1; gsl_complex_packed_array compl_freqs2 = xx2; // ********************************************************************* // ********************************************************************* // ************** Falafelling = ALFF/fALFF calcs ***************** // ********************************************************************* // ********************************************************************* // Be now have the BP'ed data set (outset) and the non-BP'ed one // (outsetALL). now we'll FFT both, get amplitudes in appropriate // ranges, and calculate: ALFF, mALFF, fALFF, ctr = 0; for( kk=0; kk<nvox ; kk++) { if(mask[kk]) { // BP one, and unBP one, either for BP_LAST or !BP_LAST for( m=0 ; m<ntime ; m++ ) { series1[m] = THD_get_voxel(outset,kk,m); series2[m] = THD_get_voxel(outsetALL,kk,m); } mm = gsl_fft_real_transform(series1, 1, ntime, real1, work); mm = gsl_fft_halfcomplex_unpack(series1, compl_freqs1, 1, ntime); mm = gsl_fft_real_transform(series2, 1, ntime, real2, work); mm = gsl_fft_halfcomplex_unpack(series2, compl_freqs2, 1, ntime); numer = 0.0f; denom = 0.0f; de_rsfa = 0.0f; nu_rsfa = 0.0f; for( m=1 ; m<N_ny ; m++ ) { mm = 2*m; pow2 = compl_freqs2[mm]*compl_freqs2[mm] + compl_freqs2[mm+1]*compl_freqs2[mm+1]; // power //pow2*=2;// factor of 2 since ampls are even funcs denom+= (float) sqrt(pow2); // amplitude de_rsfa+= (float) pow2; if( ( m>=ind_low ) && ( m<=ind_high ) ){ pow1 = compl_freqs1[mm]*compl_freqs1[mm]+ compl_freqs1[mm+1]*compl_freqs1[mm+1]; //pow1*=2; numer+= (float) sqrt(pow1); nu_rsfa+= (float) pow1; } } if( denom>0.000001 ) falff[kk] = numer/denom; else falff[kk] = 0.; alff[kk] = 2*numer/sqnt;// factor of 2 since ampl is even funct meanALFF+= alff[kk]; if(DO_RSFA){ nu_rsfa = sqrt(2*nu_rsfa); // factor of 2 since ampls de_rsfa = sqrt(2*de_rsfa); // are even funcs if( de_rsfa>0.000001 ) frsfa[kk] = nu_rsfa/de_rsfa; else frsfa[kk]=0.; rsfa[kk] = nu_rsfa/nt_fac; meanRSFA+= rsfa[kk]; } ctr+=1; } } meanALFF/= ctr; meanRSFA/= ctr; gsl_fft_real_wavetable_free(real1); gsl_fft_real_wavetable_free(real2); gsl_fft_real_workspace_free(work); // ALFFs divided by mean of brain value for( kk=0 ; kk<nvox ; kk++ ) if(mask[kk]){ malff[kk] = alff[kk]/meanALFF; if(DO_RSFA) mrsfa[kk] = rsfa[kk]/meanRSFA; } // ************************************************************** // ************************************************************** // Store and output // ************************************************************** // ************************************************************** outsetALFF = EDIT_empty_copy( inset ) ; sprintf(out_alff,"%s_ALFF",prefix); EDIT_dset_items( outsetALFF, ADN_nvals, 1, ADN_datum_all , MRI_float , ADN_prefix , out_alff, ADN_none ) ; if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetALFF)) ) ERROR_exit("Can't overwrite existing dataset '%s'", DSET_HEADNAME(outsetALFF)); EDIT_substitute_brick(outsetALFF, 0, MRI_float, alff); alff=NULL; THD_load_statistics(outsetALFF); tross_Make_History("3dRSFC", argc, argv, outsetALFF); THD_write_3dim_dataset(NULL, NULL, outsetALFF, True); outsetfALFF = EDIT_empty_copy( inset ) ; sprintf(out_falff,"%s_fALFF",prefix); EDIT_dset_items( outsetfALFF, ADN_nvals, 1, ADN_datum_all , MRI_float , ADN_prefix , out_falff, ADN_none ) ; if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetfALFF)) ) ERROR_exit("Can't overwrite existing dataset '%s'", DSET_HEADNAME(outsetfALFF)); EDIT_substitute_brick(outsetfALFF, 0, MRI_float, falff); falff=NULL; THD_load_statistics(outsetfALFF); tross_Make_History("3dRSFC", argc, argv, outsetfALFF); THD_write_3dim_dataset(NULL, NULL, outsetfALFF, True); outsetmALFF = EDIT_empty_copy( inset ) ; sprintf(out_malff,"%s_mALFF",prefix); EDIT_dset_items( outsetmALFF, ADN_nvals, 1, ADN_datum_all , MRI_float , ADN_prefix , out_malff, ADN_none ) ; if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetmALFF)) ) ERROR_exit("Can't overwrite existing dataset '%s'", DSET_HEADNAME(outsetmALFF)); EDIT_substitute_brick(outsetmALFF, 0, MRI_float, malff); malff=NULL; THD_load_statistics(outsetmALFF); tross_Make_History("3dRSFC", argc, argv, outsetmALFF); THD_write_3dim_dataset(NULL, NULL, outsetmALFF, True); if(DO_RSFA){ outsetRSFA = EDIT_empty_copy( inset ) ; sprintf(out_rsfa,"%s_RSFA",prefix); EDIT_dset_items( outsetRSFA, ADN_nvals, 1, ADN_datum_all , MRI_float , ADN_prefix , out_rsfa, ADN_none ) ; if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetRSFA)) ) ERROR_exit("Can't overwrite existing dataset '%s'", DSET_HEADNAME(outsetRSFA)); EDIT_substitute_brick(outsetRSFA, 0, MRI_float, rsfa); rsfa=NULL; THD_load_statistics(outsetRSFA); tross_Make_History("3dRSFC", argc, argv, outsetRSFA); THD_write_3dim_dataset(NULL, NULL, outsetRSFA, True); outsetfRSFA = EDIT_empty_copy( inset ) ; sprintf(out_frsfa,"%s_fRSFA",prefix); EDIT_dset_items( outsetfRSFA, ADN_nvals, 1, ADN_datum_all , MRI_float , ADN_prefix , out_frsfa, ADN_none ) ; if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetfRSFA)) ) ERROR_exit("Can't overwrite existing dataset '%s'", DSET_HEADNAME(outsetfRSFA)); EDIT_substitute_brick(outsetfRSFA, 0, MRI_float, frsfa); frsfa=NULL; THD_load_statistics(outsetfRSFA); tross_Make_History("3dRSFC", argc, argv, outsetfRSFA); THD_write_3dim_dataset(NULL, NULL, outsetfRSFA, True); outsetmRSFA = EDIT_empty_copy( inset ) ; sprintf(out_mrsfa,"%s_mRSFA",prefix); EDIT_dset_items( outsetmRSFA, ADN_nvals, 1, ADN_datum_all , MRI_float , ADN_prefix , out_mrsfa, ADN_none ) ; if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetmRSFA)) ) ERROR_exit("Can't overwrite existing dataset '%s'", DSET_HEADNAME(outsetmRSFA)); EDIT_substitute_brick(outsetmRSFA, 0, MRI_float, mrsfa); mrsfa=NULL; THD_load_statistics(outsetmRSFA); tross_Make_History("3dRSFC", argc, argv, outsetmRSFA); THD_write_3dim_dataset(NULL, NULL, outsetmRSFA, True); } // ************************************************************ // ************************************************************ // Freeing // ************************************************************ // ************************************************************ DSET_delete(inset); DSET_delete(outsetALL); DSET_delete(outset); DSET_delete(outsetALFF); DSET_delete(outsetmALFF); DSET_delete(outsetfALFF); DSET_delete(outsetRSFA); DSET_delete(outsetmRSFA); DSET_delete(outsetfRSFA); free(inset); free(outsetALL); free(outset); free(outsetALFF); free(outsetmALFF); free(outsetfALFF); free(outsetRSFA); free(outsetmRSFA); free(outsetfRSFA); free(rsfa); free(mrsfa); free(frsfa); free(alff); free(malff); free(falff); free(mask); free(series1); free(series2); free(xx1); free(xx2); exit(0) ; }
int main( int argc , char * argv[] ) { int nim , ii,nii , jj , kk , nx ; MRI_IMAGE **inim ; float *far ; int ncol , ic ; float *csum ; int nn_ignore=0 , mm_use=0 , iarg=1 , do_mean=0 , do_comments=1 ; char *comments=NULL ; /* 04 Aug 2016 */ /*-- help? --*/ if( argc < 2 || strcmp(argv[1],"-help") == 0 ){ printf("Usage: 1dsum [options] a.1D b.1D ...\n" "where each file a.1D, b.1D, etc. is an ASCII file of numbers arranged\n" "in rows and columns. The sum of each column is written to stdout.\n" "\n" "Options:\n" " -ignore nn = skip the first nn rows of each file\n" " -use mm = use only mm rows from each file\n" " -mean = compute the average instead of the sum\n" " -nocomment = the # comments from the header of the first\n" " input file will be reproduced to the output;\n" " if you do NOT want this to happen, use the\n" " '-nocomment' option.\n" ) ; PRINT_COMPILE_DATE ; exit(0) ; } machdep() ; /* parse options */ while( iarg < argc && argv[iarg][0] == '-' ){ if( strncmp(argv[iarg],"-nocom",6) == 0 ){ do_comments = 0 ; iarg++ ; continue ; } if( strncmp(argv[iarg],"-ignore",4) == 0 ){ nn_ignore = (int) strtod(argv[++iarg],NULL) ; if( nn_ignore < 0 ){fprintf(stderr,"** Illegal -ignore value!\n");exit(1);} iarg++ ; continue ; } if( strncmp(argv[iarg],"-use",4) == 0 ){ mm_use = (int) strtod(argv[++iarg],NULL) ; if( mm_use < 0 ){fprintf(stderr,"** Illegal -use value!\n");exit(1);} iarg++ ; continue ; } if( strcmp(argv[iarg],"-mean") == 0 ){ /* 17 Dec 2015 */ do_mean = 1 ; iarg++ ; continue ; } fprintf(stderr,"** Unknown option: %s\n",argv[iarg]) ; exit(1) ; } /* read input files */ nim = argc-iarg ; inim = (MRI_IMAGE **) malloc( sizeof(MRI_IMAGE *) * nim ) ; ncol = 0 ; for( jj=0 ; jj < nim ; jj++ ){ inim[jj] = mri_read_1D( argv[jj+iarg] ) ; if( inim[jj] == NULL ){ fprintf(stderr,"** Can't read input file %s\n",argv[jj+iarg]) ; exit(1) ; } if( do_comments && comments == NULL && inim[jj]->comments != NULL ) /* 04 Aug 2016 */ comments = strdup(inim[jj]->comments) ; if( jj > 0 && inim[jj]->nx != inim[0]->nx ){ fprintf(stderr, "** Input file %s doesn't match first file %s in length!\n", argv[jj+iarg],argv[iarg]) ; exit(1) ; } ncol += inim[jj]->ny ; } if( mm_use == 0 ){ mm_use = inim[0]->nx - nn_ignore ; if( mm_use < 0 ){fprintf(stderr,"** -ignore is too big for these files!\n");exit(1);} } if( nn_ignore + mm_use > inim[0]->nx ){ fprintf(stderr,"** -ignore + -use is too big for these files!\n");exit(1); } csum = (float *) malloc(sizeof(float)*ncol) ; for( ic=0 ; ic < ncol ; ic++ ) csum[ic] = 0.0 ; nx = inim[0]->nx ; for( nii=0,ii=nn_ignore ; ii < nn_ignore+mm_use ; ii++,nii++ ){ for( ic=jj=0 ; jj < nim ; jj++ ){ far = MRI_FLOAT_PTR(inim[jj]) ; for( kk=0 ; kk < inim[jj]->ny ; kk++ ) csum[ic++] += far[ii+kk*nx] ; } } if( do_mean ){ for( ic=0 ; ic < ncol ; ic++ ) csum[ic] /= nii ; } if( comments != NULL ) printf("%s",comments) ; /* 04 Aug 2016 */ for( ic=0 ; ic < ncol ; ic++ ) printf("%g ",csum[ic]) ; printf("\n"); exit(0) ; }
int main( int argc , char * argv[] ) { int do_norm=0 , qdet=2 , have_freq=0 , do_automask=0 ; float dt=0.0f , fbot=0.0f,ftop=999999.9f , blur=0.0f ; MRI_IMARR *ortar=NULL ; MRI_IMAGE *ortim=NULL ; THD_3dim_dataset **ortset=NULL ; int nortset=0 ; THD_3dim_dataset *inset=NULL , *outset ; char *prefix="bandpass" ; 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 ; /*-- help? --*/ AFNI_SETUP_OMP(0) ; /* 24 Jun 2013 */ if( argc < 2 || strcmp(argv[1],"-help") == 0 ){ printf( "\n" "** NOTA BENE: For the purpose of preparing resting-state FMRI datasets **\n" "** for analysis (e.g., with 3dGroupInCorr), this program is now mostly **\n" "** superseded by the afni_proc.py script. See the 'afni_proc.py -help' **\n" "** section 'Resting state analysis (modern)' to get our current rs-FMRI **\n" "** pre-processing recommended sequence of steps. -- RW Cox, et alii. **\n" "\n" "Usage: 3dBandpass [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 3dBandpass 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" "* 3dBandpass 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 3dBandpass will\n" " depend on the order in which you run these programs. That's why\n" " 3dBandpass 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):\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" "\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.\n" " -quiet = Turn off the fun and informative messages. (Why?)\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-voxel\n" " correlations via InstaCorr.\n" " ++ No other tests are made [yet] for non-stationary behavior\n" " in the time series data.\n" ) ; PRINT_AFNI_OMP_USAGE( "3dBandpass" , "* At present, the only part of 3dBandpass that is parallelized is the\n" " '-blur' option, which processes each sub-brick independently.\n" ) ; PRINT_COMPILE_DATE ; exit(0) ; } /*-- startup --*/ mainENTRY("3dBandpass"); machdep(); AFNI_logger("3dBandpass",argc,argv); PRINT_VERSION("3dBandpass"); AUTHOR("RW Cox"); 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],"-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 ; } } 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 ) 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 */ mrv = THD_dset_to_vectim( inset , mask , 0 ) ; if( mrv == NULL ) ERROR_exit("Can't load time series data!?") ; DSET_unload(inset) ; /* 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 ; } } /* check whether processing leaves any DoF remaining 18 Mar 2015 [rickr] */ { int nbprem = THD_bandpass_remain_dim(ntime, dt, fbot, ftop, 1); int bpused, nremain; int wlimit; /* warning limit */ bpused = ntime - nbprem; /* #dim lost in bandpass step */ nremain = nbprem - nort; /* #dim left in output */ if( nortset == 1 ) nremain--; nremain -= (qdet+1); if( verb ) INFO_message("%d dimensional data reduced to %d by:\n" " %d (bandpass), %d (-ort), %d (-dsort), %d (detrend)", ntime, nremain, bpused, nort, nortset?1:0, qdet+1); /* possibly warn (if 95% lost) user or fail */ wlimit = ntime/20; if( wlimit < 3 ) wlimit = 3; if( nremain < wlimit && nremain > 0 ) WARNING_message("dimensionality reduced from %d to %d, be careful!", ntime, nremain); if( nremain <= 0 ) /* FAILURE */ ERROR_exit("dimensionality reduced from %d to %d, failing!", ntime, nremain); } /* 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") ; (void)THD_bandpass_vectim( mrv , dt,fbot,ftop , 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 ) ; 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( verb ) INFO_message("Creating output dataset in memory, then writing it") ; outset = EDIT_empty_copy(inset) ; /* do not copy scalars 11 Sep 2015 [rickr] */ EDIT_dset_items( outset , ADN_prefix,prefix , ADN_brick_fac,NULL , 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) ; DSET_write(outset) ; if( verb ) WROTE_DSET(outset) ; exit(0) ; }
int main (int argc,char *argv[]) {/* Main */ static char FuncName[]={"SurfToSurf"}; SUMA_GENERIC_PROG_OPTIONS_STRUCT *Opt; SUMA_GENERIC_ARGV_PARSE *ps=NULL; SUMA_SurfaceObject *SO1=NULL, *SO2 = NULL; SUMA_SurfSpecFile *Spec = NULL; SUMA_M2M_STRUCT *M2M = NULL; int N_Spec=0, *nodeind = NULL, N_nodeind, icol, i, j; MRI_IMAGE *im = NULL, *im_data=NULL; int nvec=0, ncol=0, nvec_data=0, ncol_data=0, Nchar=0; float *far = NULL, *far_data=NULL, *dt = NULL, *projdir=NULL; char *outname = NULL, *s=NULL, sbuf[100]; void *SO_name = NULL; FILE *outptr=NULL; SUMA_Boolean exists = NOPE; SUMA_INDEXING_ORDER d_order = SUMA_NO_ORDER; SUMA_STRING *SS=NULL; SUMA_Boolean LocalHead = NOPE; SUMA_STANDALONE_INIT; SUMA_mainENTRY; /* Allocate space for DO structure */ SUMAg_DOv = SUMA_Alloc_DisplayObject_Struct (SUMA_MAX_DISPLAYABLE_OBJECTS); ps = SUMA_Parse_IO_Args(argc, argv, "-i;-t;-spec;-s;-sv;-o;"); Opt = SUMA_SurfToSurf_ParseInput (argv, argc, ps); if (argc < 2) { SUMA_S_Err("Too few options"); usage_SurfToSurf(ps, 0); exit (1); } /* if output surface requested, check on pre-existing file */ if (ps->o_N_surfnames) { SO_name = SUMA_Prefix2SurfaceName(ps->o_surfnames[0], NULL, NULL, ps->o_FT[0], &exists); if (exists) { fprintf(SUMA_STDERR, "Error %s:\nOutput file(s) %s* on disk.\n" "Will not overwrite.\n", FuncName, ps->o_surfnames[0]); exit(1); } } if (Opt->debug > 2) LocalHead = YUP; outname = SUMA_append_extension(Opt->out_prefix,".1D"); if (SUMA_filexists(outname) && !THD_ok_overwrite()) { fprintf(SUMA_STDERR,"Output file %s exists.\n", outname); exit(1); } /* Load the surfaces from command line*/ Spec = SUMA_IO_args_2_spec(ps, &N_Spec); if (N_Spec != 1) { SUMA_S_Err( "Multiple spec at input.\n" "Do not mix surface input types together\n"); exit(1); } if (Spec->N_Surfs != 2) { SUMA_S_Err("2 surfaces expected."); exit(1); } SO1 = SUMA_Load_Spec_Surf(Spec, 0, ps->sv[0], 0); if (!SO1) { fprintf (SUMA_STDERR,"Error %s:\n" "Failed to find surface\n" "in spec file. \n", FuncName ); exit(1); } if (!SUMA_SurfaceMetrics(SO1, "EdgeList|MemberFace", NULL)) { SUMA_SL_Err("Failed to create edge list for SO1"); exit(1); } if (Opt->fix_winding) { int orient, trouble; if (LocalHead) fprintf(SUMA_STDERR, "%s: Making sure S1 is consistently orientated\n", FuncName); if (!SUMA_MakeConsistent (SO1->FaceSetList, SO1->N_FaceSet, SO1->EL, Opt->debug, &trouble)) { SUMA_SL_Err("Failed in SUMA_MakeConsistent"); } if (trouble && LocalHead) { fprintf(SUMA_STDERR, "%s: trouble value of %d from SUMA_MakeConsistent.\n" "Inconsistencies were found and corrected unless \n" "stderr output messages from SUMA_MakeConsistent\n" "indicate otherwise.\n", FuncName, trouble); } if (LocalHead) fprintf(SUMA_STDERR,"%s: Checking orientation.\n", FuncName); orient = SUMA_OrientTriangles (SO1->NodeList, SO1->N_Node, SO1->FaceSetList, SO1->N_FaceSet, 1, 0, NULL, NULL); if (orient < 0) { /* flipping was done, dump the edge list since it is not automatically updated (should do that in function, just like in SUMA_MakeConsistent, shame on you) If you revisit this section, use the newer: SUMA_OrientSOTriangles */ if (SO1->EL) SUMA_free_Edge_List(SO1->EL); SO1->EL = NULL; if (!SUMA_SurfaceMetrics(SO1, "EdgeList", NULL)) { SUMA_SL_Err("Failed to create edge list for SO1"); exit(1); } /* free normals, new ones needed (Normals should be flipped inside of SUMA_OrientTriangles! (just like in SUMA_MakeConsistent) ) */ if (SO1->NodeNormList) SUMA_free(SO1->NodeNormList); SO1->NodeNormList = NULL; if (SO1->FaceNormList) SUMA_free(SO1->FaceNormList); SO1->FaceNormList = NULL; } if (!orient) { fprintf(SUMA_STDERR, "Error %s:\nFailed in SUMA_OrientTriangles\n", FuncName); } if (LocalHead) { if (orient < 0) { SUMA_SL_Note("S1 was reoriented"); } else { SUMA_SL_Note("S1 was properly oriented"); } } } if (!SO1->NodeNormList || !SO1->FaceNormList) { SUMA_LH("Node Normals"); SUMA_RECOMPUTE_NORMALS(SO1); } if (Opt->NodeDbg >= SO1->N_Node) { SUMA_SL_Warn( "node_debug index is larger than number " "of nodes in surface, ignoring -node_debug."); Opt->NodeDbg = -1; } SO2 = SUMA_Load_Spec_Surf(Spec, 1, ps->sv[1], 0); if (!SO2) { fprintf (SUMA_STDERR,"Error %s:\n" "Failed to find surface\n" "in spec file. \n", FuncName ); exit(1); } if (!SUMA_SurfaceMetrics(SO2, "EdgeList|MemberFace", NULL)) { SUMA_SL_Err("Failed to create edge list for SO2"); exit(1); } if (!SO2->NodeNormList || !SO2->FaceNormList) { SUMA_LH("Node Normals"); SUMA_RECOMPUTE_NORMALS(SO2); } if (LocalHead) { SUMA_LH("Surf1"); SUMA_Print_Surface_Object(SO1, NULL); SUMA_LH("Surf2"); SUMA_Print_Surface_Object(SO2, NULL); } /* a select list of nodes? */ nodeind = NULL; N_nodeind = 0; if (Opt->in_nodeindices) { im = mri_read_1D(Opt->in_nodeindices); if (!im) { SUMA_SL_Err("Failed to read 1D file of node indices"); exit(1);} far = MRI_FLOAT_PTR(im); N_nodeind = nvec = im->nx; ncol = im->ny; if (ncol != 1) { SUMA_SL_Err("More than one column in node index input file."); exit(1); } nodeind = (int *)SUMA_calloc(nvec, sizeof(int)); if (!nodeind) { SUMA_SL_Crit("Failed to allocate"); exit(1); } for (i=0;i<nvec;++i) { nodeind[i] = (int)far[i]; if (nodeind[i] < 0 || nodeind[i] >= SO1->N_Node) { fprintf(SUMA_STDERR, "Error %s:\n" "A node index of %d was found in input file %s, entry %d.\n" "Acceptable indices are positive and less than %d\n", FuncName, nodeind[i], Opt->in_nodeindices, i, SO1->N_Node); exit(1); } } mri_free(im); im = NULL; /* done with that baby */ } /* a preset directions vector ?*/ projdir = NULL; if (Opt->in_1D) { im = mri_read_1D(Opt->in_1D); if (!im) { SUMA_SL_Err("Failed to read 1D file of projection directions"); exit(1); } far = MRI_FLOAT_PTR(im); if (im->ny != 3) { SUMA_SL_Err("Need three columns in projection directions file."); exit(1); } if (im->nx != SO1->N_Node) { fprintf(SUMA_STDERR, "Error %s: You must have a direction for each node in SO1.\n" "%d directions found but SO1 has %d nodes.\n", FuncName, im->nx, SO1->N_Node); exit(1); } /* change to row major major and make it match nodeind */ projdir = (float *)SUMA_calloc(SO1->N_Node*3, sizeof(float)); if (!projdir) { SUMA_SL_Crit("Failed to allocate"); exit(1); } for (i=0; i<SO1->N_Node; ++i) { projdir[3*i ] = far[i ]; projdir[3*i+1] = far[i+ SO1->N_Node]; projdir[3*i+2] = far[i+2*SO1->N_Node]; } mri_free(im); im = NULL; /* done with that baby */ } if (SO_name) { /* user is interpolating surface coords, check on other input insanity */ if (nodeind) { fprintf( SUMA_STDERR, "Error %s: You cannot combine " "option -o_TYPE with -node_indices", FuncName); exit(1); } if (Opt->in_name) { fprintf(SUMA_STDERR, "Error %s: You cannot combine option -o_TYPE with -data", FuncName); exit(1); } } /* a 1D file containing data, or Data parameter (for XYZ)? */ if (Opt->Data > 0) { if (Opt->in_name) { /* When you are ready to work with dsets, you should checkout the function morphDsetToStd. It uses M2M */ im_data = mri_read_1D(Opt->in_name); if (!im_data) { SUMA_SL_Err("Failed to read 1D file of data"); exit(1);} far_data = MRI_FLOAT_PTR(im_data); nvec_data = im_data->nx; ncol_data = im_data->ny; if (nvec_data != SO2->N_Node) { SUMA_SL_Err("Your data file must have one row " "for each node in surface 2.\n"); exit(1); } d_order = SUMA_COLUMN_MAJOR; } else { im_data = NULL; far_data = SO2->NodeList; nvec_data = SO2->N_Node; ncol_data = 3; d_order = SUMA_ROW_MAJOR; } } else { /* just -dset */ } if (!Opt->s) { SUMA_LH("Going for the mapping of SO1 --> SO2"); M2M = SUMA_GetM2M_NN( SO1, SO2, nodeind, N_nodeind, projdir, 0, Opt->NodeDbg, Opt->iopt); SUMA_S_Notev("Saving M2M into %s\n\n", Opt->out_prefix); if (!(SUMA_Save_M2M(Opt->out_prefix, M2M))) { SUMA_S_Err("Failed to save M2M"); exit(1); } } else { SUMA_S_Notev("Reusing mapping of SO1 --> SO2 from %s\n\n", Opt->s); if (!(M2M = SUMA_Load_M2M(Opt->s))) { SUMA_S_Errv("Failed to load %s\n", Opt->s); exit(1); } } /* Now show the mapping results for a debug node ? */ if (Opt->NodeDbg >= 0) { char *s = NULL; s = SUMA_M2M_node_Info(M2M, Opt->NodeDbg); fprintf(SUMA_STDERR,"%s: Debug for node %d ([%f, %f, %f])of SO1:\n%s\n\n", FuncName, Opt->NodeDbg, SO1->NodeList[3*Opt->NodeDbg], SO1->NodeList[3*Opt->NodeDbg+1], SO1->NodeList[3*Opt->NodeDbg+2], s); SUMA_free(s); s = NULL; } /* Now please do the interpolation */ if (Opt->Data > 0) { if (Opt->NearestNode > 1) dt = SUMA_M2M_interpolate( M2M, far_data, ncol_data, nvec_data, d_order, 0 ); else if (Opt->NearestNode == 1) dt = SUMA_M2M_interpolate( M2M, far_data, ncol_data, nvec_data, d_order, 1 ); if (!dt) { SUMA_SL_Err("Failed to interpolate"); exit(1); } } else if (Opt->Data < 0) { SUMA_DSET *dset=NULL, *dseto=NULL; char *oname=NULL, *uname=NULL, *s1=NULL, *s2=NULL; int iform=SUMA_NO_DSET_FORMAT; if (Opt->NodeDbg>= 0) { SUMA_S_Notev("Processing dset %s\n", Opt->in_name); } iform = SUMA_NO_DSET_FORMAT; if (!(dset = SUMA_LoadDset_s (Opt->in_name, &iform, 0))) { SUMA_S_Errv("Failed to load %s\n", Opt->in_name); exit(1); } if (!(dseto = SUMA_morphDsetToStd ( dset, M2M, Opt->NearestNode == 1 ? 1:0))) { SUMA_S_Errv("Failed to map %s\n", Opt->in_name); exit(1); } s1 = SUMA_append_string( SUMA_FnameGet(Opt->in_name,"pa", SUMAg_CF->cwd), Opt->out_prefix); s2 = SUMA_RemoveDsetExtension_s( SUMA_FnameGet(Opt->in_name,"l",SUMAg_CF->cwd), SUMA_NO_DSET_FORMAT); uname = SUMA_append_extension(s1,s2); SUMA_free(s1); SUMA_free(s2); oname = SUMA_WriteDset_s (uname, dseto, Opt->oform, 1, 1); if (Opt->NodeDbg>= 0) SUMA_S_Notev("Wrote %s\n", oname); if (oname) SUMA_free(oname); oname=NULL; if (uname) SUMA_free(uname); oname=NULL; if (dseto) SUMA_FreeDset(dseto); dseto = NULL; if (dset) SUMA_FreeDset(dset); dset = NULL; } SUMA_LH("Forming the remaining output"); outptr = fopen(outname,"w"); if (!outptr) { SUMA_SL_Err("Failed to open file for output.\n"); exit(1); } /* first create the header of the output */ SS = SUMA_StringAppend(NULL, NULL); SS = SUMA_StringAppend_va(SS, "#Mapping from nodes on surf 1 (S1) to nodes on surf 2 (S2)\n" "# Surf 1 is labeled %s, idcode:%s\n" "# Surf 2 is labeled %s, idcode:%s\n", SO1->Label, SO1->idcode_str, SO2->Label, SO2->idcode_str); icol = 0; SS = SUMA_StringAppend_va(SS, "#Col. %d:\n" "# S1n (or nj): Index of node on S1\n" , icol); ++icol; if (Opt->NearestNode > 1) { SS = SUMA_StringAppend_va(SS, "#Col. %d..%d:\n" "# S2ne_S1n: Indices of %d nodes on S2 \n" "# that are closest neighbors of nj.\n" "# The first index is that of the node on S2 that is closest \n" "# to nj. If -1 then these values should be ignored because\n" "# in such cases, nj's projection failed.\n" , icol, icol+Opt->NearestNode-1, Opt->NearestNode); icol += Opt->NearestNode; SS = SUMA_StringAppend_va(SS, "#Col. %d..%d:\n" "# S2we_S1n: Weights assigned to nodes on surf 2 (S2) \n" "# that are closest neighbors of nj.\n" , icol, icol+Opt->NearestNode-1, Opt->NearestNode); icol += Opt->NearestNode; } else if (Opt->NearestNode == 1) { SS = SUMA_StringAppend_va(SS, "#Col. %d:\n" "# S2ne_S1n: Index of the node on S2 (label:%s idcode:%s)\n" "# that is the closest neighbor of nj.\n" "# If -1 then this value should be ignored because\n" "# nj's projection failed.\n" , icol, SO2->Label, SO2->idcode_str); ++icol; } if (Opt->NearestTriangle) { SS = SUMA_StringAppend_va(SS, "#Col. %d:\n" "# S2t_S1n: Index of the S2 triangle that hosts node nj on S1.\n" "# In other words, nj's closest projection onto S2 falls on \n" "# triangle S2t_S1n\n" "# If -1 then this value should be ignored because \n" "# nj's projection failed.\n" , icol); ++icol; } if (Opt->ProjectionOnMesh) { SS = SUMA_StringAppend_va(SS, "#Col. %d..%d:\n" "# S2p_S1n: Coordinates of projection of nj onto S2\n" , icol, icol+2); icol += 3; } if (Opt->DistanceToMesh) { SS = SUMA_StringAppend_va(SS, "#Col. %d:\n" "# Closest distance from nj to S2\n" , icol); ++icol; } if (Opt->NearestNodeCoords) { SS = SUMA_StringAppend_va(SS, "#Col. %d .. %d:\n" "# X Y Z coords of nearest node\n" , icol, icol+2); icol += 3; } if (Opt->Data > 0) { if (!Opt->in_name) { SS = SUMA_StringAppend_va(SS, "#Col. %d..%d:\n" "# Interpolation using XYZ coordinates of S2 nodes that neighbor nj\n" "# (same as coordinates of node's projection onto triangle in S2, \n" "# if using barycentric interpolation)\n" , icol, icol+2); icol += 3; } else { SS = SUMA_StringAppend_va(SS, "#Col. %d..%d:\n" "# Interpolation of data at nodes on S2 that neighbor nj\n" "# Data obtained from %s\n" , icol, icol+ncol_data-1, Opt->in_name); icol += ncol_data; } } s = SUMA_HistString("SurfToSurf", argc, argv, NULL); SS = SUMA_StringAppend_va(SS, "#History:\n" "#%s\n", s); SUMA_free(s); s = NULL; SUMA_SS2S(SS,s); fprintf(outptr,"%s\n",s); SUMA_free(s); s = NULL; /* put headers atop columns */ Nchar = 6; /* if you change this number you'll need to fix formats below */ for (i=0; i<icol; ++i) { sprintf(sbuf,"#%s", MV_format_fval2(i, Nchar -1)); fprintf(outptr,"%6s ", sbuf); } fprintf(outptr,"\n"); /* Now put in the values, make sure you parallel columns above! */ for (i=0; i<M2M->M1Nn; ++i) { fprintf(outptr,"%6s ", MV_format_fval2(M2M->M1n[i], Nchar)); if (Opt->NearestNode > 0) { for (j=0; j<Opt->NearestNode; ++j) { if (j < M2M->M2Nne_M1n[i]) fprintf(outptr,"%6s ", MV_format_fval2(M2M->M2ne_M1n[i][j], Nchar)); else fprintf(outptr,"%6s ", "-1"); } /* Neighboring nodes */ } if (Opt->NearestNode > 1) { /* add the weights */ for (j=0; j<Opt->NearestNode; ++j) { if (j < M2M->M2Nne_M1n[i]) fprintf(outptr,"%6s ", MV_format_fval2(M2M->M2we_M1n[i][j], Nchar)); else fprintf(outptr,"%6s ", "0.0"); } } if (Opt->NearestTriangle) { fprintf(outptr,"%6s ", MV_format_fval2(M2M->M2t_M1n[i], Nchar)); } if (Opt->ProjectionOnMesh) { fprintf(outptr,"%6s ", MV_format_fval2(M2M->M2p_M1n[3*i], Nchar)); fprintf(outptr,"%6s ", MV_format_fval2(M2M->M2p_M1n[3*i+1], Nchar)); fprintf(outptr,"%6s ", MV_format_fval2(M2M->M2p_M1n[3*i+2], Nchar)); } if (Opt->DistanceToMesh) { fprintf(outptr,"%6s ", MV_format_fval2(M2M->PD[i], Nchar)); } if (Opt->NearestNodeCoords) { float x=0.0,y=0.0,z=0.0; int n = M2M->M2ne_M1n[i][0]; if (n>0) { n = n * SO2->NodeDim; x = SO2->NodeList[n]; y = SO2->NodeList[n+1]; z = SO2->NodeList[n+2]; } fprintf(outptr,"%6s ", MV_format_fval2(x, Nchar)); fprintf(outptr,"%6s ", MV_format_fval2(y, Nchar)); fprintf(outptr,"%6s ", MV_format_fval2(z, Nchar)); } if (dt && Opt->Data > 0) { if (!Opt->in_name) { fprintf(outptr,"%6s ", MV_format_fval2(dt[3*i], Nchar)); fprintf(outptr,"%6s ", MV_format_fval2(dt[3*i+1], Nchar)); fprintf(outptr,"%6s ", MV_format_fval2(dt[3*i+2], Nchar)); } else { /* Column major business */ for (j=0; j<ncol_data; ++j) { fprintf(outptr,"%6s ", MV_format_fval2(dt[i+j*M2M->M1Nn], Nchar)); } } } fprintf(outptr,"\n"); } /* do they want an output surface ? */ if (SO_name) { float *tmpfv = NULL; SUMA_LH("Writing surface"); tmpfv = SO1->NodeList; SO1->NodeList = dt; if (!SUMA_Save_Surface_Object (SO_name, SO1, ps->o_FT[0], ps->o_FF[0], NULL)) { SUMA_S_Err("Failed to write surface object.\n"); exit (1); } SO1->NodeList = tmpfv; tmpfv = NULL; } if (N_Spec) { int k=0; for (k=0; k<N_Spec; ++k) { if (!SUMA_FreeSpecFields(&(Spec[k]))) { SUMA_S_Err("Failed to free spec fields"); } } SUMA_free(Spec); Spec = NULL; N_Spec = 0; } if (projdir) SUMA_free(projdir); projdir = NULL; if (SO_name) SUMA_free(SO_name); SO_name = NULL; if (outptr) fclose(outptr); outptr = NULL; if (dt) SUMA_free(dt); dt = NULL; if (s) SUMA_free(s); s = NULL; if (im_data) mri_free(im_data); im_data = NULL; /* done with the data */ if (nodeind) SUMA_free(nodeind); nodeind = NULL; if (M2M) M2M = SUMA_FreeM2M(M2M); if (SO1) SUMA_Free_Surface_Object(SO1); SO1 = NULL; if (SO2) SUMA_Free_Surface_Object(SO2); SO2 = NULL; if (Spec) SUMA_free(Spec); Spec = NULL; if (ps) SUMA_FreeGenericArgParse(ps); ps = NULL; if (Opt) Opt = SUMA_Free_Generic_Prog_Options_Struct(Opt); if (!SUMA_Free_CommonFields(SUMAg_CF)) SUMA_error_message(FuncName,"SUMAg_CF Cleanup Failed!",1); exit(0); }
int main( int argc , char * argv[] ) { int nim , ii , jj , kk , nx, narg, oform ; MRI_IMAGE **inim ; float *far; char *formatstr=NULL, *sel=NULL, *fname=NULL; int nonconst=0 , ncol,ncold , cc , nonfixed=0 , stack=0; intvec *ncv=NULL ; char *hline=NULL ; mainENTRY("1dcat:main"); /*-- help? --*/ if( argc < 2 || strcmp(argv[1],"-help") == 0 ){ printf( "Usage: 1dcat [options] a.1D b.1D ...\n" " where each file a.1D, b.1D, etc. is a 1D file.\n" " In the simplest form, a 1D file is an ASCII file of numbers\n" " arranged in rows and columns.\n" "\n" "1dcat takes as input one or more 1D files, and writes out a 1D file\n" "containing the side-by-side concatenation of all or a subset of the\n" "columns from the input files.\n" "\n" "* Output goes to stdout (the screen); redirect (e.g., '>') to save elsewhere.\n" "* All files MUST have the same number of rows!\n" "* Any header lines (i.e., lines that start with '#') will be lost.\n" "* For generic 1D file usage help and information, see '1dplot -help'\n" "\n" "OPTIONS:\n" "--------\n" " -nonconst: Columns that are identically constant should be omitted\n" " from the output.\n" "\n" " -nonfixed: Keep only columns that are marked as 'free' in the \n" " 3dAllineate header from '-1Dparam_save'.\n" " If there is no such header, all columns are kept.\n" "\n" " -form FORM: Format of the numbers to be output.\n" " You can also substitute -form FORM with shortcuts such \n" " as -i, -f, or -c.\n" " For help on -form's usage, and its shortcut versions\n" " see ccalc's help for the option of the same name. \n" "\n" " -stack: Stack the columns of the resultant matrix in the output.\n" "\n" " -sel SEL: Apply the same column/row selection string to all filenames\n" " on the command line.\n" " For example:\n" " 1dcat -sel '[0,2]' f1.1D f2.1D\n" " is the same as: 1dcat f1.1D'[1,2]' f2.1D'[1,2]'\n" " The advantage of the option is that it allows wildcard use\n" " in file specification so that you can run something like:\n" " 1dcat -sel '[0,2]' f?.1D\n" "\n" "EXAMPLE:\n" "--------\n" " Input file 1:\n 1\n 2\n 3\n 4\n" " Input file 2:\n 5\n 6\n 7\n 8\n" "\n" " 1dcat data1.1D data2.1D > catout.1D\n" " Output file: \n 1 5\n 2 6\n 3 7\n 4 8\n" "\n" ) ; PRINT_COMPILE_DATE ; exit(0) ; } machdep() ; /* do we have any options? */ oform = CCALC_NOT_SET; sel = NULL; stack = 0; narg = 1; while (narg < argc && argv[narg][0] == '-') { if( strncmp(argv[narg],"-nonconst",7) == 0 ){ /* 04 Dec 2010 */ nonconst++ ; narg++ ; continue ; } if( strncmp(argv[narg],"-nonfixed",7) == 0 ){ /* 06 Dec 2010 */ nonfixed++ ; narg++ ; continue ; } if( strncmp(argv[narg],"-stack",6) == 0 ){ /* 05 Sep 2013 */ stack = 1 ; narg++ ; continue ; } if (strcmp(argv[narg],"-form") == 0) { ++narg; if (narg >= argc) { fprintf (stderr, "need argument after -form "); exit (1); } if (strcmp(argv[narg],"double") == 0 ) oform = CCALC_DOUBLE; else if (strcmp(argv[narg],"nice") == 0 ) oform = CCALC_NICE; else if (strcmp(argv[narg],"int") == 0 ) oform = CCALC_INT; else if (strcmp(argv[narg],"rint") == 0 ) oform = CCALC_INT; else if (strcmp(argv[narg],"fint") == 0 ) oform = CCALC_FINT; else if (strcmp(argv[narg],"cint") == 0 ) oform = CCALC_CINT; else if (strlen(argv[narg])<=256) { oform = CCALC_CUSTOM; formatstr = argv[narg]; } else { fprintf (stderr, "Format type '%s' not supported.\n" "See -help for details.\n", argv[narg]); exit (1); } ++narg; } else if (strcmp(argv[narg],"-sel") == 0) { ++narg; if (narg >= argc) { fprintf (stderr, "need argument after -sel "); exit (1); } sel = argv[narg]; ++narg; } else if (strncmp(argv[narg],"-d",2) == 0) { oform = CCALC_DOUBLE; ++narg; } else if (strncmp(argv[narg],"-n",2) == 0) { oform = CCALC_NICE; ++narg; } else if (strncmp(argv[narg],"-i",2) == 0) { oform = CCALC_INT; ++narg; } else if (strncmp(argv[narg],"-r",2) == 0) { oform = CCALC_INT; ++narg; } else if (strncmp(argv[narg],"-f",2) == 0) { oform = CCALC_FINT; ++narg; } else if (strncmp(argv[narg],"-c",2) == 0) { oform = CCALC_CINT; ++narg; } else { /* break if option is not recognized */ ++narg; break; } } /* read input files */ nim = argc-narg ; inim = (MRI_IMAGE **) malloc( sizeof(MRI_IMAGE *) * nim ) ; ncol = 0 ; if( nonconst || nonfixed ) MAKE_intvec(ncv,1) ; for( jj=0 ; jj < nim ; jj++ ){ #if 0 /** for testing only **/ if( AFNI_yesenv("ragged") ){ MRI_IMAGE *qim ; qim = mri_read_ascii_ragged( argv[jj+narg] , 3.e+33 ) ; fprintf(stderr,"qim: nx=%d ny=%d\n",qim->nx,qim->ny) ; inim[jj] = mri_transpose(qim) ; mri_free(qim) ; } else #endif if (sel) { fname = (char *) calloc((strlen(argv[jj+narg])+strlen(sel)+1), sizeof(char)); strcat(fname, argv[jj+narg]); strcat(fname, sel); } else { fname = argv[jj+narg]; } inim[jj] = mri_read_1D( fname ) ; if( inim[jj] == NULL ) ERROR_exit("Can't read input file '%s'",fname) ; if( jj > 0 && inim[jj]->nx != inim[0]->nx ) ERROR_exit("Input file %s doesn't match first file %s in length!", fname,argv[1]) ; ncold = ncol ; ncol += inim[jj]->ny ; if( ncv != NULL ){ /* check for constant columns [04 Dec 2010] */ RESIZE_intvec(ncv,ncol) ; for( kk=0 ; kk < inim[jj]->ny ; kk++ ) ncv->ar[ncold+kk] = 1 ; far = MRI_FLOAT_PTR(inim[jj]) ; nx = inim[jj]->nx ; if( nonconst ){ for( kk=0 ; kk < inim[jj]->ny ; kk++ ){ /* loop over columns */ for( ii=1 ; ii < nx ; ii++ ){ /* loop down column */ if( far[ii+kk*nx] != far[kk*nx] ) break ; } if( ii == nx ) ncv->ar[ncold+kk] = 0 ; /* constant */ } } if( nonfixed ){ char *hl = mri_read_1D_headerlines( fname ) ; if( hl != NULL && *hl == '#' ){ char *spt = strchr(hl,'\n') ; if( spt != NULL ) spt = strchr(spt,'#') ; /* start of line 2 */ if( spt != NULL ){ NI_str_array *sar = NI_decode_string_list( spt+1 , "~" ) ; if( sar != NULL && sar->num >= inim[jj]->ny ){ for( kk=0 ; kk < inim[jj]->ny ; kk++ ){ spt = strchr(sar->str[kk],'$') ; if( spt != NULL && spt[1] == '\0' ) ncv->ar[ncold+kk] = 0 ; else { if( hline == NULL ) hline = strdup("#") ; hline = THD_zzprintf( hline , " %s" , sar->str[kk] ) ; } } } NI_delete_str_array(sar) ; } } } } /* end of computing ncv = array marking non-constant vectors */ if (sel) { free(fname); fname = NULL; } } /* end of input loop */ /* now do the output */ if( hline != NULL ) printf("%s\n",hline) ; nx = inim[0]->nx ; if (stack) { if (oform == CCALC_NOT_SET) { for( cc=jj=0 ; jj < nim ; jj++ ){ far = MRI_FLOAT_PTR(inim[jj]) ; for( kk=0 ; kk < inim[jj]->ny ; kk++,cc++ ){ for( ii=0 ; ii < nx ; ii++ ){ if( ncv == NULL || ncv->ar[cc] ) printf(" %g\n", far[ii+kk*nx] ) ; } } } } else { for( cc=jj=0 ; jj < nim ; jj++ ){ far = MRI_FLOAT_PTR(inim[jj]) ; for( kk=0 ; kk < inim[jj]->ny ; kk++,cc++ ){ for( ii=0 ; ii < nx ; ii++ ){ if( ncv == NULL || ncv->ar[cc] ) printf(" %s\n", format_value_4print(far[ii+kk*nx], oform, formatstr )); } } } } } else { if (oform == CCALC_NOT_SET) { for( ii=0 ; ii < nx ; ii++ ){ for( cc=jj=0 ; jj < nim ; jj++ ){ far = MRI_FLOAT_PTR(inim[jj]) ; for( kk=0 ; kk < inim[jj]->ny ; kk++,cc++ ){ if( ncv == NULL || ncv->ar[cc] ) printf(" %g", far[ii+kk*nx] ) ; /* printf(" %+.2f", far[ii+kk*nx] ) ;*/ } } printf("\n") ; } } else { for( ii=0 ; ii < nx ; ii++ ){ for( cc=jj=0 ; jj < nim ; jj++ ){ far = MRI_FLOAT_PTR(inim[jj]) ; for( kk=0 ; kk < inim[jj]->ny ; kk++,cc++ ){ if( ncv == NULL || ncv->ar[cc] ) printf(" %s", format_value_4print(far[ii+kk*nx], oform, formatstr )); } } printf("\n") ; } } } exit(0) ; }