source: trunk/src/Cubes/smoothCube.cc @ 516

Last change on this file since 516 was 516, checked in by MatthewWhiting, 16 years ago

Improvements to the Gaussian smoothing, including templating.

File size: 8.9 KB
RevLine 
[299]1// -----------------------------------------------------------------------
2// smoothCube: Smooth a Cube's array, and search for objects.
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// -----------------------------------------------------------------------
[275]28#include <vector>
[393]29#include <duchamp/duchamp.hh>
30#include <duchamp/Cubes/cubes.hh>
31#include <duchamp/Detection/detection.hh>
32#include <duchamp/PixelMap/Object2D.hh>
33#include <duchamp/Utils/feedback.hh>
34#include <duchamp/Utils/Hanning.hh>
35#include <duchamp/Utils/GaussSmooth.hh>
36#include <duchamp/Utils/Statistics.hh>
37#include <duchamp/Utils/utils.hh>
[201]38
[378]39namespace duchamp
40{
41
[258]42void Cube::SmoothSearch()
43{
44  /**
45   * The Cube is first smoothed, using Cube::SmoothCube().
[275]46   * It is then searched, using search3DArray()
[258]47   * The resulting object list is stored in the Cube, and outputted
48   *  to the log file if the user so requests.
49   */
[275]50
51  if(!this->par.getFlagSmooth()){
52    duchampWarning("SmoothSearch",
53                   "FlagSmooth not set! Using basic CubicSearch.\n");
54    this->CubicSearch();
55  }
56  else{   
[258]57
[290]58    this->SmoothCube();
[258]59 
[275]60    if(this->par.isVerbose()) std::cout << "  ";
61
62    this->setCubeStats();
63
[291]64//       this->Stats.scaleNoise(1./gauss.getStddevScale());
65
[275]66    if(this->par.isVerbose()) std::cout << "  Searching... " << std::flush;
67 
[309]68    *(this->objectList) = search3DArraySimple(this->axisDim,this->recon,
69                                              this->par,this->Stats);
[275]70 
71    if(this->par.isVerbose()) std::cout << "  Updating detection map... "
72                                        << std::flush;
73    this->updateDetectMap();
[258]74    if(this->par.isVerbose()) std::cout << "Done.\n";
[275]75
76    if(this->par.getFlagLog()){
77      if(this->par.isVerbose())
78        std::cout << "  Logging intermediate detections... " << std::flush;
79      this->logDetectionList();
80      if(this->par.isVerbose()) std::cout << "Done.\n";
81    }
82 
[258]83  }
84
85}
[275]86//-----------------------------------------------------------
[258]87
[290]88void Cube::SmoothCube()
89{
90  /**
91   *  Switching function that chooses the appropriate function with
92   *  which to smooth the cube, based on the Param::smoothType
93   *  parameter.
94   *
95   */
96  if(this->par.getSmoothType()=="spectral"){
97   
98    this->SpectralSmooth();
[377]99   
100  }
101  else if(this->par.getSmoothType()=="spatial"){
102   
103    this->SpatialSmooth();
104   
105  }
[290]106}
107//-----------------------------------------------------------
108
[275]109void Cube::SpectralSmooth()
[201]110{
111  /**
[275]112   *   A function that smoothes each spectrum in the cube using the
[201]113   *    Hanning smoothing function. The degree of smoothing is given
[272]114   *    by the parameter Param::hanningWidth.
[201]115   */
116
[275]117  long xySize = this->axisDim[0]*this->axisDim[1];
118  long zdim = this->axisDim[2];
119  ProgressBar bar;
120
[277]121  if(!this->reconExists && this->par.getSmoothType()=="spectral"){
[365]122    //    if(!this->head.isSpecOK())
123    if(!this->head.canUseThirdAxis())
[277]124      duchampWarning("SpectralSmooth",
[377]125                     "There is no spectral axis, so cannot do the spectral smoothing.\n");
[277]126    else{
127
128      Hanning hann(this->par.getHanningWidth());
[201]129 
[277]130      float *spectrum = new float[this->axisDim[2]];
[275]131
[277]132      if(this->par.isVerbose()) {
133        std::cout<<"  Smoothing spectrally... ";
134        bar.init(xySize);
135      }
[275]136
[277]137      for(int pix=0;pix<xySize;pix++){
[275]138
[277]139        if( this->par.isVerbose() ) bar.update(pix+1);
[275]140   
[277]141        for(int z=0;z<zdim;z++){
142          if(this->isBlank(z*xySize+pix)) spectrum[z]=0.;
143          else spectrum[z] = this->array[z*xySize+pix];
144        }
[275]145
[277]146        float *smoothed = hann.smooth(spectrum,zdim);
[275]147
[277]148        for(int z=0;z<zdim;z++){
149          if(this->isBlank(z*xySize+pix))
[285]150            this->recon[z*xySize+pix] = this->array[z*xySize+pix];
[277]151          else
152            this->recon[z*xySize+pix] = smoothed[z];
153        }
154        delete [] smoothed;
[275]155      }
[277]156      this->reconExists = true;
157      if(this->par.isVerbose()) bar.fillSpace("All Done.\n");
[275]158
[277]159      delete [] spectrum;
[275]160
[277]161    }
[275]162  }
163}
164//-----------------------------------------------------------
165
166void Cube::SpatialSmooth()
167{
168
[277]169  if(!this->reconExists && this->par.getSmoothType()=="spatial"){
[201]170
[277]171    if( this->head.getNumAxes() < 2 )
172      duchampWarning("SpatialSmooth",
173                     "There are not enough axes to do the spatial smoothing.\n");
174    else{
[201]175
[277]176      long xySize = this->axisDim[0]*this->axisDim[1];
177      long xdim = this->axisDim[0];
178      long ydim = this->axisDim[1];
179      long zdim = this->axisDim[2];
[275]180
[277]181      ProgressBar bar;
[372]182//       bool useBar = this->head.canUseThirdAxis();
183      bool useBar = (zdim > 1);
184     
[285]185      // if kernMin is negative (not defined), make it equal to kernMaj
186      if(this->par.getKernMin() < 0)
187        this->par.setKernMin(this->par.getKernMaj());
188
[516]189      GaussSmooth<float> gauss(this->par.getKernMaj(),
190                               this->par.getKernMin(),
191                               this->par.getKernPA());
[201]192
[277]193      if(this->par.isVerbose()) {
194        std::cout<<"  Smoothing spatially... " << std::flush;
[372]195        if(useBar) bar.init(zdim);
[277]196      }
197
198      float *image = new float[xySize];
[291]199
[277]200      for(int z=0;z<zdim;z++){
201
[372]202        if( this->par.isVerbose() && useBar ) bar.update(z+1);
[275]203     
[277]204        for(int pix=0;pix<xySize;pix++) image[pix] = this->array[z*xySize+pix];
[201]205   
[291]206        bool *mask      = this->par.makeBlankMask(image,xySize);
[275]207   
[291]208        float *smoothed = gauss.smooth(image,xdim,ydim,mask);
[275]209   
[285]210        for(int pix=0;pix<xySize;pix++){
211          if(mask[pix])
212            this->recon[z*xySize+pix] = this->array[z*xySize+pix];
213          else
214            this->recon[z*xySize+pix] = smoothed[pix];
215        }
[201]216
[291]217        delete [] smoothed;
218        delete [] mask;
[277]219      }
[201]220
[277]221      delete [] image;
[275]222 
[277]223      this->reconExists = true;
[275]224 
[372]225      if(par.isVerbose()){
226        if(useBar) bar.fillSpace("All Done.");
227        std::cout << "\n";
228      }
229
230    }
[277]231  }
[275]232}
233//-----------------------------------------------------------
234
235void Cube::SpatialSmoothNSearch()
236{
237
238  long xySize = this->axisDim[0]*this->axisDim[1];
239  long xdim = this->axisDim[0];
240  long ydim = this->axisDim[1];
241  long zdim = this->axisDim[2];
242  int numFound=0;
243  ProgressBar bar;
244
[516]245  GaussSmooth<float> gauss(this->par.getKernMaj(),
246                           this->par.getKernMin(),
247                           this->par.getKernPA());
[275]248
249  this->Stats.scaleNoise(1./gauss.getStddevScale());
250  if(this->par.getFlagFDR()) this->setupFDR();
251
252  if(this->par.isVerbose()) {
253    std::cout<<"  Smoothing spatially & searching... " << std::flush;
254    bar.init(zdim);
255  }
256
257  std::vector <Detection> outputList;
258  long *imdim = new long[2];
259  imdim[0] = xdim; imdim[1] = ydim;
260  Image *channelImage = new Image(imdim);
261  delete [] imdim;
262  channelImage->saveParam(this->par);
263  channelImage->saveStats(this->Stats);
264  channelImage->setMinSize(1);
265
266  float *image = new float[xySize];
267  float *smoothed;
268  bool *mask;
269  float median,madfm;//,threshold;
270  for(int z=0;z<zdim;z++){
271
272    if( this->par.isVerbose() ) bar.update(z+1);
273     
274    if(!this->par.isInMW(z)){
275
276      for(int pix=0;pix<xySize;pix++) image[pix] = this->array[z*xySize+pix];
277
278      mask  = this->par.makeBlankMask(image,xySize);
279
280      smoothed = gauss.smooth(image,xdim,ydim,mask);
281     
282      //     for(int pix=0;pix<xySize;pix++)
283      //       this->recon[z*xySize+pix] = smoothed[pix];
284
285      findMedianStats(smoothed,xySize,mask,median,madfm);
[277]286      //       threshold = median+this->par.getCut()*Statistics::madfmToSigma(madfm);
287      //       for(int i=0;i<xySize;i++)
288      //        if(smoothed[i]<threshold) image[i] = this->Stats.getMiddle();
289      //       channelImage->saveArray(image,xySize);
[275]290
291
[277]292      //       channelImage->stats().setMadfm(madfm);
293      //       channelImage->stats().setMedian(median);
294      //       channelImage->stats().setThresholdSNR(this->par.getCut());
[275]295      channelImage->saveArray(smoothed,xySize);
296
297      std::vector<PixelInfo::Object2D> objlist = channelImage->lutz_detect();
298      numFound += objlist.size();
299      for(int obj=0;obj<objlist.size();obj++){
300        Detection newObject;
301        newObject.pixels().addChannel(z,objlist[obj]);
302        newObject.setOffsets(this->par);
303        mergeIntoList(newObject,outputList,this->par);
304      }
305
[201]306    }
[275]307   
[201]308  }
309
[275]310  delete [] smoothed;
311  delete [] mask;
312  delete [] image;
313  delete channelImage;
314   
[277]315  //   this->reconExists = true;
[275]316  if(par.isVerbose()){
317    bar.fillSpace("Found ");
318    std::cout << numFound << ".\n";
319  }
320   
[291]321  *this->objectList = outputList;
[201]322
323}
[378]324
325}
Note: See TracBrowser for help on using the repository browser.