source: tags/release-1.1.4/src/ATrous/atrous_1d_reconstruct.cc @ 1441

Last change on this file since 1441 was 393, checked in by MatthewWhiting, 17 years ago

Fixed up headers for trunk as well.

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