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

Last change on this file since 913 was 913, checked in by MatthewWhiting, 12 years ago

A large swathe of changes aimed at improving warning/error/exception handling. Now make use of macros and streams. Also, there is now a distinction between DUCHAMPERROR and DUCHAMPTHROW.

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