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
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        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        delete [] mask;
219      }
220
221      this->reconExists = true;
222 
223      if(par.isVerbose()){
224        if(useBar) bar.fillSpace("All Done.");
225        std::cout << "\n";
226      }
227
228    }
229  }
230}
231//-----------------------------------------------------------
232
233void Cube::SpatialSmoothNSearch()
234{
235
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];
240  int numFound=0;
241  ProgressBar bar;
242
243  GaussSmooth2D<float> gauss(this->par.getKernMaj(),
244                           this->par.getKernMin(),
245                           this->par.getKernPA());
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;
256  size_t *imdim = new size_t[2];
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];
265  float *smoothed=0;
266  bool *mask=0;
267  float median,madfm;//,threshold;
268  for(size_t z=0;z<zdim;z++){
269
270    if( this->par.isVerbose() ) bar.update(z+1);
271     
272    if(!this->par.isFlaggedChannel(z)){
273
274      for(size_t pix=0;pix<xySize;pix++) image[pix] = this->array[z*xySize+pix];
275
276      mask  = this->par.makeBlankMask(image+z*xySize,xySize);
277
278      smoothed = gauss.smooth(image,xdim,ydim,mask);
279     
280      findMedianStats(smoothed,xySize,mask,median,madfm);
281
282      channelImage->saveArray(smoothed,xySize);
283
284      std::vector<PixelInfo::Object2D> objlist = channelImage->findSources2D();
285      std::vector<PixelInfo::Object2D>::iterator obj;
286      numFound += objlist.size();
287      for(obj=objlist.begin();obj<objlist.end();obj++){
288        Detection newObject;
289        newObject.addChannel(z,*obj);
290        newObject.setOffsets(this->par);
291        mergeIntoList(newObject,outputList,this->par);
292      }
293
294    }
295   
296  }
297
298  delete [] smoothed;
299  delete [] mask;
300  delete [] image;
301  delete channelImage;
302   
303  //   this->reconExists = true;
304  if(par.isVerbose()){
305    bar.fillSpace("Found ");
306    std::cout << numFound << ".\n";
307  }
308   
309  *this->objectList = outputList;
310
311}
312
313}
Note: See TracBrowser for help on using the repository browser.