MRI_IMAGE * mri_bport( float dt, float fbot, float ftop, int nblock, int *ntim ) { MRI_IMAGE *tim ; MRI_IMARR *bimar ; int nrow , nbef , naft , tt ; ENTRY("mri_bport") ; if( nblock <= 0 || ntim == NULL ) RETURN(NULL) ; if( nblock == 1 ){ tim = mri_bport_contig( dt,fbot,ftop , ntim[0],0,0 ) ; RETURN(tim) ; } for( nrow=tt=0 ; tt < nblock ; tt++ ){ if( ntim[tt] < 9 ) RETURN(NULL) ; nrow += ntim[tt] ; } INIT_IMARR(bimar) ; nbef = 0 ; naft = nrow - ntim[0] ; for( tt=0 ; tt < nblock ; tt++ ){ tim = mri_bport_contig( dt,fbot,ftop , ntim[tt],nbef,naft ) ; if( tim == NULL ){ DESTROY_IMARR(bimar) ; RETURN(NULL) ; } ADDTO_IMARR(bimar,tim) ; if( tt < nblock-1 ){ nbef += ntim[tt]; naft -= ntim[tt+1]; } } tim = mri_catvol_1D( bimar , 2 ) ; DESTROY_IMARR(bimar) ; RETURN(tim) ; }
THD_3dim_dataset * THD_detrend_dataset( THD_3dim_dataset *dset , int nref , float **ref , int meth , int scl , byte *mask , MRI_IMARR **imar ) { MRI_IMARR *qmar ; int ii,jj,kk , nvals,nvox , iv ; float *var ; THD_3dim_dataset *newset ; ENTRY("THD_detrend_dataset") ; if( !ISVALID_DSET(dset) ) RETURN(NULL) ; nvals = DSET_NVALS(dset) ; nvox = DSET_NVOX(dset) ; qmar = THD_time_fit_dataset( dset , nref,ref , meth , mask ) ; if( qmar == NULL ) RETURN(NULL) ; newset = EDIT_empty_copy(dset) ; for( iv=0 ; iv < nvals ; iv++ ){ EDIT_substitute_brick( newset , iv , MRI_float , NULL ) ; EDIT_BRICK_FACTOR( newset , iv , 0.0f ) ; /* 04 Jun 2007 */ } var = (float *)malloc(sizeof(float)*nvals) ; for( ii=0 ; ii < nvox ; ii++ ){ if( mask == NULL || mask[ii] ) THD_extract_detrended_array( dset , nref,ref , qmar , ii,scl , var ) ; else memset(var,0,sizeof(float)*nvals) ; THD_insert_series( ii , newset , nvals , MRI_float , var , 0 ) ; } free(var) ; if( imar != NULL ) *imar = qmar ; else DESTROY_IMARR(qmar) ; RETURN(newset) ; }
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) ; }
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) ; }
MRI_IMARR * THD_get_many_timeseries( THD_string_array * dlist ) { int id , ii , ndir ; MRI_IMARR * outar=NULL, * tmpar=NULL ; char * epath , * eee ; char efake[] = "./" ; THD_string_array *qlist ; /* 02 Feb 2002 */ ENTRY("THD_get_many_timeseries") ; /*----- sanity check and initialize -----*/ epath = my_getenv( "AFNI_TSPATH" ) ; if( epath == NULL ) epath = my_getenv( "AFNI_TS_PATH" ) ; /* 07 Oct 1996 */ if( epath == NULL ) epath = efake ; /* 07 Oct 1996 */ ndir = (dlist != NULL) ? dlist->num : 0 ; if( ndir == 0 && epath == NULL ) RETURN( outar ) ; INIT_IMARR( outar ) ; INIT_SARR( qlist ) ; /*----- for each input directory, find all *.1D files -----*/ for( id=0 ; id < ndir ; id++ ){ ADDTO_SARR(qlist,dlist->ar[id]) ; tmpar = THD_get_all_timeseries( dlist->ar[id] ) ; if( tmpar == NULL ) continue ; for( ii=0 ; ii < tmpar->num ; ii++ ) /* move images to output array */ ADDTO_IMARR( outar , tmpar->imarr[ii] ) ; FREE_IMARR(tmpar) ; /* don't need this no more */ } /*----- also do directories in environment path, if any -----*/ if( epath != NULL ){ int epos =0 , ll = strlen(epath) ; char * elocal ; char ename[THD_MAX_NAME] ; /* copy path list into local memory */ elocal = (char *) malloc( sizeof(char) * (ll+2) ) ; if( elocal == NULL ){ fprintf(stderr, "\n*** THD_get_many_timeseries malloc failure - is memory full? ***\n"); EXIT(1) ; } strcpy( elocal , epath ) ; elocal[ll] = ' ' ; elocal[ll+1] = '\0' ; /* replace colons with blanks */ for( ii=0 ; ii < ll ; ii++ ) if( elocal[ii] == ':' ) elocal[ii] = ' ' ; /* extract blank delimited strings, use as directory names to get timeseries files */ do{ ii = sscanf( elocal+epos , "%s%n" , ename , &id ) ; if( ii < 1 ) break ; /* no read --> end of work */ epos += id ; /* epos = char after last one scanned */ ii = strlen(ename) ; /* make sure name has */ if( ename[ii-1] != '/' ){ /* a trailing '/' on it */ ename[ii] = '/' ; ename[ii+1] = '\0' ; } if( !THD_is_directory(ename) ) continue ; /* 21 May 2002 - rcr */ /* 02 Feb 2002: check if scanned this directory before */ for( ii=0 ; ii < qlist->num ; ii++ ) if( THD_equiv_files(qlist->ar[ii],ename) ) break ; if( ii < qlist->num ) continue ; /* skip to end of do loop */ ADDTO_SARR(qlist,ename) ; tmpar = THD_get_all_timeseries( ename ) ; /* read this directory */ if( tmpar != NULL ){ for( ii=0 ; ii < tmpar->num ; ii++ ) /* move images to output array */ ADDTO_IMARR( outar , tmpar->imarr[ii] ) ; FREE_IMARR(tmpar) ; /* don't need this no more */ } } while( epos < ll ) ; /* scan until 'epos' is after end of epath */ free(elocal) ; } if( IMARR_COUNT(outar) == 0 ) DESTROY_IMARR(outar) ; DESTROY_SARR(qlist) ; RETURN( outar ) ; }
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 *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) ; }
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[] ) { int iarg , nerr=0 , nvals,nvox , nx,ny,nz , ii,jj,kk ; char *prefix="LSSout" , *save1D=NULL , nbuf[256] ; THD_3dim_dataset *inset=NULL , *outset ; MRI_vectim *inset_mrv=NULL ; byte *mask=NULL ; int mask_nx=0,mask_ny=0,mask_nz=0, automask=0, nmask=0 ; NI_element *nelmat=NULL ; char *matname=NULL ; char *cgl ; int Ngoodlist,*goodlist=NULL , nfull , ncmat,ntime ; NI_int_array *giar ; NI_str_array *gsar ; NI_float_array *gfar ; MRI_IMAGE *imX, *imA, *imC, *imS ; float *Xar, *Sar ; MRI_IMARR *imar ; int nS ; float *ss , *oo , *fv , sum ; int nvec , iv ; int nbstim , nst=0 , jst_bot,jst_top ; char *stlab="LSS" ; int nodata=1 ; /*--- help me if you can ---*/ if( argc < 2 || strcasecmp(argv[1],"-HELP") == 0 ) LSS_help() ; /*--- bureaucratic startup ---*/ PRINT_VERSION("3dLSS"); mainENTRY("3dLSS main"); machdep(); AFNI_logger("3dLSS",argc,argv); AUTHOR("RWCox"); (void)COX_clock_time() ; /**------- scan command line --------**/ iarg = 1 ; while( iarg < argc ){ if( strcmp(argv[iarg],"-verb") == 0 ){ verb++ ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-VERB") == 0 ){ verb+=2 ; iarg++ ; continue ; } /**========== -mask ==========**/ if( strcasecmp(argv[iarg],"-mask") == 0 ){ THD_3dim_dataset *mset ; if( ++iarg >= argc ) ERROR_exit("Need argument after '-mask'") ; if( mask != NULL || automask ) ERROR_exit("Can't have two mask inputs") ; mset = THD_open_dataset( argv[iarg] ) ; CHECK_OPEN_ERROR(mset,argv[iarg]) ; DSET_load(mset) ; CHECK_LOAD_ERROR(mset) ; mask_nx = DSET_NX(mset); mask_ny = DSET_NY(mset); mask_nz = DSET_NZ(mset); mask = THD_makemask( mset , 0 , 0.5f, 0.0f ) ; DSET_delete(mset) ; if( mask == NULL ) ERROR_exit("Can't make mask from dataset '%.33s'",argv[iarg]) ; nmask = THD_countmask( mask_nx*mask_ny*mask_nz , mask ) ; if( verb || nmask < 1 ) INFO_message("Number of voxels in mask = %d",nmask) ; if( nmask < 1 ) ERROR_exit("Mask is too small to process") ; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-automask") == 0 ){ if( mask != NULL ) ERROR_exit("Can't have -automask and -mask") ; automask = 1 ; iarg++ ; continue ; } /**========== -matrix ==========**/ if( strcasecmp(argv[iarg],"-matrix") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '%s'",argv[iarg-1]) ; if( nelmat != NULL ) ERROR_exit("More than 1 -matrix option!?"); nelmat = NI_read_element_fromfile( argv[iarg] ) ; /* read NIML file */ matname = argv[iarg]; if( nelmat == NULL || nelmat->type != NI_ELEMENT_TYPE ) ERROR_exit("Can't process -matrix file '%s'!?",matname) ; iarg++ ; continue ; } /**========== -nodata ===========**/ if( strcasecmp(argv[iarg],"-nodata") == 0 ){ nodata = 1 ; iarg++ ; continue ; } /**========== -input ==========**/ if( strcasecmp(argv[iarg],"-input") == 0 ){ if( inset != NULL ) ERROR_exit("Can't have two -input options!?") ; if( ++iarg >= argc ) ERROR_exit("Need argument after '%s'",argv[iarg-1]) ; inset = THD_open_dataset( argv[iarg] ) ; CHECK_OPEN_ERROR(inset,argv[iarg]) ; nodata = 0 ; iarg++ ; continue ; } /**========== -prefix =========**/ if( strcasecmp(argv[iarg],"-prefix") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '%s'",argv[iarg-1]) ; prefix = strdup(argv[iarg]) ; if( !THD_filename_ok(prefix) ) ERROR_exit("Illegal string after %s",argv[iarg-1]) ; if( verb && strcmp(prefix,"NULL") == 0 ) INFO_message("-prefix NULL ==> no dataset will be written") ; iarg++ ; continue ; } /**========== -save1D =========**/ if( strcasecmp(argv[iarg],"-save1D") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '%s'",argv[iarg-1]) ; save1D = strdup(argv[iarg]) ; if( !THD_filename_ok(save1D) ) ERROR_exit("Illegal string after %s",argv[iarg-1]) ; iarg++ ; continue ; } /***** Loser User *****/ ERROR_message("Unknown option: %s",argv[iarg]) ; suggest_best_prog_option(argv[0], argv[iarg]); exit(1); } /* end of loop over options */ /*----- check for errors -----*/ if( nelmat == NULL ){ ERROR_message("No -matrix option!?") ; nerr++ ; } if( nerr > 0 ) ERROR_exit("Can't continue without these inputs!") ; if( inset != NULL ){ nvals = DSET_NVALS(inset) ; nvox = DSET_NVOX(inset) ; nx = DSET_NX(inset) ; ny = DSET_NY(inset) ; nz = DSET_NZ(inset) ; } else { automask = nvals = 0 ; nvox = nx = ny = nz = nodata = 1 ; /* nodata */ mask = NULL ; } /*----- masque -----*/ if( mask != NULL ){ /* check -mask option for compatibility */ if( mask_nx != nx || mask_ny != ny || mask_nz != nz ) ERROR_exit("-mask dataset grid doesn't match input dataset :-(") ; } else if( automask ){ /* create a mask from input dataset */ mask = THD_automask( inset ) ; if( mask == NULL ) ERROR_message("Can't create -automask from input dataset :-(") ; nmask = THD_countmask( nvox , mask ) ; if( verb || nmask < 1 ) INFO_message("Number of voxels in automask = %d (out of %d = %.1f%%)", nmask, nvox, (100.0f*nmask)/nvox ) ; if( nmask < 1 ) ERROR_exit("Automask is too small to process") ; } else if( !nodata ) { /* create a 'mask' for all voxels */ if( verb ) INFO_message("No mask ==> computing for all %d voxels",nvox) ; mask = (byte *)malloc(sizeof(byte)*nvox) ; nmask = nvox ; memset( mask , 1 , sizeof(byte)*nvox ) ; } /*----- get matrix info from the NIML element -----*/ if( verb ) INFO_message("extracting matrix info") ; ncmat = nelmat->vec_num ; /* number of columns */ ntime = nelmat->vec_len ; /* number of rows */ if( ntime < ncmat+2 ) ERROR_exit("Matrix has too many columns (%d) for number of rows (%d)",ncmat,ntime) ; /*--- number of rows in the full matrix (without censoring) ---*/ cgl = NI_get_attribute( nelmat , "NRowFull" ) ; if( cgl == NULL ) ERROR_exit("Matrix is missing 'NRowFull' attribute!") ; nfull = (int)strtod(cgl,NULL) ; if( nodata ){ nvals = nfull ; } else if( nvals != nfull ){ ERROR_exit("-input dataset has %d time points, but matrix indicates %d", nvals , nfull ) ; } /*--- the goodlist = mapping from matrix row index to time index (which allows for possible time point censoring) ---*/ cgl = NI_get_attribute( nelmat , "GoodList" ) ; if( cgl == NULL ) ERROR_exit("Matrix is missing 'GoodList' attribute!") ; giar = NI_decode_int_list( cgl , ";," ) ; if( giar == NULL || giar->num < ntime ) ERROR_exit("Matrix 'GoodList' badly formatted?!") ; Ngoodlist = giar->num ; goodlist = giar->ar ; if( Ngoodlist != ntime ) ERROR_exit("Matrix 'GoodList' incorrect length?!") ; else if( verb > 1 && Ngoodlist < nfull ) ININFO_message("censoring reduces time series length from %d to %d",nfull,Ngoodlist) ; /*--- extract the matrix from the NIML element ---*/ imX = mri_new( ntime , ncmat , MRI_float ) ; Xar = MRI_FLOAT_PTR(imX) ; if( nelmat->vec_typ[0] == NI_FLOAT ){ /* from 3dDeconvolve_f */ float *cd ; for( jj=0 ; jj < ncmat ; jj++ ){ cd = (float *)nelmat->vec[jj] ; for( ii=0 ; ii < ntime ; ii++ ) Xar[ii+jj*ntime] = cd[ii] ; } } else if( nelmat->vec_typ[0] == NI_DOUBLE ){ /* from 3dDeconvolve */ double *cd ; for( jj=0 ; jj < ncmat ; jj++ ){ cd = (double *)nelmat->vec[jj] ; for( ii=0 ; ii < ntime ; ii++ ) Xar[ii+jj*ntime] = cd[ii] ; } } else { ERROR_exit("Matrix file stored with illegal data type!?") ; } /*--- find the stim_times_IM option ---*/ cgl = NI_get_attribute( nelmat , "BasisNstim") ; if( cgl == NULL ) ERROR_exit("Matrix doesn't have 'BasisNstim' attribute!") ; nbstim = (int)strtod(cgl,NULL) ; if( nbstim <= 0 ) ERROR_exit("Matrix 'BasisNstim' attribute is %d",nbstim) ; for( jj=1 ; jj <= nbstim ; jj++ ){ sprintf(nbuf,"BasisOption_%06d",jj) ; cgl = NI_get_attribute( nelmat , nbuf ) ; if( cgl == NULL || strcmp(cgl,"-stim_times_IM") != 0 ) continue ; if( nst > 0 ) ERROR_exit("More than one -stim_times_IM option was found in the matrix") ; nst = jj ; sprintf(nbuf,"BasisColumns_%06d",jj) ; cgl = NI_get_attribute( nelmat , nbuf ) ; if( cgl == NULL ) ERROR_exit("Matrix doesn't have %s attribute!",nbuf) ; jst_bot = jst_top = -1 ; sscanf(cgl,"%d:%d",&jst_bot,&jst_top) ; if( jst_bot < 0 || jst_top < 0 ) ERROR_exit("Can't decode matrix attribute %s",nbuf) ; if( jst_bot == jst_top ) ERROR_exit("Matrix attribute %s shows only 1 column for -stim_time_IM:\n" " -->> 3dLSS is meant to be used when more than one stimulus\n" " time was given, and then it computes the response beta\n" " for each stim time separately. If you have only one\n" " stim time with -stim_times_IM, you can use the output\n" " dataset from 3dDeconvolve (or 3dREMLfit) to get that\n" " single beta directly.\n" , nbuf ) ; if( jst_bot >= jst_top || jst_top >= ncmat ) ERROR_exit("Matrix attribute %s has illegal value: %d:%d (ncmat=%d)",nbuf,jst_bot,jst_top,ncmat) ; sprintf(nbuf,"BasisName_%06d",jj) ; cgl = NI_get_attribute( nelmat , nbuf ) ; if( cgl != NULL ) stlab = strdup(cgl) ; if( verb > 1 ) ININFO_message("-stim_times_IM at stim #%d; cols %d..%d",jj,jst_bot,jst_top) ; } if( nst == 0 ) ERROR_exit("Matrix doesn't have any -stim_times_IM options inside :-(") ; /*--- mangle matrix to segregate IM regressors from the rest ---*/ if( verb ) INFO_message("setting up LSS vectors") ; imar = LSS_mangle_matrix( imX , jst_bot , jst_top ) ; if( imar == NULL ) ERROR_exit("Can't compute LSS 'mangled' matrix :-(") ; /*--- setup for LSS computations ---*/ imA = IMARR_SUBIM(imar,0) ; imC = IMARR_SUBIM(imar,1) ; imS = LSS_setup( imA , imC ) ; DESTROY_IMARR(imar) ; if( imS == NULL ) ERROR_exit("Can't complete LSS setup :-((") ; nS = imS->ny ; Sar = MRI_FLOAT_PTR(imS) ; if( save1D != NULL ){ mri_write_1D( save1D , imS ) ; if( verb ) ININFO_message("saved LSS vectors into file %s",save1D) ; } else if( nodata ){ WARNING_message("-nodata used but -save1D not used ==> you get no output!") ; } if( nodata || strcmp(prefix,"NULL") == 0 ){ INFO_message("3dLSS ends since prefix is 'NULL' or -nodata was used") ; exit(0) ; } /*----- create output dataset -----*/ if( verb ) INFO_message("creating output datset in memory") ; outset = EDIT_empty_copy(inset) ; EDIT_dset_items( outset , ADN_prefix , prefix , ADN_datum_all , MRI_float , ADN_brick_fac , NULL , ADN_nvals , nS , ADN_ntt , nS , ADN_none ) ; tross_Copy_History( inset , outset ) ; tross_Make_History( "3dLSS" , argc,argv , outset ) ; for( kk=0 ; kk < nS ; kk++ ){ EDIT_substitute_brick( outset , kk , MRI_float , NULL ) ; sprintf(nbuf,"%s#%03d",stlab,kk) ; EDIT_BRICK_LABEL( outset , kk , nbuf ) ; } /*----- convert input dataset to vectim -----*/ if( verb ) INFO_message("loading input dataset into memory") ; DSET_load(inset) ; CHECK_LOAD_ERROR(inset) ; inset_mrv = THD_dset_to_vectim( inset , mask , 0 ) ; DSET_unload(inset) ; /*----- compute dot products, store results -----*/ if( verb ) INFO_message("computing away, me buckos!") ; nvec = inset_mrv->nvec ; for( kk=0 ; kk < nS ; kk++ ){ ss = Sar + kk*ntime ; oo = DSET_ARRAY(outset,kk) ; for( iv=0 ; iv < nvec ; iv++ ){ fv = VECTIM_PTR(inset_mrv,iv) ; for( sum=0.0f,ii=0 ; ii < ntime ; ii++ ) sum += ss[ii] * fv[goodlist[ii]] ; oo[inset_mrv->ivec[iv]] = sum ; } } DSET_write(outset) ; WROTE_DSET(outset) ; /*-------- Hasta la vista, baby --------*/ if( verb ) INFO_message("3dLSS finished: total CPU=%.2f Elapsed=%.2f", COX_cpu_time() , COX_clock_time() ) ; exit(0) ; }
MRI_IMAGE * LSS_setup( MRI_IMAGE *ima , MRI_IMAGE *imc ) { int nn, mm, nc, ii, jj, ic , nwarn=0 ; float *cc, *pp, *qq, *qj, *vv, *ss, *pv , cj, cvdot, pc ; MRI_IMAGE *ims , *imp , *imq ; MRI_IMARR *imar ; ENTRY("LSS_setup") ; if( ima == NULL || imc == NULL ){ /* bad user */ ERROR_message("LSS_setup: NULL input image?!") ; RETURN(NULL) ; } /* [A] is nn X mm ; [C] is nn x nc */ nn = ima->nx ; mm = ima->ny ; nc = imc->ny ; cc = MRI_FLOAT_PTR(imc) ; if( imc->nx != nn || nn <= mm+2 ){ /* stoopid user */ ERROR_message("LSS_setup: ima->nx=%d does not equal imc->nx=%d :-(" , ima->nx,imc->nx) ; RETURN(NULL) ; } /* get imp = [P] = psinv of [A] = mm X nn matrix imq = [Q] = ortproj onto column null space of [A] = nn X nn matrix */ mri_matrix_psinv_svd(1) ; imar = mri_matrix_psinv_ortproj( ima , 1 ) ; if( imar == NULL ){ /* should not happen */ ERROR_message("LSS_setup: cannot compute pseudo-inverse :-(") ; RETURN(NULL) ; } imp = IMARR_SUBIM(imar,0) ; pp = MRI_FLOAT_PTR(imp) ; imq = IMARR_SUBIM(imar,1) ; qq = MRI_FLOAT_PTR(imq) ; /* create output image = [S] = nn X nc Each column of [S] is the vector that we dot into a data vector [z] to get the estimate of gamma+delta for the corresponding column from [C] */ ims = mri_new(nn,nc,MRI_float) ; ss = MRI_FLOAT_PTR(ims) ; /* workspace vectors */ vv = (float *)malloc(sizeof(float)*nn) ; /* will be [Q] [c] */ pv = (float *)malloc(sizeof(float)*nn) ; /* last row of [P] */ for( ii=0 ; ii < nn ; ii++ ) pv[ii] = pp[ mm-1 + ii*mm ] ; /* loop over columns of [C] (and [S]) */ for( ic=0 ; ic < nc ; ic++,cc+=nn,ss+=nn ){ /* compute [v] = [Q] [c] */ for( ii=0 ; ii < nn ; ii++ ) vv[ii] = 0.0f ; /* initialize [v] to 0 */ for( jj=0 ; jj < nn ; jj++ ){ /* loop over columns of Q */ qj = qq + jj*nn ; /* ptr to jj-th column of Q */ cj = cc[jj] ; /* jj-th value of [c] */ for( ii=0 ; ii < nn ; ii++ ) vv[ii] += qj[ii] * cj ; /* sum into [v] */ } /* compute cvdot = [c] *dot* [v] cj = [c] *dot* [c] pc = [c] *dot* {last row of [P] = pv} */ for( pc=cj=cvdot=ii=0 ; ii < nn ; ii++ ){ cvdot += cc[ii]*vv[ii] ; cj += cc[ii]*cc[ii] ; pc += pv[ii]*cc[ii] ; } /* initialize [s] = last row of [P] */ for( ii=0 ; ii < nn ; ii++ ) ss[ii] = pv[ii] ; /* If cvdot is zero(ish), this means that the extra column [c] is collinear(ish) with the columns of [A], and we skip the next step. Note that since [Q] is an orthogonal matrix, we are guaranteed that L2norm([Q][c]) == L2norm([c]), which implies that abs(cvdot) <= abs(cj), by the triangle inequality. */ if( fabsf(cvdot) >= 1.e-5*cj ){ /* add the proper fraction of [v] into [s] */ pc = (1.0f - pc) / cvdot ; for( ii=0 ; ii < nn ; ii++ ) ss[ii] += pc * vv[ii] ; } else { nwarn++ ; } } /* end of loop over columns of [C] */ if( verb && nwarn > 0 ) INFO_message("%d (out of %d) LSS individual estimators were collinear", nwarn , nc ) ; /* toss the trash and return the output set of columns */ free(pv) ; free(vv) ; DESTROY_IMARR(imar) ; RETURN(ims) ; }
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) ; }
MRI_IMARR * THD_extract_many_series( int ns, int *ind, THD_3dim_dataset *dset ) { MRI_IMARR *imar ; /* output */ MRI_IMAGE *im ; int nv , ival , kk ; char *iar ; /* brick in the input */ float **far ; /* 27 Feb 2003: ptrs to output */ ENTRY("THD_extract_many_series") ; if( ns <= 0 || ind == NULL | dset == NULL ) RETURN( NULL ); /* try to load dataset */ nv = dset->dblk->nvals ; iar = DSET_ARRAY(dset,0) ; if( iar == NULL ){ /* if data needs to be loaded from disk */ (void) THD_load_datablock( dset->dblk ) ; iar = DSET_ARRAY(dset,0) ; if( iar == NULL ){ static int nerr=0 ; if( nerr < 2 ){ ERROR_message("Can't load dataset %s",DSET_HEADNAME(dset)); nerr++; } RETURN( NULL ); } } /* create output */ far = (float **) malloc(sizeof(float *)*ns) ; /* 27 Feb 2003 */ NULL_CHECK(far) ; INIT_IMARR(imar) ; for( kk=0 ; kk < ns ; kk++ ){ im = mri_new( nv , 1 , MRI_float ) ; /* N.B.: now does 0 fill */ far[kk] = MRI_FLOAT_PTR(im) ; /* ptr to kk-th output series */ ADDTO_IMARR(imar,im) ; } /* fill the output */ switch( DSET_BRICK_TYPE(dset,0) ){ default: /* don't know what to do --> return nada */ DESTROY_IMARR(imar) ; free(far) ; RETURN( NULL ); case MRI_byte:{ byte * bar ; for( ival=0 ; ival < nv ; ival++ ){ bar = (byte *) DSET_ARRAY(dset,ival) ; if( bar != NULL ){ for( kk=0 ; kk < ns ; kk++ ){ far[kk][ival] = (float)bar[ind[kk]] ; } } } } break ; case MRI_short:{ short * bar ; for( ival=0 ; ival < nv ; ival++ ){ bar = (short *) DSET_ARRAY(dset,ival) ; if( bar != NULL ){ for( kk=0 ; kk < ns ; kk++ ){ far[kk][ival] = (float)bar[ind[kk]] ; } } } } break ; case MRI_float:{ float * bar ; for( ival=0 ; ival < nv ; ival++ ){ bar = (float *) DSET_ARRAY(dset,ival) ; if( bar != NULL ){ for( kk=0 ; kk < ns ; kk++ ){ far[kk][ival] = bar[ind[kk]] ; } } } } break ; #if 0 case MRI_int:{ int * bar ; for( ival=0 ; ival < nv ; ival++ ){ bar = (int *) DSET_ARRAY(dset,ival) ; if( bar != NULL ){ for( kk=0 ; kk < ns ; kk++ ){ far[kk][ival] = bar[ind[kk]] ; } } } } break ; case MRI_double:{ double * bar ; for( ival=0 ; ival < nv ; ival++ ){ bar = (double *) DSET_ARRAY(dset,ival) ; if( bar != NULL ){ for( kk=0 ; kk < ns ; kk++ ){ far[kk][ival] = (float)bar[ind[kk]] ; } } } } break ; #endif case MRI_complex:{ complex * bar ; for( ival=0 ; ival < nv ; ival++ ){ bar = (complex *) DSET_ARRAY(dset,ival) ; if( bar != NULL ){ for( kk=0 ; kk < ns ; kk++ ){ far[kk][ival] = bar[ind[kk]].r ; } } } } break ; } /* scale outputs, if needed */ if( THD_need_brick_factor(dset) ){ MRI_IMAGE *qim ; for( kk=0 ; kk < ns ; kk++ ){ im = IMARR_SUBIMAGE(imar,kk) ; qim = mri_mult_to_float( dset->dblk->brick_fac , im ) ; mri_free(im) ; IMARR_SUBIMAGE(imar,kk) = qim ; } } #if 0 /* 27 Feb 2003 */ /* convert to floats, if needed */ if( IMARR_SUBIMAGE(imar,0)->kind != MRI_float ){ MRI_IMAGE * qim ; for( kk=0 ; kk < ns ; kk++ ){ im = IMARR_SUBIMAGE(imar,kk) ; qim = mri_to_float( im ) ; mri_free(im) ; IMARR_SUBIMAGE(imar,kk) = qim ; } } #endif /* add time axis stuff to output images, if present */ if( dset->taxis != NULL ){ float zz , tt ; int kz ; for( kk=0 ; kk < ns ; kk++ ){ kz = ind[kk] / ( dset->daxes->nxx * dset->daxes->nyy ) ; zz = dset->daxes->zzorg + kz * dset->daxes->zzdel ; tt = THD_timeof( 0 , zz , dset->taxis ) ; im = IMARR_SUBIMAGE(imar,kk) ; im->xo = tt ; im->dx = dset->taxis->ttdel ; /* origin and delta */ if( dset->taxis->units_type == UNITS_MSEC_TYPE ){ /* convert to sec */ im->xo *= 0.001 ; im->dx *= 0.001 ; } } } else { for( kk=0 ; kk < ns ; kk++ ){ im = IMARR_SUBIMAGE(imar,kk) ; im->xo = 0.0 ; im->dx = 1.0 ; } } free(far) ; RETURN(imar); }
char * IMREG_main( PLUGIN_interface * plint ) { MCW_idcode * idc ; /* input dataset idcode */ THD_3dim_dataset * old_dset , * new_dset ; /* input and output datasets */ char * new_prefix , * str ; /* strings from user */ int base , ntime , datum , nx,ny,nz , ii,kk , npix ; float dx,dy,dz ; MRI_IMARR * ims_in , * ims_out ; MRI_IMAGE * im , * imbase ; byte ** bptr = NULL , ** bout = NULL ; short ** sptr = NULL , ** sout = NULL ; float ** fptr = NULL , ** fout = NULL ; float * dxar = NULL , * dyar = NULL , * phiar = NULL ; /*--------------------------------------------------------------------*/ /*----- Check inputs from AFNI to see if they are reasonable-ish -----*/ /*--------- go to first input line ---------*/ PLUTO_next_option(plint) ; idc = PLUTO_get_idcode(plint) ; /* get dataset item */ old_dset = PLUTO_find_dset(idc) ; /* get ptr to dataset */ if( old_dset == NULL ) return "*************************\n" "Cannot find Input Dataset\n" "*************************" ; ntime = DSET_NUM_TIMES(old_dset) ; if( ntime < 2 ) return "*****************************\n" "Dataset has only 1 time point\n" "*****************************" ; ii = DSET_NVALS_PER_TIME(old_dset) ; if( ii > 1 ) return "************************************\n" "Dataset has > 1 value per time point\n" "************************************" ; nx = old_dset->daxes->nxx ; dx = old_dset->daxes->xxdel ; ny = old_dset->daxes->nyy ; dy = old_dset->daxes->yydel ; npix = nx*ny ; nz = old_dset->daxes->nzz ; dz = old_dset->daxes->zzdel ; if( nx != ny || fabs(dx) != fabs(dy) ) { #ifdef IMREG_DEBUG fprintf(stderr,"\nIMREG: nx=%d ny=%d nz=%d dx=%f dy=%f dz=%f\n", nx,ny,nz,dx,dy,dz ) ; #endif return "***********************************\n" "Dataset does not have square slices\n" "***********************************" ; } new_prefix = PLUTO_get_string(plint) ; /* get string item (the output prefix) */ if( ! PLUTO_prefix_ok(new_prefix) ) /* check if it is OK */ return "************************\n" "Output Prefix is illegal\n" "************************" ; /*--------- go to next input line ---------*/ PLUTO_next_option(plint) ; base = PLUTO_get_number(plint) ; if( base >= ntime ) return "********************\n" "Base value too large\n" "********************" ; /*--------- see if the 3rd option line is present --------*/ str = PLUTO_get_optiontag( plint ) ; if( str != NULL ) { float fsig , fdxy , fdph ; fsig = PLUTO_get_number(plint) * 0.42466090 ; fdxy = PLUTO_get_number(plint) ; fdph = PLUTO_get_number(plint) ; mri_align_params( 0 , 0.0,0.0,0.0 , fsig,fdxy,fdph ) ; /* fprintf(stderr,"Set fine params = %f %f %f\n",fsig,fdxy,fdph) ; */ } /*------------- ready to compute new dataset -----------*/ #ifdef IMREG_DEBUG fprintf(stderr,"IMREG: loading dataset\n") ; #endif DSET_load( old_dset ) ; /*** 1) Copy the dataset in toto ***/ #ifdef IMREG_DEBUG fprintf(stderr,"IMREG: Copying dataset\n") ; #endif new_dset = PLUTO_copy_dset( old_dset , new_prefix ) ; if( new_dset == NULL ) return "****************************\n" "Failed to copy input dataset\n" "****************************" ; /*** 2) Make an array of empty images ***/ #ifdef IMREG_DEBUG fprintf(stderr,"IMREG: making empty images\n") ; #endif datum = DSET_BRICK_TYPE(new_dset,0) ; INIT_IMARR(ims_in) ; for( ii=0 ; ii < ntime ; ii++ ) { im = mri_new_vol_empty( nx , ny , 1 , datum ) ; ADDTO_IMARR(ims_in,im) ; } imbase = mri_new_vol_empty( nx , ny , 1 , datum ) ; dxar = (float *) malloc( sizeof(float) * ntime ) ; dyar = (float *) malloc( sizeof(float) * ntime ) ; phiar = (float *) malloc( sizeof(float) * ntime ) ; /*** 3) Get pointers to sub-bricks in old and new datasets ***/ #ifdef IMREG_DEBUG fprintf(stderr,"IMREG: getting input brick pointers\n") ; #endif switch( datum ) { /* pointer type depends on input datum type */ case MRI_byte: bptr = (byte **) malloc( sizeof(byte *) * ntime ) ; bout = (byte **) malloc( sizeof(byte *) * ntime ) ; for( ii=0 ; ii < ntime ; ii++ ) { bptr[ii] = (byte *) DSET_ARRAY(old_dset,ii) ; bout[ii] = (byte *) DSET_ARRAY(new_dset,ii) ; } break ; case MRI_short: sptr = (short **) malloc( sizeof(short *) * ntime ) ; sout = (short **) malloc( sizeof(short *) * ntime ) ; for( ii=0 ; ii < ntime ; ii++ ) { sptr[ii] = (short *) DSET_ARRAY(old_dset,ii) ; sout[ii] = (short *) DSET_ARRAY(new_dset,ii) ; } #ifdef IMREG_DEBUG fprintf(stderr,"IMREG: sptr[0] = %p sout[0] = %p\n",sptr[0],sout[0]) ; #endif break ; case MRI_float: fptr = (float **) malloc( sizeof(float *) * ntime ) ; fout = (float **) malloc( sizeof(float *) * ntime ) ; for( ii=0 ; ii < ntime ; ii++ ) { fptr[ii] = (float *) DSET_ARRAY(old_dset,ii) ; fout[ii] = (float *) DSET_ARRAY(new_dset,ii) ; } break ; } /*** 4) Loop over slices ***/ PLUTO_popup_meter(plint) ; for( kk=0 ; kk < nz ; kk++ ) { /*** 4a) Setup ims_in images to point to input slices ***/ #ifdef IMREG_DEBUG fprintf(stderr,"IMREG: slice %d -- setup input images\n",kk) ; #endif for( ii=0 ; ii < ntime ; ii++ ) { im = IMARR_SUBIMAGE(ims_in,ii) ; switch( datum ) { case MRI_byte: mri_fix_data_pointer( bptr[ii] + kk*npix, im ) ; break ; case MRI_short: mri_fix_data_pointer( sptr[ii] + kk*npix, im ) ; break ; case MRI_float: mri_fix_data_pointer( fptr[ii] + kk*npix, im ) ; break ; } } /*** 4b) Setup im to point to base image ***/ #ifdef IMREG_DEBUG fprintf(stderr,"IMREG: slice %d -- setup base image\n",kk) ; #endif switch( datum ) { case MRI_byte: mri_fix_data_pointer( bptr[base] + kk*npix, imbase ) ; break ; case MRI_short: mri_fix_data_pointer( sptr[base] + kk*npix, imbase ) ; break ; case MRI_float: mri_fix_data_pointer( fptr[base] + kk*npix, imbase ) ; break ; } /*** 4c) Register this slice at all times ***/ #ifdef IMREG_DEBUG fprintf(stderr,"IMREG: slice %d -- register\n",kk) ; #endif ims_out = mri_align_dfspace( imbase , NULL , ims_in , ALIGN_REGISTER_CODE , dxar,dyar,phiar ) ; if( ims_out == NULL ) fprintf(stderr,"IMREG: mri_align_dfspace return NULL\n") ; /*** 4d) Put the output back in on top of the input; note that the output is always in MRI_float format ***/ #ifdef IMREG_DEBUG fprintf(stderr,"IMREG: slice %d -- put output back into dataset\n",kk) ; #endif for( ii=0 ; ii < ntime ; ii++ ) { switch( datum ) { case MRI_byte: im = mri_to_mri( MRI_byte , IMARR_SUBIMAGE(ims_out,ii) ) ; memcpy( bout[ii] + kk*npix , MRI_BYTE_PTR(im) , sizeof(byte)*npix ) ; mri_free(im) ; break ; case MRI_short: #ifdef IMREG_DEBUG if( ii==0 )fprintf(stderr,"IMREG: conversion to short at ii=%d\n",ii) ; #endif im = mri_to_mri( MRI_short , IMARR_SUBIMAGE(ims_out,ii) ) ; #ifdef IMREG_DEBUG if( ii==0 )fprintf(stderr,"IMREG: copying to %p from %p\n",sout[ii] + kk*npix,MRI_SHORT_PTR(im)) ; #endif memcpy( sout[ii] + kk*npix , MRI_SHORT_PTR(im) , sizeof(short)*npix ) ; #ifdef IMREG_DEBUG if( ii==0 )fprintf(stderr,"IMREG: freeing\n") ; #endif mri_free(im) ; break ; case MRI_float: im = IMARR_SUBIMAGE(ims_out,ii) ; memcpy( fout[ii] + kk*npix , MRI_FLOAT_PTR(im) , sizeof(float)*npix ) ; break ; } } PLUTO_set_meter(plint, (100*(kk+1))/nz ) ; /*** 4e) Destroy the output images ***/ #ifdef IMREG_DEBUG fprintf(stderr,"IMREG: destroying aligned output\n") ; #endif DESTROY_IMARR( ims_out ) ; } /*** 5) Destroy the empty images and other workspaces ***/ #ifdef IMREG_DEBUG fprintf(stderr,"IMREG: destroy workspaces\n") ; #endif mri_clear_data_pointer(imbase) ; mri_free(imbase) ; for( ii=0 ; ii < ntime ; ii++ ) { im = IMARR_SUBIMAGE(ims_in,ii) ; mri_clear_data_pointer(im) ; } DESTROY_IMARR(ims_in) ; FREE_WORKSPACE ; /*------------- let AFNI know about the new dataset ------------*/ #ifdef IMREG_DEBUG fprintf(stderr,"IMREG: send result to AFNI\n") ; #endif PLUTO_add_dset( plint , new_dset , DSET_ACTION_MAKE_CURRENT ) ; return NULL ; /* null string returned means all was OK */ }
int main( int argc , char *argv[] ) { int force=0 ; /* KRH loudly deprecating usage 04/13/05/ */ int iarg=1 ; THD_3dim_dataset *dset ; /* output dataset */ int nvals , ii , jj , kk ; MRI_IMARR *anar ; /* stuff from ANALYZE headers */ MRI_IMAGE *anim ; int nxan=0,nyan=0,nzan=0 , an_datum=0 , an_swapped=0 ; float dxan=-1.0,dyan=0.0,dzan=0.0 ; char anor[8] = "\0" ; THD_ivec3 nxyz , orixyz ; THD_fvec3 dxyz , orgxyz ; float TR=1.0 ; int tunits=UNITS_SEC_TYPE ; int is_fbuc=0 , is_abuc=0 , is_3dtime=0 ; int view_type=VIEW_ORIGINAL_TYPE ; char *prefix="a2a" ; int xorient=-1, yorient=-1, zorient=-1 ; int use_zoff=0,use_xoff=0,use_yoff=0 ; float zoff=0.0,xoff=0.0,yoff=0.0 ; THD_3dim_dataset *gset=NULL ; /* geometry parent */ float *fac ; char **flab , *fatr ; /*-- help the poor user? --*/ if( argc < 2 || strcmp(argv[1],"-help") == 0 ){ A2A_help(); exit(0); } mainENTRY("3dANALYZEtoAFNI main"); machdep(); PRINT_VERSION("3dANALYZEtoAFNI"); /*-- parse options --*/ while( iarg < argc && argv[iarg][0] == '-' ){ /* -prefix */ if( strcmp(argv[iarg],"-prefix") == 0 ){ if( ++iarg >= argc ){ fprintf(stderr,"** -prefix needs an argument!\n"); exit(1); } prefix = argv[iarg] ; if( !THD_filename_ok(prefix) ){ fprintf(stderr,"** Illegal prefix!\n"); exit(1); } if( strstr(prefix,"/") != NULL ){ fprintf(stderr,"** Can't use directory names in the prefix!\n"); exit(1); } iarg++ ; continue ; } /* -view */ if( strcmp(argv[iarg],"-view") == 0 ){ char *str ; if( ++iarg >= argc ){ fprintf(stderr,"** -view needs an argument!\n"); exit(1); } str = argv[iarg] ; if( str[0] == '+' ) str++ ; for( ii=FIRST_VIEW_TYPE ; ii <= LAST_VIEW_TYPE ; ii++ ) if( strcmp(str,VIEW_codestr[ii]) == 0 ) break ; if( ii <= LAST_VIEW_TYPE ){ view_type = ii ; } else { fprintf(stderr,"** Illegal -view code!\n"); exit(1); } iarg++ ; continue ; } /* -zorigin */ if( strcmp(argv[iarg],"-zorigin") == 0 ){ if( ++iarg >= argc ){ fprintf(stderr,"** -zorigin needs an argument!\n"); exit(1); } zoff = strtod( argv[iarg] , NULL ) ; use_zoff = 1 ; iarg++ ; continue ; } /* -orient */ #define ORCODE(aa) \ ( (aa)=='R' ? ORI_R2L_TYPE : (aa)=='L' ? ORI_L2R_TYPE : \ (aa)=='P' ? ORI_P2A_TYPE : (aa)=='A' ? ORI_A2P_TYPE : \ (aa)=='I' ? ORI_I2S_TYPE : (aa)=='S' ? ORI_S2I_TYPE : ILLEGAL_TYPE ) #define OR3OK(x,y,z) ( ((x)&6) + ((y)&6) + ((z)&6) == 6 ) if( strcmp(argv[iarg],"-orient") == 0 ){ char acod ; if( ++iarg >= argc ){ fprintf(stderr,"** -orient needs an argument!\n"); exit(1); } if( strlen(argv[iarg]) != 3 ){ fprintf(stderr,"** Illegal -orient code!\n"); exit(1); } acod = toupper(argv[iarg][0]) ; xorient = ORCODE(acod) ; acod = toupper(argv[iarg][1]) ; yorient = ORCODE(acod) ; acod = toupper(argv[iarg][2]) ; zorient = ORCODE(acod) ; if( xorient<0 || yorient<0 || zorient<0 || ! OR3OK(xorient,yorient,zorient) ){ fprintf(stderr,"** Unusable -orient code!\n"); exit(1); } iarg++ ; continue ; } /* -geomparent */ if( strcmp(argv[iarg],"-geomparent") == 0 ){ if( ++iarg >= argc ){ fprintf(stderr,"** -geomparent needs an argument!\n"); exit(1); } gset = THD_open_dataset( argv[iarg] ); CHECK_OPEN_ERROR(gset,argv[iarg]); iarg++ ; continue ; } /* -TR */ if( strcmp(argv[iarg],"-TR") == 0 ){ char *eptr ; if( ++iarg >= argc ){ fprintf(stderr,"** -geomparent needs an argument!\n"); exit(1); } TR = strtod( argv[iarg] , &eptr ) ; if( TR <= 0.0 ){ fprintf(stderr,"** -TR needs a positive value after it!\n"); exit(1); } if( strcmp(eptr,"ms")==0 || strcmp(eptr,"msec")==0 ){ tunits = UNITS_MSEC_TYPE ; WARNING_message("TR in millisecond units is deprecated.") ; } else if( strcmp(eptr,"s")==0 || strcmp(eptr,"sec")==0 ){ tunits = UNITS_SEC_TYPE ; } else if( strcmp(eptr,"Hz")==0 || strcmp(eptr,"Hertz")==0 ){ tunits = UNITS_HZ_TYPE ; } is_3dtime = 1 ; is_abuc = is_fbuc = 0 ; iarg++ ; continue ; } /* -fbuc */ if( strcmp(argv[iarg],"-fbuc") == 0 ){ is_fbuc = 1 ; is_abuc = is_3dtime = 0 ; iarg++ ; continue ; } /* -abuc */ if( strcmp(argv[iarg],"-abuc") == 0 ){ is_abuc = 1 ; is_fbuc = is_3dtime = 0 ; iarg++ ; continue ; } /* -OK */ if( strcmp(argv[iarg],"-OK") == 0 ){ force = 1 ; iarg++ ; continue ; } /** don't know this one **/ fprintf(stderr,"** Illegal option %s\n",argv[iarg]); exit(1); } if (!force) { A2A_help(); exit(0); } /*-- check number of remaining args --*/ nvals = argc - iarg ; if( nvals <= 0 ){ fprintf(stderr,"** No ANALYZE files on command line!?\n"); exit(1); } /*-- try to read each ANALYZE file and glean info from it --*/ CLEAR_MRILIB_globals ; /* setup */ fac = (float *) malloc(sizeof(float)*nvals) ; for( ii=iarg ; ii < argc ; ii++ ){ if( strstr(argv[ii],"/") != NULL ){ fprintf(stderr,"** ANALYZE files must all be in current directory!\n") ; exit(1) ; } anar = mri_read_analyze75( argv[ii] ) ; /* read it */ if( anar == NULL || IMARR_COUNT(anar) == 0 ){ fprintf(stderr,"** Can't read %s as ANALYZE-75 format .hdr file!\n",argv[ii]); exit(1) ; } anim = IMARR_SUBIM(anar,0) ; /* first 2D image */ fac[ii-iarg] = anim->dv ; /* save scale factor, if any */ if( ii == iarg ){ /* first time in: store header values */ nxan = anim->nx ; nyan = anim->ny ; nzan = IMARR_COUNT(anar) ; if( MRILIB_orients[0] != '\0' ) strcpy(anor,MRILIB_orients) ; an_datum = anim->kind ; if( anim->dw > 0.0 ){ dxan = anim->dx; dyan = anim->dy; dzan = anim->dz; } an_swapped = anim->was_swapped ; } else { /* check later sub-bricks */ if( nxan != anim->nx || nyan != anim->ny || nzan != IMARR_COUNT(anar) ){ fprintf(stderr,"** File %s has different dimensions than %s\n", argv[ii] , argv[iarg] ) ; exit(1) ; } if( an_datum != anim->kind ){ fprintf(stderr,"** File %s has different kind of data than %s\n", argv[ii] , argv[iarg] ) ; exit(1) ; } if( an_swapped != anim->was_swapped ){ fprintf(stderr,"** File %s %s byte-swapped, but %s %s\n", argv[ii] , (anim->was_swapped) ? "is" : "isn't" , argv[iarg] , (an_swapped) ? "is" : "isn't" ) ; exit(1) ; } if( anim->dw > 0.0 ){ if( dxan < 0.0 ){ dxan = anim->dx; dyan = anim->dy; dzan = anim->dz; } else { if( dxan != anim->dx || dyan != anim->dy || dzan != anim->dz ){ fprintf(stderr,"++ WARNING: File %s has variant voxel sizes!\n", argv[ii]) ; } } } if( anor[0] == '\0' && MRILIB_orients[0] != '\0' ) strcpy(anor,MRILIB_orients) ; } /* end of checking later volumes for compatibility */ /* destroy this data (we've sucked it dry) */ DESTROY_IMARR(anar) ; } /* end of loop over ANALYZE files */ /*-- check geomparent, if present --*/ if( gset != NULL ){ if( DSET_NX(gset)!=nxan || DSET_NY(gset)!=nyan || DSET_NZ(gset)!=nzan ){ fprintf(stderr,"** geomparent and ANALYZE files have different dimensions!\n"); exit(1) ; } if( xorient >= 0 ){ fprintf(stderr,"++ WARNING: geomparent overrides -orient!\n") ; } xorient = gset->daxes->xxorient ; yorient = gset->daxes->yyorient ; zorient = gset->daxes->zzorient ; if( use_zoff ){ fprintf(stderr,"++ WARNING: geomparent overrides -zorigin!\n") ; } use_xoff = use_yoff = use_zoff = 1 ; xoff = gset->daxes->xxorg ; yoff = gset->daxes->yyorg ; zoff = gset->daxes->zzorg ; dxan = gset->daxes->xxdel ; dyan = gset->daxes->yydel ; dzan = gset->daxes->zzdel ; if( gset->taxis != NULL ){ TR = gset->taxis->ttdel ; tunits = gset->taxis->units_type ; } DSET_delete(gset) ; /* delete to save memory */ } else { /* don't have geomparent, so check if other data is OK */ if( xorient < 0 ){ xorient = ORI_R2L_TYPE ; yorient = ORI_A2P_TYPE ; zorient = ORI_I2S_TYPE ; fprintf(stderr,"++ WARNING: orientation defaults to RAI\n") ; } if( dxan <= 0.0 ){ dxan = dyan = dzan = 1.0 ; fprintf(stderr,"++ WARNING: voxel size defaults to 1 mm\n") ; } if( ORIENT_sign[xorient] == '-' ) dxan = -dxan ; if( ORIENT_sign[yorient] == '-' ) dyan = -dyan ; if( ORIENT_sign[zorient] == '-' ) dzan = -dzan ; } /* end of setup for new dataset parameters */ /*-- At last: create empty output dataset --*/ dset = EDIT_empty_copy(NULL) ; nxyz.ijk[0] = nxan ; dxyz.xyz[0] = dxan ; nxyz.ijk[1] = nyan ; dxyz.xyz[1] = dyan ; nxyz.ijk[2] = nzan ; dxyz.xyz[2] = dzan ; orixyz.ijk[0] = xorient ; orixyz.ijk[1] = yorient ; orixyz.ijk[2] = zorient ; orgxyz.xyz[0] = (use_xoff) ? xoff : -0.5*(nxan-1)*dxan ; orgxyz.xyz[1] = (use_yoff) ? yoff : -0.5*(nyan-1)*dyan ; orgxyz.xyz[2] = (use_zoff) ? zoff : -0.5*(nzan-1)*dzan ; EDIT_dset_items( dset , ADN_prefix , prefix , ADN_datum_all , an_datum , ADN_nxyz , nxyz , ADN_xyzdel , dxyz , ADN_xyzorg , orgxyz , ADN_xyzorient , orixyz , ADN_nvals , nvals , ADN_view_type , view_type , ADN_brick_fac , fac , ADN_none ) ; /*-- select dataset type (3D+time or bucket) --*/ if( nvals == 1 && is_3dtime ){ is_3dtime = 0; is_abuc = 1; fprintf(stderr,"++ WARNING: can't make a 3D+time dataset from 1 volume!\n") ; } if( !is_3dtime && !is_abuc && !is_fbuc ){ if( nvals > 1 ) is_3dtime = 1 ; else is_abuc = 1 ; } if( is_3dtime ){ EDIT_dset_items( dset , ADN_ntt , nvals , ADN_ttorg , 0.0 , ADN_ttdel , TR , ADN_ttdur , 0.0 , ADN_tunits , tunits , ADN_type , HEAD_ANAT_TYPE , ADN_func_type, ANAT_EPI_TYPE , ADN_none ) ; } else if( is_abuc ){ EDIT_dset_items( dset , ADN_type , HEAD_ANAT_TYPE , ADN_func_type, ANAT_BUCK_TYPE , ADN_none ) ; } else if( is_fbuc ){ EDIT_dset_items( dset , ADN_type , HEAD_FUNC_TYPE , ADN_func_type, FUNC_BUCK_TYPE , ADN_none ) ; } /*-- make filename array and store it in dataset header --*/ flab = (char **) malloc(sizeof(char *)*nvals) ; kk = 0 ; for( ii=0 ; ii < nvals ; ii++ ){ jj = strlen( argv[iarg+ii] ) ; /* convert .hdr */ flab[ii] = strdup( argv[iarg+ii] ) ; /* filename to */ strcpy( flab[ii]+jj-3 , "img" ) ; /* .img name */ kk += (jj+2) ; THD_store_datablock_label( dset->dblk , ii , flab[ii] ) ; } fatr = malloc(kk) ; fatr[0] = '\0' ; /* all filenames */ for( ii=0 ; ii < nvals ; ii++ ){ /* into one big */ strcat(fatr,flab[ii] ); strcat(fatr," "); /* string */ free(flab[ii]) ; } /*-- setting this attribute marks the dataset as being stored by volumes, rather than all data in one .BRIK file --*/ THD_set_string_atr( dset->dblk , "VOLUME_FILENAMES" , fatr ) ; free(fatr) ; free(flab) ; /*-- set byte ordering flag --*/ jj = mri_short_order() ; /* order of this CPU */ if( an_swapped ) dset->dblk->diskptr->byte_order = REVERSE_ORDER(jj) ; else dset->dblk->diskptr->byte_order = jj ; /*-- set history attribute --*/ tross_Make_History( "3dANALYZEtoAFNI" , argc,argv , dset ) ; /*-- write dataset header --*/ THD_write_3dim_dataset( NULL,NULL , dset , False ) ; fprintf(stderr,"++ Wrote dataset header %s\n",DSET_HEADNAME(dset)) ; exit(0) ; }