source: trunk/src/Utils/getNormalStats.cc @ 865

Last change on this file since 865 was 865, checked in by MatthewWhiting, 13 years ago

Some debug statements for the stddev calcs (related to #124)

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