source: branches/pixel-map-branch/src/ATrous/ReconSearch.cc @ 251

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

Mainly changes to improve the execution speed and reliability of the searching:

  • Changed the extractSpectrum & extractImage functions, so that they don't call saveArray, but rather just write directly to the flux array.
  • In the searching functions, moved the definitions of spectrum and channelImage (the Image objects) out of the loops over pixels/channels. This way they are only defined once, rather than each time round the loop.
  • Fixed a bug so that the full number of individual detections in the 1D case are reported, rather than the number after the mergeIntoList has done its job.
  • When Merger prints out the counter/size information, the counter number now starts at 1, not 0 (more sensible when comparing to the size).
  • Otherwise, minor presentation tweaks.
File size: 9.5 KB
Line 
1#include <fstream>
2#include <iostream>
3#include <iomanip>
4#include <vector>
5#include <duchamp.hh>
6#include <PixelMap/Object3D.hh>
7#include <Cubes/cubes.hh>
8#include <Detection/detection.hh>
9#include <ATrous/atrous.hh>
10#include <Utils/utils.hh>
11#include <Utils/feedback.hh>
12#include <Utils/Statistics.hh>
13
14void Cube::ReconSearch()
15{
16  /**
17   * The Cube is first reconstructed, using Cube::ReconCube().
18   * The statistics of the cube are calculated next.
19   * It is then searched, using searchReconArray.
20   * The resulting object list is stored in the Cube, and outputted
21   *  to the log file if the user so requests.
22   */
23 
24  this->ReconCube();
25
26  if(this->par.isVerbose()) std::cout << "  ";
27
28  this->setCubeStats();
29   
30  if(this->par.isVerbose()) std::cout << "  Searching... " << std::flush;
31 
32  this->objectList = searchReconArray(this->axisDim,this->array,
33                                      this->recon,this->par,this->Stats);
34
35  if(this->par.isVerbose()) std::cout << "  Updating detection map... "
36                                      << std::flush;
37  this->updateDetectMap();
38  if(this->par.isVerbose()) std::cout << "Done.\n";
39
40  if(this->par.getFlagLog()){
41    if(this->par.isVerbose())
42      std::cout << "  Logging intermediate detections... " << std::flush;
43    this->logDetectionList();
44    if(this->par.isVerbose()) std::cout << "Done.\n";
45  }
46
47}
48
49/////////////////////////////////////////////////////////////////////////////
50void Cube::ReconCube()
51{
52  /**
53   * A front-end to the various reconstruction functions, the choice of
54   *  which is determined by the use of the reconDim parameter.
55   * Differs from ReconSearch only in that no searching is done.
56   */
57  int dimRecon = this->par.getReconDim();
58  // Test whether we have eg. an image, but have requested a 3-d
59  //  reconstruction.
60  // If dimension of data array is less than dimRecon, change dimRecon
61  //  to the dimension of the array.
62  int numGoodDim = 0;
63  for(int i=0;i<this->numDim;i++) if(this->axisDim[i]>1) numGoodDim++;
64  if(numGoodDim<dimRecon) dimRecon = numGoodDim;
65  this->par.setReconDim(dimRecon);
66
67  switch(dimRecon)
68    {
69    case 1: this->ReconCube1D(); break;
70    case 2: this->ReconCube2D(); break;
71    case 3: this->ReconCube3D(); break;
72    default:
73      if(dimRecon<=0){
74        std::stringstream errmsg;
75        errmsg << "reconDim (" << dimRecon
76               << ") is less than 1. Performing 1-D reconstruction.\n";
77        duchampWarning("ReconCube", errmsg.str());
78        this->par.setReconDim(1);
79        this->ReconCube1D();
80      }
81      else if(dimRecon>3){
82        //this probably won't happen with new code above, but just in case...
83        std::stringstream errmsg;
84        errmsg << "reconDim (" << dimRecon
85               << ") is more than 3. Performing 3-D reconstruction.\n";
86        duchampWarning("ReconCube", errmsg.str());
87        this->par.setReconDim(3);
88        this->ReconCube3D();
89      }
90      break;
91    }
92}
93
94/////////////////////////////////////////////////////////////////////////////
95void Cube::ReconCube1D()
96{
97  /**
98   * This reconstructs a cube by performing a 1D a trous reconstruction
99   *  in the spectrum of each spatial pixel.
100   */
101  long xySize = this->axisDim[0] * this->axisDim[1];
102
103  long zdim = this->axisDim[2];
104
105  ProgressBar bar;
106  if(!this->reconExists){
107    std::cout<<"  Reconstructing... ";
108    if(par.isVerbose()) bar.init(xySize);
109    for(int npix=0; npix<xySize; npix++){
110
111      if( par.isVerbose() ) bar.update(npix+1);
112
113      float *spec = new float[zdim];
114      float *newSpec = new float[zdim];
115      for(int z=0;z<zdim;z++) spec[z] = this->array[z*xySize + npix];
116      bool verboseFlag = this->par.isVerbose();
117      this->par.setVerbosity(false);
118      atrous1DReconstruct(this->axisDim[2],spec,newSpec,this->par);
119      this->par.setVerbosity(verboseFlag);
120      for(int z=0;z<zdim;z++) this->recon[z*xySize+npix] = newSpec[z];
121      delete [] spec;
122      delete [] newSpec;
123    }
124    this->reconExists = true;
125    bar.fillSpace(" All Done.");
126    printSpace(22);
127    std::cout << "\n";
128  }
129
130}
131
132/////////////////////////////////////////////////////////////////////////////
133void Cube::ReconCube2D()
134{
135  /**
136   * This reconstructs a cube by performing a 2D a trous reconstruction
137   *  in each spatial image (ie. each channel map) of the cube.
138   */
139  long xySize = this->axisDim[0] * this->axisDim[1];
140  ProgressBar bar;
141
142  if(!this->reconExists){
143    std::cout<<"  Reconstructing... ";
144    if(par.isVerbose()) bar.init(this->axisDim[2]);
145    for(int z=0;z<this->axisDim[2];z++){
146
147      if( par.isVerbose() ) bar.update((z+1));
148
149      if(!this->par.isInMW(z)){
150        float *im = new float[xySize];
151        float *newIm = new float[xySize];
152        for(int npix=0; npix<xySize; npix++)
153          im[npix] = this->array[z*xySize+npix];
154        bool verboseFlag = this->par.isVerbose();
155        this->par.setVerbosity(false);
156        atrous2DReconstruct(this->axisDim[0],this->axisDim[1],
157                            im,newIm,this->par);
158        this->par.setVerbosity(verboseFlag);
159        for(int npix=0; npix<xySize; npix++)
160          this->recon[z*xySize+npix] = newIm[npix];
161        delete [] im;
162        delete [] newIm;
163      }
164      else {
165        for(int i=z*xySize; i<(z+1)*xySize; i++)
166          this->recon[i] = this->array[i];
167      }
168    }
169    this->reconExists = true;
170    bar.fillSpace(" All Done.");
171    printSpace(22);
172    std::cout << "\n";
173  }
174}
175
176/////////////////////////////////////////////////////////////////////////////
177void Cube::ReconCube3D()
178{
179  /**
180   * This performs a full 3D a trous reconstruction of the cube
181   */
182  if(this->axisDim[2]==1) this->ReconCube2D();
183  else {
184
185    if(!this->reconExists){
186      std::cout<<"  Reconstructing... "<<std::flush;
187      atrous3DReconstruct(this->axisDim[0],this->axisDim[1],this->axisDim[2],
188                          this->array,this->recon,this->par);
189      this->reconExists = true;
190      std::cout << "  All Done.";
191      printSpace(22);
192      std::cout << "\n";
193    }
194
195  }
196}
197
198/////////////////////////////////////////////////////////////////////////////
199std::vector <Detection> searchReconArray(long *dim, float *originalArray,
200                                         float *reconArray, Param &par,
201                                         StatsContainer<float> &stats)
202{
203  /**
204   *  This searches for objects in a cube that has been reconstructed.
205   *
206   *  The search is conducted first in each spatial pixel (xdim*ydim 1D
207   *   searches), then in each channel image (zdim 2D searches).
208   *  The searches are done on the reconstructed array, although the detected
209   *   objects have fluxes drawn from the corresponding pixels of the original
210   *   array.
211   *
212   *  \param dim Array of dimension sizes
213   *  \param originalArray Original, un-reconstructed image array.
214   *  \param reconArray Reconstructed image array
215   *  \param par The Param set.
216   *  \param stats The StatsContainer that defines what a detection is.
217   *
218   *  \return A vector of Detections resulting from the search.
219   */
220  std::vector <Detection> outputList;
221  long zdim = dim[2];
222  long xySize = dim[0] * dim[1];
223  int num=0;
224  ProgressBar bar;
225
226  // First search --  in each spectrum.
227  if(zdim > 1){
228    if(par.isVerbose()){
229      std::cout << "1D: ";
230      bar.init(xySize);
231    }
232
233    bool *doPixel = new bool[xySize];
234    // doPixel is a bool array to say whether to look in a given spectrum
235    for(int npix=0; npix<xySize; npix++){
236      doPixel[npix] = false;
237      for(int z=0;z<zdim;z++) {
238        doPixel[npix] = doPixel[npix] ||
239          (!par.isBlank(originalArray[npix]) && !par.isInMW(z));
240      }
241      // doPixel[i] is false only when there are no good pixels in spectrum
242      //  of pixel #i.
243    }
244
245    long *specdim = new long[2];
246    specdim[0] = zdim; specdim[1]=1;
247    Image *spectrum = new Image(specdim);
248    delete [] specdim;
249    spectrum->saveParam(par);
250    spectrum->saveStats(stats);
251    spectrum->setMinSize(par.getMinChannels());
252    spectrum->pars().setBeamSize(2.);
253    // beam size: for spectrum, only neighbouring channels correlated
254
255    for(int y=0; y<dim[1]; y++){
256      for(int x=0; x<dim[0]; x++){
257
258        int npix = y*dim[0] + x;
259        if( par.isVerbose() ) bar.update(npix+1);
260
261        if(doPixel[npix]){
262
263          spectrum->extractSpectrum(reconArray,dim,npix);
264          spectrum->removeMW(); // only works if flagMW is true
265          std::vector<Scan> objlist = spectrum->spectrumDetect();
266          num += objlist.size();
267          for(int obj=0;obj<objlist.size();obj++){
268            Detection newObject;
269            // Fix up coordinates of each pixel to match original array
270            for(int z=objlist[obj].getX();z<=objlist[obj].getXmax();z++) {
271              newObject.pixels().addPixel(x,y,z);
272            }
273            newObject.setOffsets(par);
274            mergeIntoList(newObject,outputList,par);
275          }
276        }
277
278      }
279    }
280
281    delete spectrum;
282    delete [] doPixel;
283
284    if(par.isVerbose()) {
285      bar.fillSpace("Found ");
286      std::cout << num <<";" << std::flush;
287    }
288  }
289
290  // Second search --  in each channel
291  if(par.isVerbose()){
292    std::cout << "  2D: ";
293    bar.init(zdim);
294  }
295
296  num = 0;
297
298  long *imdim = new long[2];
299  imdim[0] = dim[0]; imdim[1] = dim[1];
300  Image *channelImage = new Image(imdim);
301  delete [] imdim;
302  channelImage->saveParam(par);
303  channelImage->saveStats(stats);
304  channelImage->setMinSize(par.getMinPix());
305
306  for(int z=0; z<zdim; z++){  // loop over all channels
307
308    if( par.isVerbose() ) bar.update(z+1);
309
310    if(!par.isInMW(z)){
311      // purpose of this is to ignore the Milky Way channels
312      //  if we are flagging them
313
314      channelImage->extractImage(reconArray,dim,z);
315      std::vector<Object2D> objlist = channelImage->lutz_detect();
316      num += objlist.size();
317      for(int obj=0;obj<objlist.size();obj++){
318        Detection newObject;
319        newObject.pixels().addChannel(z,objlist[obj]);
320        newObject.setOffsets(par);
321        mergeIntoList(newObject,outputList,par);
322      }
323    }
324   
325  }
326
327  delete channelImage;
328
329  if(par.isVerbose()){
330    bar.fillSpace("Found ");
331    std::cout << num << ".\n";
332  }
333
334
335  return outputList;
336}
Note: See TracBrowser for help on using the repository browser.