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

Last change on this file since 846 was 846, checked in by MatthewWhiting, 13 years ago

Lots of small changes to the reconstruction code, getting the type definitions appropriate (signed vs unsigned ints, with size_t parameters in there as well.)

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