source: trunk/src/ATrous/ReconSearch.cc @ 377

Last change on this file since 377 was 377, checked in by MatthewWhiting, 17 years ago

Made similar changes to [372].

File size: 13.6 KB
Line 
1// -----------------------------------------------------------------------
2// ReconSearch.cc: Searching a wavelet-reconstructed cube.
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 <fstream>
29#include <iostream>
30#include <iomanip>
31#include <vector>
32#include <duchamp.hh>
33#include <PixelMap/Object3D.hh>
34#include <Cubes/cubes.hh>
35#include <Detection/detection.hh>
36#include <ATrous/atrous.hh>
37#include <Utils/utils.hh>
38#include <Utils/feedback.hh>
39#include <Utils/Statistics.hh>
40
41using namespace PixelInfo;
42using namespace Statistics;
43
44void Cube::ReconSearch()
45{
46  /**
47   * The Cube is first reconstructed, using Cube::ReconCube().
48   * The statistics of the cube are calculated next.
49   * It is then searched, using searchReconArray.
50   * The resulting object list is stored in the Cube, and outputted
51   *  to the log file if the user so requests.
52   */
53
54  if(!this->par.getFlagATrous()){
55    duchampWarning("ReconSearch",
56                   "You've requested a reconSearch, but not allocated space for the reconstructed array.\nDoing the basic CubicSearch.\n");
57    this->CubicSearch();
58  }
59  else {
60 
61    this->ReconCube();
62
63    if(this->par.isVerbose()) std::cout << "  ";
64
65    this->setCubeStats();
66   
67    if(this->par.isVerbose()) std::cout << "  Searching... " << std::flush;
68 
69    *this->objectList = searchReconArraySimple(this->axisDim,this->array,
70                                               this->recon,
71                                               this->par,this->Stats);
72    //   this->objectList = searchReconArray(this->axisDim,this->array,
73    //                                this->recon,this->par,this->Stats);
74
75    if(this->par.isVerbose()) std::cout << "  Updating detection map... "
76                                        << std::flush;
77    this->updateDetectMap();
78    if(this->par.isVerbose()) std::cout << "Done.\n";
79
80    if(this->par.getFlagLog()){
81      if(this->par.isVerbose())
82        std::cout << "  Logging intermediate detections... " << std::flush;
83      this->logDetectionList();
84      if(this->par.isVerbose()) std::cout << "Done.\n";
85    }
86
87  }
88}
89
90/////////////////////////////////////////////////////////////////////////////
91void Cube::ReconCube()
92{
93  /**
94   * A front-end to the various reconstruction functions, the choice of
95   *  which is determined by the use of the reconDim parameter.
96   * Differs from ReconSearch only in that no searching is done.
97   */
98  int dimRecon = this->par.getReconDim();
99  // Test whether we have eg. an image, but have requested a 3-d
100  //  reconstruction.
101  // If dimension of data array is less than dimRecon, change dimRecon
102  //  to the dimension of the array.
103  int numGoodDim = this->head.getNumAxes();
104  if(numGoodDim<dimRecon){
105    dimRecon = numGoodDim;
106    this->par.setReconDim(dimRecon);
107    std::stringstream errmsg;
108    errmsg << "You requested a " << dimRecon << "-dimensional reconstruction,"
109           << " but the FITS file is only " << numGoodDim << "-dimensional.\n"
110           << "Changing reconDim to " << numGoodDim << ".\n";
111    duchampWarning("Reconstruction",errmsg.str());
112  }
113
114  switch(dimRecon)
115    {
116    case 1: this->ReconCube1D(); break;
117    case 2: this->ReconCube2D(); break;
118    case 3: this->ReconCube3D(); break;
119    default:
120      if(dimRecon<=0){
121        std::stringstream errmsg;
122        errmsg << "reconDim (" << dimRecon
123               << ") is less than 1. Performing 1-D reconstruction.\n";
124        duchampWarning("Reconstruction", errmsg.str());
125        this->par.setReconDim(1);
126        this->ReconCube1D();
127      }
128      else if(dimRecon>3){
129        //this probably won't happen with new code above, but just in case...
130        std::stringstream errmsg;
131        errmsg << "reconDim (" << dimRecon
132               << ") is more than 3. Performing 3-D reconstruction.\n";
133        duchampWarning("Reconstruction", errmsg.str());
134        this->par.setReconDim(3);
135        this->ReconCube3D();
136      }
137      break;
138    }
139}
140
141/////////////////////////////////////////////////////////////////////////////
142void Cube::ReconCube1D()
143{
144  /**
145   * This reconstructs a cube by performing a 1D a trous reconstruction
146   *  in the spectrum of each spatial pixel.
147   */
148  long xySize = this->axisDim[0] * this->axisDim[1];
149
150  long zdim = this->axisDim[2];
151
152  ProgressBar bar;
153  if(!this->reconExists){
154    std::cout<<"  Reconstructing... ";
155    if(par.isVerbose()) bar.init(xySize);
156    for(int npix=0; npix<xySize; npix++){
157
158      if( par.isVerbose() ) bar.update(npix+1);
159
160      float *spec = new float[zdim];
161      float *newSpec = new float[zdim];
162      for(int z=0;z<zdim;z++) spec[z] = this->array[z*xySize + npix];
163      bool verboseFlag = this->par.isVerbose();
164      this->par.setVerbosity(false);
165      atrous1DReconstruct(this->axisDim[2],spec,newSpec,this->par);
166      this->par.setVerbosity(verboseFlag);
167      for(int z=0;z<zdim;z++) this->recon[z*xySize+npix] = newSpec[z];
168      delete [] spec;
169      delete [] newSpec;
170    }
171    this->reconExists = true;
172    bar.fillSpace(" All Done.");
173    printSpace(22);
174    std::cout << "\n";
175  }
176
177}
178
179/////////////////////////////////////////////////////////////////////////////
180void Cube::ReconCube2D()
181{
182  /**
183   * This reconstructs a cube by performing a 2D a trous reconstruction
184   *  in each spatial image (ie. each channel map) of the cube.
185   */
186  long xySize = this->axisDim[0] * this->axisDim[1];
187  ProgressBar bar;
188  bool useBar = (this->axisDim[2]>1);
189
190  if(!this->reconExists){
191    std::cout<<"  Reconstructing... ";
192    if(useBar&&par.isVerbose()) bar.init(this->axisDim[2]);
193    for(int z=0;z<this->axisDim[2];z++){
194
195      if( par.isVerbose() && useBar ) bar.update((z+1));
196
197      if(!this->par.isInMW(z)){
198        float *im = new float[xySize];
199        float *newIm = new float[xySize];
200        for(int npix=0; npix<xySize; npix++)
201          im[npix] = this->array[z*xySize+npix];
202        bool verboseFlag = this->par.isVerbose();
203        this->par.setVerbosity(false);
204        atrous2DReconstruct(this->axisDim[0],this->axisDim[1],
205                            im,newIm,this->par);
206        this->par.setVerbosity(verboseFlag);
207        for(int npix=0; npix<xySize; npix++)
208          this->recon[z*xySize+npix] = newIm[npix];
209        delete [] im;
210        delete [] newIm;
211      }
212      else {
213        for(int i=z*xySize; i<(z+1)*xySize; i++)
214          this->recon[i] = this->array[i];
215      }
216    }
217    this->reconExists = true;
218    if(useBar) bar.fillSpace(" All Done.");
219    printSpace(22);
220    std::cout << "\n";
221  }
222}
223
224/////////////////////////////////////////////////////////////////////////////
225void Cube::ReconCube3D()
226{
227  /**
228   * This performs a full 3D a trous reconstruction of the cube
229   */
230  if(this->axisDim[2]==1) this->ReconCube2D();
231  else {
232
233    if(!this->reconExists){
234      std::cout<<"  Reconstructing... "<<std::flush;
235      atrous3DReconstruct(this->axisDim[0],this->axisDim[1],this->axisDim[2],
236                          this->array,this->recon,this->par);
237      this->reconExists = true;
238      std::cout << "  All Done.";
239      printSpace(22);
240      std::cout << "\n";
241    }
242
243  }
244}
245
246/////////////////////////////////////////////////////////////////////////////
247std::vector <Detection> searchReconArray(long *dim, float *originalArray,
248                                         float *reconArray, Param &par,
249                                         StatsContainer<float> &stats)
250{
251  /**
252   *  This searches for objects in a cube that has been reconstructed.
253   *
254   *  The search is conducted first in each spatial pixel (xdim*ydim 1D
255   *   searches), then in each channel image (zdim 2D searches).
256   *  The searches are done on the reconstructed array, although the detected
257   *   objects have fluxes drawn from the corresponding pixels of the original
258   *   array.
259   *
260   *  \param dim Array of dimension sizes
261   *  \param originalArray Original, un-reconstructed image array.
262   *  \param reconArray Reconstructed image array
263   *  \param par The Param set.
264   *  \param stats The StatsContainer that defines what a detection is.
265   *
266   *  \return A vector of Detections resulting from the search.
267   */
268  std::vector <Detection> outputList;
269  long zdim = dim[2];
270  long xySize = dim[0] * dim[1];
271  int num=0;
272  ProgressBar bar;
273
274  // First search --  in each spectrum.
275  if(zdim > 1){
276    if(par.isVerbose()){
277      std::cout << "1D: ";
278      bar.init(xySize);
279    }
280
281    bool *doPixel = new bool[xySize];
282    // doPixel is a bool array to say whether to look in a given spectrum
283    for(int npix=0; npix<xySize; npix++){
284      doPixel[npix] = false;
285      for(int z=0;z<zdim;z++) {
286        doPixel[npix] = doPixel[npix] ||
287          (!par.isBlank(originalArray[npix]) && !par.isInMW(z));
288      }
289      // doPixel[i] is false only when there are no good pixels in spectrum
290      //  of pixel #i.
291    }
292
293    long *specdim = new long[2];
294    specdim[0] = zdim; specdim[1]=1;
295    Image *spectrum = new Image(specdim);
296    delete [] specdim;
297    spectrum->saveParam(par);
298    spectrum->saveStats(stats);
299    spectrum->setMinSize(par.getMinChannels());
300    spectrum->pars().setBeamSize(2.);
301    // beam size: for spectrum, only neighbouring channels correlated
302
303    for(int y=0; y<dim[1]; y++){
304      for(int x=0; x<dim[0]; x++){
305
306        int npix = y*dim[0] + x;
307        if( par.isVerbose() ) bar.update(npix+1);
308
309        if(doPixel[npix]){
310
311          spectrum->extractSpectrum(reconArray,dim,npix);
312          spectrum->removeMW(); // only works if flagMW is true
313          std::vector<Scan> objlist = spectrum->spectrumDetect();
314          num += objlist.size();
315          for(int obj=0;obj<objlist.size();obj++){
316            Detection newObject;
317            // Fix up coordinates of each pixel to match original array
318            for(int z=objlist[obj].getX();z<=objlist[obj].getXmax();z++) {
319              newObject.pixels().addPixel(x,y,z);
320            }
321            newObject.setOffsets(par);
322            mergeIntoList(newObject,outputList,par);
323          }
324        }
325
326      }
327    }
328
329    delete spectrum;
330    delete [] doPixel;
331
332    if(par.isVerbose()) {
333      bar.fillSpace("Found ");
334      std::cout << num <<";" << std::flush;
335    }
336  }
337
338  // Second search --  in each channel
339  if(par.isVerbose()){
340    std::cout << "  2D: ";
341    bar.init(zdim);
342  }
343
344  num = 0;
345
346  long *imdim = new long[2];
347  imdim[0] = dim[0]; imdim[1] = dim[1];
348  Image *channelImage = new Image(imdim);
349  delete [] imdim;
350  channelImage->saveParam(par);
351  channelImage->saveStats(stats);
352  channelImage->setMinSize(par.getMinPix());
353
354  for(int z=0; z<zdim; z++){  // loop over all channels
355
356    if( par.isVerbose() ) bar.update(z+1);
357
358    if(!par.isInMW(z)){
359      // purpose of this is to ignore the Milky Way channels
360      //  if we are flagging them
361
362      channelImage->extractImage(reconArray,dim,z);
363      std::vector<Object2D> objlist = channelImage->lutz_detect();
364      num += objlist.size();
365      for(int obj=0;obj<objlist.size();obj++){
366        Detection newObject;
367        newObject.pixels().addChannel(z,objlist[obj]);
368        newObject.setOffsets(par);
369        mergeIntoList(newObject,outputList,par);
370      }
371    }
372   
373  }
374
375  delete channelImage;
376
377  if(par.isVerbose()){
378    bar.fillSpace("Found ");
379    std::cout << num << ".\n";
380  }
381
382
383  return outputList;
384}
385
386/////////////////////////////////////////////////////////////////////////////
387std::vector <Detection>
388searchReconArraySimple(long *dim, float *originalArray,
389                       float *reconArray, Param &par,
390                       StatsContainer<float> &stats)
391{
392  /**
393   *  This searches for objects in a cube that has been reconstructed.
394   *
395   *  The search is conducted only in each channel image (zdim 2D
396   *  searches) -- no searches in 1D are done.
397   *
398   *  The searches are done on the reconstructed array, although the detected
399   *   objects have fluxes drawn from the corresponding pixels of the original
400   *   array.
401   *
402   *  \param dim Array of dimension sizes
403   *  \param originalArray Original, un-reconstructed image array.
404   *  \param reconArray Reconstructed image array
405   *  \param par The Param set.
406   *  \param stats The StatsContainer that defines what a detection is.
407   *
408   *  \return A vector of Detections resulting from the search.
409   */
410  std::vector <Detection> outputList;
411  long zdim = dim[2];
412  int num=0;
413  ProgressBar bar;
414  bool useBar = (zdim>1);
415  if(useBar&&par.isVerbose()) bar.init(zdim);
416 
417  long *imdim = new long[2];
418  imdim[0] = dim[0]; imdim[1] = dim[1];
419  Image *channelImage = new Image(imdim);
420  delete [] imdim;
421  channelImage->saveParam(par);
422  channelImage->saveStats(stats);
423  channelImage->setMinSize(1);
424
425  for(int z=0; z<zdim; z++){  // loop over all channels
426
427    if( par.isVerbose() && useBar ) bar.update(z+1);
428
429    if(!par.isInMW(z)){
430      // purpose of this is to ignore the Milky Way channels
431      //  if we are flagging them
432
433      channelImage->extractImage(reconArray,dim,z);
434      std::vector<Object2D> objlist = channelImage->lutz_detect();
435      num += objlist.size();
436      for(int obj=0;obj<objlist.size();obj++){
437        Detection newObject;
438        newObject.pixels().addChannel(z,objlist[obj]);
439        newObject.setOffsets(par);
440        mergeIntoList(newObject,outputList,par);
441      }
442    }
443   
444  }
445
446  delete channelImage;
447
448  if(par.isVerbose()){
449    if(useBar) bar.remove();
450    std::cout << "Found " << num << ".\n";
451  }
452
453
454  return outputList;
455}
Note: See TracBrowser for help on using the repository browser.