source: trunk/src/ATrous/atrous_1d_reconstruct.cc @ 884

Last change on this file since 884 was 884, checked in by MatthewWhiting, 12 years ago

A large set of changes aimed at making the use of indexing variables consistent. We have moved to size_t as much as possible to represent the location in memory. This includes making the dimension array within DataArray? and derived classes an array of size_t variables. Still plenty of compilation warnings (principally comparing signed and unsigned variables) - these will need to be cleaned up.

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