source: trunk/Mars/mcore/DrsCalib.h@ 12423

Last change on this file since 12423 was 12423, checked in by tbretz, 13 years ago
Fixed some missing STL includes.
File size: 14.6 KB
Line 
1#ifndef MARS_DrsCalib
2#define MARS_DrsCalib
3
4#include <math.h> // fabs
5#include <errno.h> // errno
6
7#include "fits.h"
8
9class DrsCalibrate
10{
11protected:
12 uint64_t fNumEntries;
13
14 size_t fNumSamples;
15 size_t fNumChannels;
16
17 std::vector<int64_t> fSum;
18 std::vector<int64_t> fSum2;
19
20 /*
21 vector<map<int16_t, uint8_t> > fMedian;
22 vector<int16_t> fResult;
23 */
24public:
25 DrsCalibrate() : fNumEntries(0), fNumSamples(0), fNumChannels(0) { }
26 void Reset()
27 {
28 fNumEntries = 0;
29 fNumSamples = 0;
30 fNumChannels = 0;
31
32 fSum.clear();
33 fSum2.clear();
34 }
35
36 void InitSize(uint16_t channels, uint16_t samples)
37 {
38 fNumChannels = channels;
39 fNumSamples = samples;
40
41 fSum.resize(samples*channels);
42 fSum2.resize(samples*channels);
43
44 //fMedian.resize(40*9*1024);
45 }
46/*
47 continue;
48
49 if (ch<40*9)
50 {
51 fMedian[abs][val[rel]]++;
52
53 int n= 8;
54 if (fNumEntries>0 && fNumEntries%(n*100)==0)
55 {
56 fResult.resize(40*9*1024);
57
58 uint16_t sum = 0;
59 for (map<int16_t, uint8_t>::const_iterator it=fMedian[abs].begin();
60 it!=fMedian[abs].end(); it++)
61 {
62 map<int16_t, uint8_t>::const_iterator is = it;
63 is++;
64 if (is==fMedian[abs].end())
65 break;
66
67 sum += it->second;
68
69 double med = 0;
70
71 med += int64_t(it->second)*int64_t(it->first);
72 med += int64_t(is->second)*int64_t(is->first);
73 med /= int64_t(it->second)+int64_t(is->second);
74
75 if (sum==n*50)
76 {
77 fResult[abs] = it->first;
78 cout << ch << " MED+(50): " << it->first << endl;
79 }
80 if (sum<n*50 && sum+is->second>n*50)
81 {
82 fResult[abs] = med;
83 cout << ch << " MED-(50): " << med << endl;
84 }
85 }
86 cout << ch << " AVG=" << float(fSum[abs])/fNumEntries << endl;
87 fMedian[abs].clear();
88 }
89 } // -2029 -2012 -2003 -1996 -1990 // -1955
90 */
91
92 void AddRel(const int16_t *val, const int16_t *start)
93 {
94 for (size_t ch=0; ch<fNumChannels; ch++)
95 {
96 const int16_t spos = start[ch];
97 if (spos<0)
98 continue;
99
100 const size_t pos = ch*fNumSamples;
101
102 for (size_t i=0; i<fNumSamples; i++)
103 {
104 // Value is relative to trigger
105 // Abs is corresponding index relative to DRS pipeline
106 const size_t rel = pos + i;
107 const size_t abs = pos + (spos+i)%fNumSamples;
108
109 const int64_t v = val[rel];
110
111 fSum[abs] += v;
112 fSum2[abs] += v*v;
113 }
114 }
115
116 fNumEntries++;
117 }
118
119 void AddRel(const int16_t *val, const int16_t *start,
120 const int32_t *offset, const uint32_t scale)
121 {
122 for (size_t ch=0; ch<fNumChannels; ch++)
123 {
124 const int16_t spos = start[ch];
125 if (spos<0)
126 continue;
127
128 const size_t pos = ch*fNumSamples;
129
130 for (size_t i=0; i<fNumSamples; i++)
131 {
132 // Value is relative to trigger
133 // Offset is relative to DRS pipeline
134 // Abs is corresponding index relative to DRS pipeline
135 const size_t rel = pos + i;
136 const size_t abs = pos + (spos+i)%fNumSamples;
137
138 const int64_t v = int64_t(val[rel])*scale-offset[abs];
139
140 fSum[abs] += v;
141 fSum2[abs] += v*v;
142 }
143 }
144
145 fNumEntries++;
146 }
147
148 void AddAbs(const int16_t *val, const int16_t *start,
149 const int32_t *offset, const uint32_t scale)
150 {
151 for (size_t ch=0; ch<fNumChannels; ch++)
152 {
153 const int16_t spos = start[ch];
154 if (spos<0)
155 continue;
156
157 const size_t pos = ch*fNumSamples;
158
159 for (size_t i=0; i<fNumSamples; i++)
160 {
161 // Value is relative to trigger
162 // Offset is relative to DRS pipeline
163 // Abs is corresponding index relative to DRS pipeline
164 const size_t rel = pos + i;
165 const size_t abs = pos + (spos+i)%fNumSamples;
166
167 const int64_t v = int64_t(val[rel])*scale-offset[abs];
168
169 fSum[rel] += v;
170 fSum2[rel] += v*v;
171 }
172 }
173
174 fNumEntries++;
175 }
176
177 static void ApplyCh(float *vec, const int16_t *val, int16_t start, uint32_t roi,
178 const int32_t *offset, const uint32_t scaleabs,
179 const int64_t *gain, const uint64_t scalegain,
180 const int64_t *trgoff, const uint64_t scalerel)
181 {
182 if (start<0)
183 {
184 memset(vec, 0, roi);
185 return;
186 }
187
188 for (size_t i=0; i<roi; i++)
189 {
190 // Value is relative to trigger
191 // Offset is relative to DRS pipeline
192 // Abs is corresponding index relative to DRS pipeline
193 const size_t rel = i;
194 const size_t abs = (start+i)%1024;
195
196 const int64_t v =
197 + (int64_t(val[rel])*scaleabs-offset[abs])*scalerel
198 - trgoff[rel]
199 ;
200
201 const int64_t div = gain[abs]*scalerel;
202 vec[rel] = double(v)*scalegain/div;
203 }
204 }
205
206 static void Apply(float *vec, const int16_t *val, const int16_t *start, uint32_t roi,
207 const int32_t *offset, const uint32_t scaleabs,
208 const int64_t *gain, const uint64_t scalegain,
209 const int64_t *trgoff, const uint64_t scalerel)
210 {
211 for (size_t ch=0; ch<1440; ch++)
212 {
213 const size_t pos = ch*roi;
214 const size_t drs = ch*1024;
215 ApplyCh(vec+pos, val+pos, start[ch], roi,
216 offset+drs, scaleabs,
217 gain +drs, scalegain,
218 trgoff+drs, scalerel);
219 }
220 }
221
222 static void RemoveSpikes(float *vec, uint32_t roi)
223 {
224 if (roi<4)
225 return;
226
227 for (size_t ch=0; ch<1440; ch++)
228 {
229 float *p = vec + ch*roi;
230
231 for (size_t i=1; i<roi-2; i++)
232 {
233 if (p[i]-p[i-1]>25 && p[i]-p[i+1]>25)
234 {
235 p[i] = (p[i-1]+p[i+1])/2;
236 }
237
238 if (p[i]-p[i-1]>22 && fabs(p[i]-p[i+1])<4 && p[i+1]-p[i+2]>22)
239 {
240 p[i] = (p[i-1]+p[i+2])/2;
241 p[i+1] = p[i];
242 }
243 }
244 }
245 }
246
247 std::pair<std::vector<double>,std::vector<double> > GetSampleStats() const
248 {
249 if (fNumEntries==0)
250 return make_pair(std::vector<double>(),std::vector<double>());
251
252 std::vector<double> mean(fSum.size());
253 std::vector<double> error(fSum.size());
254
255 std::vector<int64_t>::const_iterator it = fSum.begin();
256 std::vector<int64_t>::const_iterator i2 = fSum2.begin();
257 std::vector<double>::iterator im = mean.begin();
258 std::vector<double>::iterator ie = error.begin();
259
260 while (it!=fSum.end())
261 {
262 *im = /*cnt<fResult.size() ? fResult[cnt] :*/ double(*it)/fNumEntries;
263 *ie = sqrt(double(*i2*int64_t(fNumEntries) - *it * *it))/fNumEntries;
264
265 im++;
266 ie++;
267 it++;
268 i2++;
269 }
270
271
272 /*
273 valarray<double> ...
274
275 mean /= fNumEntries;
276 error = sqrt(error/fNumEntries - mean*mean);
277 */
278
279 return make_pair(mean, error);
280 }
281
282 void GetSampleStats(float *ptr, float scale) const
283 {
284 if (fNumEntries==0)
285 {
286 memset(ptr, 0, sizeof(float)*1024*1440*2);
287 return;
288 }
289
290 std::vector<int64_t>::const_iterator it = fSum.begin();
291 std::vector<int64_t>::const_iterator i2 = fSum2.begin();
292
293 while (it!=fSum.end())
294 {
295 *ptr = scale*double(*it)/fNumEntries;
296 *(ptr+1024*1440) = scale*sqrt(double(*i2*int64_t(fNumEntries) - *it * *it))/fNumEntries;
297
298 ptr++;
299 it++;
300 i2++;
301 }
302 }
303
304 static void GetPixelStats(float *ptr, const float *data, uint16_t roi)
305 {
306 if (roi==0)
307 return;
308
309 for (int i=0; i<1440; i++)
310 {
311 const float *vec = data+i*roi;
312
313 int pos = 0;
314 double sum = vec[0];
315 double sum2 = vec[0]*vec[0];
316 for (int j=1; j<roi; j++)
317 {
318 sum += vec[j];
319 sum2 += vec[j]*vec[j];
320
321 if (vec[j]>vec[pos])
322 pos = j;
323 }
324 sum /= roi;
325 sum2 /= roi;
326
327 *(ptr+0*1440+i) = sum;
328 *(ptr+1*1440+i) = sqrt(sum2 - sum * sum);
329 *(ptr+2*1440+i) = vec[pos];
330 *(ptr+3*1440+i) = pos;
331 }
332 }
333
334 static void GetPixelMax(float *max, const float *data, uint16_t roi, int32_t first, int32_t last)
335 {
336 if (roi==0 || first<0 || last<0 || first>=roi || last>=roi || last<first)
337 return;
338
339 for (int i=0; i<1440; i++)
340 {
341 const float *beg = data+i*roi+first;
342 const float *end = data+i*roi+last;
343
344 const float *pmax = beg;
345
346 for (const float *ptr=beg+1; ptr<=end; ptr++)
347 if (*ptr>*pmax)
348 pmax = ptr;
349
350 max[i] = *pmax;
351 }
352
353 }
354
355 const std::vector<int64_t> &GetSum() const { return fSum; }
356
357 uint64_t GetNumEntries() const { return fNumEntries; }
358};
359
360struct DrsCalibration
361{
362 std::vector<int32_t> fOffset;
363 std::vector<int64_t> fGain;
364 std::vector<int64_t> fTrgOff;
365
366 uint64_t fNumOffset;
367 uint64_t fNumGain;
368 uint64_t fNumTrgOff;
369
370 uint32_t fStep;
371
372 DrsCalibration() :
373 fOffset(1440*1024, 0),
374 fGain(1440*1024, 4096),
375 fTrgOff(1440*1024, 0),
376 fNumOffset(1),
377 fNumGain(2000),
378 fNumTrgOff(1),
379 fStep(0)
380 {
381 }
382
383 void Clear()
384 {
385 // Default gain:
386 // 0.575*[45590]*2.5V / 2^16 = 0.99999 V
387 fOffset.assign(1440*1024, 0);
388 fGain.assign (1440*1024, 4096);
389 fTrgOff.assign(1440*1024, 0);
390
391 fNumOffset = 1;
392 fNumGain = 2000;
393 fNumTrgOff = 1;
394
395 fStep = 0;
396 }
397
398 std::string ReadFitsImp(const std::string &str, std::vector<float> &vec)
399 {
400 std::fits file(str);
401 if (!file)
402 {
403 std::ostringstream msg;
404 msg << "Could not open file " << str << ": " << strerror(errno);
405 return msg.str();
406 }
407
408 if (file.GetStr("TELESCOP")!="FACT")
409 {
410 std::ostringstream msg;
411 msg << "Reading " << str << " failed: Not a valid FACT file (TELESCOP not FACT in header)";
412 return msg.str();
413 }
414
415 if (!file.HasKey("STEP"))
416 {
417 std::ostringstream msg;
418 msg << "Reading " << str << " failed: Is not a DRS calib file (STEP not found in header)";
419 return msg.str();
420 }
421
422 if (file.GetNumRows()!=1)
423 {
424 std::ostringstream msg;
425 msg << "Reading " << str << " failed: Number of rows in table is not 1.";
426 return msg.str();
427 }
428
429 vec.resize(1440*1024*6+3);
430
431 float *base = vec.data();
432
433 file.SetPtrAddress("RunNumberBaseline", base, 1);
434 file.SetPtrAddress("RunNumberGain", base+1, 1);
435 file.SetPtrAddress("RunNumberTriggerOffset", base+2, 1);
436 file.SetPtrAddress("BaselineMean", base+0*1024*1440+3, 1024*1440);
437 file.SetPtrAddress("BaselineRms", base+1*1024*1440+3, 1024*1440);
438 file.SetPtrAddress("GainMean", base+2*1024*1440+3, 1024*1440);
439 file.SetPtrAddress("GainRms", base+3*1024*1440+3, 1024*1440);
440 file.SetPtrAddress("TriggerOffsetMean", base+4*1024*1440+3, 1024*1440);
441 file.SetPtrAddress("TriggerOffsetRms", base+5*1024*1440+3, 1024*1440);
442
443 if (!file.GetNextRow())
444 {
445 std::ostringstream msg;
446 msg << "Reading data from " << str << " failed.";
447 return msg.str();
448 }
449
450 fStep = file.GetUInt("STEP");
451 fNumOffset = file.GetUInt("NBOFFSET");
452 fNumGain = file.GetUInt("NBGAIN");
453 fNumTrgOff = file.GetUInt("NBTRGOFF");
454
455 fOffset.resize(1024*1440);
456 fGain.resize(1024*1440);
457 fTrgOff.resize(1024*1440);
458
459 // Convert back to ADC counts: 256/125 = 4096/2000
460 // Convert back to sum (mean * num_entries)
461 for (int i=0; i<1024*1440; i++)
462 {
463 fOffset[i] = fNumOffset *256*base[i+1024*1440*0+3]/125;
464 fGain[i] = fNumOffset*fNumGain *256*base[i+1024*1440*2+3]/125;
465 fTrgOff[i] = fNumOffset*fNumTrgOff*256*base[i+1024*1440*4+3]/125;
466 }
467
468 // DAC: 0..2.5V == 0..65535
469 // V-mV: 1000
470 //fNumGain *= 2500*50000;
471 //for (int i=0; i<1024*1440; i++)
472 // fGain[i] *= 65536;
473 if (fStep==0)
474 {
475 for (int i=0; i<1024*1440; i++)
476 fGain[i] = fNumOffset*4096;
477 }
478 else
479 {
480 fNumGain *= 1953125;
481 for (int i=0; i<1024*1440; i++)
482 fGain[i] *= 1024;
483 }
484
485 // Now mark the stored DRS data as "officially valid"
486 // However, this is not thread safe. It only ensures that
487 // this data is not used before it is completely and correctly
488 // read.
489 fStep++;
490
491 return std::string();
492 }
493
494 std::string ReadFitsImp(const std::string &str)
495 {
496 std::vector<float> vec;
497 return ReadFitsImp(str, vec);
498 }
499
500 bool IsValid() { return fStep>2; }
501
502 void Apply(float *vec, int16_t *val, const int16_t *start, uint32_t roi)
503 {
504 DrsCalibrate::Apply(vec, val, start, roi,
505 fOffset.data(), fNumOffset,
506 fGain.data(), fNumGain,
507 fTrgOff.data(), fNumTrgOff);
508
509 }
510};
511
512#endif
Note: See TracBrowser for help on using the repository browser.