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

Last change on this file since 120 was 120, checked in by Matthew Whiting, 18 years ago

Introduced error and warning reporting functions, to normalise the format
of errors and warnings. Definitions of functions go in duchamp.cc.
Changed all code that reports errors/warnings to use these new functions.

Fixed a couple of bugs that affected the way 2D images were dealt with:
ReconSearch? now looks at how many dimensions there are in the data array
before choosing the dimension of the reconstruction, and the minChannels
test was improved for the case of minChannels=0.

Some minor additions made to the Guide as well.

File size: 12.2 KB
Line 
1#include <fstream>
2#include <iostream>
3#include <iomanip>
4#include <vector>
5#include <duchamp.hh>
6#include <Cubes/cubes.hh>
7#include <ATrous/atrous.hh>
8#include <Utils/utils.hh>
9
10using std::setw;
11
12//////////////////////////////////////////////////////////////////////////////////////
13void Cube::ReconSearch()
14{
15  /**
16   * Cube::ReconSearch()
17   *   A front-end to the various ReconSearch functions, the choice of which
18   *   is determined by the use of the reconDim parameter.
19   */
20  int dimRecon = this->par.getReconDim();
21 
22  // Test whether we have eg. an image, but have requested a 3-d reconstruction.
23  // If dimension of data array is less than dimRecon, change dimRecon to the
24  // dimension of the array.
25  int numGoodDim = 0;
26  for(int i=0;i<this->numDim;i++) if(this->axisDim[i]>1) numGoodDim++;
27  if(numGoodDim<dimRecon) dimRecon = numGoodDim;
28  this->par.setReconDim(dimRecon);
29
30  switch(dimRecon)
31    {
32    case 1: this->ReconSearch1D(); break;
33    case 2: this->ReconSearch2D(); break;
34    case 3: this->ReconSearch3D(); break;
35    default:
36      if(dimRecon<=0){
37        std::stringstream errmsg;
38        errmsg << "reconDim (" << dimRecon
39               << ") is less than 1. Performing 1-D reconstruction.\n";
40        duchampWarning("ReconSearch", errmsg.str());
41        this->par.setReconDim(1);
42        this->ReconSearch1D();
43      }
44      else if(dimRecon>3){
45        //this probably won't happen with new code above, but just in case...
46        std::stringstream errmsg;
47        errmsg << "reconDim (" << dimRecon
48               << ") is more than 3. Performing 3-D reconstruction.\n";
49        duchampWarning("ReconSearch", errmsg.str());
50        this->par.setReconDim(3);
51        this->ReconSearch3D();
52      }
53      break;
54    }
55 
56}
57
58
59//////////////////////////////////////////////////////////////////////////////////////
60void Cube::ReconSearch1D()
61{
62  /**
63   * Cube::ReconSearch1D()
64   *   This reconstructs a cube by performing a 1D a trous reconstruction
65   *   in the spectrum of each spatial pixel.
66   *   It then searches the cube using searchReconArray (below).
67   *
68   *   The resulting object list is stored in the Cube.
69   */
70  long xySize = this->axisDim[0] * this->axisDim[1];
71  long zdim = this->axisDim[2];
72
73  // Reconstruct the cube by 1d atrous transform in each spatial pixel
74  if(!this->reconExists){
75    std::cout<<"  Reconstructing... ";
76    if(par.isVerbose()) std::cout << "|                    |" << std::flush;
77    for(int npix=0; npix<xySize; npix++){
78      if( par.isVerbose() && ((100*(npix+1)/xySize)%5 == 0) ){
79        std::cout << "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b|";
80        for(int i=0;i<(100*(npix+1)/xySize)/5;i++) std::cout << "#";
81        for(int i=(100*(npix+1)/xySize)/5;i<20;i++) std::cout << " ";
82        std::cout << "|" << std::flush;
83      }
84      float *spec = new float[zdim];
85      float *newSpec = new float[zdim];
86      for(int z=0;z<zdim;z++) spec[z] = this->array[z*xySize + npix];
87      bool verboseFlag = this->par.isVerbose();
88      this->par.setVerbosity(false);
89      atrous1DReconstruct(this->axisDim[2],spec,newSpec,this->par);
90      this->par.setVerbosity(verboseFlag);
91      for(int z=0;z<zdim;z++) this->recon[z*xySize+npix] = newSpec[z];
92      delete spec;
93      delete newSpec;
94    }
95    this->reconExists = true;
96    std::cout<<"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b  All Done.                      \n"
97             <<"  Searching... "<<std::flush;
98  }
99   
100  this->objectList = searchReconArray(this->axisDim,this->array,this->recon,this->par);
101
102  this->updateDetectMap();
103  if(this->par.getFlagLog()) this->logDetectionList();
104
105}
106
107//////////////////////////////////////////////////////////////////////////////////////
108void Cube::ReconSearch2D()
109{
110  /**
111   * Cube::ReconSearch2D()
112   *   This reconstructs a cube by performing a 2D a trous reconstruction
113   *   in each spatial image (ie. each channel map) of the cube.
114   *   It then searches the cube using searchReconArray (below).
115   *
116   *   The resulting object list is stored in the Cube.
117   */
118  long xySize = this->axisDim[0] * this->axisDim[1];
119
120  if(!this->reconExists){
121    // RECONSTRUCT THE CUBE BY 2D ATROUS TRANSFORM IN EACH CHANNEL 
122    std::cout<<"  Reconstructing... ";
123    if(par.isVerbose()) std::cout << "|                    |" << std::flush;
124    for(int z=0;z<this->axisDim[2];z++){
125      if( par.isVerbose() && ((100*(z+1)/this->axisDim[2])%5 == 0) ){
126        std::cout << "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b|";
127        for(int i=0;i<(100*(z+1)/this->axisDim[2])/5;i++) std::cout << "#";
128        for(int i=(100*(z+1)/this->axisDim[2])/5;i<20;i++) std::cout << " ";
129        std::cout << "|" << std::flush;
130      }
131      if(!this->par.isInMW(z)){
132        float *im = new float[xySize];
133        float *newIm = new float[xySize];
134        for(int npix=0; npix<xySize; npix++) im[npix] = this->array[z*xySize+npix];
135        bool verboseFlag = this->par.isVerbose();
136        this->par.setVerbosity(false);
137        atrous2DReconstruct(this->axisDim[0],this->axisDim[1],im,newIm,this->par);
138        this->par.setVerbosity(verboseFlag);
139        for(int npix=0; npix<xySize; npix++) this->recon[z*xySize+npix] = newIm[npix];
140        delete im;
141        delete newIm;
142      }
143      else {
144        for(int i=z*xySize; i<(z+1)*xySize; i++) this->recon[i] = this->array[i];
145      }
146    }
147    this->reconExists = true;
148    std::cout<<"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b  All Done.                      \n"
149             <<"Searching... "<<std::flush;
150
151  }
152
153  this->objectList = searchReconArray(this->axisDim,this->array,this->recon,this->par);
154 
155  this->updateDetectMap();
156  if(this->par.getFlagLog()) this->logDetectionList();
157
158}
159
160//////////////////////////////////////////////////////////////////////////////////////
161void Cube::ReconSearch3D()
162{
163  /**
164   * Cube::ReconSearch3D()
165   *   This performs a full 3D a trous reconstruction of the cube
166   *   It then searches the cube using searchReconArray (below).
167   *
168   *   The resulting object list is stored in the Cube.
169   */
170  if(this->axisDim[2]==1) this->ReconSearch2D();
171  else {
172
173    if(!this->reconExists){
174      std::cout<<"  Reconstructing... "<<std::flush;
175      atrous3DReconstruct(this->axisDim[0],this->axisDim[1],this->axisDim[2],
176                          this->array,this->recon,this->par);
177      this->reconExists = true;
178      std::cout<<"All Done.                      \n  Searching... "<<std::flush;
179    }
180
181    this->objectList = searchReconArray(this->axisDim,this->array,this->recon,this->par);
182
183    this->updateDetectMap();
184    if(this->par.getFlagLog()) this->logDetectionList();
185
186  }
187
188}
189
190
191//////////////////////////////////////////////////////////////////////////////////////
192vector <Detection> searchReconArray(long *dim, float *originalArray, float *reconArray, Param &par)
193{
194  /**
195   * searchReconArray(long *dim, float *originalArray, float *reconArray, Param &par)
196   *   This searches for objects in a cube that has been reconstructed.
197   *
198   *   Inputs:   - dimension array
199   *             - original, un-reconstructed image array
200   *             - reconstructed image array
201   *             - parameters
202   *
203   *   Searches first in each spatial pixel (1D search),
204   *   then in each channel image (2D search).
205   *
206   *   Returns: vector of Detections resulting from the search.
207   */
208  vector <Detection> outputList;
209  long zdim = dim[2];
210  long xySize = dim[0] * dim[1];
211  long fullSize = zdim * xySize;
212  int num=0, goodSize;
213
214  float blankPixValue = par.getBlankPixVal();
215  bool *isGood = new bool[fullSize];
216  for(int pos=0;pos<fullSize;pos++){
217    isGood[pos] = !par.isBlank(originalArray[pos]) && !par.isInMW(pos/xySize);
218  }
219  bool *doChannel = new bool[xySize];
220  goodSize=0;
221  for(int npix=0; npix<xySize; npix++){
222    for(int z=0;z<zdim;z++) if(isGood[z*xySize+npix]) goodSize++;
223    if(goodSize==0) doChannel[npix] = false;
224    else doChannel[npix] = true;
225  }
226 
227  float dud;
228
229  // First search --  in each spectrum.
230  if(zdim > 1){
231    if(par.isVerbose()) std::cout << "1D: |                    |" << std::flush;
232
233    for(int npix=0; npix<xySize; npix++){
234
235      if( par.isVerbose() && ((100*(npix+1)/xySize)%5 == 0) ){
236        std::cout << "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b|";
237        for(int i=0;i<(100*(npix+1)/xySize)/5;i++) std::cout << "#";
238        for(int i=(100*(npix+1)/xySize)/5;i<20;i++) std::cout << " ";
239        std::cout << "|" << std::flush;
240      }
241
242      if(doChannel[npix]){
243       
244        // First, get stats
245        float *spec = new float[zdim];
246        float specMedian,specSigma;
247        goodSize=0;
248        for(int z=0;z<zdim;z++)
249          if(isGood[z*xySize+npix]) spec[goodSize++] = originalArray[z*xySize+npix];
250        specMedian = findMedian(spec,goodSize);
251        goodSize=0;
252        for(int z=0;z<zdim;z++)
253          if(isGood[z*xySize+npix])
254            spec[goodSize++] = originalArray[z*xySize+npix]-reconArray[z*xySize+npix];
255        specSigma = findMADFM(spec,goodSize) / correctionFactor;
256        delete [] spec;
257       
258        // Next, do source finding.
259        long *specdim = new long[2];
260        specdim[0] = zdim; specdim[1]=1;
261        Image *spectrum = new Image(specdim);
262        delete [] specdim;
263        spectrum->saveParam(par);
264        spectrum->pars().setBeamSize(2.); // for spectrum, only neighbouring channels correlated
265        spectrum->extractSpectrum(reconArray,dim,npix);
266        spectrum->removeMW(); // only works if flagMW is true
267        spectrum->setStats(specMedian,specSigma,par.getCut());
268        if(par.getFlagFDR()) spectrum->setupFDR();
269        spectrum->setMinSize(par.getMinChannels());
270        spectrum->spectrumDetect();
271        for(int obj=0;obj<spectrum->getNumObj();obj++){
272          Detection *object = new Detection;
273          *object = spectrum->getObject(obj);
274          for(int pix=0;pix<object->getSize();pix++) {
275            // Fix up coordinates of each pixel to match original array
276            object->setZ(pix, object->getX(pix));
277            object->setX(pix, npix%dim[0]);
278            object->setY(pix, npix/dim[0]);
279            object->setF(pix, originalArray[object->getX(pix)+object->getY(pix)*dim[0]+object->getZ(pix)*xySize]);
280            // NB: set F to the original value, not the recon value.
281          }
282          object->addOffsets(par);
283          object->calcParams();
284          mergeIntoList(*object,outputList,par);
285          delete object;
286        }
287        delete spectrum;
288      }
289    }
290
291    num = outputList.size();
292    if(par.isVerbose())
293      std::cout <<"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bFound " << num <<"; " << std::flush;
294
295  }
296
297  // Second search --  in each channel
298  if(par.isVerbose()) std::cout << "2D: |                    |" << std::flush;
299
300  for(int z=0; z<zdim; z++){  // loop over all channels
301
302    if( par.isVerbose() && ((100*(z+1)/zdim)%5 == 0) ){
303      std::cout << "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b|";
304      for(int i=0;i<(100*(z+1)/zdim)/5;i++)  std::cout << "#";
305      for(int i=(100*(z+1)/zdim)/5;i<20;i++) std::cout << " ";
306      std::cout << "|" << std::flush;
307    }
308
309    if(!par.isInMW(z)){ // purpose of this is to ignore the Milky Way channels if we are flagging them
310      //  First, get stats
311      float *image = new float[xySize];
312      float imageMedian,imageSigma;
313      goodSize=0;
314      for(int npix=0; npix<xySize; npix++)
315        if(isGood[z*xySize + npix]) image[goodSize++] = originalArray[z*xySize + npix];
316      imageMedian = findMedian(image,goodSize);
317      goodSize=0;
318      for(int npix=0; npix<xySize; npix++)
319        if(isGood[z*xySize+npix])
320          image[goodSize++]=originalArray[z*xySize+npix]-reconArray[z*xySize+npix];
321      imageSigma = findMADFM(image,goodSize) / correctionFactor;
322      delete [] image;
323
324      // Next, do source finding.
325      long *imdim = new long[2];
326      imdim[0] = dim[0]; imdim[1] = dim[1];
327      Image *channelImage = new Image(imdim);
328      channelImage->saveParam(par);
329      delete [] imdim;
330      channelImage->extractImage(reconArray,dim,z);
331      channelImage->setStats(imageMedian,imageSigma,par.getCut());
332      if(par.getFlagFDR()) channelImage->setupFDR();
333      channelImage->setMinSize(par.getMinPix());
334      channelImage->lutz_detect();
335      for(int obj=0;obj<channelImage->getNumObj();obj++){
336        Detection *object = new Detection;
337        *object = channelImage->getObject(obj);
338        // Fix up z coordinates of each pixel to match original array (x & y are fine)
339        for(int pix=0;pix<object->getSize();pix++){
340          object->setZ(pix, z);
341          object->setF(pix, originalArray[object->getX(pix)+object->getY(pix)*dim[0]+z*xySize]);
342          // NB: set F to the original value, not the recon value.
343        }
344        object->addOffsets(par);
345        object->calcParams();
346        mergeIntoList(*object,outputList,par);
347        delete object;
348      }
349      delete channelImage;
350   }
351
352  }
353
354
355  std::cout << "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bFound " << outputList.size() - num
356            << ".                                           "  << std::endl << std::flush;
357
358  delete [] isGood;
359  delete [] doChannel;
360
361  return outputList;
362}
Note: See TracBrowser for help on using the repository browser.