source: branches/fitshead-branch/ATrous/atrous_3d_reconstruct.cc @ 1441

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

Two sets of large changes:
1) Added reconDim, to select which dimension of reconstruction to use.
2) Changed the way the MW channels are dealt with -- now not set to 0. but

simply ignored for searching purposes.

Summary of changes for each file:
duchamp.hh -- added keyword info for reconDim
param.hh -- Introduced reconDim and flagUsingBlank and isInMW.
param.cc -- Introduced reconDim and flagUsingBlank: initialisation etc commands
InputComplete? -- Added reconDim info
mainDuchamp.cc -- Removed the removeMW call. Changed search function names
docs/Guide.tex -- New code to deal with changes: reconDim, MW removal,

up-to-date output examples, better hints & notes section

Detection/thresholding_functions.cc -- minor typo correction

Cubes/cubes.hh -- added isBlank and removeMW functions in Image class, and

renamed search function prototypes

Cubes/cubes.cc -- added removeMW function for Image class, cleaned up

Cube::removeMW as well (although now not used)

Cubes/outputSpectra.cc -- Improved use of isBlank and isInMW functions: now

show MW channels but don't use them in calculating
the flux range

Cubes/getImage.cc -- added line to indicate whether the Param's blank value

is being used, rather than the FITS header.

Cubes/cubicSearch.cc -- renamed functions: front end is now CubicSearch?, and

searching function is search3DArray.

-- Improved way MW removal is dealt with. Changed

location of stats calculations.

Cubes/saveImage.cc -- added code for saving reconDim info
Cubes/readRecon.cc -- added code for reading reconDim info (and added status

intialisations before all cfitsio commands)

ATrous/ReconSearch.cc -- renamed functions: front end is now ReconSearch?, and

searching function is searchReconArray.
Using reconDim to decide which reconstruction to use.

-- Improved way MW removal is dealt with. Changed

location of stats calculations.

ATrous/atrous_1d_reconstruct.cc -- using Median stats
ATrous/atrous_2d_reconstruct.cc -- made code up to date, to conform with 1- &

3-d code. Removed boundary conditions.

ATrous/atrous_3d_reconstruct.cc -- corrected typo (avGapY /= float(xdim)).

Using median stats.

Cubes/cubicSearchNMerge.cc -- Deleted. (not used)
Cubes/readParams.cc -- Deleted. (not used)

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