source: tags/release-1.1.8/src/ATrous/ReconSearch.cc @ 1391

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

Copying changesets [539]-[543] onto release-1.1.8

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(unsigned 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(unsigned 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(unsigned 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.