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
Line 
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// -----------------------------------------------------------------------
28#include <iostream>
29#include <sstream>
30#include <iomanip>
31#include <math.h>
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>
39using Statistics::madfmToSigma;
40
41namespace duchamp
42{
43
44  void atrous1DReconstruct(size_t &xdim, float *&input, float *&output, Param &par)
45  {
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.
60
61    const float SNR_THRESH=par.getAtrousCut();
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
65
66    unsigned int numScales = par.filter().getNumScales(xdim);
67    if((MAX_SCALE>0)&&(MAX_SCALE<=numScales))
68      MAX_SCALE = std::min(MAX_SCALE,numScales);
69    else{
70      if((firstTime)&&(MAX_SCALE!=0)){
71        firstTime=false;
72        DUCHAMPWARN("Reading parameters","The requested value of the parameter scaleMax, \"" << par.getMaxScale() << "\" is outside the allowed range (1-"<< numScales <<") -- setting to " << numScales);
73      }
74      MAX_SCALE = numScales;
75      par.setMaxScale(MAX_SCALE);
76    }
77    double *sigmaFactors = new double[numScales+1];
78    for(size_t i=0;i<=numScales;i++){
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    }
83
84    float mean,originalSigma,oldsigma,newsigma;
85    std::vector<bool> isGood(xdim);
86    size_t goodSize=0;
87    for(size_t pos=0;pos<xdim;pos++) {
88      isGood[pos] = !par.isBlank(input[pos]);
89      if(isGood[pos]) goodSize++;
90    }
91
92    if(goodSize == 0){
93      // There are no good pixels -- everything is BLANK for some reason.
94      // Return the input array as the output.
95
96      for(size_t pos=0;pos<xdim; pos++) output[pos] = input[pos];
97
98    }
99    else{
100      // Otherwise, all is good, and we continue.
101
102
103      float *coeffs = new float[xdim];
104      float *wavelet = new float[xdim];
105      // float *residual = new float[xdim];
106
107      for(size_t pos=0;pos<xdim;pos++) output[pos]=0.;
108
109      int filterHW = par.filter().width()/2;
110      double *filter = new double[par.filter().width()];
111      for(size_t i=0;i<par.filter().width();i++) filter[i] = par.filter().coeff(i);
112
113
114      // No trimming done in 1D case.
115
116      float threshold;
117      int iteration=0;
118      newsigma = 1.e9;
119      do{
120        if(par.isVerbose()) {
121          std::cout << "Iteration #"<<++iteration<<":";
122          printSpace(std::cout,13);
123        }
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
128        for(size_t i=0;i<xdim;i++)  coeffs[i] = input[i] - output[i];
129   
130        // findMedianStats(input,xdim,isGood,originalMean,originalSigma);
131        // originalSigma = madfmToSigma(originalSigma);
132        if(par.getFlagRobustStats())
133          originalSigma = madfmToSigma(findMADFM(input,isGood,xdim));
134        else
135          originalSigma = findStddev<float>(input,isGood,xdim);
136
137        int spacing = 1;
138        for(unsigned int scale = 1; scale<=numScales; scale++){
139
140          if(par.isVerbose()) {
141            std::cout << "Scale " << std::setw(2) << scale
142                      << " /"     << std::setw(2) << numScales <<std::flush;
143          }
144
145          for(size_t xpos = 0; xpos<xdim; xpos++){
146            // loops over each pixel in the image
147
148            wavelet[xpos] = coeffs[xpos];
149       
150            if(!isGood[xpos] )  wavelet[xpos] = 0.;
151            else{
152
153              for(int xoffset=-filterHW; xoffset<=filterHW; xoffset++){
154                long x = xpos + spacing*xoffset;
155
156                while((x<0)||(x>=long(xdim))){
157                  // boundary conditions are reflection.
158                  if(x<0) x = 0 - x;
159                  else if(x>=long(xdim)) x = 2*(xdim-1) - x;
160                }
161
162                size_t filterpos = (xoffset+filterHW);
163                size_t oldpos = x;
164
165                if(isGood[oldpos])
166                  wavelet[xpos] -= filter[filterpos]*coeffs[oldpos];
167             
168              } //-> end of xoffset loop
169            } //-> end of else{ ( from if(!isGood[xpos])  )
170           
171          } //-> end of xpos loop
172
173          // Need to do this after we've done *all* the convolving
174          for(size_t pos=0;pos<xdim;pos++) coeffs[pos] = coeffs[pos] - wavelet[pos];
175
176          // Have found wavelet coeffs for this scale -- now threshold
177          if(scale>=MIN_SCALE && scale <=MAX_SCALE){
178            //      findMedianStats(wavelet,xdim,isGood,mean,sigma);
179            if(par.getFlagRobustStats())
180              mean = findMedian<float>(wavelet,isGood,xdim);
181            else
182              mean = findMean<float>(wavelet,isGood,xdim);
183
184            threshold = mean+SNR_THRESH*originalSigma*sigmaFactors[scale];
185            for(size_t pos=0;pos<xdim;pos++){
186              // preserve the Blank pixel values in the output.
187              if(!isGood[pos]) output[pos] = input[pos];
188              else if( fabs(wavelet[pos]) > threshold )
189                output[pos] += wavelet[pos];
190            }
191          }
192 
193          spacing *= 2;
194
195        } //-> end of scale loop
196
197        // Only add the final smoothed array if we are doing *all* the scales.
198        if(numScales == par.filter().getNumScales(xdim))
199          for(size_t pos=0;pos<xdim;pos++)
200            if(isGood[pos]) output[pos] += coeffs[pos];
201
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
208          newsigma = findStddevDiff<float>(input,output,isGood,xdim);
209
210        if(par.isVerbose()) printBackSpace(std::cout,26);
211
212      } while( (iteration==1) ||
213               (fabs(oldsigma-newsigma)/newsigma > par.getReconConvergence()) );
214
215      if(par.isVerbose()) std::cout << "Completed "<<iteration<<" iterations. ";
216
217      delete [] filter;
218      // delete [] residual;
219      delete [] wavelet;
220      delete [] coeffs;
221
222    }
223
224    delete [] sigmaFactors;
225  }
226
227}
Note: See TracBrowser for help on using the repository browser.