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

Last change on this file since 1391 was 299, checked in by Matthew Whiting, 17 years ago

Adding distribution text at the start of each file...

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