source: tags/release-1.1/src/ATrous/atrous_1d_reconstruct.cc @ 1391

Last change on this file since 1391 was 299, checked in by Matthew Whiting, 17 years ago

Adding distribution text at the start of each file...

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