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

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

Further debugging, just to check

File size: 16.7 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 << " " << size*size <<"\n";
147  std::cerr << double(sumx) << " " << double(sumxx) << " " << double(size) << " " << double(size*size)<< "\n";
148  double mean=double(sumx)/double(size);
149  if(size>0)
150    // stddev = sqrt(double(sumxx)/double(size) - double(sumx*sumx)/double(size*size));
151    stddev = sqrt(double(sumxx)/double(size) - mean*mean);
152  std::cerr << stddev << " " << float(stddev) << "\n";
153  return float(stddev);
154}
155template float findStddev<int>(int *array, size_t size);
156template float findStddev<long>(long *array, size_t size);
157template float findStddev<float>(float *array, size_t size);
158template float findStddev<double>(double *array, size_t size);
159//--------------------------------------------------------------------
160
161template <class T> float findStddevDiff(T *first, T *second, size_t size)
162{
163  /// @details Find the rms or standard deviation of an array of
164  /// numbers. Type independent. Calculated by iterating only once,
165  /// using \sum x and \sum x^2 (no call to findMean)
166  /// \param array The array of numbers.
167  /// \param size The length of the array.
168  /// \return The rms value of the array, returned as a float
169
170  T sumx=0,sumxx=0;
171  double stddev=0;
172  for(size_t i=0;i<size;i++){
173    sumx += (first[i]-second[i]);
174    sumxx += ((first[i]-second[i])*(first[i]-second[i]));
175  }
176  if(size>0)
177    stddev = sqrt(double(sumxx)/double(size) - double(sumx*sumx)/double(size*size));
178  return float(stddev);
179}
180template float findStddevDiff<int>(int *first, int *second, size_t size);
181template float findStddevDiff<long>(long *first, long *second, size_t size);
182template float findStddevDiff<float>(float *first, float *second, size_t size);
183template float findStddevDiff<double>(double *first, double *second, size_t size);
184//--------------------------------------------------------------------
185
186template <class T> float findStddev(T *array, bool *mask, size_t size)
187{
188  /// @details Find the rms or standard deviation of an array of
189  /// numbers. Type independent. Calculated by iterating only once,
190  /// using \sum x and \sum x^2 (no call to findMean)
191  /// \param array The array of numbers.
192  /// \param mask An array of the same length that says whether to
193  /// include each member of the array in the calculations. Only use
194  /// values where mask=true.
195  /// \param size The length of the array.
196  /// \return The rms value of the array, returned as a float
197
198  T sumx=0,sumxx=0;
199  double stddev=0;
200  int ct=0;
201  for(size_t i=0;i<size;i++){
202    if(mask[i]){
203      sumx += array[i];
204      sumxx += (array[i]*array[i]);
205      ct++;
206    }
207  }
208  if(ct>0)
209    stddev = sqrt(double(sumxx)/double(ct) - double(sumx*sumx)/double(ct*ct));
210  return float(stddev);
211}
212template float findStddev<int>(int *array, bool *mask, size_t size);
213template float findStddev<long>(long *array, bool *mask, size_t size);
214template float findStddev<float>(float *array, bool *mask, size_t size);
215template float findStddev<double>(double *array, bool *mask, size_t size);
216//--------------------------------------------------------------------
217
218template <class T> float findStddevDiff(T *first, T *second, bool *mask, size_t size)
219{
220  /// @details Find the rms or standard deviation of an array of
221  /// numbers. Type independent. Calculated by iterating only once,
222  /// using \sum x and \sum x^2 (no call to findMean)
223  /// \param array The array of numbers.
224  /// \param mask An array of the same length that says whether to
225  /// include each member of the array in the calculations. Only use
226  /// values where mask=true.
227  /// \param size The length of the array.
228  /// \return The rms value of the array, returned as a float
229
230  T sumx=0,sumxx=0;
231  double stddev=0;
232  int ct=0;
233  for(size_t i=0;i<size;i++){
234    if(mask[i]){
235      sumx += (first[i]-second[i]);
236      sumxx += ((first[i]-second[i])*(first[i]-second[i]));
237      ct++;
238    }
239  }
240  if(ct>0)
241    stddev = sqrt(double(sumxx)/double(ct) - double(sumx*sumx)/double(ct*ct));
242  return float(stddev);
243}
244template float findStddevDiff<int>(int *first, int *second, bool *mask, size_t size);
245template float findStddevDiff<long>(long *first, long *second, bool *mask, size_t size);
246template float findStddevDiff<float>(float *first, float *second, bool *mask, size_t size);
247template float findStddevDiff<double>(double *first, double *second, bool *mask, size_t size);
248//--------------------------------------------------------------------
249
250template <class T> void findNormalStats(T *array, size_t size,
251                                        float &mean, float &stddev)
252{
253  /// @details
254  /// Find the mean and rms or standard deviation of an array of
255  /// numbers. Type independent.
256  ///
257  /// \param array The array of numbers.
258  /// \param size The length of the array.
259  /// \param mean The mean value of the array, returned as a float.
260  /// \param stddev The rms or standard deviation of the array,
261  /// returned as a float.
262
263  if(size==0){
264    std::cerr << "Error in findNormalStats: zero sized array!\n";
265    return;
266  }
267  mean = array[0];
268  for(size_t i=1;i<size;i++){
269    mean += array[i];
270  }
271  mean /= float(size);
272
273  stddev = (array[0]-mean) * (array[0]-mean);
274  for(size_t i=1;i<size;i++) stddev += (array[i]-mean)*(array[i]-mean);
275  stddev = sqrt(stddev/float(size-1));
276
277}
278template void findNormalStats<int>(int *array, size_t size,
279                                      float &mean, float &stddev);
280template void findNormalStats<long>(long *array, size_t size,
281                                       float &mean, float &stddev);
282template void findNormalStats<float>(float *array, size_t size,
283                                        float &mean, float &stddev);
284template void findNormalStats<double>(double *array, size_t size,
285                                         float &mean, float &stddev);
286//--------------------------------------------------------------------
287
288template <class T> void findNormalStats(T *array, size_t size, bool *mask,
289                                        float &mean, float &stddev)
290{
291  /// @details
292  /// Find the mean and rms or standard deviation of a subset of an
293  /// array of numbers. The subset is defined by an array of bool
294  /// variables. Type independent.
295  ///
296  /// \param array The array of numbers.
297  /// \param size The length of the array.
298  /// \param mask An array of the same length that says whether to
299  /// include each member of the array in the calculations. Only look
300  /// at values where mask=true.
301  /// \param mean The mean value of the array, returned as a float.
302  /// \param stddev The rms or standard deviation of the array,
303  /// returned as a float.
304
305  int goodSize=0;
306  for(size_t i=0;i<size;i++) if(mask[i]) goodSize++;
307  if(goodSize==0){
308    std::cerr << "Error in findNormalStats: no good values!\n";
309    return;
310  }
311  int start=0;
312  while(!mask[start]){start++;}
313  mean = array[start];
314  for(size_t i=start+1;i<size;i++){
315    if(mask[i]) mean += array[i];
316  }
317  mean /= float(goodSize);
318
319  stddev = (array[start]-mean) * (array[start]-mean);
320  for(size_t i=1;i<size;i++){
321    if(mask[i]) stddev += (array[i]-mean)*(array[i]-mean);
322  }
323  stddev = sqrt(stddev/float(goodSize-1));
324
325}
326template void findNormalStats<int>(int *array, size_t size, bool *mask,
327                                      float &mean, float &stddev);
328template void findNormalStats<long>(long *array, size_t size, bool *mask,
329                                       float &mean, float &stddev);
330template void findNormalStats<float>(float *array, size_t size, bool *mask,
331                                        float &mean, float &stddev);
332template void findNormalStats<double>(double *array, size_t size, bool *mask,
333                                         float &mean, float &stddev);
334//-------------------------------------------------------------------- 
335
336template <class T> void findNormalStatsDiff(T *first, T *second, size_t size,
337                                            float &mean, float &stddev)
338{
339  /// @details
340  /// Find the mean and rms or standard deviation of  the difference between two arrays of
341  /// numbers. The difference is defined as first - second. Type independent.
342  ///
343  /// \param first The first array
344  /// \param second The second array
345  /// \param size The length of the array.
346  /// \param mean The mean value of the array, returned as a float.
347  /// \param stddev The rms or standard deviation of the array,
348  /// returned as a float.
349
350  if(size==0){
351    std::cerr << "Error in findNormalStats: zero sized array!\n";
352    return;
353  }
354  mean = first[0]-second[0];
355  for(size_t i=1;i<size;i++){
356    mean += (first[i]-second[i]);
357  }
358  mean /= float(size);
359
360  stddev = (first[0]-second[0]-mean) * (first[0]-second[0]-mean);
361  for(size_t i=1;i<size;i++) stddev += (first[i]-second[i]-mean)*(first[i]-second[i]-mean);
362  stddev = sqrt(stddev/float(size-1));
363
364}
365template void findNormalStatsDiff<int>(int *first, int *second, size_t size,
366                                       float &mean, float &stddev);
367template void findNormalStatsDiff<long>(long *first, long *second, size_t size,
368                                        float &mean, float &stddev);
369template void findNormalStatsDiff<float>(float *first, float *second, size_t size,
370                                         float &mean, float &stddev);
371template void findNormalStatsDiff<double>(double *first, double *second, size_t size,
372                                          float &mean, float &stddev);
373//--------------------------------------------------------------------
374
375template <class T> void findNormalStatsDiff(T *first, T *second, size_t size, bool *mask,
376                                            float &mean, float &stddev)
377{
378  /// @details Find the mean and rms or standard deviation of the
379  /// difference between two arrays of numbers, where some elements
380  /// are masked out. The mask is defined by an array of bool
381  /// variables, and the difference is defined as first - second. Type
382  /// independent.
383  ///
384  /// \param first The first array
385  /// \param second The second array
386  /// \param size The length of the array.
387  /// \param mask An array of the same length that says whether to
388  /// include each member of the array in the calculations. Only look
389  /// at values where mask=true.
390  /// \param mean The mean value of the array, returned as a float.
391  /// \param stddev The rms or standard deviation of the array,
392  /// returned as a float.
393
394  int goodSize=0;
395  for(size_t i=0;i<size;i++) if(mask[i]) goodSize++;
396  if(goodSize==0){
397    std::cerr << "Error in findNormalStats: no good values!\n";
398    return;
399  }
400  int start=0;
401  while(!mask[start]){start++;}
402  mean = first[start]-second[start];
403  for(size_t i=start+1;i<size;i++){
404    if(mask[i]) mean += (first[i]-second[i]);
405  }
406  mean /= float(goodSize);
407
408  stddev = (first[start]-second[start]-mean) * (first[start]-second[start]-mean);
409  for(size_t i=1;i<size;i++){
410    if(mask[i]) stddev += (first[i]-second[i]-mean)*(first[i]-second[i]-mean);
411  }
412  stddev = sqrt(stddev/float(goodSize-1));
413
414}
415template void findNormalStatsDiff<int>(int *first, int *second, size_t size, bool *mask,
416                                       float &mean, float &stddev);
417template void findNormalStatsDiff<long>(long *first, long *second, size_t size, bool *mask,
418                                        float &mean, float &stddev);
419template void findNormalStatsDiff<float>(float *first, float *second, size_t size, bool *mask,
420                                         float &mean, float &stddev);
421template void findNormalStatsDiff<double>(double *first, double *second, size_t size, bool *mask,
422                                          float &mean, float &stddev);
423//--------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.