void mri_invertcontrast_inplace( MRI_IMAGE *im , float uperc , byte *mask ) { byte *mmm=NULL ; int nvox , nhist , ii ; float *hist=NULL , *imar , ucut ; if( im == NULL || im->kind != MRI_float ) return ; if( uperc < 90.0f ) uperc = 90.0f ; else if( uperc > 100.0f ) uperc = 100.0f ; mmm = mask ; if( mmm == NULL ) mmm = mri_automask_image(im) ; nvox = im->nvox ; hist = (float *)malloc(sizeof(float)*nvox) ; imar = MRI_FLOAT_PTR(im) ; for( nhist=ii=0 ; ii < nvox ; ii++ ){ if( mmm[ii] ) hist[nhist++] = imar[ii]; } if( nhist < 100 ){ if( mmm != mask ) free(mmm) ; free(hist) ; return ; } qsort_float(nhist,hist) ; ii = (int)rintf(nhist*uperc*0.01f) ; ucut = hist[ii] ; free(hist) ; for( ii=0 ; ii < nvox ; ii++ ){ if( mmm[ii] ) imar[ii] = ucut - imar[ii] ; if( !mmm[ii] || imar[ii] < 0.0f ) imar[ii] = 0.0f ; } if( mmm != mask ) free(mmm) ; return ; }
float mri_quantile( MRI_IMAGE *im , float alpha ) { int ii , nvox ; float fi , quan ; ENTRY("mri_quantile") ; /*** sanity checks ***/ if( im == NULL ) RETURN( 0.0 ); if( alpha <= 0.0 ) RETURN( (float) mri_min(im) ); if( alpha >= 1.0 ) RETURN( (float) mri_max(im) ); nvox = im->nvox ; switch( im->kind ){ /*** create a float image copy of the data, sort it, then interpolate the percentage points ***/ default:{ MRI_IMAGE *inim ; float *far ; inim = mri_to_float( im ) ; far = MRI_FLOAT_PTR(inim) ; qsort_float( nvox , far ) ; fi = alpha * nvox ; ii = (int) fi ; if( ii >= nvox ) ii = nvox-1 ; fi = fi - ii ; quan = (1.0-fi) * far[ii] + fi * far[ii+1] ; mri_free( inim ) ; } break ; /*** create a short image copy of the data, sort it, then interpolate the percentage points ***/ case MRI_short: case MRI_byte:{ MRI_IMAGE *inim ; short *sar ; inim = mri_to_short( 1.0 , im ) ; sar = MRI_SHORT_PTR(inim) ; qsort_short( nvox , sar ) ; fi = alpha * nvox ; ii = (int) fi ; if( ii >= nvox ) ii = nvox-1 ; fi = fi - ii ; quan = (1.0-fi) * sar[ii] + fi * sar[ii+1] ; mri_free( inim ) ; } break ; } RETURN( quan ); }
void mri_percents( MRI_IMAGE *im , int nper , float per[] ) { register int pp , ii , nvox ; register float fi , frac ; /*** sanity checks ***/ if( im == NULL || per == NULL || nper < 2 ) return ; nvox = im->nvox ; frac = nvox / ((float) nper) ; switch( im->kind ){ /*** create a float image copy of the data, sort it, then interpolate the percentage points ***/ default:{ MRI_IMAGE *inim ; float *far ; inim = mri_to_float( im ) ; far = MRI_FLOAT_PTR(inim) ; qsort_float( nvox , far ) ; per[0] = far[0] ; for( pp=1 ; pp < nper ; pp++ ){ fi = frac * pp ; ii = fi ; fi = fi - ii ; per[pp] = (1.0-fi) * far[ii] + fi * far[ii+1] ; } per[nper] = far[nvox-1] ; mri_free( inim ) ; } break ; /*** create a short image copy of the data, sort it, then interpolate the percentage points ***/ case MRI_short: case MRI_byte:{ MRI_IMAGE *inim ; short *sar ; inim = mri_to_short( 1.0 , im ) ; sar = MRI_SHORT_PTR(inim) ; qsort_short( nvox , sar ) ; per[0] = sar[0] ; for( pp=1 ; pp < nper ; pp++ ){ fi = frac * pp ; ii = fi ; fi = fi - ii ; per[pp] = (1.0-fi) * sar[ii] + fi * sar[ii+1] ; } per[nper] = sar[nvox-1] ; mri_free( inim ) ; } } return ; }
void qsort_float_rev( int n , float *a ) { register int ii ; if( n < 2 || a == NULL ) return ; for( ii=0 ; ii < n ; ii++ ) a[ii] = -a[ii] ; qsort_float(n,a) ; for( ii=0 ; ii < n ; ii++ ) a[ii] = -a[ii] ; return ; }
float osfilt_proj( int n , float *ar ) /* 07 Dec 2007 */ { int ii , n2 ; float v=0.0f , d=0.0f ; qsort_float( n , ar ) ; n2 = n/2 ; for( ii=0 ; ii < n2 ; ii++ ){ v += (ii+1)*(ar[ii]+ar[n-1-ii]) ; d += 2*(ii+1) ; } v += (n2+1)*ar[n2] ; d += (n2+1) ; return (v/d) ; }
float_pair mri_twoquantiles( MRI_IMAGE *im, float alpha, float beta ) { int ii , nvox ; float fi ; float_pair qt = {0.0f,0.0f} ; float qalph=WAY_BIG,qbeta=WAY_BIG ; ENTRY("mri_twoquantiles") ; /*** sanity checks ***/ if( im == NULL ) RETURN( qt ); if( alpha == beta ){ qt.a = qt.b = mri_quantile(im,alpha) ; RETURN( qt ); } if( alpha <= 0.0f ) qalph = (float) mri_min(im) ; else if( alpha >= 1.0f ) qalph = (float) mri_max(im) ; if( beta <= 0.0f ) qbeta = (float) mri_min(im) ; else if( beta >= 1.0f ) qbeta = (float) mri_max(im) ; if( qalph != WAY_BIG && qbeta != WAY_BIG ){ qt.a = qalph; qt.b = qbeta; RETURN(qt); } nvox = im->nvox ; switch( im->kind ){ /*** create a float image copy of the data, sort it, then interpolate the percentage points ***/ default:{ MRI_IMAGE *inim ; float *far ; inim = mri_to_float( im ) ; far = MRI_FLOAT_PTR(inim) ; qsort_float( nvox , far ) ; if( alpha > 0.0f && alpha < 1.0f ){ fi = alpha * nvox ; ii = (int) fi ; if( ii >= nvox ) ii = nvox-1 ; fi = fi - ii ; qalph = (1.0-fi) * far[ii] + fi * far[ii+1] ; } if( beta > 0.0f && beta < 1.0f ){ fi = beta * nvox ; ii = (int) fi ; if( ii >= nvox ) ii = nvox-1 ; fi = fi - ii ; qbeta = (1.0-fi) * far[ii] + fi * far[ii+1] ; } mri_free( inim ) ; } break ; /*** create a short image copy of the data, sort it, then interpolate the percentage points ***/ case MRI_short: case MRI_byte:{ MRI_IMAGE *inim ; short *sar ; inim = mri_to_short( 1.0 , im ) ; sar = MRI_SHORT_PTR(inim) ; qsort_short( nvox , sar ) ; if( alpha > 0.0f && alpha < 1.0f ){ fi = alpha * nvox ; ii = (int) fi ; if( ii >= nvox ) ii = nvox-1 ; fi = fi - ii ; qalph = (1.0-fi) * sar[ii] + fi * sar[ii+1] ; } if( beta > 0.0f && beta < 1.0f ){ fi = beta * nvox ; ii = (int) fi ; if( ii >= nvox ) ii = nvox-1 ; fi = fi - ii ; qbeta = (1.0-fi) * sar[ii] + fi * sar[ii+1] ; } mri_free( inim ) ; } break ; } qt.a = qalph; qt.b = qbeta; RETURN(qt); }
static float orfilt( int n , float *ar ) { int nby2 ; switch( n ) { /* fast cases */ case 1: return ar[0] ; case 2: return 0.5f*(ar[0]+ar[1]) ; case 3: qsort3_float(ar) ; return OFILT(1) ; case 5: qsort5_float(ar) ; return OFILT(2) ; case 7: qsort7_float(ar) ; return OFILT(3) ; case 9: qsort9_float(ar) ; return OFILT(4) ; case 11: qsort11_float(ar) ; return OFILT(5) ; case 13: qsort13_float(ar) ; return OFILT(6) ; case 15: qsort15_float(ar) ; return OFILT(7) ; case 17: qsort17_float(ar) ; return OFILT(8) ; case 19: qsort19_float(ar) ; return OFILT(9) ; case 21: qsort21_float(ar) ; return OFILT(10) ; case 25: qsort25_float(ar) ; return OFILT(12) ; case 27: qsort27_float(ar) ; return OFILT(13) ; case 4: qsort4_float(ar) ; return EFILT(2) ; case 6: qsort6_float(ar) ; return EFILT(3) ; case 8: qsort8_float(ar) ; return EFILT(4) ; case 10: qsort10_float(ar) ; return EFILT(5) ; case 12: qsort12_float(ar) ; return EFILT(6) ; case 14: qsort14_float(ar) ; return EFILT(7) ; case 16: qsort16_float(ar) ; return EFILT(8) ; case 18: qsort18_float(ar) ; return EFILT(9) ; case 20: qsort20_float(ar) ; return EFILT(10) ; } /* general case for n not in above list -- will be slower */ qsort_float(n,ar) ; nby2 = n/2 ; return (n%2==0) ? EFILT(nby2) : OFILT(nby2) ; }
MRI_IMAGE * mri_local_percmean( MRI_IMAGE *fim , float vrad , float p1, float p2 ) { MRI_IMAGE *aim , *bim , *cim , *dim ; float *aar , *bar , *car , *dar ; byte *ams , *bms ; MCW_cluster *nbhd ; int ii , nx,ny,nz,nxy,nxyz ; float vbot=0.0f ; ENTRY("mri_local_percmean") ; if( p1 > p2 ){ float val = p1; p1 = p2; p2 = val; } if( fim == NULL || vrad < 4.0f || p1 < 0.0f || p2 > 100.0f ) RETURN(NULL) ; /* just one percentile? */ if( p1 == p2 ) RETURN( mri_local_percentile(fim,vrad,p1) ) ; if( verb ) fprintf(stderr,"A") ; /* create automask of copy of input image */ aim = mri_to_float(fim) ; aar = MRI_FLOAT_PTR(aim) ; ams = mri_automask_image(aim) ; if( ams == NULL ){ mri_free(aim) ; RETURN(NULL) ; } /* apply automask to copy of input image */ for( ii=0 ; ii < aim->nvox ; ii++ ) if( ams[ii] == 0 ) aar[ii] = 0.0f ; free(ams) ; /* shrink image by 2 for speed */ if( verb ) fprintf(stderr,"D") ; bim = mri_double_down(aim) ; bar = MRI_FLOAT_PTR(bim) ; mri_free(aim) ; bms = (byte *)malloc(sizeof(byte)*bim->nvox) ; for( ii=0 ; ii < bim->nvox ; ii++ ) bms[ii] = (bar[ii] != 0.0f) ; if( !USE_ALL_VALS ){ vbot = 0.00666f * mri_max(bim) ; } /* create neighborhood mask (1/2 radius in the shrunken copy) */ nbhd = MCW_spheremask( 1.0f,1.0f,1.0f , 0.5f*vrad+0.001f ) ; cim = mri_new_conforming(bim,MRI_float) ; car = MRI_FLOAT_PTR(cim) ; SetSearchAboutMaskedVoxel(1) ; nx = bim->nx ; ny = bim->ny ; nz = bim->nz ; nxy = nx*ny ; nxyz = nxy*nz ; /* for each output voxel, extract neighborhood array, sort it, average desired range. Since this is the slowest part of the code, it is now OpenMP-ized. */ #ifndef USE_OMP /* old serial code */ { int vvv,vstep , ii,jj,kk , nbar_num ; float val , *nbar ; nbar = (float *)malloc(sizeof(float)*nbhd->num_pt) ; vstep = (verb) ? nxyz/50 : 0 ; if( vstep ) fprintf(stderr,"\n + Voxel loop: ") ; for( vvv=kk=0 ; kk < nz ; kk++ ){ for( jj=0 ; jj < ny ; jj++ ){ for( ii=0 ; ii < nx ; ii++,vvv++ ){ if( vstep && vvv%vstep == vstep-1 ) vstep_print() ; nbar_num = mri_get_nbhd_array( bim,bms , ii,jj,kk , nbhd,nbar ) ; if( nbar_num < 1 ){ /* no data */ val = 0.0f ; } else { qsort_float(nbar_num,nbar) ; /* sort */ if( nbar_num == 1 ){ /* stoopid case */ val = nbar[0] ; } else { /* average values from p1 to p2 percentiles */ int q1,q2,qq , qb; if( !USE_ALL_VALS ){ /* Ignore tiny values [17 May 2016] */ for( qb=0 ; qb < nbar_num && nbar[qb] <= vbot ; qb++ ) ; /*nada*/ if( qb == nbar_num ){ val = 0.0f ; } else if( qb == nbar_num-1 ){ val = nbar[qb] ; } else { q1 = (int)( 0.01f*p1*(nbar_num-1-qb)) + qb; if( q1 > nbar_num-1 ) q1 = nbar_num-1; q2 = (int)( 0.01f*p2*(nbar_num-1-qb)) + qb; if( q2 > nbar_num-1 ) q2 = nbar_num-1; for( qq=q1,val=0.0f ; qq <= q2 ; qq++ ) val += nbar[qq] ; val /= (q2-q1+1.0f) ; } } else { /* Use all values [the olden way] */ q1 = (int)( 0.01f*p1*(nbar_num-1) ) ; /* p1 location */ q2 = (int)( 0.01f*p2*(nbar_num-1) ) ; /* p2 location */ for( qq=q1,val=0.0f ; qq <= q2 ; qq++ ) val += nbar[qq] ; val /= (q2-q1+1.0f) ; } } } FSUB(car,ii,jj,kk,nx,nxy) = val ; }}} free(nbar) ; if( vstep ) fprintf(stderr,"!") ; } #else /* new parallel code [06 Mar 2013 = Snowquestration Day!] */ AFNI_OMP_START ; if( verb ) fprintf(stderr,"V") ; #pragma omp parallel { int vvv , ii,jj,kk,qq , nbar_num ; float val , *nbar ; nbar = (float *)malloc(sizeof(float)*nbhd->num_pt) ; #pragma omp for for( vvv=0 ; vvv < nxyz ; vvv++ ){ ii = vvv % nx ; kk = vvv / nxy ; jj = (vvv-kk*nxy) / nx ; nbar_num = mri_get_nbhd_array( bim,bms , ii,jj,kk , nbhd,nbar ) ; if( nbar_num < 1 ){ /* no data */ val = 0.0f ; } else { qsort_float(nbar_num,nbar) ; /* sort */ if( nbar_num == 1 ){ /* stoopid case */ val = nbar[0] ; } else { /* average values from p1 to p2 percentiles */ int q1,q2,qq , qb; if( !USE_ALL_VALS ){ /* Ignore tiny values [17 May 2016] */ for( qb=0 ; qb < nbar_num && nbar[qb] <= vbot ; qb++ ) ; /*nada*/ if( qb == nbar_num ){ val = 0.0f ; } else if( qb == nbar_num-1 ){ val = nbar[qb] ; } else { q1 = (int)( 0.01f*p1*(nbar_num-1-qb)) + qb; if( q1 > nbar_num-1 ) q1 = nbar_num-1; q2 = (int)( 0.01f*p2*(nbar_num-1-qb)) + qb; if( q2 > nbar_num-1 ) q2 = nbar_num-1; for( qq=q1,val=0.0f ; qq <= q2 ; qq++ ) val += nbar[qq] ; val /= (q2-q1+1.0f) ; } } else { /* Use all values [the olden way] */ q1 = (int)( 0.01f*p1*(nbar_num-1) ) ; /* p1 location */ q2 = (int)( 0.01f*p2*(nbar_num-1) ) ; /* p2 location */ for( qq=q1,val=0.0f ; qq <= q2 ; qq++ ) val += nbar[qq] ; val /= (q2-q1+1.0f) ; } if( verb && vvv%66666==0 ) fprintf(stderr,".") ; } } car[vvv] = val ; } free(nbar) ; } /* end parallel code */ AFNI_OMP_END ; #endif mri_free(bim) ; free(bms) ; KILL_CLUSTER(nbhd) ; /* expand output image back to original size */ dim = mri_double_up( cim , fim->nx%2 , fim->ny%2 , fim->nz%2 ) ; if( verb ) fprintf(stderr,"U") ; mri_free(cim) ; RETURN(dim) ; }
MRI_IMAGE * mri_local_percentile( MRI_IMAGE *fim , float vrad , float perc ) { MRI_IMAGE *aim , *bim , *cim , *dim ; float *aar , *bar , *car , *dar , *nbar ; byte *ams , *bms ; MCW_cluster *nbhd ; int ii,jj,kk , nbar_num , nx,ny,nz,nxy ; float fq,val ; int qq,qp,qm ; ENTRY("mri_local_percentile") ; if( fim == NULL || vrad < 4.0f || perc < 0.0f || perc > 100.0f ) RETURN(NULL) ; /* compute automask */ aim = mri_to_float(fim) ; aar = MRI_FLOAT_PTR(aim) ; ams = mri_automask_image(aim) ; if( ams == NULL ){ mri_free(aim) ; RETURN(NULL) ; } /* apply automask to image copy */ for( ii=0 ; ii < aim->nvox ; ii++ ) if( ams[ii] == 0 ) aar[ii] = 0.0f ; free(ams) ; /* shrink image by 2 for speedup */ bim = mri_double_down(aim) ; bar = MRI_FLOAT_PTR(bim) ; mri_free(aim) ; bms = (byte *)malloc(sizeof(byte)*bim->nvox) ; for( ii=0 ; ii < bim->nvox ; ii++ ) bms[ii] = (bar[ii] != 0.0f) ; /* neighborhood has 1/2 radius in the shrunken volume */ nbhd = MCW_spheremask( 1.0f,1.0f,1.0f , 0.5f*vrad+0.001f ) ; nbar = (float *)malloc(sizeof(float)*nbhd->num_pt) ; cim = mri_new_conforming(bim,MRI_float) ; car = MRI_FLOAT_PTR(cim) ; SetSearchAboutMaskedVoxel(1) ; nx = bim->nx ; ny = bim->ny ; nz = bim->nz ; nxy = nx*ny ; /* for each voxel: extract neighborhood array, sort it, get result */ for( kk=0 ; kk < nz ; kk++ ){ for( jj=0 ; jj < ny ; jj++ ){ for( ii=0 ; ii < nx ; ii++ ){ nbar_num = mri_get_nbhd_array( bim,bms , ii,jj,kk , nbhd,nbar ) ; if( nbar_num < 1 ){ val = 0.0f ; } else { qsort_float(nbar_num,nbar) ; if( nbar_num == 1 || perc <= 0.000001f ){ val = nbar[0] ; } else if( perc >= 99.9999f ){ val = nbar[nbar_num-1] ; } else { fq = (0.01f*perc)*nbar_num ; qq = (int)fq ; qp = qq+1 ; if( qp == nbar_num ) qp = qq ; qm = qq-1 ; if( qm < 0 ) qm = 0 ; val = 0.3333333f * ( nbar[qm] + nbar[qq] + nbar[qp] ) ; } } FSUB(car,ii,jj,kk,nx,nxy) = val ; }}} mri_free(bim) ; free(bms) ; free(nbar) ; KILL_CLUSTER(nbhd) ; dim = mri_double_up( cim , fim->nx%2 , fim->ny%2 , fim->nz%2 ) ; mri_free(cim) ; RETURN(dim) ; }