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

Last change on this file since 1242 was 1242, checked in by MatthewWhiting, 11 years ago

Tickets #193 & #195 - Implementing channel flagging. Still a lot of commented-out code, plus the MW code is still present (although not used anywhere). Also making use of the new plotting classes.

File size: 14.1 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.");
161        printSpace(22);
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]);
[1242]182//      std::vector<bool> flaggedChans=par.getChannelFlags(this->axisDim[2]);
[894]183      for(size_t z=0;z<this->axisDim[2];z++){
[378]184
[725]185        if( this->par.isVerbose() && useBar ) bar.update((z+1));
[378]186
[1242]187        // if(!this->par.isInMW(z)){
188//      if(!flaggedChans[z]){
189        if(!this->par.isFlaggedChannel(z)){
[378]190          float *im = new float[xySize];
191          float *newIm = new float[xySize];
[894]192          for(size_t npix=0; npix<xySize; npix++)
[378]193            im[npix] = this->array[z*xySize+npix];
194          bool verboseFlag = this->par.isVerbose();
195          this->par.setVerbosity(false);
[846]196          atrous2DReconstruct(xdim,ydim,im,newIm,this->par);
[378]197          this->par.setVerbosity(verboseFlag);
[894]198          for(size_t npix=0; npix<xySize; npix++)
[378]199            this->recon[z*xySize+npix] = newIm[npix];
200          delete [] im;
201          delete [] newIm;
202        }
203        else {
[894]204          for(size_t i=z*xySize; i<(z+1)*xySize; i++)
[378]205            this->recon[i] = this->array[i];
206        }
207      }
[71]208      this->reconExists = true;
[725]209      if(this->par.isVerbose()) {
210        if(useBar) bar.fillSpace(" All Done.");
211        printSpace(22);
212        std::cout << "\n";
213      }
[71]214    }
[3]215  }
216
[378]217  /////////////////////////////////////////////////////////////////////////////
218  void Cube::ReconCube3D()
219  {
[528]220    /// This performs a full 3D a trous reconstruction of the cube
221
[378]222    if(this->axisDim[2]==1) this->ReconCube2D();
223    else {
[884]224      size_t xdim=this->axisDim[0],ydim=this->axisDim[1],zdim=this->axisDim[2];
[378]225      if(!this->reconExists){
[725]226        if(this->par.isVerbose()) std::cout<<"  Reconstructing... "<<std::flush;
[846]227        atrous3DReconstruct(xdim,ydim,zdim,this->array,this->recon,this->par);
[378]228        this->reconExists = true;
[725]229        if(this->par.isVerbose()) {
230          std::cout << "  All Done.";
231          printSpace(22);
232          std::cout << "\n";
233        }
[378]234      }
235
[175]236    }
[378]237  }
[3]238
[378]239  /////////////////////////////////////////////////////////////////////////////
[884]240  std::vector <Detection> searchReconArray(size_t *dim, float *originalArray,
[378]241                                           float *reconArray, Param &par,
242                                           StatsContainer<float> &stats)
243  {
[686]244
245  if(par.getSearchType()=="spectral")
246    return searchReconArraySpectral(dim,originalArray,reconArray,par,stats);
247  else if(par.getSearchType()=="spatial")
248    return searchReconArraySpatial(dim,originalArray,reconArray,par,stats);
249  else{
[913]250    DUCHAMPERROR("searchReconArray","Unknown search type : " << par.getSearchType());
[686]251    return std::vector<Detection>(0);
252  }
253  }
254  /////////////////////////////////////////////////////////////////////////////
[884]255  std::vector <Detection> searchReconArraySpectral(size_t *dim, float *originalArray,
[686]256                                                   float *reconArray, Param &par,
257                                                   StatsContainer<float> &stats)
258  {
[528]259    ///  This searches for objects in a cube that has been reconstructed.
260    ///
[686]261    ///  The search is conducted just in each spatial pixel (xdim*ydim 1D
262    ///   searches).
[528]263    ///  The searches are done on the reconstructed array, although the detected
264    ///   objects have fluxes drawn from the corresponding pixels of the original
265    ///   array.
266    ///
267    ///  \param dim Array of dimension sizes
268    ///  \param originalArray Original, un-reconstructed image array.
269    ///  \param reconArray Reconstructed image array
270    ///  \param par The Param set.
271    ///  \param stats The StatsContainer that defines what a detection is.
272    ///
273    ///  \return A vector of Detections resulting from the search.
274
[378]275    std::vector <Detection> outputList;
[884]276    size_t zdim = dim[2];
277    size_t xySize = dim[0] * dim[1];
[378]278    int num=0;
279
280    // First search --  in each spectrum.
281    if(zdim > 1){
[3]282
[691]283      ProgressBar bar;
284      if(par.isVerbose()) bar.init(xySize);
285
[378]286      bool *doPixel = new bool[xySize];
287      // doPixel is a bool array to say whether to look in a given spectrum
[1242]288//      std::vector<bool> flaggedChans=par.getChannelFlags(zdim);
[894]289      for(size_t npix=0; npix<xySize; npix++){
[378]290        doPixel[npix] = false;
[894]291        for(size_t z=0;z<zdim;z++) {
[378]292          doPixel[npix] = doPixel[npix] ||
[1242]293            // (!par.isBlank(originalArray[npix+xySize*z]) && !par.isInMW(z));
294//          (!par.isBlank(originalArray[npix+xySize*z]) && !flaggedChans[z]);
295              (!par.isBlank(originalArray[npix+xySize*z]) && !par.isFlaggedChannel(z));
[378]296        }
297        // doPixel[i] is false only when there are no good pixels in spectrum
298        //  of pixel #i.
299      }
[3]300
[884]301      size_t *specdim = new size_t[2];
[378]302      specdim[0] = zdim; specdim[1]=1;
303      Image *spectrum = new Image(specdim);
304      delete [] specdim;
305      spectrum->saveParam(par);
306      spectrum->saveStats(stats);
[1007]307//       spectrum->setMinSize(par.getMinChannels());
308      spectrum->setMinSize(1);
[788]309      // NB the beam is not used after this point
310      // spectrum->pars().setBeamSize(2.);
311      // // beam size: for spectrum, only neighbouring channels correlated
[192]312
[894]313      for(size_t y=0; y<dim[1]; y++){
314        for(size_t x=0; x<dim[0]; x++){
[258]315
[894]316          size_t npix = y*dim[0] + x;
[378]317          if( par.isVerbose() ) bar.update(npix+1);
[258]318
[378]319          if(doPixel[npix]){
320
321            spectrum->extractSpectrum(reconArray,dim,npix);
[1242]322            // spectrum->removeMW(); // only works if flagMW is true
323            spectrum->removeFlaggedChannels();
[582]324            std::vector<Scan> objlist = spectrum->findSources1D();
[623]325            std::vector<Scan>::iterator obj;
[378]326            num += objlist.size();
[623]327            for(obj=objlist.begin();obj!=objlist.end();obj++){
[378]328              Detection newObject;
329              // Fix up coordinates of each pixel to match original array
[623]330              for(int z=obj->getX();z<=obj->getXmax();z++) {
[570]331                newObject.addPixel(x,y,z);
[378]332              }
333              newObject.setOffsets(par);
[691]334              if(par.getFlagTwoStageMerging()) mergeIntoList(newObject,outputList,par);
335              else outputList.push_back(newObject);
[258]336            }
[103]337          }
[378]338
[3]339        }
[378]340      }
[258]341
[378]342      delete spectrum;
343      delete [] doPixel;
[691]344     
345      if(par.isVerbose()){
346        bar.remove();
347        std::cout << "Found " << num << ".\n";
348      }
[378]349
[3]350    }
351
[378]352    return outputList;
353  }
[263]354
[378]355  /////////////////////////////////////////////////////////////////////////////
[884]356  std::vector <Detection> searchReconArraySpatial(size_t *dim, float *originalArray,
[686]357                                                  float *reconArray, Param &par,
358                                                  StatsContainer<float> &stats)
[378]359  {
[528]360    ///  This searches for objects in a cube that has been reconstructed.
361    ///
362    ///  The search is conducted only in each channel image (zdim 2D
[686]363    ///  searches).
[528]364    ///
365    ///  The searches are done on the reconstructed array, although the detected
366    ///   objects have fluxes drawn from the corresponding pixels of the original
367    ///   array.
368    ///
369    ///  \param dim Array of dimension sizes
370    ///  \param originalArray Original, un-reconstructed image array.
371    ///  \param reconArray Reconstructed image array
372    ///  \param par The Param set.
373    ///  \param stats The StatsContainer that defines what a detection is.
374    ///
375    ///  \return A vector of Detections resulting from the search.
376
[378]377    std::vector <Detection> outputList;
[884]378    size_t zdim = dim[2];
[378]379    int num=0;
380    ProgressBar bar;
381    bool useBar = (zdim>1);
382    if(useBar&&par.isVerbose()) bar.init(zdim);
[263]383 
[884]384    size_t *imdim = new size_t[2];
[378]385    imdim[0] = dim[0]; imdim[1] = dim[1];
386    Image *channelImage = new Image(imdim);
387    delete [] imdim;
388    channelImage->saveParam(par);
389    channelImage->saveStats(stats);
390    channelImage->setMinSize(1);
[263]391
[1242]392//    std::vector<bool> flaggedChans=par.getChannelFlags(zdim);
[894]393    for(size_t z=0; z<zdim; z++){  // loop over all channels
[263]394
[378]395      if( par.isVerbose() && useBar ) bar.update(z+1);
[263]396
[1242]397      // if(!par.isInMW(z)){
398//      if(!flaggedChans[z]){
399      if(!par.isFlaggedChannel(z)){
[378]400        // purpose of this is to ignore the Milky Way channels
401        //  if we are flagging them
[263]402
[378]403        channelImage->extractImage(reconArray,dim,z);
[582]404        std::vector<Object2D> objlist = channelImage->findSources2D();
[623]405        std::vector<Object2D>::iterator obj;
[378]406        num += objlist.size();
[623]407        for(obj=objlist.begin();obj!=objlist.end();obj++){
[378]408          Detection newObject;
[623]409          newObject.addChannel(z,*obj);
[378]410          newObject.setOffsets(par);
[691]411          if(par.getFlagTwoStageMerging()) mergeIntoList(newObject,outputList,par);
412          else outputList.push_back(newObject);
[378]413        }
[263]414      }
[378]415   
[263]416    }
417
[378]418    delete channelImage;
[263]419
[378]420    if(par.isVerbose()){
421      if(useBar) bar.remove();
422      std::cout << "Found " << num << ".\n";
423    }
424
425
426    return outputList;
[263]427  }
428
429}
Note: See TracBrowser for help on using the repository browser.