source: trunk/src/ATrous/atrous_1d_reconstruct.cc

Last change on this file was 1393, checked in by MatthewWhiting, 10 years ago

A large changeset that moves all use of bool arrays (ie. bool *) to std::vector<bool>. This will be a bit safer, plus potentially cheaper in memory usage. Interfaces to all stats functions with masks have changed accordingly, as well as the Gaussian smoothing functions and some spectral utility functions.

File size: 7.6 KB
RevLine 
[299]1// -----------------------------------------------------------------------
2// atrous_1d_reconstruct.cc: 1-dimensional wavelet reconstruction.
3// -----------------------------------------------------------------------
4// Copyright (C) 2006, Matthew Whiting, ATNF
5//
6// This program is free software; you can redistribute it and/or modify it
7// under the terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 2 of the License, or (at your
9// option) any later version.
10//
11// Duchamp is distributed in the hope that it will be useful, but WITHOUT
12// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14// for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with Duchamp; if not, write to the Free Software Foundation,
18// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
19//
20// Correspondence concerning Duchamp may be directed to:
21//    Internet email: Matthew.Whiting [at] atnf.csiro.au
22//    Postal address: Dr. Matthew Whiting
23//                    Australia Telescope National Facility, CSIRO
24//                    PO Box 76
25//                    Epping NSW 1710
26//                    AUSTRALIA
27// -----------------------------------------------------------------------
[3]28#include <iostream>
[348]29#include <sstream>
[3]30#include <iomanip>
31#include <math.h>
[393]32#include <duchamp/duchamp.hh>
33#include <duchamp/param.hh>
34#include <duchamp/Utils/utils.hh>
35#include <duchamp/Utils/feedback.hh>
36#include <duchamp/ATrous/atrous.hh>
37#include <duchamp/ATrous/filter.hh>
38#include <duchamp/Utils/Statistics.hh>
[190]39using Statistics::madfmToSigma;
[3]40
[378]41namespace duchamp
[3]42{
[86]43
[887]44  void atrous1DReconstruct(size_t &xdim, float *&input, float *&output, Param &par)
[378]45  {
[528]46    ///  A routine that uses the a trous wavelet method to reconstruct a
47    ///   1-dimensional spectrum.
48    ///  The Param object "par" contains all necessary info about the filter and
49    ///   reconstruction parameters.
50    ///
51    ///  If all pixels are BLANK (and we are testing for BLANKs), the
52    ///  reconstruction will simply give BLANKs back, so we return the
53    ///  input array as the output array.
54    ///
55    ///  \param xdim The length of the spectrum.
56    ///  \param input The input spectrum.
57    ///  \param output The returned reconstructed spectrum. This array needs to
58    ///    be declared beforehand.
59    ///  \param par The Param set.
[3]60
[378]61    const float SNR_THRESH=par.getAtrousCut();
[1026]62    unsigned int MIN_SCALE=par.getMinScale();
63    unsigned int MAX_SCALE=par.getMaxScale();
64    static bool firstTime = true;  // need this static in case we do two reconstructions - e.g. baseline subtraction
[3]65
[884]66    unsigned int numScales = par.filter().getNumScales(xdim);
[1026]67    if((MAX_SCALE>0)&&(MAX_SCALE<=numScales))
68      MAX_SCALE = std::min(MAX_SCALE,numScales);
[378]69    else{
[1026]70      if((firstTime)&&(MAX_SCALE!=0)){
[378]71        firstTime=false;
[1026]72        DUCHAMPWARN("Reading parameters","The requested value of the parameter scaleMax, \"" << par.getMaxScale() << "\" is outside the allowed range (1-"<< numScales <<") -- setting to " << numScales);
[378]73      }
[1026]74      MAX_SCALE = numScales;
75      par.setMaxScale(MAX_SCALE);
[378]76    }
77    double *sigmaFactors = new double[numScales+1];
[846]78    for(size_t i=0;i<=numScales;i++){
[378]79      if(i<=par.filter().maxFactor(1))
80        sigmaFactors[i] = par.filter().sigmaFactor(1,i);
81      else sigmaFactors[i] = sigmaFactors[i-1] / sqrt(2.);
82    }
[3]83
[894]84    float mean,originalSigma,oldsigma,newsigma;
[1393]85    std::vector<bool> isGood(xdim);
[846]86    size_t goodSize=0;
87    for(size_t pos=0;pos<xdim;pos++) {
[378]88      isGood[pos] = !par.isBlank(input[pos]);
89      if(isGood[pos]) goodSize++;
90    }
[3]91
[378]92    if(goodSize == 0){
93      // There are no good pixels -- everything is BLANK for some reason.
94      // Return the input array as the output.
[3]95
[846]96      for(size_t pos=0;pos<xdim; pos++) output[pos] = input[pos];
[3]97
[378]98    }
99    else{
100      // Otherwise, all is good, and we continue.
[3]101
102
[378]103      float *coeffs = new float[xdim];
104      float *wavelet = new float[xdim];
[849]105      // float *residual = new float[xdim];
[3]106
[846]107      for(size_t pos=0;pos<xdim;pos++) output[pos]=0.;
[3]108
[378]109      int filterHW = par.filter().width()/2;
110      double *filter = new double[par.filter().width()];
[846]111      for(size_t i=0;i<par.filter().width();i++) filter[i] = par.filter().coeff(i);
[231]112
113
[378]114      // No trimming done in 1D case.
[3]115
[1026]116      float threshold;
[378]117      int iteration=0;
118      newsigma = 1.e9;
119      do{
[231]120        if(par.isVerbose()) {
[378]121          std::cout << "Iteration #"<<++iteration<<":";
[1384]122          printSpace(std::cout,13);
[231]123        }
[378]124        // first, get the value of oldsigma and set it to the previous
125        //   newsigma value
126        oldsigma = newsigma;
127        // all other times round, we are transforming the residual array
[846]128        for(size_t i=0;i<xdim;i++)  coeffs[i] = input[i] - output[i];
[378]129   
[849]130        // findMedianStats(input,xdim,isGood,originalMean,originalSigma);
131        // originalSigma = madfmToSigma(originalSigma);
132        if(par.getFlagRobustStats())
133          originalSigma = madfmToSigma(findMADFM(input,isGood,xdim));
134        else
[889]135          originalSigma = findStddev<float>(input,isGood,xdim);
[231]136
[378]137        int spacing = 1;
[846]138        for(unsigned int scale = 1; scale<=numScales; scale++){
[231]139
[378]140          if(par.isVerbose()) {
141            std::cout << "Scale " << std::setw(2) << scale
142                      << " /"     << std::setw(2) << numScales <<std::flush;
143          }
144
[884]145          for(size_t xpos = 0; xpos<xdim; xpos++){
[378]146            // loops over each pixel in the image
147
[884]148            wavelet[xpos] = coeffs[xpos];
[3]149       
[884]150            if(!isGood[xpos] )  wavelet[xpos] = 0.;
[378]151            else{
[3]152
[378]153              for(int xoffset=-filterHW; xoffset<=filterHW; xoffset++){
[846]154                long x = xpos + spacing*xoffset;
[3]155
[846]156                while((x<0)||(x>=long(xdim))){
[378]157                  // boundary conditions are reflection.
158                  if(x<0) x = 0 - x;
[846]159                  else if(x>=long(xdim)) x = 2*(xdim-1) - x;
[378]160                }
[3]161
[846]162                size_t filterpos = (xoffset+filterHW);
163                size_t oldpos = x;
[3]164
[378]165                if(isGood[oldpos])
[884]166                  wavelet[xpos] -= filter[filterpos]*coeffs[oldpos];
[3]167             
[378]168              } //-> end of xoffset loop
[884]169            } //-> end of else{ ( from if(!isGood[xpos])  )
[3]170           
[378]171          } //-> end of xpos loop
[3]172
[378]173          // Need to do this after we've done *all* the convolving
[846]174          for(size_t pos=0;pos<xdim;pos++) coeffs[pos] = coeffs[pos] - wavelet[pos];
[3]175
[378]176          // Have found wavelet coeffs for this scale -- now threshold
[1026]177          if(scale>=MIN_SCALE && scale <=MAX_SCALE){
[849]178            //      findMedianStats(wavelet,xdim,isGood,mean,sigma);
179            if(par.getFlagRobustStats())
[889]180              mean = findMedian<float>(wavelet,isGood,xdim);
[849]181            else
[889]182              mean = findMean<float>(wavelet,isGood,xdim);
[1026]183
184            threshold = mean+SNR_THRESH*originalSigma*sigmaFactors[scale];
[846]185            for(size_t pos=0;pos<xdim;pos++){
[378]186              // preserve the Blank pixel values in the output.
187              if(!isGood[pos]) output[pos] = input[pos];
[1026]188              else if( fabs(wavelet[pos]) > threshold )
[378]189                output[pos] += wavelet[pos];
190            }
[231]191          }
[3]192 
[378]193          spacing *= 2;
[3]194
[378]195        } //-> end of scale loop
[3]196
[378]197        // Only add the final smoothed array if we are doing *all* the scales.
198        if(numScales == par.filter().getNumScales(xdim))
[846]199          for(size_t pos=0;pos<xdim;pos++)
[378]200            if(isGood[pos]) output[pos] += coeffs[pos];
[3]201
[849]202        // for(size_t pos=0;pos<xdim;pos++) residual[pos]=input[pos]-output[pos];
203        // findMedianStats(residual,xdim,isGood,mean,newsigma);
204        // newsigma = madfmToSigma(newsigma);
205        if(par.getFlagRobustStats())
206          newsigma = madfmToSigma(findMADFMDiff(input,output,isGood,xdim));
207        else
[889]208          newsigma = findStddevDiff<float>(input,output,isGood,xdim);
[3]209
[1384]210        if(par.isVerbose()) printBackSpace(std::cout,26);
[3]211
[378]212      } while( (iteration==1) ||
[1026]213               (fabs(oldsigma-newsigma)/newsigma > par.getReconConvergence()) );
[3]214
[378]215      if(par.isVerbose()) std::cout << "Completed "<<iteration<<" iterations. ";
[3]216
[378]217      delete [] filter;
[849]218      // delete [] residual;
[650]219      delete [] wavelet;
[378]220      delete [] coeffs;
[231]221
[378]222    }
223
224    delete [] sigmaFactors;
[231]225  }
226
[3]227}
Note: See TracBrowser for help on using the repository browser.