source: trunk/src/Utils/getStats.cc @ 699

Last change on this file since 699 was 699, checked in by MatthewWhiting, 14 years ago

Fixing warnings about conversions

File size: 16.8 KB
Line 
1// -----------------------------------------------------------------------
2// getStats.cc: Basic functions to calculate statistical parameters
3//              such as mean, median, rms, madfm, min, max.
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 <algorithm>
31#include <math.h>
32#include <duchamp/Utils/utils.hh>
33
34template <class T> T absval(T value)
35{
36  /// Type-independent way of getting the absolute value.
37  if( value > 0) return value;
38  else return 0-value;
39}
40template int absval<int>(int value);
41template long absval<long>(long value);
42template float absval<float>(float value);
43template double absval<double>(double value);
44//--------------------------------------------------------------------
45
46template <class T> void findMinMax(const T *array, const int size,
47                                   T &min, T &max)
48{
49  /// @details
50  /// A function to find the minimum and maximum values of a set of numbers.
51  /// \param array The array of data values. Type independent.
52  /// \param size The length of the array
53  /// \param min The returned value of the minimum value in the array.
54  /// \param max The returned value of the maximum value in the array.
55  min = max = array[0];
56  for(int i=1;i<size;i++) {
57    if(array[i]<min) min=array[i];
58    if(array[i]>max) max=array[i];
59  }
60}
61template void findMinMax<int>(const int *array, const int size,
62                                 int &min, int &max);
63template void findMinMax<long>(const long *array, const int size,
64                                  long &min, long &max);
65template void findMinMax<float>(const float *array, const int size,
66                                   float &min, float &max);
67template void findMinMax<double>(const double *array, const int size,
68                                    double &min, double &max);
69//--------------------------------------------------------------------
70
71template <class T> float findMean(T *array, int size)
72{
73  /// @details
74  /// Find the mean of an array of numbers. Type independent.
75  /// \param array The array of numbers.
76  /// \param size The length of the array.
77  /// \return The mean value of the array, returned as a float
78  double mean = double(array[0]);
79  for(int i=1;i<size;i++) mean += double(array[i]);
80  mean /= double(size);
81  return float(mean);
82}
83template float findMean<int>(int *array, int size);
84template float findMean<long>(long *array, int size);
85template float findMean<float>(float *array, int size);
86template float findMean<double>(double *array, int size);
87//--------------------------------------------------------------------
88
89template <class T> float findStddev(T *array, int size)
90{
91  /// @details
92  /// Find the rms or standard deviation of an array of numbers. Type independent.
93  /// \param array The array of numbers.
94  /// \param size The length of the array.
95  /// \return The rms value of the array, returned as a float
96  double mean = double(findMean(array,size));
97  double stddev = (double(array[0])-mean) * (double(array[0])-mean);
98  for(int i=1;i<size;i++) stddev += (double(array[i])-mean)*(double(array[i])-mean);
99  stddev = sqrt(stddev/double(size-1));
100  return float(stddev);
101}
102template float findStddev<int>(int *array, int size);
103template float findStddev<long>(long *array, int size);
104template float findStddev<float>(float *array, int size);
105template float findStddev<double>(double *array, int size);
106//--------------------------------------------------------------------
107
108template <class T> T findMedian(T *array, int size, bool changeArray)
109{
110  /// @details
111  /// Find the median value of an array of numbers. Type independent.
112  /// \param array The array of numbers.
113  /// \param size The length of the array.
114  /// \param changeArray [false] Whether to use the provided array in calculations. If true, the input array will be altered (ie. the order of elements will be changed).
115  /// \return The median value of the array, returned as the same type as the array.
116  T *newarray;
117  if(changeArray) newarray = array;
118  else{
119    newarray = new T[size];
120    for(int i=0;i<size;i++) newarray[i] = array[i];
121  }
122  T median;
123  bool isEven = ((size/2)==0);
124  std::nth_element(newarray,newarray+size/2,newarray+size);
125  median = newarray[size/2];
126  if(isEven){
127    std::nth_element(newarray,newarray+size/2-1,newarray+size);
128    median += newarray[size/2-1];
129    median /= T(2);
130  }
131  if(!changeArray) delete [] newarray;
132  return median;
133}
134template int findMedian<int>(int *array, int size, bool changeArray);
135template long findMedian<long>(long *array, int size, bool changeArray);
136template float findMedian<float>(float *array, int size, bool changeArray);
137template double findMedian<double>(double *array, int size, bool changeArray);
138//--------------------------------------------------------------------
139
140template <class T> T findMADFM(T *array, int size, bool changeArray)
141{
142  /// @details
143  /// Find the median absolute deviation from the median value of an
144  /// array of numbers. Type independent.
145  ///
146  /// \param array The array of numbers.
147  /// \param size The length of the array.
148  /// \param changeArray [false] Whether to use the provided array in calculations. If true, the input array will be altered - both the order and values of the elements will be changed.
149  /// \return The median absolute deviation from the median value of
150  /// the array, returned as the same type as the array.
151  T *newarray;
152  if(changeArray) newarray = array;
153  else newarray = new T[size];
154
155  T median = findMedian<T>(array,size,changeArray);
156  T madfm;
157  bool isEven = ((size/2)==0);
158  for(int i=0;i<size;i++) newarray[i] = absval(array[i]-median);
159  std::nth_element(newarray,newarray+size/2,newarray+size);
160  madfm = newarray[size/2];
161  if(isEven){
162    std::nth_element(newarray,newarray+size/2-1,newarray+size);
163    madfm += newarray[size/2-1];
164    madfm /= T(2);
165  }
166  if(!changeArray) delete [] newarray;
167  return madfm;
168}
169template int findMADFM<int>(int *array, int size, bool changeArray);
170template long findMADFM<long>(long *array, int size, bool changeArray);
171template float findMADFM<float>(float *array, int size, bool changeArray);
172template double findMADFM<double>(double *array, int size, bool changeArray);
173//--------------------------------------------------------------------
174
175template <class T> void findMedianStats(T *array, int size,
176                                        T &median, T &madfm)
177{
178  /// @details
179  /// Find the median and the median absolute deviation from the median
180  /// value of an array of numbers. Type independent.
181  ///
182  /// \param array The array of numbers.
183  /// \param size The length of the array.
184  /// \param median The median value of the array, returned as the same
185  /// type as the array.
186  /// \param madfm The median absolute deviation from the median value
187  /// of the array, returned as the same type as the array.
188  if(size==0){
189    std::cerr << "Error in findMedianStats: zero sized array!\n";
190    return;
191  }
192  T *newarray = new T[size];
193   for(int i=0;i<size;i++) newarray[i] = array[i];
194
195   median = findMedian(newarray,size,true);
196   madfm = findMADFM(newarray,size,true);
197
198  delete [] newarray;
199}
200template void findMedianStats<int>(int *array, int size,
201                                      int &median, int &madfm);
202template void findMedianStats<long>(long *array, int size,
203                                       long &median, long &madfm);
204template void findMedianStats<float>(float *array, int size,
205                                        float &median, float &madfm);
206template void findMedianStats<double>(double *array, int size,
207                                         double &median, double &madfm);
208//--------------------------------------------------------------------
209
210template <class T> void findMedianStats(T *array, int size, bool *mask,
211                                        T &median, T &madfm)
212{
213  /// @details
214  /// Find the median and the median absolute deviation from the median
215  /// value of a subset of an array of numbers. The subset is defined
216  /// by an array of bool variables. Type independent.
217  ///
218  /// \param array The array of numbers.
219  /// \param size The length of the array.
220  /// \param mask An array of the same length that says whether to
221  /// include each member of the array in the calculations. Only use
222  /// values where mask=true.
223  /// \param median The median value of the array, returned as the same
224  /// type as the array.
225  /// \param madfm The median absolute deviation from the median value
226  /// of the array, returned as the same type as the array.
227
228  int goodSize=0;
229  for(int i=0;i<size;i++) if(mask[i]) goodSize++;
230  if(goodSize==0){
231    std::cerr << "Error in findMedianStats: no good values!\n";
232    return;
233  }
234  T *newarray = new T[goodSize];
235
236  goodSize=0;
237  for(int i=0;i<size;i++) if(mask[i]) newarray[goodSize++] = array[i];
238  median = findMedian(newarray,goodSize,true);
239  madfm = findMADFM(newarray,goodSize,true);
240
241  delete [] newarray;
242}
243template void findMedianStats<int>(int *array, int size, bool *mask,
244                                      int &median, int &madfm);
245template void findMedianStats<long>(long *array, int size, bool *mask,
246                                       long &median, long &madfm);
247template void findMedianStats<float>(float *array, int size, bool *mask,
248                                        float &median, float &madfm);
249template void findMedianStats<double>(double *array, int size, bool *mask,
250                                         double &median, double &madfm);
251//--------------------------------------------------------------------
252 
253
254template <class T> void findNormalStats(T *array, int size,
255                                        float &mean, float &stddev)
256{
257  /// @details
258  /// Find the mean and rms or standard deviation of an array of
259  /// numbers. Type independent.
260  ///
261  /// \param array The array of numbers.
262  /// \param size The length of the array.
263  /// \param mean The mean value of the array, returned as a float.
264  /// \param stddev The rms or standard deviation of the array,
265  /// returned as a float.
266
267  if(size==0){
268    std::cerr << "Error in findNormalStats: zero sized array!\n";
269    return;
270  }
271  mean = array[0];
272  for(int i=1;i<size;i++){
273    mean += array[i];
274  }
275  mean /= float(size);
276
277  stddev = (array[0]-mean) * (array[0]-mean);
278  for(int i=1;i<size;i++) stddev += (array[i]-mean)*(array[i]-mean);
279  stddev = sqrt(stddev/float(size-1));
280
281}
282template void findNormalStats<int>(int *array, int size,
283                                      float &mean, float &stddev);
284template void findNormalStats<long>(long *array, int size,
285                                       float &mean, float &stddev);
286template void findNormalStats<float>(float *array, int size,
287                                        float &mean, float &stddev);
288template void findNormalStats<double>(double *array, int size,
289                                         float &mean, float &stddev);
290//--------------------------------------------------------------------
291
292template <class T> void findNormalStats(T *array, int size, bool *mask,
293                                        float &mean, float &stddev)
294{
295  /// @details
296  /// Find the mean and rms or standard deviation of a subset of an
297  /// array of numbers. The subset is defined by an array of bool
298  /// variables. Type independent.
299  ///
300  /// \param array The array of numbers.
301  /// \param size The length of the array.
302  /// \param mask An array of the same length that says whether to
303  /// include each member of the array in the calculations. Only look
304  /// at values where mask=true.
305  /// \param mean The mean value of the array, returned as a float.
306  /// \param stddev The rms or standard deviation of the array,
307  /// returned as a float.
308
309  int goodSize=0;
310  for(int i=0;i<size;i++) if(mask[i]) goodSize++;
311  if(goodSize==0){
312    std::cerr << "Error in findNormalStats: no good values!\n";
313    return;
314  }
315  int start=0;
316  while(!mask[start]){start++;}
317  mean = array[start];
318  for(int i=start+1;i<size;i++){
319    if(mask[i]) mean += array[i];
320  }
321  mean /= float(goodSize);
322
323  stddev = (array[start]-mean) * (array[start]-mean);
324  for(int i=1;i<size;i++){
325    if(mask[i]) stddev += (array[i]-mean)*(array[i]-mean);
326  }
327  stddev = sqrt(stddev/float(goodSize-1));
328
329}
330template void findNormalStats<int>(int *array, int size, bool *mask,
331                                      float &mean, float &stddev);
332template void findNormalStats<long>(long *array, int size, bool *mask,
333                                       float &mean, float &stddev);
334template void findNormalStats<float>(float *array, int size, bool *mask,
335                                        float &mean, float &stddev);
336template void findNormalStats<double>(double *array, int size, bool *mask,
337                                         float &mean, float &stddev);
338//--------------------------------------------------------------------
339//--------------------------------------------------------------------
340 
341
342template <class T> void findAllStats(T *array, int size,
343                                     float &mean, float &stddev,
344                                     T &median, T &madfm)
345{
346  /// @details
347  /// Find the mean,rms (or standard deviation), median AND madfm of an
348  /// array of numbers. Type independent.
349  ///
350  /// \param array The array of numbers.
351  /// \param size The length of the array.
352  /// \param mean The mean value of the array, returned as a float.
353  /// \param stddev The rms or standard deviation of the array,
354  /// returned as a float.
355  /// \param median The median value of the array, returned as the same
356  /// type as the array.
357  /// \param madfm The median absolute deviation from the median value
358  /// of the array, returned as the same type as the array.
359
360  if(size==0){
361    std::cerr << "Error in findAllStats: zero sized array!\n";
362    return;
363  }
364
365  T *newarray = new T[size];
366
367  for(int i=0;i<size;i++) newarray[i] = array[i];
368
369  mean = findMean(newarray,size);
370  stddev = findStddev(newarray,size);
371  median = findMedian(newarray,size,true);
372  madfm = findMADFM(newarray,size,true);
373
374  delete [] newarray;
375
376}
377template void findAllStats<int>(int *array, int size,
378                                float &mean, float &stddev,
379                                int &median, int &madfm);
380template void findAllStats<long>(long *array, int size,
381                                 float &mean, float &stddev,
382                                 long &median, long &madfm);
383template void findAllStats<float>(float *array, int size,
384                                  float &mean, float &stddev,
385                                  float &median, float &madfm);
386template void findAllStats<double>(double *array, int size,
387                                   float &mean, float &stddev,
388                                   double &median, double &madfm);
389//--------------------------------------------------------------------
390
391template <class T> void findAllStats(T *array, int size, bool *mask,
392                                     float &mean, float &stddev,
393                                     T &median, T &madfm)
394{
395  /// @details
396  /// Find the mean,rms (or standard deviation), median AND madfm of a
397  /// subset of an array of numbers. Type independent.The subset is
398  /// defined by an array of bool variables. Type independent.
399  ///
400  /// \param array The array of numbers.
401  /// \param size The length of the array.
402  /// \param mask An array of the same length that says whether to
403  /// include each member of the array in the calculations. Only look
404  /// at values where mask=true.
405  /// \param mean The mean value of the array, returned as a float.
406  /// \param stddev The rms or standard deviation of the array,
407  /// returned as a float.
408  /// \param median The median value of the array, returned as the same
409  /// type as the array.
410  /// \param madfm The median absolute deviation from the median value
411  /// of the array, returned as the same type as the array.
412
413  int goodSize=0;
414  for(int i=0;i<size;i++) if(mask[i]) goodSize++;
415  if(goodSize==0){
416    std::cerr << "Error in findAllStats: no good values!\n";
417    return;
418  }
419
420  T *newarray = new T[goodSize];
421  goodSize=0;
422  for(int i=0;i<size;i++) if(mask[i]) newarray[goodSize++] = array[i];
423
424  mean = findMean(newarray,goodSize);
425  stddev = findStddev(newarray,goodSize);
426  median = findMedian(newarray,goodSize,true);
427  madfm = findMADFM(newarray,goodSize,true);
428
429  delete [] newarray;
430
431}
432template void findAllStats<int>(int *array, int size, bool *mask,
433                                float &mean, float &stddev,
434                                int &median, int &madfm);
435template void findAllStats<long>(long *array, int size, bool *mask,
436                                 float &mean, float &stddev,
437                                 long &median, long &madfm);
438template void findAllStats<float>(float *array, int size, bool *mask,
439                                  float &mean, float &stddev,
440                                  float &median, float &madfm);
441template void findAllStats<double>(double *array, int size, bool *mask,
442                                   float &mean, float &stddev,
443                                   double &median, double &madfm);
444//--------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.