00001 #include "mrilib.h"
00002 #include "thd_brainormalize.h"
00003 
00004 #undef  IJK
00005 #define IJK(i,j,k) ((i)+(j)*nx+(k)*nxy)
00006 
00007 static int verb = 0 ;
00008 void mri_brainormalize_verbose( int v ){ verb = v ; }
00009 static float thd_bn_dxyz = 1.0;
00010 static int thd_bn_nx     = 167;
00011 static int thd_bn_ny     = 212;
00012 static int thd_bn_nz     = 175;
00013 void mri_brainormalize_initialize(float dx, float dy, float dz)
00014 {
00015    
00016    thd_bn_dxyz = MIN(fabs(dx), fabs(dy)); thd_bn_dxyz = MIN(thd_bn_dxyz, fabs(dz));
00017    thd_bn_nx = (int)( (float)thd_bn_nx / thd_bn_dxyz );
00018    thd_bn_ny = (int)( (float)thd_bn_ny / thd_bn_dxyz );
00019    thd_bn_nz = (int)( (float)thd_bn_nz / thd_bn_dxyz );
00020    return;
00021 }
00022 float THD_BN_dxyz()
00023 {
00024    return thd_bn_dxyz;
00025 }
00026 int THD_BN_nx()
00027 {
00028    return thd_bn_nx;
00029 }
00030 int THD_BN_ny()
00031 {
00032    return thd_bn_ny;
00033 }
00034 int THD_BN_nz()
00035 {
00036    return thd_bn_nz;
00037 }
00038 
00039 
00040 
00041 
00042 
00043 static int mask_count( int nvox , byte *mmm )
00044 {
00045    int ii , nn ;
00046    for( nn=ii=0 ; ii < nvox ; ii++ ) nn += (mmm[ii] != 0) ;
00047    return nn ;
00048 }
00049 
00050 
00051 
00052 #undef  DALL
00053 #define DALL 4096  
00054 
00055 
00056 
00057 
00058 #undef  DPUT
00059 #define DPUT(i,j,k,d)                                               \
00060   do{ ijk = (i)+(j)*nx+(k)*nxy ;                                    \
00061       if( mmm[ijk] == 0 ) break ;                                   \
00062       if( nnow == nall ){               \
00063         nall += DALL ;                                              \
00064         inow = (short *) realloc((void *)inow,sizeof(short)*nall) ; \
00065         jnow = (short *) realloc((void *)jnow,sizeof(short)*nall) ; \
00066         know = (short *) realloc((void *)know,sizeof(short)*nall) ; \
00067       }                                                             \
00068       inow[nnow] = (i); jnow[nnow] = (j); know[nnow] = (k);         \
00069       nnow++ ; mmm[ijk] = 0 ; ddd[ijk] = (d) ;                      \
00070     } while(0)
00071 
00072 
00073 
00074 short * THD_mask_distize( int nx, int ny, int nz, byte *mmm, byte *ccc )
00075 {
00076    short *ddd , dnow ;
00077    int ii,jj,kk , nxy=nx*ny , nxyz=nx*ny*nz , ijk ;
00078    int ip,jp,kp , im,jm,km , icl ;
00079    int nccc,nmmm , nall,nnow ;
00080    short *inow , *jnow , *know ;
00081    float drat ;
00082 
00083    if( mmm == NULL || ccc == NULL ) return NULL ;
00084 
00085    ddd = (short *)malloc( sizeof(short)*nxyz ) ;
00086    nccc = nmmm = 0 ;
00087    for( ii=0 ; ii < nxyz ; ii++ ){
00088           if( ccc[ii] ){ ddd[ii] =  1; nccc++; nmmm++; }
00089      else if( mmm[ii] ){ ddd[ii] = -1; nmmm++; }
00090      else              { ddd[ii] =  0; }
00091    }
00092    if( nccc == 0 ){ free((void *)ddd); return NULL; }
00093 
00094    nall  = nccc+DALL ;                            
00095    inow  = (short *) malloc(sizeof(short)*nall) ; 
00096    jnow  = (short *) malloc(sizeof(short)*nall) ;
00097    know  = (short *) malloc(sizeof(short)*nall) ;
00098    nnow  = 0 ;
00099 
00100    for( ii=0 ; ii < nxyz ; ii++ ){
00101      if( ccc[ii] ){
00102        inow[nnow] = ii % nx ;
00103        jnow[nnow] = (ii%nxy)/nx ;
00104        know[nnow] = ii / nxy ;
00105        mmm[ii]    = 0 ;
00106        nnow++ ;
00107      }
00108    }
00109 
00110    for( icl=0 ; icl < nnow ; icl++ ){
00111      ii = inow[icl] ; jj = jnow[icl] ; kk = know[icl] ; ijk = ii+jj*nx+kk*nxy ;
00112      im = ii-1      ; jm = jj-1      ; km = kk-1      ;
00113      ip = ii+1      ; jp = jj+1      ; kp = kk+1      ; dnow = ddd[ijk]+1 ;
00114 
00115      if( im >= 0 ) DPUT(im,jj,kk,dnow) ;
00116      if( ip < nx ) DPUT(ip,jj,kk,dnow) ;
00117      if( jm >= 0 ) DPUT(ii,jm,kk,dnow) ;
00118      if( jp < ny ) DPUT(ii,jp,kk,dnow) ;
00119      if( km >= 0 ) DPUT(ii,jj,km,dnow) ;
00120      if( kp < nz ) DPUT(ii,jj,kp,dnow) ;
00121    }
00122 
00123    for( ii=0 ; ii < nxyz ; ii++ ) mmm[ii] = (ddd[ii] > 0) ;
00124 
00125    free((void *)inow); free((void *)jnow); free((void *)know);
00126 
00127    return ddd ;
00128 }
00129 
00130 
00131 
00132 
00133 #undef  CPUT
00134 #define CPUT(i,j,k)                                                   \
00135   do{ ijk = (i)+(j)*nx+(k)*nxy ;                                      \
00136       if( mmm[ijk] ){                                                 \
00137         if( nnow == nall ){               \
00138           nall += DALL ;                                              \
00139           inow = (short *) realloc((void *)inow,sizeof(short)*nall) ; \
00140           jnow = (short *) realloc((void *)jnow,sizeof(short)*nall) ; \
00141           know = (short *) realloc((void *)know,sizeof(short)*nall) ; \
00142         }                                                             \
00143         inow[nnow] = (i); jnow[nnow] = (j); know[nnow] = (k);         \
00144         nnow++ ; mmm[ijk] = 0 ;                                       \
00145       } } while(0)
00146 
00147 
00148 
00149 
00150 static void clustedit3D( int nx, int ny, int nz, byte *mmm, int csize )
00151 {
00152    int ii,jj,kk, icl , nxy,nxyz , ijk , ijk_last ;
00153    int ip,jp,kp , im,jm,km ;
00154    int nnow , nall , nsav , nkill ;
00155    short *inow , *jnow , *know ;
00156    short *isav , *jsav , *ksav ;
00157 
00158    if( nx < 1 || ny < 1 || nz < 1 || mmm == NULL || csize < 2 ) return ;
00159 
00160    nxy = nx*ny ; nxyz = nxy*nz ;
00161 
00162    nall  = 8 ;                                    
00163    inow  = (short *) malloc(sizeof(short)*nall) ; 
00164    jnow  = (short *) malloc(sizeof(short)*nall) ;
00165    know  = (short *) malloc(sizeof(short)*nall) ;
00166 
00167    nsav  = nkill = 0 ;
00168    isav  = (short *) malloc(sizeof(short)) ;
00169    jsav  = (short *) malloc(sizeof(short)) ;
00170    ksav  = (short *) malloc(sizeof(short)) ;
00171 
00172    
00173 
00174 #if 0
00175    if( verb ) fprintf(stderr," + clustedit3D: threshold size=%d voxels\n",csize) ;
00176 #endif
00177 
00178    ijk_last = 0 ;
00179    while(1) {
00180      
00181 
00182      for( ijk=ijk_last ; ijk < nxyz ; ijk++ ) if( mmm[ijk] ) break ;
00183      if( ijk == nxyz ) break ;  
00184 
00185      ijk_last = ijk+1 ;         
00186 
00187      
00188 
00189      mmm[ijk] = 0 ;                                
00190      nnow     = 1 ;                                
00191      inow[0]  = ijk % nx ;
00192      jnow[0]  = (ijk%nxy)/nx ;
00193      know[0]  = ijk / nxy ;
00194 
00195      
00196 
00197 
00198 
00199 
00200 
00201 
00202 
00203      for( icl=0 ; icl < nnow ; icl++ ){
00204        ii = inow[icl] ; jj = jnow[icl] ; kk = know[icl] ;
00205        im = ii-1      ; jm = jj-1      ; km = kk-1      ;
00206        ip = ii+1      ; jp = jj+1      ; kp = kk+1      ;
00207 
00208        if( im >= 0 ) CPUT(im,jj,kk) ;
00209        if( ip < nx ) CPUT(ip,jj,kk) ;
00210        if( jm >= 0 ) CPUT(ii,jm,kk) ;
00211        if( jp < ny ) CPUT(ii,jp,kk) ;
00212        if( km >= 0 ) CPUT(ii,jj,km) ;
00213        if( kp < nz ) CPUT(ii,jj,kp) ;
00214      }
00215 
00216      
00217 
00218      if( nnow >= csize ){
00219        kk = nsav+nnow ;
00220        isav = (short *)realloc((void *)isav,sizeof(short)*kk) ;
00221        jsav = (short *)realloc((void *)jsav,sizeof(short)*kk) ;
00222        ksav = (short *)realloc((void *)ksav,sizeof(short)*kk) ;
00223        memcpy(isav+nsav,inow,sizeof(short)*nnow) ;
00224        memcpy(jsav+nsav,jnow,sizeof(short)*nnow) ;
00225        memcpy(ksav+nsav,know,sizeof(short)*nnow) ;
00226        nsav = kk ;
00227 #if 0
00228        if( verb )
00229          fprintf(stderr," + clustedit3D: saved cluster with %d voxels\n",nnow);
00230 #endif
00231      } else {
00232        nkill += nnow ;
00233      }
00234 
00235    } 
00236 
00237    free((void *)inow); free((void *)jnow); free((void *)know);
00238 
00239    
00240 
00241    for( ii=0 ; ii < nsav ; ii++ )
00242      mmm[ IJK(isav[ii],jsav[ii],ksav[ii]) ] = 1 ;
00243 
00244    free((void *)isav); free((void *)jsav); free((void *)ksav) ;
00245 
00246 #if 0
00247    if( verb )
00248      fprintf(stderr," + clustedit3D totals:"
00249                     " saved=%d killed=%d nxyz=%d\n",nsav,nkill,nxyz) ;
00250 #endif
00251    return ;
00252 }
00253 
00254 
00255 
00256 
00257 
00258 static float partial_cliplevel( MRI_IMAGE *im , float mfrac ,
00259                                 int ibot,int itop ,
00260                                 int jbot,int jtop , int kbot,int ktop )
00261 {
00262    int ncut,ib , qq,nold ;
00263    int ii,jj,kk , nx,ny,nz,nxy ;
00264    int *hist ;
00265    short *sar ;
00266    byte *bar ;
00267    int nhist , npos , nhalf , val ;
00268    double dsum ;
00269 
00270 ENTRY("partial_cliplevel") ;
00271    if( im == NULL || im->kind != MRI_short ) RETURN(1.0) ;
00272 
00273    if( mfrac <= 0.0 || mfrac >= 0.99 ) mfrac = 0.50 ;
00274 
00275    nx = im->nx ; ny = im->ny ; nz = im->nz ; nxy = nx*ny ;
00276 
00277    if( ibot <  0  ) ibot = 0 ;
00278    if( jbot <  0  ) jbot = 0 ;
00279    if( kbot <  0  ) kbot = 0 ;
00280    if( itop >= nx ) itop = nx-1 ;
00281    if( jtop >= ny ) jtop = ny-1 ;
00282    if( ktop >= nz ) ktop = nz-1 ;
00283 
00284    if( itop < ibot || jtop < jbot || ktop < kbot ) RETURN(1.0) ;
00285 
00286    
00287 
00288    nhist = 32767 ;
00289    hist  = (int *) calloc(sizeof(int),nhist+1) ;
00290 
00291    
00292 
00293    dsum = 0.0 ;  
00294    npos = 0 ;    
00295    sar  =  MRI_SHORT_PTR(im) ;
00296    for( kk=kbot ; kk <= ktop ; kk++ ){
00297     for( jj=jbot ; jj <= jtop ; jj++ ){
00298      for( ii=ibot ; ii <= itop ; ii++ ){
00299        val = sar[IJK(ii,jj,kk)] ;
00300        if( val > 0 && val <= nhist ){
00301          hist[val]++ ;
00302          dsum += (double)(val)*(double)(val); npos++;
00303        }
00304    }}}
00305 
00306    if( npos <= 999 ){ free((void *)hist); RETURN(1.0); }
00307 
00308    
00309 
00310    qq = 0.65 * npos ; ib = rint(0.5*sqrt(dsum/npos)) ;
00311    for( kk=0,ii=nhist-1 ; ii >= ib && kk < qq ; ii-- ) kk += hist[ii] ;
00312 
00313    
00314 
00315    ncut = ii ;   
00316    qq   = 0 ;    
00317    do{
00318      for( npos=0,ii=ncut ; ii < nhist ; ii++ ) npos += hist[ii]; 
00319      nhalf = npos/2 ;
00320      for( kk=0,ii=ncut ; ii < nhist && kk < nhalf ; ii++ )  
00321        kk += hist[ii] ;                                     
00322      nold = ncut ;                                          
00323      ncut = mfrac * ii ;                                    
00324      qq++ ;
00325   } while( qq < 20 && ncut != nold ) ; 
00326 
00327    free((void *)hist) ;
00328    RETURN( (float)(ncut) ) ;
00329 }
00330 
00331 
00332 
00333 typedef struct {
00334    float clip_000, clip_100, clip_010, clip_110,
00335          clip_001, clip_101, clip_011, clip_111 ;
00336    float x0,x1,dxi , y0,y1,dyi , z0,z1,dzi ;
00337    float clip_min , clip_max ;
00338 } clipvec ;
00339 
00340 
00341 
00342 static clipvec get_octant_clips( MRI_IMAGE *im , float mfrac )
00343 {
00344    float xcm,ycm,zcm , sum,val , clip_min , clip_max ;
00345    int ii,jj,kk , nx,ny,nz,nxy , ic,jc,kc , it,jt,kt , ijk ;
00346    short *sar ;
00347    clipvec cv ;
00348 
00349 ENTRY("get_octant_clips") ;
00350 
00351    cv.clip_000 = -1 ;  
00352 
00353    if( im == NULL || im->kind != MRI_short ) RETURN(cv) ;
00354 
00355    nx = im->nx ; ny = im->ny ; nz = im->nz ; nxy = nx*ny ;
00356    it = nx-1   ; jt = ny-1   ; kt = nz-1   ;
00357 
00358    
00359 
00360    sar = MRI_SHORT_PTR(im) ; if( sar == NULL ) RETURN(cv) ;
00361 
00362    xcm = ycm = zcm = sum = 0.0 ;
00363    for( ijk=kk=0 ; kk < nz ; kk++ ){
00364     for( jj=0 ; jj < ny ; jj++ ){
00365      for( ii=0 ; ii < nx ; ii++,ijk++ ){
00366        val = (float)sar[ijk]; if( val <= 0.0 ) continue;
00367        sum += val ;
00368        xcm += val * ii ;
00369        ycm += val * jj ;
00370        zcm += val * kk ;
00371    }}}
00372    if( sum == 0.0 ) RETURN(cv) ;
00373    ic = (int)rint(xcm/sum); jc = (int)rint(ycm/sum); kc = (int)rint(zcm/sum);
00374 
00375    
00376 
00377    val = 0.5 * partial_cliplevel( im,mfrac , 0,it , 0,jt , 0,kt ) ;
00378 
00379    cv.clip_000 = partial_cliplevel( im,mfrac,  0  ,ic+2,  0  ,jc+2,  0  ,kc+2 );
00380    cv.clip_100 = partial_cliplevel( im,mfrac, ic-2,it  ,  0  ,jc+2,  0  ,kc+2 );
00381    cv.clip_010 = partial_cliplevel( im,mfrac,  0  ,ic+2, jc-2,jt  ,  0  ,kc+2 );
00382    cv.clip_110 = partial_cliplevel( im,mfrac, ic-2,it  , jc-2,jt  ,  0  ,kc+2 );
00383    cv.clip_001 = partial_cliplevel( im,mfrac,  0  ,ic+2,  0  ,jc+2, kc-2,kt   );
00384    cv.clip_101 = partial_cliplevel( im,mfrac, ic-2,it  ,  0  ,jc+2, kc-2,kt   );
00385    cv.clip_011 = partial_cliplevel( im,mfrac,  0  ,ic+2, jc-2,jt  , kc-2,kt   );
00386    cv.clip_111 = partial_cliplevel( im,mfrac, ic-2,it  , jc-2,jt  , kc-2,kt   );
00387 
00388    if( cv.clip_000 < val ) cv.clip_000 = val ;  
00389    if( cv.clip_100 < val ) cv.clip_100 = val ;  
00390    if( cv.clip_010 < val ) cv.clip_010 = val ;  
00391    if( cv.clip_110 < val ) cv.clip_110 = val ;  
00392    if( cv.clip_001 < val ) cv.clip_001 = val ;
00393    if( cv.clip_101 < val ) cv.clip_101 = val ;
00394    if( cv.clip_011 < val ) cv.clip_011 = val ;
00395    if( cv.clip_111 < val ) cv.clip_111 = val ;
00396 
00397    clip_min =              cv.clip_000  ;
00398    clip_min = MIN(clip_min,cv.clip_100) ;
00399    clip_min = MIN(clip_min,cv.clip_010) ;
00400    clip_min = MIN(clip_min,cv.clip_110) ;
00401    clip_min = MIN(clip_min,cv.clip_001) ;
00402    clip_min = MIN(clip_min,cv.clip_101) ;
00403    clip_min = MIN(clip_min,cv.clip_011) ;
00404    clip_min = MIN(clip_min,cv.clip_111) ;  cv.clip_min = clip_min ;
00405 
00406    clip_max =              cv.clip_000  ;
00407    clip_max = MAX(clip_max,cv.clip_100) ;
00408    clip_max = MAX(clip_max,cv.clip_010) ;
00409    clip_max = MAX(clip_max,cv.clip_110) ;
00410    clip_max = MAX(clip_max,cv.clip_001) ;
00411    clip_max = MAX(clip_max,cv.clip_101) ;
00412    clip_max = MAX(clip_max,cv.clip_011) ;
00413    clip_max = MAX(clip_max,cv.clip_111) ;  cv.clip_max = clip_max ;
00414 
00415    
00416 
00417 
00418    cv.x0  = 0.5*ic ; cv.x1 = 0.5*(ic+it) ;
00419    cv.y0  = 0.5*jc ; cv.y1 = 0.5*(jc+jt) ;
00420    cv.z0  = 0.5*kc ; cv.z1 = 0.5*(kc+kt) ;
00421    cv.dxi = (cv.x1 > cv.x0) ? 1.0/(cv.x1-cv.x0) : 0.0 ;
00422    cv.dyi = (cv.y1 > cv.y0) ? 1.0/(cv.y1-cv.y0) : 0.0 ;
00423    cv.dzi = (cv.z1 > cv.z0) ? 1.0/(cv.z1-cv.z0) : 0.0 ;
00424 
00425 #if 0
00426    if( verb )
00427     fprintf(stderr," + get_octant_clips:  min clip=%.1f\n"
00428                    "   clip_000=%.1f  clip_100=%.1f  clip_010=%.1f  clip_110=%.1f\n"
00429                    "   clip_001=%.1f  clip_101=%.1f  clip_011=%.1f  clip_111=%.1f\n"
00430                    "   (x0,y0,z0)=(%.1f,%.1f,%.1f) (x1,y1,z1)=(%.1f,%.1f,%.1f)\n" ,
00431             val ,
00432             cv.clip_000 , cv.clip_100 , cv.clip_010 , cv.clip_110 ,
00433             cv.clip_001 , cv.clip_101 , cv.clip_011 , cv.clip_111 ,
00434             cv.x0 , cv.y0 , cv.z0 , cv.x1 , cv.y1 , cv.z1  ) ;
00435 #endif
00436 
00437    RETURN(cv) ;
00438 }
00439 
00440 
00441 
00442 
00443 
00444 static INLINE float pointclip( int ii, int jj, int kk , clipvec *cv )
00445 {
00446    float x1,y1,z1 , x0,y0,z0 , val ;
00447 
00448    
00449 
00450    x1 = (ii-cv->x0)*cv->dxi; if(x1 < 0.0) x1=0.0; else if(x1 > 1.0) x1=1.0;
00451    y1 = (jj-cv->y0)*cv->dyi; if(y1 < 0.0) y1=0.0; else if(y1 > 1.0) y1=1.0;
00452    z1 = (kk-cv->z0)*cv->dzi; if(z1 < 0.0) z1=0.0; else if(z1 > 1.0) z1=1.0;
00453 
00454    x0 = 1.0-x1 ; y0 = 1.0-y1 ; z0 = 1.0-z1 ;
00455 
00456    val =  cv->clip_000 * x0*y0*z0 + cv->clip_100 * x1*y0*z0
00457         + cv->clip_010 * x0*y1*z0 + cv->clip_110 * x1*y1*z0
00458         + cv->clip_001 * x0*y0*z1 + cv->clip_101 * x1*y0*z1
00459         + cv->clip_011 * x0*y1*z1 + cv->clip_111 * x1*y1*z1 ;
00460    return val ;
00461 }
00462 
00463 
00464 
00465 
00466 
00467 static byte * mri_short2mask( MRI_IMAGE *im )
00468 {
00469    int ii,jj,kk,ijk , nx,ny,nz,nxy,nxyz ;
00470    clipvec bvec , tvec ;
00471    short *sar ;
00472    byte *mask ;
00473    float bval , tval ;
00474 
00475 ENTRY("mri_short2mask") ;
00476    if( im == NULL || im->kind != MRI_short ) RETURN(NULL) ;
00477    sar = MRI_SHORT_PTR(im) ; if( sar == NULL ) RETURN(NULL) ;
00478 
00479    nx = im->nx ; ny = im->ny ; nz = im->nz ; nxy = nx*ny ; nxyz = nxy*nz ;
00480 
00481    bvec = get_octant_clips( im , 0.40f ) ;
00482    if( bvec.clip_000 < 0.0 ) RETURN(NULL) ;
00483 
00484    tvec = bvec ;
00485    tvec.clip_000 *= 9.91 ;
00486    tvec.clip_100 *= 9.91 ;
00487    tvec.clip_010 *= 9.91 ;
00488    tvec.clip_110 *= 9.91 ;
00489    tvec.clip_001 *= 9.91 ;
00490    tvec.clip_101 *= 9.91 ;
00491    tvec.clip_011 *= 9.91 ;
00492    tvec.clip_111 *= 9.91 ;
00493 
00494    
00495 
00496 #if 0
00497    if( verb ) fprintf(stderr," + mri_short2mask: clipping\n") ;
00498 #endif
00499 
00500    mask = (byte *) malloc( sizeof(byte)*nxyz ) ;
00501    for( ijk=kk=0 ; kk < nz ; kk++ ){
00502     for( jj=0 ; jj < ny ; jj++ ){
00503      for( ii=0 ; ii < nx ; ii++,ijk++ ){
00504        bval = pointclip( ii,jj,kk , &bvec ) ; 
00505 #if 0
00506        tval = pointclip( ii,jj,kk , &tvec ) ; 
00507        mask[ijk] = (sar[ijk] >= bval && sar[ijk] <= tval) ; 
00508 #else
00509        mask[ijk] = (sar[ijk] >= bval) ; 
00510 #endif
00511    }}}
00512 
00513    
00514 
00515    clustedit3D( nx,ny,nz , mask , (int)rint(0.02*nxyz) ) ;
00516 
00517    if( verb ) fprintf(stderr," + mri_short2mask: %d voxels survive\n",
00518                              mask_count(nxyz,mask) ) ;
00519 
00520    RETURN(mask) ;
00521 }
00522 
00523 
00524 
00525 typedef struct { short i,j,k,val; int basin; } shortvox ;
00526 
00527 
00528 
00529 
00530 static sort_shortvox( int n , shortvox *ar , int dec , float botperc, float topperc )
00531 {
00532    int ii,jj , sbot,stop,nsv , sval , pbot,ptop ;
00533    int *hsv , *csv ;
00534    shortvox *tar ;
00535 
00536    if( n < 2 || ar == NULL ) return ;
00537 
00538    
00539 
00540    if( dec ){
00541      float tmp ;
00542      for( ii=0 ; ii < n ; ii++ ) ar[ii].val = -ar[ii].val ;
00543      tmp = botperc ; botperc = topperc ; topperc = tmp ;
00544    }
00545 
00546    
00547 
00548    sbot = stop = ar[0].val ;
00549    for( ii=1 ; ii < n ; ii++ ){
00550      sval = ar[ii].val ;
00551           if( sval < sbot ) sbot = sval ;
00552      else if( sval > stop ) stop = sval ;
00553    }
00554    nsv = stop-sbot+1 ;   
00555    if( nsv <= 1 ) return ;
00556 
00557    
00558 
00559 
00560    hsv = (int *)calloc(sizeof(int),nsv) ;
00561    csv = (int *)calloc(sizeof(int),nsv+1) ;
00562    for( ii=0 ; ii <  n   ; ii++ ) hsv[ar[ii].val-sbot]++ ;
00563    for( ii=1 ; ii <= nsv ; ii++ ) csv[ii] = csv[ii-1]+hsv[ii-1] ;
00564    free((void *)hsv) ;
00565 
00566    if( botperc > 0.0 && botperc < 50.0 ){
00567      jj = (int)rint(0.01*botperc*n) ;
00568      for( ii=0 ; ii < nsv && csv[ii] <= jj ; ii++ ) ;
00569      pbot = ii+sbot ;
00570      if( verb ) fprintf(stderr," + sort_shortvox: sbot=%d pbot=%d\n",sbot,pbot) ;
00571    } else {
00572      pbot = sbot ;
00573    }
00574 
00575    if( topperc > 0.0 && topperc < 50.0 ){
00576      jj = (int)rint(0.01*(100.0-topperc)*n) ;
00577      for( ii=0 ; ii < nsv && csv[ii] <= jj ; ii++ ) ;
00578      ptop = ii+sbot ;
00579      if( verb ) fprintf(stderr," + sort_shortvox: stop=%d ptop=%d\n",stop,ptop) ;
00580    } else {
00581      ptop = stop ;
00582    }
00583 
00584    
00585 
00586 
00587    tar = (shortvox *)calloc(sizeof(shortvox),n) ;
00588    for( ii=0 ; ii < n ; ii++ ){
00589      sval = ar[ii].val - sbot ;   
00590      tar[ csv[sval] ] = ar[ii] ;
00591      csv[sval]++ ;
00592    }
00593 
00594    if( pbot > sbot ){
00595      for( ii=0 ; ii < n ; ii++ )
00596        if( tar[ii].val < pbot ) tar[ii].val = pbot ;
00597    }
00598    if( ptop < stop ){
00599      for( ii=0 ; ii < n ; ii++ )
00600        if( tar[ii].val > ptop ) tar[ii].val = ptop ;
00601    }
00602 
00603    
00604 
00605    memcpy( ar , tar , sizeof(shortvox)*n ) ;
00606    free((void *)tar) ; free((void *)csv) ;
00607 
00608    
00609 
00610    if( dec )
00611      for( ii=0 ; ii < n ; ii++ ) ar[ii].val = -ar[ii].val ;
00612 
00613    return ;
00614 }
00615 
00616 
00617 
00618 typedef struct { int num, nall, depth, *ivox; } basin ;
00619 
00620 #define DBALL 32768
00621 
00622 #define BDEP(i) (baslist[i]->depth)
00623 
00624 #define INIT_BASIN(iv)                                       \
00625  { register int qb=nbtop;                                    \
00626    if( qb >= nball ){                                        \
00627      register int qqb=nball+DBALL,zb ;                       \
00628      baslist = (basin **)realloc((void *)baslist,            \
00629                                  sizeof(basin *)*qqb) ;      \
00630      for( zb=nball ; zb < qqb ; zb++ ) baslist[zb] = NULL ;  \
00631      nball = qqb ;                                           \
00632    }                                                         \
00633    baslist[qb] = (basin *) malloc(sizeof(basin)) ;           \
00634    baslist[qb]->num     = 1 ;                                \
00635    baslist[qb]->nall    = 1 ;                                \
00636    baslist[qb]->depth   = svox[iv].val ;                     \
00637    baslist[qb]->ivox    = (int *)malloc(sizeof(int)) ;       \
00638    baslist[qb]->ivox[0] = (iv) ;                             \
00639    svox[iv].basin       = qb ; nbtop++ ;                     \
00640  }
00641 
00642 #define KILL_BASIN(ib)                                       \
00643  { if( baslist[ib] != NULL ){                                \
00644      free((void *)baslist[ib]->ivox) ;                       \
00645      free((void *)baslist[ib]) ;                             \
00646      baslist[ib] = NULL ; }                                  \
00647  }
00648 
00649 #define ADDTO_BASIN(ib,iv)                                   \
00650  { register basin *bb = baslist[ib] ;                        \
00651    if( bb->num == bb->nall ){                                \
00652      bb->nall = (int)(1.2*bb->nall)+32 ;                     \
00653      bb->ivox = (int *)realloc( (void *)bb->ivox ,           \
00654                                  sizeof(int)*bb->nall ) ;    \
00655    }                                                         \
00656    bb->ivox[bb->num] = (iv) ; bb->num++ ;                    \
00657    svox[iv].basin = (ib) ; }
00658 
00659 #define MERGE_BASIN(ib,ic)                                   \
00660  { register basin *bb = baslist[ib], *cc = baslist[ic] ;     \
00661    int zz = bb->num + cc->num ;                              \
00662    if( bb->nall < zz ){                                      \
00663      bb->nall = zz+1 ;                                       \
00664      bb->ivox = (int *)realloc( (void *)bb->ivox ,           \
00665                                   sizeof(int)*bb->nall ) ;   \
00666    }                                                         \
00667    memcpy( bb->ivox + bb->num ,                              \
00668            cc->ivox , sizeof(int) * cc->num ) ;              \
00669    bb->num = zz ;                                            \
00670    for( zz=0 ; zz < cc->num ; zz++ )                         \
00671      svox[cc->ivox[zz]].basin = (ib) ;                       \
00672    KILL_BASIN(ic) ; }
00673 
00674 
00675 
00676 MRI_IMAGE * mri_watershedize( MRI_IMAGE *sim , float prefac )
00677 {
00678    MRI_IMAGE *tim ;
00679    int ii,jj,kk , pp,qq , nx,ny,nz,nxy,nxyz , nvox ;
00680    int ip,jp,kp , im,jm,km ;
00681    short *sar , *tar ;
00682    shortvox *svox ;
00683    int *isvox , *bcount,*bname ;
00684    int nb,vb,mb,m,mu,mq,mz , bp[6] , hpf ;
00685 
00686    basin **baslist ;
00687    int nball , nbtop ;
00688 
00689 ENTRY("watershedize") ;
00690 
00691    if( sim == NULL || sim->kind != MRI_short ) RETURN(NULL) ;
00692    sar = MRI_SHORT_PTR(sim) ; if( sar == NULL ) RETURN(NULL) ;
00693 
00694    nx = sim->nx; ny = sim->ny; nz = sim->nz; nxy = nx*ny; nxyz = nxy*nz;
00695 
00696    
00697 
00698    for( nvox=0,pp=0 ; pp < nxyz ; pp++ ) if( sar[pp] > 0 ) nvox++ ;
00699    if( nvox <= 999 ) RETURN(NULL) ;
00700 
00701    if( verb ) fprintf(stderr," + mri_watershedize: %d voxels input\n",nvox) ;
00702 
00703    
00704 
00705    svox  = (shortvox *) malloc( sizeof(shortvox)* nvox ) ;
00706    isvox = (int *)      malloc( sizeof(int)     * nxyz ) ;
00707    for( qq=pp=0 ; pp < nxyz ; pp++ ){
00708      if( sar[pp] > 0 ){                  
00709        ii             = pp % nx ;        
00710        jj             = (pp%nxy) / nx ;
00711        kk             = pp / nxy ;
00712        svox[qq].i     = ii ;
00713        svox[qq].j     = jj ;
00714        svox[qq].k     = kk ;
00715        svox[qq].val   = sar[pp] ;        
00716        svox[qq].basin = -1 ;             
00717        qq++ ;
00718        isvox[pp]      = qq ;             
00719      } else {
00720        isvox[pp] = -1 ;                  
00721      }
00722    }
00723 
00724    
00725 
00726    if( verb ) fprintf(stderr," + mri_watershedize: sorting voxels\n") ;
00727 
00728    sort_shortvox( nvox , svox , 1 , 0.00 , 0.02 ) ;
00729 
00730    
00731 
00732    nball    = DBALL ;
00733    nbtop    = 0 ;
00734    baslist  = (basin **) calloc(sizeof(basin *),nball) ;
00735 
00736    INIT_BASIN(0) ;
00737 
00738    hpf      = (int)rint(prefac*svox[0].val) ;      
00739 
00740    
00741 
00742    if( verb ){
00743      fprintf(stderr," + mri_watershedize: basinating voxels\n") ;
00744      fprintf(stderr,"  data range: %d..%d preflood_height=%d\n",
00745              svox[nvox-1].val , svox[0].val , hpf ) ;
00746    }
00747 
00748    for( pp=1 ; pp < nvox ; pp++ ){
00749 
00750      ii = svox[pp].i; jj = svox[pp].j; kk = svox[pp].k;  
00751      ip = ii+1 ; jp = jj+1 ; kp = kk+1 ;                 
00752      im = ii-1 ; jm = jj-1 ; km = kk-1 ;
00753 
00754      if( verb && pp%100000 == 0 ) fprintf(stderr, (pp%1000000)?".":"!") ;
00755 
00756      
00757 
00758 
00759 
00760 
00761 
00762 
00763 
00764 #undef  BASECHECK
00765 #define BASECHECK(a,b,c)                                   \
00766     { qq = isvox[IJK(a,b,c)] ;                             \
00767       if( qq >= 0 && svox[qq].basin >= 0 ){                \
00768         qq = svox[qq].basin ;                              \
00769         for( m=0 ; m < nb && bp[m] != qq ; m++ ) ;         \
00770         if( m == nb ){                                     \
00771           bp[nb] = qq ;                                    \
00772           if( BDEP(qq) > vb ){ mb = nb; vb = BDEP(qq); }   \
00773           nb++ ;                                           \
00774         }                                                  \
00775       }                                                    \
00776     }
00777 
00778      nb = 0 ; vb = -1 ; mb = -1 ;         
00779      if( ip < nx ) BASECHECK(ip,jj,kk) ;  
00780      if( im >= 0 ) BASECHECK(im,jj,kk) ;  
00781      if( jp < ny ) BASECHECK(ii,jp,kk) ;
00782      if( jm >= 0 ) BASECHECK(ii,jm,kk) ;
00783      if( kp < nz ) BASECHECK(ii,jj,kp) ;
00784      if( km >= 0 ) BASECHECK(ii,jj,km) ;
00785 
00786      if( nb == 0 ){  
00787 
00788        INIT_BASIN(pp) ;
00789 
00790      } else {        
00791 
00792        mq = bp[mb] ;                      
00793        ADDTO_BASIN( mq , pp ) ;
00794 
00795                        
00796        if( nb > 1 ){   
00797          mz = svox[pp].val ;          
00798          for( m=0 ; m < nb ; m++ ){
00799            if( m == mb ) continue ;        
00800            mu = bp[m] ;
00801            if( BDEP(mu)-mz <= hpf ){       
00802              MERGE_BASIN(mq,mu) ;
00803            }
00804          }
00805        }
00806      }
00807    } 
00808 
00809    
00810 
00811    free((void *)isvox) ;
00812 
00813    
00814 
00815    for( mu=m=0 ; m < nbtop ; m++ )
00816      if( baslist[m] != NULL ) mu++ ;
00817 
00818    if( verb ) fprintf(stderr,"\n++ %d active basins left, out of %d\n",mu,nbtop) ;
00819 
00820    bcount = (int *) calloc(sizeof(int),mu) ;     
00821    bname  = (int *) calloc(sizeof(int),mu) ;
00822    isvox  = (int *) calloc(sizeof(int),nbtop) ;  
00823 
00824    for( m=ii=0 ; m < nbtop ; m++ )
00825      if( baslist[m] != NULL ){ isvox[m] = ii; bname[ii] = ii; ii++; KILL_BASIN(m); }
00826    free((void *)baslist) ;
00827 
00828    for( pp=0 ; pp < nvox ; pp++ ){
00829      m  = svox[pp].basin ;           
00830      ii = isvox[m] ;                 
00831      svox[pp].basin = ii ;           
00832      bcount[ii]++ ;                  
00833    }
00834 
00835    tim = mri_new_conforming( sim , MRI_short ) ;  
00836    MRI_COPY_AUX(tim,sim) ;
00837    tar = MRI_SHORT_PTR(tim) ;
00838 
00839    for( ii=0 ; ii < mu ; ii++ ) bcount[ii] = -bcount[ii] ;
00840    qsort_intint( mu , bcount , bname ) ;  
00841    for( ii=0 ; ii < mu ; ii++ ) bcount[ii] = -bcount[ii] ;
00842 
00843    if( verb )
00844      fprintf(stderr," + top 9 basin counts: %d %d %d %d %d %d %d %d %d\n",
00845              bcount[0] , bcount[1] , bcount[2] , bcount[3] ,
00846              bcount[4] , bcount[5] , bcount[6] , bcount[7] , bcount[8] ) ;
00847 
00848    for( ii=0 ; ii < mu ; ii++ ) isvox[ii] = ii ;
00849    qsort_intint( mu , bname , isvox ) ;
00850 
00851    for( pp=0 ; pp < nvox ; pp++ ){
00852      m = svox[pp].basin ; jj = isvox[m]+1 ; if( jj > 32767 ) jj = 32767 ;
00853      tar[IJK(svox[pp].i,svox[pp].j,svox[pp].k)] = jj ;
00854    }
00855 
00856    free((void *)isvox) ; free((void *)svox );
00857    free((void *)bcount); free((void *)bname);
00858 
00859    return tim ;
00860 }
00861 
00862 
00863 
00864 static byte * make_peel_mask( int nx, int ny, int nz , byte *mmm, int pdepth )
00865 {
00866    int nxy=nx*ny,nxyz=nxy*nz , ii,jj,kk , ijk , bot,top , pd=pdepth ;
00867    byte *ppp ;
00868 
00869    if( mmm == NULL || pdepth <= 1 ) return NULL ;
00870 
00871    ppp = (byte *)calloc(sizeof(byte),nxyz) ;
00872 
00873    for( kk=0 ; kk < nz ; kk++ ){
00874     for( jj=0 ; jj < ny ; jj++ ){
00875       ijk = jj*nx + kk*nxy ;
00876       for( bot=0 ; bot < nx && !mmm[bot+ijk]; bot++ ) ;
00877       top = bot+pd ; if( top >= nx ) continue ;
00878       for( ii=bot+1 ; ii <= top && mmm[ii+ijk] ; ii++ ) ;
00879       if( ii <= top ){
00880         top = ii; for( ii=bot ; ii <= top ; ii++ ) ppp[ii+ijk] = 1;
00881       }
00882    }}
00883 
00884    for( kk=0 ; kk < nz ; kk++ ){
00885     for( jj=0 ; jj < ny ; jj++ ){
00886       ijk = jj*nx + kk*nxy ;
00887       for( top=nx-1 ; top >= 0 && !mmm[top+ijk]; top-- ) ;
00888       bot = top-pd ; if( bot < 0 ) continue ;
00889       for( ii=top-1 ; ii >= bot && mmm[ii+ijk] ; ii-- ) ;
00890       if( ii >= bot ){
00891         bot = ii; for( ii=top ; ii >= bot ; ii-- ) ppp[ii+ijk] = 1;
00892       }
00893    }}
00894 
00895    for( kk=0 ; kk < nz ; kk++ ){
00896     for( ii=0 ; ii < nx ; ii++ ){
00897       ijk = ii + kk*nxy ;
00898       for( bot=0 ; bot < ny && !mmm[bot*nx+ijk] ; bot++ ) ;
00899       top = bot+pd ;
00900       if( top >= ny ) continue ;
00901       for( jj=bot+1 ; jj <= top && mmm[jj*nx+ijk] ; jj++ ) ;
00902       if( jj <= top ){
00903         top = jj; for( jj=bot ; jj <= top ; jj++ ) ppp[jj*nx+ijk] = 1;
00904       }
00905    }}
00906 
00907    for( kk=0 ; kk < nz ; kk++ ){
00908     for( ii=0 ; ii < nx ; ii++ ){
00909       ijk = ii + kk*nxy ;
00910       for( top=ny-1 ; top >= 0 && !mmm[top*nx+ijk] ; top-- ) ;
00911       bot = top-pd ; if( bot < 0 ) continue ;
00912       for( jj=top-1 ; jj >= bot && mmm[jj*nx+ijk] ; jj-- ) ;
00913       if( jj >= bot ){
00914         bot = jj; for( jj=top ; jj >= bot ; jj-- ) ppp[jj*nx+ijk] = 1;
00915       }
00916    }}
00917 
00918 #if 1
00919     for( jj=0 ; jj < ny ; jj++ ){
00920      for( ii=0 ; ii < nx ; ii++ ){
00921        ijk = ii + jj*nx ;
00922        for( top=nz-1 ; top >= 0 && !mmm[top*nxy+ijk] ; top-- ) ;
00923        bot = top-pd ; if( bot < 0 ) continue ;
00924        for( kk=top-1 ; kk >= bot && mmm[kk*nxy+ijk] ; kk-- ) ;
00925        if( kk >= bot ){
00926          bot = kk; for( kk=top ; kk >= bot ; kk-- ) ppp[kk*nxy+ijk] = 1;
00927        }
00928     }}
00929 #endif
00930 
00931    kk = mask_count(nxyz,ppp) ;
00932    if( kk == 0 ){ free((void *)ppp) ; return NULL ; }
00933    if( verb ) fprintf(stderr," + Initial peel mask has %d voxels\n",kk ) ;
00934    THD_mask_erode( nx,ny,nz, ppp ) ;
00935    THD_mask_clust( nx,ny,nz, ppp ) ;
00936    kk = mask_count(nxyz,ppp) ;
00937    if( kk == 0 ){ free((void *)ppp) ; return NULL ; }
00938    if( verb ) fprintf(stderr," + Final   peel mask has %d voxels\n",kk ) ;
00939 
00940    return ppp ;
00941 }
00942 
00943 
00944 
00945 static void zedit_mask( int nx, int ny, int nz, byte *mmm, int zdepth, int zbot )
00946 {
00947    int nxy=nx*ny,nxyz=nxy*nz , ii,jj,kk , ijk , bot,top ;
00948    int zd=zdepth , zb=zbot , zt , zslab , zz ;
00949    byte *ppp , *zzz ;
00950 
00951    if( mmm == NULL ) return ;
00952 
00953    if( zd < 1  ) zd = 1  ;
00954    if( zb < zd ) zb = zd ;
00955    zslab = 2*zd+1 ;
00956 
00957    for( kk=nz-1 ; kk >= zb ; kk-- ){
00958      jj = mask_count( nxy , mmm+kk*nxy ) ;
00959      if( jj > 0.005*nxy ) break ;
00960    }
00961    zt = kk-zd ; if( zt < zb ) return ;
00962 
00963    ppp = (byte *)calloc(sizeof(byte),nxyz) ;
00964    zzz = (byte *)calloc(sizeof(byte),nxy*zslab) ;
00965 
00966    for( zz=zb ; zz <= zt ; zz++ ){
00967      memcpy( zzz , mmm+(zz-zd)*nxy , nxy*zslab ) ;
00968      THD_mask_erode( nx,ny,zslab, zzz ) ;
00969      THD_mask_clust( nx,ny,zslab, zzz ) ;
00970      memcpy( ppp+zz*nxy , zzz+zd*nxy , nxy ) ;
00971    }
00972    free((void *)zzz) ;
00973    memcpy( mmm+zb*nxy , ppp+zb*nxy , (zt-zb+1)*nxy ) ;
00974    free((void *)ppp) ;
00975    THD_mask_erode( nx,ny,nz, mmm ) ;
00976    THD_mask_clust( nx,ny,nz, mmm ) ;
00977 }
00978 
00979 
00980 
00981 
00982 
00983 
00984 static float ai,bi , aj,bj , ak,bk ;  
00985 
00986 static void ijkwarp( float  i, float  j, float  k ,
00987                      float *x, float *y, float *z  )
00988 {
00989   *x = ai*i + bi ;
00990   *y = aj*j + bj ;
00991   *z = ak*k + bk ;
00992 }
00993 
00994 static void ijk_invwarp(   float x, float y, float z ,  
00995                            float  *i, float  *j, float  *k)
00996 {
00997   *i = ( x - bi ) / ai;
00998   *j = ( y - bj ) / aj;
00999   *k = ( z - bk ) / ak;
01000 }
01001 
01002 
01003 
01004 
01005 
01006 
01007 
01008 
01009 
01010 
01011 
01012 
01013 
01014 
01015 
01016 
01017 
01018 
01019 
01020 
01021 
01022 
01023 void brainnormalize_coord( float  ispat, float  jspat, float  kspat ,
01024                            float *iorig, float *jorig, float *korig ,
01025                            THD_3dim_dataset *origset,
01026                            float *xrai_orig, float *yrai_orig, float *zrai_orig)
01027 {
01028    THD_dataxes * daxes ;
01029    THD_fvec3     fv, fvdic ;
01030    float irai, jrai, krai;
01031    
01032    
01033    ijkwarp(ispat, jspat, kspat , &irai, &jrai, &krai);
01034    
01035 
01036     
01037    
01038       
01039       switch( origset->daxes->xxorient ){
01040         case ORI_R2L_TYPE: *iorig =  irai ; break ;
01041         case ORI_L2R_TYPE: *iorig =  origset->daxes->nxx - irai ; break ;
01042         case ORI_P2A_TYPE: *iorig =  origset->daxes->nxx - jrai  ; break ;
01043         case ORI_A2P_TYPE: *iorig =  jrai ; break ;
01044         case ORI_I2S_TYPE: *iorig =  krai ; break ;
01045         case ORI_S2I_TYPE: *iorig =  origset->daxes->nxx - krai ; break ;
01046       }
01047       switch( origset->daxes->yyorient ){
01048         case ORI_R2L_TYPE: *jorig =  irai ; break ;
01049         case ORI_L2R_TYPE: *jorig =  origset->daxes->nyy - irai  ; break ;
01050         case ORI_P2A_TYPE: *jorig =  origset->daxes->nyy - jrai ; break ;
01051         case ORI_A2P_TYPE: *jorig =  jrai ; break ;
01052         case ORI_I2S_TYPE: *jorig =  krai ; break ;
01053         case ORI_S2I_TYPE: *jorig =  origset->daxes->nyy - krai ; break ;
01054       }
01055       switch( origset->daxes->zzorient ){
01056         case ORI_R2L_TYPE: *korig =  irai ; break ;
01057         case ORI_L2R_TYPE: *korig =  origset->daxes->nzz - irai ; break ;
01058         case ORI_P2A_TYPE: *korig =  origset->daxes->nzz - jrai ; break ;
01059         case ORI_A2P_TYPE: *korig =  jrai ; break ;
01060         case ORI_I2S_TYPE: *korig =  krai ; break ;
01061         case ORI_S2I_TYPE: *korig =  origset->daxes->nzz - krai ; break ;
01062       }
01063       
01064             
01065       
01066       daxes = CURRENT_DAXES(origset) ;
01067 
01068       fv.xyz[0] = daxes->xxorg + *iorig * daxes->xxdel ;  
01069       fv.xyz[1] = daxes->yyorg + *jorig * daxes->yydel ;
01070       fv.xyz[2] = daxes->zzorg + *korig * daxes->zzdel ;
01071 
01072       fvdic = THD_3dmm_to_dicomm(origset,   fv );                
01073       *xrai_orig = fvdic.xyz[0];
01074       *yrai_orig = fvdic.xyz[1]; 
01075       *zrai_orig = fvdic.xyz[2];
01076        
01077    
01078    if (0) {
01079       fprintf(stderr,   "brainnormalize_coord:\n"
01080                      " ijk_spat_rai = [%f %f %f]\n"
01081                      " ijk_orig_rai = [%f %f %f] (in rai order, not native to iset!)\n"
01082                      " ijk_orig     = [%f %f %f] (in native order)\n"
01083                      " XYZ_orig     = [%f %f %f]\n"
01084                      " Origin spat = [%f %f %f]\n", 
01085                      ispat, jspat, kspat,
01086                      irai, jrai, krai ,
01087                      *iorig, *jorig, *korig ,
01088                      *xrai_orig, *yrai_orig, *zrai_orig,
01089                      THD_BN_XORG, THD_BN_YORG, THD_BN_ZORG);   
01090    }      
01091    return;
01092 } 
01093 
01094 
01095 
01096 
01097 
01098 
01099 
01100 
01101 
01102 
01103 
01104 
01105 
01106 MRI_IMAGE * mri_brainormalize( MRI_IMAGE *im, int xxor, int yyor, int zzor, MRI_IMAGE **imout_origp , MRI_IMAGE **imout_edge)
01107 {
01108    MRI_IMAGE *sim , *tim , *bim ;
01109    short *sar , sval ;
01110    int ii,jj,kk,ijk,ktop,kbot , nx,ny,nz,nxy,nxyz ;
01111    float val , icm,jcm,kcm,sum , dx,dy,dz ;
01112    byte *mask , *bar ;
01113    float sim_dx, sim_dy, sim_dz, sim_xo, sim_yo, sim_zo;
01114    int sim_nx, sim_ny, sim_nz;
01115    int *zcount , *hist,*gist , z1,z2,z3 ;
01116    MRI_IMAGE *imout_orig = NULL;
01117    
01118 ENTRY("mri_brainormalize") ;
01119 
01120    if( im == NULL || xxor < 0 || xxor > LAST_ORIENT_TYPE ||
01121                      yyor < 0 || yyor > LAST_ORIENT_TYPE ||
01122                      zzor < 0 || zzor > LAST_ORIENT_TYPE   ) RETURN(NULL) ;
01123 
01124    if( im->nx < 16 || im->ny < 16 || im->nz < 16 ) RETURN(NULL) ;
01125 
01126    val = mri_maxabs(im) ; if( val <= 0.0 ) RETURN(NULL) ;
01127 
01128    
01129 
01130    if( verb ) fprintf(stderr,"++mri_brainormalize: copying input\n") ;
01131 
01132    if( im->kind == MRI_short || im->kind == MRI_byte || im->kind == MRI_rgb )
01133      tim = mri_to_short( 1.0 , im ) ;
01134    else
01135      tim = mri_to_short( 32767.0/val , im ) ;
01136 
01137    
01138 
01139    ii = jj = kk = 0 ;
01140    switch( xxor ){
01141      case ORI_R2L_TYPE: ii =  1 ; break ;
01142      case ORI_L2R_TYPE: ii = -1 ; break ;
01143      case ORI_P2A_TYPE: jj = -1 ; break ;
01144      case ORI_A2P_TYPE: jj =  1 ; break ;
01145      case ORI_I2S_TYPE: kk =  1 ; break ;
01146      case ORI_S2I_TYPE: kk = -1 ; break ;
01147    }
01148    switch( yyor ){
01149      case ORI_R2L_TYPE: ii =  2 ; break ;
01150      case ORI_L2R_TYPE: ii = -2 ; break ;
01151      case ORI_P2A_TYPE: jj = -2 ; break ;
01152      case ORI_A2P_TYPE: jj =  2 ; break ;
01153      case ORI_I2S_TYPE: kk =  2 ; break ;
01154      case ORI_S2I_TYPE: kk = -2 ; break ;
01155    }
01156    switch( zzor ){
01157      case ORI_R2L_TYPE: ii =  3 ; break ;
01158      case ORI_L2R_TYPE: ii = -3 ; break ;
01159      case ORI_P2A_TYPE: jj = -3 ; break ;
01160      case ORI_A2P_TYPE: jj =  3 ; break ;
01161      case ORI_I2S_TYPE: kk =  3 ; break ;
01162      case ORI_S2I_TYPE: kk = -3 ; break ;
01163    }
01164 
01165    if( ii==1 && jj==2 && kk==3 ){      
01166      sim = tim ;
01167    } else {                            
01168      if( verb )
01169        fprintf(stderr,"++mri_brainormalize: flipping to RAI orientation\n") ;
01170      sim = mri_flip3D( ii,jj,kk , tim ) ;
01171      mri_free(tim) ;
01172      if( sim == NULL ) RETURN(NULL) ;  
01173    }
01174 
01175    sar = MRI_SHORT_PTR(sim) ;
01176    if( sar == NULL ){ mri_free(sim); RETURN(NULL); }  
01177 
01178    
01179 
01180    nx = sim->nx ; ny = sim->ny ; nz = sim->nz ; nxy = nx*ny ; nxyz = nxy*nz ;
01181    dx = fabs(sim->dx) ; if( dx == 0.0 ) dx = 1.0 ;
01182    dy = fabs(sim->dy) ; if( dy == 0.0 ) dy = 1.0 ;
01183    dz = fabs(sim->dz) ; if( dz == 0.0 ) dz = 1.0 ;
01184       
01185    
01186    sim_dx = sim->dx; sim_dy = sim->dy; sim_dz = sim->dz;
01187    sim_xo = 0.0; sim_yo = 0.0; sim_zo = 0.0;  
01188    sim_nx = sim->nx; sim_ny = sim->ny; sim_nz = sim->nz; 
01189    
01190    if( verb ) fprintf(stderr,"++mri_brainormalize: making mask\n") ;
01191    mask = mri_short2mask( sim ) ;
01192 
01193    if( mask == NULL ){ mri_free(sim); RETURN(NULL); }
01194 
01195    
01196 
01197    (void) THD_mask_fillin_once( nx,ny,nz , mask , 2 ) ;  
01198           THD_mask_dilate     ( nx,ny,nz , mask , 5 ) ;
01199           THD_mask_dilate     ( nx,ny,nz , mask , 5 ) ;
01200 
01201    kk = mask_count(nxyz,mask) ;
01202    if( verb )
01203      fprintf(stderr,"++mri_brainormalize: filled in mask now has %d voxels\n",kk) ;
01204 
01205    if( kk <= 999 ){ free((void *)mask); mri_free(sim); RETURN(NULL); }
01206 
01207    
01208 
01209 
01210 
01211 
01212 
01213    zcount = (int *)  malloc( sizeof(int) *nz  ) ;  
01214    for( kk=nz-1 ; kk >= 0 ; kk-- ){
01215      zcount[kk] = mask_count( nxy , mask+kk*nxy ) ;
01216    }
01217 
01218 #if 0
01219    if( verb ){
01220      fprintf(stderr,"++mri_brainormalize: zcount from top slice #%d\n",nz-1) ;
01221      for( kk=nz-1 ; kk >= 0 ; kk-- ){
01222        fprintf(stderr," %.3f",((double)(zcount[kk]))/((double)nxy) ) ;
01223        if( (nz-kk)%10 == 0 && kk > 0 ) fprintf(stderr,"\n") ;
01224      }
01225      fprintf(stderr,"\n") ;
01226    }
01227 #endif
01228 
01229    
01230 
01231    z1 = (int)(0.010*nxy) ;
01232    z2 = (int)(0.015*nxy) ;
01233    z3 = (int)(0.020*nxy) ;
01234    for( kk=nz-1 ; kk > 2 ; kk-- )
01235      if( zcount[kk] >= z1 && zcount[kk-1] >= z2 && zcount[kk-2] >= z3 ) break ;
01236 
01237    free((void *)zcount) ;
01238    if( kk <= 2 ){ free((void *)mask); mri_free(sim); RETURN(NULL); }
01239 
01240    
01241 
01242    ktop = kk ;
01243    if( ktop < nz-1 ){
01244      if( verb )
01245        fprintf(stderr,"++mri_brainormalize: top clip above slice %d\n",ktop) ;
01246      memset( mask+(ktop+1)*nxy , 0 , nxy*(nz-1-ktop)*sizeof(byte) ) ;
01247    }
01248 
01249    
01250 
01251    jj = (int)( ktop-THD_BN_ZHEIGHT/dz ) ;
01252    if( jj >= 0 ){
01253      if( verb )
01254        fprintf(stderr,"++mri_brainormalize: bot clip below slice %d\n",jj) ;
01255      memset( mask , 0 , nxy*(jj+1)*sizeof(byte) ) ;
01256    }
01257 
01258    kk = mask_count(nxyz,mask) ;
01259    if( kk <= 999 ){ free((void *)mask); mri_free(sim); RETURN(NULL); }
01260 
01261    
01262 
01263    if( verb )
01264      fprintf(stderr,"++mri_brainormalize: applying mask to image; %d voxels\n",kk) ;
01265    for( ii=0 ; ii < nxyz ; ii++ ) if( !mask[ii] ) sar[ii] = 0 ;
01266 
01267    free((void *)mask) ;  
01268 
01269    
01270 
01271    icm = jcm = kcm = sum = 0.0 ;
01272 #ifndef THD_BN_CMTOP
01273    kbot = 0 ;
01274    ktop = nz-1 ;
01275 #else
01276    kbot = (int)rint( ktop-110.0/dz ); if( kbot < 0 ) kbot = 0;
01277 #endif
01278    for( ijk=kbot*nxy,kk=kbot ; kk <= ktop ; kk++ ){
01279     for( jj=0 ; jj < ny ; jj++ ){
01280      for( ii=0 ; ii < nx ; ii++,ijk++ ){
01281        val = (float)sar[ijk] ;
01282        sum += val ;
01283        icm += val * ii ;
01284        jcm += val * jj ;
01285        kcm += val * kk ;
01286    }}}
01287    if( sum == 0.0 ){ mri_free(sim); RETURN(NULL); }  
01288 
01289    ai = thd_bn_dxyz/dx ; bi = icm/sum - ai*(THD_BN_XCM-THD_BN_XORG)/thd_bn_dxyz ;
01290    aj = thd_bn_dxyz/dy ; bj = jcm/sum - aj*(THD_BN_YCM-THD_BN_YORG)/thd_bn_dxyz ;
01291    ak = thd_bn_dxyz/dz ; bk = kcm/sum - ak*(THD_BN_ZCM-THD_BN_ZORG)/thd_bn_dxyz ;
01292 
01293    if( verb ) fprintf(stderr,"++mri_brainormalize: warping to standard grid\n a = [%f %f %f], b = [%f %f %f]\n", ai, aj, ak, bi, bj, bk) ;
01294 
01295    mri_warp3D_method( MRI_CUBIC ) ;
01296    tim = mri_warp3D( sim , thd_bn_nx,thd_bn_ny,thd_bn_nz , ijkwarp ) ;
01297    mri_free(sim) ;
01298 
01299    tim->dx = tim->dy = tim->dz = thd_bn_dxyz ;
01300    tim->xo = THD_BN_XORG ;
01301    tim->yo = THD_BN_YORG ;
01302    tim->zo = THD_BN_ZORG ;
01303    
01304    nx = tim->nx ; ny = tim->ny ; nz = tim->nz ; nxy = nx*ny ; nxyz = nxy*nz ;
01305    sar = MRI_SHORT_PTR(tim) ;
01306 
01307    
01308 
01309    { clipvec bvec ; float bval , sv ;
01310      bvec = get_octant_clips( tim , 0.40f ) ;
01311      if( bvec.clip_000 > 0.0f ){
01312        for( ijk=kk=0 ; kk < nz ; kk++ ){
01313         for( jj=0 ; jj < ny ; jj++ ){
01314          for( ii=0 ; ii < nx ; ii++,ijk++ ){
01315            bval = pointclip( ii,jj,kk , &bvec ) ; 
01316            sv   = 1000.0f * sar[ijk] / bval ;
01317            sar[ijk] = SHORTIZE(sv) ;
01318          }
01319      }}}
01320    }
01321 
01322    
01323    if( !AFNI_noenv("REMASK") ){
01324      int sbot,stop , nwid , cbot,ctop , ibot,itop ;
01325      float dsum , ws , *wt ;
01326      int pval[128] , wval[128] , npk , tval , nmask,nhalf ;
01327      float pdif ;
01328      short mbot,mtop ;
01329 
01330      
01331 
01332      hist = (int *) calloc(sizeof(int),32768) ;
01333      gist = (int *) calloc(sizeof(int),32768) ;
01334 
01335      memset( hist , 0 , sizeof(int)*32768 ) ;
01336      for( ii=0 ; ii < nxyz ; ii++ ) hist[sar[ii]]++ ;
01337      for( sbot=1 ; sbot < 32768 && hist[sbot]==0 ; sbot++ ) ; 
01338      if( sbot == 32768 ) goto Remask_Done ;
01339      for( stop=32768-1 ; stop > sbot && hist[stop]==0 ; stop-- ) ; 
01340      if( stop == sbot ) goto Remask_Done ;
01341 
01342      
01343      
01344      nmask = 0 ;
01345      for( ii=sbot ; ii <= stop ; ii++ ) nmask += hist[ii] ;
01346      nhalf = nmask / 2 ; nmask = 0 ;
01347      for( ii=sbot ; ii <= stop && nmask < nhalf ; ii++ ) nmask += hist[ii] ;
01348      cbot = 0.40 * ii ;
01349      ctop = 1.60 * ii ;
01350 
01351 #if 0
01352      
01353 
01354      nwid = rint(0.10*cbot) ;
01355 
01356      if( nwid <= 0 ){
01357        memcpy( gist , hist , sizeof(int)*32768 ) ;
01358      } else {
01359        ws = 0.0f ;
01360        wt = (float *)malloc(sizeof(float)*(2*nwid+1)) ;
01361        for( ii=0 ; ii <= 2*nwid ; ii++ ){
01362          wt[ii] = nwid-abs(nwid-ii) + 0.5f ;
01363          ws += wt[ii] ;
01364        }
01365        for( ii=0 ; ii <= 2*nwid ; ii++ ) wt[ii] /= ws ;
01366        for( jj=cbot ; jj <= ctop ; jj++ ){
01367          ibot = jj-nwid ; if( ibot < sbot ) ibot = sbot ;
01368          itop = jj+nwid ; if( itop > stop ) itop = stop ;
01369          ws = 0.0 ;
01370          for( ii=ibot ; ii <= itop ; ii++ )
01371            ws += wt[nwid-jj+ii] * hist[ii] ;
01372          gist[jj] = rint(ws) ;
01373        }
01374        free(wt) ;
01375      }
01376 
01377      
01378 
01379      npk = 0 ;
01380      for( ii=cbot+2 ; ii <= ctop-2 ; ii++ ){
01381        if( gist[ii] > gist[ii-1] &&
01382            gist[ii] > gist[ii-2] &&
01383            gist[ii] > gist[ii+1] &&
01384            gist[ii] > gist[ii+2]   ){
01385              pval[npk]=ii; wval[npk++] = gist[ii];
01386            }
01387 
01388        else if( gist[ii] == gist[ii+1] &&   
01389                 gist[ii] >  gist[ii-1] &&
01390                 gist[ii] >  gist[ii-2] &&
01391                 gist[ii] >  gist[ii+2]   ){
01392                   pval[npk]=ii+0.5; wval[npk++] = gist[ii];
01393                 }
01394 
01395        else if( gist[ii] == gist[ii+1] &&   
01396                 gist[ii] == gist[ii-1] &&
01397                 gist[ii] >  gist[ii-2] &&
01398                 gist[ii] >  gist[ii+2]   ){
01399                   pval[npk]=ii; wval[npk++] = gist[ii];
01400                 }
01401      }
01402 
01403      if( npk > 2 ){  
01404        float pval_top, pval_2nd, wval_top, wval_2nd , www; int iii,itop ;
01405        www = wval[0] ; iii = 0 ;
01406        for( ii=1 ; ii < npk ; ii++ ){
01407          if( wval[ii] > www ){ www = wval[ii] ; iii = ii ; }
01408        }
01409        pval_top = pval[iii] ; wval_top = www ; itop = iii ;
01410        www = -1 ; iii = -1 ;
01411        for( ii=0 ; ii < npk ; ii++ ){
01412          if( ii != itop && wval[ii] > www ){ www = wval[ii] ; iii = ii ; }
01413        }
01414        pval_2nd = pval[iii] ; wval_2nd = www ;
01415 
01416        
01417 
01418        if( pval_top < pval_2nd ){
01419          pval[0] = pval_top ; wval[0] = wval_top ;
01420          pval[1] = pval_2nd ; wval[1] = wval_2nd ;
01421        } else {
01422          pval[0] = pval_2nd ; wval[0] = wval_2nd ;
01423          pval[1] = pval_top ; wval[1] = wval_top ;
01424        }
01425        npk = 2 ;
01426      }
01427 
01428      if( npk == 2 ){
01429        jj = gist[pval[0]] ; tval = pval[0] ;
01430        for( ii=pval[0]+1 ; ii < pval[1] ; ii++ ){
01431          if( gist[ii] < jj ){ tval = ii ; jj = gist[ii] ; }
01432        }
01433 
01434        pdif = 1.5f * (tval-pval[0]) ;
01435        if( pdif < pval[1]-pval[0] ) pdif = pval[1]-pval[0] ;
01436        mbot = (short)(pval[0]-pdif) ;
01437        if( mbot < cbot ) mbot = cbot ;
01438 
01439        pdif = 1.5f * (pval[1]-tval) ;
01440        if( pdif < pval[1]-pval[0] ) pdif = pval[1]-pval[0] ;
01441        mtop = (short)(pval[1]+pdif) ;
01442        if( mtop > ctop ) mtop = ctop ;
01443      } else {
01444        mbot = cbot ; mtop = ctop ;
01445      }
01446      mtop = stop+1 ;  
01447 #endif
01448 
01449      mbot = cbot ; mtop = 32767 ;
01450 
01451      if( verb )
01452       fprintf(stderr,"++mri_brainormalize: masking standard image %d..%d\n",mbot,mtop) ;
01453 
01454      mask = (byte *) malloc( sizeof(byte)*nxyz ) ;
01455      for( ii=0 ; ii < nxyz ; ii++ )
01456        mask[ii] = (sar[ii] > mbot) && (sar[ii] < mtop) ;
01457 
01458      THD_mask_erode( nx,ny,nz, mask ) ;
01459      THD_mask_clust( nx,ny,nz, mask ) ;
01460      for( ii=0 ; ii < nxyz ; ii++ ) mask[ii] = !mask[ii] ;
01461      THD_mask_clust( nx,ny,nz, mask ) ;
01462      for( ii=0 ; ii < nxyz ; ii++ ) mask[ii] = !mask[ii] ;
01463 
01464      for( ii=0 ; ii < nxyz ; ii++ ) if( !mask[ii] ) sar[ii] = 0 ;
01465      free((void *)mask) ;
01466 
01467    Remask_Done:
01468      free((void *)hist) ; free((void *)gist) ;
01469 
01470    }
01471 #if 0
01472    else
01473 #endif
01474    {
01475      
01476 
01477      hist = (int *) calloc(sizeof(int),32768) ;
01478      for( ii=0 ; ii < nxyz ; ii++ ) hist[sar[ii]]++ ;
01479      for( ii=kk=0 ; ii < 32767 ; ii++ ) kk += hist[ii] ;
01480      kk = (int)(0.01*kk) ; ktop = 0 ;
01481      for( jj=0,ii=32767 ; ii > 0 && jj < kk ; ii-- ){
01482        jj += hist[ii] ; if( hist[ii] > 0 && ktop == 0 ) ktop = ii ;
01483      }
01484      jj = ii ;
01485      if( verb ) fprintf(stderr," + 99%% clipping at %d (from %d)\n",jj,ktop) ;
01486      for( ii=0 ; ii < nxyz ; ii++ ) if( sar[ii] > jj ) sar[ii] = jj ;
01487 
01488      free((void *)hist) ;
01489    }
01490 
01491    
01492 
01493    if( AFNI_yesenv("DISTIZE") ){
01494      byte *ccc = (byte *)calloc(sizeof(byte),nxyz);
01495      short *ddd ;
01496      int kbot=(int)rint(0.45*nz) , ktop=(int)rint(0.65*nz) ,
01497          jbot=(int)rint(0.30*ny) , jtop=(int)rint(0.70*ny) ,
01498          ibot=(int)rint(0.30*nx) , itop=(int)rint(0.70*nx)  ;
01499 
01500      mask = (byte *)malloc( sizeof(byte)*nxyz ) ;
01501      for( ii=0 ; ii < nxyz ; ii++ ) mask[ii] = (sar[ii] > 0) ;
01502      for( kk=kbot ; kk <= ktop ; kk++ ){
01503       for( jj=jbot ; jj <= jtop ; jj++ ){
01504        for( ii=ibot ; ii <= itop ; ii++ ){
01505          ijk = ii + jj*nx + kk*nxy ;
01506          ccc[ijk] = mask[ijk] ;
01507      }}}
01508      if( verb ) fprintf(stderr," + distizing\n") ;
01509      ddd = THD_mask_distize( nx,ny,nz , mask , ccc ) ;
01510      if( ddd != NULL ){
01511        int id,jd,kd , ijk , dijk ; float ff ;
01512        for( ijk=0 ; ijk < nxyz ; ijk++ ){
01513          if( ddd[ijk] > 0 ){
01514            ii = ijk % nx ; jj = (ijk%nxy)/nx ; kk = ijk / nxy ;
01515                 if( ii < ibot ) id = ibot-ii ;
01516            else if( ii > itop ) id = ii-itop ; else id = 0 ;
01517                 if( jj < jbot ) jd = jbot-jj ;
01518            else if( jj > jtop ) jd = jj-jtop ; else jd = 0 ;
01519                 if( kk < kbot ) kd = kbot-kk ;
01520            else if( kk > ktop ) kd = kk-ktop ; else kd = 0 ;
01521            dijk = id+jd+kd+1 ;
01522            ff = (100.0f * ddd[ijk]) / (float)dijk - 98.9f ;
01523            if( ff > 255.0f ) ff = 255.0f ;
01524            sar[ijk] = (short)ff ;
01525          } else {
01526            sar[ijk] = 0 ;
01527          }
01528        }
01529        free((void *)ddd) ;
01530      }
01531      free((void *)mask); free((void *)ccc);
01532    }
01533 
01534    
01535    if (imout_origp) {
01536       mri_warp3D_method( MRI_NN ) ;
01537       if (1 && verb) fprintf(stderr,"thd_brainormalize (ZSS):\n n: %d %d %d\n d: %f %f %f\n o: %f %f %f\n ", sim_nx, sim_ny, sim_nz, sim_dx, sim_dy, sim_dz, sim_xo, sim_yo, sim_zo);
01538       imout_orig = mri_warp3D( tim, sim_nx, sim_ny, sim_nz, ijk_invwarp );
01539       imout_orig->dx = sim_dx; imout_orig->dy = sim_dy; imout_orig->dz = sim_dz; 
01540       imout_orig->xo = sim_xo; imout_orig->yo = sim_yo; imout_orig->zo = sim_zo; 
01541       *imout_origp = imout_orig;
01542    }
01543    
01544    if (imout_edge) { 
01545       *imout_edge = NULL;
01546    }
01547       
01548    
01549 
01550    bim = mri_new_conforming( tim , MRI_byte ) ;
01551    MRI_COPY_AUX(bim,tim) ;
01552    bar = MRI_BYTE_PTR(bim) ;
01553 
01554    jj = 0 ;
01555    for( ii=0 ; ii < nxyz ; ii++ ) if( sar[ii] > jj ) jj = sar[ii] ;
01556 
01557    if( jj > 255 ){
01558      float fac = 255.0 / jj ;
01559      if( verb ) fprintf(stderr," + scaling by fac=%g\n",fac) ;
01560      for( ii=0 ; ii < nxyz ; ii++ ) bar[ii] = (byte)(fac*sar[ii]+0.49) ;
01561    } else {
01562      for( ii=0 ; ii < nxyz ; ii++ ) bar[ii] = (byte)sar[ii] ;
01563    }
01564    mri_free(tim) ;
01565 
01566    
01567 
01568    RETURN(bim) ;
01569 }