// ----------------------------------------------------------------------- // atrous_3d_reconstruct.cc: 3-dimensional wavelet reconstruction. // ----------------------------------------------------------------------- // Copyright (C) 2006, Matthew Whiting, ATNF // // This program is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the // Free Software Foundation; either version 2 of the License, or (at your // option) any later version. // // Duchamp is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // // You should have received a copy of the GNU General Public License // along with Duchamp; if not, write to the Free Software Foundation, // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA // // Correspondence concerning Duchamp may be directed to: // Internet email: Matthew.Whiting [at] atnf.csiro.au // Postal address: Dr. Matthew Whiting // Australia Telescope National Facility, CSIRO // PO Box 76 // Epping NSW 1710 // AUSTRALIA // ----------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #include using Statistics::madfmToSigma; using std::endl; using std::setw; namespace duchamp { void atrous3DReconstruct(size_t &xdim, size_t &ydim, size_t &zdim, float *&input, float *&output, Param &par) { /// A routine that uses the a trous wavelet method to reconstruct a /// 3-dimensional image cube. /// The Param object "par" contains all necessary info about the filter and /// reconstruction parameters. /// /// If there are no non-BLANK pixels (and we are testing for /// BLANKs), the reconstruction cannot be done, so we return the /// input array as the output array and give a warning message. /// /// \param xdim The length of the x-axis. /// \param ydim The length of the y-axis. /// \param zdim The length of the z-axis. /// \param input The input spectrum. /// \param output The returned reconstructed spectrum. This array needs to be declared beforehand. /// \param par The Param set. const float SNR_THRESH=par.getAtrousCut(); unsigned int MIN_SCALE=par.getMinScale(); unsigned int MAX_SCALE=par.getMaxScale(); size_t size = xdim * ydim * zdim; size_t spatialSize = xdim * ydim; size_t mindim = xdim; if (ydim0)&&(MAX_SCALE<=numScales)) MAX_SCALE = std::min(MAX_SCALE,numScales); else{ if(MAX_SCALE!=0) DUCHAMPWARN("Reading parameters","The requested value of the parameter scaleMax, \"" << par.getMaxScale() << "\" is outside the allowed range (1-"<< numScales <<") -- setting to " << numScales); MAX_SCALE = numScales; par.setMaxScale(MAX_SCALE); } double *sigmaFactors = new double[numScales+1]; for(size_t i=0;i<=numScales;i++){ if(i<=size_t(par.filter().maxFactor(3)) ) sigmaFactors[i] = par.filter().sigmaFactor(3,i); else sigmaFactors[i] = sigmaFactors[i-1] / sqrt(8.); } float mean,originalSigma,oldsigma,newsigma; bool *isGood = new bool[size]; size_t goodSize=0; for(size_t pos=0;pos(input,isGood,size); float *coeffs = new float[size]; float *wavelet = new float[size]; // float *residual = new float[size]; for(size_t pos=0;posct1)&&(par.isBlank(input[row*xdim+ct2]))) ct2--; // xLim1[row] = ct1; // xLim2[row] = ct2; // avGapX += ct2 - ct1 + 1; // } // avGapX /= float(ydim); // for(size_t col=0;colct1)&&(par.isBlank(input[col+xdim*ct2]))) ct2--; // yLim1[col] = ct1; // yLim2[col] = ct2; // avGapY += ct2 - ct1 + 1; // } // avGapY /= float(xdim); // // if(avGapX < mindim) mindim = int(avGapX); // // if(avGapY < mindim) mindim = int(avGapY); // // numScales = par.filter().getNumScales(mindim); // } float threshold; int iteration=0; newsigma = 1.e9; for(size_t i=0;i=long(zdim))){ if(z<0) z = -z; // boundary conditions are if(z>=long(zdim)) z = 2*(zdim-1) - z; // reflection. } size_t oldchan = z * spatialSize; for(int yoffset=-filterHW; yoffset<=filterHW; yoffset++){ long y = long(ypos) + spacing*yoffset; while((y<0)||(y>=long(ydim))){ // boundary conditions are reflection. if(y<0) y = 0 - y; else if(y>=long(ydim)) y = 2*(ydim-1) - y; } // // Boundary conditions -- assume reflection at boundaries. // // Use limits as calculated above // if(yLim1[xpos]!=yLim2[xpos]){ // // if these are equal we will get into an infinite loop // while((yyLim2[xpos])){ // // std::cerr << y << " " <yLim2[xpos]) y = 2*yLim2[xpos] - y; // } // } size_t oldrow = y * xdim; for(int xoffset=-filterHW; xoffset<=filterHW; xoffset++){ long x = long(xpos) + spacing*xoffset; while((x<0)||(x>=long(xdim))){ // boundary conditions are reflection. if(x<0) x = 0 - x; else if(x>=long(xdim)) x = 2*(xdim-1) - x; } // // Boundary conditions -- assume reflection at boundaries. // // Use limits as calculated above // if(xLim1[ypos]!=xLim2[ypos]){ // // if these are equal we will get into an infinite loop // while((xxLim2[ypos])){ // if(xxLim2[ypos]) x = 2*xLim2[ypos] - x; // } // } size_t oldpos = oldchan + oldrow + x; if(isGood[oldpos]) wavelet[pos] -= filter[filterpos]*coeffs[oldpos]; filterpos++; } //-> end of xoffset loop } //-> end of yoffset loop } //-> end of zoffset loop } //-> end of else{ ( from if(!isGood[pos]) ) pos++; } //-> end of xpos loop } //-> end of ypos loop } //-> end of zpos loop // Need to do this after we've done *all* the convolving for(size_t pos=0;pos=MIN_SCALE && scale <=MAX_SCALE){ if(par.getFlagRobustStats()) // findMedianStats(wavelet,size,isGood,mean,sigma); mean = findMedian(wavelet,isGood,size); else //findNormalStats(wavelet,size,isGood,mean,sigma); mean = findMean(wavelet,isGood,size); threshold = mean + SNR_THRESH*originalSigma*sigmaFactors[scale]; for(size_t pos=0;pos threshold ){ output[pos] += wavelet[pos]; // only add to the output if the wavelet coefficient is significant } } } spacing *= 2; // double the scale of the filter. } //-> end of scale loop for(size_t pos=0;pos(input,output,isGood,size); if(par.isVerbose()) printBackSpace(15); } while( (iteration==1) || (fabs(oldsigma-newsigma)/newsigma > par.getReconConvergence()) ); if(par.isVerbose()) std::cout << "Completed "<