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) ; }
THD_3dim_dataset * THD_localhistog( int nsar , THD_3dim_dataset **insar , int numval , int *rlist , MCW_cluster *nbhd , int do_prob , int verb ) { THD_3dim_dataset *outset=NULL , *inset ; int nvox=DSET_NVOX(insar[0]) ; int ids, iv, bb, nnpt=nbhd->num_pt ; MRI_IMAGE *bbim ; int btyp ; float **outar , **listar ; ENTRY("THD_localhistog") ; /*---- create output dataset ----*/ outset = EDIT_empty_copy(insar[0]) ; EDIT_dset_items( outset , ADN_nvals , numval , ADN_datum_all , MRI_float , ADN_nsl , 0 , ADN_brick_fac , NULL , ADN_none ) ; outar = (float **)malloc(sizeof(float *)*numval) ; for( bb=0 ; bb < numval ; bb++ ){ EDIT_substitute_brick( outset , bb , MRI_float , NULL ) ; outar[bb] = DSET_BRICK_ARRAY(outset,bb) ; } /*---- make mapping between values and arrays to get those values ----*/ listar = (float **)malloc(sizeof(float *)*TWO16) ; for( bb=0 ; bb < TWO16 ; bb++ ) listar[bb] = outar[0] ; for( bb=1 ; bb < numval ; bb++ ){ listar[ rlist[bb] + TWO15 ] = outar[bb] ; } /*----------- loop over datasets, add in counts for all voxels -----------*/ for( ids=0 ; ids < nsar ; ids++ ){ /* dataset loop */ inset = insar[ids] ; DSET_load(inset) ; for( iv=0 ; iv < DSET_NVALS(inset) ; iv++ ){ /* sub-brick loop */ if( verb ) fprintf(stderr,".") ; bbim = DSET_BRICK(inset,iv) ; btyp = bbim->kind ; if( nnpt == 1 ){ /* only 1 voxel in nbhd */ int qq,ii,jj,kk,ib,nb ; switch( bbim->kind ){ case MRI_short:{ short *sar = MRI_SHORT_PTR(bbim) ; for( qq=0 ; qq < nvox ; qq++ ) listar[sar[qq]+TWO15][qq]++ ; } break ; case MRI_byte:{ byte *bar = MRI_BYTE_PTR(bbim) ; for( qq=0 ; qq < nvox ; qq++ ) listar[bar[qq]+TWO15][qq]++ ; } break ; case MRI_float:{ float *far = MRI_FLOAT_PTR(bbim) ; short ss ; for( qq=0 ; qq < nvox ; qq++ ){ ss = SHORTIZE(far[qq]); listar[ss+TWO15][qq]++; } } break ; } } else { /* multiple voxels in nbhd */ AFNI_OMP_START ; #pragma omp parallel { int qq,ii,jj,kk,ib,nb ; void *nar ; short *sar,ss ; byte *bar ; float *far ; nar = malloc(sizeof(float)*nnpt) ; sar = (short *)nar ; bar = (byte *)nar ; far = (float *)nar ; #pragma omp for for( qq=0 ; qq < nvox ; qq++ ){ /* qq=voxel index */ ii = DSET_index_to_ix(inset,qq) ; jj = DSET_index_to_jy(inset,qq) ; kk = DSET_index_to_kz(inset,qq) ; nb = mri_get_nbhd_array( bbim , NULL , ii,jj,kk , nbhd , nar ) ; if( nb == 0 ) continue ; switch( btyp ){ case MRI_short: for( ib=0 ; ib < nb ; ib++ ) listar[sar[ib]+TWO15][qq]++ ; break ; case MRI_byte: for( ib=0 ; ib < nb ; ib++ ) listar[bar[ib]+TWO15][qq]++ ; break ; case MRI_float: for( ib=0 ; ib < nb ; ib++ ){ ss = SHORTIZE(far[ib]); listar[ss+TWO15][qq]++; } break ; } } /* end of voxel loop */ free(nar) ; } /* end of OpenMP */ AFNI_OMP_END ; } } /* end of sub-brick loop */ DSET_unload(inset) ; } /* end of dataset loop */ if( verb ) fprintf(stderr,"\n") ; free(listar) ; /*---- post-process output ---*/ if( do_prob ){ byte **bbar ; int pp ; if( verb ) INFO_message("Conversion to probabilities") ; AFNI_OMP_START ; #pragma omp parallel { int qq , ib ; float pfac , val ; byte **bbar ; #pragma omp for for( qq=0 ; qq < nvox ; qq++ ){ pfac = 0.0001f ; for( ib=0 ; ib < numval ; ib++ ) pfac += outar[ib][qq] ; pfac = 250.0f / pfac ; for( ib=0 ; ib < numval ; ib++ ){ val = outar[ib][qq]*pfac ; outar[ib][qq] = BYTEIZE(val) ; } } } /* end OpenMP */ AFNI_OMP_END ; bbar = (byte **)malloc(sizeof(byte *)*numval) ; for( bb=0 ; bb < numval ; bb++ ){ bbar[bb] = (byte *)malloc(sizeof(byte)*nvox) ; for( pp=0 ; pp < nvox ; pp++ ) bbar[bb][pp] = (byte)outar[bb][pp] ; EDIT_substitute_brick(outset,bb,MRI_byte,bbar[bb]) ; EDIT_BRICK_FACTOR(outset,bb,0.004f) ; } free(bbar) ; } /* end of do_prob */ free(outar) ; RETURN(outset) ; }
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) ; }