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

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

Changing the documentation comments to match the askapsoft style. Also have split ChanMap? and Object3D into separate files.

File size: 13.9 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 = 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);
75
76      if(this->par.isVerbose()) std::cout << "  Updating detection map... "
77                                          << std::flush;
78      this->updateDetectMap();
79      if(this->par.isVerbose()) std::cout << "Done.\n";
80
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      }
87
88    }
89  }
90
91  /////////////////////////////////////////////////////////////////////////////
92  void Cube::ReconCube()
93  {
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
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());
112    }
113
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      }
139  }
140
141  /////////////////////////////////////////////////////////////////////////////
142  void Cube::ReconCube1D()
143  {
144    /// This reconstructs a cube by performing a 1D a trous reconstruction
145    ///  in the spectrum of each spatial pixel.
146
147    long xySize = this->axisDim[0] * this->axisDim[1];
148
149    long zdim = this->axisDim[2];
150
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++){
156
157        if( par.isVerbose() ) bar.update(npix+1);
158
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];
162        bool verboseFlag = this->par.isVerbose();
163        this->par.setVerbosity(false);
164        atrous1DReconstruct(this->axisDim[2],spec,newSpec,this->par);
165        this->par.setVerbosity(verboseFlag);
166        for(int z=0;z<zdim;z++) this->recon[z*xySize+npix] = newSpec[z];
167        delete [] spec;
168        delete [] newSpec;
169      }
170      this->reconExists = true;
171      bar.fillSpace(" All Done.");
172      printSpace(22);
173      std::cout << "\n";
174    }
175
176  }
177
178  /////////////////////////////////////////////////////////////////////////////
179  void Cube::ReconCube2D()
180  {
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
184    long xySize = this->axisDim[0] * this->axisDim[1];
185    ProgressBar bar;
186    bool useBar = (this->axisDim[2]>1);
187
188    if(!this->reconExists){
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      }
215      this->reconExists = true;
216      if(useBar) bar.fillSpace(" All Done.");
217      printSpace(22);
218      std::cout << "\n";
219    }
220  }
221
222  /////////////////////////////////////////////////////////////////////////////
223  void Cube::ReconCube3D()
224  {
225    /// This performs a full 3D a trous reconstruction of the cube
226
227    if(this->axisDim[2]==1) this->ReconCube2D();
228    else {
229
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
240    }
241  }
242
243  /////////////////////////////////////////////////////////////////////////////
244  std::vector <Detection> searchReconArray(long *dim, float *originalArray,
245                                           float *reconArray, Param &par,
246                                           StatsContainer<float> &stats)
247  {
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
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);
275      }
276
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      }
288
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
298
299      for(int y=0; y<dim[1]; y++){
300        for(int x=0; x<dim[0]; x++){
301
302          int npix = y*dim[0] + x;
303          if( par.isVerbose() ) bar.update(npix+1);
304
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();
311            for(int obj=0;obj<objlist.size();obj++){
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);
319            }
320          }
321
322        }
323      }
324
325      delete spectrum;
326      delete [] doPixel;
327
328      if(par.isVerbose()) {
329        bar.fillSpace("Found ");
330        std::cout << num <<";" << std::flush;
331      }
332    }
333
334    // Second search --  in each channel
335    if(par.isVerbose()){
336      std::cout << "  2D: ";
337      bar.init(zdim);
338    }
339
340    num = 0;
341
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());
349
350    for(int z=0; z<zdim; z++){  // loop over all channels
351
352      if( par.isVerbose() ) bar.update(z+1);
353
354      if(!par.isInMW(z)){
355        // purpose of this is to ignore the Milky Way channels
356        //  if we are flagging them
357
358        channelImage->extractImage(reconArray,dim,z);
359        std::vector<Object2D> objlist = channelImage->lutz_detect();
360        num += objlist.size();
361        for(int obj=0;obj<objlist.size();obj++){
362          Detection newObject;
363          newObject.pixels().addChannel(z,objlist[obj]);
364          newObject.setOffsets(par);
365          mergeIntoList(newObject,outputList,par);
366        }
367      }
368   
369    }
370
371    delete channelImage;
372
373    if(par.isVerbose()){
374      bar.fillSpace("Found ");
375      std::cout << num << ".\n";
376    }
377
378
379    return outputList;
380  }
381
382  /////////////////////////////////////////////////////////////////////////////
383  std::vector <Detection>
384  searchReconArraySimple(long *dim, float *originalArray,
385                         float *reconArray, Param &par,
386                         StatsContainer<float> &stats)
387  {
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
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);
411 
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);
419
420    for(int z=0; z<zdim; z++){  // loop over all channels
421
422      if( par.isVerbose() && useBar ) bar.update(z+1);
423
424      if(!par.isInMW(z)){
425        // purpose of this is to ignore the Milky Way channels
426        //  if we are flagging them
427
428        channelImage->extractImage(reconArray,dim,z);
429        std::vector<Object2D> objlist = channelImage->lutz_detect();
430        num += objlist.size();
431        for(int obj=0;obj<objlist.size();obj++){
432          Detection newObject;
433          newObject.pixels().addChannel(z,objlist[obj]);
434          newObject.setOffsets(par);
435          mergeIntoList(newObject,outputList,par);
436        }
437      }
438   
439    }
440
441    delete channelImage;
442
443    if(par.isVerbose()){
444      if(useBar) bar.remove();
445      std::cout << "Found " << num << ".\n";
446    }
447
448
449    return outputList;
450  }
451
452}
Note: See TracBrowser for help on using the repository browser.