source: tags/release-1.2.2/src/Utils/Statistics.cc

Last change on this file was 528, checked in by MatthewWhiting, 15 years ago

Changing the documentation comments to match the askapsoft style. Also have split ChanMap? and Object3D into separate files.

File size: 14.1 KB
Line 
1// -----------------------------------------------------------------------
2// Statistics.cc: Member functions for the templated StatsContainer
3//                class.
4// -----------------------------------------------------------------------
5// Copyright (C) 2006, Matthew Whiting, ATNF
6//
7// This program is free software; you can redistribute it and/or modify it
8// under the terms of the GNU General Public License as published by the
9// Free Software Foundation; either version 2 of the License, or (at your
10// option) any later version.
11//
12// Duchamp is distributed in the hope that it will be useful, but WITHOUT
13// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15// for more details.
16//
17// You should have received a copy of the GNU General Public License
18// along with Duchamp; if not, write to the Free Software Foundation,
19// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
20//
21// Correspondence concerning Duchamp may be directed to:
22//    Internet email: Matthew.Whiting [at] atnf.csiro.au
23//    Postal address: Dr. Matthew Whiting
24//                    Australia Telescope National Facility, CSIRO
25//                    PO Box 76
26//                    Epping NSW 1710
27//                    AUSTRALIA
28// -----------------------------------------------------------------------
29#include <iostream>
30#include <duchamp/Utils/Statistics.hh>
31#include <duchamp/Utils/utils.hh>
32
33namespace Statistics
34{
35
36  template <class T>
37  float madfmToSigma(T madfm){
38    return float(madfm)/correctionFactor;
39  }
40  template float madfmToSigma<int>(int madfm);
41  template float madfmToSigma<long>(long madfm);
42  template float madfmToSigma<float>(float madfm);
43  template float madfmToSigma<double>(double madfm);
44
45  //--------------------------------------------------------------------
46  float sigmaToMADFM(float sigma){
47    return float(sigma)*correctionFactor;
48  }
49  //--------------------------------------------------------------------
50  //--------------------------------------------------------------------
51
52  template <class Type>
53  StatsContainer<Type>::StatsContainer(const StatsContainer<Type>& s)
54  {
55    ///  @details
56    ///  The copy constructor for the StatsContainer class. Just uses
57    ///  the assignment operator.
58
59    operator=(s);
60  }
61  template StatsContainer<int>::StatsContainer(const StatsContainer<int>& s);
62  template StatsContainer<long>::StatsContainer(const StatsContainer<long>& s);
63  template StatsContainer<float>::StatsContainer(const StatsContainer<float>& s);
64  template StatsContainer<double>::StatsContainer(const StatsContainer<double>& s);
65  //--------------------------------------------------------------------
66
67  template <class Type>
68  StatsContainer<Type>&
69  StatsContainer<Type>::operator= (const StatsContainer<Type>& s)
70  {
71    ///  The assignment operator for the StatsContainer class.
72
73    if(this == &s) return *this;
74    this->defined    = s.defined;
75    this->mean       = s.mean;
76    this->stddev     = s.stddev;
77    this->median     = s.median;
78    this->madfm      = s.madfm;
79    this->threshold  = s.threshold;
80    this->pThreshold = s.pThreshold;
81    this->useRobust  = s.useRobust;
82    this->useFDR     = s.useFDR;
83    return *this;
84  }
85  template StatsContainer<int>& StatsContainer<int>::operator= (const StatsContainer<int>& s);
86  template StatsContainer<long>& StatsContainer<long>::operator= (const StatsContainer<long>& s);
87  template StatsContainer<float>& StatsContainer<float>::operator= (const StatsContainer<float>& s);
88  template StatsContainer<double>& StatsContainer<double>::operator= (const StatsContainer<double>& s);
89  //--------------------------------------------------------------------
90
91  template <class Type>
92  float StatsContainer<Type>::getThresholdSNR()
93  {
94    ///  @details
95    /// The SNR is defined in terms of excess over the middle estimator
96    /// in units of the spread estimator.
97    return (threshold - this->getMiddle())/this->getSpread();
98  }
99  template float StatsContainer<int>::getThresholdSNR();
100  template float StatsContainer<long>::getThresholdSNR();
101  template float StatsContainer<float>::getThresholdSNR();
102  template float StatsContainer<double>::getThresholdSNR();
103  //--------------------------------------------------------------------
104
105  template <class Type>
106  void  StatsContainer<Type>::setThresholdSNR(float snr)
107  {
108    ///  @details
109    /// The SNR is defined in terms of excess over the middle estimator
110    /// in units of the spread estimator.
111    threshold=this->getMiddle() + snr*this->getSpread();
112  }
113  template void StatsContainer<int>::setThresholdSNR(float snr);
114  template void StatsContainer<long>::setThresholdSNR(float snr);
115  template void StatsContainer<float>::setThresholdSNR(float snr);
116  template void StatsContainer<double>::setThresholdSNR(float snr);
117  //--------------------------------------------------------------------
118 
119  template <class Type>
120  float StatsContainer<Type>::valueToSNR(float value)
121  {
122    ///  @details
123    /// The SNR is defined in terms of excess over the middle estimator
124    /// in units of the spread estimator.
125    return (value - this->getMiddle())/this->getSpread();
126  }
127  template float StatsContainer<int>::valueToSNR(float value);
128  template float StatsContainer<long>::valueToSNR(float value);
129  template float StatsContainer<float>::valueToSNR(float value);
130  template float StatsContainer<double>::valueToSNR(float value);
131  //--------------------------------------------------------------------
132 
133  template <class Type>
134  float StatsContainer<Type>::snrToValue(float snr)
135  {
136    ///  @details
137    /// The SNR is defined in terms of excess over the middle estimator
138    /// in units of the spread estimator.
139    return snr * this->getSpread() + this->getMiddle();
140  }
141  template float StatsContainer<int>::snrToValue(float value);
142  template float StatsContainer<long>::snrToValue(float value);
143  template float StatsContainer<float>::snrToValue(float value);
144  template float StatsContainer<double>::snrToValue(float value);
145  //--------------------------------------------------------------------
146   
147  template <class Type>
148  void StatsContainer<Type>::setMiddle(float middle)
149  {
150    ///  @details
151    /// The middle value is determined by the StatsContainer::useRobust
152    /// flag -- it will be either the median (if true), or the mean (if
153    /// false).
154    if(useRobust) this->median = Type(middle);
155    else this->mean = middle;
156  }
157  template void StatsContainer<int>::setMiddle(float middle);
158  template void StatsContainer<long>::setMiddle(float middle);
159  template void StatsContainer<float>::setMiddle(float middle);
160  template void StatsContainer<double>::setMiddle(float middle);
161  //--------------------------------------------------------------------
162   
163  template <class Type>
164  float StatsContainer<Type>::getMiddle()
165  {
166    ///  @details
167    /// The middle value is determined by the StatsContainer::useRobust
168    /// flag -- it will be either the median (if true), or the mean (if
169    /// false).
170    if(useRobust) return float(this->median);
171    else return this->mean;
172  }
173  template float StatsContainer<int>::getMiddle();
174  template float StatsContainer<long>::getMiddle();
175  template float StatsContainer<float>::getMiddle();
176  template float StatsContainer<double>::getMiddle();
177  //--------------------------------------------------------------------
178   
179  template <class Type>
180  void StatsContainer<Type>::setSpread(float spread)
181  {
182    ///  @details
183    /// The spread value is set according to the
184    /// StatsContainer::useRobust flag -- it will be either the madfm
185    /// (if true), or the rms (if false). If robust, the spread value will be
186    /// converted to a madfm from an equivalent rms under the assumption of
187    /// Gaussianity, using the Statistics::sigmaToMADFM function.
188    if(useRobust) this->madfm = Type(sigmaToMADFM(spread));
189    else this->stddev = spread;
190  }
191  template void StatsContainer<int>::setSpread(float spread);
192  template void StatsContainer<long>::setSpread(float spread);
193  template void StatsContainer<float>::setSpread(float spread);
194  template void StatsContainer<double>::setSpread(float spread);
195  //--------------------------------------------------------------------
196   
197  template <class Type>
198  float StatsContainer<Type>::getSpread()
199  {
200    ///  @details
201    /// The spread value returned is determined by the
202    /// StatsContainer::useRobust flag -- it will be either the madfm
203    /// (if true), or the rms (if false). If robust, the madfm will be
204    /// converted to an equivalent rms under the assumption of
205    /// Gaussianity, using the Statistics::madfmToSigma function.
206    if(useRobust) return madfmToSigma(this->madfm);
207    else return this->stddev;
208  }
209  template float StatsContainer<int>::getSpread();
210  template float StatsContainer<long>::getSpread();
211  template float StatsContainer<float>::getSpread();
212  template float StatsContainer<double>::getSpread();
213  //--------------------------------------------------------------------
214   
215  template <class Type>
216  void  StatsContainer<Type>::scaleNoise(float scale)
217  {
218    /// @details
219    ///  Multiply the noise parameters (stddev & madfm) by a given
220    ///  factor, and adjust the threshold.
221    float snr = (threshold - this->getMiddle())/this->getSpread();   
222    this->madfm  = Type(this->madfm*scale);
223    this->stddev *= scale;
224    this->threshold = this->getMiddle() + snr*this->getSpread();
225  }
226  template void StatsContainer<int>::scaleNoise(float scale);
227  template void StatsContainer<long>::scaleNoise(float scale);
228  template void StatsContainer<float>::scaleNoise(float scale);
229  template void StatsContainer<double>::scaleNoise(float scale);
230 //--------------------------------------------------------------------
231
232  template <class Type>
233  float StatsContainer<Type>::getPValue(float value)
234  {
235    ///  @details
236    /// Get the "probability", under the assumption of normality, of a
237    /// value occuring. 
238    ///
239    /// It is defined by \f$0.5 \operatorname{erfc}(z/\sqrt{2})\f$, where
240    /// \f$z=(x-\mu)/\sigma\f$. We need the factor of 0.5 here, as we are
241    /// only considering the positive tail of the distribution -- we
242    /// don't care about negative detections.
243   
244    float zStat = (value - this->getMiddle()) / this->getSpread();
245    return 0.5 * erfc( zStat / M_SQRT2 );
246  }
247  template float StatsContainer<int>::getPValue(float value);
248  template float StatsContainer<long>::getPValue(float value);
249  template float StatsContainer<float>::getPValue(float value);
250  template float StatsContainer<double>::getPValue(float value);
251  //--------------------------------------------------------------------
252   
253  template <class Type>
254  bool StatsContainer<Type>::isDetection(float value)
255  {
256    ///  @details
257    /// Compares the value given to the correct threshold, depending on
258    /// the value of the StatsContainer::useFDR flag.
259    if(useFDR) return (this->getPValue(value) < this->pThreshold);
260    else       return (value > this->threshold);
261  }
262  template bool StatsContainer<int>::isDetection(float value);
263  template bool StatsContainer<long>::isDetection(float value);
264  template bool StatsContainer<float>::isDetection(float value);
265  template bool StatsContainer<double>::isDetection(float value);
266  //--------------------------------------------------------------------
267
268  template <class Type>
269  void StatsContainer<Type>::calculate(Type *array, long size)
270  {
271    /// @details
272    /// Calculate all four statistics for all elements of a given
273    /// array.
274    ///
275    /// \param array The input data array.
276    /// \param size The length of the input array
277//     findNormalStats(array, size, this->mean, this->stddev);
278//     findMedianStats(array, size, this->median, this->madfm);
279    findAllStats(array,size,this->mean,this->stddev,this->median,this->madfm);
280    this->defined = true;
281  }
282  template void StatsContainer<int>::calculate(int *array, long size);
283  template void StatsContainer<long>::calculate(long *array, long size);
284  template void StatsContainer<float>::calculate(float *array, long size);
285  template void StatsContainer<double>::calculate(double *array, long size);
286  //--------------------------------------------------------------------
287
288  template <class Type>
289  void StatsContainer<Type>::calculate(Type *array, long size, bool *mask)
290  {
291    /// @details
292    /// Calculate all four statistics for a subset of a given
293    /// array. The subset is defined by an array of bool
294    /// variables. 
295    ///
296    /// \param array The input data array.
297    /// \param size The length of the input array
298    /// \param mask An array of the same length that says whether to
299    /// include each member of the array in the calculations. Use a
300    /// value if mask=true.
301//     findNormalStats(array, size, mask, this->mean, this->stddev);
302//     findMedianStats(array, size, mask, this->median, this->madfm);
303    findAllStats(array, size, mask,
304                 this->mean, this->stddev, this->median, this->madfm);
305    this->defined = true;
306  }
307  template void StatsContainer<int>::calculate(int *array, long size, bool *mask);
308  template void StatsContainer<long>::calculate(long *array, long size, bool *mask);
309  template void StatsContainer<float>::calculate(float *array, long size, bool *mask);
310  template void StatsContainer<double>::calculate(double *array, long size, bool *mask);
311  //--------------------------------------------------------------------
312
313  template <class Type>
314  std::ostream& operator<< (std::ostream& theStream, StatsContainer<Type> &s)
315  {
316    /// Prints out the four key statistics to the requested stream.
317    theStream << "Mean   = "   << s.mean   << "\t"
318              << "Std.Dev. = " << s.stddev << "\n"
319              << "Median = "   << s.median << "\t"
320              << "MADFM    = " << s.madfm  << " (= " << madfmToSigma(s.madfm) << " as std.dev.)\n";
321    return theStream;
322  }
323  template std::ostream& operator<<<int> (std::ostream& theStream, StatsContainer<int> &s);
324  template std::ostream& operator<<<long> (std::ostream& theStream, StatsContainer<long> &s);
325  template std::ostream& operator<<<float> (std::ostream& theStream, StatsContainer<float> &s);
326  template std::ostream& operator<<<double> (std::ostream& theStream, StatsContainer<double> &s);
327
328
329
330}  // matches:  namespace Statistics {
Note: See TracBrowser for help on using the repository browser.