#include "mrilib.h" void print_results( char * , int , float *, float * ) ; /* later, dude */ static float threshold=0.0 , cer=0.0 , cjv=0.0 , gmcount=0.0 , wmcount=0.0 ; /*---------------------------------------------------------------------------*/ static double apar=0.0 ; /** skewness parameter [-1..1] **/ static double pmodel_pdf( double x ) { double q = 1.0-x*x ; return (q <= 0.0) ? 0.0 : 0.9375*q*q * (1.0 + apar*x*fabs(x)) ; } static double pmodel_cdf( double x ) { double q , val , sss ; if( x <= -1.0 ) return 0.0 ; if( x >= 1.0 ) return 1.0 ; q = x*x ; val = 0.5 + x*(15.0-10.0*q+3.0*q*q)/16.0 - apar/14.0 ; sss = 0.9375 * (apar*x*q)*(1.0/3.0-0.4*q+q*q/7.0) ; if( x < 0.0 ) val -= sss ; else val += sss ; return val ; } #define pmodel_bin(x1,x2,pk,wd) (pmodel_cdf((x2-pk)/wd)-pmodel_cdf((x1-pk)/wd)) #define pmodel_mean(pk,wd) ((pk)+0.078125*apar*(wd)) #define pmodel_sigma(wd) (0.002232142857*(wd)*sqrt(28672.-1225.*apar*apar)) /*---------------------------------------------------------------------------*/ int main( int argc , char * argv[] ) { THD_3dim_dataset *dset , *mset ; byte *mask ; int iarg=1 , nmask,nfill , dilate=1 , dd,nx,ny,nz,nxy,nxyz , ii,jj,kk ; float SIhh=130.0 ; int SIax=0 , SIbot,SItop ; short *sar , *mar ; float pval[128] , wval[128] ; int npk , verb=1 , win=0 , his=0 , fit=1 , do2=0 ; char *dname , cmd[2222] , *label=NULL , *fname="Anhist" ; static int hist[32768] , gist[32768] ; int qq,ncut,ib,nold , sbot,stop , npos,nhalf , cbot,ctop,nwid ; double dsum ; float *wt=NULL , ws ; int ibot,itop ; FILE *hf ; float **Gmat=NULL, *Hvec, *lam, *rez, sum,wtm, wbot,wtop, ebest=-1.0; float *ap,*pk,*ww ; int nregtry , nbetter ; float *pkbest=NULL,*wwbest=NULL,*apbest=NULL,*lambest=NULL , pplm,aplm,wplm ; float *pklast,*wwlast,*aplast ; if( argc < 2 || strcmp(argv[1],"-help") == 0 ){ printf("Usage: 3dAnhist [options] dataset\n" "Input dataset is a T1-weighted high-res of the brain (shorts only).\n" "Output is a list of peaks in the histogram, to stdout, in the form\n" " ( datasetname #peaks peak1 peak2 ... )\n" "In the C-shell, for example, you could do\n" " set anhist = `3dAnhist -q -w1 dset+orig`\n" "Then the number of peaks found is in the shell variable $anhist[2].\n" "\n" "Options:\n" " -q = be quiet (don't print progress reports)\n" " -h = dump histogram data to Anhist.1D and plot to Anhist.ps\n" " -F = DON'T fit histogram with stupid curves.\n" " -w = apply a Winsorizing filter prior to histogram scan\n" " (or -w7 to Winsorize 7 times, etc.)\n" " -2 = Analyze top 2 peaks only, for overlap etc.\n" "\n" " -label xxx = Use 'xxx' for a label on the Anhist.ps plot file\n" " instead of the input dataset filename.\n" " -fname fff = Use 'fff' for the filename instead of 'Anhist'.\n" "\n" "If the '-2' option is used, AND if 2 peaks are detected, AND if\n" "the -h option is also given, then stdout will be of the form\n" " ( datasetname 2 peak1 peak2 thresh CER CJV count1 count2 count1/count2)\n" "where 2 = number of peaks\n" " thresh = threshold between peak1 and peak2 for decision-making\n" " CER = classification error rate of thresh\n" " CJV = coefficient of joint variation\n" " count1 = area under fitted PDF for peak1\n" " count2 = area under fitted PDF for peak2\n" " count1/count2 = ratio of the above quantities\n" "NOTA BENE\n" "---------\n" "* If the input is a T1-weighted MRI dataset (the usual case), then\n" " peak 1 should be the gray matter (GM) peak and peak 2 the white\n" " matter (WM) peak.\n" "* For the definitions of CER and CJV, see the paper\n" " Method for Bias Field Correction of Brain T1-Weighted Magnetic\n" " Resonance Images Minimizing Segmentation Error\n" " JD Gispert, S Reig, J Pascau, JJ Vaquero, P Garcia-Barreno,\n" " and M Desco, Human Brain Mapping 22:133-144 (2004).\n" "* Roughly speaking, CER is the ratio of the overlapping area of the\n" " 2 peak fitted PDFs to the total area of the fitted PDFS. CJV is\n" " (sigma_GM+sigma_WM)/(mean_WM-mean_GM), and is a different, ad hoc,\n" " measurement of how much the two PDF overlap.\n" "* The fitted PDFs are NOT Gaussians. They are of the form\n" " f(x) = b((x-p)/w,a), where p=location of peak, w=width, 'a' is\n" " a skewness parameter between -1 and 1; the basic distribution\n" " is defined by b(x)=(1-x^2)^2*(1+a*x*abs(x)) for -1 < x < 1.\n" "\n" "-- RWCox - November 2004\n" ) ; PRINT_COMPILE_DATE ; exit(0) ; } mainENTRY("3dAnhist main"); machdep(); AFNI_logger("3dAnhist",argc,argv); PRINT_VERSION("3dAnhist") ; /*-- options --*/ while( iarg < argc && argv[iarg][0] == '-' ){ if( strcmp(argv[iarg],"-label") == 0 ){ /* 14 Mar 2003 */ label = argv[++iarg] ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-fname") == 0 ){ /* 14 Mar 2003 */ fname = argv[++iarg] ; if( !THD_filename_ok(fname) ){ fprintf(stderr,"** Bad name after -fname!\n"); exit(1); } iarg++ ; continue ; } if( argv[iarg][1] == 'q' ){ verb=0 ; iarg++ ; continue ; } if( argv[iarg][1] == 'v' ){ verb++ ; iarg++ ; continue ; } if( argv[iarg][1] == 'h' ){ his =1 ; iarg++ ; continue ; } if( argv[iarg][1] == 'F' ){ fit =0 ; iarg++ ; continue ; } if( argv[iarg][1] == '2' ){ do2 =1 ; iarg++ ; continue ; } if( argv[iarg][1] == 'w' ){ win = -1 ; if( isdigit(argv[iarg][2]) ) sscanf(argv[iarg],"-w%d",&win) ; if( win <= 0 ) win = 1 ; iarg++ ; continue ; } fprintf(stderr,"** ILLEGAL option: %s\n",argv[iarg]) ; exit(1) ; } /*------------------*/ /*-- read dataset --*/ dset = THD_open_dataset(argv[iarg]) ; dname = argv[iarg] ; CHECK_OPEN_ERROR(dset,dname) ; if( DSET_BRICK_TYPE(dset,0) != MRI_short ){ fprintf(stderr,"** ILLEGAL non-short dataset type\n"); exit(1); } nx = DSET_NX(dset); ny = DSET_NY(dset); nz = DSET_NZ(dset); nxy = nx*ny; nxyz = nxy*nz; if( nx < 32 || ny < 32 || nz < 32 ){ fprintf(stderr,"** Dataset dimensions are less than 32x32x32?!\n"); exit(1); } if( verb ) fprintf(stderr,"++ Loading dataset %s\n", DSET_BRIKNAME(dset) ) ; DSET_load(dset) ; CHECK_LOAD_ERROR(dset) ; if( label == NULL ) label = dname ; /* 14 Mar 2003 */ /*-----------------------------*/ /*** FIND THE BRAIN-ish MASK ***/ if (1) { if( verb ) fprintf(stderr,"++ Forming automask of connected high-intensity voxels\n") ; mask = THD_automask( dset ) ; if( mask == NULL ){ fprintf(stderr,"** Mask creation fails for unknown reasons!\n"); exit(1); } /* do fillin, etc, after dilation */ if( dilate > 0 ){ int nmm=1 ; if( verb ) fprintf(stderr,"++ Dilating automask %d time%c\n",dilate,(dilate==1)?'.':'s') ; ii = rint(0.032*nx) ; nmm = MAX(nmm,ii) ; ii = rint(0.032*ny) ; nmm = MAX(nmm,ii) ; ii = rint(0.032*nz) ; nmm = MAX(nmm,ii) ; for( dd=0 ; dd < dilate ; dd++ ){ THD_mask_dilate ( nx,ny,nz , mask, 3, 2 ) ; THD_mask_fillin_completely( nx,ny,nz , mask, nmm ) ; } for( ii=0 ; ii < nxyz ; ii++ ) mask[ii] = !mask[ii] ; THD_mask_clust( nx,ny,nz, mask ) ; for( ii=0 ; ii < nxyz ; ii++ ) mask[ii] = !mask[ii] ; } } else { mask = (byte *)malloc(sizeof(byte)*DSET_NVOX(dset)); for (ii=0 ; ii < DSET_NVOX(dset); ii++ ) mask[ii] = 1; } nmask = THD_countmask( DSET_NVOX(dset) , mask ) ; if( nmask == 0 ){ fprintf(stderr,"** No voxels in the automask?!\n"); print_results( label,0,NULL,NULL ) ; exit(1); } /* find most superior point, clip off all more than SIhh (130) mm below it */ if( SIhh > 0.0 ){ if( ORIENT_tinystr[dset->daxes->xxorient][0] == 'S' ){ for( ii=0 ; ii < nx ; ii++ ) for( kk=0 ; kk < nz ; kk++ ) for( jj=0 ; jj < ny ; jj++ ) if( mask[ii+jj*nx+kk*nxy] ) goto CP5 ; CP5: SIax = 1 ; SIbot = ii + (int)(SIhh/fabs(DSET_DX(dset))+0.5) ; SItop = nx-1 ; } else if( ORIENT_tinystr[dset->daxes->xxorient][1] == 'S' ){ for( ii=nx-1 ; ii >= 0 ; ii-- ) for( kk=0 ; kk < nz ; kk++ ) for( jj=0 ; jj < ny ; jj++ ) if( mask[ii+jj*nx+kk*nxy] ) goto CP6 ; CP6: SIax = 1 ; SIbot = 0 ; SItop = ii - (int)(SIhh/fabs(DSET_DX(dset))+0.5) ; } else if( ORIENT_tinystr[dset->daxes->yyorient][0] == 'S' ){ for( jj=0 ; jj < ny ; jj++ ) for( kk=0 ; kk < nz ; kk++ ) for( ii=0 ; ii < nx ; ii++ ) if( mask[ii+jj*nx+kk*nxy] ) goto CP3 ; CP3: SIax = 2 ; SIbot = jj + (int)(SIhh/fabs(DSET_DY(dset))+0.5) ; SItop = ny-1 ; } else if( ORIENT_tinystr[dset->daxes->yyorient][1] == 'S' ){ for( jj=ny-1 ; jj >= 0 ; jj-- ) for( kk=0 ; kk < nz ; kk++ ) for( ii=0 ; ii < nx ; ii++ ) if( mask[ii+jj*nx+kk*nxy] ) goto CP4 ; CP4: SIax = 2 ; SIbot = 0 ; SItop = jj - (int)(SIhh/fabs(DSET_DY(dset))+0.5) ; } else if( ORIENT_tinystr[dset->daxes->zzorient][0] == 'S' ){ for( kk=0 ; kk < nz ; kk++ ) for( jj=0 ; jj < ny ; jj++ ) for( ii=0 ; ii < nx ; ii++ ) if( mask[ii+jj*nx+kk*nxy] ) goto CP1 ; CP1: SIax = 3 ; SIbot = kk + (int)(SIhh/fabs(DSET_DZ(dset))+0.5) ; SItop = nz-1 ; } else if( ORIENT_tinystr[dset->daxes->zzorient][1] == 'S' ){ for( kk=nz-1 ; kk >= 0 ; kk-- ) for( jj=0 ; jj < ny ; jj++ ) for( ii=0 ; ii < nx ; ii++ ) if( mask[ii+jj*nx+kk*nxy] ) goto CP2 ; CP2: SIax = 3 ; SIbot = 0 ; SItop = kk - (int)(SIhh/fabs(DSET_DZ(dset))+0.5) ; } /* cut off stuff below SIhh mm from most Superior point */ if( SIax > 0 && SIbot <= SItop ){ char *cax="xyz" ; if( verb ) fprintf(stderr,"++ SI clipping mask along axis %c: slices %d..%d\n" , cax[SIax-1] , SIbot,SItop ) ; switch( SIax ){ case 1: for( ii=SIbot ; ii <= SItop ; ii++ ) for( kk=0 ; kk < nz ; kk++ ) for( jj=0 ; jj < ny ; jj++ ) mask[ii+jj*nx+kk*nxy] = 0 ; break ; case 2: for( jj=SIbot ; jj <= SItop ; jj++ ) for( kk=0 ; kk < nz ; kk++ ) for( ii=0 ; ii < nx ; ii++ ) mask[ii+jj*nx+kk*nxy] = 0 ; break ; case 3: for( kk=SIbot ; kk <= SItop ; kk++ ) for( jj=0 ; jj < ny ; jj++ ) for( ii=0 ; ii < nx ; ii++ ) mask[ii+jj*nx+kk*nxy] = 0 ; break ; } } } nmask = THD_countmask( DSET_NVOX(dset) , mask ) ; if( nmask <= 999 ){ fprintf(stderr,"** Only %d voxels in the automask?!\n",nmask); print_results( label,0,NULL,NULL); exit(1); } /* Winsorize? */ if( win ){ THD_3dim_dataset *wset ; float irad ; irad = (verb) ? 2.5 : -2.5 ; wset = WINsorize( dset , win , -1,-1 , irad , "winsor" , 0,0 , mask ) ; DSET_delete(dset) ; dset = wset ; } /* copy data in mask region to private array, then expunge dataset */ sar = DSET_ARRAY(dset,0) ; mar = (short *) malloc( sizeof(short)*nmask ) ; for( jj=ii=0 ; ii < nxyz ; ii++ ) if( mask[ii] && sar[ii] > 0 ) mar[jj++] = sar[ii] ; nmask = jj ; if( verb ) fprintf(stderr,"++ %d voxels in mask [out of %d in dataset]\n",nmask,DSET_NVOX(dset)) ; DSET_delete(dset) ; free(mask) ; /*--------------------------------------------------------------------*/ /*** Mask is finished. Now build histogram of data in mask region. ***/ sbot = stop = mar[0] ; for( ii=1 ; ii < nmask ; ii++ ) if( mar[ii] < sbot ) sbot = mar[ii] ; else if( mar[ii] > stop ) stop = mar[ii] ; if( sbot == stop ){ if( verb ) fprintf(stderr,"+ All voxels inside mask have value=%d ?!\n",sbot); pval[0] = sbot ; wval[0] = 0 ; print_results( label,1 , pval,wval ) ; exit(0) ; } if( verb > 1 ) fprintf(stderr,"++ Data range: %d .. %d\n",sbot,stop) ; /* build histogram */ memset( hist , 0 , sizeof(int)*32768 ) ; for( ii=0 ; ii < nmask ; ii++ ) hist[mar[ii]]++ ; dsum = 0.0 ; for( ii=sbot ; ii <= stop ; ii++ ) dsum += (double)(hist[ii])*(double)(hist[ii])*ii ; /* find cliplevel */ qq = 0.65 * nmask ; ib = rint(0.5*sqrt(dsum/nmask)) ; for( kk=0,ii=stop ; ii >= ib && kk < qq ; ii-- ) kk += hist[ii] ; ncut = ii ; qq = 0 ; do{ for( npos=0,ii=ncut ; ii <= stop ; ii++ ) npos += hist[ii] ; /* number >= cut */ nhalf = npos/2 ; for( kk=0,ii=ncut ; ii <= stop && kk < nhalf ; ii++ ) /* find median */ kk += hist[ii] ; nold = ncut ; ncut = 0.5 * ii ; /* new cut */ qq++ ; } while( qq < 20 && ncut != nold ) ; /* make smoothed histogram */ cbot = ncut ; ctop = 3*ncut ; if( verb ) fprintf(stderr,"++ Histogram range = %d .. %d\n",cbot,ctop) ; nwid = rint(0.1*ncut) ; if( nwid <= 0 ){ if( verb ) fprintf(stderr,"++ Using unsmoothed histogram\n") ; memcpy( gist , hist , sizeof(int)*32768 ) ; } else { if( verb > 1 ) fprintf(stderr,"++ Computing smoothing weights:") ; ws = 0.0 ; wt = (float *)malloc(sizeof(float)*(2*nwid+1)) ; for( ii=0 ; ii <= 2*nwid ; ii++ ){ wt[ii] = nwid-abs(nwid-ii) + 0.5f ; if( verb > 1 ) fprintf(stderr," (%d,%g)" , ii,wt[ii]) ; ws += wt[ii] ; } if( verb > 1 ) fprintf(stderr,"\n") ; for( ii=0 ; ii <= 2*nwid ; ii++ ) wt[ii] /= ws ; if( verb ) fprintf(stderr,"++ Smoothing histogram = %d .. %d around each value\n", -nwid,nwid) ; for( jj=cbot ; jj <= ctop ; jj++ ){ ibot = jj-nwid ; if( ibot < sbot ) ibot = sbot ; itop = jj+nwid ; if( itop > stop ) itop = stop ; ws = 0.0 ; for( ii=ibot ; ii <= itop ; ii++ ) ws += wt[nwid-jj+ii] * hist[ii] ; gist[jj] = rint(ws) ; if( verb > 1 ) fprintf(stderr," + %3d: unsmoothed=%d smoothed=%d\n", jj,hist[jj],gist[jj]) ; } free(wt) ; } if( verb ) fprintf(stderr,"++ Scanning histogram for peaks:" ) ; npk = 0 ; for( ii=cbot+2 ; ii <= ctop-2 ; ii++ ){ if( gist[ii] > gist[ii-1] && gist[ii] > gist[ii-2] && gist[ii] > gist[ii+1] && gist[ii] > gist[ii+2] ){ pval[npk]=ii; wval[npk++] = gist[ii]; if( verb ) fprintf(stderr," %.1f",pval[npk-1]) ; } else if( gist[ii] == gist[ii+1] && /* very special case */ gist[ii] > gist[ii-1] && gist[ii] > gist[ii-2] && gist[ii] > gist[ii+2] ){ pval[npk]=ii+0.5; wval[npk++] = gist[ii]; if( verb ) fprintf(stderr," %.1f",pval[npk-1]) ; } else if( gist[ii] == gist[ii+1] && /* super special case */ gist[ii] == gist[ii-1] && gist[ii] > gist[ii-2] && gist[ii] > gist[ii+2] ){ pval[npk]=ii; wval[npk++] = gist[ii]; if( verb ) fprintf(stderr," %.1f",pval[npk-1]) ; } } if( verb ) fprintf(stderr,"\n") ; if( do2 && npk > 2 ){ /* find largest two peaks and keep only them */ float pval_top, pval_2nd, wval_top, wval_2nd , www; int iii,itop ; www = wval[0] ; iii = 0 ; for( ii=1 ; ii < npk ; ii++ ){ if( wval[ii] > www ){ www = wval[ii] ; iii = ii ; } } pval_top = pval[iii] ; wval_top = www ; itop = iii ; www = -1 ; iii = -1 ; for( ii=0 ; ii < npk ; ii++ ){ if( ii != itop && wval[ii] > www ){ www = wval[ii] ; iii = ii ; } } pval_2nd = pval[iii] ; wval_2nd = www ; /* make sure peaks are increasing in pval */ if( pval_top < pval_2nd ){ pval[0] = pval_top ; wval[0] = wval_top ; pval[1] = pval_2nd ; wval[1] = wval_2nd ; } else { pval[0] = pval_2nd ; wval[0] = wval_2nd ; pval[1] = pval_top ; wval[1] = wval_top ; } npk = 2 ; if( verb ) fprintf(stderr,"++ Keeping top 2 peaks: %.1f %.1f\n",pval[0],pval[1]) ; } if( his ){ /* fit histogram? */ npos = 0 ; if( npk > 0 && fit ){ int ndim=ctop-cbot+1 , nvec=npk , iw,nw ; srand48((long)time(NULL)) ; Gmat = (float **)malloc(sizeof(float *)*nvec) ; for( jj=0 ; jj < nvec ; jj++ ) Gmat[jj] = (float *)malloc(sizeof(float)*ndim) ; Hvec = (float *)malloc(sizeof(float)*ndim) ; rez = (float *)malloc(sizeof(float)*ndim) ; wt = (float *)malloc(sizeof(float)*ndim) ; lam = (float *)malloc(sizeof(float)*nvec) ; ww = (float *)malloc(sizeof(float)*nvec) ; pk = (float *)malloc(sizeof(float)*nvec) ; ap = (float *)malloc(sizeof(float)*nvec) ; apbest = (float *)malloc(sizeof(float)*nvec) ; pkbest = (float *)malloc(sizeof(float)*nvec) ; wwbest = (float *)malloc(sizeof(float)*nvec) ; lambest= (float *)malloc(sizeof(float)*nvec) ; aplast = (float *)malloc(sizeof(float)*nvec) ; pklast = (float *)malloc(sizeof(float)*nvec) ; wwlast = (float *)malloc(sizeof(float)*nvec) ; if( verb ) fprintf(stderr,"++ Regressing histogram") ; wbot=0.1*cbot; wtop=0.9*cbot; pplm=0.05*cbot; aplm=0.75; wplm=0.4*cbot; nregtry = 0 ; RegTry: switch(nvec){ case 1: nw = 30000 ; break ; case 2: nw = 400000 ; break ; default: nw = 666000 ; break ; } if( nregtry > 0 ){ /* keep previous best estimates */ pplm *= 0.7 ; aplm *= 0.7 ; wplm *= 0.7 ; nw /= 2 ; memcpy(aplast,apbest,sizeof(float)*nvec) ; memcpy(pklast,pkbest,sizeof(float)*nvec) ; memcpy(wwlast,wwbest,sizeof(float)*nvec) ; } else { for( jj=0 ; jj < nvec ; jj++ ){ /* initial estimates */ wwlast[jj] = 0.5*cbot ; aplast[jj] = 0.0 ; pklast[jj] = pval[jj] ; } } for( ii=0 ; ii < ndim ; ii++ ){ wt[ii] = pow( (double)(1+gist[cbot+ii]) , 1.25 ) ; } for( ii=0,sum=0.0 ; ii < ndim ; ii++ ) sum += wt[ii] ; for( ii=0 ; ii < ndim ; ii++ ) wt[ii] /= sum ; wtm = 1.0 ; for( ii=0 ; ii < ndim ; ii++ ) if( wt[ii] < wtm && wt[ii] > 0.0 ) wtm = wt[ii] ; for( ii=0 ; ii < ndim ; ii++ ) if( wt[ii] == 0.0 ) wt[ii] = wtm ; nbetter = 0 ; for( iw=0 ; iw < nw ; iw++ ){ /* random search nw times */ for( jj=0 ; jj < nvec ; jj++ ){ ww[jj] = wwlast[jj] + (2.*drand48()-1.)*wplm ; pk[jj] = pklast[jj] + (2.*drand48()-1.)*pplm ; ap[jj] = aplast[jj] + (2.*drand48()-1.)*aplm ; if( pk[jj] > 0.9*ctop ) pk[jj] = 0.9*ctop ; else if( pk[jj] < 1.1*cbot ) pk[jj] = 1.1*cbot ; if( ap[jj] > 1.0 ) ap[jj] = 1.0 ; else if( ap[jj] < -1.0 ) ap[jj] = -1.0 ; if( ww[jj] < 0.1*cbot ) ww[jj] = 0.1*cbot ; else if( ww[jj] > 0.9*cbot ) ww[jj] = 0.9*cbot ; if( pk[jj]+ww[jj] > ctop ) ww[jj] = ctop-pk[jj] ; else if( pk[jj]-ww[jj] < cbot ) ww[jj] = pk[jj]-cbot ; } sum = wtm = 0.0 ; for( ii=0 ; ii < ndim ; ii++ ){ /* create basis vectors */ for( jj=0 ; jj < nvec ; jj++ ){ /* basis for jj-th peak pdf */ apar = ap[jj] ; Gmat[jj][ii] = pmodel_bin(cbot+ii-0.5,cbot+ii+0.5,pk[jj],ww[jj]) ; if( Gmat[jj][ii] < 0.0 ) Gmat[jj][ii] = 0.0 ; } } for( ii=0 ; ii < ndim ; ii++ ){ Hvec[ii] = gist[cbot+ii] * wt[ii] ; for( jj=0 ; jj < nvec ; jj++ ) Gmat[jj][ii] *= wt[ii] ; } for( jj=0 ; jj < nvec ; jj++ ) lam[jj] = 1.0 ; /* constraints */ for( ii=0 ; ii < ndim ; ii++ ) rez[ii] = 1.0 ; sum = cl1_solve_res( ndim,nvec , Hvec,Gmat , lam,1 , rez,1 ) ; if( sum >= 0.0 ){ if( ebest < 0.0 || sum < ebest ){ ebest = sum ; for( ii=0 ; ii < ndim ; ii++ ){ sum = 0.0 ; for( jj=0 ; jj < nvec ; jj++ ) sum += Gmat[jj][ii] * lam[jj] ; hist[cbot+ii] = (int)rint(sum/wt[ii]) ; } npos = 1 ; nbetter++ ; memcpy( apbest , ap , sizeof(float)*nvec ) ; memcpy( pkbest , pk , sizeof(float)*nvec ) ; memcpy( wwbest , ww , sizeof(float)*nvec ) ; memcpy( lambest, lam, sizeof(float)*nvec ) ; if( verb ) fprintf(stderr,"+") ; if( verb > 1 ){ fprintf(stderr,"[") ; for( jj=0 ; jj < nvec ; jj++ ){ fprintf(stderr,"p=%.1f w=%.2f a=%.3f", pkbest[jj],wwbest[jj],apbest[jj]) ; if( jj < nvec-1 ) fprintf(stderr,";") ; } fprintf(stderr,"]") ; } } } } /* end of nw searches */ if( verb ) fprintf(stderr,".") ; if( nregtry < 8 ){ nregtry++ ; goto RegTry ; } if( nregtry < 12 && nbetter > 0 ){ nregtry++ ; goto RegTry ; } if( verb ) fprintf(stderr,"!\n") ; } /* end of fitting */ /* save some results */ sprintf(cmd,"%s.1D",fname) ; hf = fopen( cmd , "w" ) ; if( hf == NULL ){ fprintf(stderr,"** Can't open file %s for output!\n",cmd) ; } else { static char pbuf[1024]="\0" ; fprintf(hf,"# 3dAnhist") ; for( ii=1 ; ii < argc ; ii++ ) fprintf(hf," %s",argv[ii]) ; fprintf(hf,"\n") ; for( jj=0 ; jj < npk ; jj++ ){ fprintf(hf,"# Peak %d: location=%.1f histpeak=%.1f\n",jj+1,pval[jj],wval[jj]) ; } if( fit && npos > 0 ){ float gval ; int gtot ; /* compute individual fits into Gmat[jj] curves, and total number in each fit into wt[jj] values */ if( verb > 1 ) fprintf(stderr,"++ Computing individual fits:") ; for( jj=0 ; jj < npk ; jj++ ) wt[jj] = 0.0 ; gtot = 0 ; for( ii=cbot ; ii <= ctop ; ii++ ){ gtot += gist[ii] ; for( jj=0 ; jj < npk ; jj++ ){ if( verb > 1 ) fprintf(stderr,"(%d,%d)",jj,ii) ; apar = apbest[jj] ; gval = lambest[jj] * pmodel_bin(ii-0.5,ii+0.5,pkbest[jj],wwbest[jj]) ; Gmat[jj][ii-cbot] = rint(gval) ; wt[jj] += Gmat[jj][ii-cbot] ; } } if( verb > 1 ) fprintf(stderr,"\n") ; for( jj=0 ; jj < npk ; jj++ ){ fprintf(hf,"# Peak %d fit: location=%.1f width=%.2f skew=%.3f height=%.1f\n", jj+1,pkbest[jj],wwbest[jj],apbest[jj],lambest[jj] ) ; if( jj < 4 ){ ii = strlen(pbuf) ; sprintf(pbuf+ii," #%d=%.1f\\pm%.1f",jj+1,pkbest[jj],wwbest[jj]) ; } } fprintf(hf,"#\n") ; /* 03 Nov 2004: calculate some measures of the overlap */ if( do2 && npk == 2 ){ float mu_bot,sd_bot , mu_top,sd_top ; int ibot,itop , ix , gx0,gx1 ; /* statistics of variation and location */ apar = apbest[0] ; mu_bot = pmodel_mean(pkbest[0],wwbest[0]) ; sd_bot = pmodel_sigma(wwbest[0]) ; fprintf(hf,"# mu_bot=%.1f sd_bot=%.2f\n",mu_bot,sd_bot) ; apar = apbest[1] ; mu_top = pmodel_mean(pkbest[1],wwbest[1]) ; sd_top = pmodel_sigma(wwbest[1]) ; fprintf(hf,"# mu_top=%.1f sd_top=%.2f\n",mu_top,sd_top) ; cjv = (sd_bot+sd_top)/fabs(mu_top-mu_bot) ; fprintf(hf,"# CJV = %.3f%%\n",100.0*cjv) ; fprintf(hf,"# Histogram = %d voxels\n",gtot) ; fprintf(hf,"# Fit 1 = %d voxels\n",(int)wt[0]) ; fprintf(hf,"# Fit 2 = %d voxels\n",(int)wt[1]) ; fprintf(hf,"# Ratio 1/2 = %.3f\n" ,wt[0]/wt[1]) ; gmcount = wt[0] ; wmcount = wt[1] ; /* scan for crossover between fitted densities */ ibot = (int)mu_bot; ibot = MAX(ibot,cbot); ibot = MIN(ibot,ctop); itop = 1+(int)mu_top; itop = MAX(itop,cbot); itop = MIN(itop,ctop); for( ix=ibot ; ix < itop ; ix++ ) if( Gmat[0][ix-cbot] < Gmat[1][ix-cbot] ) break ; if( ix < itop && ix > ibot ){ threshold = ix-0.5 ; gx0 = gx1 = 0 ; for( ii=cbot ; ii < ix ; ii++ ) gx0 += Gmat[1][ii-cbot] ; for( ii=ix ; ii <= ctop ; ii++ ) gx1 += Gmat[0][ii-cbot] ; fprintf(hf,"# Overlaps: Thresh=%.1f Fit 1=%d Fit 2=%d\n", threshold,gx0,gx1) ; cer = ((float)(gx0+gx1))/(wt[0]+wt[1]) ; fprintf(hf,"# CER = %.3f%%\n",100.0*cer) ; #if 0 } else { /* 15 Nov 2004 */ fprintf(hf,"# Overlaps: None\n") ; threshold = 0.5*(mu_bot+mu_top) ; cer = MIN(gmcount,wmcount)/(gmcount+wmcount) ; #endif } } fprintf(hf,"# Histogram Region: min=%d max=%d\n",cbot,ctop) ; fprintf(hf,"# Val Histog FitSum Hi-Fit") ; for( jj=0 ; jj < npk ; jj++ ) fprintf(hf," Fit#%1d ",jj+1) ; fprintf(hf,"\n") ; fprintf(hf,"# --- ------ ------ ------") ; for( jj=0 ; jj < npk ; jj++ ) fprintf(hf," ------") ; fprintf(hf,"\n") ; for( ii=cbot ; ii <= ctop ; ii++ ){ fprintf(hf,"%5d %6d %6d %6d",ii,gist[ii],hist[ii],gist[ii]-hist[ii]) ; for( jj=0 ; jj < npk ; jj++ ) fprintf(hf," %6d",(int)Gmat[jj][ii-cbot]) ; fprintf(hf,"\n") ; } #if 0 for( jj=0; jj < npk ; jj++ ) free(Gmat[jj]); free(Gmat);free(pk);free(ww);free(ap);free(Hvec);free(lam);free(rez);free(wt); free(apbest);free(wwbest);free(pkbest);free(lambest); free(aplast);free(wwlast);free(pklast); #endif ii = (do2 && npk == 2) ? 5 : 3 ; sprintf(cmd, "1dplot -ps -nopush -one -xzero %d -xlabel '%s:%s' '%s.1D[1..%d]' > %s.ps" , cbot , label , pbuf , fname,ii,fname ) ; } else { fprintf(hf,"# Histogram Region: min=%d max=%d\n",cbot,ctop) ; fprintf(hf,"# Val Histog\n") ; fprintf(hf,"# --- ------\n") ; for( ii=cbot ; ii <= ctop ; ii++ ) fprintf(hf,"%5d %6d\n",ii,gist[ii]) ; for( jj=0 ; jj < npk && jj < 4 ; jj++ ){ ii = strlen(pbuf) ; sprintf(pbuf+ii," #1%d=%.1f",jj+1,pval[jj]) ; } sprintf(cmd,"1dplot -ps -nopush -xzero %d -xlabel '%s:%s' '%s.1D[1]' > %s.ps", cbot , label , pbuf , fname,fname ) ; } fclose(hf) ; if( verb ){ fprintf(stderr,"++ %s\n",cmd) ; fprintf(stderr,"++ To view plot: gv -landscape %s.ps\n",fname) ; } system( cmd ) ; } } print_results( label,npk , pval , wval ) ; exit(0) ; } /*---------------------------------------------------------------------------------*/ void print_results( char *dname , int np , float *pk , float *wd ) { int ii ; printf(" ( %s %d " , dname,np ) ; for( ii=0 ; ii < np ; ii++ ) printf(" %.2f ",pk[ii]) ; if( threshold > 0.0 ){ printf(" %.2f %.4f %.4f %.0f %.0f %.3f", threshold , cer , cjv , gmcount , wmcount , gmcount/wmcount ) ; } printf(" )\n") ; }