GRSISort "v4.0.0.5"
An extension of the ROOT analysis Framework
Loading...
Searching...
No Matches
TPPG.cxx
Go to the documentation of this file.
1#include "TPPG.h"
2
3#include <iomanip>
4#include "TDirectory.h"
5
6#include "TRunInfo.h"
7
9
11{
12 Clear();
13}
14
16 : TObject(rhs)
17{
18 rhs.Copy(*this);
19}
20
21void TPPGData::Copy(TObject& rhs) const
22{
23 static_cast<TPPGData&>(rhs).fTimeStamp = fTimeStamp;
24 static_cast<TPPGData&>(rhs).fOldPpg = fOldPpg;
25 static_cast<TPPGData&>(rhs).fNewPpg = fNewPpg;
26 static_cast<TPPGData&>(rhs).fNetworkPacketId = fNetworkPacketId;
27 static_cast<TPPGData&>(rhs).fLowTimeStamp = fLowTimeStamp;
28 static_cast<TPPGData&>(rhs).fHighTimeStamp = fHighTimeStamp;
29}
30
32{
33 Long64_t time = GetHighTimeStamp();
34 time = time << 28;
35 time |= GetLowTimeStamp() & 0x0fffffff;
37}
38
39void TPPGData::Clear(Option_t*)
40{
41 /// Clears the TPPGData and leaves it a "junk" state. By junk, I just mean default
42 /// so that we can tell that this PPG is no good.
43 fTimeStamp = 0;
47 fLowTimeStamp = 0;
49}
50
51void TPPGData::Print(Option_t*) const
52{
53 std::cout << "time: " << std::setw(7) << GetTimeStamp() << "\t PPG Status: " << hex(static_cast<std::underlying_type<EPpgPattern>::type>(fNewPpg), 7) << "\t Old: " << hex(static_cast<std::underlying_type<EPpgPattern>::type>(fOldPpg), 7) << std::endl;
54}
55
57 : fPPGStatusMap(new PPGMap_t)
58{
59 Clear();
60}
61
62TPPG::TPPG(const TPPG& rhs)
63 : fPPGStatusMap(new PPGMap_t)
64{
65 rhs.Copy(*this);
66}
67
69{
70 Clear();
71 if(fPPGStatusMap != nullptr) {
72 for(auto& ppgit : *fPPGStatusMap) {
73 delete ppgit.second;
74 }
75 delete fPPGStatusMap;
76 }
77}
78
80{
81 if(fPPGStatusMap != nullptr) {
82 for(auto& ppgit : *fPPGStatusMap) {
83 delete ppgit.second;
84 }
85 delete fPPGStatusMap;
86 }
88 rhs.Copy(*this);
89
90 return *this;
91}
92
93void TPPG::Copy(TObject& obj) const
94{
95 static_cast<TPPG&>(obj).Clear();
96 static_cast<TPPG&>(obj).fCycleLength = fCycleLength;
98
99 // We want to provide a copy of each of the data in the PPG rather than a copy of the pointer
100 if(static_cast<TPPG&>(obj).fPPGStatusMap != nullptr && fPPGStatusMap != nullptr) {
101 for(auto& ppgit : *fPPGStatusMap) {
102 if(ppgit.second != nullptr) {
103 static_cast<TPPG&>(obj).AddData(ppgit.second);
104 }
105 }
106 static_cast<TPPG&>(obj).fCurrIterator = static_cast<TPPG&>(obj).fPPGStatusMap->begin();
107 }
108
109 static_cast<TPPG&>(obj).fOdbPPGCodes = fOdbPPGCodes;
110 static_cast<TPPG&>(obj).fOdbDurations = fOdbDurations;
111}
112
113Bool_t TPPG::MapIsEmpty() const
114{
115 /// Checks to see if the ppg map is empty. We need this because we need to put a default
116 /// PPG in at time T=0 to prevent bad things from happening. This function says the map
117 /// is empty when only the default is there, which it essentially is.
118 return (fPPGStatusMap->size() == 1); // We check for size 1 because we always start with a Junk event at time 0.
119}
120
122{
123 /// Adds a PPG status word at a given time in the current run. Makes a copy of the pointer to
124 /// store in the map.
125 fPPGStatusMap->insert(std::make_pair(pat->GetTimeStamp(), new TPPGData(*pat)));
126 fCycleLength = 0;
127 fCycleSet = false;
128 fNumberOfCycleLengths.clear();
129}
130
131ULong64_t TPPG::GetLastStatusTime(ULong64_t time, EPpgPattern pat) const
132{
133 /// Gets the last time that a status was given. If the EPpgPattern kJunk is passed, the
134 /// current status at the time "time" is looked for.
135 /// "time" is in ns (since we store the PPG timestamp in ns as well)
136 if(MapIsEmpty()) {
137 std::cout << "Empty" << std::endl;
138 return 0;
139 }
140
141 auto curppg_it = --(fPPGStatusMap->upper_bound(time));
142 PPGMap_t::iterator ppg_it;
143 if(pat == EPpgPattern::kJunk) {
144 for(ppg_it = curppg_it; ppg_it != fPPGStatusMap->begin(); --ppg_it) {
145 if(curppg_it->second->GetNewPPG() == ppg_it->second->GetNewPPG() && curppg_it != ppg_it) {
146 return ppg_it->first;
147 }
148 }
149 } else {
150 for(ppg_it = curppg_it; ppg_it != fPPGStatusMap->begin(); --ppg_it) {
151 if(pat == ppg_it->second->GetNewPPG()) {
152 return ppg_it->first;
153 }
154 }
155 }
156 return 0;
157}
158
159ULong64_t TPPG::GetNextStatusTime(ULong64_t time, EPpgPattern pat) const
160{
161 /// Gets the next time that a status was given. If the EPpgPattern kJunk is passed, the
162 /// current status at the time "time" is looked for.
163 /// "time" is in ns (since we store the PPG timestamp in ns as well)
164 if(MapIsEmpty()) {
165 std::cout << "Empty" << std::endl;
166 return 0;
167 }
168
169 auto curppg_it = --(fPPGStatusMap->upper_bound(time));
170 PPGMap_t::iterator ppg_it;
171 if(pat == EPpgPattern::kJunk) {
172 for(ppg_it = curppg_it; ppg_it != fPPGStatusMap->end(); ++ppg_it) {
173 if(curppg_it->second->GetNewPPG() == ppg_it->second->GetNewPPG() && curppg_it != ppg_it) {
174 return ppg_it->first;
175 }
176 }
177 } else {
178 for(ppg_it = curppg_it; ppg_it != fPPGStatusMap->end(); ++ppg_it) {
179 if(pat == ppg_it->second->GetNewPPG()) {
180 return ppg_it->first;
181 }
182 }
183 }
184 return 0;
185}
186
187EPpgPattern TPPG::GetStatus(ULong64_t time) const
188{
189 /// Returns the current status of the PPG at the time "time".
190 /// "time" is in ns (since we store the PPG timestamp in ns as well)
191 if(MapIsEmpty()) {
192 std::cout << "Empty" << std::endl;
193 }
194 // The upper_bound and lower_bound functions always return an iterator to the NEXT map element. We back off by one
195 // because we want to know what the last PPG event was.
196 return ((--(fPPGStatusMap->upper_bound(time)))->second->GetNewPPG());
197}
198
199EPpgPattern TPPG::GetNextStatus(ULong64_t time) const
200{
201 /// Returns the next status of the PPG at the time "time".
202 /// "time" is in ns (since we store the PPG timestamp in ns as well)
203 if(MapIsEmpty()) {
204 std::cout << "Empty" << std::endl;
205 }
206 // The upper_bound and lower_bound functions always return an iterator to the NEXT map element. We back off by one
207 // because we want to know what the last PPG event was.
208 if(fPPGStatusMap->upper_bound(time) == fPPGStatusMap->end()) {
209 return EPpgPattern::kJunk;
210 }
211 return ((fPPGStatusMap->upper_bound(time))->second->GetNewPPG());
212}
213
214void TPPG::Print(Option_t* opt) const
215{
216 if(fOdbPPGCodes.size() != fOdbDurations.size()) {
217 std::cout << "Mismatch between number of ppg codes (" << fOdbPPGCodes.size() << ") and durations ("
218 << fOdbDurations.size() << ")" << std::endl;
219 } else {
220 if(fOdbPPGCodes.empty()) {
221 std::cout << "No ODB cycle read!" << std::endl;
222 } else {
223 std::cout << "ODB cycle: " << OdbCycleLength() / 1000000 << " s" << std::endl
224 << "Code Duration" << std::endl;
225 for(size_t i = 0; i < fOdbPPGCodes.size(); ++i) {
226 std::cout << hex(fOdbPPGCodes[i], 4) << " " << fOdbDurations[i] << std::endl;
227 }
228 }
229 }
230 if(TString(opt).Contains("odb", TString::ECaseCompare::kIgnoreCase)) {
231 return;
232 }
233 if(MapIsEmpty()) {
234 std::cout << "Empty" << std::endl;
235 return;
236 }
237 if(TString(opt).Contains("all", TString::ECaseCompare::kIgnoreCase)) {
238 // print all ppg data
239 PPGMap_t::iterator ppgit;
240 std::cout << "*****************************" << std::endl;
241 std::cout << " PPG STATUS " << std::endl;
242 std::cout << "*****************************" << std::endl;
243 for(ppgit = MapBegin(); ppgit != MapEnd(); ppgit++) {
244 ppgit->second->Print();
245 }
246 return;
247 }
248 // print only an overview of the ppg
249 // can't call non-const GetCycleLength here, so we do the calculation with local variables here
250 std::map<EPpgPattern, int> status; // to calculate how often each different status occured
251 std::map<ULong64_t, int> numberOfCycleLengths; // to calculate the length of the whole cycle
252 std::array<std::map<ULong64_t, int>, 4> numberOfStateLengths; // to calculate the length of each state (tape move, background, beam on, and decay)
253 std::map<int, int> numberOfOffsets; // to calculate the offset on each timestamp
254 for(auto ppgIt = MapBegin(); ppgIt != MapEnd(); ++ppgIt) {
255 status[ppgIt->second->GetNewPPG()]++;
256 ULong64_t diff = ppgIt->second->GetTimeStamp() - GetLastStatusTime(ppgIt->second->GetTimeStamp());
257 numberOfCycleLengths[diff]++;
258 numberOfOffsets[static_cast<int>(ppgIt->second->GetTimeStamp() % 1000)]++; // let's assume our offset is less than 10 us
259 switch(ppgIt->second->GetNewPPG()) {
261 diff = ppgIt->second->GetTimeStamp() - GetLastStatusTime(ppgIt->second->GetTimeStamp(), EPpgPattern::kTapeMove);
262 numberOfStateLengths[0][diff]++;
263 break;
265 diff = ppgIt->second->GetTimeStamp() - GetLastStatusTime(ppgIt->second->GetTimeStamp(), EPpgPattern::kBackground);
266 numberOfStateLengths[1][diff]++;
267 break;
269 diff = ppgIt->second->GetTimeStamp() - GetLastStatusTime(ppgIt->second->GetTimeStamp(), EPpgPattern::kBeamOn);
270 numberOfStateLengths[2][diff]++;
271 break;
273 diff = ppgIt->second->GetTimeStamp() - GetLastStatusTime(ppgIt->second->GetTimeStamp(), EPpgPattern::kDecay);
274 numberOfStateLengths[3][diff]++;
275 break;
276 default: break;
277 }
278 }
279 int counter = 0;
280 ULong64_t cycleLength = 0;
281 for(auto& numberOfCycleLength : numberOfCycleLengths) {
282 if(numberOfCycleLength.second > counter) {
283 counter = numberOfCycleLength.second;
284 cycleLength = numberOfCycleLength.first;
285 }
286 }
287 std::array<ULong64_t, 4> stateLength = {0, 0, 0, 0};
288 for(int i = 0; i < 4; ++i) {
289 counter = 0;
290 for(auto it = numberOfStateLengths[i].begin(); it != numberOfStateLengths[i].end(); ++it) {
291 if(it->second > counter) {
292 counter = it->second;
293 stateLength[i] = it->first;
294 }
295 }
296 }
297 counter = 0;
298 int offset = 0;
299 for(auto& numberOfOffset : numberOfOffsets) {
300 if(numberOfOffset.second > counter) {
301 counter = numberOfOffset.second;
302 offset = numberOfOffset.first;
303 }
304 }
305
306 // the print statement itself
307 std::cout << "Cycle length is " << cycleLength << " in ns = " << cycleLength / 1000000000 << " seconds." << std::endl;
308 std::cout << "Cycle: " << stateLength[0] / 1000000000 << " s tape move, " << stateLength[1] / 1000000000 << " s background, " << stateLength[2] / 1000000000 << " s beam on, and " << stateLength[3] / 1000000000 << " s decay" << std::endl;
309 std::cout << "Offset is " << offset << " [ns]" << std::endl;
310 std::cout << "Got " << fPPGStatusMap->size() - 1 << " PPG words:" << std::endl;
311 for(auto& statu : status) {
312 std::cout << "\tfound status " << hex(static_cast<std::underlying_type<EPpgPattern>::type>(statu.first), 4) << " " << statu.second << " times" << std::endl;
313 }
314
315 if(TString(opt).Contains("missing", TString::ECaseCompare::kIgnoreCase)) {
316 // go through all expected ppg words
317 ULong64_t time = offset;
318 auto iter = MapEnd();
319 --iter;
320 ULong64_t lastTimeStamp = iter->second->GetTimeStamp();
321 for(int cycle = 1; time < lastTimeStamp; ++cycle) {
322 if(GetLastStatusTime(time, EPpgPattern::kTapeMove) != time) {
323 std::cout << "Missing tape move status at " << std::setw(12) << time << " in " << cycle << ". cycle, last tape move status came at " << GetLastStatusTime(time, EPpgPattern::kTapeMove) << "." << std::endl;
324 }
325 if(GetLastStatusTime(time + cycleLength, EPpgPattern::kBackground) != time + stateLength[0]) {
326 std::cout << "Missing background status at " << std::setw(12) << time + stateLength[0] << " in " << cycle << ". cycle, last background status came at " << GetLastStatusTime(time + cycleLength, EPpgPattern::kBackground) << "." << std::endl;
327 }
328 if(GetLastStatusTime(time + cycleLength, EPpgPattern::kBeamOn) != time + stateLength[0] + stateLength[1]) {
329 std::cout << "Missing beam on status at " << std::setw(12) << time + stateLength[0] + stateLength[1] << " in " << cycle << ". cycle, last beam on status came at " << GetLastStatusTime(time + cycleLength, EPpgPattern::kBeamOn) << "." << std::endl;
330 }
331 if(GetLastStatusTime(time + cycleLength, EPpgPattern::kDecay) != time + stateLength[0] + stateLength[1] + stateLength[2]) {
332 std::cout << "Missing decay status at " << std::setw(12) << time + stateLength[0] + stateLength[1] + stateLength[2] << " in " << cycle << ". cycle, last decay status came at " << GetLastStatusTime(time + cycleLength, EPpgPattern::kDecay) << "." << std::endl;
333 }
334 time += cycleLength;
335 }
336 }
337}
338
339bool TPPG::OdbMatchesData(bool verbose)
340{
341 if(!CalculateCycleFromData(verbose)) { return false; }
342
343 // we got a cycle from the data, so we can compare it
344 if(fPPGCodes.size() != fOdbPPGCodes.size()) {
345 if(verbose) {
346 std::cout << "Got: " << fPPGCodes.size() << " states from data, and " << fOdbPPGCodes.size() << " states from ODB" << std::endl;
347 }
348 return false;
349 }
350 for(size_t i = 0; i < fPPGCodes.size(); ++i) {
351 // we only check the lowest nibble of the code, as the ODB code quite often is of the form 0xc00x (x = 1, 2, 4, or 8)
352 // and we need to convert the data durations (in ns) to the ODB duration (in microseconds)
353 if((fPPGCodes.at(i) & 0xf) != (fOdbPPGCodes.at(i) & 0xf) || static_cast<int>(fDurations.at(i) / 1000) != fOdbDurations.at(i)) {
354 if(verbose) {
355 std::cout << i << ": Mismatch between lowest nibble of codes (" << hex(fPPGCodes.at(i), 4) << ", " << hex(fOdbPPGCodes.at(i), 4) << ") or durations (" << fDurations.at(i) << ", " << fOdbDurations.at(i) << ")" << std::endl;
356 }
357 return false;
358 }
359 }
360 // if we got here without finding anything wrong the odb matches the data
361 return true;
362}
363
364void TPPG::SetOdbFromData(bool verbose)
365{
366 if(!CalculateCycleFromData(verbose)) {
367 std::cerr << RED << "Can't set ODB from data as we failed to calculate the cycle from data!" << RESET_COLOR << std::endl;
368 return;
369 }
370 // we got a cycle, so we can set the ODB to it
372 // need to convert the durations from ns to microseconds
373 fOdbDurations.resize(fDurations.size());
374 for(size_t i = 0; i < fDurations.size(); ++i) {
375 fOdbDurations[i] = fDurations[i] / 1000;
376 }
377}
378
380{
381 /// Calculate the cycle from the data and store it.
382 if(fCycleSet) { return true; }
383
384 // loop over all data and count how often we get each time difference between one state and the previous state
385 std::array<std::map<ULong64_t, int>, 4> numberOfStateLengths; // to calculate the length of each state (tape move, background, beam on, and decay)
386 ULong64_t diff = 0;
387 for(auto ppgIt = MapBegin(); ppgIt != MapEnd(); ++ppgIt) {
388 switch(ppgIt->second->GetNewPPG()) {
390 diff = ppgIt->second->GetTimeStamp() - GetLastStatusTime(ppgIt->second->GetTimeStamp(), EPpgPattern::kTapeMove);
391 numberOfStateLengths[0][diff]++;
392 break;
394 diff = ppgIt->second->GetTimeStamp() - GetLastStatusTime(ppgIt->second->GetTimeStamp(), EPpgPattern::kBackground);
395 numberOfStateLengths[1][diff]++;
396 break;
398 diff = ppgIt->second->GetTimeStamp() - GetLastStatusTime(ppgIt->second->GetTimeStamp(), EPpgPattern::kBeamOn);
399 numberOfStateLengths[2][diff]++;
400 break;
402 diff = ppgIt->second->GetTimeStamp() - GetLastStatusTime(ppgIt->second->GetTimeStamp(), EPpgPattern::kDecay);
403 numberOfStateLengths[3][diff]++;
404 break;
405 default: break;
406 }
407 }
408 // set the durations to the one that occured the most often
409 // (codes are already set)
410 for(int i = 0; i < 4; ++i) {
411 int counter = 0;
412 if(verbose) { std::cout << "state " << hex(fPPGCodes[i], 4) << " checking " << numberOfStateLengths[i].size() << " lengths:"; }
413 for(auto it : numberOfStateLengths[i]) {
414 if(it.second > counter) {
415 if(verbose) { std::cout << " " << it.second << ">" << counter << " => fDurations[" << i << "] = " << it.first; }
416 counter = it.second;
417 fDurations[i] = it.first;
418 } else if(verbose) {
419 std::cout << " " << it.second << "<" << counter << " => fDurations[" << i << "] != " << it.first;
420 }
421 }
422 if(verbose) { std::cout << std::endl; }
423 }
424
425 fCycleSet = true;
426
427 return true;
428}
429
430void TPPG::Clear(Option_t*)
431{
432 if(fPPGStatusMap != nullptr) {
433 PPGMap_t::iterator ppgit;
434 for(ppgit = fPPGStatusMap->begin(); ppgit != fPPGStatusMap->end(); ppgit++) {
435 delete ppgit->second;
436 }
437 fPPGStatusMap->clear();
438 }
439 // We always add a junk event to keep the code from crashing if we ask for a PPG below the lowest PPG time.
440 AddData(new TPPGData);
441 fCurrIterator = fPPGStatusMap->begin();
442 fCycleLength = 0;
443 fNumberOfCycleLengths.clear();
444 fOdbPPGCodes.clear();
445 fOdbDurations.clear();
446 fCycleSet = false;
447}
448
449Int_t TPPG::Write(const char* name, Int_t, Int_t) const
450{
451 if(name == nullptr) { name = "TPPG"; }
452 if(PPGSize() > 0 || OdbPPGSize() > 0) {
453 std::cout << "Writing PPG with " << PPGSize() << " events and " << OdbPPGSize() << " ODB settings" << std::endl;
454 return TObject::Write(name, TObject::kSingleKey);
455 }
456
457 return 0;
458}
459
461{
462 if(TRunInfo::SubRunNumber() > 0) {
463 auto* prevSubRun =
464 new TFile(Form("fragment%05d_%03d.root", TRunInfo::RunNumber(), TRunInfo::SubRunNumber() - 1));
465 if(prevSubRun != nullptr && prevSubRun->IsOpen()) {
466 TPPG* prev_ppg = static_cast<TPPG*>(prevSubRun->Get("TPPG"));
467 if(prev_ppg != nullptr) {
468 prev_ppg->Copy(*this);
469 std::cout << "Found previous PPG data from run " << prevSubRun->GetName() << std::endl;
470 } else {
471 std::cout << "Error, could not find PPG in file fragment" << std::setfill('0') << std::setw(5) << TRunInfo::RunNumber() << "_" << std::setw(3) << TRunInfo::SubRunNumber() - 1 << std::setfill(' ') << ".root, not adding previous PPG data" << std::endl;
472 std::cout << "PPG set up." << std::endl;
473 }
474 prevSubRun->Close();
475 } else {
476 std::cout << "Error, could not find file fragment" << std::setfill('0') << std::setw(5) << TRunInfo::RunNumber() << "_" << std::setw(3) << TRunInfo::SubRunNumber() - 1 << std::setfill(' ') << ".root, not adding previous PPG data" << std::endl;
477 std::cout << "PPG set up." << std::endl;
478 }
479 }
480}
481
482bool TPPG::Correct(bool verbose)
483{
484 /// Correct the map of PPG events by checking that we always have a PPG event with the same status that occured
485 /// fCycleLength ago.
486
487 // we use the cycle time to correct our ppg, so make sure it's set (GetCycleLength calculates and sets fCycleLength
488 // only if it's not already set)
490
491 if(verbose) {
492 // we can now use fNumberOfCycleLengths to see how many cycle lengths we have that are wrong
493 for(auto& fNumberOfCycleLength : fNumberOfCycleLengths) {
494 if(fNumberOfCycleLength.first < fCycleLength) {
495 continue;
496 }
497 if(fNumberOfCycleLength.first != fCycleLength) {
498 std::cout << "Found " << fNumberOfCycleLength.second << " wrong cycle length(s) of " << fNumberOfCycleLength.first << " (correct is " << fCycleLength << ")." << std::endl;
499 }
500 }
501 }
502
503 // loop over all ppg data, check that the last ppg data of the same type was fCycleLength ago
504 // if it's not, enter ppg data at that time (multiple times?)
505 for(auto it = MapBegin(); it != MapEnd(); it++) {
506 // skip the first cycle
507 if((*it).first < fCycleLength) {
508 continue;
509 }
510 // get time difference to previous ppg with same status
511 ULong64_t diff = (*it).second->GetTimeStamp() - GetLastStatusTime((*it).second->GetTimeStamp());
512 if(diff != fCycleLength) {
513 if(verbose) {
514 std::cout << std::distance(MapBegin(), it) << ": found missing ppg at time " << (*it).first << " (" << diff << " != " << fCycleLength << ")" << std::endl;
515 }
516 // check that the previous ppg with the same status is a multiple of fCycleLength ago and that no other ppg is
517 // in the map that was fCycleLength ago
518 if(diff % fCycleLength != 0) {
519 if(verbose) {
520 std::cout << DRED << "PPG is messed up, cycle length is " << fCycleLength << ", but the previous event with the same status was " << diff << " ago!" << RESET_COLOR << std::endl;
521 }
522 continue;
523 return false;
524 }
525 auto prev = fPPGStatusMap->find((*it).first - fCycleLength);
526 if(prev != fPPGStatusMap->end()) {
527 // check if the status of the current ppg and the old status of the ppg following the one fCycleLength ago
528 // are the same
529 // if they are, we change the status of the one fCycleLength ago to match the current status
530 if(it->second->GetNewPPG() == (++prev)->second->GetOldPPG()) {
531 (--prev)->second->SetNewPPG(it->second->GetNewPPG());
532 } else if(verbose) {
533 std::cout << DBLUE << "PPG at " << (*it).first - fCycleLength << " already exist with status " << hex(static_cast<std::underlying_type<EPpgPattern>::type>(prev->second->GetNewPPG())) << " (current status is " << hex(static_cast<std::underlying_type<EPpgPattern>::type>(it->second->GetNewPPG())) << ")." << RESET_COLOR << std::endl;
534 }
535 continue;
536 }
537 // copy the current ppg data and correct it's time before inserting it into the map
538 auto* new_data = new TPPGData(*((*it).second));
539 ULong64_t new_ts = (*it).first - fCycleLength;
540 new_data->SetHighTimeStamp(new_ts >> 28);
541 new_data->SetLowTimeStamp(new_ts & 0x0fffffff);
542 if(verbose) {
543 std::cout << "inserting new ppg data at " << new_data->GetTimeStamp() << std::endl;
544 }
545 it = fPPGStatusMap->insert(std::make_pair(new_data->GetTimeStamp(), new_data)).first;
546 --it;
547 }
548 }
549
550 // now we reset fCycleLength and calculate it again
551 fCycleLength = 0;
552 fNumberOfCycleLengths.clear();
554
555 if(verbose) {
556 // we can now use fNumberOfCycleLengths to see how many cycle lengths we have that are wrong
557 for(auto& fNumberOfCycleLength : fNumberOfCycleLengths) {
558 if(fNumberOfCycleLength.first < fCycleLength) {
559 continue;
560 }
561 if(fNumberOfCycleLength.first != fCycleLength) {
562 std::cout << "Found " << fNumberOfCycleLength.second << " wrong cycle length(s) of " << fNumberOfCycleLength.first << " (correct is " << fCycleLength << ")." << std::endl;
563 }
564 }
565 }
566
567 return true;
568}
569
571{
572 if(++fCurrIterator != MapEnd()) {
573 return fCurrIterator->second;
574 }
575 std::cout << "Already at last PPG" << std::endl;
576 return nullptr;
577}
578
580{
581 if(fCurrIterator != MapBegin()) {
582 return (--fCurrIterator)->second;
583 }
584 std::cout << "Already at first PPG" << std::endl;
585 return nullptr;
586}
587
589{
592 return fCurrIterator->second;
593}
594
596{
598 return fCurrIterator->second;
599}
600
601void TPPG::Streamer(TBuffer& R__b)
602{
603 /// Stream an object of class TPPG.
604
605 if(R__b.IsReading()) {
606 R__b.ReadClassBuffer(TPPG::Class(), this);
607 fCurrIterator = fPPGStatusMap->begin();
608 } else {
609 R__b.WriteClassBuffer(TPPG::Class(), this);
610 }
611}
612
613ULong64_t TPPG::GetTimeInCycle(ULong64_t real_time)
614{
615 /// Returns the time in the cycle based on "real_time", i.e. the modulus of the
616 /// time and the cycle length.
617 /// "real_time" is in ns since that's how we store the PPG timestamps as well.
618 return real_time % GetCycleLength();
619}
620
621ULong64_t TPPG::GetCycleNumber(ULong64_t real_time)
622{
623 /// Returns the cycle number based on "real_time", i.e. the time divided by the
624 /// cycle length.
625 /// "real_time" is in ns since that's how we store the PPG timestamps as well.
626 return real_time / GetCycleLength();
627}
628
630{
631 /// Calculates cycle length from the most often occuring time difference between
632 /// two PPG events with the same code. The result is also stored in fCycleLength
633 /// (which prevents a second calculation of it the next time this function is called)
634 if(fCycleLength == 0) {
635 PPGMap_t::iterator ppgit;
636 for(ppgit = MapBegin(); ppgit != MapEnd(); ++ppgit) {
637 ULong64_t diff = ppgit->second->GetTimeStamp() - GetLastStatusTime(ppgit->second->GetTimeStamp());
638 fNumberOfCycleLengths[diff]++;
639 }
640 int counter = 0;
641 for(auto& fNumberOfCycleLength : fNumberOfCycleLengths) {
642 if(fNumberOfCycleLength.second > counter) {
643 counter = fNumberOfCycleLength.second;
644 fCycleLength = fNumberOfCycleLength.first;
645 }
646 }
647 }
648
649 return fCycleLength;
650}
651
653{
654 return Last()->GetTimeStamp() / GetCycleLength();
655}
656
657Long64_t TPPG::Merge(TCollection* list)
658{
659 TIter iter(list);
660 TPPG* ppg = nullptr;
661
662 while((ppg = static_cast<TPPG*>(iter.Next())) != nullptr) {
663 *this += *ppg;
664 }
665
666 return 0;
667}
668
670{
671 /// return the time in the cycle when pat starts
672 return GetTimeInCycle(GetLastStatusTime(Last()->GetTimeStamp(), pat));
673}
674
675void TPPG::operator+=(const TPPG& rhs)
676{
677 Add(&rhs);
678}
679
680void TPPG::Add(const TPPG* ppg)
681{
682 if(ppg == nullptr) {
683 std::cerr << "Passed nullptr to TPPG::Add(const TPPG* ppg)!" << std::endl;
684 return;
685 }
686 PPGMap_t::iterator ppgit;
687 for(ppgit = ppg->MapBegin(); ppgit != ppg->MapEnd(); ++ppgit) {
688 if(ppgit->second != nullptr) {
689 AddData(ppgit->second);
690 }
691 }
692 // We want to rebuild our cycle length map and this is the easiest way to do it
693 fNumberOfCycleLengths.clear();
694 fCycleLength = 0;
696 if(fOdbPPGCodes.empty()) {
699 }
700}
#define DRED
Definition Globals.h:18
#define DBLUE
Definition Globals.h:15
#define RED
Definition Globals.h:9
std::string hex(T val, int width=-1)
Definition Globals.h:129
#define RESET_COLOR
Definition Globals.h:5
TPPGData()
Definition TPPG.cxx:10
ULong64_t GetTimeStamp() const
Definition TPPG.h:116
ULong64_t fTimeStamp
time stamp in ns
Definition TPPG.h:120
void Copy(TObject &rhs) const override
Definition TPPG.cxx:21
void Clear(Option_t *opt="") override
Definition TPPG.cxx:39
UInt_t GetLowTimeStamp() const
Definition TPPG.h:110
void SetTimeStamp()
Definition TPPG.cxx:31
UInt_t fNetworkPacketId
Definition TPPG.h:123
void Print(Option_t *opt="") const override
Definition TPPG.cxx:51
UInt_t fHighTimeStamp
high bits of time stamp in 10 ns
Definition TPPG.h:125
EPpgPattern fOldPpg
Definition TPPG.h:121
EPpgPattern fNewPpg
Definition TPPG.h:122
static int16_t fTimestampUnits
timestamp units of the PPG (10 ns)
Definition TPPG.h:119
UInt_t GetHighTimeStamp() const
Definition TPPG.h:111
UInt_t fLowTimeStamp
low bits of time stamp in 10 ns
Definition TPPG.h:124
Definition TPPG.h:132
bool fCycleSet
! flag to indicate whether the codes and durations have been calculated from the data
Definition TPPG.h:220
PPGMap_t::iterator MapBegin() const
Definition TPPG.h:209
void Print(Option_t *opt="") const override
Definition TPPG.cxx:214
ULong64_t GetCycleNumber(ULong64_t real_time)
Definition TPPG.cxx:621
TPPG & operator=(const TPPG &)
Definition TPPG.cxx:79
const TPPGData * First()
Definition TPPG.cxx:595
Int_t Write(const char *name=nullptr, Int_t option=0, Int_t bufsize=0) override
Definition TPPG.h:149
ULong64_t GetTimeInCycle(ULong64_t real_time)
Definition TPPG.cxx:613
void Clear(Option_t *opt="") override
Definition TPPG.cxx:430
const TPPGData * Next()
Definition TPPG.cxx:570
TPPG()
Definition TPPG.cxx:56
std::vector< int16_t > fOdbPPGCodes
ppg state codes read from odb
Definition TPPG.h:217
ULong64_t fCycleLength
Definition TPPG.h:214
ULong64_t GetNumberOfCycles()
Definition TPPG.cxx:652
PPGMap_t::iterator fCurrIterator
!
Definition TPPG.h:211
ULong64_t GetStatusStart(EPpgPattern)
Definition TPPG.cxx:669
std::vector< ULong64_t > fDurations
! duration of ppg state calculated from data
Definition TPPG.h:222
bool OdbMatchesData(bool verbose=false)
Definition TPPG.cxx:339
Bool_t MapIsEmpty() const
Definition TPPG.cxx:113
const TPPGData * Last()
Definition TPPG.cxx:588
ULong64_t GetNextStatusTime(ULong64_t time, EPpgPattern pat=EPpgPattern::kJunk) const
Definition TPPG.cxx:159
ULong64_t GetCycleLength()
Definition TPPG.cxx:629
EPpgPattern GetStatus(ULong64_t time) const
Definition TPPG.cxx:187
std::vector< int16_t > fPPGCodes
! ppg state codes (these are always set)
Definition TPPG.h:221
Long64_t OdbCycleLength() const
Definition TPPG.h:171
std::map< ULong64_t, int > fNumberOfCycleLengths
Definition TPPG.h:215
void Add(const TPPG *ppg)
Definition TPPG.cxx:680
void operator+=(const TPPG &rhs)
Definition TPPG.cxx:675
std::map< ULong_t, TPPGData * > PPGMap_t
Definition TPPG.h:136
PPGMap_t::iterator MapEnd() const
Definition TPPG.h:210
ULong64_t GetLastStatusTime(ULong64_t time, EPpgPattern pat=EPpgPattern::kJunk) const
Definition TPPG.cxx:131
void AddData(TPPGData *pat)
Definition TPPG.cxx:121
void SetOdbFromData(bool verbose=false)
Definition TPPG.cxx:364
bool CalculateCycleFromData(bool verbose=false)
Definition TPPG.cxx:379
std::size_t PPGSize() const
Definition TPPG.h:167
void Setup()
Definition TPPG.cxx:460
~TPPG()
Definition TPPG.cxx:68
void Copy(TObject &obj) const override
Definition TPPG.cxx:93
const TPPGData * Previous()
Definition TPPG.cxx:579
EPpgPattern GetNextStatus(ULong64_t time) const
Definition TPPG.cxx:199
std::size_t OdbPPGSize() const
Definition TPPG.h:168
std::vector< int > fOdbDurations
duration of ppg state as read from odb
Definition TPPG.h:218
Long64_t Merge(TCollection *list)
Definition TPPG.cxx:657
PPGMap_t * fPPGStatusMap
Definition TPPG.h:213
bool Correct(bool verbose=false)
Definition TPPG.cxx:482
static int SubRunNumber()
Definition TRunInfo.h:202
static int RunNumber()
Definition TRunInfo.h:201
EPpgPattern
Definition TPPG.h:38