source: tags/release-1.1.8/src/ATrous/ReconSearch.cc @ 1391

Last change on this file since 1391 was 591, checked in by MatthewWhiting, 15 years ago

Copying changesets [539]-[543] onto release-1.1.8

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