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