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

Last change on this file since 377 was 377, checked in by MatthewWhiting, 17 years ago

Made similar changes to [372].

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