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

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

Actually making use of the spatialSmoothCutoff parameter, and spacing out some of the columns a bit better.

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