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

Last change on this file since 894 was 894, checked in by MatthewWhiting, 12 years ago

A large swathe of changes aimed at fixing compilation warnings. These mostly refer to size_t conversions, although there is at least one instance of adding a return value to a function that needed it. Note there are still a few warnings - I need to decide how best to reconcile the size_t variables with integral values that could conceivably be negative...

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