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

Last change on this file since 1141 was 1141, checked in by MatthewWhiting, 11 years ago

Fixing major problem with the spatial smoothing - I had the sense of the mask wrong, so no good pixels were getting smoothed!

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