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

Last change on this file since 1441 was 1430, checked in by MatthewWhiting, 7 years ago

Undoing previous commit, as I didn't mean to commit everything :)

File size: 8.7 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   
[1393]210        std::vector<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;
[277]218      }
[201]219
[277]220      this->reconExists = true;
[275]221 
[372]222      if(par.isVerbose()){
223        if(useBar) bar.fillSpace("All Done.");
224        std::cout << "\n";
225      }
226
227    }
[277]228  }
[275]229}
230//-----------------------------------------------------------
231
232void Cube::SpatialSmoothNSearch()
233{
234
[884]235  size_t xySize = this->axisDim[0]*this->axisDim[1];
236  size_t xdim = this->axisDim[0];
237  size_t ydim = this->axisDim[1];
238  size_t zdim = this->axisDim[2];
[275]239  int numFound=0;
240  ProgressBar bar;
241
[638]242  GaussSmooth2D<float> gauss(this->par.getKernMaj(),
[516]243                           this->par.getKernMin(),
244                           this->par.getKernPA());
[275]245
246  this->Stats.scaleNoise(1./gauss.getStddevScale());
247  if(this->par.getFlagFDR()) this->setupFDR();
248
249  if(this->par.isVerbose()) {
250    std::cout<<"  Smoothing spatially & searching... " << std::flush;
251    bar.init(zdim);
252  }
253
254  std::vector <Detection> outputList;
[884]255  size_t *imdim = new size_t[2];
[275]256  imdim[0] = xdim; imdim[1] = ydim;
257  Image *channelImage = new Image(imdim);
258  delete [] imdim;
259  channelImage->saveParam(this->par);
260  channelImage->saveStats(this->Stats);
261  channelImage->setMinSize(1);
262
263  float *image = new float[xySize];
[634]264  float *smoothed=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     
[1242]270    if(!this->par.isFlaggedChannel(z)){
[275]271
[894]272      for(size_t pix=0;pix<xySize;pix++) image[pix] = this->array[z*xySize+pix];
[275]273
[1393]274      std::vector<bool> mask  = this->par.makeBlankMask(image+z*xySize,xySize);
[275]275
276      smoothed = gauss.smooth(image,xdim,ydim,mask);
277     
278      findMedianStats(smoothed,xySize,mask,median,madfm);
279
280      channelImage->saveArray(smoothed,xySize);
281
[582]282      std::vector<PixelInfo::Object2D> objlist = channelImage->findSources2D();
[623]283      std::vector<PixelInfo::Object2D>::iterator obj;
[275]284      numFound += objlist.size();
[623]285      for(obj=objlist.begin();obj<objlist.end();obj++){
[275]286        Detection newObject;
[623]287        newObject.addChannel(z,*obj);
[275]288        newObject.setOffsets(this->par);
[1430]289        mergeIntoList(newObject,outputList,this->par);
[275]290      }
291
[201]292    }
[275]293   
[201]294  }
295
[275]296  delete [] smoothed;
297  delete [] image;
298  delete channelImage;
299   
[277]300  //   this->reconExists = true;
[275]301  if(par.isVerbose()){
302    bar.fillSpace("Found ");
303    std::cout << numFound << ".\n";
304  }
305   
[291]306  *this->objectList = outputList;
[201]307
308}
[378]309
310}
Note: See TracBrowser for help on using the repository browser.