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

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

Some major changes to the 2D smoothing. Fixing the normalisation of the kernel, so that the fluxes do the right thing in the smoothed array (ie. don't go up). Also moving to size_t types for a lot of the indexing variables. Finally, improving the memory management of the arrays in the function that calls the smoother.

File size: 8.9 KB
Line 
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// -----------------------------------------------------------------------
28#include <vector>
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/GaussSmooth2D.hh>
36#include <duchamp/Utils/Statistics.hh>
37#include <duchamp/Utils/utils.hh>
38
39namespace duchamp
40{
41
42void Cube::SmoothSearch()
43{
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.
49
50  if(!this->par.getFlagSmooth()){
51    DUCHAMPWARN("SmoothSearch","FlagSmooth not set! Using basic CubicSearch.");
52    this->CubicSearch();
53  }
54  else{   
55
56    this->SmoothCube();
57 
58    if(this->par.isVerbose()) std::cout << "  ";
59
60    this->setCubeStats();
61
62//       this->Stats.scaleNoise(1./gauss.getStddevScale());
63
64    if(this->par.isVerbose()) std::cout << "  Searching... " << std::flush;
65 
66    *(this->objectList) = search3DArray(this->axisDim,this->recon,
67                                        this->par,this->Stats);
68 
69    if(this->par.isVerbose()) std::cout << "  Updating detection map... "
70                                        << std::flush;
71    this->updateDetectMap();
72    if(this->par.isVerbose()) std::cout << "Done.\n";
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 
81  }
82
83}
84//-----------------------------------------------------------
85
86void Cube::SmoothCube()
87{
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
93  if(this->par.getSmoothType()=="spectral"){
94   
95    this->SpectralSmooth();
96   
97  }
98  else if(this->par.getSmoothType()=="spatial"){
99   
100    this->SpatialSmooth();
101   
102  }
103}
104//-----------------------------------------------------------
105
106void Cube::SpectralSmooth()
107{
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.
112
113  size_t xySize = this->axisDim[0]*this->axisDim[1];
114  size_t zdim = this->axisDim[2];
115  ProgressBar bar;
116
117  if(!this->reconExists && this->par.getSmoothType()=="spectral"){
118    //    if(!this->head.isSpecOK())
119    if(!this->head.canUseThirdAxis()){
120      DUCHAMPWARN("SpectralSmooth","There is no spectral axis, so cannot do the spectral smoothing.");
121    }
122    else{
123
124      Hanning hann(this->par.getHanningWidth());
125 
126      float *spectrum = new float[this->axisDim[2]];
127
128      if(this->par.isVerbose()) {
129        std::cout<<"  Smoothing spectrally... ";
130        bar.init(xySize);
131      }
132
133      for(size_t pix=0;pix<xySize;pix++){
134
135        if( this->par.isVerbose() ) bar.update(pix+1);
136   
137        for(size_t z=0;z<zdim;z++){
138          if(this->isBlank(z*xySize+pix)) spectrum[z]=0.;
139          else spectrum[z] = this->array[z*xySize+pix];
140        }
141
142        float *smoothed = hann.smooth(spectrum,zdim);
143
144        for(size_t z=0;z<zdim;z++){
145          if(this->isBlank(z*xySize+pix))
146            this->recon[z*xySize+pix] = this->array[z*xySize+pix];
147          else
148            this->recon[z*xySize+pix] = smoothed[z];
149        }
150        delete [] smoothed;
151      }
152      this->reconExists = true;
153      if(this->par.isVerbose()) bar.fillSpace("All Done.\n");
154
155      delete [] spectrum;
156
157    }
158  }
159}
160//-----------------------------------------------------------
161
162void Cube::SpatialSmooth()
163{
164
165  if(!this->reconExists && this->par.getSmoothType()=="spatial"){
166
167    if( this->head.getNumAxes() < 2 ){
168      DUCHAMPWARN("SpatialSmooth","There are not enough axes to do the spatial smoothing.");
169    }
170    else{
171
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];
176
177      ProgressBar bar;
178//       bool useBar = this->head.canUseThirdAxis();
179      bool useBar = (zdim > 1);
180     
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
185      GaussSmooth2D<float> gauss(this->par.getKernMaj(),
186                               this->par.getKernMin(),
187                               this->par.getKernPA());
188
189      if(this->par.isVerbose()) {
190        std::cout<<"  Smoothing spatially... " << std::flush;
191        if(useBar) bar.init(zdim);
192      }
193
194      float *image=0;
195
196      for(size_t z=0;z<zdim;z++){
197
198        if( this->par.isVerbose() && useBar ) bar.update(z+1);
199     
200        image = this->array + z*xySize;
201   
202        bool *mask      = this->par.makeBlankMask(image,xySize);
203   
204        float *smoothed = gauss.smooth(image,xdim,ydim,mask);
205   
206        for(size_t pix=0;pix<xySize;pix++)
207            this->recon[z*xySize+pix] = smoothed[pix];
208
209        if(gauss.isAllocated()) delete [] smoothed;
210        delete [] mask;
211      }
212
213      this->reconExists = true;
214 
215      if(par.isVerbose()){
216        if(useBar) bar.fillSpace("All Done.");
217        std::cout << "\n";
218      }
219
220    }
221  }
222}
223//-----------------------------------------------------------
224
225void Cube::SpatialSmoothNSearch()
226{
227
228  size_t xySize = this->axisDim[0]*this->axisDim[1];
229  size_t xdim = this->axisDim[0];
230  size_t ydim = this->axisDim[1];
231  size_t zdim = this->axisDim[2];
232  int numFound=0;
233  ProgressBar bar;
234
235  GaussSmooth2D<float> gauss(this->par.getKernMaj(),
236                           this->par.getKernMin(),
237                           this->par.getKernPA());
238
239  this->Stats.scaleNoise(1./gauss.getStddevScale());
240  if(this->par.getFlagFDR()) this->setupFDR();
241
242  if(this->par.isVerbose()) {
243    std::cout<<"  Smoothing spatially & searching... " << std::flush;
244    bar.init(zdim);
245  }
246
247  std::vector <Detection> outputList;
248  size_t *imdim = new size_t[2];
249  imdim[0] = xdim; imdim[1] = ydim;
250  Image *channelImage = new Image(imdim);
251  delete [] imdim;
252  channelImage->saveParam(this->par);
253  channelImage->saveStats(this->Stats);
254  channelImage->setMinSize(1);
255
256  float *image = new float[xySize];
257  float *smoothed=0;
258  bool *mask=0;
259  float median,madfm;//,threshold;
260  for(size_t z=0;z<zdim;z++){
261
262    if( this->par.isVerbose() ) bar.update(z+1);
263     
264    if(!this->par.isInMW(z)){
265
266      for(size_t pix=0;pix<xySize;pix++) image[pix] = this->array[z*xySize+pix];
267
268      mask  = this->par.makeBlankMask(image+z*xySize,xySize);
269
270      smoothed = gauss.smooth(image,xdim,ydim,mask);
271     
272      //     for(int pix=0;pix<xySize;pix++)
273      //       this->recon[z*xySize+pix] = smoothed[pix];
274
275      findMedianStats(smoothed,xySize,mask,median,madfm);
276      //       threshold = median+this->par.getCut()*Statistics::madfmToSigma(madfm);
277      //       for(int i=0;i<xySize;i++)
278      //        if(smoothed[i]<threshold) image[i] = this->Stats.getMiddle();
279      //       channelImage->saveArray(image,xySize);
280
281
282      //       channelImage->stats().setMadfm(madfm);
283      //       channelImage->stats().setMedian(median);
284      //       channelImage->stats().setThresholdSNR(this->par.getCut());
285      channelImage->saveArray(smoothed,xySize);
286
287      std::vector<PixelInfo::Object2D> objlist = channelImage->findSources2D();
288      std::vector<PixelInfo::Object2D>::iterator obj;
289      numFound += objlist.size();
290      for(obj=objlist.begin();obj<objlist.end();obj++){
291        Detection newObject;
292        newObject.addChannel(z,*obj);
293        newObject.setOffsets(this->par);
294        mergeIntoList(newObject,outputList,this->par);
295      }
296
297    }
298   
299  }
300
301  delete [] smoothed;
302  delete [] mask;
303  delete [] image;
304  delete channelImage;
305   
306  //   this->reconExists = true;
307  if(par.isVerbose()){
308    bar.fillSpace("Found ");
309    std::cout << numFound << ".\n";
310  }
311   
312  *this->objectList = outputList;
313
314}
315
316}
Note: See TracBrowser for help on using the repository browser.