source: tags/release-1.1.4/src/ATrous/ReconSearch.cc @ 1441

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

Fixed up headers for trunk as well.

File size: 14.0 KB
Line 
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// -----------------------------------------------------------------------
28#include <fstream>
29#include <iostream>
30#include <iomanip>
31#include <vector>
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>
40
41using namespace PixelInfo;
42using namespace Statistics;
43
44namespace duchamp
45{
46
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 {
63 
64      this->ReconCube();
65
66      if(this->par.isVerbose()) std::cout << "  ";
67
68      this->setCubeStats();
69   
70      if(this->par.isVerbose()) std::cout << "  Searching... " << std::flush;
71 
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);
77
78      if(this->par.isVerbose()) std::cout << "  Updating detection map... "
79                                          << std::flush;
80      this->updateDetectMap();
81      if(this->par.isVerbose()) std::cout << "Done.\n";
82
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      }
89
90    }
91  }
92
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());
115    }
116
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      }
142  }
143
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];
152
153    long zdim = this->axisDim[2];
154
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++){
160
161        if( par.isVerbose() ) bar.update(npix+1);
162
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];
166        bool verboseFlag = this->par.isVerbose();
167        this->par.setVerbosity(false);
168        atrous1DReconstruct(this->axisDim[2],spec,newSpec,this->par);
169        this->par.setVerbosity(verboseFlag);
170        for(int z=0;z<zdim;z++) this->recon[z*xySize+npix] = newSpec[z];
171        delete [] spec;
172        delete [] newSpec;
173      }
174      this->reconExists = true;
175      bar.fillSpace(" All Done.");
176      printSpace(22);
177      std::cout << "\n";
178    }
179
180  }
181
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);
192
193    if(!this->reconExists){
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      }
220      this->reconExists = true;
221      if(useBar) bar.fillSpace(" All Done.");
222      printSpace(22);
223      std::cout << "\n";
224    }
225  }
226
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 {
235
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
246    }
247  }
248
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);
282      }
283
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      }
295
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
305
306      for(int y=0; y<dim[1]; y++){
307        for(int x=0; x<dim[0]; x++){
308
309          int npix = y*dim[0] + x;
310          if( par.isVerbose() ) bar.update(npix+1);
311
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);
326            }
327          }
328
329        }
330      }
331
332      delete spectrum;
333      delete [] doPixel;
334
335      if(par.isVerbose()) {
336        bar.fillSpace("Found ");
337        std::cout << num <<";" << std::flush;
338      }
339    }
340
341    // Second search --  in each channel
342    if(par.isVerbose()){
343      std::cout << "  2D: ";
344      bar.init(zdim);
345    }
346
347    num = 0;
348
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());
356
357    for(int z=0; z<zdim; z++){  // loop over all channels
358
359      if( par.isVerbose() ) bar.update(z+1);
360
361      if(!par.isInMW(z)){
362        // purpose of this is to ignore the Milky Way channels
363        //  if we are flagging them
364
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        }
374      }
375   
376    }
377
378    delete channelImage;
379
380    if(par.isVerbose()){
381      bar.fillSpace("Found ");
382      std::cout << num << ".\n";
383    }
384
385
386    return outputList;
387  }
388
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);
419 
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);
427
428    for(int z=0; z<zdim; z++){  // loop over all channels
429
430      if( par.isVerbose() && useBar ) bar.update(z+1);
431
432      if(!par.isInMW(z)){
433        // purpose of this is to ignore the Milky Way channels
434        //  if we are flagging them
435
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        }
445      }
446   
447    }
448
449    delete channelImage;
450
451    if(par.isVerbose()){
452      if(useBar) bar.remove();
453      std::cout << "Found " << num << ".\n";
454    }
455
456
457    return outputList;
458  }
459
460}
Note: See TracBrowser for help on using the repository browser.