// ----------------------------------------------------------------------- // atrous_1d_reconstruct.cc: 1-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 #include using Statistics::madfmToSigma; namespace duchamp { void atrous1DReconstruct(size_t &xdim, float *&input, float *&output, Param &par) { /// A routine that uses the a trous wavelet method to reconstruct a /// 1-dimensional spectrum. /// The Param object "par" contains all necessary info about the filter and /// reconstruction parameters. /// /// If all pixels are BLANK (and we are testing for BLANKs), the /// reconstruction will simply give BLANKs back, so we return the /// input array as the output array. /// /// \param xdim The length of the spectrum. /// \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(); static bool firstTime = true; // need this static in case we do two reconstructions - e.g. baseline subtraction unsigned int numScales = par.filter().getNumScales(xdim); if((MAX_SCALE>0)&&(MAX_SCALE<=numScales)) MAX_SCALE = std::min(MAX_SCALE,numScales); else{ if((firstTime)&&(MAX_SCALE!=0)){ firstTime=false; 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<=par.filter().maxFactor(1)) sigmaFactors[i] = par.filter().sigmaFactor(1,i); else sigmaFactors[i] = sigmaFactors[i-1] / sqrt(2.); } float mean,originalSigma,oldsigma,newsigma; std::vector isGood(xdim); size_t goodSize=0; for(size_t pos=0;pos(input,isGood,xdim); int spacing = 1; for(unsigned int scale = 1; scale<=numScales; scale++){ if(par.isVerbose()) { std::cout << "Scale " << std::setw(2) << scale << " /" << std::setw(2) << numScales <=long(xdim))){ // boundary conditions are reflection. if(x<0) x = 0 - x; else if(x>=long(xdim)) x = 2*(xdim-1) - x; } size_t filterpos = (xoffset+filterHW); size_t oldpos = x; if(isGood[oldpos]) wavelet[xpos] -= filter[filterpos]*coeffs[oldpos]; } //-> end of xoffset loop } //-> end of else{ ( from if(!isGood[xpos]) ) } //-> end of xpos loop // Need to do this after we've done *all* the convolving for(size_t pos=0;pos=MIN_SCALE && scale <=MAX_SCALE){ // findMedianStats(wavelet,xdim,isGood,mean,sigma); if(par.getFlagRobustStats()) mean = findMedian(wavelet,isGood,xdim); else mean = findMean(wavelet,isGood,xdim); threshold = mean+SNR_THRESH*originalSigma*sigmaFactors[scale]; for(size_t pos=0;pos threshold ) output[pos] += wavelet[pos]; } } spacing *= 2; } //-> end of scale loop // Only add the final smoothed array if we are doing *all* the scales. if(numScales == par.filter().getNumScales(xdim)) for(size_t pos=0;pos(input,output,isGood,xdim); if(par.isVerbose()) printBackSpace(std::cout,26); } while( (iteration==1) || (fabs(oldsigma-newsigma)/newsigma > par.getReconConvergence()) ); if(par.isVerbose()) std::cout << "Completed "<