void VolumeTexture::generateChargeTexture(float vmin, float vmax) { // need a volumetric dataset for this if (!v) return; int x, y, z; int addr, addr2; int daddr; float vscale, vrange; size[0] = v->xsize; size[1] = v->ysize; size[2] = v->zsize; for (int i=0; i<3; i++) { size[i] = nextpower2(size[i]); } int num = size[0]*size[1]*size[2]; if (!allocateTextureMap(num)) return; vrange = vmax - vmin; if (fabs(vrange) < 0.00001) vscale = 0.0f; else vscale = 1.00001f / vrange; // map volume data scalars to colors for (z=0; z<v->zsize; z++) { for (y=0; y<v->ysize; y++) { addr = z * size[0] * size[1] + y * size[0]; daddr = z * v->xsize * v->ysize + y * v->xsize; for (x=0; x<v->xsize; x++) { addr2 = (addr + x) * 3; float level, r, g, b; // map data to range 0->1 level = (v->data[daddr + x] - vmin) * vscale; level = level < 0 ? 0 : level > 1 ? 1 : level; // low values are mapped to red, high to blue r = (1.0f - level) * 255.0f; b = level * 255.0f; if (level < 0.5f) { g = level * 2.0f * 128.0f; } else { g = (0.5f - (level - 0.5f)) * 2.0f * 128.0f; } texmap[addr2 ] = (unsigned char) r; texmap[addr2 + 1] = (unsigned char) g; texmap[addr2 + 2] = (unsigned char) b; } } } }
void VolumeTexture::generateHSVTexture(float vmin, float vmax) { int x, y, z; int index, addr, addr2, addr3; int daddr; float vscale, vrange; unsigned char coltable[3 * 4096]; size[0] = v->xsize; size[1] = v->ysize; size[2] = v->zsize; for (int i=0; i<3; i++) { size[i] = nextpower2(size[i]); } int num = size[0]*size[1]*size[2]; if (!allocateTextureMap(num)) return; // build a fast color lookup table for (index=0; index<4096; index++) { addr = index * 3; HSItoRGB(4.0f * index / 4096.0f, 0.75, 1.0, coltable+addr, coltable+addr+1, coltable+addr+2); } // calculate scaling factors vrange = vmax - vmin; if (fabs(vrange) < 0.00001) vscale = 0.0f; else vscale = 1.00001f / vrange; // map volume data scalars to colors for (z=0; z<v->zsize; z++) { for (y=0; y<v->ysize; y++) { addr = z * size[0] * size[1] + y * size[0]; daddr = z * v->xsize * v->ysize + y * v->xsize; for (x=0; x<v->xsize; x++) { addr2 = (addr + x) * 3; float level; // map data to range 0->1 level = (v->data[daddr + x] - vmin) * vscale; level = level < 0 ? 0 : level > 1 ? 1 : level; // map values to an HSV color map addr3 = ((int) (level * 4095)) * 3; texmap[addr2 ] = coltable[addr3 ]; texmap[addr2 + 1] = coltable[addr3 + 1]; texmap[addr2 + 2] = coltable[addr3 + 2]; } } } }
void VolumeTexture::generateContourLineTexture(float densityperline, float linewidth) { int x, y, z; int addr, addr2; float xp, yp, zp; printf("Contour lines...\n"); printf("range / densityperline: %f\n", log(v->datamax - v->datamin) / densityperline); size[0] = nextpower2(v->xsize*2); size[1] = nextpower2(v->ysize*2); size[2] = nextpower2(v->zsize*2); int num = size[0]*size[1]*size[2]; if (!allocateTextureMap(num)) return; // map volume data scalars to contour line colors for (z=0; z<size[2]; z++) { zp = ((float) z / size[2]) * v->zsize; for (y=0; y<size[1]; y++) { addr = z * size[0] * size[1] + y * size[0]; yp = ((float) y / size[1]) * v->ysize; for (x=0; x<size[0]; x++) { addr2 = (addr + x) * 3; xp = ((float) x / size[0]) * v->xsize; float level; level = float(fmod(log(v->voxel_value_interpolate(xp,yp,zp)), densityperline) / densityperline); if (level < linewidth) { texmap[addr2 ] = 0; texmap[addr2 + 1] = 0; texmap[addr2 + 2] = 0; } else { texmap[addr2 ] = 255; texmap[addr2 + 1] = 255; texmap[addr2 + 2] = 255; } } } } }
void VolumeTexture::generateColorScaleTexture(float vmin, float vmax, const Scene *scene) { int x, y, z; int addr, addr2; int daddr; float vscale, vrange; size[0] = v->xsize; size[1] = v->ysize; size[2] = v->zsize; for (int i=0; i<3; i++) { size[i] = nextpower2(size[i]); } int num = size[0]*size[1]*size[2]; if (!allocateTextureMap(num)) return; vrange = vmax - vmin; if (fabs(vrange) < 0.00001) vscale = 0.0f; else vscale = 1.00001f / vrange; // map volume data scalars to colors for (z=0; z<v->zsize; z++) { for (y=0; y<v->ysize; y++) { addr = z * size[0] * size[1] + y * size[0]; daddr = z * v->xsize * v->ysize + y * v->xsize; for (x=0; x<v->xsize; x++) { addr2 = (addr + x) * 3; float level; // map data min/max to range 0->1 // values must be clamped before use, since user-specified // min/max can cause out-of-range color indices to be generated level = (v->data[daddr + x] - vmin) * vscale; int colindex = (int)(level * MAPCLRS-1); if (colindex < 0) colindex = 0; else if (colindex >= MAPCLRS) colindex = MAPCLRS-1; const float *rgb = scene->color_value(MAPCOLOR(colindex)); texmap[addr2 ] = (unsigned char)(rgb[0]*255.0f); texmap[addr2 + 1] = (unsigned char)(rgb[1]*255.0f); texmap[addr2 + 2] = (unsigned char)(rgb[2]*255.0f); } } } }
int main(int argc, char* argv[]) { bool verb, pow2; char key[7], *mode;; int n1, n2, n1padded, n2padded, num, dim, n[SF_MAX_DIM], npadded[SF_MAX_DIM], ii[SF_MAX_DIM]; int i, j, i1, i2, index, nw, iter, niter, nthr, *pad; float thr, pclip, normp; float *dobs_t, *thresh, *mask; fftwf_complex *mm, *dd, *dobs; fftwf_plan fft1, ifft1, fftrem, ifftrem;/* execute plan for FFT and IFFT */ sf_file in, out, Fmask; /* mask and I/O files*/ sf_init(argc,argv); /* Madagascar initialization */ in=sf_input("in"); /* read the data to be interpolated */ out=sf_output("out"); /* output the reconstructed data */ Fmask=sf_input("mask"); /* read the (n-1)-D mask for n-D data */ if(!sf_getbool("verb",&verb)) verb=false; /* verbosity */ if(!sf_getbool("pow2",&pow2)) pow2=false; /* round up the length of each axis to be power of 2 */ if (!sf_getint("niter",&niter)) niter=100; /* total number of iterations */ if (!sf_getfloat("pclip",&pclip)) pclip=10.; /* starting data clip percentile (default is 10)*/ if ( !(mode=sf_getstring("mode")) ) mode = "exp"; /* thresholding mode: 'hard', 'soft','pthresh','exp'; 'hard', hard thresholding; 'soft', soft thresholding; 'pthresh', generalized quasi-p; 'exp', exponential shrinkage */ if (pclip <=0. || pclip > 100.) sf_error("pclip=%g should be > 0 and <= 100",pclip); if (!sf_getfloat("normp",&normp)) normp=1.; /* quasi-norm: normp<2 */ for (i=0; i < SF_MAX_DIM; i++) {/* dimensions */ snprintf(key,3,"n%d",i+1); if (!sf_getint(key,n+i) && (NULL == in || !sf_histint(in,key,n+i))) break; /*( n# size of #-th axis )*/ sf_putint(out,key,n[i]); } if (0==i) sf_error("Need n1="); dim=i; pad=sf_intalloc (dim); for (i=0; i<dim; i++) pad[i]=0; sf_getints("pad",pad,dim); /* number of zeros to be padded for each axis */ n1=n[0]; n2=sf_leftsize(in,1); for (i=0; i<SF_MAX_DIM; i++) npadded[i]=1; npadded[0]=n1+pad[0]; n1padded=npadded[0]; n2padded=1; for (i=1; i<dim; i++){ npadded[i]=n[i]+pad[i]; if (pow2) {/* zero-padding to be power of 2 */ npadded[i]=nextpower2(n[i]); fprintf(stderr,"n%d=%d n%dpadded=%d\n",i,n[i],i,npadded[i]); } n2padded*=npadded[i]; } nw=npadded[0]/2+1; num=nw*n2padded;/* data: total number of elements in frequency domain */ /* allocate data and mask arrays */ thresh=(float*) malloc(nw*n2padded*sizeof(float)); dobs_t=(float*) fftwf_malloc(n1padded*n2padded*sizeof(float)); /* time domain observation */ dobs=(fftwf_complex*)fftwf_malloc(nw*n2padded*sizeof(fftwf_complex));/* freq-domain observation */ dd=(fftwf_complex*) fftwf_malloc(nw*n2padded*sizeof(fftwf_complex)); mm=(fftwf_complex*) fftwf_malloc(nw*n2padded*sizeof(fftwf_complex)); if (NULL != sf_getstring("mask")){ mask=sf_floatalloc(n2padded); } else sf_error("mask needed!"); /* initialize the input data and mask arrays */ memset(dobs_t,0,n1padded*n2padded*sizeof(float)); memset(mask,0,n2padded*sizeof(float)); for (i=0; i<n1*n2; i+=n1){ sf_line2cart(dim,n,i,ii); j=sf_cart2line(dim,npadded,ii); sf_floatread(&dobs_t[j], n1, in); sf_floatread(&mask[j/n1padded], 1, Fmask); } /* FFT for the 1st dimension and the remaining dimensions */ fft1=fftwf_plan_many_dft_r2c(1, &n1padded, n2padded, dobs_t, &n1padded, 1, n1padded, dobs, &n1padded, 1, nw, FFTW_MEASURE); ifft1=fftwf_plan_many_dft_c2r(1, &n1padded, n2padded, dobs, &n1padded, 1, nw, dobs_t, &n1padded, 1, n1padded, FFTW_MEASURE); fftrem=fftwf_plan_many_dft(dim-1, &npadded[1], nw, dd, &npadded[1], nw, 1, dd, &npadded[1], nw, 1, FFTW_FORWARD, FFTW_MEASURE); ifftrem=fftwf_plan_many_dft(dim-1, &npadded[1], nw, dd, &npadded[1], nw, 1, dd, &npadded[1], nw, 1, FFTW_BACKWARD, FFTW_MEASURE); /* transform the data from time domain to frequency domain: dobs_t-->dobs */ fftwf_execute(fft1); for(i=0; i<num; i++) dobs[i]/=sqrtf(n1padded); memset(mm,0,num*sizeof(fftwf_complex)); /* Iterative Shrinkage-Thresholding (IST) Algorithm: mm^{k+1}=T[mm^k+A^* M^* (dobs-M A mm^k)] (M^*=M; Mdobs=dobs) =T[mm^k+A^*(dobs-M A mm^k)]; (k=0,1,...niter-1) dd^=A mm^; */ for(iter=0; iter<niter; iter++) { /* dd<-- A mm^k */ memcpy(dd, mm, num*sizeof(fftwf_complex)); fftwf_execute(ifftrem); for(i=0; i<num; i++) dd[i]/=sqrtf(n2padded); /* apply mask: dd<--dobs-M A mm^k=dobs-M dd */ for(i2=0; i2<n2padded; i2++) for(i1=0; i1<nw; i1++) { index=i1+nw*i2; dd[index]=dobs[index]-mask[i2]*dd[index]; } /* mm^k += A^*(dobs-M A mm^k); dd=dobs-M A mm^k */ fftwf_execute(fftrem); for(i=0; i<num; i++) mm[i]+=dd[i]/sqrtf(n2padded); /* perform thresholding */ for(i=0; i<num; i++) thresh[i]=cabsf(mm[i]); nthr = 0.5+num*(1.-0.01*pclip); /* round off */ if (nthr < 0) nthr=0; if (nthr >= num) nthr=num-1; thr=sf_quantile(nthr, num, thresh); sf_cpthresh(mm, num, thr, normp, mode); if (verb) sf_warning("iteration %d;",iter+1); } /* frequency--> time domain: dobs-->dobs_t */ memcpy(dd, mm, num*sizeof(fftwf_complex)); fftwf_execute(ifftrem); for(i=0; i<num; i++) dd[i]/=sqrtf(n2padded); memcpy(dobs, dd, num*sizeof(fftwf_complex)); fftwf_execute(ifft1); for(i=0; i<n1padded*n2padded; i++) dobs_t[i]/=sqrtf(n1padded); for (i=0; i<n1*n2; i+=n1){ sf_line2cart(dim,n,i,ii); j=sf_cart2line(dim,npadded,ii); sf_floatwrite(&dobs_t[j],n1,out); } free(thresh); fftwf_free(dobs_t); fftwf_free(dobs); fftwf_free(dd); fftwf_free(mm); exit(0); }