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

Last change on this file since 1455 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
RevLine 
[299]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// -----------------------------------------------------------------------
[3]28#include <fstream>
29#include <iostream>
30#include <iomanip>
31#include <vector>
[393]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>
[3]40
[258]41using namespace PixelInfo;
[274]42using namespace Statistics;
[258]43
[378]44namespace duchamp
[103]45{
[285]46
[378]47  void Cube::ReconSearch()
48  {
[528]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.
[378]54
55    if(!this->par.getFlagATrous()){
[913]56      DUCHAMPWARN("ReconSearch","You've requested a reconSearch, but not allocated space for the reconstructed array. Doing the basic CubicSearch.");
[378]57      this->CubicSearch();
58    }
59    else {
[188]60 
[378]61      this->ReconCube();
[188]62
[378]63      if(this->par.isVerbose()) std::cout << "  ";
[219]64
[378]65      this->setCubeStats();
[189]66   
[378]67      if(this->par.isVerbose()) std::cout << "  Searching... " << std::flush;
[188]68 
[686]69      *this->objectList = searchReconArray(this->axisDim,this->array,
70                                           this->recon,this->par,this->Stats);
[188]71
[378]72      if(this->par.isVerbose()) std::cout << "  Updating detection map... "
73                                          << std::flush;
74      this->updateDetectMap();
[285]75      if(this->par.isVerbose()) std::cout << "Done.\n";
76
[378]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      }
[188]83
[378]84    }
[285]85  }
[120]86
[378]87  /////////////////////////////////////////////////////////////////////////////
88  void Cube::ReconCube()
89  {
[528]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
[378]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);
[913]103      DUCHAMPWARN("Reconstruction","You requested a " << dimRecon << "-dimensional reconstruction, but the FITS file is only " << numGoodDim << "-dimensional. Changing reconDim to " << numGoodDim );
[103]104    }
105
[378]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){
[913]113          DUCHAMPWARN("Reconstruction", "reconDim (" << dimRecon << ") is less than 1. Performing 1-D reconstruction.");
[378]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...
[913]119          DUCHAMPWARN("Reconstruction", "reconDim (" << dimRecon << ") is more than 3. Performing 3-D reconstruction.");
[378]120          this->par.setReconDim(3);
121          this->ReconCube3D();
122        }
123        break;
124      }
[3]125  }
[103]126
[378]127  /////////////////////////////////////////////////////////////////////////////
128  void Cube::ReconCube1D()
129  {
[528]130    /// This reconstructs a cube by performing a 1D a trous reconstruction
131    ///  in the spectrum of each spatial pixel.
132
[884]133    size_t xySize = this->axisDim[0] * this->axisDim[1];
[3]134
[884]135    size_t zdim = this->axisDim[2];
[3]136
[378]137    ProgressBar bar;
138    if(!this->reconExists){
[725]139      if(this->par.isVerbose()){
140        std::cout<<"  Reconstructing... ";
141        bar.init(xySize);
142      }
[894]143      for(size_t npix=0; npix<xySize; npix++){
[175]144
[725]145        if( this->par.isVerbose() ) bar.update(npix+1);
[175]146
[378]147        float *spec = new float[zdim];
148        float *newSpec = new float[zdim];
[846]149        for(size_t z=0;z<zdim;z++) spec[z] = this->array[z*xySize + npix];
[103]150        bool verboseFlag = this->par.isVerbose();
151        this->par.setVerbosity(false);
[846]152        atrous1DReconstruct(zdim,spec,newSpec,this->par);
[103]153        this->par.setVerbosity(verboseFlag);
[846]154        for(size_t z=0;z<zdim;z++) this->recon[z*xySize+npix] = newSpec[z];
[378]155        delete [] spec;
156        delete [] newSpec;
[3]157      }
[378]158      this->reconExists = true;
[725]159      if(this->par.isVerbose()){
160        bar.fillSpace(" All Done.");
[1384]161        printSpace(std::cout,26);
[725]162        std::cout << "\n";
163      }
[3]164    }
[378]165
[3]166  }
167
[378]168  /////////////////////////////////////////////////////////////////////////////
169  void Cube::ReconCube2D()
170  {
[528]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
[884]174    size_t xySize = this->axisDim[0] * this->axisDim[1];
[378]175    ProgressBar bar;
176    bool useBar = (this->axisDim[2]>1);
[884]177    size_t xdim=this->axisDim[0],ydim=this->axisDim[1];
[3]178
[71]179    if(!this->reconExists){
[725]180      if(this->par.isVerbose()) std::cout<<"  Reconstructing... ";
181      if(useBar&&this->par.isVerbose()) bar.init(this->axisDim[2]);
[894]182      for(size_t z=0;z<this->axisDim[2];z++){
[378]183
[725]184        if( this->par.isVerbose() && useBar ) bar.update((z+1));
[378]185
[1242]186        if(!this->par.isFlaggedChannel(z)){
[378]187          float *im = new float[xySize];
188          float *newIm = new float[xySize];
[894]189          for(size_t npix=0; npix<xySize; npix++)
[378]190            im[npix] = this->array[z*xySize+npix];
191          bool verboseFlag = this->par.isVerbose();
192          this->par.setVerbosity(false);
[846]193          atrous2DReconstruct(xdim,ydim,im,newIm,this->par);
[378]194          this->par.setVerbosity(verboseFlag);
[894]195          for(size_t npix=0; npix<xySize; npix++)
[378]196            this->recon[z*xySize+npix] = newIm[npix];
197          delete [] im;
198          delete [] newIm;
199        }
200        else {
[894]201          for(size_t i=z*xySize; i<(z+1)*xySize; i++)
[378]202            this->recon[i] = this->array[i];
203        }
204      }
[71]205      this->reconExists = true;
[725]206      if(this->par.isVerbose()) {
207        if(useBar) bar.fillSpace(" All Done.");
[1384]208        printSpace(std::cout,26);
[725]209        std::cout << "\n";
210      }
[71]211    }
[3]212  }
213
[378]214  /////////////////////////////////////////////////////////////////////////////
215  void Cube::ReconCube3D()
216  {
[528]217    /// This performs a full 3D a trous reconstruction of the cube
218
[378]219    if(this->axisDim[2]==1) this->ReconCube2D();
220    else {
[884]221      size_t xdim=this->axisDim[0],ydim=this->axisDim[1],zdim=this->axisDim[2];
[378]222      if(!this->reconExists){
[725]223        if(this->par.isVerbose()) std::cout<<"  Reconstructing... "<<std::flush;
[846]224        atrous3DReconstruct(xdim,ydim,zdim,this->array,this->recon,this->par);
[378]225        this->reconExists = true;
[725]226        if(this->par.isVerbose()) {
227          std::cout << "  All Done.";
[1384]228          printSpace(std::cout,26);
[725]229          std::cout << "\n";
230        }
[378]231      }
232
[175]233    }
[378]234  }
[3]235
[378]236  /////////////////////////////////////////////////////////////////////////////
[884]237  std::vector <Detection> searchReconArray(size_t *dim, float *originalArray,
[378]238                                           float *reconArray, Param &par,
239                                           StatsContainer<float> &stats)
240  {
[686]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{
[913]247    DUCHAMPERROR("searchReconArray","Unknown search type : " << par.getSearchType());
[686]248    return std::vector<Detection>(0);
249  }
250  }
251  /////////////////////////////////////////////////////////////////////////////
[884]252  std::vector <Detection> searchReconArraySpectral(size_t *dim, float *originalArray,
[686]253                                                   float *reconArray, Param &par,
254                                                   StatsContainer<float> &stats)
255  {
[528]256    ///  This searches for objects in a cube that has been reconstructed.
257    ///
[686]258    ///  The search is conducted just in each spatial pixel (xdim*ydim 1D
259    ///   searches).
[528]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
[378]272    std::vector <Detection> outputList;
[884]273    size_t zdim = dim[2];
274    size_t xySize = dim[0] * dim[1];
[378]275    int num=0;
276
277    // First search --  in each spectrum.
278    if(zdim > 1){
[3]279
[691]280      ProgressBar bar;
281      if(par.isVerbose()) bar.init(xySize);
282
[1393]283      std::vector<bool> doPixel(xySize,false);
[378]284      // doPixel is a bool array to say whether to look in a given spectrum
[894]285      for(size_t npix=0; npix<xySize; npix++){
[1393]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));
[378]288        }
[1393]289        // doPixel[i] is now false only when there are no good pixels in spectrum of pixel #i.
[378]290      }
[3]291
[884]292      size_t *specdim = new size_t[2];
[378]293      specdim[0] = zdim; specdim[1]=1;
294      Image *spectrum = new Image(specdim);
295      delete [] specdim;
296      spectrum->saveParam(par);
297      spectrum->saveStats(stats);
[1007]298//       spectrum->setMinSize(par.getMinChannels());
299      spectrum->setMinSize(1);
[788]300      // NB the beam is not used after this point
301      // spectrum->pars().setBeamSize(2.);
302      // // beam size: for spectrum, only neighbouring channels correlated
[192]303
[894]304      for(size_t y=0; y<dim[1]; y++){
305        for(size_t x=0; x<dim[0]; x++){
[258]306
[894]307          size_t npix = y*dim[0] + x;
[378]308          if( par.isVerbose() ) bar.update(npix+1);
[258]309
[378]310          if(doPixel[npix]){
311
312            spectrum->extractSpectrum(reconArray,dim,npix);
[1242]313            spectrum->removeFlaggedChannels();
[582]314            std::vector<Scan> objlist = spectrum->findSources1D();
[623]315            std::vector<Scan>::iterator obj;
[378]316            num += objlist.size();
[623]317            for(obj=objlist.begin();obj!=objlist.end();obj++){
[378]318              Detection newObject;
319              // Fix up coordinates of each pixel to match original array
[623]320              for(int z=obj->getX();z<=obj->getXmax();z++) {
[570]321                newObject.addPixel(x,y,z);
[378]322              }
323              newObject.setOffsets(par);
[691]324              if(par.getFlagTwoStageMerging()) mergeIntoList(newObject,outputList,par);
325              else outputList.push_back(newObject);
[258]326            }
[103]327          }
[378]328
[3]329        }
[378]330      }
[258]331
[378]332      delete spectrum;
[691]333     
334      if(par.isVerbose()){
335        bar.remove();
336        std::cout << "Found " << num << ".\n";
337      }
[378]338
[3]339    }
340
[378]341    return outputList;
342  }
[263]343
[378]344  /////////////////////////////////////////////////////////////////////////////
[884]345  std::vector <Detection> searchReconArraySpatial(size_t *dim, float *originalArray,
[686]346                                                  float *reconArray, Param &par,
347                                                  StatsContainer<float> &stats)
[378]348  {
[528]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
[686]352    ///  searches).
[528]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
[378]366    std::vector <Detection> outputList;
[884]367    size_t zdim = dim[2];
[378]368    int num=0;
369    ProgressBar bar;
370    bool useBar = (zdim>1);
371    if(useBar&&par.isVerbose()) bar.init(zdim);
[263]372 
[884]373    size_t *imdim = new size_t[2];
[378]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);
[263]380
[894]381    for(size_t z=0; z<zdim; z++){  // loop over all channels
[263]382
[378]383      if( par.isVerbose() && useBar ) bar.update(z+1);
[263]384
[1242]385      if(!par.isFlaggedChannel(z)){
[1252]386        // purpose of this is to ignore the flagged channels
[263]387
[378]388        channelImage->extractImage(reconArray,dim,z);
[582]389        std::vector<Object2D> objlist = channelImage->findSources2D();
[623]390        std::vector<Object2D>::iterator obj;
[378]391        num += objlist.size();
[623]392        for(obj=objlist.begin();obj!=objlist.end();obj++){
[378]393          Detection newObject;
[623]394          newObject.addChannel(z,*obj);
[378]395          newObject.setOffsets(par);
[691]396          if(par.getFlagTwoStageMerging()) mergeIntoList(newObject,outputList,par);
397          else outputList.push_back(newObject);
[378]398        }
[263]399      }
[378]400   
[263]401    }
402
[378]403    delete channelImage;
[263]404
[378]405    if(par.isVerbose()){
406      if(useBar) bar.remove();
407      std::cout << "Found " << num << ".\n";
408    }
409
410
411    return outputList;
[263]412  }
413
414}
Note: See TracBrowser for help on using the repository browser.