source: tags/release-1.6.1/src/Utils/getNormalStats.cc @ 1441

Last change on this file since 1441 was 1393, checked in by MatthewWhiting, 10 years ago

A large changeset that moves all use of bool arrays (ie. bool *) to std::vector<bool>. This will be a bit safer, plus potentially cheaper in memory usage. Interfaces to all stats functions with masks have changed accordingly, as well as the Gaussian smoothing functions and some spectral utility functions.

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