source: trunk/src/ATrous/ReconSearch.cc

Last change on this file was 1393, checked in by MatthewWhiting, 10 years ago

A large changeset that moves all use of bool arrays (ie. bool *) to std::vector<bool>. This will be a bit safer, plus potentially cheaper in memory usage. Interfaces to all stats functions with masks have changed accordingly, as well as the Gaussian smoothing functions and some spectral utility functions.

File size: 13.5 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      DUCHAMPWARN("Reconstruction","You requested a " << dimRecon << "-dimensional reconstruction, but the FITS file is only " << numGoodDim << "-dimensional. Changing reconDim to " << numGoodDim );
104    }
105
106    switch(dimRecon)
107      {
108      case 1: this->ReconCube1D(); break;
109      case 2: this->ReconCube2D(); break;
110      case 3: this->ReconCube3D(); break;
111      default:
112        if(dimRecon<=0){
113          DUCHAMPWARN("Reconstruction", "reconDim (" << dimRecon << ") is less than 1. Performing 1-D reconstruction.");
114          this->par.setReconDim(1);
115          this->ReconCube1D();
116        }
117        else if(dimRecon>3){
118          //this probably won't happen with new code above, but just in case...
119          DUCHAMPWARN("Reconstruction", "reconDim (" << dimRecon << ") is more than 3. Performing 3-D reconstruction.");
120          this->par.setReconDim(3);
121          this->ReconCube3D();
122        }
123        break;
124      }
125  }
126
127  /////////////////////////////////////////////////////////////////////////////
128  void Cube::ReconCube1D()
129  {
130    /// This reconstructs a cube by performing a 1D a trous reconstruction
131    ///  in the spectrum of each spatial pixel.
132
133    size_t xySize = this->axisDim[0] * this->axisDim[1];
134
135    size_t zdim = this->axisDim[2];
136
137    ProgressBar bar;
138    if(!this->reconExists){
139      if(this->par.isVerbose()){
140        std::cout<<"  Reconstructing... ";
141        bar.init(xySize);
142      }
143      for(size_t npix=0; npix<xySize; npix++){
144
145        if( this->par.isVerbose() ) bar.update(npix+1);
146
147        float *spec = new float[zdim];
148        float *newSpec = new float[zdim];
149        for(size_t z=0;z<zdim;z++) spec[z] = this->array[z*xySize + npix];
150        bool verboseFlag = this->par.isVerbose();
151        this->par.setVerbosity(false);
152        atrous1DReconstruct(zdim,spec,newSpec,this->par);
153        this->par.setVerbosity(verboseFlag);
154        for(size_t z=0;z<zdim;z++) this->recon[z*xySize+npix] = newSpec[z];
155        delete [] spec;
156        delete [] newSpec;
157      }
158      this->reconExists = true;
159      if(this->par.isVerbose()){
160        bar.fillSpace(" All Done.");
161        printSpace(std::cout,26);
162        std::cout << "\n";
163      }
164    }
165
166  }
167
168  /////////////////////////////////////////////////////////////////////////////
169  void Cube::ReconCube2D()
170  {
171    /// This reconstructs a cube by performing a 2D a trous reconstruction
172    ///  in each spatial image (ie. each channel map) of the cube.
173
174    size_t xySize = this->axisDim[0] * this->axisDim[1];
175    ProgressBar bar;
176    bool useBar = (this->axisDim[2]>1);
177    size_t xdim=this->axisDim[0],ydim=this->axisDim[1];
178
179    if(!this->reconExists){
180      if(this->par.isVerbose()) std::cout<<"  Reconstructing... ";
181      if(useBar&&this->par.isVerbose()) bar.init(this->axisDim[2]);
182      for(size_t z=0;z<this->axisDim[2];z++){
183
184        if( this->par.isVerbose() && useBar ) bar.update((z+1));
185
186        if(!this->par.isFlaggedChannel(z)){
187          float *im = new float[xySize];
188          float *newIm = new float[xySize];
189          for(size_t npix=0; npix<xySize; npix++)
190            im[npix] = this->array[z*xySize+npix];
191          bool verboseFlag = this->par.isVerbose();
192          this->par.setVerbosity(false);
193          atrous2DReconstruct(xdim,ydim,im,newIm,this->par);
194          this->par.setVerbosity(verboseFlag);
195          for(size_t npix=0; npix<xySize; npix++)
196            this->recon[z*xySize+npix] = newIm[npix];
197          delete [] im;
198          delete [] newIm;
199        }
200        else {
201          for(size_t i=z*xySize; i<(z+1)*xySize; i++)
202            this->recon[i] = this->array[i];
203        }
204      }
205      this->reconExists = true;
206      if(this->par.isVerbose()) {
207        if(useBar) bar.fillSpace(" All Done.");
208        printSpace(std::cout,26);
209        std::cout << "\n";
210      }
211    }
212  }
213
214  /////////////////////////////////////////////////////////////////////////////
215  void Cube::ReconCube3D()
216  {
217    /// This performs a full 3D a trous reconstruction of the cube
218
219    if(this->axisDim[2]==1) this->ReconCube2D();
220    else {
221      size_t xdim=this->axisDim[0],ydim=this->axisDim[1],zdim=this->axisDim[2];
222      if(!this->reconExists){
223        if(this->par.isVerbose()) std::cout<<"  Reconstructing... "<<std::flush;
224        atrous3DReconstruct(xdim,ydim,zdim,this->array,this->recon,this->par);
225        this->reconExists = true;
226        if(this->par.isVerbose()) {
227          std::cout << "  All Done.";
228          printSpace(std::cout,26);
229          std::cout << "\n";
230        }
231      }
232
233    }
234  }
235
236  /////////////////////////////////////////////////////////////////////////////
237  std::vector <Detection> searchReconArray(size_t *dim, float *originalArray,
238                                           float *reconArray, Param &par,
239                                           StatsContainer<float> &stats)
240  {
241
242  if(par.getSearchType()=="spectral")
243    return searchReconArraySpectral(dim,originalArray,reconArray,par,stats);
244  else if(par.getSearchType()=="spatial")
245    return searchReconArraySpatial(dim,originalArray,reconArray,par,stats);
246  else{
247    DUCHAMPERROR("searchReconArray","Unknown search type : " << par.getSearchType());
248    return std::vector<Detection>(0);
249  }
250  }
251  /////////////////////////////////////////////////////////////////////////////
252  std::vector <Detection> searchReconArraySpectral(size_t *dim, float *originalArray,
253                                                   float *reconArray, Param &par,
254                                                   StatsContainer<float> &stats)
255  {
256    ///  This searches for objects in a cube that has been reconstructed.
257    ///
258    ///  The search is conducted just in each spatial pixel (xdim*ydim 1D
259    ///   searches).
260    ///  The searches are done on the reconstructed array, although the detected
261    ///   objects have fluxes drawn from the corresponding pixels of the original
262    ///   array.
263    ///
264    ///  \param dim Array of dimension sizes
265    ///  \param originalArray Original, un-reconstructed image array.
266    ///  \param reconArray Reconstructed image array
267    ///  \param par The Param set.
268    ///  \param stats The StatsContainer that defines what a detection is.
269    ///
270    ///  \return A vector of Detections resulting from the search.
271
272    std::vector <Detection> outputList;
273    size_t zdim = dim[2];
274    size_t xySize = dim[0] * dim[1];
275    int num=0;
276
277    // First search --  in each spectrum.
278    if(zdim > 1){
279
280      ProgressBar bar;
281      if(par.isVerbose()) bar.init(xySize);
282
283      std::vector<bool> doPixel(xySize,false);
284      // doPixel is a bool array to say whether to look in a given spectrum
285      for(size_t npix=0; npix<xySize; npix++){
286        for(size_t z=0;z<zdim && !doPixel[npix];z++) {
287          doPixel[npix] = doPixel[npix] || (!par.isBlank(originalArray[npix+xySize*z]) && !par.isFlaggedChannel(z));
288        }
289        // doPixel[i] is now false only when there are no good pixels in spectrum of pixel #i.
290      }
291
292      size_t *specdim = new size_t[2];
293      specdim[0] = zdim; specdim[1]=1;
294      Image *spectrum = new Image(specdim);
295      delete [] specdim;
296      spectrum->saveParam(par);
297      spectrum->saveStats(stats);
298//       spectrum->setMinSize(par.getMinChannels());
299      spectrum->setMinSize(1);
300      // NB the beam is not used after this point
301      // spectrum->pars().setBeamSize(2.);
302      // // beam size: for spectrum, only neighbouring channels correlated
303
304      for(size_t y=0; y<dim[1]; y++){
305        for(size_t x=0; x<dim[0]; x++){
306
307          size_t npix = y*dim[0] + x;
308          if( par.isVerbose() ) bar.update(npix+1);
309
310          if(doPixel[npix]){
311
312            spectrum->extractSpectrum(reconArray,dim,npix);
313            spectrum->removeFlaggedChannels();
314            std::vector<Scan> objlist = spectrum->findSources1D();
315            std::vector<Scan>::iterator obj;
316            num += objlist.size();
317            for(obj=objlist.begin();obj!=objlist.end();obj++){
318              Detection newObject;
319              // Fix up coordinates of each pixel to match original array
320              for(int z=obj->getX();z<=obj->getXmax();z++) {
321                newObject.addPixel(x,y,z);
322              }
323              newObject.setOffsets(par);
324              if(par.getFlagTwoStageMerging()) mergeIntoList(newObject,outputList,par);
325              else outputList.push_back(newObject);
326            }
327          }
328
329        }
330      }
331
332      delete spectrum;
333     
334      if(par.isVerbose()){
335        bar.remove();
336        std::cout << "Found " << num << ".\n";
337      }
338
339    }
340
341    return outputList;
342  }
343
344  /////////////////////////////////////////////////////////////////////////////
345  std::vector <Detection> searchReconArraySpatial(size_t *dim, float *originalArray,
346                                                  float *reconArray, Param &par,
347                                                  StatsContainer<float> &stats)
348  {
349    ///  This searches for objects in a cube that has been reconstructed.
350    ///
351    ///  The search is conducted only in each channel image (zdim 2D
352    ///  searches).
353    ///
354    ///  The searches are done on the reconstructed array, although the detected
355    ///   objects have fluxes drawn from the corresponding pixels of the original
356    ///   array.
357    ///
358    ///  \param dim Array of dimension sizes
359    ///  \param originalArray Original, un-reconstructed image array.
360    ///  \param reconArray Reconstructed image array
361    ///  \param par The Param set.
362    ///  \param stats The StatsContainer that defines what a detection is.
363    ///
364    ///  \return A vector of Detections resulting from the search.
365
366    std::vector <Detection> outputList;
367    size_t zdim = dim[2];
368    int num=0;
369    ProgressBar bar;
370    bool useBar = (zdim>1);
371    if(useBar&&par.isVerbose()) bar.init(zdim);
372 
373    size_t *imdim = new size_t[2];
374    imdim[0] = dim[0]; imdim[1] = dim[1];
375    Image *channelImage = new Image(imdim);
376    delete [] imdim;
377    channelImage->saveParam(par);
378    channelImage->saveStats(stats);
379    channelImage->setMinSize(1);
380
381    for(size_t z=0; z<zdim; z++){  // loop over all channels
382
383      if( par.isVerbose() && useBar ) bar.update(z+1);
384
385      if(!par.isFlaggedChannel(z)){
386        // purpose of this is to ignore the flagged channels
387
388        channelImage->extractImage(reconArray,dim,z);
389        std::vector<Object2D> objlist = channelImage->findSources2D();
390        std::vector<Object2D>::iterator obj;
391        num += objlist.size();
392        for(obj=objlist.begin();obj!=objlist.end();obj++){
393          Detection newObject;
394          newObject.addChannel(z,*obj);
395          newObject.setOffsets(par);
396          if(par.getFlagTwoStageMerging()) mergeIntoList(newObject,outputList,par);
397          else outputList.push_back(newObject);
398        }
399      }
400   
401    }
402
403    delete channelImage;
404
405    if(par.isVerbose()){
406      if(useBar) bar.remove();
407      std::cout << "Found " << num << ".\n";
408    }
409
410
411    return outputList;
412  }
413
414}
Note: See TracBrowser for help on using the repository browser.