source: trunk/src/ATrous/atrous_3d_reconstruct.cc @ 211

Last change on this file since 211 was 205, checked in by Matthew Whiting, 18 years ago

Changes here mostly aimed at reducing/removing memory leaks. These were one of:

  • Forgetting to delete something allocated with "new". The Cube destructor has improved with the use of bool variables to keep track of when recon & baseline ahave been allocated.
  • Incorrectly using the wcs->flag parameter (eg. wcsIO had it set to -1 *after* calling wcsini)
  • Not closing a fits file once finished with (dataIO)
  • Allocating the wcsprm structs with calloc before calling wcsini, so that wcsvfree can work (it calls "free", so the memory needs to be allocated with calloc or malloc).

The only other change was the following:

  • A new way of doing the Cube::setCubeStats -- rather than calling the functions in getStats.cc, we explicitly do the calculations. This means we can sort the tempArray that has the BLANKS etc removed. This saves a great deal of memory usage on large FITS files (such as Enno's 2Gb one)
  • The old setCubeStats function is still there but called setCubeStatsOld.
File size: 7.8 KB
Line 
1#include <iostream>
2#include <iomanip>
3#include <math.h>
4#include <duchamp.hh>
5#include <ATrous/atrous.hh>
6#include <Utils/utils.hh>
7#include <Utils/Statistics.hh>
8using Statistics::madfmToSigma;
9
10using std::endl;
11using std::setw;
12
13void atrous3DReconstruct(long &xdim, long &ydim, long &zdim, float *&input,
14                         float *&output, Param &par)
15{
16  /**
17   *  atrous3DReconstruct(xdim, ydim, zdim, input, output, par)
18   *
19   *  A routine that uses the a trous wavelet method to reconstruct a
20   *   3-dimensional image cube.
21   *  The Param object "par" contains all necessary info about the filter and
22   *   reconstruction parameters, although a Filter object has to be declared
23   *   elsewhere previously.
24   *  The input array is in "input", of dimensions "xdim"x"ydim"x"zdim", and
25   *   the reconstructed array is in "output".
26   */
27
28  extern Filter reconFilter;
29  long size = xdim * ydim * zdim;
30  long spatialSize = xdim * ydim;
31  long mindim = xdim;
32  if (ydim<mindim) mindim = ydim;
33  if (zdim<mindim) mindim = zdim;
34  int numScales = reconFilter.getNumScales(mindim);
35
36  double *sigmaFactors = new double[numScales+1];
37  for(int i=0;i<=numScales;i++){
38    if(i<=reconFilter.maxFactor(3))
39      sigmaFactors[i] = reconFilter.sigmaFactor(3,i);
40    else sigmaFactors[i] = sigmaFactors[i-1] / sqrt(8.);
41  }
42
43  float mean,sigma,originalSigma,originalMean,oldsigma,newsigma;
44  bool *isGood = new bool[size];
45  float blankPixValue = par.getBlankPixVal();
46  for(int pos=0;pos<size;pos++){
47    isGood[pos] = !par.isBlank(input[pos]);
48  }
49
50  float *array = new float[size];
51  int goodSize=0;
52  for(int i=0;i<size;i++) if(isGood[i]) array[goodSize++] = input[i];
53  findMedianStats(array,goodSize,originalMean,originalSigma);
54  originalSigma = madfmToSigma(originalSigma);
55  delete [] array;
56
57  float *coeffs = new float[size];
58  float *wavelet = new float[size];
59
60  for(int pos=0;pos<size;pos++) output[pos]=0.;
61
62  // Define the 3-D (separable) filter, using info from reconFilter
63  int filterwidth = reconFilter.width();
64  int filterHW = filterwidth/2;
65  int fsize = filterwidth*filterwidth*filterwidth;
66  double *filter = new double[fsize];
67  for(int i=0;i<filterwidth;i++){
68    for(int j=0;j<filterwidth;j++){
69      for(int k=0;k<filterwidth;k++){
70      filter[i +j*filterwidth + k*filterwidth*filterwidth] =
71        reconFilter.coeff(i) * reconFilter.coeff(j) * reconFilter.coeff(k);
72      }
73    }
74  }
75
76  // Locating the borders of the image -- ignoring BLANK pixels
77  //  Only do this if flagBlankPix is true.
78  //  Otherwise use the full range of x and y.
79  //  No trimming is done in the z-direction at this point.
80  int *xLim1 = new int[ydim];
81  for(int i=0;i<ydim;i++) xLim1[i] = 0;
82  int *xLim2 = new int[ydim];
83  for(int i=0;i<ydim;i++) xLim2[i] = xdim-1;
84  int *yLim1 = new int[xdim];
85  for(int i=0;i<xdim;i++) yLim1[i] = 0;
86  int *yLim2 = new int[xdim];
87  for(int i=0;i<xdim;i++) yLim2[i] = ydim-1;
88
89  if(par.getFlagBlankPix()){
90    float avGapX = 0, avGapY = 0;
91    for(int row=0;row<ydim;row++){
92      int ct1 = 0;
93      int ct2 = xdim - 1;
94      while((ct1<ct2)&&(par.isBlank(input[row*xdim+ct1]))) ct1++;
95      while((ct2>ct1)&&(par.isBlank(input[row*xdim+ct2]))) ct2--;
96      xLim1[row] = ct1;
97      xLim2[row] = ct2;
98      avGapX += ct2 - ct1 + 1;
99    }
100    avGapX /= float(ydim);
101
102    for(int col=0;col<xdim;col++){
103      int ct1=0;
104      int ct2=ydim-1;
105      while((ct1<ct2)&&(par.isBlank(input[col+xdim*ct1]))) ct1++;
106      while((ct2>ct1)&&(par.isBlank(input[col+xdim*ct2]))) ct2--;
107      yLim1[col] = ct1;
108      yLim2[col] = ct2;
109      avGapY += ct2 - ct1 + 1;
110    }
111    avGapY /= float(xdim);
112 
113    mindim = int(avGapX);
114    if(avGapY < avGapX) mindim = int(avGapY);
115    numScales = reconFilter.getNumScales(mindim);
116  }
117
118  float threshold;
119  int iteration=0;
120  newsigma = 1.e9;
121  for(int i=0;i<size;i++) output[i] = 0;
122  do{
123    if(par.isVerbose()) std::cout << "Iteration #"<<setw(2)<<++iteration<<": ";
124    // first, get the value of oldsigma, set it to the previous newsigma value
125    oldsigma = newsigma;
126    // we are transforming the residual array (input array first time around)
127    for(int i=0;i<size;i++)  coeffs[i] = input[i] - output[i];
128
129    int spacing = 1;
130    for(int scale = 1; scale<=numScales; scale++){
131
132      if(par.isVerbose()){
133        std::cout << "Scale ";
134        std::cout << setw(2)<<scale<<" / "<<setw(2)<<numScales;
135        printBackSpace(13);
136        std::cout << std::flush;
137      }
138
139      int pos = -1;
140      for(int zpos = 0; zpos<zdim; zpos++){
141        for(int ypos = 0; ypos<ydim; ypos++){
142          for(int xpos = 0; xpos<xdim; xpos++){
143            // loops over each pixel in the image
144            pos++;
145
146            wavelet[pos] = coeffs[pos];
147           
148            if(!isGood[pos] )  wavelet[pos] = 0.;
149            else{
150
151              int filterpos = -1;
152              for(int zoffset=-filterHW; zoffset<=filterHW; zoffset++){
153                int z = zpos + spacing*zoffset;
154                if(z<0) z = -z;                 // boundary conditions are
155                if(z>=zdim) z = 2*(zdim-1) - z; //    reflection.
156               
157                int oldchan = z * spatialSize;
158               
159                for(int yoffset=-filterHW; yoffset<=filterHW; yoffset++){
160                  int y = ypos + spacing*yoffset;
161
162                  // Boundary conditions -- assume reflection at boundaries.
163                  // Use limits as calculated above
164                  if(yLim1[xpos]!=yLim2[xpos]){
165                    // if these are equal we will get into an infinite loop
166                    while((y<yLim1[xpos])||(y>yLim2[xpos])){
167                      if(y<yLim1[xpos]) y = 2*yLim1[xpos] - y;     
168                      else if(y>yLim2[xpos]) y = 2*yLim2[xpos] - y;     
169                    }
170                  }
171                  int oldrow = y * xdim;
172         
173                  for(int xoffset=-filterHW; xoffset<=filterHW; xoffset++){
174                    int x = xpos + spacing*xoffset;
175
176                    // Boundary conditions -- assume reflection at boundaries.
177                    // Use limits as calculated above
178                    if(xLim1[ypos]!=xLim2[ypos]){
179                      // if these are equal we will get into an infinite loop
180                      while((x<xLim1[ypos])||(x>xLim2[ypos])){
181                        if(x<xLim1[ypos]) x = 2*xLim1[ypos] - x;     
182                        else if(x>xLim2[ypos]) x = 2*xLim2[ypos] - x;     
183                      }
184                    }
185
186                    int oldpos = oldchan + oldrow + x;
187
188                    filterpos++;
189                   
190                    if(isGood[oldpos])
191                      wavelet[pos] -= filter[filterpos]*coeffs[oldpos];
192                     
193                  } //-> end of xoffset loop
194                } //-> end of yoffset loop
195              } //-> end of zoffset loop
196            } //-> end of else{ ( from if(!isGood[pos])  )
197           
198          } //-> end of xpos loop
199        } //-> end of ypos loop
200      } //-> end of zpos loop
201
202      // Need to do this after we've done *all* the convolving
203      for(int pos=0;pos<size;pos++) coeffs[pos] = coeffs[pos] - wavelet[pos];
204
205      // Have found wavelet coeffs for this scale -- now threshold
206      if(scale>=par.getMinScale()){
207        array = new float[size];
208        goodSize=0;
209        for(int pos=0;pos<size;pos++)
210          if(isGood[pos]) array[goodSize++] = wavelet[pos];
211        findMedianStats(array,goodSize,mean,sigma);
212        delete [] array;
213       
214        threshold = mean +
215          par.getAtrousCut()*originalSigma*sigmaFactors[scale];
216        for(int pos=0;pos<size;pos++){
217          if(!isGood[pos]){
218            output[pos] = blankPixValue;
219            // this preserves the Blank pixel values in the output.
220          }
221          else if( fabs(wavelet[pos]) > threshold ){
222            output[pos] += wavelet[pos];
223            // only add to the output if the wavelet coefficient is significant
224          }
225        }
226      }
227 
228      spacing *= 2;  // double the scale of the filter.
229
230    } //-> end of scale loop
231
232    for(int pos=0;pos<size;pos++) if(isGood[pos]) output[pos] += coeffs[pos];
233
234    array = new float[size];
235    goodSize=0;
236    for(int i=0;i<size;i++) {
237      if(isGood[i]) array[goodSize++] = input[i] - output[i];
238    }
239    findMedianStats(array,goodSize,mean,newsigma);
240    newsigma = madfmToSigma(newsigma);
241    delete [] array;
242
243    if(par.isVerbose()) printBackSpace(15);
244
245  } while( (iteration==1) ||
246           (fabs(oldsigma-newsigma)/newsigma > reconTolerance) );
247
248  if(par.isVerbose()) std::cout << "Completed "<<iteration<<" iterations. ";
249
250  delete [] xLim1;
251  delete [] xLim2;
252  delete [] yLim1;
253  delete [] yLim2;
254  delete [] coeffs;
255  delete [] wavelet;
256  delete [] isGood;
257  delete [] filter;
258  delete [] sigmaFactors;
259}
Note: See TracBrowser for help on using the repository browser.