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

Last change on this file since 528 was 528, checked in by MatthewWhiting, 15 years ago

Changing the documentation comments to match the askapsoft style. Also have split ChanMap? and Object3D into separate files.

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    ///  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 int MIN_SCALE=par.getMinScale();
63    static bool firstTime = true;
64
65    int numScales = par.filter().getNumScales(xdim);
66    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(int 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    int goodSize=0;
90    for(int 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(int 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
109      for(int pos=0;pos<xdim;pos++) output[pos]=0.;
110
111      int filterHW = par.filter().width()/2;
112      double *filter = new double[par.filter().width()];
113      for(int i=0;i<par.filter().width();i++) filter[i] = par.filter().coeff(i);
114
115
116      // No trimming done in 1D case.
117
118      int iteration=0;
119      newsigma = 1.e9;
120      do{
121        if(par.isVerbose()) {
122          std::cout << "Iteration #"<<++iteration<<":";
123          printSpace(13);
124        }
125        // first, get the value of oldsigma and set it to the previous
126        //   newsigma value
127        oldsigma = newsigma;
128        // all other times round, we are transforming the residual array
129        for(int i=0;i<xdim;i++)  coeffs[i] = input[i] - output[i];
130   
131        float *array = new float[xdim];
132        goodSize=0;
133        for(int i=0;i<xdim;i++) if(isGood[i]) array[goodSize++] = input[i];
134        findMedianStats(array,goodSize,originalMean,originalSigma);
135        originalSigma = madfmToSigma(originalSigma);
136        delete [] array;
137
138        int spacing = 1;
139        for(int scale = 1; scale<=numScales; scale++){
140
141          if(par.isVerbose()) {
142            //    printBackSpace(12);
143            std::cout << "Scale " << std::setw(2) << scale
144                      << " /"     << std::setw(2) << numScales <<std::flush;
145          }
146
147          for(int xpos = 0; xpos<xdim; xpos++){
148            // loops over each pixel in the image
149            int pos = xpos;
150
151            wavelet[pos] = coeffs[pos];
152       
153            if(!isGood[pos] )  wavelet[pos] = 0.;
154            else{
155
156              for(int xoffset=-filterHW; xoffset<=filterHW; xoffset++){
157                int x = xpos + spacing*xoffset;
158
159                while((x<0)||(x>=xdim)){
160                  // boundary conditions are reflection.
161                  if(x<0) x = 0 - x;
162                  else if(x>=xdim) x = 2*(xdim-1) - x;
163                }
164
165                int filterpos = (xoffset+filterHW);
166                int oldpos = x;
167
168                if(isGood[oldpos])
169                  wavelet[pos] -= filter[filterpos]*coeffs[oldpos];
170             
171              } //-> end of xoffset loop
172            } //-> end of else{ ( from if(!isGood[pos])  )
173           
174          } //-> end of xpos loop
175
176          // Need to do this after we've done *all* the convolving
177          for(int pos=0;pos<xdim;pos++) coeffs[pos] = coeffs[pos] - wavelet[pos];
178
179          // Have found wavelet coeffs for this scale -- now threshold
180          if(scale>=MIN_SCALE){
181            array = new float[xdim];
182            goodSize=0;
183            for(int pos=0;pos<xdim;pos++)
184              if(isGood[pos]) array[goodSize++] = wavelet[pos];
185            findMedianStats(array,goodSize,mean,sigma);
186            delete [] array;
187       
188            for(int pos=0;pos<xdim;pos++){
189              // preserve the Blank pixel values in the output.
190              if(!isGood[pos]) output[pos] = input[pos];
191              else if( fabs(wavelet[pos]) >
192                       (mean+SNR_THRESH*originalSigma*sigmaFactors[scale]) )
193                output[pos] += wavelet[pos];
194            }
195          }
196 
197          spacing *= 2;
198
199        } //-> end of scale loop
200
201        // Only add the final smoothed array if we are doing *all* the scales.
202        if(numScales == par.filter().getNumScales(xdim))
203          for(int pos=0;pos<xdim;pos++)
204            if(isGood[pos]) output[pos] += coeffs[pos];
205
206        array = new float[xdim];
207        goodSize=0;
208        for(int i=0;i<xdim;i++)
209          if(isGood[i]) array[goodSize++] = input[i] - output[i];
210        findMedianStats(array,goodSize,mean,newsigma);
211        newsigma = madfmToSigma(newsigma);
212        delete [] array;
213
214        if(par.isVerbose()) printBackSpace(26);
215
216      } while( (iteration==1) ||
217               (fabs(oldsigma-newsigma)/newsigma > reconTolerance) );
218
219      if(par.isVerbose()) std::cout << "Completed "<<iteration<<" iterations. ";
220
221      delete [] filter;
222      delete [] coeffs;
223      delete [] wavelet;
224
225    }
226
227    delete [] isGood;
228    delete [] sigmaFactors;
229  }
230
231}
Note: See TracBrowser for help on using the repository browser.