Subversion Repositories f9daq

Rev

Rev 197 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
195 f9daq 1
/********************************************************************\
2
 
3
  Name:         averager.cpp
4
  Created by:   Stefan Ritt
5
 
6
  Contents:     Robust averager
7
 
8
  $Id: averager.cpp 21210 2013-12-12 11:36:59Z ritt $
9
 
10
\********************************************************************/
11
 
12
#include <stdio.h>
13
#include <stdlib.h>
14
#include <string.h>
15
#include <math.h>
16
#include <assert.h>
17
 
18
#include "averager.h"
19
 
20
/*----------------------------------------------------------------*/
21
 
22
Averager::Averager(int nx, int ny, int nz, int dim)
23
{
24
   fNx = nx;
25
   fNy = ny;
26
   fNz = nz;
27
   fDim = dim;
28
 
29
   int size = sizeof(float)*nx*ny*nz * dim;
30
   fArray = (float *)malloc(size);
31
   assert(fArray);
32
   memset(fArray, 0, size);
33
   size = sizeof(float)*nx*ny*nz;
34
   fN = (unsigned short *)malloc(size);
35
   assert(fN);
36
   memset(fN, 0, size);
37
}
38
 
39
/*----------------------------------------------------------------*/
40
 
41
Averager::~Averager()
42
{
43
   if (fN)
44
      free(fN);
45
   if (fArray)
46
      free(fArray);
47
   fN = NULL;
48
   fArray = NULL;
49
}
50
 
51
/*----------------------------------------------------------------*/
52
 
53
void Averager::Add(int x, int y, int z, float value)
54
{
55
   assert(x < fNx);
56
   assert(y < fNy);
57
   assert(z < fNz);
58
 
59
   int nIndex = (x*fNy + y)*fNz + z;
60
   if (fN[nIndex] == fDim - 1) // check if array full
61
      return;
62
 
63
   int aIndex = ((x*fNy + y)*fNz + z) * fDim + fN[nIndex];
64
   fN[nIndex]++;
65
   fArray[aIndex] = value;
66
}
67
 
68
/*----------------------------------------------------------------*/
69
 
70
void Averager::Reset()
71
{
72
   int size = sizeof(float)*fNx*fNy*fNz * fDim;
73
   memset(fArray, 0, size);
74
   size = sizeof(float)*fNx*fNy*fNz;
75
   memset(fN, 0, size);
76
}
77
 
78
/*----------------------------------------------------------------*/
79
 
80
int compar(const void *a, const void *b);
81
 
82
int compar(const void *a, const void *b)
83
{
84
   if (*((float *)a) == *((float *)b))
85
      return 0;
86
 
87
   return (*((float *)a) < *((float *)b)) ? -1 : 1;
88
}
89
 
90
double Averager::Average(int x, int y, int z)
91
{
92
   assert(x < fNx);
93
   assert(y < fNy);
94
   assert(z < fNz);
95
 
96
   double a = 0;
97
 
98
   int nIndex = (x*fNy + y)*fNz + z;
99
   int aIndex = ((x*fNy + y)*fNz + z) * fDim;
100
 
101
   for (int i=0 ; i<fN[nIndex] ; i++)
102
      a += fArray[aIndex + i];
103
 
104
   if (fN[nIndex] > 0)
105
      a /= fN[nIndex];
106
 
107
   return a;
108
}
109
 
110
/*----------------------------------------------------------------*/
111
 
112
double Averager::Median(int x, int y, int z)
113
{
114
   assert(x < fNx);
115
   assert(y < fNy);
116
   assert(z < fNz);
117
 
118
   double m = 0;
119
 
120
   int nIndex = (x*fNy + y)*fNz + z;
121
   int aIndex = ((x*fNy + y)*fNz + z) * fDim;
122
 
123
   qsort(&fArray[aIndex], fN[nIndex], sizeof(float), compar);
124
   m = fArray[aIndex + fN[nIndex]/2];
125
 
126
   return m;
127
}
128
 
129
/*----------------------------------------------------------------*/
130
 
131
double Averager::RobustAverage(double range, int x, int y, int z)
132
{
133
   assert(x < fNx);
134
   assert(y < fNy);
135
   assert(z < fNz);
136
 
137
   double ra = 0;
138
   int n = 0;
139
   double m = Median(x, y, z);
140
 
141
   int nIndex = (x*fNy + y)*fNz + z;
142
   int aIndex = ((x*fNy + y)*fNz + z) * fDim;
143
 
144
   for (int i=0 ; i<fN[nIndex] ; i++) {
145
      if (fArray[aIndex + i] > m - range && fArray[aIndex + i] < m + range) {
146
         ra += fArray[aIndex + i];
147
         n++;
148
      }
149
   }
150
 
151
   if (n > 0)
152
      ra /= n;
153
 
154
   //if (y == 0 && z == 7 && fN[nIndex] > 10)
155
   //   printf("%d %lf %lf %lf\n", fN[nIndex], a, m, ra);
156
 
157
   return ra;
158
}
159
 
160
/*----------------------------------------------------------------*/
161
 
162
int Averager::SaveNormalizedDistribution(const char *filename, int x, float range)
163
{
164
   assert(x < fNx);
165
   FILE *f = fopen(filename, "wt");
166
 
167
   if (!f)
168
      return 0;
169
 
170
   fprintf(f, "X, Y, Z, Min, Max, Ave, Sigma\n");
171
 
172
   for (int y=0 ; y<fNy ; y++)
173
      for (int z=0 ; z<fNz ; z++) {
174
 
175
         int nIndex = (x*fNy + y)*fNz + z;
176
         int aIndex = ((x*fNy + y)*fNz + z) * fDim;
177
 
178
         if (fN[nIndex] > 1) {
179
            fprintf(f, "%d,%d, %d, ", x, y, z);
180
 
181
            double s = 0;
182
            double s2 = 0;
183
            double min = 0;
184
            double max = 0;
185
            int n = fN[nIndex];
186
            double m = Median(x, y, z);
187
 
188
            for (int i=0 ; i<n ; i++) {
189
               double v = fArray[aIndex + i] - m;
190
               s += v;
191
               s2 += v*v;
192
               if (v < min)
193
                  min = v;
194
               if (v > max)
195
                  max = v;
196
            }
197
            double sigma = sqrt((n * s2 - s * s) / (n * (n-1)));
198
            double average = s / n;
199
 
200
            fprintf(f, "%3.1lf, %3.1lf, %3.1lf, %3.3lf, ", min, max, average, sigma);
201
 
202
            if (min < -range || max > range) {
203
               for (int i=0 ; i<n ; i++)
204
                  fprintf(f, "%3.1lf,", fArray[aIndex + i] - m);
205
            }
206
 
207
            fprintf(f, "\n");
208
         }
209
      }
210
 
211
   fclose(f);
212
   return 1;
213
}
214