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
RevLine 
[301]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// -----------------------------------------------------------------------
[3]29#include <iostream>
[204]30#include <algorithm>
[3]31#include <math.h>
[393]32#include <duchamp/Utils/utils.hh>
[3]33
[848]34template <class T> float findMean(T *array, size_t size)
[70]35{
[528]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
[848]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);
[653]45  return float(mean);
[53]46}
[848]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);
[190]51//--------------------------------------------------------------------
[53]52
[849]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
[848]72template <class T> float findMean(T *array, bool *mask, size_t size)
[53]73{
[528]74  /// @details
[848]75  /// Find the mean of an array of numbers. Type independent.
[528]76  /// \param array The array of numbers.
[848]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.
[528]80  /// \param size The length of the array.
[848]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    }
[646]89  }
[848]90  if(ct>0) mean /= double(ct);
91  return float(mean);
[53]92}
[848]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);
[190]97//--------------------------------------------------------------------
[53]98
[849]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
[848]126template <class T> float findStddev(T *array, size_t size)
[53]127{
[848]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)
[528]131  /// \param array The array of numbers.
132  /// \param size The length of the array.
[848]133  /// \return The rms value of the array, returned as a float
[646]134
[848]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));
[190]139
[848]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]);
[756]145  }
[867]146  std::cerr << sumx << " " << sumxx << " " << size << " " << size*size <<"\n";
147  std::cerr << double(sumx) << " " << double(sumxx) << " " << double(size) << " " << double(size*size)<< "\n";
[866]148  double mean=double(sumx)/double(size);
[848]149  if(size>0)
[866]150    // stddev = sqrt(double(sumxx)/double(size) - double(sumx*sumx)/double(size*size));
151    stddev = sqrt(double(sumxx)/double(size) - mean*mean);
[865]152  std::cerr << stddev << " " << float(stddev) << "\n";
[848]153  return float(stddev);
[756]154}
[848]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);
[756]159//--------------------------------------------------------------------
160
[849]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
[848]186template <class T> float findStddev(T *array, bool *mask, size_t size)
[3]187{
[848]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)
[528]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.
[848]195  /// \param size The length of the array.
196  /// \return The rms value of the array, returned as a float
[528]197
[848]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    }
[190]207  }
[848]208  if(ct>0)
209    stddev = sqrt(double(sumxx)/double(ct) - double(sumx*sumx)/double(ct*ct));
210  return float(stddev);
[3]211}
[848]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);
[190]216//--------------------------------------------------------------------
[3]217
[849]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
[848]250template <class T> void findNormalStats(T *array, size_t size,
[190]251                                        float &mean, float &stddev)
[3]252{
[528]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
[190]263  if(size==0){
264    std::cerr << "Error in findNormalStats: zero sized array!\n";
265    return;
266  }
[3]267  mean = array[0];
[848]268  for(size_t i=1;i<size;i++){
[3]269    mean += array[i];
270  }
271  mean /= float(size);
272
[79]273  stddev = (array[0]-mean) * (array[0]-mean);
[848]274  for(size_t i=1;i<size;i++) stddev += (array[i]-mean)*(array[i]-mean);
[79]275  stddev = sqrt(stddev/float(size-1));
[3]276
277}
[848]278template void findNormalStats<int>(int *array, size_t size,
[222]279                                      float &mean, float &stddev);
[848]280template void findNormalStats<long>(long *array, size_t size,
[222]281                                       float &mean, float &stddev);
[848]282template void findNormalStats<float>(float *array, size_t size,
[222]283                                        float &mean, float &stddev);
[848]284template void findNormalStats<double>(double *array, size_t size,
[222]285                                         float &mean, float &stddev);
[190]286//--------------------------------------------------------------------
[3]287
[848]288template <class T> void findNormalStats(T *array, size_t size, bool *mask,
[190]289                                        float &mean, float &stddev)
[70]290{
[528]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
[190]305  int goodSize=0;
[848]306  for(size_t i=0;i<size;i++) if(mask[i]) goodSize++;
[190]307  if(goodSize==0){
308    std::cerr << "Error in findNormalStats: no good values!\n";
309    return;
310  }
311  int start=0;
[275]312  while(!mask[start]){start++;}
[190]313  mean = array[start];
[848]314  for(size_t i=start+1;i<size;i++){
[275]315    if(mask[i]) mean += array[i];
[190]316  }
317  mean /= float(goodSize);
[70]318
[190]319  stddev = (array[start]-mean) * (array[start]-mean);
[848]320  for(size_t i=1;i<size;i++){
[275]321    if(mask[i]) stddev += (array[i]-mean)*(array[i]-mean);
[190]322  }
323  stddev = sqrt(stddev/float(goodSize-1));
324
325}
[848]326template void findNormalStats<int>(int *array, size_t size, bool *mask,
[222]327                                      float &mean, float &stddev);
[848]328template void findNormalStats<long>(long *array, size_t size, bool *mask,
[222]329                                       float &mean, float &stddev);
[848]330template void findNormalStats<float>(float *array, size_t size, bool *mask,
[222]331                                        float &mean, float &stddev);
[848]332template void findNormalStats<double>(double *array, size_t size, bool *mask,
[222]333                                         float &mean, float &stddev);
[848]334//-------------------------------------------------------------------- 
[275]335
[848]336template <class T> void findNormalStatsDiff(T *first, T *second, size_t size,
337                                            float &mean, float &stddev)
[275]338{
[528]339  /// @details
[848]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.
[528]342  ///
[848]343  /// \param first The first array
344  /// \param second The second array
[528]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
[275]350  if(size==0){
[848]351    std::cerr << "Error in findNormalStats: zero sized array!\n";
[275]352    return;
353  }
[848]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);
[275]359
[848]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));
[275]363
364}
[848]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);
[275]373//--------------------------------------------------------------------
374
[848]375template <class T> void findNormalStatsDiff(T *first, T *second, size_t size, bool *mask,
376                                            float &mean, float &stddev)
[275]377{
[848]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.
[528]383  ///
[848]384  /// \param first The first array
385  /// \param second The second array
[528]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
[275]394  int goodSize=0;
[848]395  for(size_t i=0;i<size;i++) if(mask[i]) goodSize++;
[275]396  if(goodSize==0){
[848]397    std::cerr << "Error in findNormalStats: no good values!\n";
[275]398    return;
399  }
[848]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);
[275]407
[848]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));
[275]413
414}
[848]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);
[275]423//--------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.