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

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

Fixed up headers for trunk as well.

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