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

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