source: tags/release-1.1.8/src/ATrous/atrous_2d_reconstruct.cc @ 1391

Last change on this file since 1391 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: 9.4 KB
Line 
1// -----------------------------------------------------------------------
2// atrous_2d_reconstruct.cc: 2-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/duchamp.hh>
32#include <duchamp/param.hh>
33#include <duchamp/ATrous/atrous.hh>
34#include <duchamp/ATrous/filter.hh>
35#include <duchamp/Utils/utils.hh>
36#include <duchamp/Utils/feedback.hh>
37#include <duchamp/Utils/Statistics.hh>
38using Statistics::madfmToSigma;
39
40namespace duchamp
41{
42
43  void atrous2DReconstruct(long &xdim, long &ydim, float *&input, float *&output, Param &par)
44  {
45    ///  A routine that uses the a trous wavelet method to reconstruct a
46    ///   2-dimensional image.
47    ///
48    ///  If there are no non-BLANK pixels (and we are testing for
49    ///  BLANKs), the reconstruction cannot be done, so we return the
50    ///  input array as the output array and give a warning message.
51    ///
52    ///  \param xdim The length of the x-axis of the image.
53    ///  \param ydim The length of the y-axis of the image.
54    ///  \param input The input spectrum.
55    ///  \param output The returned reconstructed spectrum. This array
56    ///  needs to be declared beforehand.
57    ///  \param par The Param set:contains all necessary info about the
58    ///  filter and reconstruction parameters.
59
60    long size = xdim * ydim;
61    long mindim = xdim;
62    if (ydim<mindim) mindim = ydim;
63    int numScales = par.filter().getNumScales(mindim);
64    double *sigmaFactors = new double[numScales+1];
65    for(int i=0;i<=numScales;i++){
66      if(i<=par.filter().maxFactor(2))
67        sigmaFactors[i] = par.filter().sigmaFactor(2,i);
68      else sigmaFactors[i] = sigmaFactors[i-1] / 2.;
69    }
70
71    float mean,sigma,originalSigma,originalMean,oldsigma,newsigma;
72    int goodSize=0;
73    bool *isGood = new bool[size];
74    for(int pos=0;pos<size;pos++){
75      isGood[pos] = !par.isBlank(input[pos]);
76      if(isGood[pos]) goodSize++;
77    }
78
79    if(goodSize == 0){
80      // There are no good pixels -- everything is BLANK for some reason.
81      // Return the input array as the output, and give a warning message.
82
83      for(int pos=0;pos<size; pos++) output[pos] = input[pos];
84
85      duchampWarning("2D Reconstruction","\
86There are no good pixels to be reconstructed -- all are BLANK.\n\
87Returning input array.\n");
88    }
89    else{
90      // Otherwise, all is good, and we continue.
91
92      float *array = new float[size];
93      goodSize=0;
94      for(int i=0;i<size;i++) if(isGood[i]) array[goodSize++] = input[i];
95      findMedianStats(array,goodSize,originalMean,originalSigma);
96      originalSigma = madfmToSigma(originalSigma);
97      delete [] array;
98 
99      float *coeffs    = new float[size];
100      float *wavelet   = new float[size];
101
102      for(int pos=0;pos<size;pos++) output[pos]=0.;
103
104      int filterwidth = par.filter().width();
105      int filterHW = filterwidth/2;
106      double *filter = new double[filterwidth*filterwidth];
107      for(int i=0;i<filterwidth;i++){
108        for(int j=0;j<filterwidth;j++){
109          filter[i*filterwidth+j] = par.filter().coeff(i) * par.filter().coeff(j);
110        }
111      }
112
113      int *xLim1 = new int[ydim];
114      for(int i=0;i<ydim;i++) xLim1[i] = 0;
115      int *yLim1 = new int[xdim];
116      for(int i=0;i<xdim;i++) yLim1[i] = 0;
117      int *xLim2 = new int[ydim];
118      for(int i=0;i<ydim;i++) xLim2[i] = xdim-1;
119      int *yLim2 = new int[xdim];
120      for(int i=0;i<xdim;i++) yLim2[i] = ydim-1;
121
122      if(par.getFlagBlankPix()){
123        float avGapX = 0, avGapY = 0;
124        for(int row=0;row<ydim;row++){
125          int ct1 = 0;
126          int ct2 = xdim - 1;
127          while((ct1<ct2)&&(par.isBlank(input[row*xdim+ct1]))) ct1++;
128          while((ct2>ct1)&&(par.isBlank(input[row*xdim+ct2]))) ct2--;
129          xLim1[row] = ct1;
130          xLim2[row] = ct2;
131          avGapX += ct2 - ct1;
132        }
133        avGapX /= float(ydim);
134   
135        for(int col=0;col<xdim;col++){
136          int ct1=0;
137          int ct2=ydim-1;
138          while((ct1<ct2)&&(par.isBlank(input[col+xdim*ct1]))) ct1++;
139          while((ct2>ct1)&&(par.isBlank(input[col+xdim*ct2]))) ct2--;
140          yLim1[col] = ct1;
141          yLim2[col] = ct2;
142          avGapY += ct2 - ct1;
143        }
144        avGapY /= float(xdim);
145   
146        mindim = int(avGapX);
147        if(avGapY < avGapX) mindim = int(avGapY);
148        numScales = par.filter().getNumScales(mindim);
149      }
150
151      float threshold;
152      int iteration=0;
153      newsigma = 1.e9;
154      for(int i=0;i<size;i++) output[i] = 0;
155      do{
156        if(par.isVerbose()) {
157          std::cout << "Iteration #"<<std::setw(2)<<++iteration<<":";
158          printBackSpace(13);
159        }
160
161        // first, get the value of oldsigma and set it to the previous
162        //   newsigma value
163        oldsigma = newsigma;
164        // we are transforming the residual array
165        for(int i=0;i<size;i++)  coeffs[i] = input[i] - output[i]; 
166
167        int spacing = 1;
168        for(int scale = 1; scale<numScales; scale++){
169
170          if(par.isVerbose()){
171            std::cout << "Scale ";
172            std::cout << std::setw(2)<<scale<<" / "<<std::setw(2)<<numScales;
173            printBackSpace(13);
174            std::cout <<std::flush;
175          }
176
177          for(int ypos = 0; ypos<ydim; ypos++){
178            for(int xpos = 0; xpos<xdim; xpos++){
179              // loops over each pixel in the image
180              int pos = ypos*xdim + xpos;
181         
182              wavelet[pos] = coeffs[pos];
183
184              if(!isGood[pos]) wavelet[pos] = 0.;
185              else{
186
187                int filterpos = -1;
188                for(int yoffset=-filterHW; yoffset<=filterHW; yoffset++){
189                  int y = ypos + spacing*yoffset;
190                  // Boundary conditions -- assume reflection at boundaries.
191                  // Use limits as calculated above
192                  //          if(yLim1[xpos]!=yLim2[xpos]){
193                  //            // if these are equal we will get into an infinite loop here
194                  //            while((y<yLim1[xpos])||(y>yLim2[xpos])){
195                  //              if(y<yLim1[xpos]) y = 2*yLim1[xpos] - y;     
196                  //              else if(y>yLim2[xpos]) y = 2*yLim2[xpos] - y;     
197                  //            }
198                  //          }
199                  int oldrow = y * xdim;
200         
201                  for(int xoffset=-filterHW; xoffset<=filterHW; xoffset++){
202                    int x = xpos + spacing*xoffset;
203                    // Boundary conditions -- assume reflection at boundaries.
204                    // Use limits as calculated above
205                    //          if(xLim1[ypos]!=xLim2[ypos]){
206                    //            // if these are equal we will get into an infinite loop here
207                    //            while((x<xLim1[ypos])||(x>xLim2[ypos])){
208                    //              if(x<xLim1[ypos]) x = 2*xLim1[ypos] - x;     
209                    //              else if(x>xLim2[ypos]) x = 2*xLim2[ypos] - x;     
210                    //            }
211                    //          }
212
213                    int oldpos = oldrow + x;
214
215                    float oldCoeff;
216                    if((y>=yLim1[xpos])&&(y<=yLim2[xpos])&&
217                       (x>=xLim1[ypos])&&(x<=xLim2[ypos])  )
218                      oldCoeff = coeffs[oldpos];
219                    else oldCoeff = 0.;
220
221                    filterpos++;
222
223                    if(isGood[pos]) wavelet[pos] -= filter[filterpos] * oldCoeff;
224                    //            wavelet[pos] -= filter[filterpos] * coeffs[oldpos];
225
226                  } //-> end of xoffset loop
227                } //-> end of yoffset loop
228              } //-> end of else{ ( from if(!isGood[pos])  )
229       
230            } //-> end of xpos loop
231          } //-> end of ypos loop
232
233          // Need to do this after we've done *all* the convolving
234          for(int pos=0;pos<size;pos++) coeffs[pos] = coeffs[pos] - wavelet[pos];
235
236          // Have found wavelet coeffs for this scale -- now threshold   
237          if(scale>=par.getMinScale()){
238            array = new float[size];
239            goodSize=0;
240            for(int pos=0;pos<size;pos++){
241              if(isGood[pos]) array[goodSize++] = wavelet[pos];
242            }
243            findMedianStats(array,goodSize,mean,sigma);
244            delete [] array;
245
246            threshold = mean +
247              par.getAtrousCut() * originalSigma * sigmaFactors[scale];
248            for(int pos=0;pos<size;pos++){
249              if(!isGood[pos]) output[pos] = input[pos];
250              // preserve the Blank pixel values in the output.
251              else if( fabs(wavelet[pos]) > threshold )
252                output[pos] += wavelet[pos];
253            }
254          }
255          spacing *= 2;
256
257        } // END OF LOOP OVER SCALES
258
259        for(int pos=0;pos<size;pos++) if(isGood[pos]) output[pos] += coeffs[pos];
260
261        array = new float[size];
262        goodSize=0;
263        for(int i=0;i<size;i++){
264          if(isGood[i]) array[goodSize++] = input[i] - output[i];
265        }
266        findMedianStats(array,goodSize,mean,newsigma);
267        newsigma = madfmToSigma(newsigma);
268        delete [] array;
269   
270        if(par.isVerbose()) printBackSpace(15);
271
272      } while( (iteration==1) ||
273               (fabs(oldsigma-newsigma)/newsigma > reconTolerance) );
274
275      if(par.isVerbose()) std::cout << "Completed "<<iteration<<" iterations. ";
276
277      delete [] xLim1;
278      delete [] xLim2;
279      delete [] yLim1;
280      delete [] yLim2;
281      delete [] filter;
282      delete [] coeffs;
283      delete [] wavelet;
284
285    }
286
287    delete [] isGood;
288    delete [] sigmaFactors;
289  }
290   
291}
Note: See TracBrowser for help on using the repository browser.