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

Last change on this file since 782 was 725, checked in by MatthewWhiting, 14 years ago

Making sure outputs are covered by verbose flag.

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