readWDpp
Read binary files from DRS and WDB
Loading...
Searching...
No Matches
readWD.cc
Go to the documentation of this file.
1
11#include "readWD.hh"
12
13using namespace std;
14
15/*
16 ┌─────────────────────────────────────────────────────────────────────────┐
17 │ FUNCTIONS │
18 └─────────────────────────────────────────────────────────────────────────┘
19 */
20
28ostream &operator<<(ostream &o, const TAG &tag) // cout << TAG
29{
30 if (tag.tag[0] == 'B')
31 {
32 o << tag.tag[0] << tag.tag[1] << *(short *)(tag.tag + 2);
33 }
34 else if (tag.tag[0] == 'T' and tag.tag[1] == '#')
35 {
36 o << tag.tag[0] << tag.tag[1] << *(short *)(tag.tag + 2);
37 }
38 else
39 {
40 o << tag.tag;
41 }
42 return o;
43}
44
52ostream &operator<<(ostream &o, const EventHeader &eh) // cout << EventHeader
53{
54 o << eh.tag << endl;
55 o << "Date: " << eh.year << "/" << eh.month << "/" << eh.day << endl;
56 o << "Hour: " << eh.hour << ":" << eh.min << ":" << eh.sec << "." << eh.ms << endl;
57 o << "Range: " << eh.rangeCenter << " Serial number: " << eh.serialNumber;
58 return o;
59}
60
61/*
62 ┌─────────────────────────────────────────────────────────────────────────┐
63 │ CLASSES : DAQEvent │
64 └─────────────────────────────────────────────────────────────────────────┘
65 */
66
77{
78 is_getch_ = false;
79 is_init_ = false;
80 is_iw_ = false;
81 is_ped_ = false;
82 is_peak_ = false;
83 ped_interval_ = {0, 100};
84 iw_ = {0, SAMPLES_PER_WAVEFORM - 1};
85 peak_threshold_ = 1.;
86 routine_ = {false, false, false};
87 ch_old_ = {-1, -1};
88}
89
102DAQEvent &DAQEvent::GetChannel(const int &board, const int &channel)
103{
104 if (board < 0 or channel < 0)
105 {
106 cerr << "!! Error: board and channel ID number(s) must be positive integers" << endl;
107 exit(0);
108 }
109
110 else if (ch_.first == board and ch_.second == channel)
111 {
112 is_getch_ = true;
113 return *this;
114 }
115
116 else if (volts_.find(board) != volts_.end())
117 {
118 if (volts_[board].find(channel) != volts_[board].end())
119 {
120 is_getch_ = true;
121 ch_ = {board, channel};
122 routine_ = {false, false, false};
123 return *this;
124 }
125 cerr << "!! Error: invalid channel, max channel ID number for this board is " << volts_[board].size() - 1 << endl;
126 exit(0);
127 }
128
129 else if (is_init_ == false && config_.is_makeconfig_ == true)
130 {
131 is_getch_ = true;
132 ch_ = {board, channel};
133 return *this;
134 }
135 cerr << "!! Error: invalid board, max board ID number is " << volts_.size() - 1 << endl;
136 exit(0);
137}
138
149void DAQEvent::SetPedInterval(int a, int b)
150{
151 if (is_getch_)
152 {
153 config_.SetPedInterval(pair<int, int>{a, b}, ch_.first, ch_.second);
154 }
155 else
156 {
157 config_.SetPedInterval(pair<int, int>{a, b});
158 }
159 is_getch_ = false;
160 return;
161}
162
171void DAQEvent::SetPeakThr(float thr)
172{
173 if (is_getch_)
174 {
175 config_.SetPeakThr(thr, ch_.first, ch_.second);
176 }
177 else
178 {
179 config_.SetPeakThr(thr);
180 }
181 is_getch_ = false;
182 return;
183}
184
194void DAQEvent::SetIntWindow(int a, int b)
195{
196 if (is_getch_)
197 {
198 config_.SetIntWindow({a, b}, ch_.first, ch_.second);
199 }
200 else
201 {
202 config_.SetIntWindow({a, b});
203 }
204 is_getch_ = false;
205 return;
206}
207
217void DAQEvent::SetIntWindow(float a, float b)
218{
219 if (!is_getch_)
220 {
221 cerr << "!! Error: select a channel using DAQEvent::GetChannel()" << endl;
222 exit(0);
223 }
224
225 if (!is_init_)
226 {
227 cerr << "!! Error: no event read yet" << endl;
228 exit(0);
229 }
230
231 auto &times = times_[ch_.first][ch_.second];
232 if (a < times[0] or a > b or b > times[SAMPLES_PER_WAVEFORM - 1])
233 {
234 cerr << "!! Error: invalid times passed as integration window" << endl;
235 exit(0);
236 }
237
238 config_.intWindow_[ch_.first][ch_.second].first = distance(times.begin(), lower_bound(times.begin(), times.end(), a));
239
240 auto &iw_first = config_.intWindow_[ch_.first][ch_.second].first;
241 config_.intWindow_[ch_.first][ch_.second].second = distance(times.begin(), lower_bound(times.begin() + iw_first, times.end(), b));
242 return;
243}
244
254{
255 if (!is_init_)
256 {
257 cerr << "!! Error: no event read yet" << endl;
258 exit(0);
259 }
260
261 if (!is_getch_)
262 {
263 cerr << "!! Error: select a channel using DAQEvent::GetChannel()" << endl;
264 exit(0);
265 }
266
267 auto &volts = volts_[ch_.first][ch_.second];
268 return any_of(volts.begin() + 2, volts.end() - 2, [](float val)
269 { return (val < -0.499) || (val > +0.499); });
270}
271
281{
282 if (!is_init_)
283 {
284 cerr << "!! Error: no event read yet" << endl;
285 exit(0);
286 }
287
288 (*this).EvalPedestal();
289 (*this).FindPeaks();
290 (*this).EvalIntegrationBounds();
291
292 const auto &volts = volts_[ch_.first][ch_.second];
293 const auto &times = times_[ch_.first][ch_.second];
294
295 is_getch_ = false;
296 iw_ = config_.intWindow_[ch_.first][ch_.second];
297 float charge = 0;
298
299 for (int i = iw_.first; i < iw_.second; ++i)
300 {
301 charge += (volts[i + 1] + volts[i] - 2 * ped_.first) / (2 * (times[i + 1] - times[i]));
302 }
303
304 return abs(charge);
305}
306
313{
314 if (!is_init_)
315 {
316 cerr << "!! Error: no event read yet" << endl;
317 exit(0);
318 }
319
320 (*this).EvalPedestal();
321 (*this).FindPeaks();
322
323 is_getch_ = false;
324
325 return peak_.first - ped_.first;
326}
327
338float DAQEvent::GetTime(float thr)
339{
340 if (!is_init_)
341 {
342 cerr << "!! Error: no event read yet" << endl;
343 exit(0);
344 }
345
346 if (!is_getch_)
347 {
348 cerr << "!! Error: select a channel using DAQEvent::GetChannel()" << endl;
349 exit(0);
350 }
351
352 (*this).EvalPedestal();
353
354 auto &volts = volts_[ch_.first][ch_.second];
355 auto &times = times_[ch_.first][ch_.second];
356 int i = 10;
357
358 if (thr < ped_.first)
359 {
360 while (volts[i] > thr && i < SAMPLES_PER_WAVEFORM - 10)
361 {
362 ++i;
363 }
364 }
365 else
366 {
367 while (volts[i] < thr && i < SAMPLES_PER_WAVEFORM - 10)
368 {
369 ++i;
370 }
371 }
372
373 if (i == SAMPLES_PER_WAVEFORM)
374 {
375 return 0;
376 }
377
378 auto time = times[i] + (thr - volts[i]) * (times[i + 1] - times[i]) / (volts[i + 1] - volts[i]);
379
380 is_getch_ = false;
381
382 return time;
383}
384
391float DAQEvent::GetTimeCF(float CF)
392{
393 if (!is_init_)
394 {
395 cerr << "!! Error: no event read yet" << endl;
396 exit(0);
397 }
398
399 if (CF <= 0 or CF > 1)
400 {
401 cerr << "!! Error: CF value must be in range (0, 1)" << endl;
402 exit(0);
403 }
404
405 (*this).EvalPedestal();
406 (*this).FindPeaks();
407
408 float thr = ped_.first + (peak_.first - ped_.first) * CF;
409
410 return (*this).GetTime(thr);
411}
412
419{
420 if (!is_init_)
421 {
422 cerr << "!! Error: no event read yet" << endl;
423 exit(0);
424 }
425
426 return (*this).GetTimeCF(0.9) - (*this).GetTimeCF(0.1);
427}
428
434const pair<float, float> &DAQEvent::GetPedestal()
435{
436 if (!is_init_)
437 {
438 cerr << "!! Error: no event read yet" << endl;
439 exit(0);
440 }
441
442 if (!is_getch_)
443 {
444 cerr << "!! Error: select a channel with DAQEvent::GetChannel()" << endl;
445 exit(0);
446 }
447
448 (*this).EvalPedestal();
449 is_getch_ = false;
450 return ped_;
451}
452
461const vector<float> &DAQEvent::GetVolts()
462{
463 if (!is_init_)
464 {
465 cerr << "!! Error: no event read yet" << endl;
466 exit(0);
467 }
468
469 if (!is_getch_)
470 {
471 cerr << "!! Error: select a channel with DAQEvent::GetChannel()" << endl;
472 exit(0);
473 }
474
475 is_getch_ = false;
476 return volts_[ch_.first][ch_.second];
477}
478
487const vector<float> &DAQEvent::GetTimes()
488{
489 if (!is_init_)
490 {
491 cerr << "!! Error: no event read yet" << endl;
492 exit(0);
493 }
494
495 if (!is_getch_)
496 {
497 cerr << "!! Error: select a channel with DAQEvent::GetChannel()" << endl;
498 exit(0);
499 }
500
501 is_getch_ = false;
502 return times_[ch_.first][ch_.second];
503}
504
510const vector<int> &DAQEvent::GetPeakIndices()
511{
512 if (!is_init_)
513 {
514 cerr << "!! Error: no event read yet" << endl;
515 exit(0);
516 }
517 (*this).EvalPedestal();
518 (*this).FindPeaks();
519
520 is_getch_ = false;
521
522 return indexMin_;
523}
524
530const pair<int, int> &DAQEvent::GetIntegrationBounds()
531{
532 if (!is_init_)
533 {
534 cerr << "!! Error: no event read yet" << endl;
535 exit(0);
536 }
537
538 if (!config_.user_iw_[ch_.first][ch_.second])
539 {
540 (*this).EvalPedestal();
541 (*this).FindPeaks();
542 (*this).EvalIntegrationBounds();
543 }
544
545 is_getch_ = false;
546
547 return config_.intWindow_[ch_.first][ch_.second];
548}
549
563DAQEvent &DAQEvent::TimeCalibration(const unsigned short &tCell, const std::vector<float> &times, int i, int j)
564{
565 times_[i][j] = times;
566 vector<float> &times_ij = times_[i][j];
567 rotate(times_ij.begin(), times_ij.begin() + tCell, times_ij.end());
568 partial_sum(times_ij.begin(), times_ij.end(), times_ij.begin());
569
570 return *this;
571}
572
579{
580 if (!is_getch_)
581 {
582 cerr << "!! Error: select a channel using DAQEvent::GetChannel()" << endl;
583 exit(0);
584 }
585
586 auto same_ch = (ch_old_.first == ch_.first) && (ch_old_.second == ch_.second);
587 auto same_evt = (evtserial_old_ == eh_.serialNumber);
588
589 if (routine_[0] && same_ch && same_evt)
590 {
591 return *this;
592 }
593 else
594 {
595 routine_[0] = true;
596 ch_old_ = ch_;
598 }
599
600 ped_interval_ = config_.pedInterval_[ch_.first][ch_.second];
601 int ped_interval_dist = ped_interval_.second - ped_interval_.first;
602 const vector<float> &volts = volts_[ch_.first][ch_.second];
603 ped_ = {0., 0.};
604 ped_.first = accumulate(volts.begin() + ped_interval_.first, volts.begin() + ped_interval_.second, 0.) / ped_interval_dist;
605 for (int i = ped_interval_.first; i < ped_interval_.second; ++i)
606 {
607 ped_.second += pow(volts[i] - ped_.first, 2);
608 }
609 ped_.second = sqrt(ped_.second / ped_interval_dist);
610
611 return *this;
612}
613
620{
621 if (!is_getch_)
622 {
623 cerr << "!! Error: select a channel using DAQEvent::GetChannel()" << endl;
624 exit(0);
625 }
626
627 if (config_.user_iw_[ch_.first][ch_.second])
628 {
629 return *this;
630 }
631
632 auto same_ch = (ch_old_.first == ch_.first) && (ch_old_.second == ch_.second);
633 auto same_evt = (evtserial_old_ == eh_.serialNumber);
634
635 if (routine_[2] && same_ch && same_evt)
636 {
637 return *this;
638 }
639 else
640 {
641 routine_[2] = true;
642 ch_old_ = ch_;
644 }
645
646 iw_ = {indexMin_[0], indexMin_[0]};
647
648 const vector<float> &volts = volts_[ch_.first][ch_.second];
649 auto lower_bound = ped_.first - 5 * ped_.second;
650
651 if (peak_.first < lower_bound)
652 {
653 while (volts[iw_.first] < lower_bound and iw_.first > 10)
654 {
655 --iw_.first;
656 }
657
658 while (volts[iw_.second] < lower_bound and iw_.second < SAMPLES_PER_WAVEFORM - 10)
659 {
660 ++iw_.second;
661 }
662 }
663
664 config_.intWindow_[ch_.first][ch_.second] = {iw_.first, iw_.second};
665 return *this;
666}
667
674{
675 if (!is_getch_)
676 {
677 cerr << "!! Error: select a channel using DAQEvent::GetChannel()" << endl;
678 exit(0);
679 }
680
681 auto same_ch = (ch_old_.first == ch_.first) && (ch_old_.second == ch_.second);
682 auto same_evt = (evtserial_old_ == eh_.serialNumber);
683
684 if (routine_[1] && same_ch && same_evt)
685 {
686 return *this;
687 }
688 else
689 {
690 routine_[1] = true;
691 ch_old_ = ch_;
693 }
694
695 long index_min;
696 auto &volts = volts_[ch_.first][ch_.second];
697 auto &times = times_[ch_.first][ch_.second];
698 indexMin_ = {};
699
700 iw_ = config_.intWindow_[ch_.first][ch_.second];
701 peak_threshold_ = config_.peakThr_[ch_.first][ch_.second];
702
703 if (config_.user_iw_[ch_.first][ch_.second]) // Integration window set by the user
704 {
705 index_min = distance(volts.begin(), min_element(volts.begin() + iw_.first, volts.begin() + iw_.second));
706 indexMin_.push_back(index_min);
707 }
708 else // No user integration window set
709 {
710 index_min = distance(volts.begin() + 10, min_element(volts.begin() + 10, volts.end() - 10)) + 10;
711 bool signal, min_left, min_right, at_least;
712 for (int i = 10; i < SAMPLES_PER_WAVEFORM - 10; ++i)
713 {
714 signal = abs(volts[i] - ped_.first) > 5 * ped_.second;
715 min_left = abs(volts[i]) > abs(volts[i - 1]) + ped_.second;
716 min_right = abs(volts[i]) > abs(volts[i + 1]) + ped_.second;
717 if (config_.peakThr_[ch_.first][ch_.second] == 0.5) // Default threshold level
718 {
719 at_least = abs(volts[i] - ped_.first) > abs(volts[index_min] - ped_.first) * 0.5;
720 }
721 else // Custom threshold level
722 {
723 at_least = volts[i] < peak_threshold_;
724 }
725
726 if (signal and min_left and min_right and at_least)
727 {
728 indexMin_.push_back(i);
729 }
730 }
731
732 if (find(indexMin_.begin(), indexMin_.end(), index_min) == indexMin_.end()) // Sorted insertion of min element's index
733 {
734 auto pos = find_if(indexMin_.begin(), indexMin_.end(), [index_min](auto i)
735 { return i > index_min; });
736 indexMin_.insert(pos, index_min);
737 }
738 }
739
740 if (indexMin_.size() == 0) // Assure that at least global minimum is inserted in indexMin_
741 {
742 index_min = distance(volts.begin() + 10, min_element(volts.begin() + 10, volts.end() - 10)) + 10;
743 indexMin_.push_back(index_min);
744 }
745
746 peak_ = {volts[indexMin_[0]], times[indexMin_[0]]}; // First local minimum taken as peak
747
748 return *this;
749}
750
751/*
752 ┌─────────────────────────────────────────────────────────────────────────┐
753 │ CLASSES : DRSEvent │
754 └─────────────────────────────────────────────────────────────────────────┘
755 */
756
757DRSEvent::DRSEvent()
758{
759 evtserial_old_ = 1;
760}
761const string DRSEvent::type_ = "DRS";
762
763/*
764 ┌─────────────────────────────────────────────────────────────────────────┐
765 │ CLASSES : WDBEvent │
766 └─────────────────────────────────────────────────────────────────────────┘
767 */
768
769WDBEvent::WDBEvent()
770{
771 evtserial_old_ = 0;
772}
773const string WDBEvent::type_ = "WDB";
774
775/*
776 ┌─────────────────────────────────────────────────────────────────────────┐
777 │ CLASSES : DAQConfig │
778 └─────────────────────────────────────────────────────────────────────────┘
779 */
780
789{
790 is_makeconfig_ = false;
791}
792
804{
805 if (file.initialization_ == false)
806 {
807 cerr << "!! Error : File was not initialised, use DAQFile::Open()" << endl;
808 exit(0);
809 }
810
811 is_makeconfig_ = true;
812 for (auto &[bKey, bVal] : file.times_)
813 {
814 for (auto &[cKey, cVal] : bVal)
815 {
816 intWindow_[bKey][cKey] = {0, SAMPLES_PER_WAVEFORM - 1};
817 pedInterval_[bKey][cKey] = {0, 100};
818 peakThr_[bKey][cKey] = +0.5;
819 user_iw_[bKey][cKey] = false;
820 }
821 }
822}
823
829{
830 cout << "----- CONFIGURATION SETTINGS -----" << endl;
831 for (auto &[bKey, bVal] : peakThr_)
832 {
833 for (auto &[cKey, cVal] : bVal)
834 {
835 cout << " - Board/Channel ID : " << bKey << "/" << cKey << endl
836 << " - Integration window : (" << intWindow_[bKey][cKey].first << ", " << intWindow_[bKey][cKey].second << ")" << endl
837 << " - Pedestal interval : (" << pedInterval_[bKey][cKey].first << ", " << pedInterval_[bKey][cKey].second << ")" << endl
838 << " - Peak threshold : " << cVal << " V" << endl;
839 }
840 }
841}
842
852void DAQConfig::SetIntWindow(pair<int, int> intWindow, int b, int c)
853{
854 if (is_makeconfig_ == false)
855 {
856 cerr << "!! Error : Configuration class not initialised, use DAQEvent::MakeConfig()" << endl;
857 exit(0);
858 }
859
860 if (intWindow.first < 0 || intWindow.first > intWindow.second || intWindow.second > SAMPLES_PER_WAVEFORM - 1)
861 {
862 cerr << "!! Error : Integration window has invalid value" << endl
863 << " Values must be in interval (0, " << SAMPLES_PER_WAVEFORM << "), passed values are ( " << intWindow.first << ", " << intWindow.second << ")" << endl;
864 exit(0);
865 }
866
867 if (intWindow_.find(b) != intWindow_.end())
868 {
869 if (intWindow_[b].find(c) != intWindow_[b].end())
870 {
871 intWindow_[b][c] = intWindow;
872 user_iw_[b][c] = true;
873 return;
874 }
875 }
876 cerr << "!! Error : Couldn't find board-channel of ID (" << b << ", " << c << ")" << endl;
877 ;
878 exit(0);
879}
880
888void DAQConfig::SetIntWindow(pair<int, int> intWindow)
889{
890 if (is_makeconfig_ == false)
891 {
892 cerr << "!! Error : Configuration class not initialised, use DAQEvent::MakeConfig()" << endl;
893 exit(0);
894 }
895
896 if (intWindow.first < 0 || intWindow.first > intWindow.second || intWindow.second > SAMPLES_PER_WAVEFORM - 1)
897 {
898 cerr << "!! Error : Integration window has invalid value" << endl
899 << " Values must be in interval (0, " << SAMPLES_PER_WAVEFORM << "), passed values are ( " << intWindow.first << ", " << intWindow.second << ")" << endl;
900 exit(0);
901 }
902
903 for (auto &[bKey, bVal] : intWindow_)
904 {
905 for (auto &[cKey, cVal] : bVal)
906 {
907 cVal = intWindow;
908 user_iw_[bKey][cKey] = true;
909 }
910 }
911}
912
922void DAQConfig::SetPedInterval(pair<int, int> pedInterval, int b, int c)
923{
924 if (is_makeconfig_ == false)
925 {
926 cerr << "!! Error : Configuration class not initialised, use DAQEvent::MakeConfig()" << endl;
927 exit(0);
928 }
929
930 if (pedInterval.first < 0 || pedInterval.first > pedInterval.second || pedInterval.second > SAMPLES_PER_WAVEFORM - 1)
931 {
932 cerr << "!! Error : Pedestal interval has invalid value" << endl
933 << " Values must be in interval (0, " << SAMPLES_PER_WAVEFORM << "), passed values are ( " << pedInterval.first << ", " << pedInterval.second << ")" << endl;
934 exit(0);
935 }
936
937 if (pedInterval_.find(b) != pedInterval_.end())
938 {
939 if (pedInterval_[b].find(c) != pedInterval_[b].end())
940 {
941 pedInterval_[b][c] = pedInterval;
942 return;
943 }
944 }
945 cerr << "!! Error : Couldn't find board-channel of ID (" << b << ", " << c << ")" << endl;
946 exit(0);
947}
948
956void DAQConfig::SetPedInterval(pair<int, int> pedInterval)
957{
958 if (is_makeconfig_ == false)
959 {
960 cerr << "!! Error : Configuration class not initialised, use DAQEvent::MakeConfig()" << endl;
961 exit(0);
962 }
963
964 if (pedInterval.first < 0 || pedInterval.first > pedInterval.second || pedInterval.second > SAMPLES_PER_WAVEFORM - 1)
965 {
966 cerr << "!! Error : Pedestal interval has invalid value" << endl
967 << " Values must be in interval (0, " << SAMPLES_PER_WAVEFORM << "), passed values are ( " << pedInterval.first << ", " << pedInterval.second << ")";
968 exit(0);
969 }
970
971 for (auto &[bKey, bVal] : pedInterval_)
972 {
973 for (auto &[cKey, cVal] : bVal)
974 {
975 cVal = pedInterval;
976 }
977 }
978}
979
989void DAQConfig::SetPeakThr(float thr, int b, int c)
990{
991 if (is_makeconfig_ == false)
992 {
993 cerr << "!! Error : Configuration class not initialised, use DAQEvent::MakeConfig()" << endl;
994 exit(0);
995 }
996
997 if (thr < -0.5 || thr > +0.5)
998 {
999 cerr << "!! Error : Peak threshold has invalid value" << endl
1000 << " Values must be in interval (-0.5, +0.5), passed values is " << thr << endl;
1001 exit(0);
1002 }
1003
1004 if (peakThr_.find(b) != peakThr_.end())
1005 {
1006 if (peakThr_[b].find(c) != peakThr_[b].end())
1007 {
1008 peakThr_[b][c] = thr;
1009 return;
1010 }
1011 }
1012 cerr << "!! Error : Couldn't find board-channel of ID (" << b << ", " << c << ")" << endl;
1013 exit(0);
1014}
1015
1024{
1025 if (is_makeconfig_ == false)
1026 {
1027 cerr << "!! Error : Configuration class not initialised, use DAQEvent::MakeConfig()" << endl;
1028 exit(0);
1029 }
1030
1031 if (thr < -0.5 || thr > +0.5)
1032 {
1033 cerr << "!! Error : Peak threshold has invalid value" << endl
1034 << " Values must be in interval (-0.5, +0.5), passed values is " << thr << endl;
1035 exit(0);
1036 }
1037
1038 for (auto &[bKey, bVal] : peakThr_)
1039 {
1040 for (auto &[cKey, cVal] : bVal)
1041 {
1042 cVal = thr;
1043 }
1044 }
1045}
1046
1047/*
1048 ┌─────────────────────────────────────────────────────────────────────────┐
1049 │ CLASSES : DAQFile │
1050 └─────────────────────────────────────────────────────────────────────────┘
1051 */
1052
1058{
1059 std::cout << "Created DAQFile, open a file using DAQFile::Open()" << endl;
1060 is_lab_ = 0;
1061 initialization_ = 0;
1062}
1063
1069DAQFile::DAQFile(const string &fname)
1070{
1071 filename_ = fname;
1072 in_.open(fname, std::ios::in | std::ios::binary);
1073 std::cout << "Created DAQFile, opened file " << fname << std::endl;
1074 initialization_ = 0;
1075 is_lab_ = 0;
1076 (*this).Initialise();
1077}
1078
1085{
1086 DAQFile &file = *this;
1087
1088 if (!in_.is_open())
1089 {
1090 cerr << "!! Error: file not open --> use DAQFile(filename)" << endl;
1091 return file;
1092 }
1093
1094 if (initialization_ == 1)
1095 {
1096 return file;
1097 }
1098
1099 TAG bTag, cTag;
1100 vector<float> times(SAMPLES_PER_WAVEFORM);
1101
1102 cout << "Initializing file " << filename_ << endl;
1103
1104 file >> bTag; // DRSx (TIME for Lab's DRS boards)
1105 if (bTag.tag[0] == 'D' && bTag.tag[1] == 'R' && bTag.tag[2] == 'S')
1106 {
1107 cout << bTag;
1108 if (bTag.tag[3] == '8')
1109 {
1110 cout << " --> WaveDREAM Board" << endl;
1111 type_ = "WDB";
1112 }
1113 else
1114 {
1115 cout << " --> DRS Evaluation Board" << endl;
1116 type_ = "DRS";
1117 }
1118 file >> bTag; // TIME
1119 }
1120 else if (strcmp(bTag.tag, "TIME") == 0)
1121 {
1122 cout << "LAB-DRS" << endl;
1123 is_lab_ = 1;
1124 type_ = "DRS";
1125 }
1126 else
1127 {
1128 cerr << "!! Error: invalid file header --> expected \"DRS\", found " << bTag << endl;
1129 cerr << "Initialisation failed" << endl;
1130 return file;
1131 }
1132 if (strcmp(bTag.tag, "TIME") != 0)
1133 {
1134 cerr << "!! Error: invalid time header --> expected \"TIME\", found " << cTag << endl;
1135 cerr << "Initialisation failed" << endl;
1136 return file;
1137 }
1138
1139 o_ = 'B';
1140 int i = 0, j = 0;
1141 while (file >> bTag)
1142 {
1143 cout << bTag << ":" << endl;
1144 j = 0;
1145 while (file >> cTag)
1146 {
1147 cout << " --> " << cTag << endl;
1148 file.Read(times);
1149 times_[i][j] = times;
1150 ++j;
1151 }
1152 ++i;
1153 file.ResetTag();
1154 }
1155
1156 initialization_ = true;
1157 file.ResetTag();
1158 first_evt_pos_ = in_.tellg();
1159
1160 return file;
1161}
1162
1169{
1170 if (in_.is_open())
1171 {
1172 cout << "Closing file " << filename_ << "..." << endl;
1173 in_.close();
1174 }
1175 else
1176 {
1177 cout << "File is already closed" << endl;
1178 }
1179 return *this;
1180}
1181
1188DAQFile &DAQFile::Open(const string &fname)
1189{
1190 if (!in_.is_open())
1191 {
1192 filename_ = fname;
1193 in_.open(fname, std::ios::in | std::ios::binary);
1194 std::cout << std::endl
1195 << "Created DAQFile, opened file " << fname << std::endl;
1196 (*this).Initialise();
1197 return *this;
1198 }
1199 else
1200 {
1201 std::cerr << "!! Error: File is already opened --> " << filename_ << std::endl;
1202 return *this;
1203 }
1204}
1205
1214{
1215 if (initialization_ == 0)
1216 {
1217 cerr << "Warning: file is not initialised. Nothing to reset..." << endl;
1218 return *this;
1219 }
1220
1221 in_.seekg(first_evt_pos_);
1222 return *this;
1223}
1224
1235{
1236 DAQFile &file = *this;
1237 int next_evt_pos;
1238 int evt_id_pos;
1239 int evt_size;
1240 int file_size;
1241 TAG tag;
1242 EventHeader eh;
1243 file.Initialise();
1244
1245 // Evaluate event size
1246 file.Read(tag); // Reading EHDR
1247 file.Read(tag); // Reading new line to reset tag.tag
1248 while (strcmp(tag.tag, "EHDR") != 0)
1249 {
1250 file.Read(tag);
1251 }
1252 file.ResetTag();
1253 next_evt_pos = in_.tellg();
1254 evt_size = next_evt_pos - first_evt_pos_;
1255 cout << "Event size: " << evt_size << endl;
1256
1257 // Evaluate file size
1258 in_.seekg(0, in_.end);
1259 file_size = in_.tellg();
1260
1261 // Reset position
1262 in_.seekg(first_evt_pos_);
1263
1264 // Check to stay into boundaries of file
1265 if (file_size - (first_evt_pos_ + evt_id * evt_size) < evt_size)
1266 {
1267 cerr << "!! Error : Invalid position reached, out of bounds of file" << endl
1268 << "Reset position to first event header..." << endl;
1269 }
1270 else
1271 {
1272 // Moving to requested event
1273 cout << "Moving to event: " << evt_id << endl;
1274 in_.seekg(first_evt_pos_ + evt_size * evt_id);
1275 evt_id_pos = in_.tellg();
1276 file.Read(eh);
1277 cout << eh << endl;
1278 in_.seekg(evt_id_pos);
1279 }
1280
1281 return file;
1282}
1283
1291bool DAQFile::operator>>(TAG &t) // DAQFile >> TAG
1292{
1293 if (!in_.good())
1294 {
1295 return 0;
1296 }
1297 this->Read(t);
1298 return *this;
1299}
1300
1308bool DAQFile::operator>>(EventHeader &eh) // DAQFile >> EventHeader
1309{
1310 if (!in_.good())
1311 {
1312 return 0;
1313 }
1314 this->Read(eh);
1315 return *this;
1316}
1317
1329bool DAQFile::operator>>(DRSEvent &event) // DAQFile >> DRSEvent
1330{
1331 if (!in_.good())
1332 {
1333 return 0;
1334 }
1335
1336 if (type_ != event.type_)
1337 {
1338 cerr << "!! Error: Invalid type of class used" << endl
1339 << "Type expected: " << type_ << endl
1340 << "Event given: " << event.type_ << endl;
1341 exit(0);
1342 }
1343
1344 if (!event.config_.is_makeconfig_)
1345 {
1346 cout << "Autocall to: DAQEvent::MakeConfig()...";
1347 event.MakeConfig(*this);
1348 cout << " Done!" << endl;
1349 }
1350
1351 DAQFile &file = *this;
1352 TAG bTag, cTag, tag;
1353 vector<float> volts(SAMPLES_PER_WAVEFORM);
1354 int i = 0, j = 0;
1355
1356 // Read only one event
1357 file >> event.eh_;
1358 if (event.eh_.serialNumber % 100 == 0)
1359 {
1360 cout << "Event serial number: " << event.eh_.serialNumber << endl;
1361 }
1362
1363 event.is_init_ = true;
1364 event.routine_ = {false, false, false};
1365
1366 while (file >> bTag)
1367 {
1368 file >> tag; // Trigger cell
1369 auto tCell = *(unsigned short *)(tag.tag + 2);
1370 j = 0;
1371 while (file >> cTag)
1372 {
1373 if (!is_lab_)
1374 {
1375 file >> tag; // Time scaler, LAB-DRS don't have time scaler
1376 }
1377 file.Read(volts, event.eh_.rangeCenter);
1378 event.volts_[i][j] = volts;
1379 event.TimeCalibration(tCell, times_[i][j], i, j);
1380 ++j;
1381 }
1382 ++i;
1383 file.ResetTag();
1384 }
1385 file.ResetTag();
1386 return 1;
1387}
1388
1400bool DAQFile::operator>>(WDBEvent &event) // DAQFile >> WDBEvent
1401{
1402 if (!in_.good())
1403 {
1404 return 0;
1405 }
1406
1407 if (type_ != event.type_)
1408 {
1409 cerr << "!! Error: Invalid type of class used" << endl
1410 << "Type expected: " << type_ << endl
1411 << "Event given: " << event.type_ << endl;
1412 exit(0);
1413 }
1414
1415 if (!event.config_.is_makeconfig_)
1416 {
1417 cout << "Autocall to: DAQEvent::MakeConfig()...";
1418 event.MakeConfig(*this);
1419 cout << " Done!" << endl;
1420 }
1421
1422 DAQFile &file = *this;
1423 TAG bTag, cTag, tag;
1424 vector<float> volts(SAMPLES_PER_WAVEFORM);
1425 int i = 0, j = 0;
1426
1427 // Read only one event
1428 file >> event.eh_;
1429 if (event.eh_.serialNumber % 100 == 0 and event.eh_.serialNumber > 0)
1430 {
1431 cout << "Event serial number: " << event.eh_.serialNumber << endl;
1432 }
1433
1434 event.is_init_ = true;
1435 event.routine_ = {false, false, false};
1436
1437 while (file >> bTag)
1438 {
1439 j = 0;
1440 while (file >> cTag)
1441 {
1442 file >> tag; // Time scaler
1443 file >> tag; // Trigger cell
1444 auto tCell = *(unsigned short *)(tag.tag + 2);
1445 file.Read(volts, event.eh_.rangeCenter);
1446 event.volts_[i][j] = volts;
1447 event.TimeCalibration(tCell, times_[i][j], i, j);
1448 ++j;
1449 }
1450 file.ResetTag();
1451 ++i;
1452 }
1453 file.ResetTag();
1454 return 1;
1455}
1456
1463{
1464 in_.read(t.tag, 4);
1465 n_ = t.tag[0];
1466 return;
1467}
1468
1475{
1476 in_.read((char *)&eh, sizeof(eh));
1477 n_ = eh.tag[0];
1478}
1479
1485void DAQFile::Read(vector<float> &vec)
1486{
1487 for (int i = 0; i < vec.size(); ++i)
1488 {
1489 in_.read((char *)&vec.at(i), sizeof(float));
1490 }
1491 return;
1492}
1493
1502void DAQFile::Read(vector<float> &vec, const unsigned short &range_center)
1503{
1504 unsigned short val;
1505 for (int i = 0; i < vec.size(); ++i)
1506 {
1507 in_.read((char *)&val, sizeof(unsigned short));
1508 vec[i] = val / 65536. + range_center / 1000. - 0.5;
1509 }
1510 return;
1511}
1512
1523DAQFile::operator bool()
1524{
1525 map<char, char> header{{'E', 'B'}, {'B', 'C'}, {'C', 'B'}};
1526 if (!in_.good())
1527 {
1528 cout << "End of file reached" << endl;
1529 return 0;
1530 }
1531 else if (n_ == 'T' or n_ == 'D') // Ignores DRSx and TIME
1532 return 0;
1533 else if (n_ == o_) // C --> C, B --> B
1534 return 1;
1535 else if (n_ == header[o_]) // E --> B, B --> C, C --> B
1536 {
1537 o_ = n_;
1538 return 1;
1539 }
1540 else if (n_ == 'E' and initialization_ == 0) // End of initialization, first EHDR
1541 {
1542 cout << "Initialization done --> EHDR next" << endl;
1543 initialization_ = 1;
1544 return 0;
1545 }
1546 return 0;
1547}
std::map< int, std::map< int, float > > peakThr_
Data member to hold peak threshold values of various channels.
Definition readWD.hh:90
void MakeConfig(DAQFile &)
Initialise the configuration class with the default values for any board and any channel.
Definition readWD.cc:803
bool is_makeconfig_
Flag to check if the method DAQConfig::MakeConfig() has been called at least once.
Definition readWD.hh:100
void ShowConfig()
Simple method to print on stream the current settings of the class.
Definition readWD.cc:828
std::map< int, std::map< int, std::pair< int, int > > > intWindow_
Data member to hold integration windows intervals of various channels.
Definition readWD.hh:88
std::map< int, std::map< int, std::pair< int, int > > > pedInterval_
Data member to hold pedestal intervals of various channels.
Definition readWD.hh:89
std::map< int, std::map< int, bool > > user_iw_
Data member to hold which integration windows were set by the user.
Definition readWD.hh:91
void SetPeakThr(float, int, int)
Method to set the peak threshold given the peak threshold in Volts and the board/channel IDs.
Definition readWD.cc:989
DAQConfig()
Construct a new DAQConfig::DAQConfig object.
Definition readWD.cc:788
Main class to store voltage and time values.
Definition readWD.hh:113
void SetPeakThr(float)
Set the threshold in volt by the user.
Definition readWD.cc:171
bool is_iw_
Flag to check if integration window has been evaluated once.
Definition readWD.hh:174
DAQConfig config_
Class to hold settings about pedestal and integration window intervals.
Definition readWD.hh:163
MAP volts_
Structure to hold voltage values of all boards and channels.
Definition readWD.hh:160
void SetPedInterval(int, int)
Function to set the interval where to perform pedestal evaluation.
Definition readWD.cc:149
std::pair< float, float > ped_
Pair to hold pedestal mean and pedestal std.dev..
Definition readWD.hh:165
const std::vector< float > & GetTimes()
Getter method read-only for the waveform's times selected.
Definition readWD.cc:487
DAQEvent & EvalPedestal()
Method to evaluate the pedestal of the currently selected waveform.
Definition readWD.cc:578
DAQEvent & TimeCalibration(const unsigned short &, const std::vector< float > &, int, int)
Function to perform the time calibration.
Definition readWD.cc:563
const std::pair< float, float > & GetPedestal()
Getter method read-only for the attribute DAQEvent::ped_.
Definition readWD.cc:434
std::pair< int, int > iw_
Pair to hold indices as boundary edges where integration is performed by DAQEvent::GetCharge().
Definition readWD.hh:168
bool is_init_
Flag to check if the file is initialised.
Definition readWD.hh:172
std::pair< int, int > ch_old_
Pair to store last channel on which routines were made.
Definition readWD.hh:180
DAQEvent()
Construct a new DAQEvent() object.
Definition readWD.cc:76
std::pair< int, int > ch_
Pair to hold indices of board and channel selected;.
Definition readWD.hh:169
float GetRiseTime()
Evaluate the risetime of the waveform.
Definition readWD.cc:418
const std::pair< int, int > & GetIntegrationBounds()
Definition readWD.cc:530
unsigned int evtserial_old_
Value to store last event read.
Definition readWD.hh:179
bool is_ped_
Flag to check if pedestal has been evaluated once.
Definition readWD.hh:175
float GetTimeCF(float)
Find the time at which the waveform goes under a given percentage of the waveform peak value.
Definition readWD.cc:391
float GetTime(float)
Find the time at which the waveform goes under a given threshold level.
Definition readWD.cc:338
DAQEvent & EvalIntegrationBounds()
Method to evaluate the integration window of the currently selected waveform.
Definition readWD.cc:619
float peak_threshold_
Value to store the threshold in volts passed by the user.
Definition readWD.hh:177
float GetCharge()
Method to evaluate charge in the integration region.
Definition readWD.cc:280
const std::vector< float > & GetVolts()
Getter method read-only for the waveform's voltages selected.
Definition readWD.cc:461
std::pair< float, float > peak_
Pair to hold value of voltage and time at the peak.
Definition readWD.hh:166
bool IsSaturated()
Check if in the selected channel there is (or not) saturation.
Definition readWD.cc:253
DAQEvent & FindPeaks()
Method to find peaks in the integration window.
Definition readWD.cc:673
std::vector< int > indexMin_
Indices of local minima found.
Definition readWD.hh:170
std::pair< int, int > ped_interval_
Pair to hold indices as boundary edges where pedestal is evaluated.
Definition readWD.hh:167
void SetIntWindow(int, int)
Set the integration window passing two indices that go from 0 to SAMPLES_PER_WAVEFORM.
Definition readWD.cc:194
DAQEvent & GetChannel(const int &, const int &)
Select the channel to analyze.
Definition readWD.cc:102
const std::vector< int > & GetPeakIndices()
Definition readWD.cc:510
bool is_getch_
Flag to check if the method DAQEvent::GetChannel() has been called.
Definition readWD.hh:173
std::vector< bool > routine_
Definition readWD.hh:181
bool is_peak_
Flag to check if peaks have been found once.
Definition readWD.hh:176
MAP times_
Structure to hold integrated times values of all boards and channels.
Definition readWD.hh:159
float GetAmplitude()
Method to evaluate amplitude in the integration region.
Definition readWD.cc:312
Class to manage the file and the outputing of data in a DAQEvent instance.
Definition readWD.hh:214
bool initialization_
Flag to store if DAQFile::Initialise() was already called.
Definition readWD.hh:249
std::string type_
Flag to store the type of the board.
Definition readWD.hh:252
DAQFile & Reset()
Method to reset the file.
Definition readWD.cc:1213
char o_
The initial letter of the previous tag read.
Definition readWD.hh:247
std::string filename_
The name of the file.
Definition readWD.hh:245
char n_
The initial letter of the newest tag read.
Definition readWD.hh:248
bool is_lab_
Flag to check if the board is from LAB or not.
Definition readWD.hh:251
DAQFile()
Construct a new DAQFile::DAQFile object.
Definition readWD.cc:1057
DAQFile & GetEvent(int)
Method to select what event must be read next.
Definition readWD.cc:1234
DAQFile & Open(const std::string &)
Method to open a file given the file path and name.
Definition readWD.cc:1188
DAQFile & Close()
Method to close the file.
Definition readWD.cc:1168
MAP times_
Struct to hold read from the TIMEpart of the file.
Definition readWD.hh:250
void Read(TAG &)
Read a tag.
Definition readWD.cc:1462
bool operator>>(DRSEvent &)
Read into a DRSEvent.
Definition readWD.cc:1329
DAQFile & Initialise()
Initialise the file reading the TIME block.
Definition readWD.cc:1084
int first_evt_pos_
Position of first event header.
Definition readWD.hh:253
std::ifstream in_
The input file to read.
Definition readWD.hh:246
Specialization of DAQEvent to a DRS board.
Definition readWD.hh:192
Specialization of DAQEvent to a WaveDREAM board.
Definition readWD.hh:203
ostream & operator<<(ostream &o, const TAG &tag)
Function to print a TAG istance easily on stream::cout.
Definition readWD.cc:28
Declaration of classes and methods.
#define SAMPLES_PER_WAVEFORM
The number of samples made by the waveforms, both DRS and WDB.
Definition readWD.hh:25
Informations about the event contained in the file.
Definition readWD.hh:56
unsigned int serialNumber
The serial number of the event: starting from 1 for DRS and 0 for WDB.
Definition readWD.hh:58
unsigned short sec
The second.
Definition readWD.hh:64
char tag[4]
The tag of the event header.
Definition readWD.hh:57
unsigned short ms
The millisecond.
Definition readWD.hh:65
unsigned short month
The month.
Definition readWD.hh:60
unsigned short day
The day.
Definition readWD.hh:61
unsigned short min
The minute.
Definition readWD.hh:63
unsigned short rangeCenter
The rangeCenter (in Volts).
Definition readWD.hh:66
unsigned short hour
The hour.
Definition readWD.hh:62
unsigned short year
The year.
Definition readWD.hh:59
5 char long word ended with '\0' for simple printing.
Definition readWD.hh:39
char tag[5]
The array of char.
Definition readWD.hh:46