source: tags/release-1.6.1/src/Cubes/smoothCube.cc

Last change on this file was 1393, checked in by MatthewWhiting, 10 years ago

A large changeset that moves all use of bool arrays (ie. bool *) to std::vector<bool>. This will be a bit safer, plus potentially cheaper in memory usage. Interfaces to all stats functions with masks have changed accordingly, as well as the Gaussian smoothing functions and some spectral utility functions.

File size: 8.7 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    if(this->par.isVerbose()) std::cout << "  Searching... " << std::flush;
63 
64    *(this->objectList) = search3DArray(this->axisDim,this->recon,
65                                        this->par,this->Stats);
66 
67    if(this->par.isVerbose()) std::cout << "  Updating detection map... "
68                                        << std::flush;
69    this->updateDetectMap();
70    if(this->par.isVerbose()) std::cout << "Done.\n";
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 
79  }
80
81}
82//-----------------------------------------------------------
83
84void Cube::SmoothCube()
85{
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
91  if(this->par.getSmoothType()=="spectral"){
92   
93    this->SpectralSmooth();
94   
95  }
96  else if(this->par.getSmoothType()=="spatial"){
97   
98    this->SpatialSmooth();
99   
100  }
101}
102//-----------------------------------------------------------
103
104void Cube::SpectralSmooth()
105{
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.
110
111  size_t xySize = this->axisDim[0]*this->axisDim[1];
112  size_t zdim = this->axisDim[2];
113  ProgressBar bar;
114
115  if(!this->reconExists && this->par.getSmoothType()=="spectral"){
116    //    if(!this->head.isSpecOK())
117    if(!this->head.canUseThirdAxis()){
118      DUCHAMPWARN("SpectralSmooth","There is no spectral axis, so cannot do the spectral smoothing.");
119    }
120    else{
121
122      Hanning hann(this->par.getHanningWidth());
123 
124      float *spectrum = new float[this->axisDim[2]];
125
126      if(this->par.isVerbose()) {
127        std::cout<<"  Smoothing spectrally... ";
128        bar.init(xySize);
129      }
130
131      for(size_t pix=0;pix<xySize;pix++){
132
133        if( this->par.isVerbose() ) bar.update(pix+1);
134   
135        for(size_t z=0;z<zdim;z++){
136          if(this->isBlank(z*xySize+pix)) spectrum[z]=0.;
137          else spectrum[z] = this->array[z*xySize+pix];
138        }
139
140        float *smoothed = hann.smooth(spectrum,zdim);
141
142        for(size_t z=0;z<zdim;z++){
143          if(this->isBlank(z*xySize+pix))
144            this->recon[z*xySize+pix] = this->array[z*xySize+pix];
145          else
146            this->recon[z*xySize+pix] = smoothed[z];
147        }
148        delete [] smoothed;
149      }
150      this->reconExists = true;
151      if(this->par.isVerbose()) bar.fillSpace("All Done.\n");
152
153      delete [] spectrum;
154
155    }
156  }
157}
158//-----------------------------------------------------------
159
160void Cube::SpatialSmooth()
161{
162
163  if(!this->reconExists && this->par.getSmoothType()=="spatial"){
164
165    if( this->head.getNumAxes() < 2 ){
166      DUCHAMPWARN("SpatialSmooth","There are not enough axes to do the spatial smoothing.");
167    }
168    else{
169
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];
174
175      ProgressBar bar;
176      bool useBar = this->par.isVerbose() && (zdim > 1);
177     
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
182      std::cout << "  ";
183      GaussSmooth2D<float> gauss(this->par.getKernMaj(),
184                                 this->par.getKernMin(),
185                                 this->par.getKernPA(),
186                                 this->par.getSpatialSmoothCutoff());
187 
188      if(this->par.isVerbose()) {
189        std::cout<<"  Smoothing spatially... " << std::flush;
190        if(useBar) bar.init(zdim);
191      }
192
193      // pointer used to point to start of a given channel's image
194      //  Can do this because the spatial axes vary the quickest.
195      float *image=0;
196
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
203      for(size_t z=0;z<zdim;z++){
204
205        if(useBar) bar.update(z+1);
206     
207        // update pointer to point to current channel
208        image = this->array + z*xySize;
209   
210        std::vector<bool> mask = this->par.makeBlankMask(image,xySize);
211   
212        float *smoothed = gauss.smooth(image,xdim,ydim,mask,edgeTreatment);
213   
214        for(size_t pix=0;pix<xySize;pix++)
215            this->recon[z*xySize+pix] = smoothed[pix];
216
217        if(gauss.isAllocated()) delete [] smoothed;
218      }
219
220      this->reconExists = true;
221 
222      if(par.isVerbose()){
223        if(useBar) bar.fillSpace("All Done.");
224        std::cout << "\n";
225      }
226
227    }
228  }
229}
230//-----------------------------------------------------------
231
232void Cube::SpatialSmoothNSearch()
233{
234
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];
239  int numFound=0;
240  ProgressBar bar;
241
242  GaussSmooth2D<float> gauss(this->par.getKernMaj(),
243                           this->par.getKernMin(),
244                           this->par.getKernPA());
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;
255  size_t *imdim = new size_t[2];
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];
264  float *smoothed=0;
265  float median,madfm;//,threshold;
266  for(size_t z=0;z<zdim;z++){
267
268    if( this->par.isVerbose() ) bar.update(z+1);
269     
270    if(!this->par.isFlaggedChannel(z)){
271
272      for(size_t pix=0;pix<xySize;pix++) image[pix] = this->array[z*xySize+pix];
273
274      std::vector<bool> mask  = this->par.makeBlankMask(image+z*xySize,xySize);
275
276      smoothed = gauss.smooth(image,xdim,ydim,mask);
277     
278      findMedianStats(smoothed,xySize,mask,median,madfm);
279
280      channelImage->saveArray(smoothed,xySize);
281
282      std::vector<PixelInfo::Object2D> objlist = channelImage->findSources2D();
283      std::vector<PixelInfo::Object2D>::iterator obj;
284      numFound += objlist.size();
285      for(obj=objlist.begin();obj<objlist.end();obj++){
286        Detection newObject;
287        newObject.addChannel(z,*obj);
288        newObject.setOffsets(this->par);
289        mergeIntoList(newObject,outputList,this->par);
290      }
291
292    }
293   
294  }
295
296  delete [] smoothed;
297  delete [] image;
298  delete channelImage;
299   
300  //   this->reconExists = true;
301  if(par.isVerbose()){
302    bar.fillSpace("Found ");
303    std::cout << numFound << ".\n";
304  }
305   
306  *this->objectList = outputList;
307
308}
309
310}
Note: See TracBrowser for help on using the repository browser.