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

Last change on this file since 12726 was 12503, checked in by tbretz, 13 years ago
Make sure that we don't get exceptions from old drs calib files without time marker channels (NTM)
File size: 17.2 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
20public:
21 DrsCalibrate() : fNumEntries(0), fNumSamples(0), fNumChannels(0) { }
22 void Reset()
23 {
24 fNumEntries = 0;
25 fNumSamples = 0;
26 fNumChannels = 0;
27
28 fSum.clear();
29 fSum2.clear();
30 }
31
32 void InitSize(uint16_t channels, uint16_t samples)
33 {
34 fNumChannels = channels;
35 fNumSamples = samples;
36
37 fSum.resize(samples*channels);
38 fSum2.resize(samples*channels);
39 }
40
41 void AddRel(const int16_t *val, const int16_t *start)
42 {
43 for (size_t ch=0; ch<fNumChannels; ch++)
44 {
45 const int16_t spos = start[ch];
46 if (spos<0)
47 continue;
48
49 const size_t pos = ch*1024;
50
51 for (size_t i=0; i<1024; i++)
52 {
53 // Value is relative to trigger
54 // Abs is corresponding index relative to DRS pipeline
55 const size_t rel = pos + i;
56 const size_t abs = pos + (spos+i)%1024;
57
58 const int64_t v = val[rel];
59
60 fSum[abs] += v;
61 fSum2[abs] += v*v;
62 }
63 }
64
65 fNumEntries++;
66 }
67
68 void AddRel(const int16_t *val, const int16_t *start,
69 const int32_t *offset, const uint32_t scale)
70 {
71 for (size_t ch=0; ch<fNumChannels; ch++)
72 {
73 const int16_t spos = start[ch];
74 if (spos<0)
75 continue;
76
77 const size_t pos = ch*fNumSamples;
78
79 for (size_t i=0; i<fNumSamples; i++)
80 {
81 // Value is relative to trigger
82 // Offset is relative to DRS pipeline
83 // Abs is corresponding index relative to DRS pipeline
84 const size_t rel = pos + i;
85 const size_t abs = pos + (spos+i)%fNumSamples;
86
87 const int64_t v = int64_t(val[rel])*scale-offset[abs];
88
89 fSum[abs] += v;
90 fSum2[abs] += v*v;
91 }
92 }
93
94 fNumEntries++;
95 }
96 /*
97 void AddAbs(const int16_t *val, const int16_t *start,
98 const int32_t *offset, const uint32_t scale)
99 {
100 for (size_t ch=0; ch<fNumChannels; ch++)
101 {
102 const int16_t spos = start[ch];
103 if (spos<0)
104 continue;
105
106 const size_t pos = ch*fNumSamples;
107
108 for (size_t i=0; i<fNumSamples; i++)
109 {
110 // Value is relative to trigger
111 // Offset is relative to DRS pipeline
112 // Abs is corresponding index relative to DRS pipeline
113 const size_t rel = pos + i;
114 const size_t abs = pos + (spos+i)%fNumSamples;
115
116 const int64_t v = int64_t(val[rel])*scale-offset[abs];
117
118 fSum[rel] += v;
119 fSum2[rel] += v*v;
120 }
121 }
122
123 fNumEntries++;
124 }*/
125
126 void AddAbs(const int16_t *val, const int16_t *start,
127 const int32_t *offset, const uint32_t scale)
128 {
129 // 1440 without tm, 1600 with tm
130 for (size_t ch=0; ch<fNumChannels; ch++)
131 {
132 const int16_t spos = start[ch];
133 if (spos<0)
134 continue;
135
136 const size_t pos = ch*fNumSamples;
137 const size_t drs = ch>1439 ? ((ch-1440)*9+8)*1024 : ch*1024;
138
139 for (size_t i=0; i<fNumSamples; i++)
140 {
141 // Value is relative to trigger
142 // Offset is relative to DRS pipeline
143 // Abs is corresponding index relative to DRS pipeline
144 const size_t rel = pos + i;
145 const size_t abs = drs + (spos+i)%1024;
146
147 const int64_t v = int64_t(val[rel])*scale-offset[abs];
148
149 fSum[rel] += v;
150 fSum2[rel] += v*v;
151 }
152 }
153
154 fNumEntries++;
155 }
156
157 void AddT(const int16_t *val, const int16_t *start)
158 {
159 // 1440 without tm, 1600 with tm
160 for (size_t ch=0; ch<fNumChannels; ch++)
161 {
162 const int16_t spos = start[ch];
163 if (spos<0)
164 continue;
165
166 const size_t pos = ch*fNumSamples;
167
168 uint32_t nperiods = 0;
169
170 for (size_t i=0; i<fNumSamples; i++)
171 {
172 const size_t abs0 = pos + (spos+i )%1024;
173 const size_t abs1 = pos + (spos+i+1)%1024;
174
175 const float &v0 = val[abs0];
176 const float &v1 = val[abs1];
177
178 // Has sign changed?
179 if (v0*v1>0)
180 {
181 // Sign has not changed
182 fSum[abs0] += nperiods;
183 fSum2[abs0] += nperiods*nperiods;
184 continue;
185 }
186
187 const double p = v0==v1 ? 1 : v0/(v0-v1);
188
189 const double value = nperiods*p + (nperiods+1)*(1-p);
190
191 fSum[abs0] += value;
192 fSum2[abs0] += value*value;
193
194 nperiods++;
195 }
196 }
197
198 fNumEntries++;
199 }
200
201 static void ApplyCh(float *vec, const int16_t *val, int16_t start, uint32_t roi,
202 const int32_t *offset, const uint32_t scaleabs,
203 const int64_t *gain, const uint64_t scalegain)
204 {
205 if (start<0)
206 {
207 memset(vec, 0, roi);
208 return;
209 }
210
211 for (size_t i=0; i<roi; i++)
212 {
213 // Value is relative to trigger
214 // Offset is relative to DRS pipeline
215 // Abs is corresponding index relative to DRS pipeline
216 const size_t abs = (start+i)%1024;
217
218 const int64_t v =
219 + int64_t(val[i])*scaleabs-offset[abs]
220 ;
221
222 const int64_t div = gain[abs];
223 vec[i] = double(v)*scalegain/div;
224 }
225 }
226
227 static void ApplyCh(float *vec, const int16_t *val, int16_t start, uint32_t roi,
228 const int32_t *offset, const uint32_t scaleabs,
229 const int64_t *gain, const uint64_t scalegain,
230 const int64_t *trgoff, const uint64_t scalerel)
231 {
232 if (start<0)
233 {
234 memset(vec, 0, roi);
235 return;
236 }
237
238 for (size_t i=0; i<roi; i++)
239 {
240 // Value is relative to trigger
241 // Offset is relative to DRS pipeline
242 // Abs is corresponding index relative to DRS pipeline
243 const size_t abs = (start+i)%1024;
244
245 const int64_t v =
246 + (int64_t(val[i])*scaleabs-offset[abs])*scalerel
247 - trgoff[i]
248 ;
249
250 const int64_t div = gain[abs]*scalerel;
251 vec[i] = double(v)*scalegain/div;
252 }
253 }
254
255 static void RemoveSpikes(float *vec, uint32_t roi)
256 {
257 if (roi<4)
258 return;
259
260 for (size_t ch=0; ch<1440; ch++)
261 {
262 float *p = vec + ch*roi;
263
264 for (size_t i=1; i<roi-2; i++)
265 {
266 if (p[i]-p[i-1]>25 && p[i]-p[i+1]>25)
267 {
268 p[i] = (p[i-1]+p[i+1])/2;
269 }
270
271 if (p[i]-p[i-1]>22 && fabs(p[i]-p[i+1])<4 && p[i+1]-p[i+2]>22)
272 {
273 p[i] = (p[i-1]+p[i+2])/2;
274 p[i+1] = p[i];
275 }
276 }
277 }
278 }
279
280 std::pair<std::vector<double>,std::vector<double> > GetSampleStats() const
281 {
282 if (fNumEntries==0)
283 return make_pair(std::vector<double>(),std::vector<double>());
284
285 std::vector<double> mean(fSum.size());
286 std::vector<double> error(fSum.size());
287
288 std::vector<int64_t>::const_iterator it = fSum.begin();
289 std::vector<int64_t>::const_iterator i2 = fSum2.begin();
290 std::vector<double>::iterator im = mean.begin();
291 std::vector<double>::iterator ie = error.begin();
292
293 while (it!=fSum.end())
294 {
295 *im = /*cnt<fResult.size() ? fResult[cnt] :*/ double(*it)/fNumEntries;
296 *ie = sqrt(double(*i2*int64_t(fNumEntries) - *it * *it))/fNumEntries;
297
298 im++;
299 ie++;
300 it++;
301 i2++;
302 }
303
304
305 /*
306 valarray<double> ...
307
308 mean /= fNumEntries;
309 error = sqrt(error/fNumEntries - mean*mean);
310 */
311
312 return make_pair(mean, error);
313 }
314
315 void GetSampleStats(float *ptr, float scale) const
316 {
317 const size_t sz = fNumSamples*fNumChannels;
318
319 if (fNumEntries==0)
320 {
321 memset(ptr, 0, sizeof(float)*sz*2);
322 return;
323 }
324
325 std::vector<int64_t>::const_iterator it = fSum.begin();
326 std::vector<int64_t>::const_iterator i2 = fSum2.begin();
327
328 while (it!=fSum.end())
329 {
330 *ptr = scale*double(*it)/fNumEntries;
331 *(ptr+sz) = scale*sqrt(double(*i2*int64_t(fNumEntries) - *it * *it))/fNumEntries;
332
333 ptr++;
334 it++;
335 i2++;
336 }
337 }
338
339 static void GetPixelStats(float *ptr, const float *data, uint16_t roi)
340 {
341 if (roi==0)
342 return;
343
344 for (int i=0; i<1440; i++)
345 {
346 const float *vec = data+i*roi;
347
348 int pos = 0;
349 double sum = vec[0];
350 double sum2 = vec[0]*vec[0];
351 for (int j=1; j<roi; j++)
352 {
353 sum += vec[j];
354 sum2 += vec[j]*vec[j];
355
356 if (vec[j]>vec[pos])
357 pos = j;
358 }
359 sum /= roi;
360 sum2 /= roi;
361
362 *(ptr+0*1440+i) = sum;
363 *(ptr+1*1440+i) = sqrt(sum2 - sum * sum);
364 *(ptr+2*1440+i) = vec[pos];
365 *(ptr+3*1440+i) = pos;
366 }
367 }
368
369 static void GetPixelMax(float *max, const float *data, uint16_t roi, int32_t first, int32_t last)
370 {
371 if (roi==0 || first<0 || last<0 || first>=roi || last>=roi || last<first)
372 return;
373
374 for (int i=0; i<1440; i++)
375 {
376 const float *beg = data+i*roi+first;
377 const float *end = data+i*roi+last;
378
379 const float *pmax = beg;
380
381 for (const float *ptr=beg+1; ptr<=end; ptr++)
382 if (*ptr>*pmax)
383 pmax = ptr;
384
385 max[i] = *pmax;
386 }
387
388 }
389
390 const std::vector<int64_t> &GetSum() const { return fSum; }
391
392 uint64_t GetNumEntries() const { return fNumEntries; }
393};
394
395struct DrsCalibration
396{
397 std::vector<int32_t> fOffset;
398 std::vector<int64_t> fGain;
399 std::vector<int64_t> fTrgOff;
400
401 uint64_t fNumOffset;
402 uint64_t fNumGain;
403 uint64_t fNumTrgOff;
404
405 uint32_t fStep;
406 uint16_t fRoi; // Region of interest for trgoff
407 uint16_t fNumTm; // Number of time marker channels in trgoff
408
409// uint16_t fDAC[8];
410
411 DrsCalibration() :
412 fOffset (1440*1024, 0),
413 fGain (1440*1024, 4096),
414 fTrgOff (1600*1024, 0),
415 fNumOffset(1),
416 fNumGain(2000),
417 fNumTrgOff(1),
418 fStep(0)
419 {
420 }
421
422 void Clear()
423 {
424 // Default gain:
425 // 0.575*[45590]*2.5V / 2^16 = 0.99999 V
426 fOffset.assign(1440*1024, 0);
427 fGain.assign (1440*1024, 4096);
428 fTrgOff.assign(1600*1024, 0);
429
430 fNumOffset = 1;
431 fNumGain = 2000;
432 fNumTrgOff = 1;
433
434 fStep = 0;
435 }
436
437 std::string ReadFitsImp(const std::string &str, std::vector<float> &vec)
438 {
439 std::fits file(str);
440 if (!file)
441 {
442 std::ostringstream msg;
443 msg << "Could not open file " << str << ": " << strerror(errno);
444 return msg.str();
445 }
446
447 if (file.GetStr("TELESCOP")!="FACT")
448 {
449 std::ostringstream msg;
450 msg << "Reading " << str << " failed: Not a valid FACT file (TELESCOP not FACT in header)";
451 return msg.str();
452 }
453
454 if (!file.HasKey("STEP"))
455 {
456 std::ostringstream msg;
457 msg << "Reading " << str << " failed: Is not a DRS calib file (STEP not found in header)";
458 return msg.str();
459 }
460
461 if (file.GetNumRows()!=1)
462 {
463 std::ostringstream msg;
464 msg << "Reading " << str << " failed: Number of rows in table is not 1.";
465 return msg.str();
466 }
467
468 fStep = file.GetUInt("STEP");
469 fNumOffset = file.GetUInt("NBOFFSET");
470 fNumGain = file.GetUInt("NBGAIN");
471 fNumTrgOff = file.GetUInt("NBTRGOFF");
472 fRoi = file.GetUInt("NROI");
473 fNumTm = file.HasKey("NTM") ? file.GetUInt("NTM") : 0;
474/*
475 fDAC[0] = file.GetUInt("DAC_A");
476 fDAC[1] = file.GetUInt("DAC_B");
477 fDAC[4] = file.GetUInt("DAC_C");
478*/
479 vec.resize(1440*1024*4 + (1440+fNumTm)*fRoi*2 + 4);
480
481 float *base = vec.data();
482
483 reinterpret_cast<uint32_t*>(base)[0] = fRoi;
484
485 file.SetPtrAddress("RunNumberBaseline", base+1, 1);
486 file.SetPtrAddress("RunNumberGain", base+2, 1);
487 file.SetPtrAddress("RunNumberTriggerOffset", base+3, 1);
488 file.SetPtrAddress("BaselineMean", base+4+0*1024*1440, 1024*1440);
489 file.SetPtrAddress("BaselineRms", base+4+1*1024*1440, 1024*1440);
490 file.SetPtrAddress("GainMean", base+4+2*1024*1440, 1024*1440);
491 file.SetPtrAddress("GainRms", base+4+3*1024*1440, 1024*1440);
492 file.SetPtrAddress("TriggerOffsetMean", base+4+4*1024*1440, fRoi*1440);
493 file.SetPtrAddress("TriggerOffsetRms", base+4+4*1024*1440+fRoi*1440, fRoi*1440);
494 if (fNumTm>0)
495 {
496 file.SetPtrAddress("TriggerOffsetTMMean", base+4+4*1024*1440+ 2*fRoi*1440, fRoi*fNumTm);
497 file.SetPtrAddress("TriggerOffsetTMRms", base+4+4*1024*1440+ 2*fRoi*1440+ fRoi*fNumTm, fRoi*fNumTm);
498 }
499
500 if (!file.GetNextRow())
501 {
502 std::ostringstream msg;
503 msg << "Reading data from " << str << " failed.";
504 return msg.str();
505 }
506/*
507 fDAC[2] = fDAC[1];
508 fDAC[4] = fDAC[1];
509
510 fDAC[5] = fDAC[4];
511 fDAC[6] = fDAC[4];
512 fDAC[7] = fDAC[4];
513*/
514 fOffset.resize(1024*1440);
515 fGain.resize(1024*1440);
516
517 fTrgOff.resize(fRoi*(1440+fNumTm));
518
519 // Convert back to ADC counts: 256/125 = 4096/2000
520 // Convert back to sum (mean * num_entries)
521 for (int i=0; i<1024*1440; i++)
522 {
523 fOffset[i] = fNumOffset *256*base[i+1024*1440*0+4]/125;
524 fGain[i] = fNumOffset*fNumGain*256*base[i+1024*1440*2+4]/125;
525 }
526
527 for (int i=0; i<fRoi*1440; i++)
528 fTrgOff[i] = fNumOffset*fNumTrgOff*256*base[i+1024*1440*4+4]/125;
529
530 for (int i=0; i<fRoi*fNumTm; i++)
531 fTrgOff[i+1440*fRoi] = fNumOffset*fNumTrgOff*256*base[i+1024*1440*4+2*fRoi*1440+4]/125;
532
533
534 // DAC: 0..2.5V == 0..65535
535 // V-mV: 1000
536 //fNumGain *= 2500*50000;
537 //for (int i=0; i<1024*1440; i++)
538 // fGain[i] *= 65536;
539 if (fStep==0)
540 {
541 for (int i=0; i<1024*1440; i++)
542 fGain[i] = fNumOffset*4096;
543 }
544 else
545 {
546 fNumGain *= 1953125;
547 for (int i=0; i<1024*1440; i++)
548 fGain[i] *= 1024;
549 }
550
551 // Now mark the stored DRS data as "officially valid"
552 // However, this is not thread safe. It only ensures that
553 // this data is not used before it is completely and correctly
554 // read.
555 fStep++;
556
557 return std::string();
558 }
559
560 std::string ReadFitsImp(const std::string &str)
561 {
562 std::vector<float> vec;
563 return ReadFitsImp(str, vec);
564 }
565
566 bool IsValid() { return fStep>2; }
567
568 bool Apply(float *vec, const int16_t *val, const int16_t *start, uint32_t roi)
569 {
570 if (roi!=fRoi)
571 {
572 for (size_t ch=0; ch<1440; ch++)
573 {
574 const size_t pos = ch*roi;
575 const size_t drs = ch*1024;
576
577 DrsCalibrate::ApplyCh(vec+pos, val+pos, start[ch], roi,
578 fOffset.data()+drs, fNumOffset,
579 fGain.data() +drs, fNumGain);
580 }
581
582 return false;
583 }
584
585 for (size_t ch=0; ch<1440; ch++)
586 {
587 const size_t pos = ch*fRoi;
588 const size_t drs = ch*1024;
589
590 DrsCalibrate::ApplyCh(vec+pos, val+pos, start[ch], roi,
591 fOffset.data()+drs, fNumOffset,
592 fGain.data() +drs, fNumGain,
593 fTrgOff.data()+pos, fNumTrgOff);
594 }
595
596 for (size_t ch=0; ch<fNumTm; ch++)
597 {
598 const size_t pos = (ch+1440)*fRoi;
599 const size_t drs = (ch*9+8)*1024;
600
601 DrsCalibrate::ApplyCh(vec+pos, val+pos, start[ch], roi,
602 fOffset.data()+drs, fNumOffset,
603 fGain.data() +drs, fNumGain,
604 fTrgOff.data()+pos, fNumTrgOff);
605 }
606
607 return true;
608 }
609};
610
611#endif
Note: See TracBrowser for help on using the repository browser.