int main( int argc , char *argv[] ) { THD_3dim_dataset *dset ; MRI_IMAGE *im ; int iarg=1 ; if( strcmp(argv[1],"-nper") == 0 ){ nper = strtol( argv[2] , NULL , 10 ) ; iarg = 3 ; } for( ; iarg < argc ; iarg++ ){ printf("======= dataset %s nper=%d ========\n",argv[iarg],nper) ; dset = THD_open_dataset(argv[iarg]) ; if( dset == NULL ) continue ; DSET_load(dset) ; im = DSET_BRICK(dset,0) ; im->dx = DSET_DX(dset) ; im->dy = DSET_DY(dset) ; im->dz = DSET_DZ(dset) ; (void) THD_orient_guess( im ) ; printf( "Data Axes Orientation:\n" " first (x) = %s\n" " second (y) = %s\n" " third (z) = %s\n" , ORIENT_typestr[dset->daxes->xxorient] , ORIENT_typestr[dset->daxes->yyorient] , ORIENT_typestr[dset->daxes->zzorient] ) ; DSET_delete(dset) ; } exit(0) ; }
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 *dset=NULL; int iarg , verbose = -1 ; char *outbuf, *stmp=NULL; char *labelName = NULL; char *sbdelim = {"|"}; char *NAflag = {"NA"}; char *atrdelim = {"\t"}, *form=NULL; INFO_FIELDS sing[512]; int iis=0, N_sing = 0, isb=0, withhead = 0, itmp=0; int ip=0, needpair = 0, namelen=0, monog_pairs = 0; THD_3dim_dataset *tttdset=NULL, *dsetp=NULL; char *tempstr = NULL; int extinit = 0; float RL_AP_IS[6]; mainENTRY("3dinfo main") ; machdep() ; if( argc < 2) { Syntax(TXT,1) ; RETURN(0); } iarg = 1 ; while (iarg < argc && argv[iarg][0] == '-') { CHECK_HELP(argv[iarg],Syntax); if( strncmp(argv[iarg],"-verb" ,5) == 0 ){ verbose = 0; iarg++; continue; } else if( strncmp(argv[iarg],"-VERB" ,5) == 0 ){ verbose = 1; iarg++; continue; } else if( strncmp(argv[iarg],"-short",5) == 0 ){ verbose = -1; iarg++; continue; } else if( strcasecmp(argv[iarg],"-header_line") == 0 || strcasecmp(argv[iarg],"-hdr") == 0 ){ withhead = 1; iarg++; continue; } else if( strcasecmp(argv[iarg],"-monog_pairs") == 0 ){ monog_pairs = 1; iarg++; continue; } else if ( strncmp(argv[iarg],"-label2",7) == 0 ) { iarg++; if (iarg >= argc) ERROR_exit( "3dinfo needs an argument after -label2number\n"); labelName = malloc(sizeof(char) * 2048); strcpy(labelName, argv[iarg]); iarg++; continue; } else if( strcasecmp(argv[iarg],"-sb_delim") == 0) { iarg++; if (iarg >= argc) ERROR_exit( "3dinfo needs a string after -sb_delim\n"); sbdelim = argv[iarg]; iarg++; continue; } else if( strcasecmp(argv[iarg],"-NA_flag") == 0) { iarg++; if (iarg >= argc) ERROR_exit( "3dinfo needs a string after -NA_flag\n"); NAflag = argv[iarg]; iarg++; continue; } else if( strcasecmp(argv[iarg],"-atr_delim") == 0) { iarg++; if (iarg >= argc) ERROR_exit( "3dinfo needs a string after -atr_delim\n"); atrdelim = argv[iarg]; iarg++; continue; } else if( strcasecmp(argv[iarg],"-space") == 0) { sing[N_sing++] = DSET_SPACE; iarg++; continue; } else if( strcasecmp(argv[iarg],"-av_space") == 0) { sing[N_sing++] = AV_DSET_SPACE; iarg++; continue; } else if( strcasecmp(argv[iarg],"-gen_space") == 0) { sing[N_sing++] = DSET_GEN_SPACE; iarg++; continue; } else if( strcasecmp(argv[iarg],"-is_nifti") == 0) { sing[N_sing++] = IS_NIFTI; iarg++; continue; } else if( strcasecmp(argv[iarg],"-is_atlas") == 0) { sing[N_sing++] = IS_ATLAS; iarg++; continue; } else if( strcasecmp(argv[iarg],"-exists") == 0) { sing[N_sing++] = DSET_EXISTS; iarg++; continue; } else if( strcasecmp(argv[iarg],"-is_oblique") == 0) { sing[N_sing++] = IS_OBLIQUE; iarg++; continue; } else if( strcasecmp(argv[iarg],"-obliquity") == 0) { sing[N_sing++] = OBLIQUITY; iarg++; continue; } else if( strcasecmp(argv[iarg],"-handedness") == 0) { sing[N_sing++] = HANDEDNESS; iarg++; continue; } else if( strcasecmp(argv[iarg],"-prefix") == 0) { sing[N_sing++] = PREFIX; iarg++; continue; } else if( strcasecmp(argv[iarg],"-prefix_noext") == 0) { sing[N_sing++] = PREFIX_NOEXT; iarg++; continue; } else if( strcasecmp(argv[iarg],"-ni") == 0) { sing[N_sing++] = NI; iarg++; continue; } else if( strcasecmp(argv[iarg],"-nj") == 0) { sing[N_sing++] = NJ; iarg++; continue; } else if( strcasecmp(argv[iarg],"-nk") == 0) { sing[N_sing++] = NK; iarg++; continue; } else if( strcasecmp(argv[iarg],"-n4") == 0) { sing[N_sing++] = NI; sing[N_sing++] = NJ; sing[N_sing++] = NK; sing[N_sing++] = NV; iarg++; continue; } else if( strcasecmp(argv[iarg],"-Rextent") == 0) { sing[N_sing++] = EXTENT_R; iarg++; continue; } else if( strcasecmp(argv[iarg],"-Lextent") == 0) { sing[N_sing++] = EXTENT_L; iarg++; continue; } else if( strcasecmp(argv[iarg],"-Aextent") == 0) { sing[N_sing++] = EXTENT_A; iarg++; continue; } else if( strcasecmp(argv[iarg],"-Pextent") == 0) { sing[N_sing++] = EXTENT_P; iarg++; continue; } else if( strcasecmp(argv[iarg],"-Iextent") == 0) { sing[N_sing++] = EXTENT_I; iarg++; continue; } else if( strcasecmp(argv[iarg],"-Sextent") == 0) { sing[N_sing++] = EXTENT_S; iarg++; continue; } else if( strcasecmp(argv[iarg],"-extent") == 0) { sing[N_sing++] = EXTENT_R; sing[N_sing++] = EXTENT_L; sing[N_sing++] = EXTENT_A; sing[N_sing++] = EXTENT_P; sing[N_sing++] = EXTENT_I; sing[N_sing++] = EXTENT_S; iarg++; continue; } else if( strcasecmp(argv[iarg],"-di") == 0) { sing[N_sing++] = DI; iarg++; continue; } else if( strcasecmp(argv[iarg],"-dj") == 0) { sing[N_sing++] = DJ; iarg++; continue; } else if( strcasecmp(argv[iarg],"-dk") == 0) { sing[N_sing++] = DK; iarg++; continue; } else if( strcasecmp(argv[iarg],"-d3") == 0) { sing[N_sing++] = DI; sing[N_sing++] = DJ; sing[N_sing++] = DK; iarg++; continue; } else if( strcasecmp(argv[iarg],"-adi") == 0) { sing[N_sing++] = ADI; iarg++; continue; } else if( strcasecmp(argv[iarg],"-adj") == 0) { sing[N_sing++] = ADJ; iarg++; continue; } else if( strcasecmp(argv[iarg],"-adk") == 0) { sing[N_sing++] = ADK; iarg++; continue; } else if( strcasecmp(argv[iarg],"-ad3") == 0) { sing[N_sing++] = ADI; sing[N_sing++] = ADJ; sing[N_sing++] = ADK; iarg++; continue; } else if( strcasecmp(argv[iarg],"-voxvol") == 0) { sing[N_sing++] = VOXVOL; iarg++; continue; } else if( strcasecmp(argv[iarg],"-iname") == 0) { sing[N_sing++] = INAME; iarg++; continue; } else if( strcasecmp(argv[iarg],"-oi") == 0) { sing[N_sing++] = OI; iarg++; continue; } else if( strcasecmp(argv[iarg],"-oj") == 0) { sing[N_sing++] = OJ; iarg++; continue; } else if( strcasecmp(argv[iarg],"-ok") == 0) { sing[N_sing++] = OK; iarg++; continue; } else if( strcasecmp(argv[iarg],"-o3") == 0) { sing[N_sing++] = OI; sing[N_sing++] = OJ; sing[N_sing++] = OK; iarg++; continue; }else if( strcasecmp(argv[iarg],"-nt") == 0) { sing[N_sing++] = NT; iarg++; continue; } else if( strcasecmp(argv[iarg],"-nti") == 0) { sing[N_sing++] = NTI; iarg++; continue; } else if( strcasecmp(argv[iarg],"-nv") == 0) { sing[N_sing++] = NV; iarg++; continue; } else if( strcasecmp(argv[iarg],"-nvi") == 0) { sing[N_sing++] = NVI; iarg++; continue; } else if( strcasecmp(argv[iarg],"-ntimes") == 0) { sing[N_sing++] = NTIMES; iarg++; continue; } else if( strcasecmp(argv[iarg],"-max_node") == 0) { sing[N_sing++] = MAX_NODE; iarg++; continue; } else if( strcasecmp(argv[iarg],"-nijk") == 0) { sing[N_sing++] = NIJK; iarg++; continue; } else if( strcasecmp(argv[iarg],"-labeltable") == 0) { sing[N_sing++] = LTABLE; iarg++; continue; } else if( strcasecmp(argv[iarg],"-labeltable_as_atlas_points") == 0) { sing[N_sing++] = LTABLE_AS_ATLAS_POINT_LIST; iarg++; continue; } else if( strcasecmp(argv[iarg],"-atlas_points") == 0) { sing[N_sing++] = ATLAS_POINTS; iarg++; continue; } else if( strcasecmp(argv[iarg],"-fac") == 0) { sing[N_sing++] = FAC; iarg++; continue; } else if( strcasecmp(argv[iarg],"-datum") == 0) { sing[N_sing++] = DATUM; iarg++; continue; } else if( strcasecmp(argv[iarg],"-label") == 0) { sing[N_sing++] = LABEL; iarg++; continue; } else if( strcasecmp(argv[iarg],"-min") == 0) { sing[N_sing++] = MIN; iarg++; continue; } else if( strcasecmp(argv[iarg],"-max") == 0) { sing[N_sing++] = MAX; iarg++; continue; } else if( strcasecmp(argv[iarg],"-minus") == 0) { sing[N_sing++] = MINUS; iarg++; continue; } else if( strcasecmp(argv[iarg],"-maxus") == 0) { sing[N_sing++] = MAXUS; iarg++; continue; } else if( strcasecmp(argv[iarg],"-dmin") == 0) { sing[N_sing++] = DMIN; iarg++; continue; } else if( strcasecmp(argv[iarg],"-dmax") == 0) { sing[N_sing++] = DMAX; iarg++; continue; } else if( strcasecmp(argv[iarg],"-dminus") == 0) { sing[N_sing++] = DMINUS; iarg++; continue; } else if( strcasecmp(argv[iarg],"-dmaxus") == 0) { sing[N_sing++] = DMAXUS; iarg++; continue; } else if( strcasecmp(argv[iarg],"-TR") == 0) { sing[N_sing++] = TR; iarg++; continue; } else if( strcasecmp(argv[iarg],"-header_name") == 0) { sing[N_sing++] = HEADER_NAME; iarg++; continue; } else if( strcasecmp(argv[iarg],"-brick_name") == 0) { sing[N_sing++] = BRICK_NAME; iarg++; continue; } else if( strcasecmp(argv[iarg],"-history") == 0) { sing[N_sing++] = HISTORY; iarg++; continue; } else if( strcasecmp(argv[iarg],"-all_names") == 0) { sing[N_sing++] = ALL_NAMES; iarg++; continue; } else if( strcasecmp(argv[iarg],"-orient") == 0) { sing[N_sing++] = ORIENT; iarg++; continue; } else if( strcasecmp(argv[iarg],"-same_grid") == 0) { sing[N_sing++] = SAME_GRID; needpair = 1; iarg++; continue; } else if( strcasecmp(argv[iarg],"-same_dim") == 0) { sing[N_sing++] = SAME_DIM; needpair = 1; iarg++; continue; } else if( strcasecmp(argv[iarg],"-same_delta") == 0) { sing[N_sing++] = SAME_DELTA; needpair = 1; iarg++; continue; } else if( strcasecmp(argv[iarg],"-same_orient") == 0) { sing[N_sing++] = SAME_ORIENT; needpair = 1; iarg++; continue; } else if( strcasecmp(argv[iarg],"-same_center") == 0) { sing[N_sing++] = SAME_CENTER; needpair = 1; iarg++; continue; } else if( strcasecmp(argv[iarg],"-same_obl") == 0) { sing[N_sing++] = SAME_OBL; needpair = 1; iarg++; continue; } else if( strcasecmp(argv[iarg],"-slice_timing") == 0) { sing[N_sing++] = SLICE_TIMING; iarg++; continue; } else if( strcasecmp(argv[iarg],"-sval_diff") == 0) { sing[N_sing++] = SVAL_DIFF; needpair = 1; iarg++; continue; } else if( strcasecmp(argv[iarg],"-val_diff") == 0) { sing[N_sing++] = VAL_DIFF; needpair = 1; iarg++; continue; } else if( strcasecmp(argv[iarg],"-same_all_grid") == 0) { sing[N_sing++] = SAME_DIM; sing[N_sing++] = SAME_DELTA; sing[N_sing++] = SAME_ORIENT; sing[N_sing++] = SAME_CENTER; sing[N_sing++] = SAME_OBL; needpair = 1; iarg++; continue; } else if( strcasecmp(argv[iarg],"-id") == 0) { sing[N_sing++] = ID; iarg++; continue; } else if( strcasecmp(argv[iarg],"-smode") == 0) { sing[N_sing++] = SMODE; iarg++; continue; } else { ERROR_message("Option %s unknown", argv[iarg]); suggest_best_prog_option(argv[0], argv[iarg]); exit(1); } } if (N_sing == 0) { sing[N_sing++] = CLASSIC; } if (sing[iis] == CLASSIC) PRINT_VERSION("3dinfo") ; THD_allow_empty_dataset(1) ; /* 21 Mar 2007 */ if (iarg == argc) { ERROR_message("No dsets on command line? I have nothing to do.\n"); exit(1); } if (needpair && monog_pairs) needpair = 2; /* pair each couple separately */ if (needpair==2 && (argc-iarg) % 2) { ERROR_message("Using options requiring dset pairs but have odd number\n" "of dsets (%d) on command line.\n", (argc-iarg)); exit (1); } else if (needpair==1 && (argc-iarg) < 2) { ERROR_message("Using options requiring dset pairs but have less than\n" "two dsets (%d) on command line.\n", (argc-iarg)); exit (1); } ip = 0; for( ; iarg < argc ; iarg++ ){ if (ip == 0) { int kkk, nml; char *etr; namelen = 0; for (kkk=iarg; kkk<argc; ++kkk) { if ((etr = THD_trailname(argv[kkk],0))) { nml=strlen(etr); if (nml < 48 && nml > namelen) namelen = nml; } } if (namelen < 6) namelen = 6; if (withhead) { int havenew=0; for (iis = 0; iis < N_sing; ++iis) { if (sing[iis] != CLASSIC) { ++havenew; form = PrintForm(sing[iis], namelen, 1); /*fprintf(stderr,"ZSS: %d %s >%s<\n", sing[iis], Field_Names[sing[iis]], form);*/ fprintf(stdout, form, Field_Names[sing[iis]]); } if (havenew) { if (N_sing > 1 && iis < N_sing-1) fprintf(stdout,"%s",atrdelim); else fprintf(stdout,"\n"); } } } } if( argv[iarg][0] == '\0' ) continue ; /* bad filename */ set_obliquity_report(0); /* silence obliquity */ if (!needpair) { if (!(dset = load_3dinfo_dataset(argv[iarg]))) { /* exit(1); */ } } else { if (needpair == 2) { /* Crazy idea of comparing each pair separately */ if (ip % 2 == 0) { if (!(dset = load_3dinfo_dataset(argv[iarg] ))) { /* exit(1); */ } if (iarg+1==argc || argv[iarg+1][0] == '\0') { ERROR_message("Bad dset pair for %s\n", argv[iarg]); exit(1); } if (!(dsetp = load_3dinfo_dataset(argv[iarg+1] ))) { /* exit(1); */ } } else { /* swap the pair - this allows non pair requiring functions to work as before.*/ tttdset = dsetp; dsetp = dset; dset = tttdset; tttdset=NULL; } } else { /* always compare to very first dset */ if (ip==0) { if (!(dset = load_3dinfo_dataset(argv[iarg] ))) { /*exit(1);*/ } if (!(dsetp = load_3dinfo_dataset(argv[iarg+1] ))) { /*exit(1);*/ } } else if (ip==1) { /* switch order of first two */ tttdset = dsetp; dsetp = dset; /* now dsetp is the very first dset */ dset = tttdset; tttdset=NULL; } else { /* pair with very first, which is dsetp */ if (!(dset = load_3dinfo_dataset(argv[iarg] ))) { /*exit(1);*/ } } } } ++ip; if (0 && !dset) { /* allow for DSET_EXISTS option */ ERROR_exit("Should not get here"); } /* we should re-capture this per dataset 5 Feb 2019 [rickr] */ extinit = 0; for (iis = 0; iis < N_sing; ++iis) { if (!dset) { if (sing[iis] == CLASSIC) { if( dset == NULL ){ /* still not open? */ ERROR_exit("Can't open dataset %s\n", argv[iarg]) ; } } else if (sing[iis] != DSET_EXISTS && sing[iis] != INAME) { fprintf(stdout, "NO-DSET"); SPIT_DELIM(iis, N_sing, atrdelim); continue; } } switch (sing[iis]) { case CLASSIC: if (labelName == NULL ) /*** get and output info ***/ { outbuf = THD_dataset_info( dset , verbose ) ; if( outbuf != NULL ){ printf("\n") ; puts(outbuf) ; free(outbuf) ; outbuf = NULL ; } else { ERROR_exit("Can't get info for dataset %s",argv[iarg]) ; } } else /*** get and output label ***/ { int nval_per = dset->dblk->nvals; int foundLabel = 0; int ival=0; for (ival=0 ; ival < nval_per && !foundLabel; ival++ ) { if (strcmp(DSET_BRICK_LAB(dset,ival), labelName) == 0) { printf("%d\n", ival); foundLabel = 1; } } /* end of for (ival=0 ; ival < nval_per ; ival++ ) */ if (!foundLabel) printf("\n"); } THD_delete_3dim_dataset( dset , False ) ; free(labelName); break; case DSET_EXISTS: fprintf(stdout, "%d", dset ? 1:0); break; case DSET_SPACE: tempstr = THD_get_space(dset); if(tempstr==NULL) fprintf(stdout, "-----"); else fprintf(stdout, "%s", tempstr); break; case DSET_GEN_SPACE: tempstr = THD_get_generic_space(dset); if(tempstr==NULL) fprintf(stdout, "-----"); else fprintf(stdout, "%s", tempstr); break; case AV_DSET_SPACE: /* don't allow anything but the three AFNI views */ tempstr = THD_get_view_space(dset); if(tempstr==NULL) fprintf(stdout, "+orig"); else if (!strncasecmp(tempstr,"ORIG",4)) fprintf(stdout, "+orig"); else if (!strncasecmp(tempstr,"ACPC",4)) fprintf(stdout, "+acpc"); else if (!strncasecmp(tempstr,"TLRC",4)) fprintf(stdout, "+tlrc"); else /* shouldn't get here */ fprintf(stdout, "+orig"); break; case IS_NIFTI: if ( dset->dblk->diskptr && dset->dblk->diskptr->storage_mode == STORAGE_BY_NIFTI ) { fprintf(stdout,"1"); } else { fprintf(stdout,"0"); } break; case IS_ATLAS: if ( is_Dset_Atlasy(dset, NULL) ) { fprintf(stdout,"1"); } else { fprintf(stdout,"0"); } break; case IS_OBLIQUE: if (dset_obliquity(dset,NULL) > 0) { fprintf(stdout,"1"); } else { fprintf(stdout,"0"); } break; case HANDEDNESS: if (THD_handedness(dset) > 0) { fprintf(stdout,"R"); } else { fprintf(stdout,"L"); } break; case OBLIQUITY: fprintf(stdout,"%.3f", THD_compute_oblique_angle(dset->daxes->ijk_to_dicom_real, 0)); break; case PREFIX: form = PrintForm(sing[iis], namelen, 1); fprintf(stdout,form, DSET_PREFIX(dset)); break; case PREFIX_NOEXT: { form = PrintForm(sing[iis], namelen, 1); stmp=DSET_prefix_noext(dset); fprintf(stdout,form, stmp); free(stmp); stmp=NULL; } break; case HEADER_NAME: fprintf(stdout,"%s", dset->dblk->diskptr->header_name); break; case BRICK_NAME: fprintf(stdout,"%s", dset->dblk->diskptr->brick_name); break; case ALL_NAMES: THD_show_dataset_names(dset, "FOR_3DINFO", stdout); break; case HISTORY: stmp = tross_Get_History(dset); fprintf(stdout,"%s", stmp ? stmp:NAflag); if (stmp) free(stmp); stmp=NULL; break; case NI: fprintf(stdout,"%d", DSET_NX(dset)); break; case NJ: fprintf(stdout,"%d", DSET_NY(dset)); break; case NK: fprintf(stdout,"%d", DSET_NZ(dset)); break; case NIJK: fprintf(stdout,"%d", DSET_NVOX(dset)); break; case NTIMES: fprintf(stdout,"%d", DSET_NUM_TIMES(dset)); break; case MAX_NODE: DSET_MAX_NODE(dset,itmp); fprintf(stdout,"%d", itmp); break; case NT: case NV: fprintf(stdout,"%d", DSET_NVALS(dset)); break; case NTI: case NVI: fprintf(stdout,"%d", DSET_NVALS(dset)-1); break; case DI: fprintf(stdout,"%f", DSET_DX(dset)); break; case DJ: fprintf(stdout,"%f", DSET_DY(dset)); break; case DK: fprintf(stdout,"%f", DSET_DZ(dset)); break; case OI: fprintf(stdout,"%f", DSET_XORG(dset)); break; case OJ: fprintf(stdout,"%f", DSET_YORG(dset)); break; case OK: fprintf(stdout,"%f", DSET_ZORG(dset)); break; case ADI: fprintf(stdout,"%f", fabs(DSET_DX(dset))); break; case EXTENT_R: case EXTENT_L: case EXTENT_A: case EXTENT_P: case EXTENT_I: case EXTENT_S: { if (!extinit) { THD_dset_extent(dset, '-', RL_AP_IS); extinit = 1; } fprintf(stdout,"%f", RL_AP_IS[sing[iis]-EXTENT_R]); } break; case ADJ: fprintf(stdout,"%f", fabs(DSET_DY(dset))); break; case ADK: fprintf(stdout,"%f", fabs(DSET_DZ(dset))); break; case VOXVOL: fprintf(stdout,"%f", fabs(DSET_DX(dset))* fabs(DSET_DY(dset))*fabs(DSET_DZ(dset))); break; case INAME: fprintf(stdout,"%s", argv[iarg]); break; case LTABLE: { char *str; if ((str = Dtable_to_nimlstring(DSET_Label_Dtable(dset), "VALUE_LABEL_DTABLE"))) { fprintf(stdout,"%s", str); free(str); } else { fprintf(stdout,"NO_LABEL_TABLE"); } } break; case LTABLE_AS_ATLAS_POINT_LIST: { ATLAS_POINT_LIST *apl=NULL; if ((apl = label_table_to_atlas_point_list(DSET_Label_Dtable(dset)))) { atlas_list_to_niml(apl,NULL); free_atlas_point_list(apl); } else { fprintf(stdout,"NO_LABEL_TABLE"); } } break; case ATLAS_POINTS: { ATR_string *atr = THD_find_string_atr( dset->dblk, "ATLAS_LABEL_TABLE"); if (atr) { fprintf(stdout,"%s", atr->ch); } else { fprintf(stdout,"NO_APL"); } } break; case FAC: { for (isb=0; isb<DSET_NVALS(dset); ++isb) { fprintf(stdout,"%f%s", DSET_BRICK_FACTOR(dset,isb), (isb == (DSET_NVALS(dset)-1)) ? "" : sbdelim); } break; } case DATUM: { for (isb=0; isb<DSET_NVALS(dset); ++isb) { fprintf(stdout,"%s%s", MRI_TYPE_name[DSET_BRICK_TYPE(dset,isb)], (isb == (DSET_NVALS(dset)-1)) ? "" : sbdelim); } break; } case LABEL: { for (isb=0; isb<DSET_NVALS(dset); ++isb) { fprintf(stdout,"%s%s", DSET_BRICK_LABEL(dset,isb) ? DSET_BRICK_LABEL(dset,isb):NAflag, (isb == (DSET_NVALS(dset)-1)) ? "" : sbdelim); } break; } case MIN: case MINUS: case MAX: case MAXUS: { float vv=0.0, min, max; for (isb=0; isb<DSET_NVALS(dset); ++isb) { if (!THD_subbrick_minmax(dset, isb, (sing[iis] == MINUS || sing[iis] == MAXUS) ? 0:1, &min, &max)) { fprintf(stdout,"%s%s", NAflag, (isb == (DSET_NVALS(dset)-1)) ? "" : sbdelim); } else { if (sing[iis] == MINUS) vv = min; else if (sing[iis] == MAXUS) vv = max; else if (sing[iis] == MIN) vv = min; else if (sing[iis] == MAX) vv = max; fprintf(stdout,"%g%s", vv, (isb == (DSET_NVALS(dset)-1)) ? "" : sbdelim); } } break; } case DMIN: case DMINUS: case DMAX: case DMAXUS: { float vv=0.0, min, max; if (!THD_dset_minmax(dset, (sing[iis] == DMINUS || sing[iis] == DMAXUS) ? 0:1, &min, &max)) { fprintf(stdout,"%s%s", NAflag, (isb == (DSET_NVALS(dset)-1)) ? "" : sbdelim); } else { if (sing[iis] == DMINUS) vv = min; else if (sing[iis] == DMAXUS) vv = max; else if (sing[iis] == DMIN) vv = min; else if (sing[iis] == DMAX) vv = max; fprintf(stdout,"%g%s", vv, (isb == (DSET_NVALS(dset)-1)) ? "" : sbdelim); } break; } case TR: #if 0 fprintf(stdout,"%f", DSET_TR_SEC(dset)); #else fprintf(stdout,"%f", DSET_TR(dset)); #endif break; case ORIENT: { /* fprintf(stdout,"%c%c%c", * ORIENT_typestr[dset->daxes->xxorient][0], ... ); */ char ostr[4]; /* just to show 23 Jan 2013 [rickr] */ THD_fill_orient_str_3(dset->daxes, ostr); fprintf(stdout,"%3s", ostr); } break; case SAME_GRID: fprintf(stdout,"%d", !THD_dataset_mismatch( dset , dsetp )); break; case SAME_DIM: fprintf(stdout,"%d", !(THD_dataset_mismatch( dset , dsetp ) & MISMATCH_DIMEN)); break; case SAME_DELTA: fprintf(stdout,"%d", !(THD_dataset_mismatch( dset , dsetp ) & MISMATCH_DELTA)); break; case SAME_ORIENT: fprintf(stdout,"%d", !(THD_dataset_mismatch( dset , dsetp ) & MISMATCH_ORIENT)); break; case SAME_CENTER: fprintf(stdout,"%d", !(THD_dataset_mismatch( dset , dsetp ) & MISMATCH_CENTER)); break; case SAME_OBL: fprintf(stdout,"%d", !(THD_dataset_mismatch( dset , dsetp ) & MISMATCH_OBLIQ)); break; case SLICE_TIMING: /* 6 May 2013 [rickr] */ { if( DSET_HAS_SLICE_TIMING(dset) ) { DSET_UNMSEC(dset); /* make sure times are in seconds */ for (isb=0; isb<dset->taxis->nsl; ++isb) { fprintf(stdout,"%s%f", (isb > 0) ? sbdelim : "", dset->taxis->toff_sl[isb]); } } else { /* all slices times are at t=0.0 */ for (isb=0; isb<DSET_NZ(dset); ++isb) { fprintf(stdout,"%s%f", (isb > 0) ? sbdelim : "", 0.0); } } } break; case SVAL_DIFF: fprintf(stdout,"%f",THD_diff_vol_vals(dset, dsetp, 1)); break; case VAL_DIFF: fprintf(stdout,"%f",THD_diff_vol_vals(dset, dsetp, 0)); break; case ID: fprintf(stdout,"%s", DSET_IDCODE_STR(dset)); break; case SMODE: fprintf(stdout,"%s", DSET_STORAGE_MODE_STR(dset)); break; default: ERROR_message("Info field not set properly (%d)\n", sing[iis]); exit(1); } if (sing[iis] != CLASSIC) { SPIT_DELIM(iis, N_sing, atrdelim); } } } exit(0) ; }
/*! A function version of the program mc by Thomas Lewiner see main.c in ./MarchingCubes */ SUMA_SurfaceObject *SUMA_MarchingCubesSurface( SUMA_GENERIC_PROG_OPTIONS_STRUCT * Opt) { static char FuncName[]={"SUMA_MarchingCubesSurface"}; SUMA_SurfaceObject *SO=NULL; int nxx, nyy, nzz, cnt, i, j, k, *FaceSetList=NULL; float *NodeList=NULL; SUMA_NEW_SO_OPT *nsoopt = NULL; THD_fvec3 fv, iv; MCB *mcp ; SUMA_ENTRY; if (Opt->obj_type < 0) { nxx = DSET_NX(Opt->in_vol); nyy = DSET_NY(Opt->in_vol); nzz = DSET_NZ(Opt->in_vol); if (Opt->debug) { fprintf(SUMA_STDERR, "%s:\nNxx=%d\tNyy=%d\tNzz=%d\n", FuncName, nxx, nyy, nzz); } mcp = MarchingCubes(-1, -1, -1); set_resolution( mcp, nxx, nyy, nzz ) ; init_all(mcp) ; if (Opt->debug) fprintf(SUMA_STDERR,"%s:\nSetting data...\n", FuncName); cnt = 0; for( k = 0 ; k < mcp->size_z ; k++ ) { for( j = 0 ; j < mcp->size_y ; j++ ) { for( i = 0 ; i < mcp->size_x ; i++ ) { SUMA_SET_MC_DATA ( mcp, Opt->mcdatav[cnt], i, j, k); ++cnt; } } } } else { /* built in */ nxx = nyy = nzz = Opt->obj_type_res; mcp = MarchingCubes(-1, -1, -1); set_resolution( mcp, nxx, nyy, nzz) ; init_all(mcp) ; compute_data( *mcp , Opt->obj_type) ; } if (Opt->debug) fprintf(SUMA_STDERR,"%s:\nrunning MarchingCubes...\n", FuncName); run(mcp) ; clean_temps(mcp) ; if (Opt->debug > 1) { fprintf(SUMA_STDERR,"%s:\nwriting out NodeList and FaceSetList...\n", FuncName); write1Dmcb(mcp); } if (Opt->debug) { fprintf(SUMA_STDERR,"%s:\nNow creating SO...\n", FuncName); } NodeList = (float *)SUMA_malloc(sizeof(float)*3*mcp->nverts); FaceSetList = (int *)SUMA_malloc(sizeof(int)*3*mcp->ntrigs); if (!NodeList || !FaceSetList) { SUMA_SL_Crit("Failed to allocate!"); SUMA_RETURN(SO); } nsoopt = SUMA_NewNewSOOpt(); if (Opt->obj_type < 0) { nsoopt->LargestBoxSize = -1; if (Opt->debug) { fprintf(SUMA_STDERR, "%s:\nCopying vertices, changing to DICOM \n" "Orig:(%f %f %f) \nD:(%f %f %f)...\n", FuncName, DSET_XORG(Opt->in_vol), DSET_YORG(Opt->in_vol), DSET_ZORG(Opt->in_vol), DSET_DX(Opt->in_vol), DSET_DY(Opt->in_vol), DSET_DZ(Opt->in_vol)); } for ( i = 0; i < mcp->nverts; i++ ) { j = 3*i; /* change from index coordinates to mm DICOM, next three lines are equivalent of SUMA_THD_3dfind_to_3dmm*/ fv.xyz[0] = DSET_XORG(Opt->in_vol) + mcp->vertices[i].x * DSET_DX(Opt->in_vol); fv.xyz[1] = DSET_YORG(Opt->in_vol) + mcp->vertices[i].y * DSET_DY(Opt->in_vol); fv.xyz[2] = DSET_ZORG(Opt->in_vol) + mcp->vertices[i].z * DSET_DZ(Opt->in_vol); /* change mm to RAI coords */ iv = SUMA_THD_3dmm_to_dicomm( Opt->in_vol->daxes->xxorient, Opt->in_vol->daxes->yyorient, Opt->in_vol->daxes->zzorient, fv ); NodeList[j ] = iv.xyz[0]; NodeList[j+1] = iv.xyz[1]; NodeList[j+2] = iv.xyz[2]; } for ( i = 0; i < mcp->ntrigs; i++ ) { j = 3*i; FaceSetList[j ] = mcp->triangles[i].v3; FaceSetList[j+1] = mcp->triangles[i].v2; FaceSetList[j+2] = mcp->triangles[i].v1; } } else { nsoopt->LargestBoxSize = 100; /* built in */ for ( i = 0; i < mcp->nverts; i++ ) { j = 3*i; NodeList[j ] = mcp->vertices[i].x; NodeList[j+1] = mcp->vertices[i].y; NodeList[j+2] = mcp->vertices[i].z; } for ( i = 0; i < mcp->ntrigs; i++ ) { j = 3*i; FaceSetList[j ] = mcp->triangles[i].v3; FaceSetList[j+1] = mcp->triangles[i].v2; FaceSetList[j+2] = mcp->triangles[i].v1; } } SO = SUMA_NewSO(&NodeList, mcp->nverts, &FaceSetList, mcp->ntrigs, nsoopt); if (Opt->obj_type < 0) { /* not sure if anything needs to be done here ...*/ } else { if (Opt->obj_type == 0) SO->normdir = 1; else SO->normdir = -1; } if (Opt->debug) { fprintf(SUMA_STDERR,"%s:\nCleaning mcp...\n", FuncName); } clean_all(mcp) ; free(mcp); nsoopt=SUMA_FreeNewSOOpt(nsoopt); SUMA_RETURN(SO); }
int AFNI_vedit( THD_3dim_dataset *dset , VEDIT_settings vednew , byte *mask ) { THD_datablock *dblk ; int ival ; MRI_IMAGE *dim ; ENTRY("AFNI_vedit") ; if( !ISVALID_DSET(dset) ) RETURN(0) ; dblk = dset->dblk ; /*--- check if we are to clear any existing edits, and also set future editing status to 'do nothing' ---*/ if( vednew.code <= 0 || vednew.code > VEDIT_LASTCODE ){ if( dblk->vedim != NULL ){ mri_free(dblk->vedim); dblk->vedim=NULL; } dblk->vedset.code = 0; dblk->vedset.ival = -1; dblk->vedset.exinfo = NULL; RETURN(0) ; } /* if we have existing editing results, and they correspond to the same parameters as before, then are done. otherwise, we clear out the existing results so they can be replaced. */ if( dblk->vedim != NULL && (vednew.flags&1) == 0 ){ if( memcmp(&(dblk->vedset),&vednew,sizeof(VEDIT_settings)) == 0 ) RETURN(0) ; /* exactly the same as before */ mri_free(dblk->vedim); dblk->vedim=NULL; /* clear old results */ } /*--- at this point, must edit dataset brick ---*/ dblk->vedset = vednew ; /* save settings for next time in */ dblk->vedset.flags = 0 ; /*--- create edited volume ---*/ if( vednew.code == VEDIT_CLUST ){ /*----- Clusterize -----*/ MRI_IMAGE *tim=NULL ; float thr,rmm,vmul,thb,tht ; int thrsign,posfunc,ithr ; ival = vednew.ival ; if( ival < 0 || ival > DSET_NVALS(dset) ) RETURN(0) ; dim = DBLK_BRICK(dblk,ival) ; if( dim == NULL || mri_data_pointer(dim) == NULL ){ DSET_load(dset) ; dim = DBLK_BRICK(dblk,ival) ; if( dim == NULL || mri_data_pointer(dim) == NULL ) RETURN(0) ; } dim->dx = fabs(DSET_DX(dset)); dim->dy = fabs(DSET_DY(dset)); dim->dz = fabs(DSET_DZ(dset)); ithr = (int)vednew.param[0] ; thrsign = (int)vednew.param[4] ; posfunc = (int)vednew.param[5] ; if( ithr >= 0 && ithr < DSET_NVALS(dset) ) tim = DBLK_BRICK(dblk,ithr) ; thr = vednew.param[1] ; if( DSET_BRICK_FACTOR(dset,ithr) > 0.0f ) thr /= DSET_BRICK_FACTOR(dset,ithr) ; thb = THBOT(thr) ; tht = THTOP(thr) ; rmm = vednew.param[2] ; vmul = vednew.param[3] ; dblk->vedim = mri_clusterize( rmm,vmul,dim,thb,tht,tim,posfunc , mask ); } /*--- done ---*/ RETURN(1) ; }
int main( int argc , char * argv[] ) { float mrad=0.0f , fwhm=0.0f ; int nrep=1 ; char *prefix = "Polyfit" ; char *resid = NULL ; char *cfnam = NULL ; int iarg , verb=0 , do_automask=0 , nord=3 , meth=2 , do_mclip=0 ; THD_3dim_dataset *inset ; MRI_IMAGE *imout , *imin ; byte *mask=NULL ; int nvmask=0 , nmask=0 , do_mone=0 , do_byslice=0 ; MRI_IMARR *exar=NULL ; floatvec *fvit=NULL ; /* 26 Feb 2019 */ if( argc < 2 || strcasecmp(argv[1],"-help") == 0 ){ printf("\n" "Usage: 3dPolyfit [options] dataset ~1~\n" "\n" "* Fits a polynomial in space to the input dataset and outputs that fitted dataset.\n" "\n" "* You can also add your own basis datasets to the fitting mix, using the\n" " '-base' option.\n" "\n" "* You can get the fit coefficients using the '-1Dcoef' option.\n" "\n" "--------\n" "Options: ~1~\n" "--------\n" "\n" " -nord n = Maximum polynomial order (0..9) [default order=3]\n" " [n=0 is the constant 1]\n" " [n=-1 means only use volumes from '-base']\n" "\n" " -blur f = Gaussian blur input dataset (inside mask) with FWHM='f' (mm)\n" "\n" " -mrad r = Radius (voxels) of preliminary median filter of input\n" " [default is no blurring of either type; you can]\n" " [do both types (Gaussian and median), but why??]\n" " [N.B.: median blur is slower than Gaussian]\n" "\n" " -prefix pp = Use 'pp' for prefix of output dataset (the fit).\n" " [default prefix is 'Polyfit'; use NULL to skip this output]\n" "\n" " -resid rr = Use 'rr' for the prefix of the residual dataset.\n" " [default is not to output residuals]\n" "\n" " -1Dcoef cc = Save coefficients of fit into text file cc.1D.\n" " [default is not to save these coefficients]\n" "\n" " -automask = Create a mask (a la 3dAutomask)\n" " -mask mset = Create a mask from nonzero voxels in 'mset'.\n" " [default is not to use a mask, which is probably a bad idea]\n" "\n" " -mone = Scale the mean value of the fit (inside the mask) to 1.\n" " [probably this option is not useful for anything]\n" "\n" " -mclip = Clip fit values outside the rectilinear box containing the\n" " mask to the edge of that box, to avoid weird artifacts.\n" "\n" " -meth mm = Set 'mm' to 2 for least squares fit;\n" " set it to 1 for L1 fit [default method=2]\n" " [Note that L1 fitting is slower than L2 fitting!]\n" "\n" " -base bb = In addition to the polynomial fit, also use\n" " the volumes in dataset 'bb' as extra basis functions.\n" " [If you use a base dataset, then you can set nord]\n" " [to -1, to skip using any spatial polynomial fit.]\n" "\n" " -verb = Print fun and useful progress reports :-)\n" "\n" "------\n" "Notes: ~1~\n" "------\n" "* Output dataset is always stored in float format.\n" "\n" "* If the input dataset has more than 1 sub-brick, only sub-brick #0\n" " is processed. To fit more than one volume, you'll have to use a script\n" " to loop over the input sub-bricks, and then glue (3dTcat) the results\n" " together to get a final result. A simple example:\n" " #!/bin/tcsh\n" " set base = model.nii\n" " set dset = errts.nii\n" " set nval = `3dnvals $dset`\n" " @ vtop = $nval - 1\n" " foreach vv ( `count 0 $vtop` )\n" " 3dPolyfit -base \"$base\" -nord 0 -mask \"$base\" -1Dcoef QQ.$vv -prefix QQ.$vv.nii $dset\"[$vv]\"\n" " end\n" " 3dTcat -prefix QQall.nii QQ.0*.nii\n" " 1dcat QQ.0*.1D > QQall.1D\n" " \rm QQ.0*\n" " exit 0\n" "\n" "* If the '-base' dataset has multiple sub-bricks, all of them are used.\n" "\n" "* You can use the '-base' option more than once, if desired or needed.\n" "\n" "* The original motivation for this program was to fit a spatial model\n" " to a field map MRI, but that didn't turn out to be useful. Nevertheless,\n" " I make this program available to someone who might find it beguiling.\n" "\n" "* If you really want, I could allow you to put sign constraints on the\n" " fit coefficients (e.g., say that the coefficient for a given base volume\n" " should be non-negative). But you'll have to beg for this.\n" "\n" "-- Emitted by RWCox\n" ) ; PRINT_COMPILE_DATE ; exit(0) ; } /*-- startup paperwork --*/ mainENTRY("3dPolyfit main"); machdep(); AFNI_logger("3dPolyfit",argc,argv); PRINT_VERSION("3dPolyfit") ; /*-- scan command line --*/ iarg = 1 ; while( iarg < argc && argv[iarg][0] == '-' ){ if( strcasecmp(argv[iarg],"-base") == 0 ){ THD_3dim_dataset *bset ; int kk ; MRI_IMAGE *bim ; if( ++iarg >= argc ) ERROR_exit("Need argument after '-base'") ; bset = THD_open_dataset(argv[iarg]) ; CHECK_OPEN_ERROR(bset,argv[iarg]) ; DSET_load(bset) ; CHECK_LOAD_ERROR(bset) ; if( exar == NULL ) INIT_IMARR(exar) ; for( kk=0 ; kk < DSET_NVALS(bset) ; kk++ ){ bim = THD_extract_float_brick(kk,bset) ; if( bim != NULL ) ADDTO_IMARR(exar,bim) ; DSET_unload_one(bset,kk) ; } DSET_delete(bset) ; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-verb") == 0 ){ verb++ ; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-hermite") == 0 ){ /* 25 Mar 2013 [New Year's Day] */ mri_polyfit_set_basis("hermite") ; /* HIDDEN */ iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-byslice") == 0 ){ /* 25 Mar 2013 [New Year's Day] */ do_byslice++ ; iarg++ ; continue ; /* HIDDEN */ } if( strcasecmp(argv[iarg],"-mask") == 0 ){ THD_3dim_dataset *mset ; if( ++iarg >= argc ) ERROR_exit("Need argument after '-mask'") ; if( mask != NULL || do_automask ) ERROR_exit("Can't have two mask inputs") ; mset = THD_open_dataset(argv[iarg]) ; CHECK_OPEN_ERROR(mset,argv[iarg]) ; DSET_load(mset) ; CHECK_LOAD_ERROR(mset) ; nvmask = DSET_NVOX(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]) ; nmask = THD_countmask( nvmask , mask ) ; if( nmask < 99 ) ERROR_exit("Too few voxels in mask (%d)",nmask) ; if( verb ) INFO_message("Number of voxels in mask = %d",nmask) ; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-nord") == 0 ){ nord = (int)strtol( argv[++iarg], NULL , 10 ) ; if( nord < -1 || nord > 9 ) ERROR_exit("Illegal value after -nord :(") ; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-meth") == 0 ){ meth = (int)strtol( argv[++iarg], NULL , 10 ) ; if( meth < 1 || meth > 2 ) ERROR_exit("Illegal value after -meth :(") ; iarg++ ; continue ; } if( strncmp(argv[iarg],"-automask",5) == 0 ){ if( mask != NULL ) ERROR_exit("Can't use -mask and -automask together!") ; do_automask++ ; iarg++ ; continue ; } if( strncmp(argv[iarg],"-mclip",5) == 0 ){ do_mclip++ ; iarg++ ; continue ; } if( strncmp(argv[iarg],"-mone",5) == 0 ){ do_mone++ ; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-mrad") == 0 ){ mrad = strtod( argv[++iarg] , NULL ) ; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-blur") == 0 ){ fwhm = strtod( argv[++iarg] , NULL ) ; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-prefix") == 0 ){ prefix = argv[++iarg] ; if( !THD_filename_ok(prefix) ) ERROR_exit("Illegal value after -prefix :("); if( strcasecmp(prefix,"NULL") == 0 ) prefix = NULL ; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-resid") == 0 ){ resid = argv[++iarg] ; if( !THD_filename_ok(resid) ) ERROR_exit("Illegal value after -resid :("); if( strcasecmp(resid,"NULL") == 0 ) resid = NULL ; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-1Dcoef") == 0 ){ /* 26 Feb 2019 */ cfnam = argv[++iarg] ; if( !THD_filename_ok(cfnam) ) ERROR_exit("Illegal value after -1Dcoef :("); if( strcasecmp(cfnam,"NULL") == 0 ) cfnam = NULL ; iarg++ ; continue ; } ERROR_exit("Unknown option: %s\n",argv[iarg]); } /*--- check for blatant errors ---*/ if( iarg >= argc ) ERROR_exit("No input dataset name on command line?"); if( prefix == NULL && resid == NULL && cfnam == NULL ) ERROR_exit("-prefix and -resid and -1Dcoef are all NULL?!") ; if( do_byslice && cfnam != NULL ){ WARNING_message("-byslice does not work with -1Dcoef option :(") ; cfnam = NULL ; } if( nord < 0 && exar == NULL ) ERROR_exit("no polynomial fit AND no -base option ==> nothing to compute :(") ; /*-- read input --*/ if( verb ) INFO_message("Load input dataset") ; inset = THD_open_dataset( argv[iarg] ) ; CHECK_OPEN_ERROR(inset,argv[iarg]) ; DSET_load(inset) ; CHECK_LOAD_ERROR(inset) ; if( DSET_NVALS(inset) > 1 ) WARNING_message( "Only processing sub-brick #0 (out of %d)" , DSET_NVALS(inset) ); /* check input mask or create automask */ if( mask != NULL ){ if( nvmask != DSET_NVOX(inset) ) ERROR_exit("-mask and input datasets don't match in voxel counts :-(") ; } else if( do_automask ){ THD_automask_verbose( (verb > 1) ) ; THD_automask_extclip( 1 ) ; mask = THD_automask( inset ) ; nvmask = DSET_NVOX(inset) ; nmask = THD_countmask( nvmask , mask ) ; if( nmask < 99 ) ERROR_exit("Too few voxels in automask (%d)",nmask) ; if( verb ) ININFO_message("Number of voxels in automask = %d",nmask) ; } else { WARNING_message("3dPolyfit is running without a mask") ; } #undef GOOD #define GOOD(i) (mask == NULL || mask[i]) /* check -base input datasets */ if( exar != NULL ){ int ii,kk , nvbad=0 , nvox=DSET_NVOX(inset),nm ; float *ex , exb ; for( kk=0 ; kk < IMARR_COUNT(exar) ; kk++ ){ if( nvox != IMARR_SUBIM(exar,kk)->nvox ){ if( IMARR_SUBIM(exar,kk)->nvox != nvbad ){ ERROR_message("-base volume (%d voxels) doesn't match input dataset grid size (%d voxels)", IMARR_SUBIM(exar,kk)->nvox , nvox ) ; nvbad = IMARR_SUBIM(exar,kk)->nvox ; } } } if( nvbad != 0 ) ERROR_exit("Cannot continue :-(") ; /* subtract mean from each base input, if is a constant polynomial in the fit */ if( nord >= 0 ){ if( verb ) INFO_message("subtracting spatial mean from '-base'") ; for( kk=0 ; kk < IMARR_COUNT(exar) ; kk++ ){ exb = 0.0f ; ex = MRI_FLOAT_PTR(IMARR_SUBIM(exar,kk)) ; for( nm=ii=0 ; ii < nvox ; ii++ ){ if( GOOD(ii) ){ exb += ex[ii]; nm++; } } exb /= nm ; for( ii=0 ; ii < nvox ; ii++ ) ex[ii] -= exb ; } } } /* if blurring, edit mask a little */ if( mask != NULL && (fwhm > 0.0f || mrad > 0.0f) ){ int ii ; ii = THD_mask_remove_isolas( DSET_NX(inset),DSET_NY(inset),DSET_NZ(inset),mask ) ; if( ii > 0 ){ nmask = THD_countmask( nvmask , mask ) ; if( verb ) ININFO_message("Removed %d isola%s from mask, leaving %d voxels" , ii,(ii==1)?"\0":"s" , nmask ) ; if( nmask < 99 ) ERROR_exit("Too few voxels left in mask after isola removal :-(") ; } } /* convert input to float, which is simpler to deal with */ imin = THD_extract_float_brick(0,inset) ; if( imin == NULL ) ERROR_exit("Can't extract input dataset brick?! :-(") ; DSET_unload(inset) ; if( verb ) INFO_message("Start fitting process") ; /* do the Gaussian blurring */ if( fwhm > 0.0f ){ if( verb ) ININFO_message("Gaussian blur: FWHM=%g mm",fwhm) ; imin->dx = fabsf(DSET_DX(inset)) ; imin->dy = fabsf(DSET_DY(inset)) ; imin->dz = fabsf(DSET_DZ(inset)) ; mri_blur3D_addfwhm( imin , mask , fwhm ) ; } /* do the fitting */ mri_polyfit_verb(verb) ; if( do_byslice ) imout = mri_polyfit_byslice( imin , nord , exar , mask , mrad , meth ) ; else imout = mri_polyfit ( imin , nord , exar , mask , mrad , meth ) ; /* WTF? */ if( imout == NULL ) ERROR_exit("Can't compute polynomial fit :-( !?") ; if( resid == NULL ) mri_free(imin) ; if( ! do_byslice ) fvit = mri_polyfit_get_fitvec() ; /* get coefficients of fit [26 Feb 2019] */ /* scale the fit dataset? */ if( do_mone ){ float sum=0.0f ; int nsum=0 , ii,nvox ; float *par=MRI_FLOAT_PTR(imout) ; nvox = imout->nvox ; for( ii=0 ; ii < nvox ; ii++ ){ if( mask != NULL && mask[ii] == 0 ) continue ; sum += par[ii] ; nsum++ ; } if( nsum > 0 && sum != 0.0f ){ sum = nsum / sum ; if( verb ) ININFO_message("-mone: scaling fit by %g",sum) ; for( ii=0 ; ii < nvox ; ii++ ) par[ii] *= sum ; } } /* if there's a mask, clip values outside of its box */ #undef PF #define PF(i,j,k) par[(i)+(j)*nx+(k)*nxy] if( mask != NULL && do_mclip ){ int xm,xp,ym,yp,zm,zp , ii,jj,kk , nx,ny,nz,nxy ; float *par ; MRI_IMAGE *bim = mri_empty_conforming( imout , MRI_byte ) ; mri_fix_data_pointer(mask,bim) ; if( verb ) ININFO_message("-mclip: polynomial fit to autobox of mask") ; MRI_autobbox( bim , &xm,&xp , &ym,&yp , &zm,&zp ) ; mri_clear_data_pointer(bim) ; mri_free(bim) ; nx = imout->nx ; ny = imout->ny ; nz = imout->nz ; nxy = nx*ny ; par = MRI_FLOAT_PTR(imout) ; for( ii=0 ; ii < xm ; ii++ ) for( kk=0 ; kk < nz ; kk++ ) for( jj=0 ; jj < ny ; jj++ ) PF(ii,jj,kk) = PF(xm,jj,kk) ; for( ii=xp+1 ; ii < nx ; ii++ ) for( kk=0 ; kk < nz ; kk++ ) for( jj=0 ; jj < ny ; jj++ ) PF(ii,jj,kk) = PF(xp,jj,kk) ; for( jj=0 ; jj < ym ; jj++ ) for( kk=0 ; kk < nz ; kk++ ) for( ii=0 ; ii < nx ; ii++ ) PF(ii,jj,kk) = PF(ii,ym,kk) ; for( jj=yp+1 ; jj < ny ; jj++ ) for( kk=0 ; kk < nz ; kk++ ) for( ii=0 ; ii < nx ; ii++ ) PF(ii,jj,kk) = PF(ii,yp,kk) ; for( kk=0 ; kk < zm ; kk++ ) for( jj=0 ; jj < ny ; jj++ ) for( ii=0 ; ii < nx ; ii++ ) PF(ii,jj,kk) = PF(ii,jj,zm) ; for( kk=zp+1 ; kk < nz ; kk++ ) for( jj=0 ; jj < ny ; jj++ ) for( ii=0 ; ii < nx ; ii++ ) PF(ii,jj,kk) = PF(ii,jj,zp) ; } if( mask != NULL ) free(mask) ; /* write outputs */ if( prefix != NULL ){ THD_3dim_dataset *outset = EDIT_empty_copy( inset ) ; EDIT_dset_items( outset , ADN_prefix , prefix , ADN_nvals , 1 , ADN_ntt , 0 , ADN_none ) ; EDIT_substitute_brick( outset , 0 , MRI_float , MRI_FLOAT_PTR(imout) ) ; tross_Copy_History( inset , outset ) ; tross_Make_History( "3dPolyfit" , argc,argv , outset ) ; DSET_write(outset) ; WROTE_DSET(outset) ; } if( resid != NULL ){ THD_3dim_dataset *outset = EDIT_empty_copy( inset ) ; float *inar=MRI_FLOAT_PTR(imin) , *outar=MRI_FLOAT_PTR(imout) ; int nx,ny,nz , nxyz , kk ; nx = imout->nx ; ny = imout->ny ; nz = imout->nz ; nxyz = nx*ny*nz ; for( kk=0 ; kk < nxyz ; kk++ ) outar[kk] = inar[kk] - outar[kk] ; mri_free(imin) ; EDIT_dset_items( outset , ADN_prefix , resid , ADN_nvals , 1 , ADN_ntt , 0 , ADN_none ) ; EDIT_substitute_brick( outset , 0 , MRI_float , MRI_FLOAT_PTR(imout) ) ; tross_Copy_History( inset , outset ) ; tross_Make_History( "3dPolyfit" , argc,argv , outset ) ; DSET_write(outset) ; WROTE_DSET(outset) ; } if( cfnam != NULL && fvit != NULL ){ /* won't work with '-byslice' */ char *qn ; qn = STRING_HAS_SUFFIX(cfnam,".1D") ? cfnam : modify_afni_prefix(cfnam,NULL,".1D") ; mri_write_floatvec( qn , fvit ) ; } exit(0) ; }
int main( int argc , char *argv[] ) { char *aname ; THD_3dim_dataset *dset ; int ii , scl ; MRI_IMAGE *im , *qim ; char *fname ; float fac ; int do_4D=0 , iarg=1 ; /* 30 Sep 2002 */ FILE *ifp=NULL ; int xxor=-1,yyor=0,zzor=0 , xdir=0,ydir=0,zdir=0; /* 19 Mar 2003 */ float xdel=0.0 ,ydel=0.0,zdel=0.0; char orient_code[4] ; /*-- help me if you can --*/ WARNING_message("This program (3dAFNItoANALYZE) is old, not maintained, and probably useless!") ; if( argc < 3 || strcmp(argv[1],"-help") == 0 ){ printf("Usage: 3dAFNItoANALYZE [-4D] [-orient code] aname dset\n" "Writes AFNI dataset 'dset' to 1 or more ANALYZE 7.5 format\n" ".hdr/.img file pairs (one pair for each sub-brick in the\n" "AFNI dataset). The ANALYZE files will be named\n" " aname_0000.hdr aname_0000.img for sub-brick #0\n" " aname_0001.hdr aname_0001.img for sub-brick #1\n" "and so forth. Each file pair will contain a single 3D array.\n" "\n" "* If the AFNI dataset does not include sub-brick scale\n" " factors, then the ANALYZE files will be written in the\n" " datum type of the AFNI dataset.\n" "* If the AFNI dataset does have sub-brick scale factors,\n" " then each sub-brick will be scaled to floating format\n" " and the ANALYZE files will be written as floats.\n" "* The .hdr and .img files are written in the native byte\n" " order of the computer on which this program is executed.\n" "\n" "Options\n" "-------\n" "-4D [30 Sep 2002]:\n" " If you use this option, then all the data will be written to\n" " one big ANALYZE file pair named aname.hdr/aname.img, rather\n" " than a series of 3D files. Even if you only have 1 sub-brick,\n" " you may prefer this option, since the filenames won't have\n" " the '_0000' appended to 'aname'.\n" "\n" "-orient code [19 Mar 2003]:\n" " This option lets you flip the dataset to a different orientation\n" " when it is written to the ANALYZE files. The orientation code is\n" " formed as follows:\n" " The code must be 3 letters, one each from the\n" " pairs {R,L} {A,P} {I,S}. The first letter gives\n" " the orientation of the x-axis, the second the\n" " orientation of the y-axis, the third the z-axis:\n" " R = Right-to-Left L = Left-to-Right\n" " A = Anterior-to-Posterior P = Posterior-to-Anterior\n" " I = Inferior-to-Superior S = Superior-to-Inferior\n" " For example, 'LPI' means\n" " -x = Left +x = Right\n" " -y = Posterior +y = Anterior\n" " -z = Inferior +z = Superior\n" " * For display in SPM, 'LPI' or 'RPI' seem to work OK.\n" " Be careful with this: you don't want to confuse L and R\n" " in the SPM display!\n" " * If you DON'T use this option, the dataset will be written\n" " out in the orientation in which it is stored in AFNI\n" " (e.g., the output of '3dinfo dset' will tell you this.)\n" " * The dataset orientation is NOT stored in the .hdr file.\n" " * AFNI and ANALYZE data are stored in files with the x-axis\n" " varying most rapidly and the z-axis most slowly.\n" " * Note that if you read an ANALYZE dataset into AFNI for\n" " display, AFNI assumes the LPI orientation, unless you\n" " set environment variable AFNI_ANALYZE_ORIENT.\n" ) ; PRINT_COMPILE_DATE; exit(0) ; } mainENTRY("3dAFNItoANALYZE main"); machdep(); PRINT_VERSION("3dAFNItoANALYZE"); /*-- read inputs --*/ while( iarg < argc && argv[iarg][0] == '-' ){ if( strcmp(argv[iarg],"-4D") == 0 ){ /* 30 Sep 2002 */ do_4D = 1 ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-orient") == 0 ){ /* 19 Mar 2003 */ char acod ; if( iarg+1 >= argc ){ fprintf(stderr,"** Need something after -orient!\n"); exit(1); } MCW_strncpy(orient_code,argv[++iarg],4) ; if( strlen(orient_code) != 3 ){ fprintf(stderr,"** Illegal code '%s' after -orient!\n",argv[iarg]); exit(1); } acod = toupper(orient_code[0]) ; xxor = ORCODE(acod) ; acod = toupper(orient_code[1]) ; yyor = ORCODE(acod) ; acod = toupper(orient_code[2]) ; zzor = ORCODE(acod) ; if( xxor<0 || yyor<0 || zzor<0 || !OR3OK(xxor,yyor,zzor) ){ fprintf(stderr,"** Unusable code after -orient!\n"); exit(1); } iarg++ ; continue ; } fprintf(stderr,"** Illegal option: %s\n",argv[iarg]); exit(1); } if( iarg >= argc-1 ){ fprintf(stderr,"** Not enough arguments on command line!\n"); exit(1); } aname = argv[iarg++] ; if( !THD_filename_ok(aname) ){ fprintf(stderr,"** Illegal aname string %s\n",aname) ; exit(1) ; } fname = malloc( strlen(aname)+16 ) ; dset = THD_open_dataset( argv[iarg++] ); CHECK_OPEN_ERROR(dset,argv[iarg-1]); if( xxor >= 0 ){ /* 19 Mar 2003: figure how to flip */ xdir = THD_get_axis_direction( dset->daxes , xxor ) ; ydir = THD_get_axis_direction( dset->daxes , yyor ) ; zdir = THD_get_axis_direction( dset->daxes , zzor ) ; if( ydir == 0 || zdir == 0 ) xdir = 0 ; if( xdir == 1 && ydir == 2 && zdir == 3 ) xdir = 0 ; } if( xdir != 0 ){ float dx=fabs(DSET_DX(dset)) , dy=fabs(DSET_DY(dset)) , dz=fabs(DSET_DZ(dset)) ; DSET_mallocize(dset) ; switch( xdir ){ case 1: case -1: xdel = dx ; break ; case 2: case -2: xdel = dy ; break ; case 3: case -3: xdel = dz ; break ; } switch( ydir ){ case 1: case -1: ydel = dx ; break ; case 2: case -2: ydel = dy ; break ; case 3: case -3: ydel = dz ; break ; } switch( zdir ){ case 1: case -1: zdel = dx ; break ; case 2: case -2: zdel = dy ; break ; case 3: case -3: zdel = dz ; break ; } } else { xdel = fabs(DSET_DX(dset)) ; ydel = fabs(DSET_DY(dset)) ; zdel = fabs(DSET_DZ(dset)) ; } DSET_load(dset) ; CHECK_LOAD_ERROR(dset) ; /* determine if we scale to floats */ scl = THD_need_brick_factor( dset ) ; /* 30 Sep 2002: if doing a 4D file, write single .hdr now */ if( do_4D ){ im = mri_empty_conforming( DSET_BRICK(dset,0) , (scl) ? MRI_float : DSET_BRICK_TYPE(dset,0) ) ; if( xdir != 0 ){ qim = mri_flip3D( xdir,ydir,zdir , im ) ; if( qim == NULL){ fprintf(stderr,"mri_flip3D fails?!\n"); exit(1); } mri_free(im); im = qim; } im->dx = xdel ; /* load voxel sizes */ im->dy = ydel ; im->dz = zdel ; im->dw = 1.0 ; if( AFNI_yesenv("AFNI_ANALYZE_ORIGINATOR") ){ im->xo = dset->daxes->xxorg ; /* load voxel origin */ im->yo = dset->daxes->yyorg ; /* 03/11/04 KRH added this bit for SPM */ im->zo = dset->daxes->zzorg ; if( ORIENT_sign[dset->daxes->xxorient] == '-' ){ im->dx = -im->dx ; /* im->xo = -im->xo ; */ } if( ORIENT_sign[dset->daxes->yyorient] == '-' ){ im->dy = -im->dy ; /* im->yo = -im->yo ; */ } if( ORIENT_sign[dset->daxes->zzorient] == '-' ){ im->dz = -im->dz ; /* im->zo = -im->zo ; */ } } im->nt = DSET_NVALS(dset) ; /* add a time axis */ im->dt = DSET_TR(dset) ; if( im->dt <= 0.0 ) im->dt = 1.0 ; if( DSET_TIMEUNITS(dset) == UNITS_MSEC_TYPE ) im->dt *= 0.001 ; /* 05 Jul 2005 */ mri_write_analyze( aname , im ) ; /* output 4D .hdr file */ mri_free(im) ; sprintf(fname,"%s.img",aname) ; /* open output .img file */ ifp = fopen( fname , "wb" ) ; if( ifp == NULL ){ fprintf(stderr,"** Can't open file %s for output!\n",fname) ; exit(1) ; } } /* loop over sub-bricks */ for( ii=0 ; ii < DSET_NVALS(dset) ; ii++ ){ im = DSET_BRICK(dset,ii) ; /* get the sub-brick */ if( scl ){ /* scale it to floats */ fac = DSET_BRICK_FACTOR(dset,ii) ; if( fac == 0.0 ) fac = 1.0 ; qim = mri_scale_to_float( fac , im ) ; } else { qim = im ; } if( xdir != 0 ){ /* 19 Mar 2003: flip it */ MRI_IMAGE *fim ; fim = mri_flip3D( xdir,ydir,zdir , qim ) ; if( fim == NULL ){ fprintf(stderr,"mri_flip3D fails at ii=%d ?!\n",ii); exit(1); } if( qim != im ) mri_free(qim) ; qim = fim ; } if( do_4D ){ /* 30 Sep 2002: write into 4D .img file */ fwrite( mri_data_pointer(qim) , qim->nvox , qim->pixel_size , ifp ) ; } else { /* write separate 3D .hdr/.img files */ qim->dx = xdel ; /* load voxel sizes */ qim->dy = ydel ; qim->dz = zdel ; qim->dw = 1.0 ; if( AFNI_yesenv("AFNI_ANALYZE_ORIGINATOR") ){ qim->xo = dset->daxes->xxorg ; /* load voxel origin */ qim->yo = dset->daxes->yyorg ; /* 03/11/04 KRH added this bit for SPM */ qim->zo = dset->daxes->zzorg ; if( ORIENT_sign[dset->daxes->xxorient] == '-' ){ qim->dx = -qim->dx ; /* qim->xo = -qim->xo ; */ } if( ORIENT_sign[dset->daxes->yyorient] == '-' ){ qim->dy = -qim->dy ; /* qim->yo = -qim->yo ; */ } if( ORIENT_sign[dset->daxes->zzorient] == '-' ){ qim->dz = -qim->dz ; /* qim->zo = -qim->zo ; */ } } sprintf(fname,"%s_%04d",aname,ii) ; /* make up a filename */ mri_write_analyze( fname , qim ) ; /* do the real work */ } if( qim != im ) mri_free(qim) ; DSET_unload_one(dset,ii) ; /* clean up the trash */ } if( ifp != NULL ) fclose(ifp) ; /* 30 Sep 2002 */ free(fname) ; exit(0) ; }
int main( int argc , char * argv[] ) { THD_dfvec3 *xx , *yy , dv ; int nvec=0 , ii,jj, iarg ; THD_dvecmat rt , rtinv ; THD_dmat33 pp,ppt , rr ; THD_dfvec3 tt ; THD_3dim_dataset *mset=NULL , *dset=NULL ; double *ww=NULL ; int nww=0 ; int keeptags=1 , wtval=0 , verb=0 , dummy=0 ; char * prefix = "tagalign" , *mfile=NULL ; float *fvol , cbot,ctop , dsum ; int nval , nvox , clipit , ival, RMETH=MRI_CUBIC; float matar[12] ; int use_3dWarp=1 , matrix_type=ROTATION ; mainENTRY("3dTagalign main"); /*--- help? ---*/ /*- scan args -*/ iarg = 1 ; RMETH=MRI_CUBIC; while( iarg < argc && argv[iarg][0] == '-' ){ /*-----*/ if( strcmp(argv[iarg],"-h") == 0 || strcmp(argv[iarg],"-help") == 0){ /* 22 Apr 2003 */ usage_3dTagalign(strlen(argv[iarg]) > 3 ? 2:1); exit(0); } /*-----*/ if( strcmp(argv[iarg],"-NN") == 0 ){ RMETH = MRI_NN ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-linear") == 0 ){ RMETH = MRI_LINEAR ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-cubic") == 0 ){ RMETH = MRI_CUBIC ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-quintic") == 0 ){ RMETH = MRI_QUINTIC ; iarg++ ; continue ; } /*-----*/ if( strcmp(argv[iarg],"-rotate") == 0 ){ /* 22 Apr 2003 */ matrix_type = ROTATION ; use_3dWarp = 1 ; iarg++ ; continue ; } /*-----*/ if( strcmp(argv[iarg],"-affine") == 0 ){ /* 21 Apr 2003 */ matrix_type = AFFINE ; use_3dWarp = 1 ; iarg++ ; continue ; } /*-----*/ if( strcmp(argv[iarg],"-rotscl") == 0 ){ /* 22 Apr 2003 */ matrix_type = ROTSCL ; use_3dWarp = 1 ; iarg++ ; continue ; } #if 0 /*-----*/ if( strcmp(argv[iarg],"-3dWarp") == 0 ){ /* 21 Apr 2003 */ use_3dWarp = 1 ; iarg++ ; continue ; } #endif /*-----*/ if( strcmp(argv[iarg],"-master") == 0 ){ if( mset != NULL ) ERREX("Can only have one -master option") ; if( ++iarg >= argc ) ERREX("Need an argument after -master") ; mset = THD_open_dataset( argv[iarg] ) ; if( mset == NULL ) ERREX("Can't open -master dataset") ; if( mset->tagset == NULL ) ERREX("No tags in -master dataset") ; if( TAGLIST_COUNT(mset->tagset) < 3 ) ERREX("Not enough tags in -master dataset") ; for( nvec=ii=0 ; ii < TAGLIST_COUNT(mset->tagset) ; ii++ ) if( TAG_SET(TAGLIST_SUBTAG(mset->tagset,ii)) ) nvec++ ; if( nvec < 3 ) ERREX("Not enough tags set in -master dataset") ; if( nvec < TAGLIST_COUNT(mset->tagset) ) fprintf(stderr,"++ WARNING: not all tags are set in -master dataset\n") ; if( verb ) fprintf(stderr,"++ Found %d tags in -master dataset\n",nvec) ; iarg++ ; continue ; } #if 0 /*-----*/ if( strcmp(argv[iarg],"-wtval") == 0 ){ if( ww != NULL ) ERREX("Can't have -wtval after -wt1D") ; wtval++ ; iarg++ ; continue ; } /*-----*/ if( strcmp(argv[iarg],"-wt1D") == 0 ){ MRI_IMAGE * wtim ; float * wtar ; if( wtval ) ERREX("Can't have -wt1D after -wtval") ; if( ww != NULL ) ERREX("Can't have two -wt1D options!") ; if( ++iarg >= argc ) ERREX("Need an argument after -wt1D") ; wtim = mri_read_1D( argv[iarg] ) ; if( wtim == NULL ) ERREX("Can't read -wtim file") ; if( wtim->ny > 1 ) ERREX("-wtim file has more than one columm") ; wtar = MRI_FLOAT_PTR(wtim) ; ww = (double *) malloc(sizeof(double)*wtim->nx) ; nww = wtim->nx ; for( ii=0 ; ii < nww ; ii++ ){ ww[ii] = (double) wtar[ii] ; if( ww[ii] < 0.0 ) ERREX("Negative value found in -wt1D file") ; } mri_free(wtim) ; iarg++ ; continue ; } #endif /*-----*/ if( strcmp(argv[iarg],"-nokeeptags") == 0 ){ keeptags = 0 ; iarg++ ; continue ; } /*-----*/ if( strncmp(argv[iarg],"-verb",5) == 0 ){ verb++ ; iarg++ ; continue ; } /*-----*/ if( strcmp(argv[iarg],"-dummy") == 0 ){ dummy++ ; iarg++ ; continue ; } /*-----*/ if( strcmp(argv[iarg],"-prefix") == 0 ){ if( ++iarg >= argc ) ERREX("Need an argument after -prefix") ; prefix = argv[iarg] ; if( !THD_filename_ok(prefix) ) ERREX("-prefix string is illegal") ; iarg++ ; continue ; } /*-----*/ if( strcmp(argv[iarg],"-matvec") == 0 ){ if( ++iarg >= argc ) ERREX("Need an argument after -matvec") ; mfile = argv[iarg] ; if( !THD_filename_ok(mfile) ) ERREX("-matvec string is illegal") ; iarg++ ; continue ; } /*-----*/ fprintf(stderr,"** Unknown option: %s\n",argv[iarg]) ; suggest_best_prog_option(argv[0], argv[iarg]); exit(1) ; } /* end of scanning command line for options */ if( argc < 2 ){ ERROR_message("Too few options"); usage_3dTagalign(0); exit(1) ; } if( mset == NULL ) ERREX("No -master option found on command line") ; #if 0 if( ww != NULL && nww < nvec ) ERREX("Not enough weights found in -wt1D file") ; /*-- if -wtval, setup weights from master tag values --*/ if( wtval ){ ww = (double *) malloc(sizeof(double)*nvec) ; nww = nvec ; for( ii=jj=0 ; ii < TAGLIST_COUNT(mset->tagset) ; ii++ ){ if( TAG_SET(TAGLIST_SUBTAG(mset->tagset,ii)) ){ ww[jj] = (double) TAG_VAL(TAGLIST_SUBTAG(mset->tagset,ii)) ; if( ww[jj] < 0.0 ) ERREX("Negative value found in -master tag values") ; jj++ ; } } } #endif /*-- read input dataset (to match to master dataset) --*/ if( iarg >= argc ) ERREX("No input dataset?") ; dset = THD_open_dataset( argv[iarg] ) ; if( dset == NULL ) ERREX("Can't open input dataset") ; if( dset->tagset == NULL ) ERREX("No tags in input dataset") ; if( TAGLIST_COUNT(dset->tagset) != TAGLIST_COUNT(mset->tagset) ) ERREX("Tag counts don't match in -master and input") ; /* check if set tags match exactly */ for( ii=0 ; ii < TAGLIST_COUNT(mset->tagset) ; ii++ ){ if( TAG_SET(TAGLIST_SUBTAG(mset->tagset,ii)) != TAG_SET(TAGLIST_SUBTAG(dset->tagset,ii)) ) ERREX("Set tags don't match in -master and input") ; } /*-- load vector lists: xx=master, yy=input --*/ xx = (THD_dfvec3 *) malloc( sizeof(THD_dfvec3) * nvec ) ; yy = (THD_dfvec3 *) malloc( sizeof(THD_dfvec3) * nvec ) ; dsum = 0.0 ; for( ii=jj=0 ; ii < nvec ; ii++ ){ if( TAG_SET(TAGLIST_SUBTAG(mset->tagset,ii)) ){ LOAD_DFVEC3( xx[jj] , /* N.B.: */ TAG_X( TAGLIST_SUBTAG(mset->tagset,ii) ) , /* these are */ TAG_Y( TAGLIST_SUBTAG(mset->tagset,ii) ) , /* in Dicom */ TAG_Z( TAGLIST_SUBTAG(mset->tagset,ii) ) ) ; /* order now */ LOAD_DFVEC3( yy[jj] , TAG_X( TAGLIST_SUBTAG(dset->tagset,ii) ) , TAG_Y( TAGLIST_SUBTAG(dset->tagset,ii) ) , TAG_Z( TAGLIST_SUBTAG(dset->tagset,ii) ) ) ; dv = SUB_DFVEC3( xx[jj] , yy[jj] ) ; dsum += dv.xyz[0]*dv.xyz[0] + dv.xyz[1]*dv.xyz[1] + dv.xyz[2]*dv.xyz[2] ; jj++ ; } } dsum = sqrt(dsum/nvec) ; fprintf(stderr,"++ RMS distance between tags before = %.2f mm\n" , dsum ) ; /*-- compute best transformation from mset to dset coords --*/ switch( matrix_type ){ default: case ROTATION: rt = DLSQ_rot_trans( nvec , yy , xx , ww ) ; /* in thd_rot3d.c */ break ; case AFFINE: rt = DLSQ_affine ( nvec , yy , xx ) ; /* 21 Apr 2003 */ break ; case ROTSCL: rt = DLSQ_rotscl ( nvec , yy , xx , (DSET_NZ(dset)==1) ? 2 : 3 ) ; break ; } rtinv = INV_DVECMAT(rt) ; /*-- check for floating point legality --*/ nval = 0 ; for( ii=0 ; ii < 3 ; ii++ ){ dsum = rt.vv.xyz[ii] ; nval += thd_floatscan(1,&dsum) ; for( jj=0 ; jj < 3 ; jj++ ){ dsum = rt.mm.mat[ii][jj] ; nval += thd_floatscan(1,&dsum) ; } } if( nval > 0 ){ fprintf(stderr,"** Floating point errors during calculation\n" "** of transform matrix and translation vector\n" ) ; exit(1) ; } /*-- check for rotation matrix legality --*/ dsum = DMAT_DET(rt.mm) ; if( dsum == 0.0 || (matrix_type == ROTATION && fabs(dsum-1.0) > 0.01) ){ fprintf(stderr,"** Invalid transform matrix computed: tags dependent?\n" "** computed [matrix] and [vector] follow:\n" ) ; for( ii=0 ; ii < 3 ; ii++ ) fprintf(stderr," [ %10.5f %10.5f %10.5f ] [ %10.5f ] \n", rt.mm.mat[ii][0],rt.mm.mat[ii][1],rt.mm.mat[ii][2],rt.vv.xyz[ii] ); exit(1) ; } /*-- print summary --*/ if( verb ){ fprintf(stderr,"++ Matrix & Vector [Dicom: x=R-L; y=A-P; z=I-S]\n") ; for( ii=0 ; ii < 3 ; ii++ ) fprintf(stderr," %10.5f %10.5f %10.5f %10.5f\n", rt.mm.mat[ii][0],rt.mm.mat[ii][1],rt.mm.mat[ii][2],rt.vv.xyz[ii] ); } if( matrix_type == ROTATION || matrix_type == ROTSCL ){ double theta, costheta , dist , fac=1.0 ; if( matrix_type == ROTSCL ){ fac = DMAT_DET(rt.mm); fac = fabs(fac); if( DSET_NZ(dset) == 1 ) fac = sqrt(fac) ; else fac = cbrt(fac) ; } costheta = 0.5 * sqrt(1.0 + DMAT_TRACE(rt.mm)/fac ) ; theta = 2.0 * acos(costheta) * 180/3.14159265 ; dist = SIZE_DFVEC3(rt.vv) ; fprintf(stderr,"++ Total rotation=%.2f degrees; translation=%.2f mm; scaling=%.2f\n", theta,dist,fac) ; } if( mfile ){ FILE * mp ; if( THD_is_file(mfile) ) fprintf(stderr,"++ Warning: -matvec will overwrite file %s\n",mfile) ; mp = fopen(mfile,"w") ; if( mp == NULL ){ fprintf(stderr,"** Can't write to -matvec %s\n",mfile) ; } else { for( ii=0 ; ii < 3 ; ii++ ) fprintf(mp," %10.5f %10.5f %10.5f %10.5f\n", rt.mm.mat[ii][0],rt.mm.mat[ii][1],rt.mm.mat[ii][2],rt.vv.xyz[ii] ); fclose(mp) ; if( verb ) fprintf(stderr,"++ Wrote matrix+vector to %s\n",mfile) ; } } if( dummy ){ fprintf(stderr,"++ This was a -dummy run: no output dataset\n") ; exit(0) ; } /*-- 21 Apr 2003: transformation can be done the old way (a la 3drotate), or the new way (a la 3dWarp). --*/ #if 0 if( !use_3dWarp ){ /**** the old way ****/ /*-- now must scramble the rotation matrix and translation vector from Dicom coordinate order to dataset brick order --*/ pp = DBLE_mat_to_dicomm( dset ) ; ppt = TRANSPOSE_DMAT(pp) ; rr = DMAT_MUL(ppt,rt.mm) ; rr = DMAT_MUL(rr,pp) ; tt = DMATVEC(ppt,rt.vv) ; /*-- now create the output dataset by screwing with the input dataset (this code is adapted from 3drotate.c) --*/ DSET_mallocize(dset) ; DSET_load( dset ) ; CHECK_LOAD_ERROR(dset) ; dset->idcode = MCW_new_idcode() ; dset->dblk->diskptr->storage_mode = STORAGE_BY_BRICK ; /* 14 Jan 2004 */ EDIT_dset_items( dset , ADN_prefix , prefix , ADN_label1 , prefix , ADN_none ) ; if( !THD_ok_overwrite() && (THD_deathcon() && THD_is_file(dset->dblk->diskptr->header_name) )){ fprintf(stderr, "** Output file %s already exists -- cannot continue!\n", dset->dblk->diskptr->header_name ) ; exit(1) ; } tross_Make_History( "3dTagalign" , argc,argv , dset ) ; /*-- if desired, keep old tagset --*/ if( keeptags ){ THD_dfvec3 rv ; dsum = 0.0 ; for( jj=ii=0 ; ii < TAGLIST_COUNT(dset->tagset) ; ii++ ){ if( TAG_SET(TAGLIST_SUBTAG(dset->tagset,ii)) ){ rv = DMATVEC( rt.mm , yy[jj] ) ; /* operating on */ rv = ADD_DFVEC3( rt.vv , rv ) ; /* Dicom order */ dv = SUB_DFVEC3( xx[jj] , rv ) ; dsum += dv.xyz[0]*dv.xyz[0] + dv.xyz[1]*dv.xyz[1] + dv.xyz[2]*dv.xyz[2] ; UNLOAD_DFVEC3( rv , TAG_X( TAGLIST_SUBTAG(dset->tagset,ii) ) , TAG_Y( TAGLIST_SUBTAG(dset->tagset,ii) ) , TAG_Z( TAGLIST_SUBTAG(dset->tagset,ii) ) ) ; jj++ ; } } dsum = sqrt(dsum/nvec) ; fprintf(stderr,"++ RMS distance between tags after = %.2f mm\n" , dsum ) ; } else { myXtFree(dset->tagset) ; /* send it to the dustbin */ } /*-- rotate sub-bricks --*/ if( verb ) fprintf(stderr,"++ computing output BRIK") ; nvox = DSET_NVOX(dset) ; nval = DSET_NVALS(dset) ; fvol = (float *) malloc( sizeof(float) * nvox ) ; THD_rota_method( MRI_HEPTIC ) ; clipit = 1 ; for( ival=0 ; ival < nval ; ival++ ){ /*- get sub-brick out of dataset -*/ EDIT_coerce_type( nvox , DSET_BRICK_TYPE(dset,ival),DSET_ARRAY(dset,ival) , MRI_float,fvol ) ; if( clipit ){ register int ii ; register float bb,tt ; bb = tt = fvol[0] ; for( ii=1 ; ii < nvox ; ii++ ){ if( fvol[ii] < bb ) bb = fvol[ii] ; else if( fvol[ii] > tt ) tt = fvol[ii] ; } cbot = bb ; ctop = tt ; } if( verb && nval < 5 ) fprintf(stderr,".") ; /*- rotate it -*/ THD_rota_vol_matvec( DSET_NX(dset) , DSET_NY(dset) , DSET_NZ(dset) , fabs(DSET_DX(dset)) , fabs(DSET_DY(dset)) , fabs(DSET_DZ(dset)) , fvol , rr , tt ) ; if( verb ) fprintf(stderr,".") ; if( clipit ){ register int ii ; register float bb,tt ; bb = cbot ; tt = ctop ; for( ii=0 ; ii < nvox ; ii++ ){ if( fvol[ii] < bb ) fvol[ii] = bb ; else if( fvol[ii] > tt ) fvol[ii] = tt ; } } if( verb && nval < 5 ) fprintf(stderr,".") ; /*- put it back into dataset -*/ EDIT_coerce_type( nvox, MRI_float,fvol , DSET_BRICK_TYPE(dset,ival),DSET_ARRAY(dset,ival) ); } /* end of loop over sub-brick index */ if( verb ) fprintf(stderr,":") ; /* save matrix+vector into dataset, too */ UNLOAD_DMAT(rt.mm,matar[0],matar[1],matar[2], matar[4],matar[5],matar[6], matar[8],matar[9],matar[10] ) ; UNLOAD_DFVEC3(rt.vv,matar[3],matar[7],matar[11]) ; THD_set_atr( dset->dblk, "TAGALIGN_MATVEC", ATR_FLOAT_TYPE, 12, matar ) ; /* write dataset to disk */ dset->dblk->master_nvals = 0 ; /* in case this was a mastered dataset */ DSET_write(dset) ; if( verb ) fprintf(stderr,"\n") ; } else #endif { /**** the new way: use 3dWarp type transformation ****/ THD_3dim_dataset *oset ; THD_vecmat tran ; #if 0 DFVEC3_TO_FVEC3( rt.vv , tran.vv ) ; DMAT_TO_MAT ( rt.mm , tran.mm ) ; #else DFVEC3_TO_FVEC3( rtinv.vv , tran.vv ) ; DMAT_TO_MAT ( rtinv.mm , tran.mm ) ; #endif mri_warp3D_method( RMETH ) ; oset = THD_warp3D_affine( dset, tran, mset, prefix, 0, WARP3D_NEWDSET ) ; if( oset == NULL ){ fprintf(stderr,"** ERROR: THD_warp3D() fails!\n"); exit(1); } tross_Copy_History( dset , oset ) ; tross_Make_History( "3dTagalign" , argc,argv , oset ) ; UNLOAD_DMAT(rt.mm,matar[0],matar[1],matar[2], matar[4],matar[5],matar[6], matar[8],matar[9],matar[10] ) ; UNLOAD_DFVEC3(rt.vv,matar[3],matar[7],matar[11]) ; THD_set_atr( oset->dblk, "TAGALIGN_MATVEC", ATR_FLOAT_TYPE, 12, matar ) ; /*-- if desired, keep old tagset --*/ if( keeptags ){ THD_dfvec3 rv ; oset->tagset = myXtNew(THD_usertaglist) ; *(oset->tagset) = *(dset->tagset) ; dsum = 0.0 ; for( jj=ii=0 ; ii < TAGLIST_COUNT(oset->tagset) ; ii++ ){ if( TAG_SET(TAGLIST_SUBTAG(oset->tagset,ii)) ){ rv = DMATVEC( rt.mm , yy[jj] ) ; rv = ADD_DFVEC3( rt.vv , rv ) ; dv = SUB_DFVEC3( xx[jj] , rv ) ; dsum += dv.xyz[0]*dv.xyz[0] + dv.xyz[1]*dv.xyz[1] + dv.xyz[2]*dv.xyz[2] ; UNLOAD_DFVEC3( rv , TAG_X( TAGLIST_SUBTAG(oset->tagset,ii) ) , TAG_Y( TAGLIST_SUBTAG(oset->tagset,ii) ) , TAG_Z( TAGLIST_SUBTAG(oset->tagset,ii) ) ) ; jj++ ; } } dsum = sqrt(dsum/nvec) ; fprintf(stderr,"++ RMS distance between tags after = %.2f mm\n" , dsum ) ; } DSET_write(oset) ; } /* end of 3dWarp-like work */ exit(0) ; }
MRI_vectim * THD_2dset_to_vectim( THD_3dim_dataset *dset1, byte *mask1 , THD_3dim_dataset *dset2, byte *mask2 , int ignore ) { byte *mmmv[2]={NULL, NULL}, *mmmt=NULL; THD_3dim_dataset *dsetv[2]={NULL, NULL}; MRI_vectim *mrv=NULL ; int kk2, kk,iv,id, nvals , nvoxv[2]={0,0} , nmaskv[2]={0,0} ; int *ivvectmp=NULL; ENTRY("THD_2dset_to_vectim") ; mmmv[0] = mask1; mmmv[1] = mask2; dsetv[0] = dset1; dsetv[1] = dset2; for (id=0; id<2;++id) { if( !ISVALID_DSET(dsetv[id]) ) RETURN(NULL) ; DSET_load(dsetv[id]) ; if( !DSET_LOADED(dsetv[id]) ) RETURN(NULL) ; nvoxv[id] = DSET_NVOX(dsetv[id]) ; } if (DSET_NVALS(dsetv[0]) != DSET_NVALS(dsetv[1])) { RETURN(NULL) ; } if( ignore < 0 ) ignore = 0 ; nvals = DSET_NVALS(dsetv[0]) - ignore ; if( nvals <= 0 ) RETURN(NULL) ; for (id=0; id<2; ++id) { if( mmmv[id] != NULL ){ nmaskv[id] = THD_countmask( nvoxv[id] , mmmv[id] ) ;/* number to keep */ if( nmaskv[id] <= 0 ) RETURN(NULL) ; } else { nmaskv[id] = nvoxv[id] ; /* keep them all */ #pragma omp critical (MALLOC) mmmv[id] = (byte *)malloc(sizeof(byte)*nmaskv[id]) ; if( mmmv[id] == NULL ){ ERROR_message("THD_2dset_to_vectim: out of memory") ; RETURN(NULL) ; } memset( mmmv[id] , 1 , sizeof(byte)*nmaskv[id] ) ; } } #pragma omp critical (MALLOC) mrv = (MRI_vectim *)malloc(sizeof(MRI_vectim)) ; mrv->nvec = nmaskv[0]+nmaskv[1] ; mrv->nvals = nvals ; mrv->ignore = ignore ; #pragma omp critical (MALLOC) mrv->ivec = (int *)malloc(sizeof(int)*(nmaskv[0]+nmaskv[1])) ; #pragma omp critical (MALLOC) ivvectmp = (int *)malloc(sizeof(int)*(nmaskv[1])) ; if( mrv->ivec == NULL || ivvectmp == NULL){ ERROR_message("THD_2dset_to_vectim: out of memory") ; if (mrv->ivec) free(mrv->ivec) ; if (ivvectmp) free(ivvectmp) ; free(mrv) ; if( mmmv[0] != mask1 ) free(mmmv[0]) ; if( mmmv[1] != mask2 ) free(mmmv[1]) ; RETURN(NULL) ; } #pragma omp critical (MALLOC) mrv->fvec = (float *)malloc(sizeof(float)*(nmaskv[0]+nmaskv[1])*(size_t)nvals) ; if( mrv->fvec == NULL ){ ERROR_message("THD_2dset_to_vectim: out of memory") ; if (ivvectmp) free(ivvectmp) ; free(mrv->ivec) ; free(mrv) ; if( mmmv[0] != mask1 ) free(mmmv[0]) ; if( mmmv[1] != mask2 ) free(mmmv[1]) ; RETURN(NULL) ; } /* store desired voxel time series */ mmmt = mmmv[0]; for( kk=iv=0 ; iv < nvoxv[0] ; iv++ ){ if( mmmt[iv] ) mrv->ivec[kk++] = iv ; /* build index list to 1st dset */ } mmmt = mmmv[1]; kk2 = 0; for( iv=0 ; iv < nvoxv[1] ; iv++ ){ if( mmmt[iv] ) { mrv->ivec[kk++] = iv + nvoxv[0] ; /* build index list to 2nd dset*/ ivvectmp[kk2++] = iv; } } if( ignore > 0 ){ /* extract 1 at a time, save what we want */ #pragma omp critical (MALLOC) float *var = (float *)malloc(sizeof(float)*(nvals+ignore)) ; mmmt = mmmv[0]; for( kk=iv=0 ; iv < nvoxv[0] ; iv++ ){ if( mmmt[iv] == 0 ) continue ; (void)THD_extract_array( iv , dsetv[0] , 0 , var ) ; AAmemcpy( VECTIM_PTR(mrv,kk) , var+ignore , sizeof(float)*nvals ) ; kk++ ; } mmmt = mmmv[1]; for( iv=0 ; iv < nvoxv[1] ; iv++ ){ if( mmmt[iv] == 0 ) continue ; (void)THD_extract_array( iv , dsetv[1] , 0 , var ) ; AAmemcpy( VECTIM_PTR(mrv,kk) , var+ignore , sizeof(float)*nvals ) ; kk++ ; } free(var) ; } else { /* do all at once: this way is a lot faster */ THD_extract_many_arrays( nmaskv[0] , mrv->ivec , dsetv[0] , mrv->fvec ) ; THD_extract_many_arrays( nmaskv[1] , ivvectmp, dsetv[1] , (mrv->fvec+(size_t)nmaskv[0]*(size_t)mrv->nvals) ) ; } mrv->nx = DSET_NX(dsetv[0]) + DSET_NX(dsetv[1]); mrv->dx = fabs(DSET_DX(dsetv[0])) ; mrv->ny = DSET_NY(dsetv[0]) ; mrv->dy = fabs(DSET_DY(dsetv[0])) ; mrv->nz = DSET_NZ(dsetv[0]) ; mrv->dz = fabs(DSET_DZ(dsetv[0])) ; DSET_UNMSEC(dsetv[0]) ; mrv->dt = DSET_TR(dsetv[0]) ; if( mrv->dt <= 0.0f ) mrv->dt = 1.0f ; if( mmmv[0] != mask1 ) free(mmmv[0]) ; if( mmmv[1] != mask2 ) free(mmmv[1]) ; if (ivvectmp) free(ivvectmp) ; if (0) { int ShowThisTs=38001; float *fff=NULL; fprintf(stderr,"++ ZSS mrv->nvec = %d, mrv->nvals = %d\n", mrv->nvec, mrv->nvals); for( kk=0 ; kk < mrv->nvals; ++kk) { fff=mrv->fvec+((size_t)mrv->nvals*(size_t)ShowThisTs); fprintf(stderr," %f \t", *(fff+kk)); } } VECTIM_scan(mrv) ; /* 09 Nov 2010 */ RETURN(mrv) ; }
MRI_vectim * THD_dset_to_vectim_stend( THD_3dim_dataset *dset, byte *mask , int start, int end ) { byte *mmm=mask ; MRI_vectim *mrv=NULL ; int kk,iv , nvals , nvox , nmask ; ENTRY("THD_dset_to_vectim_stend") ; if( !ISVALID_DSET(dset) ) RETURN(NULL) ; DSET_load(dset) ; if( !DSET_LOADED(dset) ) RETURN(NULL) ; if( start < 0 ) start = 0 ; if( end < start ) end = DSET_NVALS(dset)-1 ; nvals = end - start + 1 ; if( nvals <= 0 ) RETURN(NULL) ; nvox = DSET_NVOX(dset) ; if( mmm != NULL ){ nmask = THD_countmask( nvox , mmm ) ; /* number to keep */ if( nmask <= 0 ) RETURN(NULL) ; } else { nmask = nvox ; /* keep them all */ #pragma omp critical (MALLOC) mmm = (byte *)malloc(sizeof(byte)*nmask) ; if( mmm == NULL ){ ERROR_message("THD_dset_to_vectim: out of memory") ; RETURN(NULL) ; } memset( mmm , 1 , sizeof(byte)*nmask ) ; } #pragma omp critical (MALLOC) mrv = (MRI_vectim *)malloc(sizeof(MRI_vectim)) ; mrv->nvec = nmask ; mrv->nvals = nvals ; mrv->ignore = start ; #pragma omp critical (MALLOC) mrv->ivec = (int *)malloc(sizeof(int)*nmask) ; if( mrv->ivec == NULL ){ ERROR_message("THD_dset_to_vectim: out of memory") ; free(mrv) ; if( mmm != mask ) free(mmm) ; RETURN(NULL) ; } #pragma omp critical (MALLOC) mrv->fvec = (float *)malloc(sizeof(float)*(size_t)nmask*(size_t)nvals) ; if( mrv->fvec == NULL ){ ERROR_message("THD_dset_to_vectim: out of memory") ; free(mrv->ivec) ; free(mrv) ; if( mmm != mask ) free(mmm) ; RETURN(NULL) ; } /* store desired voxel time series */ for( kk=iv=0 ; iv < nvox ; iv++ ){ if( mmm[iv] ) mrv->ivec[kk++] = iv ; /* build index list */ } if( nvals < DSET_NVALS(dset) ){ /* extract 1 at a time, save what we want */ #pragma omp critical (MALLOC) float *var = (float *)malloc(sizeof(float)*(DSET_NVALS(dset))) ; for( kk=iv=0 ; iv < nvox ; iv++ ){ if( mmm[iv] == 0 ) continue ; (void)THD_extract_array( iv , dset , 0 , var ) ; AAmemcpy( VECTIM_PTR(mrv,kk) , var+start , sizeof(float)*nvals ) ; kk++ ; } free(var) ; } else { /* do all at once: this way is a lot faster */ THD_extract_many_arrays( nmask , mrv->ivec , dset , mrv->fvec ) ; } mrv->nx = DSET_NX(dset) ; mrv->dx = fabs(DSET_DX(dset)) ; mrv->ny = DSET_NY(dset) ; mrv->dy = fabs(DSET_DY(dset)) ; mrv->nz = DSET_NZ(dset) ; mrv->dz = fabs(DSET_DZ(dset)) ; DSET_UNMSEC(dset) ; mrv->dt = DSET_TR(dset) ; if( mrv->dt <= 0.0f ) mrv->dt = 1.0f ; if( mmm != mask ) free(mmm) ; VECTIM_scan(mrv) ; /* 09 Nov 2010 */ RETURN(mrv) ; }
MRI_vectim * THD_dset_to_vectim( THD_3dim_dataset *dset, byte *mask , int ignore ) { byte *mmm=mask ; MRI_vectim *mrv=NULL ; int kk,iv , nvals , nvox , nmask ; size_t ntot ; ENTRY("THD_dset_to_vectim") ; if( !ISVALID_DSET(dset) ) RETURN(NULL) ; DSET_load(dset) ; if( !DSET_LOADED(dset) ) RETURN(NULL) ; if( ignore < 0 ) ignore = 0 ; nvals = DSET_NVALS(dset) - ignore ; if( nvals <= 0 ) RETURN(NULL) ; nvox = DSET_NVOX(dset) ; if( mmm != NULL ){ nmask = THD_countmask( nvox , mmm ) ; /* number to keep */ if( nmask <= 0 ) RETURN(NULL) ; } else { nmask = nvox ; /* keep them all */ #pragma omp critical (MALLOC) mmm = (byte *)malloc(sizeof(byte)*nmask) ; if( mmm == NULL ){ ERROR_message("THD_dset_to_vectim: out of memory") ; RETURN(NULL) ; } memset( mmm , 1 , sizeof(byte)*nmask ) ; } #pragma omp critical (MALLOC) mrv = (MRI_vectim *)malloc(sizeof(MRI_vectim)) ; mrv->nvec = nmask ; mrv->nvals = nvals ; mrv->ignore = ignore ; #pragma omp critical (MALLOC) mrv->ivec = (int *)malloc(sizeof(int)*nmask) ; if( mrv->ivec == NULL ){ ERROR_message("THD_dset_to_vectim: out of memory") ; free(mrv) ; if( mmm != mask ) free(mmm) ; RETURN(NULL) ; } ntot = sizeof(float)*(size_t)nmask*(size_t)nvals ; #pragma omp critical (MALLOC) mrv->fvec = (float *)malloc(ntot) ; if( mrv->fvec == NULL ){ ERROR_message("THD_dset_to_vectim: out of memory -- tried to get %lld bytes",(long long)ntot) ; free(mrv->ivec) ; free(mrv) ; if( mmm != mask ) free(mmm) ; RETURN(NULL) ; } else if( ntot > 1000000000 ){ INFO_message("THD_dset_to_vectim: allocated %lld bytes",(long long)ntot) ; } /* store desired voxel time series */ STATUS("create index list") ; for( kk=iv=0 ; iv < nvox ; iv++ ){ if( mmm[iv] ) mrv->ivec[kk++] = iv ; /* build index list */ } if( ignore > 0 ){ /* extract 1 at a time, save what we want */ #pragma omp critical (MALLOC) float *var = (float *)malloc(sizeof(float)*(nvals+ignore)) ; STATUS("ignore > 0 --> extracting one at a time") ; for( kk=iv=0 ; iv < nvox ; iv++ ){ if( mmm[iv] == 0 ) continue ; (void)THD_extract_array( iv , dset , 0 , var ) ; AAmemcpy( VECTIM_PTR(mrv,kk) , var+ignore , sizeof(float)*nvals ) ; kk++ ; } free(var) ; } else { /* do all at once: this way is a lot faster */ STATUS("ignore==0 --> extracting all at once") ; THD_extract_many_arrays( nmask , mrv->ivec , dset , mrv->fvec ) ; } STATUS("setting parameters in vectim header") ; mrv->nx = DSET_NX(dset) ; mrv->dx = fabs(DSET_DX(dset)) ; mrv->ny = DSET_NY(dset) ; mrv->dy = fabs(DSET_DY(dset)) ; mrv->nz = DSET_NZ(dset) ; mrv->dz = fabs(DSET_DZ(dset)) ; DSET_UNMSEC(dset) ; mrv->dt = DSET_TR(dset) ; if( mrv->dt <= 0.0f ) mrv->dt = 1.0f ; if( mmm != mask ){ STATUS("free(mmm)") ; free(mmm) ; } STATUS("VECTIM_scan()") ; VECTIM_scan(mrv) ; /* 09 Nov 2010 */ RETURN(mrv) ; }
MRI_vectim * THD_dset_censored_to_vectim( THD_3dim_dataset *dset, byte *mask , int nkeep , int *keep ) { byte *mmm=mask ; MRI_vectim *mrv=NULL ; int kk,iv,jj , nvals , nvox , nmask ; ENTRY("THD_dset_censored_to_vectim") ; if( !ISVALID_DSET(dset) ) RETURN(NULL) ; if( nkeep <= 0 || keep == NULL ){ mrv = THD_dset_to_vectim( dset , mask , 0 ) ; RETURN(mrv) ; } if( ! THD_subset_loaded(dset,nkeep,keep) ){ DSET_load(dset) ; if( !DSET_LOADED(dset) ) RETURN(NULL) ; } nvals = nkeep ; nvox = DSET_NVOX(dset) ; if( mmm != NULL ){ nmask = THD_countmask( nvox , mmm ) ; /* number to keep */ if( nmask <= 0 ) RETURN(NULL) ; } else { nmask = nvox ; /* keep them all */ #pragma omp critical (MALLOC) mmm = (byte *)malloc(sizeof(byte)*nmask) ; if( mmm == NULL ){ ERROR_message("THD_dset_to_vectim: out of memory") ; RETURN(NULL) ; } memset( mmm , 1 , sizeof(byte)*nmask ) ; } #pragma omp critical (MALLOC) mrv = (MRI_vectim *)malloc(sizeof(MRI_vectim)) ; mrv->nvec = nmask ; mrv->nvals = nvals ; mrv->ignore = 0 ; #pragma omp critical (MALLOC) mrv->ivec = (int *)malloc(sizeof(int)*nmask) ; if( mrv->ivec == NULL ){ ERROR_message("THD_dset_to_vectim: out of memory") ; free(mrv) ; if( mmm != mask ) free(mmm) ; RETURN(NULL) ; } #pragma omp critical (MALLOC) mrv->fvec = (float *)malloc(sizeof(float)*(size_t)nmask*(size_t)nvals) ; if( mrv->fvec == NULL ){ ERROR_message("THD_dset_to_vectim: out of memory") ; free(mrv->ivec) ; free(mrv) ; if( mmm != mask ) free(mmm) ; RETURN(NULL) ; } /* store desired voxel time series */ for( kk=iv=0 ; iv < nvox ; iv++ ){ if( mmm[iv] ) mrv->ivec[kk++] = iv ; /* build index list */ } #pragma omp critical (MALLOC) { float *var = (float *)malloc(sizeof(float)*DSET_NVALS(dset)) ; float *vpt ; for( kk=iv=0 ; iv < nvox ; iv++ ){ if( mmm[iv] == 0 ) continue ; vpt = VECTIM_PTR(mrv,kk) ; kk++ ; if( nkeep > 1 ){ (void)THD_extract_array( iv , dset , 0 , var ) ; for( jj=0 ; jj < nkeep ; jj++ ) vpt[jj] = var[keep[jj]] ; } else { vpt[0] = THD_get_float_value(iv,keep[0],dset) ; } } free(var) ; } mrv->nx = DSET_NX(dset) ; mrv->dx = fabs(DSET_DX(dset)) ; mrv->ny = DSET_NY(dset) ; mrv->dy = fabs(DSET_DY(dset)) ; mrv->nz = DSET_NZ(dset) ; mrv->dz = fabs(DSET_DZ(dset)) ; DSET_UNMSEC(dset) ; mrv->dt = DSET_TR(dset) ; if( mrv->dt <= 0.0f ) mrv->dt = 1.0f ; if( mmm != mask ) free(mmm) ; VECTIM_scan(mrv) ; /* 09 Nov 2010 */ RETURN(mrv) ; }
int main( int argc , char *argv[] ) { THD_3dim_dataset *inset=NULL , *jnset=NULL , *outset , *wset=NULL; int ncode=0 , code[MAX_NCODE] , iarg=1 , ii ; MCW_cluster *nbhd=NULL ; byte *mask=NULL ; int mask_nx=0,mask_ny=0,mask_nz=0 , automask=0 ; char *prefix="./localstat" ; int ntype=0 ; float na=0.0f,nb=0.0f,nc=0.0f ; double hist_pow=0.3333333 ; int hist_nbin=0 ; float hbot1=1.0f , htop1=-1.0f ; int hbot1_perc=0, htop1_perc=0 ; float hbot2=1.0f , htop2=-1.0f ; int hbot2_perc=0, htop2_perc=0 ; /*---- for the clueless who wish to become clued-in ----*/ if( argc < 2 || strcmp(argv[1],"-help") == 0 ){ printf( "Usage: 3dLocalBistat [options] dataset1 dataset2\n" "\n" "This program computes statistics between 2 datasets,\n" "at each voxel, based on a local neighborhood of that voxel.\n" " - The neighborhood is defined by the '-nbhd' option.\n" " - Statistics to be calculated are defined by the '-stat' option(s).\n" " - The 2 input datasets should have the same number of sub-bricks.\n" " - OR dataset1 should have 1 sub-brick and dataset2 can have more than 1:\n" " - In which case, the statistics of dataset2 against dataset1 are\n" " calculated for the #0 sub-brick of dataset1 against each sub-brick\n" " of dataset2.\n" "\n" "OPTIONS\n" "-------\n" " -nbhd 'nnn' = The string 'nnn' defines the region around each\n" " voxel that will be extracted for the statistics\n" " calculation. The format of the 'nnn' string are:\n" " * 'SPHERE(r)' where 'r' is the radius in mm;\n" " the neighborhood is all voxels whose center-to-\n" " center distance is less than or equal to 'r'.\n" " ** A negative value for 'r' means that the region\n" " is calculated using voxel indexes rather than\n" " voxel dimensions; that is, the neighborhood\n" " region is a \"sphere\" in voxel indexes of\n" " \"radius\" abs(r).\n" " * 'RECT(a,b,c)' is a rectangular block which\n" " proceeds plus-or-minus 'a' mm in the x-direction,\n" " 'b' mm in the y-direction, and 'c' mm in the\n" " z-direction. The correspondence between the\n" " dataset xyz axes and the actual spatial orientation\n" " can be determined by using program 3dinfo.\n" " ** A negative value for 'a' means that the region\n" " extends plus-and-minus abs(a) voxels in the\n" " x-direction, rather than plus-and-minus a mm.\n" " Mutatis mutandum for negative 'b' and/or 'c'.\n" " * 'RHDD(r)' is a rhombic dodecahedron of 'radius' r.\n" " * 'TOHD(r)' is a truncated octahedron of 'radius' r.\n" "\n" " -stat sss = Compute the statistic named 'sss' on the values\n" " extracted from the region around each voxel:\n" " * pearson = Pearson correlation coefficient\n" " * spearman = Spearman correlation coefficient\n" " * quadrant = Quadrant correlation coefficient\n" " * mutinfo = Mutual Information\n" " * normuti = Normalized Mutual Information\n" " * jointent = Joint entropy\n" " * hellinger= Hellinger metric\n" " * crU = Correlation ratio (Unsymmetric)\n" " * crM = Correlation ratio (symmetrized by Multiplication)\n" " * crA = Correlation ratio (symmetrized by Addition)\n" " * L2slope = slope of least-squares (L2) linear regression of\n" " the data from dataset1 vs. the dataset2\n" " (i.e., d2 = a + b*d1 ==> this is 'b')\n" " * L1slope = slope of least-absolute-sum (L1) linear regression\n" " of the data from dataset1 vs. the dataset2\n" " * num = number of the values in the region:\n" " with the use of -mask or -automask,\n" " the size of the region around any given\n" " voxel will vary; this option lets you\n" " map that size.\n" #if 0 " * ncd = Normalized Compression Distance (zlib; very slow)\n" #endif #if 0 /* activate after testing */ " * euclidian = Euclidian distance.\n" " * cityblock = City Block distance.\n" #endif " * ALL = all of the above, in that order\n" " More than one '-stat' option can be used.\n" "\n" " -mask mset = Read in dataset 'mset' and use the nonzero voxels\n" " therein as a mask. Voxels NOT in the mask will\n" " not be used in the neighborhood of any voxel. Also,\n" " a voxel NOT in the mask will have its statistic(s)\n" " computed as zero (0).\n" " -automask = Compute the mask as in program 3dAutomask.\n" " -mask and -automask are mutually exclusive: that is,\n" " you can only specify one mask.\n" " -weight ws = Use dataset 'ws' as a weight. Only applies to 'pearson'.\n" "\n" " -prefix ppp = Use string 'ppp' as the prefix for the output dataset.\n" " The output dataset is always stored as floats.\n" "\n" "ADVANCED OPTIONS\n" "----------------\n" " -histpow pp = By default, the number of bins in the histogram used\n" " for calculating the Hellinger, Mutual Information,\n" " and Correlation Ratio statistics is n^(1/3), where n\n" " is the number of data points in the -nbhd mask. You\n" " can change that exponent to 'pp' with this option.\n" " -histbin nn = Or you can just set the number of bins directly to 'nn'.\n" " -hclip1 a b = Clip dataset1 to lie between values 'a' and 'b'. If 'a'\n" " and 'b' end in '%%', then these values are percentage\n" " points on the cumulative histogram.\n" " -hclip2 a b = Similar to '-hclip1' for dataset2.\n" "\n" "-----------------------------\n" "Author: RWCox - October 2006.\n" ) ; PRINT_COMPILE_DATE ; exit(0) ; } /*---- official startup ---*/ PRINT_VERSION("3dLocalBistat"); mainENTRY("3dLocalBistat main"); machdep(); AFNI_logger("3dLocalBistat",argc,argv) ; /*---- loop over options ----*/ while( iarg < argc && argv[iarg][0] == '-' ){ if( strcmp(argv[iarg],"-hclip1") == 0 ){ char *cpt1, *cpt2 ; if( ++iarg >= argc-1 ) ERROR_exit("need 2 arguments after -hclip1") ; hbot1 = (float)strtod(argv[iarg],&cpt1) ; iarg++ ; htop1 = (float)strtod(argv[iarg],&cpt2) ; if( hbot1 >= htop1 ) ERROR_exit("illegal values after -hclip1") ; if( *cpt1 == '%' ){ hbot1_perc = 1 ; hbot1 = (int)rint((double)hbot1) ; if( hbot1 < 0 || hbot1 > 99 ) ERROR_exit("illegal bot percentage after -hclip1") ; } if( *cpt2 == '%' ){ htop1_perc = 1 ; htop1 = (int)rint((double)htop1) ; if( htop1 < 1 || htop1 > 100 ) ERROR_exit("illegal top percentage after -hclip1") ; } iarg++ ; continue ; } if( strcmp(argv[iarg],"-hclip2") == 0 ){ char *cpt1, *cpt2 ; if( ++iarg >= argc-1 ) ERROR_exit("need 2 arguments after -hclip2") ; hbot2 = (float)strtod(argv[iarg],&cpt1) ; iarg++ ; htop2 = (float)strtod(argv[iarg],&cpt2) ; if( hbot2 >= htop2 ) ERROR_exit("illegal values after -hclip2") ; if( *cpt1 == '%' ){ hbot2_perc = 1 ; hbot2 = (int)rint((double)hbot2) ; if( hbot2 < 0 || hbot2 > 99 ) ERROR_exit("illegal bot percentage after -hclip2") ; } if( *cpt2 == '%' ){ htop2_perc = 1 ; htop2 = (int)rint((double)htop2) ; if( htop2 < 1 || htop2 > 100 ) ERROR_exit("illegal top percentage after -hclip2") ; } iarg++ ; continue ; } if( strcmp(argv[iarg],"-histpow") == 0 ){ if( ++iarg >= argc ) ERROR_exit("no argument after '%s'!",argv[iarg-1]) ; hist_pow = strtod(argv[iarg],NULL) ; if( hist_pow <= 0.0 || hist_pow > 0.5 ){ WARNING_message("Illegal value after -histpow"); hist_pow = 0.33333; } iarg++ ; continue ; } if( strcmp(argv[iarg],"-histbin") == 0 ){ if( ++iarg >= argc ) ERROR_exit("no argument after '%s'!",argv[iarg-1]) ; hist_nbin = (int)strtod(argv[iarg],NULL) ; if( hist_nbin <= 1 ) WARNING_message("Illegal value after -histbin"); iarg++ ; continue ; } if( strcmp(argv[iarg],"-prefix") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '-prefix'") ; prefix = strdup(argv[iarg]) ; if( !THD_filename_ok(prefix) ) ERROR_exit("Bad name after '-prefix'") ; 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],"-weight") == 0 ){ /* 14 Aug 2007 */ if( ++iarg >= argc ) ERROR_exit("Need argument after '-weight'") ; if( wset != NULL ) ERROR_exit("Can't have two weight inputs") ; wset = THD_open_dataset( argv[iarg] ) ; CHECK_OPEN_ERROR(wset,argv[iarg]) ; DSET_load(wset) ; CHECK_LOAD_ERROR(wset) ; 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],"-stat") == 0 ){ char *cpt ; if( ++iarg >= argc ) ERROR_exit("Need argument after '-stat'") ; cpt = argv[iarg] ; if( *cpt == '-' ) cpt++ ; if( strcasecmp(cpt,"pearson") == 0 ) code[ncode++] = NBISTAT_PEARSON_CORR ; else if( strcasecmp(cpt,"spearman") == 0 ) code[ncode++] = NBISTAT_SPEARMAN_CORR; else if( strcasecmp(cpt,"quadrant") == 0 ) code[ncode++] = NBISTAT_QUADRANT_CORR; else if( strcasecmp(cpt,"mutinfo") == 0 ) code[ncode++] = NBISTAT_MUTUAL_INFO ; else if( strcasecmp(cpt,"normuti") == 0 ) code[ncode++] = NBISTAT_NORMUT_INFO ; else if( strcasecmp(cpt,"jointent") == 0 ) code[ncode++] = NBISTAT_JOINT_ENTROPY; else if( strcasecmp(cpt,"hellinger")== 0 ) code[ncode++] = NBISTAT_HELLINGER ; else if( strcasecmp(cpt,"crU") == 0 ) code[ncode++] = NBISTAT_CORR_RATIO_U ; else if( strcasecmp(cpt,"crM") == 0 ) code[ncode++] = NBISTAT_CORR_RATIO_M ; else if( strcasecmp(cpt,"crA") == 0 ) code[ncode++] = NBISTAT_CORR_RATIO_A ; else if( strcasecmp(cpt,"L2slope") == 0 ) code[ncode++] = NBISTAT_L2SLOPE ; else if( strcasecmp(cpt,"L1slope") == 0 ) code[ncode++] = NBISTAT_L1SLOPE ; else if( strcasecmp(cpt,"num") == 0 ) code[ncode++] = NBISTAT_NUM ; #if 0 else if( strcasecmp(cpt,"ncd") == 0 ) code[ncode++] = NBISTAT_NCD ; #endif #if 0 /* activate after testing */ else if( strcasecmp(cpt,"euclidian") == 0 ) code[ncode++] = NBISTAT_EUCLIDIAN_DIST ; else if( strcasecmp(cpt,"cityblock") == 0 ) code[ncode++] = NBISTAT_CITYBLOCK_DIST ; #endif else if( strcasecmp(cpt,"ALL") == 0 ){ code[ncode++] = NBISTAT_PEARSON_CORR ; code[ncode++] = NBISTAT_SPEARMAN_CORR; code[ncode++] = NBISTAT_QUADRANT_CORR; code[ncode++] = NBISTAT_MUTUAL_INFO ; code[ncode++] = NBISTAT_NORMUT_INFO ; code[ncode++] = NBISTAT_JOINT_ENTROPY; code[ncode++] = NBISTAT_HELLINGER ; code[ncode++] = NBISTAT_CORR_RATIO_U ; code[ncode++] = NBISTAT_CORR_RATIO_M ; code[ncode++] = NBISTAT_CORR_RATIO_A ; code[ncode++] = NBISTAT_L2SLOPE ; code[ncode++] = NBISTAT_L1SLOPE ; code[ncode++] = NBISTAT_NUM ; #if 0 code[ncode++] = NBISTAT_NCD ; #endif #if 0 /* activate after testing */ code[ncode++] = NBISTAT_EUCLIDIAN_DIST; code[ncode++] = NBISTAT_CITYBLOCK_DIST; #endif } else ERROR_exit("-stat '%s' is an unknown statistic type",argv[iarg]) ; 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,"RHDD",4) == 0 ){ sscanf( cpt+5 , "%f" , &na ) ; if( na == 0.0f ) ERROR_exit("Can't have a RHDD of radius 0") ; ntype = NTYPE_RHDD ; } else if( strncasecmp(cpt,"TOHD",4) == 0 ){ sscanf( cpt+5 , "%f" , &na ) ; if( na == 0.0f ) ERROR_exit("Can't have a TOHD of radius 0") ; ntype = NTYPE_TOHD ; } else 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 { ERROR_exit("Unknown -nbhd shape: '%s'",cpt) ; } iarg++ ; continue ; } ERROR_exit("Unknown option '%s'",argv[iarg]) ; } /*--- end of loop over options ---*/ /*---- check for stupid user inputs ----*/ if( ncode <= 0 ) ERROR_exit("No '-stat' options given?") ; if( ntype <= 0 ) ERROR_exit("No '-nbhd' option given?!") ; /*---- deal with input datasets ----*/ if( iarg > argc-1 ) ERROR_exit("No first input dataset on command line?") ; inset = THD_open_dataset( argv[iarg] ) ; CHECK_OPEN_ERROR(inset,argv[iarg]) ; iarg++ ; if( iarg > argc-1 ) ERROR_exit("No second input dataset on command line?") ; jnset = THD_open_dataset( argv[iarg] ) ; CHECK_OPEN_ERROR(jnset,argv[iarg]) ; if( jnset == NULL ) ERROR_exit("Can't open dataset '%s'",argv[iarg]) ; if( DSET_NVOX(jnset) != DSET_NVOX(inset) ) ERROR_exit("Input datasets have different numbers of voxels!?"); if( DSET_NVALS(jnset) != DSET_NVALS(inset) ){ if( DSET_NVALS(inset) > 1 ){ ERROR_exit("Input datasets have different numbers of sub-bricks!?"); } else { INFO_message("first input dataset has 1 sub-brick, second has %d",DSET_NVALS(jnset)) ; } } DSET_load(inset) ; CHECK_LOAD_ERROR(inset) ; DSET_load(jnset) ; CHECK_LOAD_ERROR(jnset) ; 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 , nvox ; byte *jask ; mask = THD_automask( inset ) ; if( mask == NULL ) ERROR_message("Can't create -automask from input dataset #1?") ; jask = THD_automask( jnset ) ; if( jask == NULL ) ERROR_message("Can't create -automask from input dataset #2?") ; nvox = DSET_NVOX(inset) ; for( ii=0 ; ii < nvox ; ii++ ) mask[ii] = (mask[ii] || jask[ii]) ; free(jask) ; mmm = THD_countmask( nvox , mask ) ; INFO_message("Number of voxels in dual automask = %d",mmm) ; if( mmm < 11 ) ERROR_exit("Automask is too small to process") ; } if( wset != NULL ){ /* 14 Aug 2007 */ MRI_IMAGE *wim ; float *war ; if( DSET_NVOX(wset) != DSET_NVOX(inset) ) ERROR_exit("-weight dataset mismatch with input datasets!") ; wim = mri_scale_to_float( DSET_BRICK_FACTOR(wset,0), DSET_BRICK(wset,0) ); war = MRI_FLOAT_PTR(wim) ; DSET_delete(wset) ; if( mask != NULL ){ int nvox = DSET_NVOX(inset) ; for( ii=0 ; ii < nvox ; ii++ ) if( !mask[ii] ) war[ii] = 0.0f ; } mri_bistat_setweight( wim ) ; mri_free(wim) ; } /*---- create neighborhood -----*/ switch( ntype ){ default: ERROR_exit("WTF? ntype=%d",ntype) ; case NTYPE_SPHERE:{ float dx , dy , dz ; 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_RHDD:{ float dx , dy , dz ; 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 ; case NTYPE_TOHD:{ float dx , dy , dz ; 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_tohdmask( dx,dy,dz , na ) ; } break ; case NTYPE_RECT:{ float dx , dy , dz ; if( na < 0.0f ){ dx = 1.0f; na = -na; } else dx = fabsf(DSET_DX(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 ; } INFO_message("Neighborhood comprises %d voxels",nbhd->num_pt) ; if( hist_nbin <= 1 ) hist_nbin = (int)pow((double)nbhd->num_pt,hist_pow) ; if( hist_nbin <= 1 ) hist_nbin = 2 ; INFO_message("2D histogram size = %d",hist_nbin) ; set_2Dhist_hbin( hist_nbin ) ; if( hbot1_perc || htop1_perc ){ MRI_IMAGE *fim ; float perc[101] ; fim = THD_median_brick(inset) ; mri_percents(fim,100,perc) ; mri_free(fim) ; if( hbot1_perc ) hbot1 = perc[(int)hbot1] ; if( htop1_perc ) htop1 = perc[(int)htop1] ; INFO_message("Clipping dataset '%s' between %g and %g" , DSET_BRIKNAME(inset),hbot1,htop1 ) ; } if( hbot2_perc || htop2_perc ){ MRI_IMAGE *fim ; float perc[101] ; fim = THD_median_brick(jnset) ; mri_percents(fim,100,perc) ; mri_free(fim) ; if( hbot2_perc ) hbot2 = perc[(int)hbot2] ; if( htop2_perc ) htop2 = perc[(int)htop2] ; INFO_message("Clipping dataset '%s' between %g and %g" , DSET_BRIKNAME(jnset),hbot2,htop2 ) ; } mri_nbistat_setclip( hbot1,htop1 , hbot2,htop2 ) ; /*---- actually do some work for a change ----*/ THD_localbistat_verb(1) ; outset = THD_localbistat( inset,jnset , mask , nbhd , ncode , code ) ; DSET_unload(inset) ; DSET_unload(jnset) ; if( outset == NULL ) ERROR_exit("Function THD_localbistat() fails?!") ; EDIT_dset_items( outset , ADN_prefix,prefix , ADN_none ) ; tross_Copy_History( inset , outset ) ; tross_Make_History( "3dLocalBistat" , argc,argv , outset ) ; #if 1 { char *lcode[66] , lll[66] ; lcode[0] = "Rank cor" ; lcode[1] = "Quad cor" ; lcode[2] = "Pear cor" ; lcode[3] = "MI" ; lcode[4] = "NMI" ; lcode[5] = "Jnt Entropy" ; lcode[6] = "Hlngr metric" ; lcode[7] = "CorRat Sym*" ; lcode[8] = "CorRat Sym+" ; lcode[9] = "CorRatUnsym" ; lcode[10]= "Number" ; lcode[11]= "NCD" ; lcode[12]= "Euclidian Dist"; lcode[13]= "CityBlock Dist"; if( DSET_NVALS(inset) == 1 ){ for( ii=0 ; ii < DSET_NVALS(outset) ; ii++ ) EDIT_dset_items( outset , ADN_brick_label_one+ii, lcode[code[ii%ncode]-NBISTAT_BASE], ADN_none ) ; } else { for( ii=0 ; ii < DSET_NVALS(outset) ; ii++ ){ sprintf(lll,"%s[%d]",lcode[code[ii%ncode]-NBISTAT_BASE],(ii/ncode)) ; EDIT_dset_items( outset , ADN_brick_label_one+ii,lll, ADN_none ) ; } } } #endif DSET_write( outset ) ; WROTE_DSET( outset ) ; exit(0) ; }
int main( int argc , char *argv[] ) { int iarg=1 , ii,nvox , nvals ; THD_3dim_dataset *inset=NULL, *outset=NULL , *mset=NULL ; char *prefix="./blurinmask" ; float fwhm_goal=0.0f ; int fwhm_2D=0 ; byte *mask=NULL ; int mask_nx=0,mask_ny=0,mask_nz=0 , automask=0 , nmask=0 ; float dx,dy,dz=0.0f , *bar , val ; int floatize=0 ; /* 18 May 2009 */ MRI_IMAGE *immask=NULL ; /* 07 Oct 2009 */ short *mmask=NULL ; short *unval_mmask=NULL ; int nuniq_mmask=0 ; int do_preserve=0 , use_qsar ; /* 19 Oct 2009 */ THD_3dim_dataset *fwhmset=NULL ; MRI_IMAGE *fxim=NULL, *fyim=NULL, *fzim=NULL ; /* 13 Jun 2016 */ int niter_fxyz=0 ; float dmax=0.0f , dmin=0.0f ; /*------- help the pitifully ignorant luser? -------*/ AFNI_SETUP_OMP(0) ; /* 24 Jun 2013 */ if( argc < 2 || strcmp(argv[1],"-help") == 0 ){ printf( "Usage: ~1~\n" "3dBlurInMask [options]\n" "Blurs a dataset spatially inside a mask. That's all. Experimental.\n" "\n" "OPTIONS ~1~\n" "-------\n" " -input ddd = This required 'option' specifies the dataset\n" " that will be smoothed and output.\n" " -FWHM f = Add 'f' amount of smoothness to the dataset (in mm).\n" " **N.B.: This is also a required 'option'.\n" " -FWHMdset d = Read in dataset 'd' and add the amount of smoothness\n" " given at each voxel -- spatially variable blurring.\n" " ** EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL **\n" " -mask mmm = Mask dataset, if desired. Blurring will\n" " occur only within the mask. Voxels NOT in\n" " the mask will be set to zero in the output.\n" " -Mmask mmm = Multi-mask dataset -- each distinct nonzero\n" " value in dataset 'mmm' will be treated as\n" " a separate mask for blurring purposes.\n" " **N.B.: 'mmm' must be byte- or short-valued!\n" " -automask = Create an automask from the input dataset.\n" " **N.B.: only 1 masking option can be used!\n" " -preserve = Normally, voxels not in the mask will be\n" " set to zero in the output. If you want the\n" " original values in the dataset to be preserved\n" " in the output, use this option.\n" " -prefix ppp = Prefix for output dataset will be 'ppp'.\n" " **N.B.: Output dataset is always in float format.\n" " -quiet = Don't be verbose with the progress reports.\n" " -float = Save dataset as floats, no matter what the\n" " input data type is.\n" " **N.B.: If the input dataset is unscaled shorts, then\n" " the default is to save the output in short\n" " format as well. In EVERY other case, the\n" " program saves the output as floats. Thus,\n" " the ONLY purpose of the '-float' option is to\n" " force an all-shorts input dataset to be saved\n" " as all-floats after blurring.\n" "\n" "NOTES ~1~\n" "-----\n" " * If you don't provide a mask, then all voxels will be included\n" " in the blurring. (But then why are you using this program?)\n" " * Note that voxels inside the mask that are not contiguous with\n" " any other voxels inside the mask will not be modified at all!\n" " * Works iteratively, similarly to 3dBlurToFWHM, but without\n" " the extensive overhead of monitoring the smoothness.\n" " * But this program will be faster than 3dBlurToFWHM, and probably\n" " slower than 3dmerge.\n" " * Since the blurring is done iteratively, rather than all-at-once as\n" " in 3dmerge, the results will be slightly different than 3dmerge's,\n" " even if no mask is used here (3dmerge, of course, doesn't take a mask).\n" " * If the original FWHM of the dataset was 'S' and you input a value\n" " 'F' with the '-FWHM' option, then the output dataset's smoothness\n" " will be about sqrt(S*S+F*F). The number of iterations will be\n" " about (F*F/d*d) where d=grid spacing; this means that a large value\n" " of F might take a lot of CPU time!\n" " * The spatial smoothness of a 3D+time dataset can be estimated with a\n" " command similar to the following:\n" " 3dFWHMx -detrend -mask mmm+orig -input ddd+orig\n" ) ; printf( " * The minimum number of voxels in the mask is %d\n",MASK_MIN) ; printf( " * Isolated voxels will be removed from the mask!\n") ; PRINT_AFNI_OMP_USAGE("3dBlurInMask",NULL) ; PRINT_COMPILE_DATE ; exit(0) ; } /*---- official startup ---*/ PRINT_VERSION("3dBlurInMask"); mainENTRY("3dBlurInMask main"); machdep(); AFNI_logger("3dBlurInMask",argc,argv); AUTHOR("RW Cox") ; /*---- loop over options ----*/ while( iarg < argc && argv[iarg][0] == '-' ){ if( strncmp(argv[iarg],"-preserve",5) == 0 ){ /* 19 Oct 2009 */ do_preserve = 1 ; iarg++ ; continue ; } if( strncmp(argv[iarg],"-qui",4) == 0 ){ verb = 0 ; iarg++ ; continue ; } if( strncmp(argv[iarg],"-ver",4) == 0 ){ verb++ ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-input") == 0 || strcmp(argv[iarg],"-dset") == 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]) ; if( !THD_filename_ok(prefix) ) ERROR_exit("Bad name after '-prefix'") ; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-Mmask") == 0 ){ /* 07 Oct 2009 */ if( ++iarg >= argc ) ERROR_exit("Need argument after '-Mmask'") ; if( mmask != NULL || 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); #if 0 if( !MRI_IS_INT_TYPE(DSET_BRICK_TYPE(mset,0)) ) ERROR_exit("-Mmask dataset is not integer type!") ; #endif immask = mri_to_short( 1.0 , DSET_BRICK(mset,0) ) ; mmask = MRI_SHORT_PTR(immask) ; unval_mmask = UniqueShort( mmask, mask_nx*mask_ny*mask_nz, &nuniq_mmask, 0 ) ; if( unval_mmask == NULL || nuniq_mmask == 0 ) ERROR_exit("-Mmask dataset cannot be processed!?") ; if( nuniq_mmask == 1 && unval_mmask[0] == 0 ) ERROR_exit("-Mmask dataset is all zeros!?") ; if( verb ){ int qq , ww ; for( ii=qq=0 ; ii < nuniq_mmask ; ii++ ) if( unval_mmask[ii] != 0 ) qq++ ; for( ii=ww=0 ; ii < immask->nvox ; ii++ ) if( mmask[ii] != 0 ) ww++ ; INFO_message("%d unique nonzero values in -Mmask; %d nonzero voxels",qq,ww) ; } iarg++ ; continue ; } if( strcmp(argv[iarg],"-mask") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '-mask'") ; if( mmask != NULL || 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_unload(mset) ; if( mask == NULL ) ERROR_exit("Can't make mask from dataset '%s'",argv[iarg]) ; ii = THD_mask_remove_isolas( mask_nx,mask_ny,mask_nz , mask ) ; if( verb && ii > 0 ) INFO_message("Removed %d isola%s from mask dataset",ii,(ii==1)?"\0":"s") ; nmask = THD_countmask( mask_nx*mask_ny*mask_nz , mask ) ; if( verb ) INFO_message("Number of voxels in mask = %d",nmask) ; if( nmask < MASK_MIN ) ERROR_exit("Mask is too small to process") ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-automask") == 0 ){ if( mmask != NULL || mask != NULL ) ERROR_exit("Can't have 2 mask inputs") ; automask = 1 ; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-FWHM") == 0 || strcasecmp(argv[iarg],"-FHWM") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '%s'",argv[iarg-1]); val = (float)strtod(argv[iarg],NULL) ; if( val <= 0.0f ) ERROR_exit("Illegal value after '%s': '%s'", argv[iarg-1],argv[iarg]) ; fwhm_goal = val ; fwhm_2D = 0 ; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-FWHMdset") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '%s'",argv[iarg-1]); if( fwhmset != NULL ) ERROR_exit("You can't use option '-FWHMdset' twice :(") ; fwhmset = THD_open_dataset( argv[iarg] ) ; CHECK_OPEN_ERROR(fwhmset,argv[iarg]) ; do_preserve = 1 ; iarg++ ; continue ; } if( strncmp(argv[iarg],"-float",6) == 0 ){ /* 18 May 2009 */ floatize = 1 ; iarg++ ; continue ; } #if 0 if( strcmp(argv[iarg],"-FWHMxy") == 0 || strcmp(argv[iarg],"-FHWMxy") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '%s'",argv[iarg-1]); val = (float)strtod(argv[iarg],NULL) ; if( val <= 0.0f ) ERROR_exit("Illegal value after '%s': '%s'", argv[iarg-1],argv[iarg]) ; fwhm_goal = val ; fwhm_2D = 1 ; iarg++ ; continue ; } #endif ERROR_exit("Uknown option '%s'",argv[iarg]) ; } /*--- end of loop over options ---*/ /*----- check for stupid inputs, load datasets, et cetera -----*/ if( fwhmset == NULL && fwhm_goal == 0.0f ) ERROR_exit("No -FWHM option given! What do you want?") ; if( fwhmset != NULL && fwhm_goal > 0.0f ){ WARNING_message("-FWHMdset option replaces -FWHM value") ; fwhm_goal = 0.0f ; } if( fwhmset != NULL && mmask != NULL ) ERROR_exit("Sorry: -FWHMdset and -Mmask don't work together (yet)") ; 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]) ; } nvox = DSET_NVOX(inset) ; dx = fabs(DSET_DX(inset)) ; if( dx == 0.0f ) dx = 1.0f ; dy = fabs(DSET_DY(inset)) ; if( dy == 0.0f ) dy = 1.0f ; dz = fabs(DSET_DZ(inset)) ; if( dz == 0.0f ) dz = 1.0f ; dmax = MAX(dx,dy) ; if( dmax < dz ) dmax = dz ; /* 13 Jun 2016 */ dmin = MIN(dx,dy) ; if( dmin > dz ) dmin = dz ; if( !floatize ){ /* 18 May 2009 */ if( !THD_datum_constant(inset->dblk) || THD_need_brick_factor(inset) || DSET_BRICK_TYPE(inset,0) != MRI_short ){ if( verb ) INFO_message("forcing output to be stored in float format") ; floatize = 1 ; } else { if( verb ) INFO_message("output dataset will be stored as shorts") ; } } else { if( verb ) INFO_message("output dataset will be stored as floats") ; } #if 0 if( DSET_NZ(inset) == 1 && !fwhm_2D ){ WARNING_message("Dataset is 2D ==> switching from -FWHM to -FWHMxy") ; fwhm_2D = 1 ; } #endif /*--- deal with mask or automask ---*/ 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 ){ mask = THD_automask( inset ) ; if( mask == NULL ) ERROR_message("Can't create -automask from input dataset?") ; nmask = THD_countmask( DSET_NVOX(inset) , mask ) ; if( verb ) INFO_message("Number of voxels in automask = %d",nmask); if( nmask < MASK_MIN ) ERROR_exit("Automask is too small to process") ; } else if( mmask != NULL ){ if( mask_nx != DSET_NX(inset) || mask_ny != DSET_NY(inset) || mask_nz != DSET_NZ(inset) ) ERROR_exit("-Mmask dataset grid doesn't match input dataset") ; } else { mask = (byte *)malloc(sizeof(byte)*nvox) ; nmask = nvox ; memset(mask,1,sizeof(byte)*nvox) ; if( verb ) INFO_message("No mask ==> processing all %d voxels",nvox); } /*--- process FWHMdset [13 Jun 2016] ---*/ if( fwhmset != NULL ){ float *fxar,*fyar,*fzar , *fwar ; MRI_IMAGE *fwim ; float fwmax=0.0f , fsx,fsy,fsz ; int ii, nfpos=0 ; if( DSET_NX(inset) != DSET_NX(fwhmset) || DSET_NY(inset) != DSET_NY(fwhmset) || DSET_NZ(inset) != DSET_NZ(fwhmset) ) ERROR_exit("grid dimensions for FWHMdset and input dataset do not match :(") ; STATUS("get fwim") ; DSET_load(fwhmset) ; fwim = mri_scale_to_float(DSET_BRICK_FACTOR(fwhmset,0),DSET_BRICK(fwhmset,0)); fwar = MRI_FLOAT_PTR(fwim); DSET_unload(fwhmset) ; STATUS("process fwar") ; for( ii=0 ; ii < nvox ; ii++ ){ if( mask[ii] && fwar[ii] > 0.0f ){ nfpos++ ; if( fwar[ii] > fwmax ) fwmax = fwar[ii] ; } else { fwar[ii] = 0.0f ; mask[ii] = 0 ; } } if( nfpos < 100 ) ERROR_exit("Cannot proceed: too few (%d) voxels are positive in -FWHMdset!",nfpos) ; niter_fxyz = (int)rintf(2.0f*fwmax*fwmax*FFAC/(0.05f*dmin*dmin)) + 1 ; if( verb ) INFO_message("-FWHMdset: niter=%d npos=%d",niter_fxyz,nfpos) ; STATUS("create fxim etc.") ; fxim = mri_new_conforming(fwim,MRI_float); fxar = MRI_FLOAT_PTR(fxim); fyim = mri_new_conforming(fwim,MRI_float); fyar = MRI_FLOAT_PTR(fyim); fzim = mri_new_conforming(fwim,MRI_float); fzar = MRI_FLOAT_PTR(fzim); fsx = FFAC/(dx*dx*niter_fxyz) ; fsy = FFAC/(dy*dy*niter_fxyz) ; fsz = FFAC/(dz*dz*niter_fxyz) ; /** INFO_message("fsx=%g fsy=%g fsz=%g",fsx,fsy,fsz) ; **/ for( ii=0 ; ii < nvox ; ii++ ){ if( fwar[ii] > 0.0f ){ fxar[ii] = fwar[ii]*fwar[ii] * fsx ; fyar[ii] = fwar[ii]*fwar[ii] * fsy ; fzar[ii] = fwar[ii]*fwar[ii] * fsz ; } else { fxar[ii] = fyar[ii] = fzar[ii] = 0.0f ; } } STATUS("free(fwim)") ; mri_free(fwim) ; } /*--- process input dataset ---*/ STATUS("load input") ; DSET_load(inset) ; CHECK_LOAD_ERROR(inset) ; outset = EDIT_empty_copy( inset ) ; /* moved here 04 Jun 2007 */ EDIT_dset_items( outset , ADN_prefix , prefix , ADN_none ) ; EDIT_dset_items( outset , ADN_brick_fac , NULL , ADN_none ) ; /* 11 Sep 2007 */ tross_Copy_History( inset , outset ) ; tross_Make_History( "3dBlurInMask" , argc,argv , outset ) ; nvals = DSET_NVALS(inset) ; use_qsar = (do_preserve || mmask != NULL) ; /* 19 Oct 20090 */ AFNI_OMP_START ; #pragma omp parallel if( nvals > 1 ) { MRI_IMAGE *dsim ; int ids,qit ; byte *qmask=NULL ; register int vv ; MRI_IMAGE *qim=NULL, *qsim=NULL; float *qar=NULL, *dsar, *qsar=NULL; #pragma omp critical (MALLOC) { if( use_qsar ){ qsim = mri_new_conforming(DSET_BRICK(inset,0),MRI_float); qsar = MRI_FLOAT_PTR(qsim); } if( mmask != NULL ){ qmask = (byte *)malloc(sizeof(byte)*nvox) ; qim = mri_new_conforming(immask,MRI_float); qar = MRI_FLOAT_PTR(qim); qim->dx = dx ; qim->dy = dy ; qim->dz = dz ; } } #pragma omp for for( ids=0 ; ids < nvals ; ids++ ){ #pragma omp critical (MALLOC) { dsim = mri_scale_to_float(DSET_BRICK_FACTOR(inset,ids),DSET_BRICK(inset,ids)); DSET_unload_one(inset,ids) ; } dsim->dx = dx ; dsim->dy = dy ; dsim->dz = dz ; dsar = MRI_FLOAT_PTR(dsim) ; /* if needed, initialize qsar with data to be preserved in output */ if( do_preserve ){ for( vv=0 ; vv < nvox ; vv++ ) qsar[vv] = dsar[vv] ; } else if( mmask != NULL ){ for( vv=0 ; vv < nvox ; vv++ ) qsar[vv] = 0.0f ; } if( fwhmset != NULL ){ /* 13 Jun 2016: spatially variable blurring */ for( qit=0 ; qit < niter_fxyz ; qit++ ){ mri_blur3D_variable( dsim , mask , fxim,fyim,fzim ) ; } if( do_preserve ){ for( vv=0 ; vv < nvox ; vv++ ) if( mask[vv] ) qsar[vv] = dsar[vv] ; } } else if( mmask != NULL ){ /* 07 Oct 2009: multiple masks */ int qq ; register short uval ; for( qq=0 ; qq < nuniq_mmask ; qq++ ){ uval = unval_mmask[qq] ; if( uval == 0 ) continue ; for( vv=0 ; vv < nvox ; vv++ ) qmask[vv] = (mmask[vv]==uval) ; /* make mask */ (void)THD_mask_remove_isolas( mask_nx,mask_ny,mask_nz , qmask ) ; nmask = THD_countmask( nvox , qmask ) ; if( verb && ids==0 ) ININFO_message("voxels in Mmask[%d] = %d",uval,nmask) ; if( nmask >= MASK_MIN ){ /* copy data from dataset to qar */ for( vv=0 ; vv < nvox ; vv++ ) if( qmask[vv] ) qar[vv] = dsar[vv] ; /* blur qar (output will be zero where qmask==0) */ mri_blur3D_addfwhm( qim , qmask , fwhm_goal ) ; /** the real work **/ /* copy results back to qsar */ for( vv=0 ; vv < nvox ; vv++ ) if( qmask[vv] ) qsar[vv] = qar[vv] ; } } } else { /* the olden way: 1 mask */ mri_blur3D_addfwhm( dsim , mask , fwhm_goal ) ; /** all the work **/ /* dsim will be zero where mask==0; if we want to preserve the input values, copy dsar into qsar now at all mask!=0 voxels, since qsar contains the original data values */ if( do_preserve ){ for( vv=0 ; vv < nvox ; vv++ ) if( mask[vv] ) qsar[vv] = dsar[vv] ; } } /* if necessary, copy combined results in qsar to dsar for output */ if( use_qsar ){ for( vv=0 ; vv < nvox ; vv++ ) dsar[vv] = qsar[vv] ; } if( floatize ){ EDIT_substitute_brick( outset , ids , MRI_float , dsar ) ; } else { #pragma omp critical (MALLOC) { EDIT_substscale_brick( outset , ids , MRI_float , dsar , MRI_short , 1.0f ) ; mri_free(dsim) ; } } } /* end of loop over sub-bricks */ #pragma omp critical (MALLOC) { if( qsim != NULL ) mri_free(qsim); if( immask != NULL ){ free(qmask); mri_free(qim); } } } /* end OpenMP */ AFNI_OMP_END ; if( mask != NULL ) free( mask) ; if( immask != NULL ) mri_free(immask) ; DSET_unload(inset) ; DSET_write(outset) ; WROTE_DSET(outset) ; exit(0) ; }
int main(int argc, char *argv[]) { int i,j,k,m,n,aa,ii,jj,kk,mm,rr; int iarg; int nmask1=0; int nmask2=0; THD_3dim_dataset *insetFA = NULL, *insetV1 = NULL, *insetMD = NULL, *insetL1 = NULL; THD_3dim_dataset *insetEXTRA=NULL; THD_3dim_dataset *mset2=NULL; THD_3dim_dataset *mset1=NULL; THD_3dim_dataset *outsetMAP=NULL, *outsetMASK=NULL; char *prefix="tracky"; int LOG_TYPE=0; char in_FA[300]; char in_V1[300]; char in_MD[300]; char in_L1[300]; int EXTRAFILE=0; // switch for whether other file is input as WM map char OUT_bin[300]; char OUT_tracstat[300]; char prefix_mask[300]; char prefix_map[300]; // FACT algopts FILE *fout0; float MinFA=0.2,MaxAngDeg=45,MinL=20.0; float MaxAng; int SeedPerV[3]={2,2,2}; int ArrMax=0; float tempvmagn; int Nvox=-1; // tot number vox int Dim[3]={0,0,0}; // dim in each dir int Nseed=0,M=30,bval=1000; int DimSeed[3]; // number of seeds there will be float Ledge[3]; // voxel edge lengths int *ROI1, *ROI2; short int *temp_arr; char *temp_byte; int **Tforw, **Tback; int **Ttot; float **flTforw, **flTback; float ****coorded; int ****INDEX; int len_forw, len_back; // int count of num of squares through float phys_forw[1], phys_back[1]; int idx; float ave_tract_len, ave_tract_len_phys; int inroi1, inroi2, KEEPIT; // switches for detecting int in[3]; // to pass to trackit float physin[3]; // also for trackit, physical loc, int totlen; float totlen_phys; int Numtract; int READS_in; float READS_fl; int end[2][3]; int test_ind[2][3]; int roi3_ct=0, id=0; float roi3_mu_MD = 0.,roi3_mu_RD = 0.,roi3_mu_L1 = 0.,roi3_mu_FA = 0.; float roi3_sd_MD = 0.,roi3_sd_RD = 0.,roi3_sd_L1 = 0.,roi3_sd_FA = 0.; float tempMD,tempFA,tempRD,tempL1; char dset_or[4] = "RAI"; THD_3dim_dataset *dsetn; int TV_switch[3] = {0,0,0}; TAYLOR_BUNDLE *tb=NULL; TAYLOR_TRACT *tt=NULL; char *mode = "NI_fast_binary"; NI_element *nel=NULL; int dump_opts=0; tv_io_header header1 = {.id_string = "TRACK\0", .origin = {0,0,0}, .n_scalars = 3, .scal_n[0] = "FA", .scal_n[1] = "MD", .scal_n[2] = "L1", .n_properties = 0, .vox_to_ras = {{0.,0.,0.,0.},{0.,0.,0.,0.}, {0.,0.,0.,0.},{0.,0.,0.,0.}}, // reset this later based on actual data set .voxel_order = "RAI\0", .invert_x = 0, .invert_y = 0, .invert_z = 0, .swap_xy = 0, .swap_yz = 0, .swap_zx = 0, .n_count = 0, .version = 2, .hdr_size = 1000}; // for testing names... char *postfix[4]={"+orig.HEAD\0",".nii.gz\0",".nii\0","+tlrc.HEAD\0"}; int FOUND =-1; int RECORD_ORIG = 0; float Orig[3] = {0.0,0.0,0.0}; mainENTRY("3dTrackID"); machdep(); // **************************************************************** // **************************************************************** // load AFNI stuff // **************************************************************** // **************************************************************** INFO_message("version: MU"); /** scan args **/ if (argc == 1) { usage_TrackID(1); exit(0); } iarg = 1; while( iarg < argc && argv[iarg][0] == '-' ){ if( strcmp(argv[iarg],"-help") == 0 || strcmp(argv[iarg],"-h") == 0 ) { usage_TrackID(strlen(argv[iarg])>3 ? 2:1); exit(0); } if( strcmp(argv[iarg],"-verb") == 0) { if( ++iarg >= argc ) ERROR_exit("Need argument after '-verb'") ; set_tract_verb(atoi(argv[iarg])); iarg++ ; continue ; } if( strcmp(argv[iarg],"-write_opts") == 0) { dump_opts=1; iarg++ ; continue ; } if( strcmp(argv[iarg],"-rec_orig") == 0) { RECORD_ORIG=1; iarg++ ; continue ; } if( strcmp(argv[iarg],"-tract_out_mode") == 0) { if( ++iarg >= argc ) ERROR_exit("Need argument after '-tract_out_mode'") ; if (strcmp(argv[iarg], "NI_fast_binary") && strcmp(argv[iarg], "NI_fast_text") && strcmp(argv[iarg], "NI_slow_binary") && strcmp(argv[iarg], "NI_slow_text") ) { ERROR_message("Bad value (%s) for -tract_out_mode",argv[iarg]); exit(1); } mode = argv[iarg]; iarg++ ; continue ; } if( strcmp(argv[iarg],"-mask1") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '-mask1'") ; mset1 = THD_open_dataset( argv[iarg] ) ; if( mset1 == NULL ) ERROR_exit("Can't open mask1 dataset '%s'", argv[iarg]) ; DSET_load(mset1) ; CHECK_LOAD_ERROR(mset1) ; nmask1 = DSET_NVOX(mset1) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-mask2") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '-mask2'") ; mset2 = THD_open_dataset( argv[iarg] ) ; if( mset2 == NULL ) ERROR_exit("Can't open mask2 dataset '%s'", argv[iarg]) ; DSET_load(mset2) ; CHECK_LOAD_ERROR(mset2) ; nmask2 = DSET_NVOX(mset2) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-prefix") == 0 ){ iarg++ ; if( iarg >= argc ) ERROR_exit("Need argument after '-prefix'"); prefix = strdup(argv[iarg]) ; if( !THD_filename_ok(prefix) ) ERROR_exit("Illegal name after '-prefix'"); iarg++ ; continue ; } if( strcmp(argv[iarg],"-input") == 0 ){ iarg++ ; if( iarg >= argc ) ERROR_exit("Need argument after '-input'"); for( i=0 ; i<4 ; i++) { sprintf(in_FA,"%s_FA%s", argv[iarg],postfix[i]); if(THD_is_ondisk(in_FA)) { FOUND = i; break; } } insetFA = THD_open_dataset(in_FA) ; if( (insetFA == NULL ) || (FOUND==-1)) ERROR_exit("Can't open dataset '%s': for FA.",in_FA); DSET_load(insetFA) ; CHECK_LOAD_ERROR(insetFA) ; Nvox = DSET_NVOX(insetFA) ; Dim[0] = DSET_NX(insetFA); Dim[1] = DSET_NY(insetFA); Dim[2] = DSET_NZ(insetFA); Ledge[0] = fabs(DSET_DX(insetFA)); Ledge[1] = fabs(DSET_DY(insetFA)); Ledge[2] = fabs(DSET_DZ(insetFA)); Orig[0] = DSET_XORG(insetFA); Orig[1] = DSET_YORG(insetFA); Orig[2] = DSET_ZORG(insetFA); // check tot num vox match (as proxy for dims...) if( (Nvox != nmask1) || (Nvox != nmask2) ) ERROR_exit("Input dataset does not match both mask volumes!"); // this stores the original data file orientation for later use, // as well since we convert everything to RAI temporarily, as // described below header1.voxel_order[0]=ORIENT_typestr[insetFA->daxes->xxorient][0]; header1.voxel_order[1]=ORIENT_typestr[insetFA->daxes->yyorient][0]; header1.voxel_order[2]=ORIENT_typestr[insetFA->daxes->zzorient][0]; for( i=0 ; i<3 ; i++) { header1.dim[i] = Dim[i]; header1.voxel_size[i] = Ledge[i]; // will want this when outputting file later for TrackVis. TV_switch[i] = !(dset_or[i]==header1.voxel_order[i]); } dset_or[3]='\0'; FOUND = -1; for( i=0 ; i<4 ; i++) { sprintf(in_V1,"%s_V1%s", argv[iarg],postfix[i]); if(THD_is_ondisk(in_V1)) { FOUND = i; break; } } insetV1 = THD_open_dataset(in_V1); if( insetV1 == NULL ) ERROR_exit("Can't open dataset '%s':V1",in_V1); DSET_load(insetV1) ; CHECK_LOAD_ERROR(insetV1) ; FOUND = -1; for( i=0 ; i<4 ; i++) { sprintf(in_L1,"%s_L1%s", argv[iarg],postfix[i]); if(THD_is_ondisk(in_L1)) { FOUND = i; break; } } insetL1 = THD_open_dataset(in_L1); if( insetL1 == NULL ) ERROR_exit("Can't open dataset '%s':L1",in_L1); DSET_load(insetL1) ; CHECK_LOAD_ERROR(insetL1) ; FOUND = -1; for( i=0 ; i<4 ; i++) { sprintf(in_MD,"%s_MD%s", argv[iarg],postfix[i]); if(THD_is_ondisk(in_MD)) { FOUND = i; break; } } insetMD = THD_open_dataset(in_MD); if( insetMD == NULL ) ERROR_exit("Can't open dataset '%s':MD",in_MD); DSET_load(insetMD) ; CHECK_LOAD_ERROR(insetMD) ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-algopt") == 0 ){ iarg++ ; if( iarg >= argc ) ERROR_exit("Need argument after '-algopt'"); if (!(nel = ReadTractAlgOpts(argv[iarg]))) { ERROR_message("Failed to read options in %s\n", argv[iarg]); exit(19); } if (NI_getTractAlgOpts(nel, &MinFA, &MaxAngDeg, &MinL, SeedPerV, &M, &bval)) { ERROR_message("Failed to get options"); exit(1); } NI_free_element(nel); nel=NULL; iarg++ ; continue ; } if( strcmp(argv[iarg],"-logic") == 0 ){ iarg++ ; if( iarg >= argc ) ERROR_exit("Need argument after '-logic'"); INFO_message("ROI logic type is: %s",argv[iarg]); if( strcmp(argv[iarg],"AND") == 0 ) LOG_TYPE = 1; else if( strcmp(argv[iarg],"OR") == 0 ) LOG_TYPE = 0; else if( strcmp(argv[iarg],"ALL") == 0 ) LOG_TYPE = -1; else ERROR_exit("Illegal after '-logic': need 'OR' or 'AND'"); iarg++ ; continue ; } //@@ if( strcmp(argv[iarg],"-extra_set") == 0) { if( ++iarg >= argc ) ERROR_exit("Need argument after '-extra_set'"); EXTRAFILE = 1; // switch on insetEXTRA = THD_open_dataset(argv[iarg]); if( (insetEXTRA == NULL ) ) ERROR_exit("Can't open dataset '%s': for extra set.",argv[iarg]); DSET_load(insetEXTRA) ; CHECK_LOAD_ERROR(insetEXTRA) ; if( !((Dim[0] == DSET_NX(insetEXTRA)) && (Dim[1] == DSET_NY(insetEXTRA)) && (Dim[2] == DSET_NZ(insetEXTRA)))) ERROR_exit("Dimensions of extra set '%s' don't match those of the DTI prop ones ('%s', etc.).",argv[iarg], in_FA); iarg++ ; continue ; } ERROR_message("Bad option '%s'\n",argv[iarg]) ; suggest_best_prog_option(argv[0], argv[iarg]); exit(1); } if (iarg < 4) { ERROR_message("Too few options. Try -help for details.\n"); exit(1); } if (dump_opts) { nel = NI_setTractAlgOpts(NULL, &MinFA, &MaxAngDeg, &MinL, SeedPerV, &M, &bval); WriteTractAlgOpts(prefix, nel); NI_free_element(nel); nel=NULL; } // Process the options a little for( i=0 ; i<3 ; i++) DimSeed[i] = Dim[i]*SeedPerV[i]; Nseed = Nvox*SeedPerV[0]*SeedPerV[1]*SeedPerV[2]; // convert to cos of rad value for comparisons, instead of using acos() MaxAng = cos(CONV*MaxAngDeg); // switch to add header-- option for now, added Sept. 2012 // for use with map_TrackID to map tracks to different space if(RECORD_ORIG) { for( i=0 ; i<3 ; i++) header1.origin[i] = Orig[i]; } // at some point, we will have to convert indices into // pseudo-locations; being forced into this choice means that // different data set orientations would be represented differently // and incorrectly in some instances... so, for now, we'll resample // everything to RAI, and then resample back later. guess this will // just slow things down slightly. // have all be RAI for processing here if(TV_switch[0] || TV_switch[1] || TV_switch[2]) { dsetn = r_new_resam_dset(insetFA, NULL, 0.0, 0.0, 0.0, dset_or, RESAM_NN_TYPE, NULL, 1, 0); DSET_delete(insetFA); insetFA=dsetn; dsetn=NULL; dsetn = r_new_resam_dset(insetMD, NULL, 0.0, 0.0, 0.0, dset_or, RESAM_NN_TYPE, NULL, 1, 0); DSET_delete(insetMD); insetMD=dsetn; dsetn=NULL; dsetn = r_new_resam_dset(insetV1, NULL, 0.0, 0.0, 0.0, dset_or, RESAM_NN_TYPE, NULL, 1, 0); DSET_delete(insetV1); insetV1=dsetn; dsetn=NULL; dsetn = r_new_resam_dset(insetL1, NULL, 0.0, 0.0, 0.0, dset_or, RESAM_NN_TYPE, NULL, 1, 0); DSET_delete(insetL1); insetL1=dsetn; dsetn=NULL; dsetn = r_new_resam_dset(mset1, NULL, 0.0, 0.0, 0.0, dset_or, RESAM_NN_TYPE, NULL, 1, 0); DSET_delete(mset1); mset1=dsetn; dsetn=NULL; dsetn = r_new_resam_dset(mset2, NULL, 0.0, 0.0, 0.0, dset_or, RESAM_NN_TYPE, NULL, 1, 0); DSET_delete(mset2); mset2=dsetn; dsetn=NULL; if(EXTRAFILE) { dsetn = r_new_resam_dset(insetEXTRA, NULL, 0.0, 0.0, 0.0, dset_or, RESAM_NN_TYPE, NULL, 1, 0); DSET_delete(insetEXTRA); insetEXTRA=dsetn; dsetn=NULL; } } // **************************************************************** // **************************************************************** // make arrays for tracking // **************************************************************** // **************************************************************** // for temp storage array, just a multiple of longest dimension! if(Dim[0] > Dim[1]) ArrMax = Dim[0] * 4; else ArrMax = Dim[1] * 4; if(4*Dim[2] > ArrMax) ArrMax = Dim[2] * 4; ROI1 = (int *)calloc(Nvox, sizeof(int)); ROI2 = (int *)calloc(Nvox, sizeof(int)); temp_arr = (short int *)calloc(Nvox, sizeof(short int)); temp_byte = (char *)calloc(Nvox, sizeof(char)); // temp storage whilst tracking Tforw = calloc(ArrMax, sizeof(Tforw)); for(i=0 ; i<ArrMax ; i++) Tforw[i] = calloc(3, sizeof(int)); Ttot = calloc(2*ArrMax , sizeof(Ttot)); for(i=0 ; i<2*ArrMax ; i++) Ttot[i] = calloc(3, sizeof(int)); Tback = calloc(ArrMax, sizeof(Tback)); for(i=0 ; i<ArrMax ; i++) Tback[i] = calloc(3, sizeof(int)); // temp storage whilst tracking, physical loc flTforw = calloc(ArrMax, sizeof(flTforw)); for(i=0 ; i<ArrMax ; i++) flTforw[i] = calloc(3, sizeof(int)); flTback = calloc(ArrMax,sizeof(flTback)); for(i=0 ; i<ArrMax ; i++) flTback[i] = calloc(3, sizeof(int)); if( (ROI1 == NULL) || (ROI2 == NULL) || (temp_arr == NULL) || (Tforw == NULL) || (Tback == NULL) || (flTforw == NULL) || (flTback == NULL) || (Ttot == NULL)) { fprintf(stderr, "\n\n MemAlloc failure.\n\n"); exit(12); } coorded = (float ****) calloc( Dim[0], sizeof(float ***) ); for ( i = 0 ; i < Dim[0] ; i++ ) coorded[i] = (float ***) calloc( Dim[1], sizeof(float **) ); for ( i = 0 ; i < Dim[0] ; i++ ) for ( j = 0 ; j < Dim[1] ; j++ ) coorded[i][j] = (float **) calloc( Dim[2], sizeof(float *) ); for ( i=0 ; i<Dim[0] ; i++ ) for ( j=0 ; j<Dim[1] ; j++ ) for ( k= 0 ; k<Dim[2] ; k++ ) //3 comp of V1 and FA coorded[i][j][k] = (float *) calloc( 4, sizeof(float) ); INDEX = (int ****) calloc( Dim[0], sizeof(int ***) ); for ( i = 0 ; i < Dim[0] ; i++ ) INDEX[i] = (int ***) calloc( Dim[1], sizeof(int **) ); for ( i = 0 ; i < Dim[0] ; i++ ) for ( j = 0 ; j < Dim[1] ; j++ ) INDEX[i][j] = (int **) calloc( Dim[2], sizeof(int *) ); for ( i=0 ; i<Dim[0] ; i++ ) for ( j=0 ; j<Dim[1] ; j++ ) for ( k= 0 ; k<Dim[2] ; k++ ) INDEX[i][j][k] = (int *) calloc( 4, sizeof(int) ); // this statement will never be executed if allocation fails above if( (INDEX == NULL) || (coorded == NULL) ) { fprintf(stderr, "\n\n MemAlloc failure.\n\n"); exit(122); } for(i=0 ; i<Nvox ; i++) { if(THD_get_voxel( mset1, i, 0) >0.5){ ROI1[i] = 1; } if(THD_get_voxel( mset2, i, 0) >0.5) ROI2[i] = 1; } // set up eigvecs in 3D coord sys, // mark off where ROIs are and keep index handy idx=0; for( k=0 ; k<Dim[2] ; k++ ) for( j=0 ; j<Dim[1] ; j++ ) for( i=0 ; i<Dim[0] ; i++ ) { for( m=0 ; m<3 ; m++ ) coorded[i][j][k][m] = THD_get_voxel(insetV1, idx, m); if(EXTRAFILE) coorded[i][j][k][3] = THD_get_voxel(insetEXTRA, idx, 0); else coorded[i][j][k][3] = THD_get_voxel(insetFA, idx, 0); // make sure that |V1| == 1 for all eigenvects, otherwise it's /// a problem in the tractography; currently, some from // 3dDWItoDT do not have this property... tempvmagn = sqrt(coorded[i][j][k][0]*coorded[i][j][k][0]+ coorded[i][j][k][1]*coorded[i][j][k][1]+ coorded[i][j][k][2]*coorded[i][j][k][2]); if( tempvmagn<0.99 ) for( m=0 ; m<3 ; m++ ) coorded[i][j][k][m]/= tempvmagn; INDEX[i][j][k][0] =idx; // first value is the index itself if( ROI1[idx]==1 ) INDEX[i][j][k][1]=1; // second value identifies ROI1 mask else INDEX[i][j][k][1]=0; if( ROI2[idx]==1 ) INDEX[i][j][k][2]=1; // third value identifies ROI2 mask else INDEX[i][j][k][2]=0; // fourth value will be counter for number of kept tracks // passing through INDEX[i][j][k][3] = 0; idx+= 1; } // ************************************************************* // ************************************************************* // Beginning of main loop // ************************************************************* // ************************************************************* Numtract = 0; ave_tract_len = 0.; ave_tract_len_phys = 0.; sprintf(OUT_bin,"%s.trk",prefix); if( (fout0 = fopen(OUT_bin, "w")) == NULL) { fprintf(stderr, "Error opening file %s.",OUT_bin); exit(16); } fwrite(&header1,sizeof(tv_io_header),1,fout0); if (get_tract_verb()) { INFO_message("Begin tracking..."); } tb = AppCreateBundle(NULL, 0, NULL, insetFA); // start bundle id = 0; for( k=0 ; k<Dim[2] ; k++ ) for( j=0 ; j<Dim[1] ; j++ ) for( i=0 ; i<Dim[0] ; i++ ) if(coorded[i][j][k][3] >= MinFA) { for( ii=0 ; ii<SeedPerV[0] ; ii++ ) for( jj=0 ; jj<SeedPerV[1] ; jj++ ) for( kk=0 ; kk<SeedPerV[2] ; kk++ ) { in[0] = i; in[1] = j; in[2] = k; physin[0] = ((float) in[0] + (0.5 + (float) ii)/SeedPerV[0])*Ledge[0]; physin[1] = ((float) in[1] + (0.5 + (float) jj)/SeedPerV[1])*Ledge[1]; physin[2] = ((float) in[2] + (0.5 + (float) kk)/SeedPerV[2])*Ledge[2]; len_forw = TrackIt(coorded, in, physin, Ledge, Dim, MinFA, MaxAng, ArrMax, Tforw, flTforw, 1, phys_forw); // reset, because it's changed in TrackIt func in[0] = i; in[1] = j; in[2] = k; physin[0] = ((float) in[0] + (0.5 + (float) ii)/SeedPerV[0])*Ledge[0]; physin[1] = ((float) in[1] + (0.5 + (float) jj)/SeedPerV[1])*Ledge[1]; physin[2] = ((float) in[2] + (0.5 + (float) kk)/SeedPerV[2])*Ledge[2]; len_back = TrackIt(coorded, in, physin, Ledge, Dim, MinFA, MaxAng, ArrMax, Tback, flTback, -1, phys_back); KEEPIT = 0; // a simple switch totlen = len_forw+len_back-1; // NB: overlap of starts totlen_phys = phys_forw[0] + phys_back[0]; if( totlen_phys >= MinL ) { // glue together for simpler notation later for( n=0 ; n<len_back ; n++) { // all of this rr = len_back-n-1; // read in backward for(m=0;m<3;m++) Ttot[rr][m] = Tback[n][m]; } for( n=1 ; n<len_forw ; n++){// skip first->overlap rr = n+len_back-1; // put after for(m=0;m<3;m++) Ttot[rr][m] = Tforw[n][m]; } // <<So close and orthogonal condition>>: // test projecting ends, to see if they abut ROI. for(m=0;m<3;m++) { //actual projected ends end[1][m] = 2*Ttot[totlen-1][m]-Ttot[totlen-2][m]; end[0][m] = 2*Ttot[0][m]-Ttot[1][m]; // default choice, just retest known ends // as default test_ind[1][m] = test_ind[0][m] = Ttot[0][m]; } tt = Create_Tract(len_back, flTback, len_forw, flTforw, id, insetFA); ++id; if (LOG_TYPE == -1) { KEEPIT = 1; } else { inroi1 = 0; // check forw for( n=0 ; n<len_forw ; n++) { if(INDEX[Tforw[n][0]][Tforw[n][1]][Tforw[n][2]][1]==1){ inroi1 = 1; break; } else continue; } if( inroi1==0 ){// after 1st half, check 2nd half for( m=0 ; m<len_back ; m++) { if(INDEX[Tback[m][0]][Tback[m][1]][Tback[m][2]][1]==1){ inroi1 = 1; break; } else continue; } } // after 1st&2nd halves, check bound/neigh if( inroi1==0 ) { if(INDEX[test_ind[1][0]][test_ind[1][1]][test_ind[1][2]][1]==1) inroi1 = 1; if(INDEX[test_ind[0][0]][test_ind[0][1]][test_ind[0][2]][1]==1) inroi1 = 1; } if( ((LOG_TYPE ==0) && (inroi1 ==0)) || ((LOG_TYPE ==1) && (inroi1 ==1))) { // have to check in ROI2 inroi2 = 0; // check forw for( n=0 ; n<len_forw ; n++) { if(INDEX[Tforw[n][0]][Tforw[n][1]][Tforw[n][2]][2]==1){ inroi2 = 1; break; } else continue; } //after 1st half, check 2nd half if( inroi2==0 ) { for( m=0 ; m<len_back ; m++) { if(INDEX[Tback[m][0]][Tback[m][1]][Tback[m][2]][2]==1){ inroi2 = 1; break; } else continue; } } // after 1st&2nd halves, check bound/neigh if( inroi2==0 ) { if(INDEX[test_ind[1][0]][test_ind[1][1]][test_ind[1][2]][2]==1) inroi2 = 1; if(INDEX[test_ind[0][0]][test_ind[0][1]][test_ind[0][2]][2]==1) inroi2 = 1; } // for both cases, need to see it here to keep if( inroi2 ==1 ) KEEPIT = 1; // otherwise, it's gone } else if((LOG_TYPE ==0) && (inroi1 ==1)) KEEPIT = 1; } } // by now, we *know* if we're keeping this or not. if( KEEPIT == 1 ) { tb = AppCreateBundle(tb, 1, tt, NULL); tt = Free_Tracts(tt, 1); READS_in = totlen; fwrite(&READS_in,sizeof(READS_in),1,fout0); for( n=0 ; n<len_back ; n++) { //put this one in backwords, to make it connect m = len_back - 1 - n; for(aa=0 ; aa<3 ; aa++) { // recenter phys loc for trackvis, if nec... // just works this way (where they define // origin) READS_fl = flTback[m][aa]; if(!TV_switch[aa]) READS_fl = Ledge[aa]*Dim[aa]-READS_fl; fwrite(&READS_fl,sizeof(READS_fl),1,fout0); } mm = INDEX[Tback[m][0]][Tback[m][1]][Tback[m][2]][0]; READS_fl =THD_get_voxel(insetFA, mm, 0); // FA fwrite(&READS_fl,sizeof(READS_fl),1,fout0); READS_fl =THD_get_voxel(insetMD, mm, 0); // MD fwrite(&READS_fl,sizeof(READS_fl),1,fout0); READS_fl =THD_get_voxel(insetL1, mm, 0); // L1 fwrite(&READS_fl,sizeof(READS_fl),1,fout0); // count this voxel for having a tract INDEX[Tback[m][0]][Tback[m][1]][Tback[m][2]][3]+= 1; } for( m=1 ; m<len_forw ; m++) { for(aa=0 ; aa<3 ; aa++) { // recenter phys loc for trackvis, if nec... READS_fl = flTforw[m][aa]; if(!TV_switch[aa]) READS_fl = Ledge[aa]*Dim[aa]-READS_fl; fwrite(&READS_fl,sizeof(READS_fl),1,fout0); } mm = INDEX[Tforw[m][0]][Tforw[m][1]][Tforw[m][2]][0]; READS_fl =THD_get_voxel(insetFA, mm, 0); // FA fwrite(&READS_fl,sizeof(READS_fl),1,fout0); READS_fl =THD_get_voxel(insetMD, mm, 0); // MD fwrite(&READS_fl,sizeof(READS_fl),1,fout0); READS_fl =THD_get_voxel(insetL1, mm, 0); // L1 fwrite(&READS_fl,sizeof(READS_fl),1,fout0); // count this voxel for having a tract INDEX[Tforw[m][0]][Tforw[m][1]][Tforw[m][2]][3]+= 1; } ave_tract_len+= totlen; ave_tract_len_phys+= totlen_phys; Numtract+=1; } } } fclose(fout0); if (get_tract_verb()) { INFO_message("Done tracking, have %d tracks.", tb->N_tracts); Show_Taylor_Bundle(tb, NULL, 3); } if (!Write_Bundle(tb,prefix,mode)) { ERROR_message("Failed to write the bundle"); } // ************************************************************** // ************************************************************** // Some simple stats on ROIs and outputs // ************************************************************** // ************************************************************** for( k=0 ; k<Dim[2] ; k++ ) for( j=0 ; j<Dim[1] ; j++ ) for( i=0 ; i<Dim[0] ; i++ ) { if( INDEX[i][j][k][3]>=1 ) { tempMD = THD_get_voxel(insetMD,INDEX[i][j][k][0],0); tempFA = THD_get_voxel(insetFA,INDEX[i][j][k][0],0); tempL1 = THD_get_voxel(insetL1,INDEX[i][j][k][0],0); tempRD = 0.5*(3*tempMD-tempL1); roi3_mu_MD+= tempMD; roi3_mu_FA+= tempFA; roi3_mu_L1+= tempL1; roi3_mu_RD+= tempRD; roi3_sd_MD+= tempMD*tempMD; roi3_sd_FA+= tempFA*tempFA; roi3_sd_L1+= tempL1*tempL1; roi3_sd_RD+= tempRD*tempRD; roi3_ct+= 1; } } if(roi3_ct > 0 ) { // !!!! make into afni file roi3_mu_MD/= (float) roi3_ct; roi3_mu_FA/= (float) roi3_ct; roi3_mu_L1/= (float) roi3_ct; roi3_mu_RD/= (float) roi3_ct; roi3_sd_MD-= roi3_ct*roi3_mu_MD*roi3_mu_MD; roi3_sd_FA-= roi3_ct*roi3_mu_FA*roi3_mu_FA; roi3_sd_L1-= roi3_ct*roi3_mu_L1*roi3_mu_L1; roi3_sd_RD-= roi3_ct*roi3_mu_RD*roi3_mu_RD; roi3_sd_MD/= (float) roi3_ct-1; roi3_sd_FA/= (float) roi3_ct-1; roi3_sd_L1/= (float) roi3_ct-1; roi3_sd_RD/= (float) roi3_ct-1; roi3_sd_MD = sqrt(roi3_sd_MD); roi3_sd_FA = sqrt(roi3_sd_FA); roi3_sd_L1 = sqrt(roi3_sd_L1); roi3_sd_RD = sqrt(roi3_sd_RD); sprintf(OUT_tracstat,"%s.stats",prefix); if( (fout0 = fopen(OUT_tracstat, "w")) == NULL) { fprintf(stderr, "Error opening file %s.",OUT_tracstat); exit(19); } fprintf(fout0,"%d\t%d\n",Numtract,roi3_ct); fprintf(fout0,"%.3f\t%.3f\n",ave_tract_len/Numtract, ave_tract_len_phys/Numtract); // as usual, these next values would have to be divided by the // bval to get their actual value in standard phys units fprintf(fout0,"%.4f\t%.4f\n",roi3_mu_FA,roi3_sd_FA); fprintf(fout0,"%.4f\t%.4f\n",roi3_mu_MD,roi3_sd_MD); fprintf(fout0,"%.4f\t%.4f\n",roi3_mu_RD,roi3_sd_RD); fprintf(fout0,"%.4f\t%.4f\n",roi3_mu_L1,roi3_sd_L1); fclose(fout0); sprintf(prefix_map,"%s_MAP",prefix); sprintf(prefix_mask,"%s_MASK",prefix); outsetMAP = EDIT_empty_copy( mset1 ) ; EDIT_dset_items( outsetMAP , ADN_datum_all , MRI_short , ADN_prefix , prefix_map , ADN_none ) ; if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetMAP)) ) ERROR_exit("Can't overwrite existing dataset '%s'", DSET_HEADNAME(outsetMAP)); outsetMASK = EDIT_empty_copy( mset1 ) ; EDIT_dset_items( outsetMASK , ADN_datum_all , MRI_byte , ADN_prefix , prefix_mask , ADN_none ) ; if(!THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetMASK)) ) ERROR_exit("Can't overwrite existing dataset '%s'", DSET_HEADNAME(outsetMASK)); m=0; for( k=0 ; k<Dim[2] ; k++ ) for( j=0 ; j<Dim[1] ; j++ ) for( i=0 ; i<Dim[0] ; i++ ) { temp_arr[m]=INDEX[i][j][k][3]; if(temp_arr[m]>0.5) temp_byte[m]=1; else temp_byte[m]=0; m++; } // re-orient the data as original inputs // (this function copies the pointer) EDIT_substitute_brick(outsetMAP, 0, MRI_short, temp_arr); temp_arr=NULL; if(TV_switch[0] || TV_switch[1] || TV_switch[2]) { dsetn = r_new_resam_dset(outsetMAP, NULL, 0.0, 0.0, 0.0, header1.voxel_order, RESAM_NN_TYPE, NULL, 1, 0); DSET_delete(outsetMAP); outsetMAP=dsetn; dsetn=NULL; } EDIT_dset_items( outsetMAP , ADN_prefix , prefix_map , ADN_none ) ; THD_load_statistics(outsetMAP ); if( !THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetMAP)) ) ERROR_exit("Can't overwrite existing dataset '%s'", DSET_HEADNAME(outsetMAP)); tross_Make_History( "3dTrackID" , argc , argv , outsetMAP) ; THD_write_3dim_dataset(NULL, NULL, outsetMAP, True); // re-orient the data as original inputs EDIT_substitute_brick(outsetMASK, 0, MRI_byte, temp_byte); temp_byte=NULL; if(TV_switch[0] || TV_switch[1] || TV_switch[2]) { dsetn = r_new_resam_dset(outsetMASK, NULL, 0.0, 0.0, 0.0, header1.voxel_order, RESAM_NN_TYPE, NULL, 1, 0); DSET_delete(outsetMASK); outsetMASK=dsetn; dsetn=NULL; } EDIT_dset_items( outsetMASK , ADN_prefix , prefix_mask , ADN_none ) ; THD_load_statistics(outsetMASK); if(!THD_ok_overwrite() && THD_is_ondisk(DSET_HEADNAME(outsetMASK)) ) ERROR_exit("Can't overwrite existing dataset '%s'", DSET_HEADNAME(outsetMASK)); tross_Make_History( "3dTrackID" , argc , argv , outsetMASK) ; THD_write_3dim_dataset(NULL, NULL, outsetMASK, True); INFO_message("Number of tracts found = %d",Numtract) ; } else INFO_message("\n No Tracts Found!!!\n"); // ************************************************************ // ************************************************************ // Freeing // ************************************************************ // ************************************************************ // !!! need to free afni-sets? DSET_delete(insetFA); DSET_delete(insetMD); DSET_delete(insetL1); DSET_delete(insetV1); DSET_delete(insetEXTRA); //DSET_delete(outsetMAP); //DSET_delete(outsetMASK); DSET_delete(mset2); DSET_delete(mset1); free(prefix); free(insetV1); free(insetFA); free(mset1); free(mset2); free(insetEXTRA); free(ROI1); free(ROI2); free(temp_byte); for( i=0 ; i<ArrMax ; i++) { free(Tforw[i]); free(Tback[i]); free(flTforw[i]); free(flTback[i]); } free(Tforw); free(Tback); free(flTforw); free(flTback); for( i=0 ; i<Dim[0] ; i++) for( j=0 ; j<Dim[1] ; j++) for( k=0 ; k<Dim[2] ; k++) free(coorded[i][j][k]); for( i=0 ; i<Dim[0] ; i++) for( j=0 ; j<Dim[1] ; j++) free(coorded[i][j]); for( i=0 ; i<Dim[0] ; i++) free(coorded[i]); free(coorded); for( i=0 ; i<Dim[0] ; i++) for( j=0 ; j<Dim[1] ; j++) for( k=0 ; k<Dim[2] ; k++) free(INDEX[i][j][k]); for( i=0 ; i<Dim[0] ; i++) for( j=0 ; j<Dim[1] ; j++) free(INDEX[i][j]); for( i=0 ; i<Dim[0] ; i++) free(INDEX[i]); free(INDEX); free(temp_arr); // need to free for( i=0 ; i<2*ArrMax ; i++) free(Ttot[i]); free(Ttot); //free(mode); return 0; }
int main( int argc , char *argv[] ) { THD_3dim_dataset *inset=NULL , *outset ; THD_3dim_dataset **insar=NULL ; int nsar=0 ; int iarg=1 , ii,kk , ids ; MCW_cluster *nbhd=NULL ; char *prefix="./localhistog" ; int ntype=0 ; float na=0.0f,nb=0.0f,nc=0.0f ; int verb=1 , do_prob=0 ; int nx=0,ny=0,nz=0,nvox=0, rbot,rtop ; char *labfile=NULL ; NI_element *labnel=NULL ; int nlab=0 , *labval=NULL ; char **lablab=NULL ; char buf[THD_MAX_SBLABEL] ; UINT32 *ohist , *mhist=NULL ; char *ohist_name=NULL ; int ohzadd=0 ; int *rlist , numval ; float mincount=0.0f ; int mcc ; int *exlist=NULL, numex=0 ; int do_excNONLAB=0 ; /*---- for the clueless who wish to become clued-in ----*/ if( argc == 1 ){ usage_3dLocalHistog(1); exit(0); } /* Bob's help shortcut */ /*---- official startup ---*/ #if defined(USING_MCW_MALLOC) && !defined(USE_OMP) enable_mcw_malloc() ; #endif PRINT_VERSION("3dLocalHistog"); mainENTRY("3dLocalHistog main"); machdep(); AFNI_logger("3dLocalHistog",argc,argv); if( getpid()%2 ) AUTHOR("Bilbo Baggins"); else AUTHOR("Thorin Oakenshield"); AFNI_SETUP_OMP(0) ; /* 24 Jun 2013 */ /*---- loop over options ----*/ while( iarg < argc && argv[iarg][0] == '-' ){ if( strcmp(argv[iarg],"-help") == 0 || strcmp(argv[iarg],"-h") == 0){ usage_3dLocalHistog(strlen(argv[iarg])>3 ? 2:1); exit(0); } if( strncmp(argv[iarg],"-qu",3) == 0 ){ verb = 0 ; iarg++ ; continue ; } if( strncmp(argv[iarg],"-verb",5) == 0 ){ verb++ ; iarg++ ; continue ; } #ifdef ALLOW_PROB if( strncmp(argv[iarg],"-prob",5) == 0 ){ do_prob = 1 ; iarg++ ; continue ; } #endif if( strcmp(argv[iarg],"-exclude") == 0 ){ int ebot=-6666666,etop=-6666666 , ee ; if( ++iarg >= argc ) ERROR_exit("Need argument after '-exclude'") ; sscanf(argv[iarg],"%d..%d",&ebot,&etop) ; if( ebot >= -TWO15 && ebot <= TWO15 ){ if( etop < -TWO15 || etop > TWO15 || etop < ebot ) etop = ebot ; exlist = (int *)realloc(exlist,sizeof(int)*(etop-ebot+1+numex+1)) ; for( ee=ebot ; ee <= etop ; ee++ ){ if( ee != 0 ) exlist[numex++] = ee ; } } iarg++ ; continue ; } if( strcmp(argv[iarg],"-excNONLAB") == 0 ){ do_excNONLAB = 1 ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-prefix") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '-prefix'") ; prefix = strdup(argv[iarg]) ; if( !THD_filename_ok(prefix) ) ERROR_exit("Bad -prefix!") ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-hsave") == 0 ){ if( ++iarg >= argc ) ERROR_exit("Need argument after '-hsave'") ; ohist_name = strdup(argv[iarg]) ; if( !THD_filename_ok(ohist_name) ) ERROR_exit("Bad -hsave!") ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-mincount") == 0 ){ char *cpt ; if( ++iarg >= argc ) ERROR_exit("Need argument after '-mincount'") ; mincount = (float)strtod(argv[iarg],&cpt) ; #if 0 if( mincount > 0.0f && mincount < 50.0f && *cpt == '%' ) /* percentage */ mincount = -0.01f*mincount ; #endif iarg++ ; continue ; } if( strcmp(argv[iarg],"-nbhd") == 0 ){ char *cpt ; if( ntype > 0 ) ERROR_exit("Can't have 2 '-nbhd' options") ; if( ++iarg >= argc ) ERROR_exit("Need argument after '-nbhd'") ; cpt = argv[iarg] ; if( strncasecmp(cpt,"SPHERE",6) == 0 ){ sscanf( cpt+7 , "%f" , &na ) ; ntype = NTYPE_SPHERE ; } else if( strncasecmp(cpt,"RECT",4) == 0 ){ sscanf( cpt+5 , "%f,%f,%f" , &na,&nb,&nc ) ; if( na == 0.0f && nb == 0.0f && nc == 0.0f ) ERROR_exit("'RECT(0,0,0)' is not a legal neighborhood") ; ntype = NTYPE_RECT ; } else if( strncasecmp(cpt,"RHDD",4) == 0 ){ sscanf( cpt+5 , "%f" , &na ) ; if( na == 0.0f ) ERROR_exit("Can't have a RHDD of radius 0") ; ntype = NTYPE_RHDD ; } else if( strncasecmp(cpt,"TOHD",4) == 0 ){ sscanf( cpt+5 , "%f" , &na ) ; if( na == 0.0f ) ERROR_exit("Can't have a TOHD of radius 0") ; ntype = NTYPE_TOHD ; } else { ERROR_exit("Unknown -nbhd shape: '%s'",cpt) ; } iarg++ ; continue ; } if( strcmp(argv[iarg],"-lab_file") == 0 || strcmp(argv[iarg],"-labfile") == 0 ){ char **labnum ; int nbad=0 ; if( ++iarg >= argc ) ERROR_exit("Need argument after '%s'",argv[iarg-1]) ; if( labfile != NULL ) ERROR_exit("Can't use '%s' twice!",argv[iarg-1]) ; labfile = strdup(argv[iarg]) ; labnel = THD_string_table_read(labfile,0) ; if( labnel == NULL || labnel->vec_num < 2 ) ERROR_exit("Can't read label file '%s'",labfile) ; nlab = labnel->vec_len ; labnum = (char **)labnel->vec[0] ; lablab = (char **)labnel->vec[1] ; labval = (int *)calloc(sizeof(int),nlab) ; for( ii=0 ; ii < nlab ; ii++ ){ if( labnum[ii] != NULL ){ labval[ii] = (int)strtod(labnum[ii],NULL) ; if( labval[ii] < -TWO15 || labval[ii] > TWO15 ){ labval[ii] = 0; nbad++; } } } if( nbad > 0 ) ERROR_message("%d label values are outside the range %d..%d :-(" , nbad , -TWO15 , TWO15 ) ; iarg++ ; continue ; } ERROR_message("** 3dLocalHistog: Illegal option: '%s'",argv[iarg]) ; suggest_best_prog_option(argv[0], argv[iarg]); exit(1) ; } /*--- end of loop over options ---*/ /*---- check for stupid user inputs ----*/ if( iarg >= argc ) ERROR_exit("No datasets on command line?") ; if( ohist_name == NULL && strcmp(prefix,"NULL") == 0 ) ERROR_exit("-prefix NULL is only meaningful if you also use -hsave :-(") ; /*------------ scan input datasets, built overall histogram ------------*/ nsar = argc - iarg ; insar = (THD_3dim_dataset **)malloc(sizeof(THD_3dim_dataset *)*nsar) ; if( verb ) fprintf(stderr,"Scanning %d datasets ",nsar) ; ohist = (UINT32 *)calloc(sizeof(UINT32),TWO16) ; for( ids=iarg ; ids < argc ; ids++ ){ /* dataset loop */ insar[ids-iarg] = inset = THD_open_dataset(argv[ids]) ; CHECK_OPEN_ERROR(inset,argv[ids]) ; if( ids == iarg ){ nx = DSET_NX(inset); ny = DSET_NY(inset); nz = DSET_NZ(inset); nvox = nx*ny*nz; } else if( nx != DSET_NX(inset) || ny != DSET_NY(inset) || nz != DSET_NZ(inset) ){ ERROR_exit("Dataset %s grid doesn't match!",argv[ids]) ; } if( !THD_datum_constant(inset->dblk) ) ERROR_exit("Dataset %s doesn't have a fixed data type! :-(",argv[ids]) ; if( THD_need_brick_factor(inset) ) ERROR_exit("Dataset %s has scale factors! :-(",argv[ids]) ; if( DSET_BRICK_TYPE(inset,0) != MRI_byte && DSET_BRICK_TYPE(inset,0) != MRI_short && DSET_BRICK_TYPE(inset,0) != MRI_float ) ERROR_exit("Dataset %s is not byte- or short-valued! :-(",argv[ids]) ; DSET_load(inset) ; CHECK_LOAD_ERROR(inset) ; for( ii=0 ; ii < DSET_NVALS(inset) ; ii++ ){ /* add to overall histogram */ if( verb ) fprintf(stderr,".") ; switch( DSET_BRICK_TYPE(inset,ii) ){ case MRI_short:{ short *sar = (short *)DSET_BRICK_ARRAY(inset,ii) ; for( kk=0 ; kk < nvox ; kk++ ) ohist[ sar[kk]+TWO15 ]++ ; } break ; case MRI_byte:{ byte *bar = (byte *)DSET_BRICK_ARRAY(inset,ii) ; for( kk=0 ; kk < nvox ; kk++ ) ohist[ bar[kk]+TWO15 ]++ ; } break ; case MRI_float:{ float *far = (float *)DSET_BRICK_ARRAY(inset,ii) ; short ss ; for( kk=0 ; kk < nvox ; kk++ ){ ss = SHORTIZE(far[kk]); ohist[ss+TWO15]++; } } break ; } } /* end of sub-brick loop */ DSET_unload(inset) ; /* will re-load later, as needed */ } /* end of dataset loop */ if( verb ) fprintf(stderr,"\n") ; /*-------------- process overall histogram for fun and profit -------------*/ /* if we didn't actually find 0, put it in the histogram now */ if( ohist[0+TWO15] == 0 ){ ohist[0+TWO15] = 1 ; ohzadd = 1 ; } /* excNONLAB? */ if( nlab > 0 && do_excNONLAB ){ byte *klist = (byte *)calloc(sizeof(byte),TWO16) ; int nee ; for( ii=0 ; ii < nlab ; ii++ ){ if( labval[ii] != 0 ) klist[labval[ii]+TWO15] = 1 ; } for( nee=ii=0 ; ii < TWO16 ; ii++ ){ if( !klist[ii] ) nee++ ; } exlist = (int *)realloc(exlist,sizeof(int)*(numex+nee+1)) ; for( ii=0 ; ii < TWO16 ; ii++ ){ if( ii != TWO15 && !klist[ii] ) exlist[numex++] = ii-TWO15 ; } free(klist) ; } /* make a copy of ohist and edit it for mincount, etc */ mhist = (UINT32 *)malloc(sizeof(UINT32)*TWO16) ; memcpy(mhist,ohist,sizeof(UINT32)*TWO16) ; mcc = (mincount < 0.0f) ? (int)(-mincount*nvox) : (int)mincount ; if( mcc > 1 ){ for( ids=ii=0 ; ii < TWO16 ; ii++ ){ if( ii != TWO15 && mhist[ii] > 0 && mhist[ii] < mcc ){ mhist[ii] = 0; ids++; } } if( ids > 0 && verb ) INFO_message("Edited out %d values with overall histogram counts less than %d",ids,mcc) ; } if( numex > 0 ){ int ee ; for( ids=0,ii=0 ; ii < numex ; ii++ ){ ee = exlist[ii] ; if( mhist[ee+TWO15] > 0 ){ mhist[ee+TWO15] = 0; ids++; } } free(exlist) ; if( ids > 0 && verb ) INFO_message("Edited out %d values from the exclude list",ids) ; } /* count number of values with nonzero (edited) counts */ numval = 0 ; for( ii=0 ; ii < TWO16 ; ii++ ) if( mhist[ii] != 0 ) numval++ ; if( numval == 0 ) ERROR_exit("Nothing found! WTF?") ; /* should not happen */ /* make list of all values with nonzero (edited) count */ rlist = (int *)malloc(sizeof(int)*numval) ; if( verb > 1 ) fprintf(stderr,"++ Include list:") ; for( ii=kk=0 ; ii < TWO16 ; ii++ ){ if( mhist[ii] != 0 ){ rlist[kk++] = ii-TWO15 ; if( verb > 1 ) fprintf(stderr," %d[%u]",ii-TWO15,mhist[ii]) ; } } if( verb > 1 ) fprintf(stderr,"\n") ; rbot = rlist[0] ; rtop = rlist[numval-1] ; /* smallest and largest values found */ if( rbot == rtop ) ERROR_exit("Only one value (%d) found in all inputs!",rbot) ; /* if 0 isn't first in rlist, then put it in first place and move negative values up by one spot */ if( rbot < 0 ){ for( kk=0 ; kk < numval && rlist[kk] != 0 ; kk++ ) ; /*nada*/ if( kk < numval ){ /* should always be true */ for( ii=kk-1 ; ii >= 0 ; ii-- ) rlist[ii+1] = rlist[ii] ; rlist[0] = 0 ; } } if( verb ) INFO_message("Value range = %d..%d (%d distinct values)",rbot,rtop,numval ); /* save overall histogram? */ if( ohist_name != NULL ){ FILE *fp = fopen(ohist_name,"w") ; int nl=0 ; if( fp == NULL ) ERROR_exit("Can't open -hsave '%s' for output!",ohist_name) ; if( ohzadd ) ohist[0+TWO15] = 0 ; for( ii=0 ; ii < TWO16 ; ii++ ){ if( ohist[ii] != 0 ){ fprintf(fp,"%6d %u\n",ii-TWO15,ohist[ii]); nl++; } } fclose(fp) ; if( verb ) INFO_message("Wrote %d lines to -hsave file %s",nl,ohist_name) ; } free(ohist) ; free(mhist) ; mhist = ohist = NULL ; /* done with this */ if( strcmp(prefix,"NULL") == 0 ) exit(0) ; /* special case */ /*----------- build the neighborhood mask -----------*/ if( ntype <= 0 ){ /* default neighborhood */ ntype = NTYPE_SPHERE ; na = 0.0f ; if( verb ) INFO_message("Using default neighborhood = self") ; } switch( ntype ){ default: ERROR_exit("WTF? ntype=%d",ntype) ; /* should not happen */ case NTYPE_SPHERE:{ float dx , dy , dz ; if( na < 0.0f ){ dx = dy = dz = 1.0f ; na = -na ; } else { dx = fabsf(DSET_DX(insar[0])) ; dy = fabsf(DSET_DY(insar[0])) ; dz = fabsf(DSET_DZ(insar[0])) ; } nbhd = MCW_spheremask( dx,dy,dz , na ) ; } break ; case NTYPE_RECT:{ float dx , dy , dz ; if( na < 0.0f ){ dx = 1.0f; na = -na; } else dx = fabsf(DSET_DX(insar[0])); if( nb < 0.0f ){ dy = 1.0f; nb = -nb; } else dy = fabsf(DSET_DY(insar[0])); if( nc < 0.0f ){ dz = 1.0f; nc = -nc; } else dz = fabsf(DSET_DZ(insar[0])); nbhd = MCW_rectmask( dx,dy,dz , na,nb,nc ) ; } break ; case NTYPE_RHDD:{ float dx , dy , dz ; if( na < 0.0f ){ dx = dy = dz = 1.0f ; na = -na ; } else { dx = fabsf(DSET_DX(insar[0])) ; dy = fabsf(DSET_DY(insar[0])) ; dz = fabsf(DSET_DZ(insar[0])) ; } nbhd = MCW_rhddmask( dx,dy,dz , na ) ; } break ; case NTYPE_TOHD:{ float dx , dy , dz ; if( na < 0.0f ){ dx = dy = dz = 1.0f ; na = -na ; } else { dx = fabsf(DSET_DX(insar[0])) ; dy = fabsf(DSET_DY(insar[0])) ; dz = fabsf(DSET_DZ(insar[0])) ; } nbhd = MCW_tohdmask( dx,dy,dz , na ) ; } break ; } if( verb ) INFO_message("Neighborhood comprises %d voxels",nbhd->num_pt) ; /*------- actually do some work for a change (is it lunchtime yet?) -------*/ if( verb ) fprintf(stderr,"Voxel-wise histograms ") ; outset = THD_localhistog( nsar,insar , numval,rlist , nbhd , do_prob,verb ) ; if( outset == NULL ) ERROR_exit("Function THD_localhistog() fails?!") ; /*---- save resulting dataset ----*/ EDIT_dset_items( outset , ADN_prefix,prefix , ADN_none ) ; tross_Copy_History( insar[0] , outset ) ; tross_Make_History( "3dLocalHistog" , argc,argv , outset ) ; /* but first attach labels to sub-bricks */ EDIT_BRICK_LABEL(outset,0,"0:Other") ; for( kk=1 ; kk < numval ; kk++ ){ sprintf(buf,"%d:",rlist[kk]) ; for( ii=0 ; ii < nlab ; ii++ ){ if( labval[ii] == rlist[kk] && lablab[ii] != NULL ){ ids = strlen(buf) ; MCW_strncpy(buf+ids,lablab[ii],THD_MAX_SBLABEL-ids) ; break ; } } EDIT_BRICK_LABEL(outset,kk,buf) ; } DSET_write( outset ) ; if( verb ) WROTE_DSET( outset ) ; exit(0) ; }
/*! A function to call SUMA_qhull_wrap or SUMA_qdelaunay_wrap */ SUMA_SurfaceObject *SUMA_ConvexHullSurface( SUMA_GENERIC_PROG_OPTIONS_STRUCT * Opt) { static char FuncName[]={"SUMA_ConvexHullSurface"}; SUMA_SurfaceObject *SO=NULL; float *xyz=NULL, *xyzp=NULL, *txyz=NULL; int npt, *ijk=NULL, nf=0, cnt, i, j, k, nxx, nyy, nzz,N_txyz=-1; FILE *fid=NULL; THD_fvec3 fv, iv; SUMA_Boolean LocalHead = NOPE; SUMA_ENTRY; npt = 0; N_txyz=-1; if (Opt->UseThisBrain) { MRI_IMAGE *im = NULL; float *far=NULL; int nx2, i3; /* load the 1D file */ im = mri_read_1D (Opt->UseThisBrain); if (!im) { SUMA_S_Err("Failed to read file"); SUMA_RETURN(NULL); } far = MRI_FLOAT_PTR(im); if (im->nx == 0) { SUMA_S_Errv("Empty file %s.\n", Opt->UseThisBrain); SUMA_RETURN(NULL); } if (im->ny != 3) { SUMA_S_Errv("Found %d columns in %s. Expecting 3\n", im->ny, Opt->UseThisBrain); SUMA_RETURN(NULL); } /* copy the columns */ N_txyz = im->nx; txyz = (float *)SUMA_malloc(im->nx*im->ny*sizeof(float)); if (!txyz) { SUMA_S_Crit("Failed to allocate."); SUMA_RETURN(NULL); } nx2 = 2*im->nx; for (i=0; i<N_txyz; ++i) { i3 = 3*i; txyz[i3 ] = far[i]; txyz[i3+1] = far[i+im->nx]; txyz[i3+2] = far[i+nx2]; } /* done, clean up and out you go */ if (im) mri_free(im); im = NULL; } if (Opt->in_vol) { cnt = 0; npt = 0; nxx = (DSET_NX(Opt->in_vol)); nyy = (DSET_NY(Opt->in_vol)); nzz = (DSET_NZ(Opt->in_vol)); if (Opt->debug) fprintf(SUMA_STDERR,"%s:\nRunning qhull...\n", FuncName); xyz = (float *)SUMA_malloc(3*nxx*nyy*nzz*sizeof(float)); if (!xyz) { SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NULL); } for( k = 0 ; k < nzz ; k++ ) { for( j = 0 ; j < nyy ; j++ ) { for( i = 0 ; i < nxx ; i++ ) { if (Opt->mcdatav[cnt] == 1) { fv.xyz[0] = DSET_XORG(Opt->in_vol) + i * DSET_DX(Opt->in_vol); fv.xyz[1] = DSET_YORG(Opt->in_vol) + j * DSET_DY(Opt->in_vol); fv.xyz[2] = DSET_ZORG(Opt->in_vol) + k * DSET_DZ(Opt->in_vol); /* change mm to RAI coords */ iv = SUMA_THD_3dmm_to_dicomm( Opt->in_vol->daxes->xxorient, Opt->in_vol->daxes->yyorient, Opt->in_vol->daxes->zzorient, fv ); xyz[3*npt] = iv.xyz[0]; xyz[3*npt+1] = iv.xyz[1]; xyz[3*npt+2] = iv.xyz[2]; npt++; } ++cnt; } } } } else if (Opt->XYZ) { xyz = (float *)SUMA_malloc(3*Opt->N_XYZ*sizeof(float)); if (!xyz) { SUMA_S_Err("Failed to allocate"); SUMA_RETURN(NULL); } for( k = 0 ; k < 3*Opt->N_XYZ ; k++ ) { xyz[k] = Opt->XYZ[k]; npt = Opt->N_XYZ; } } else { SUMA_S_Err("No input"); goto CLEANUP; } if (Opt->corder) { SUMA_PC_XYZ_PROJ *pcp=NULL; if (Opt->geom==1) { SUMA_S_Warn("PCA projection makes no sense for usual convex hull"); } if (!(pcp = SUMA_Project_Coords_PCA (xyz, npt, npt/2, NULL, E3_PLN_PRJ, ROT_2_Z,0))) { SUMA_S_Err("Failed to project"); goto CLEANUP; } xyzp = pcp->xyzp; pcp->xyzp = NULL; pcp = SUMA_Free_PC_XYZ_Proj(pcp); } else { xyzp = xyz; } if (N_txyz >= 0 && N_txyz != npt) { SUMA_S_Errv("Mismatch between number of coordinates for convex hull\n" "and number of coordinates to adopt in the end.\n" " %d, versus %d in -these_coords\n", npt, N_txyz); goto CLEANUP; } if (Opt->geom == 1) { /* convex hull */ if (! (nf = SUMA_qhull_wrap(npt, xyzp, &ijk, 1, Opt->s)) ) { fprintf(SUMA_STDERR,"%s:\nFailed in SUMA_qhull_wrap\n", FuncName); goto CLEANUP; } /* Other than unif==0 make no sense here, but leave it to the user */ switch (Opt->unif) { case 0: /* coordinates as passed to qhull, could be projected ones*/ SO = SUMA_Patch2Surf(xyzp, npt, ijk, nf, 3); break; case 1: /* Original corrdinates passed to qhull (pre-projections, if any) */ SO = SUMA_Patch2Surf(xyz, npt, ijk, nf, 3); break; case 2: /* special coordinates passed by user, never passed in any form to qhull */ SUMA_S_Warn("Makes no sense to mess with coords for convex hull..."); SO = SUMA_Patch2Surf(txyz, npt, ijk, nf, 3); break; default: SUMA_S_Err("pit of despair"); goto CLEANUP; } if (Opt->debug) fprintf(SUMA_STDERR,"%s:\n%d triangles.\n", FuncName, nf); } else if (Opt->geom == 2) { /* triangulation */ if (! (nf = SUMA_qdelaunay_wrap(npt, xyzp, &ijk, 1, Opt->s)) ) { fprintf(SUMA_STDERR,"%s:\nFailed in SUMA_qdelaunay_wrap\n", FuncName); goto CLEANUP; } switch (Opt->unif) { case 0: /* coordinates as passed to qdelaunay, could be projected ones*/ if (xyz == xyzp) xyz=NULL; /* xyzp will be set to null in next call, so xyz is treated the same here */ SO = SUMA_NewSO(&xyzp, npt, &ijk, nf, NULL); SUMA_LHv("xyzp %p, ijk %p\n", txyz, ijk); break; case 1: /* Original corrdinates passed to qdelaunay (pre-projections, if any) */ SO = SUMA_NewSO(&xyz, npt, &ijk, nf, NULL); SUMA_LHv("xyz %p, ijk %p\n", txyz, ijk); break; case 2: /* special coordinates passed by user, never passed in any form to qdelaunay */ SO = SUMA_NewSO(&txyz, npt, &ijk, nf, NULL); SUMA_LHv("txyz %p, ijk %p\n", txyz, ijk); break; default: SUMA_S_Err("pit of despair, again"); goto CLEANUP; } } else { SUMA_S_Errv("Opt->geom = %d not valid\n", Opt->geom); goto CLEANUP; } CLEANUP: if (ijk) SUMA_free(ijk); ijk=NULL; if(txyz) SUMA_free(txyz); txyz=NULL; if (xyzp != xyz && xyzp != NULL) SUMA_free(xyzp); xyzp = NULL; if (xyz) SUMA_free(xyz); xyz = NULL; SUMA_RETURN(SO); }