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

Last change on this file since 1441 was 691, checked in by MatthewWhiting, 14 years ago

New parameter that allows us to turn off the use of mergeIntoList. Fully documented!

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