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
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
[378]44  void atrous1DReconstruct(long &xdim, float *&input, float *&output, Param &par)
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();
62    const int MIN_SCALE=par.getMinScale();
63    static bool firstTime = true;
[3]64
[378]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    }
[3]86
[378]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    }
[3]94
[378]95    if(goodSize == 0){
96      // There are no good pixels -- everything is BLANK for some reason.
97      // Return the input array as the output.
[3]98
[378]99      for(int pos=0;pos<xdim; pos++) output[pos] = input[pos];
[3]100
[378]101    }
102    else{
103      // Otherwise, all is good, and we continue.
[3]104
105
[378]106      float *coeffs = new float[xdim];
107      float *wavelet = new float[xdim];
[3]108
[378]109      for(int pos=0;pos<xdim;pos++) output[pos]=0.;
[3]110
[378]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);
[231]114
115
[378]116      // No trimming done in 1D case.
[3]117
[378]118      int iteration=0;
119      newsigma = 1.e9;
120      do{
[231]121        if(par.isVerbose()) {
[378]122          std::cout << "Iteration #"<<++iteration<<":";
123          printSpace(13);
[231]124        }
[378]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;
[231]137
[378]138        int spacing = 1;
139        for(int scale = 1; scale<=numScales; scale++){
[231]140
[378]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];
[3]152       
[378]153            if(!isGood[pos] )  wavelet[pos] = 0.;
154            else{
[3]155
[378]156              for(int xoffset=-filterHW; xoffset<=filterHW; xoffset++){
157                int x = xpos + spacing*xoffset;
[3]158
[378]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                }
[3]164
[378]165                int filterpos = (xoffset+filterHW);
166                int oldpos = x;
[3]167
[378]168                if(isGood[oldpos])
169                  wavelet[pos] -= filter[filterpos]*coeffs[oldpos];
[3]170             
[378]171              } //-> end of xoffset loop
172            } //-> end of else{ ( from if(!isGood[pos])  )
[3]173           
[378]174          } //-> end of xpos loop
[3]175
[378]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];
[3]178
[378]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;
[3]187       
[378]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            }
[231]195          }
[3]196 
[378]197          spacing *= 2;
[3]198
[378]199        } //-> end of scale loop
[3]200
[378]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];
[3]205
[378]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;
[3]213
[378]214        if(par.isVerbose()) printBackSpace(26);
[3]215
[378]216      } while( (iteration==1) ||
217               (fabs(oldsigma-newsigma)/newsigma > reconTolerance) );
[3]218
[378]219      if(par.isVerbose()) std::cout << "Completed "<<iteration<<" iterations. ";
[3]220
[378]221      delete [] filter;
222      delete [] coeffs;
223      delete [] wavelet;
[231]224
[378]225    }
226
227    delete [] isGood;
228    delete [] sigmaFactors;
[231]229  }
230
[3]231}
Note: See TracBrowser for help on using the repository browser.