File indexing completed on 2025-08-05 08:16:17
0001 #include "SingleTriggeredInput.h"
0002 #include "SingleGl1TriggeredInput.h"
0003
0004 #include <frog/FROG.h>
0005
0006 #include <ffarawobjects/CaloPacketContainerv1.h>
0007 #include <ffarawobjects/CaloPacketv1.h>
0008
0009 #include <fun4all/Fun4AllReturnCodes.h>
0010
0011 #include <phool/PHCompositeNode.h>
0012 #include <phool/PHIODataNode.h> // for PHIODataNode
0013 #include <phool/PHNode.h> // for PHNode
0014 #include <phool/PHNodeIterator.h> // for PHNodeIterator
0015 #include <phool/PHObject.h> // for PHObject
0016 #include <phool/getClass.h>
0017 #include <phool/phool.h>
0018
0019 #include <TSystem.h>
0020
0021 #include <cstdint> // for uint64_t
0022 #include <iostream> // for operator<<, basic_ostream, endl
0023 #include <ranges>
0024 #include <set>
0025 #include <unordered_set>
0026 #include <utility> // for pair
0027 #include <vector>
0028
0029 SingleTriggeredInput::SingleTriggeredInput(const std::string &name)
0030 : Fun4AllBase(name)
0031 {
0032 m_bclkarray.fill(std::numeric_limits<uint64_t>::max());
0033 m_bclkdiffarray.fill(std::numeric_limits<uint64_t>::max());
0034 }
0035
0036 SingleTriggeredInput::~SingleTriggeredInput()
0037 {
0038 for (auto& [pid, dq] : m_PacketEventDeque)
0039 {
0040 while (!dq.empty())
0041 {
0042 delete dq.front();
0043 dq.pop_front();
0044 }
0045 }
0046
0047 for (auto& [pid, evt] : m_PacketEventBackup)
0048 {
0049 delete evt;
0050 }
0051
0052 delete m_EventIterator;
0053 }
0054
0055 bool SingleTriggeredInput::CheckFemDiffIdx(int pid, size_t index, const std::deque<Event*>& events, uint64_t gl1diffidx)
0056 {
0057 if (index >= events.size())
0058 {
0059 return false;
0060 }
0061
0062 Packet* pkt_prev = events[index-1]->getPacket(pid);
0063 Packet* pkt_curr = events[index]->getPacket(pid);
0064 if (!pkt_prev || !pkt_curr)
0065 {
0066 delete pkt_prev;
0067 delete pkt_curr;
0068 return false;
0069 }
0070
0071 auto get_majority_femclk = [](Packet* pkt) -> uint16_t {
0072 int nmod = pkt->iValue(0, "NRMODULES");
0073 std::map<uint16_t, int> counts;
0074 for (int j = 0; j < nmod; ++j)
0075 {
0076 uint16_t clk = static_cast<uint16_t>(pkt->iValue(j, "FEMCLOCK"));
0077 counts[clk]++;
0078 }
0079 if (counts.empty())
0080 {
0081 return std::numeric_limits<uint16_t>::max();
0082 }
0083 return std::max_element(counts.begin(), counts.end(), [](const auto& a, const auto& b) { return a.second < b.second; })->first;
0084 };
0085
0086 uint16_t clk_prev = get_majority_femclk(pkt_prev);
0087 uint16_t clk_curr = get_majority_femclk(pkt_curr);
0088
0089 delete pkt_prev;
0090 delete pkt_curr;
0091
0092 if (clk_prev == std::numeric_limits<uint16_t>::max() || clk_curr == std::numeric_limits<uint16_t>::max())
0093 {
0094 return false;
0095 }
0096
0097 uint16_t femdiff = static_cast<uint16_t>(clk_curr - clk_prev);
0098 gl1diffidx = static_cast<uint16_t>(gl1diffidx & 0xFFFFU);
0099 return (femdiff == gl1diffidx);
0100 }
0101
0102 bool SingleTriggeredInput::CheckPoolAlignment(int pid, const std::array<uint64_t, pooldepth>& sebdiff, const std::array<uint64_t, pooldepth>& gl1diff, std::vector<int>& bad_indices, int& shift, bool& CurrentPoolLastDiffBad, bool PrevPoolLastDiffBad)
0103 {
0104 bad_indices.clear();
0105 shift = 0;
0106 CurrentPoolLastDiffBad=false;
0107
0108 if (std::equal(sebdiff.begin(), sebdiff.end(), gl1diff.begin()))
0109 {
0110 return true;
0111 }
0112
0113
0114 size_t n = sebdiff.size();
0115 std::vector<int> bad_diff_indices;
0116 for (size_t i = 0; i < n; ++i)
0117 {
0118 if ( sebdiff[i] != gl1diff[i] )
0119 {
0120 if ( !m_packetclk_copy_runs )
0121 {
0122
0123 size_t idxcheck = i == 0 ? i+1 : i;
0124 bool passFemDiffCheckIdx = CheckFemDiffIdx(pid, idxcheck, m_PacketEventDeque[pid], gl1diff[idxcheck]);
0125 if ( passFemDiffCheckIdx )
0126 {
0127 m_OverrideWithRepClock.insert(pid);
0128 continue;
0129 }
0130 }
0131 bad_diff_indices.push_back(i);
0132 }
0133 }
0134
0135 if (bad_diff_indices.empty())
0136 {
0137 if ( Verbosity() > 0 )
0138 {
0139 std::cout << Name() << " recovered from bad XMIT clocks. Merging pool" << std::endl;
0140 }
0141 return true;
0142 }
0143
0144 bool move_to_shift_algo = false;
0145 if(bad_diff_indices.size() >=5)
0146 {
0147 std::cout << std::endl;
0148 std::cout << "----------------- " << Name() << " -----------------" << std::endl;
0149 std::cout << "More than 5 diffs are bad.. try shifting algorithm" << std::endl;
0150 move_to_shift_algo = true;
0151 }
0152 if(!move_to_shift_algo)
0153 {
0154 std::cout << std::endl;
0155 std::cout << "----------------- " << Name() << " -----------------" << std::endl;
0156 }
0157
0158 size_t idx = 0;
0159 while (idx < bad_diff_indices.size() && !move_to_shift_algo)
0160 {
0161 int start = bad_diff_indices[idx];
0162 int end = start;
0163 while ((idx+1) < bad_diff_indices.size() && bad_diff_indices[idx+1] == end + 1)
0164 {
0165 ++idx;
0166 ++end;
0167 }
0168
0169 int length = end - start + 1;
0170 if(length<=0)
0171 {
0172 std::cout << Name() << ": length of bad diffs is <=0. This should not happen... something very wrong. rejecting the pool" << std::endl;
0173 return false;
0174 }
0175 if(length>=5)
0176 {
0177 std::cout << Name() << ": length of bad diffs >=5 with bad_diff_indices.size() " << bad_diff_indices.size() << ". This should not have happened.. rejecting pool" << std::endl;
0178 return false;
0179 }
0180
0181 if(start==static_cast<int>(pooldepth - 1))
0182 {
0183 bad_indices.push_back(start);
0184 CurrentPoolLastDiffBad= true;
0185 }
0186 else if (start==0)
0187 {
0188 if (PrevPoolLastDiffBad)
0189 {
0190 for (int j = start; j < end; ++j)
0191 {
0192 bad_indices.push_back(j);
0193 }
0194 }
0195 else
0196 {
0197 if (length == 1)
0198 {
0199 std::cout << Name() << ": diff[0] alone bad. isolated bad diff which should not happen.. rejecting pool" << std::endl;
0200 return false;
0201 }
0202 for (int j = start; j < end; ++j)
0203 {
0204 bad_indices.push_back(j);
0205 }
0206 }
0207 }
0208 else if (start < static_cast<int>(pooldepth - 1) && start >0)
0209 {
0210 if(length==1)
0211 {
0212 std::cout << Name() << ": Isolated bad diff[" << start << "] - rejecting pool" << std::endl;
0213 return false;
0214 }
0215 if(length>=2)
0216 {
0217 for (int j = start; j < end; ++j)
0218 {
0219 bad_indices.push_back(j);
0220 }
0221 }
0222 }
0223 else
0224 {
0225 std::cout << Name() << ": no categories assigned for length " << length << " and start / end " << start << " / " << end << " rejecting pool" << std::endl;
0226 return false;
0227 }
0228 ++idx;
0229 }
0230
0231 if (!move_to_shift_algo)
0232 {
0233 size_t nbads = bad_indices.size();
0234
0235 if (nbads == 0 || nbads >= 4)
0236 {
0237 std::cout << Name() << ": unexpected number of bad events = " << nbads << " – rejecting pool" << std::endl;
0238 return false;
0239 }
0240
0241 std::cout << Name() << ": intermittent bad events = " << nbads << " – do not try shifting algorithm" << std::endl;
0242 return true;
0243 }
0244
0245
0246
0247 if(!move_to_shift_algo)
0248 {
0249 std::cout << Name() << ": Unexpected shift flag = " << move_to_shift_algo << ". Something went wrong - rejecting pool" << std::endl;
0250 return false;
0251 }
0252
0253 if(move_to_shift_algo)
0254 {
0255 std::cout << Name() << ": Inconsistent diffs of " << bad_diff_indices.size() << ". Trying now shifting events to resynchronize" << std::endl;
0256 }
0257
0258 bool match = true;
0259 bool first_pool = (gl1diff[0] == std::numeric_limits<uint64_t>::max());
0260 size_t start = first_pool ? 2 : 1;
0261
0262 for (size_t i = start; i < pooldepth; ++i)
0263 {
0264 if (sebdiff[i] != gl1diff[i - 1])
0265 {
0266 match= false;
0267 break;
0268 }
0269 }
0270 if (match)
0271 {
0272 shift = -1;
0273 return true;
0274 }
0275
0276 match = true;
0277 start = first_pool ? 1 : 0;
0278 for (size_t i = start; i < pooldepth - 1; ++i)
0279 {
0280 if (sebdiff[i] != gl1diff[i + 1])
0281 {
0282 match= false;
0283 break;
0284 }
0285 }
0286 if (match)
0287 {
0288 shift = 1;
0289 return true;
0290 }
0291
0292 return false;
0293 }
0294
0295 int SingleTriggeredInput::fileopen(const std::string &filenam)
0296 {
0297 std::cout << PHWHERE << "trying to open " << filenam << std::endl;
0298 if (IsOpen())
0299 {
0300 std::cout << "Closing currently open file "
0301 << FileName()
0302 << " and opening " << filenam << std::endl;
0303 fileclose();
0304 }
0305 FileName(filenam);
0306 FROG frog;
0307 std::string fname = frog.location(FileName());
0308 if (Verbosity() > 0)
0309 {
0310 std::cout << Name() << ": opening file " << FileName() << std::endl;
0311 }
0312 int status = 0;
0313 m_EventIterator = new fileEventiterator(fname.c_str(), status);
0314 if (status)
0315 {
0316 delete m_EventIterator;
0317 m_EventIterator = nullptr;
0318 std::cout << PHWHERE << Name() << ": could not open file " << fname << std::endl;
0319 return -1;
0320 }
0321 IsOpen(1);
0322 AddToFileOpened(fname);
0323 return 0;
0324 }
0325
0326 int SingleTriggeredInput::fileclose()
0327 {
0328 if (!IsOpen())
0329 {
0330 std::cout << Name() << ": fileclose: No Input file open" << std::endl;
0331 return -1;
0332 }
0333 delete m_EventIterator;
0334 m_EventIterator = nullptr;
0335 IsOpen(0);
0336 UpdateFileList();
0337 return 0;
0338 }
0339
0340 int SingleTriggeredInput::FillEventVector()
0341 {
0342 while (GetEventIterator() == nullptr)
0343 {
0344 if (!OpenNextFile())
0345 {
0346 AllDone(1);
0347 return -1;
0348 }
0349 }
0350
0351 bool allPacketEventDequeEmpty = true;
0352 int representative_pid = -1;
0353 for (int pid : m_PacketSet)
0354 {
0355 if ( !m_PacketEventDeque[pid].empty() )
0356 {
0357 allPacketEventDequeEmpty = false;
0358 break;
0359 }
0360 uint64_t tmp = m_bclkarray_map[pid][pooldepth];
0361 m_bclkarray_map[pid].fill(std::numeric_limits<uint64_t>::max());
0362 m_bclkarray_map[pid][0] = tmp;
0363 m_bclkdiffarray_map[pid].fill(std::numeric_limits<uint64_t>::max());
0364
0365 if ( representative_pid == -1 )
0366 {
0367 representative_pid = pid;
0368 }
0369 }
0370 if ( !allPacketEventDequeEmpty )
0371 {
0372 return 0;
0373 }
0374
0375 size_t i{0};
0376 std::map<int, Event*> m_ShiftedEvents;
0377
0378 while (i < pooldepth)
0379 {
0380 Event* evt{nullptr};
0381 if (this != Gl1Input())
0382 {
0383 auto* gl1 = dynamic_cast<SingleGl1TriggeredInput*>(Gl1Input());
0384 if (gl1)
0385 {
0386 int nskip = gl1->GetGl1SkipArray()[i];
0387 if (m_Gl1PacketOneSkipActiveTrace)
0388 {
0389 int gl1packetcountdiff = static_cast<int>(gl1->GetPacketNumbers()[i] - m_Gl1PacketNumberOneSkip);
0390 if ( nskip == -1 && gl1packetcountdiff < m_Gl1PacketOneSkipCount )
0391 {
0392 m_Gl1PacketOneSkipActiveTrace = false;
0393 if (Verbosity() > 0)
0394 {
0395 std::cout << Name() << ": GL1 stuck detected at " << gl1->GetPacketNumbers()[i] << " after skipping " << gl1packetcountdiff << ". Clearing trace." << std::endl;
0396 }
0397 }
0398 else if ( gl1packetcountdiff >= m_Gl1PacketOneSkipCount )
0399 {
0400 m_Gl1PacketOneSkipActiveTrace = false;
0401 if (Verbosity() > 0)
0402 {
0403 std::cout << Name() << ": No stuck found before " << m_Gl1PacketOneSkipCount << " events. Skipping one SEB event now." << std::endl;
0404 }
0405 Event* skip_evt = GetEventIterator()->getNextEvent();
0406 while (!skip_evt)
0407 {
0408 fileclose();
0409 if (!OpenNextFile())
0410 {
0411 FilesDone(1);
0412 return -1;
0413 }
0414 skip_evt = GetEventIterator()->getNextEvent();
0415 }
0416 }
0417 }
0418 if (nskip == 1 && m_packetclk_copy_runs == true)
0419 {
0420 m_Gl1PacketOneSkipActiveTrace = true;
0421 m_Gl1PacketNumberOneSkip = gl1->GetPacketNumbers()[i];
0422 if (Verbosity() > 0)
0423 {
0424 std::cout << Name() << ": GL1 packet skip for " << m_Gl1PacketNumberOneSkip << ". Start tracing Gl1 packet number." << std::endl;
0425 }
0426 nskip = 0;
0427 }
0428
0429 while (nskip > 0)
0430 {
0431 Event* skip_evt = GetEventIterator()->getNextEvent();
0432 while (!skip_evt)
0433 {
0434 fileclose();
0435 if (!OpenNextFile())
0436 {
0437 FilesDone(1);
0438 return -1;
0439 }
0440 skip_evt = GetEventIterator()->getNextEvent();
0441 }
0442 if (Verbosity() > 0)
0443 {
0444 std::cout << Name() << ": Skipping SEB events because of GL1 packet number diff : " << nskip
0445 << ", with event sequence number " << skip_evt->getEvtSequence() << std::endl;
0446 }
0447
0448 Packet* pkt = skip_evt->getPacket(representative_pid);
0449 if (!pkt)
0450 {
0451 delete skip_evt;
0452 continue;
0453 }
0454
0455 FillPacketClock(skip_evt, pkt, i);
0456 delete pkt;
0457
0458 uint64_t seb_diff = m_bclkdiffarray_map[representative_pid][i];
0459 int gl1pid = Gl1Input()->m_bclkdiffarray_map.begin()->first;
0460 uint64_t gl1_diff = Gl1Input()->m_bclkdiffarray_map[gl1pid][i];
0461
0462 if (seb_diff == gl1_diff)
0463 {
0464 if (Verbosity() > 0)
0465 {
0466 std::cout << Name() << ": Early stop of SEB skip after " << (gl1->GetGl1SkipArray()[i] - nskip)
0467 << " from intial " << gl1->GetGl1SkipArray()[i] << " events." << std::endl;
0468 }
0469 evt = skip_evt;
0470 break;
0471 }
0472 delete skip_evt;
0473 nskip--;
0474 }
0475 }
0476 }
0477
0478 if (!evt)
0479 {
0480 evt = GetEventIterator()->getNextEvent();
0481 while (!evt)
0482 {
0483 fileclose();
0484 if (!OpenNextFile())
0485 {
0486 FilesDone(1);
0487 return -1;
0488 }
0489 evt = GetEventIterator()->getNextEvent();
0490 }
0491 }
0492 if (evt->getEvtType() != DATAEVENT)
0493 {
0494 if (Verbosity() > 0)
0495 {
0496 std::cout << Name() << " dropping non data event: " << evt->getEvtSequence() << std::endl;
0497 }
0498 delete evt;
0499 continue;
0500 }
0501 evt->convert();
0502
0503 if (firstcall)
0504 {
0505 std::cout << "Creating DSTs first call" << std::endl;
0506 CreateDSTNodes(evt);
0507 int run = evt->getRunNumber();
0508 m_packetclk_copy_runs = (run >= 44000 && run < 56079);
0509 firstcall = false;
0510 }
0511
0512 for (int pid : m_PacketSet)
0513 {
0514 Event *thisevt = evt;
0515 if (m_PacketShiftOffset[pid] == 1)
0516 {
0517 if (i==0)
0518 {
0519 thisevt = m_PacketEventBackup[pid];
0520 m_ShiftedEvents[pid] = evt;
0521 }
0522 else if (i > 0)
0523 {
0524 thisevt = m_ShiftedEvents[pid];
0525 m_ShiftedEvents[pid] = evt;
0526 if (i == pooldepth -1)
0527 {
0528 m_PacketEventBackup[pid] = evt;
0529 }
0530 }
0531 }
0532
0533 Packet* pkt = thisevt->getPacket(pid);
0534 if (!pkt)
0535 {
0536 continue;
0537 }
0538 FillPacketClock(thisevt, pkt, i);
0539 m_PacketEventDeque[pid].push_back(thisevt);
0540 delete pkt;
0541
0542 if (representative_pid == -1 && m_PacketShiftOffset[pid] == 0)
0543 {
0544 representative_pid = pid;
0545 }
0546 }
0547 i++;
0548 }
0549
0550 size_t minSize = pooldepth;
0551 for (const auto& [pid, dq] : m_PacketEventDeque)
0552 {
0553 minSize = std::min(dq.size(), minSize);
0554 }
0555 return minSize;
0556 }
0557
0558 uint64_t SingleTriggeredInput::GetClock(Event *evt, int pid)
0559 {
0560 Packet* packet = evt->getPacket(pid);
0561 if (!packet)
0562 {
0563 std::cout << Name() << ": Missing packet " << pid << " in event " << evt->getEvtSequence() << std::endl;
0564 return std::numeric_limits<uint64_t>::max();
0565 }
0566 uint64_t clkval = static_cast<uint64_t>(packet->lValue(0, "CLOCK"));
0567 uint64_t clk = clkval & 0xFFFFFFFFU;
0568 delete packet;
0569 return clk;
0570 }
0571
0572 void SingleTriggeredInput::FillPacketClock(Event* evt, Packet* pkt, size_t event_index)
0573 {
0574 if (!pkt)
0575 {
0576 return;
0577 }
0578 int pid = pkt->getIdentifier();
0579
0580 if (m_bclkarray_map.find(pid) == m_bclkarray_map.end())
0581 {
0582 m_bclkarray_map[pid].fill(std::numeric_limits<uint64_t>::max());
0583 m_bclkdiffarray_map[pid].fill(std::numeric_limits<uint64_t>::max());
0584 }
0585
0586 auto& clkarray = m_bclkarray_map[pid];
0587 auto& diffarray = m_bclkdiffarray_map[pid];
0588
0589
0590
0591 if (m_packetclk_copy_runs && m_CorrectCopiedClockPackets.count(pid))
0592 {
0593 if (event_index == 0)
0594 {
0595 clkarray[event_index+1] = m_PreviousValidBCOMap[pid];
0596 }
0597 else if (event_index >=1)
0598 {
0599 Event* shifted_evt = m_PacketEventDeque[pid][event_index - 1];
0600 clkarray[event_index+1] = GetClock(shifted_evt, pid);
0601 }
0602
0603 uint64_t prev = clkarray[event_index];
0604 uint64_t curr = clkarray[event_index + 1];
0605
0606 if (prev == std::numeric_limits<uint64_t>::max() || curr == std::numeric_limits<uint64_t>::max())
0607 {
0608 diffarray[event_index] = std::numeric_limits<uint64_t>::max();
0609 }
0610 else
0611 {
0612 diffarray[event_index] = ComputeClockDiff(curr, prev);
0613 }
0614
0615 return;
0616 }
0617
0618
0619 uint64_t clk = GetClock(evt, pid);
0620 if (clk == std::numeric_limits<uint64_t>::max())
0621 {
0622 std::cout << Name() << ": Bad clock for packet " << pid << " at event index " << event_index << std::endl;
0623 return;
0624 }
0625
0626 clkarray[event_index + 1] = clk;
0627
0628 uint64_t prev = clkarray[event_index];
0629 if(prev == std::numeric_limits<uint64_t>::max())
0630 {
0631 static std::unordered_set<int> warned;
0632
0633 if (warned.find(pid) == warned.end())
0634 {
0635 std::cout << Name() << ": First pool for pacekt " << pid << " – skipping first diff because of no previous clock" << std::endl;
0636 warned.insert(pid);
0637 }
0638 else
0639 {
0640 std::cout << "prev clock is max something is wrong... : " << event_index << std::endl;
0641 }
0642 diffarray[event_index] = std::numeric_limits<uint64_t>::max();
0643 }
0644 else
0645 {
0646 diffarray[event_index] = ComputeClockDiff(clk, prev);
0647 }
0648
0649 if (auto* gl1 = dynamic_cast<SingleGl1TriggeredInput*>(this))
0650 {
0651 int packet_number = pkt->iValue(0);
0652 gl1->SetPacketNumbers(gl1->GetCurrentPacketNumber(), packet_number);
0653 if ( event_index < pooldepth )
0654 {
0655 gl1->SetGl1PacketNumber(event_index, packet_number);
0656 }
0657
0658 int skip_count = 0;
0659 if (gl1->GetLastPacketNumber() != 0)
0660 {
0661 int diff = gl1->GetCurrentPacketNumber() - gl1->GetLastPacketNumber() ;
0662 skip_count = diff - 1;
0663 }
0664
0665 if (event_index < pooldepth)
0666 {
0667 gl1->SetGl1SkipAtIndex(event_index, skip_count);
0668 }
0669 }
0670 }
0671
0672 void SingleTriggeredInput::FillPool()
0673 {
0674 if (AllDone() || EventAlignmentProblem())
0675 {
0676 return;
0677 }
0678
0679 bool all_packets_bad = !m_PacketAlignmentProblem.empty() && std::all_of(m_PacketAlignmentProblem.begin(), m_PacketAlignmentProblem.end(), [](const std::pair<const int, bool> &entry) -> bool { return entry.second;});
0680 if (all_packets_bad)
0681 {
0682 std::cout << Name() << ": ALL packets are marked as bad. Stop combining for this SEB." << std::endl;
0683 EventAlignmentProblem(1);
0684 return;
0685 }
0686
0687 if (!FilesDone())
0688 {
0689 int eventvectorsize = FillEventVector();
0690 if (eventvectorsize != 0)
0691 {
0692 if (Gl1Input()->m_bclkdiffarray_map.empty())
0693 {
0694 std::cout << Name() << " : GL1 clock map is empty!" << std::endl;
0695 return;
0696 }
0697 m_OverrideWithRepClock.clear();
0698
0699 int gl1pid = Gl1Input()->m_bclkdiffarray_map.begin()->first;
0700 const auto& gl1diff = Gl1Input()->m_bclkdiffarray_map.at(gl1pid);
0701
0702 bool allgl1max = std::all_of(gl1diff.begin(), gl1diff.end(), [](uint64_t val) {
0703 return val == std::numeric_limits<uint64_t>::max();
0704 });
0705 if (allgl1max)
0706 {
0707 std::cout << Name() << " : GL1 clock diffs all filled with max 64 bit values for PID " << gl1pid << " return and try next pool" << std::endl;
0708 return;
0709 }
0710 m_DitchPackets.clear();
0711
0712 for (auto& [pid, _] : m_PrevPoolLastDiffBad)
0713 {
0714 m_PrevPoolLastDiffBad[pid] = false;
0715 }
0716
0717 for (const auto& [pid, sebdiff] : m_bclkdiffarray_map)
0718 {
0719 size_t packetpoolsize = m_PacketEventDeque[pid].size();
0720 if(packetpoolsize==0)
0721 {
0722 std::cout << Name() << ": packet pool size is zero.... something is wrong" << std::endl;
0723 return;
0724 }
0725
0726 if(m_PacketAlignmentProblem[pid])
0727 {
0728 continue;
0729 }
0730 std::vector<int> bad_indices;
0731 int shift = 0;
0732
0733 bool CurrentPoolLastDiffBad = false;
0734 bool PrevPoolLastDiffBad = m_PrevPoolLastDiffBad[pid];
0735
0736 bool aligned = CheckPoolAlignment(pid, sebdiff, gl1diff, bad_indices, shift, CurrentPoolLastDiffBad, PrevPoolLastDiffBad);
0737
0738 if (aligned)
0739 {
0740 m_PrevPoolLastDiffBad[pid] = CurrentPoolLastDiffBad;
0741 if (!bad_indices.empty())
0742 {
0743 std::cout << Name() << ": Packet " << pid << " has bad indices: ";
0744 for (int bi : bad_indices){
0745 std::cout << bi << " ";
0746 m_DitchPackets[pid].insert(bi);
0747 }
0748 std::cout << std::endl;
0749
0750 std::cout << "full print out of gl1 vs seb clocks " << std::endl;
0751 for (size_t i = 0; i <= pooldepth; ++i)
0752 {
0753 uint64_t gl1_clk = Gl1Input()->m_bclkarray_map[gl1pid][i];
0754 uint64_t seb_clk = m_bclkarray_map[pid][i];
0755 std::cout << "pool index i " << i << ", gl1 / seb : " << gl1_clk << " / " << seb_clk;
0756 if(i<pooldepth){
0757 uint64_t gl1_diff = Gl1Input()->m_bclkdiffarray_map[gl1pid][i];
0758 uint64_t seb_diff = m_bclkdiffarray_map[pid][i];
0759 std::cout << " -> diff of gl1 vs seb : " << gl1_diff << " " << seb_diff << std::endl;
0760 }
0761 else if(i==pooldepth)
0762 {
0763 std::cout << std::endl;
0764 }
0765 }
0766 }
0767
0768 if (shift == -1)
0769 {
0770 std::cout << Name() << ": Packet " << pid << " shifted by -1 with dropping the first seb event" << std::endl;
0771 if(m_PacketShiftOffset[pid] == -1)
0772 {
0773 std::cout << "Packet " << pid << " requires an additional shift -1. Lets not handle this for the moment.. stop combining" << std::endl;
0774 m_PacketAlignmentProblem[pid] = true;
0775 }
0776
0777 if (!m_PacketEventDeque[pid].empty())
0778 {
0779 m_PacketEventDeque[pid].pop_front();
0780 }
0781 else
0782 {
0783 std::cout << Name() << ": ERROR — shift -1 requested but packet deque is empty!" << std::endl;
0784 continue;
0785 }
0786
0787 for (size_t i = 0; i < packetpoolsize - 1; ++i)
0788 {
0789 m_bclkarray_map[pid][i] = m_bclkarray_map[pid][i+1];
0790 }
0791
0792 for (size_t i = 0; i < packetpoolsize; ++i)
0793 {
0794 m_bclkdiffarray_map[pid][i] = ComputeClockDiff(m_bclkarray_map[pid][i+1], m_bclkarray_map[pid][i]);
0795 }
0796 Event* evt = GetEventIterator()->getNextEvent();
0797 if (evt)
0798 {
0799 evt->convert();
0800 std::vector<Packet*> pktvec = evt->getPacketVector();
0801 for (Packet* pkt : pktvec)
0802 {
0803 if (pkt->getIdentifier() == pid)
0804 {
0805 FillPacketClock(evt, pkt, packetpoolsize - 1);
0806 m_PacketEventDeque[pid].push_back(evt);
0807 }
0808 delete pkt;
0809 }
0810 }
0811 else
0812 {
0813 std::cout << Name() << ": Cannot refill after shift -1" << std::endl;
0814 FilesDone(1);
0815 return;
0816 }
0817 m_PacketShiftOffset[pid] -= 1;
0818 }
0819 else if (shift == 1)
0820 {
0821 std::cout << Name() << ": Packet " << pid << " requires shift +1 (insert dummy at front)" << std::endl;
0822
0823 if (m_packetclk_copy_runs)
0824 {
0825 std::cout << Name() << " : runs where clocks are copied from the first XMIT. Checking FEM clock diff" << std::endl;
0826 if (FemClockAlignment(pid, m_PacketEventDeque[pid], gl1diff))
0827 {
0828 std::cout << Name() << " : Packet identified as aligned with FEM clocks. Apply shift only on packet clocks." << std::endl;
0829 m_CorrectCopiedClockPackets.insert(pid);
0830 m_DitchPackets[pid].insert(0);
0831
0832 Event* evt0 = m_PacketEventDeque[pid].front();
0833 m_PreviousValidBCOMap[pid] = GetClock(evt0, pid);
0834 m_bclkarray_map[pid][pooldepth] = m_bclkarray_map[pid][pooldepth - 1];
0835 continue;
0836 }
0837 std::cout << Name() << " : Packet identified as misaligned also with FEMs. Do normal recovery process" << std::endl;
0838 }
0839
0840 if(m_PacketShiftOffset[pid] == 1)
0841 {
0842 std::cout << "Packet " << pid << " requires an additional shift +1. Lets not handle this for the moment.. stop combining" << std::endl;
0843 m_PacketAlignmentProblem[pid] = true;
0844 }
0845
0846 for (size_t i = pooldepth; i > 0; --i)
0847 {
0848 m_bclkarray_map[pid][i] = m_bclkarray_map[pid][i-1];
0849 }
0850 for (size_t i = 1 ; i < pooldepth; ++i)
0851 {
0852 m_bclkdiffarray_map[pid][i] = ComputeClockDiff(m_bclkarray_map[pid][i+1], m_bclkarray_map[pid][i]);
0853 }
0854
0855 m_bclkarray_map[pid][0] = 0;
0856 m_bclkdiffarray_map[pid][0] = 0;
0857 m_DitchPackets[pid].insert(0);
0858
0859 if (!m_PacketEventDeque[pid].empty())
0860 {
0861 m_PacketEventBackup[pid] = m_PacketEventDeque[pid].back();
0862 Event* dummy_event = m_PacketEventDeque[pid][0];
0863 m_PacketEventDeque[pid].push_front(dummy_event);
0864 m_PacketEventDeque[pid].pop_back();
0865 }
0866 else
0867 {
0868 std::cout << Name() << ": m_PacketEventDeque is empty, cannot insert dummy event!" << std::endl;
0869 return;
0870 }
0871
0872 m_PacketShiftOffset[pid] += 1;
0873 std::cout << std::endl;
0874 }
0875 }
0876 else
0877 {
0878 std::cout << Name() << ": Alignment failed for packet " << pid
0879 << " (retry count = " << m_PacketAlignmentFailCount[pid] << ")" << std::endl;
0880 std::cout << "full print out of gl1 vs seb clocks " << std::endl;
0881 for (size_t i = 0; i <= pooldepth; ++i)
0882 {
0883 uint64_t gl1_clk = Gl1Input()->m_bclkarray_map[gl1pid][i];
0884 uint64_t seb_clk = m_bclkarray_map[pid][i];
0885 std::cout << "pool index i " << i << ", gl1 / seb : " << gl1_clk << " / " << seb_clk;
0886 if(i<pooldepth){
0887 uint64_t gl1_diff = Gl1Input()->m_bclkdiffarray_map[gl1pid][i];
0888 uint64_t seb_diff = m_bclkdiffarray_map[pid][i];
0889 std::cout << " -- diff of gl1 vs seb : " << gl1_diff << " " << seb_diff << std::endl;
0890 }
0891 else if(i==pooldepth)
0892 {
0893 std::cout << std::endl;
0894 }
0895 }
0896
0897 m_PacketAlignmentFailCount[pid]++;
0898 for (size_t i = 0; i < pooldepth; ++i)
0899 {
0900 m_DitchPackets[pid].insert(i);
0901 }
0902
0903 if (m_PacketAlignmentFailCount[pid] >= m_max_alignment_retries)
0904 {
0905 std::cout << Name() << ": Max retries reached — permanently ditching packet " << pid << std::endl;
0906 m_PacketAlignmentFailCount[pid] = 0;
0907 m_PacketAlignmentProblem[pid] = true;
0908 }
0909 }
0910 }
0911 }
0912 }
0913 return;
0914 }
0915
0916 void SingleTriggeredInput::CreateDSTNodes(Event *evt)
0917 {
0918 std::string CompositeNodeName = "Packets";
0919 if (KeepMyPackets())
0920 {
0921 CompositeNodeName = "PacketsKeep";
0922 }
0923 PHNodeIterator iter(m_topNode);
0924 PHCompositeNode *dstNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "DST"));
0925 if (!dstNode)
0926 {
0927 dstNode = new PHCompositeNode("DST");
0928 m_topNode->addNode(dstNode);
0929 }
0930 PHNodeIterator iterDst(dstNode);
0931 PHCompositeNode *detNode = dynamic_cast<PHCompositeNode *>(iterDst.findFirst("PHCompositeNode", CompositeNodeName));
0932 if (!detNode)
0933 {
0934 detNode = new PHCompositeNode(CompositeNodeName);
0935 dstNode->addNode(detNode);
0936 }
0937 std::vector<Packet *> pktvec = evt->getPacketVector();
0938 for (auto *piter : pktvec)
0939 {
0940 int packet_id = piter->getIdentifier();
0941 m_PacketSet.insert(packet_id);
0942 std::string PacketNodeName = std::to_string(packet_id);
0943 CaloPacket *calopacket = findNode::getClass<CaloPacket>(detNode, PacketNodeName);
0944 if (!calopacket)
0945 {
0946 calopacket = new CaloPacketv1();
0947 PHIODataNode<PHObject> *newNode = new PHIODataNode<PHObject>(calopacket, PacketNodeName, "PHObject");
0948 detNode->addNode(newNode);
0949 }
0950 m_PacketShiftOffset.try_emplace(packet_id, 0);
0951 delete piter;
0952 }
0953 }
0954
0955 bool SingleTriggeredInput::FemClockAlignment(int pid, const std::deque<Event*>& events, const std::array<uint64_t, pooldepth>& gl1diff)
0956 {
0957 if (events.size() < pooldepth)
0958 {
0959 std::cout << Name() << ": Not enough events for FEMClockAlignment check for packet " << pid << std::endl;
0960 return false;
0961 }
0962
0963 uint64_t prev_clk = std::numeric_limits<uint64_t>::max();
0964
0965 for (size_t i = 0; i < pooldepth; ++i)
0966 {
0967 Event* evt = events[i];
0968 Packet* pkt = evt->getPacket(pid);
0969 if (!pkt)
0970 {
0971 continue;
0972 }
0973
0974 int nmod = pkt->iValue(0, "NRMODULES");
0975 std::map<int, int> clk_count;
0976
0977 for (int j = 0; j < nmod; ++j)
0978 {
0979 int femclk = static_cast<uint16_t>(pkt->iValue(j, "FEMCLOCK"));
0980 clk_count[femclk]++;
0981 }
0982
0983 delete pkt;
0984
0985 if (clk_count.empty())
0986 {
0987 continue;
0988 }
0989
0990 int majority_clk = std::max_element(
0991 clk_count.begin(), clk_count.end(),
0992 [](const auto& a, const auto& b) { return a.second < b.second; })->first;
0993
0994 if (clk_count[majority_clk] < 2)
0995 {
0996 std::cout << Name() << ": FemClockAlignment — no majority FEM clocks for packet " << pid << " at pool index " << i << std::endl;
0997 return false;
0998 }
0999
1000
1001 if (i >= 1 && prev_clk != std::numeric_limits<uint64_t>::max() && gl1diff[i] != std::numeric_limits<uint64_t>::max())
1002 {
1003 uint16_t fem_diff = static_cast<uint16_t>(ComputeClockDiff(majority_clk, prev_clk) & 0xFFFFU);
1004 uint16_t gl1_diff = static_cast<uint16_t>(gl1diff[i] & 0xFFFFU);
1005
1006 std::cout << "i " << i << " curr_fem_clk / prev_fem_clk " << majority_clk << " " << prev_clk << " , fem_diff / gl1_diff " << fem_diff << " " << gl1_diff << std::endl;
1007 if (fem_diff != gl1_diff)
1008 {
1009 return false;
1010 }
1011 }
1012
1013 prev_clk = majority_clk;
1014 }
1015
1016 return true;
1017 }
1018
1019 int SingleTriggeredInput::FemEventNrClockCheck(OfflinePacket *pkt)
1020 {
1021 CaloPacket *calopkt = dynamic_cast<CaloPacket *>(pkt);
1022 if (!calopkt)
1023 {
1024 return 0;
1025 }
1026
1027 int nrModules = calopkt->iValue(0, "NRMODULES");
1028 std::set<int> EventNoSet;
1029 for (int j = 0; j < nrModules; j++)
1030 {
1031 EventNoSet.insert(calopkt->iValue(j, "FEMEVTNR"));
1032 }
1033 size_t femeventnumbers = EventNoSet.size();
1034 if (femeventnumbers > 1)
1035 {
1036 int goodfemevent = 0;
1037 if (femeventnumbers == 2)
1038 {
1039
1040 std::map<int, int> EventMap;
1041 std::map<int, int> BadModuleMap;
1042 for (int j = 0; j < nrModules; j++)
1043 {
1044 EventMap[calopkt->iValue(j, "FEMEVTNR")]++;
1045 BadModuleMap[calopkt->iValue(j, "FEMEVTNR")] = j;
1046 }
1047 for (const auto iter : EventMap)
1048 {
1049 if (iter.second == 1)
1050 {
1051 calopkt->setFemStatus(BadModuleMap[iter.first], CaloPacket::BAD_EVENTNR);
1052 }
1053 else
1054 {
1055 goodfemevent = iter.first;
1056 }
1057 }
1058 }
1059 else
1060 {
1061 for (int j = 0; j < nrModules; j++)
1062 {
1063 calopkt->setFemStatus(j, CaloPacket::BAD_EVENTNR);
1064 }
1065 }
1066 std::set<int> FemClockSet;
1067 for (int j = 0; j < nrModules; j++)
1068 {
1069 FemClockSet.insert(calopkt->iValue(j, "FEMCLOCK"));
1070 }
1071 if (FemClockSet.size() == 1)
1072 {
1073 static int icnt = 0;
1074 if (icnt < 10)
1075 {
1076 icnt++;
1077 std::cout << "Packet " << calopkt->getIdentifier() << " has not unique event numbers"
1078 << " but FEM Clock counters are identical" << std::endl;
1079 }
1080 if (goodfemevent > 0)
1081 {
1082 m_FEMEventNrSet.insert(goodfemevent);
1083 }
1084 return 1;
1085 }
1086 static int icnt = 0;
1087 if (icnt < 1000)
1088 {
1089 icnt++;
1090 std::cout << "resetting packet " << calopkt->getIdentifier()
1091 << " with fem event and clock mismatch" << std::endl;
1092 std::map<int, int> ClockMap;
1093 std::map<int, int> EventMap;
1094 for (int j = 0; j < nrModules; j++)
1095 {
1096 EventMap[calopkt->iValue(j, "FEMEVTNR")]++;
1097 ClockMap[calopkt->iValue(j, "FEMCLOCK")]++;
1098 }
1099 for (const auto iterA : EventMap)
1100 {
1101 std::cout << "Event Nr : " << iterA.first << " shows up " << iterA.second << " times"
1102 << std::hex << ", Event Nr 0x" << iterA.first << std::dec << std::endl;
1103 }
1104 for (const auto iterA : ClockMap)
1105 {
1106 std::cout << "Clock : 0x" << std::hex << iterA.first << std::dec
1107 << " shows up " << iterA.second << " times" << std::endl;
1108 }
1109 }
1110 return -1;
1111 }
1112 m_FEMEventNrSet.insert(*(EventNoSet.begin()));
1113 return 0;
1114 }
1115
1116 void SingleTriggeredInput::dumpdeque()
1117 {
1118 const auto *iter1 = clkdiffbegin();
1119 const auto *iter2 = Gl1Input()->clkdiffbegin();
1120 while (iter1 != clkdiffend())
1121 {
1122 std::cout << Name() << " clk: 0x" << std::hex << *iter1
1123 << " Gl1 clk: 0x" << *iter2 << std::dec << std::endl;
1124 iter1++;
1125 iter2++;
1126 }
1127 return;
1128 }
1129
1130 int SingleTriggeredInput::ReadEvent()
1131 {
1132 for (const auto& [pid, dq] : m_PacketEventDeque)
1133 {
1134 if (dq.empty())
1135 {
1136 if (!EventAlignmentProblem())
1137 {
1138 std::cout << Name() << ": Packet " << pid << " has empty deque — all events done" << std::endl;
1139 AllDone(1);
1140 }
1141 return -1;
1142 }
1143 }
1144
1145 if (Verbosity() > 1)
1146 {
1147 size_t size = m_PacketEventDeque.begin()->second.size();
1148 std::cout << "deque size: " << size << std::endl;
1149 }
1150
1151 auto *ref_evt = m_PacketEventDeque.begin()->second.front();
1152 RunNumber(ref_evt->getRunNumber());
1153
1154 uint64_t event_number = ref_evt->getEvtSequence();
1155 if(event_number % 10000==0)
1156 {
1157 std::cout << "processed events : " << event_number << std::endl;
1158 }
1159
1160 m_FEMEventNrSet.clear();
1161
1162 bool all_packets_unshifted = std::all_of(
1163 m_PacketShiftOffset.begin(), m_PacketShiftOffset.end(),
1164 [](const std::pair<int, int>& p) { return p.second == 0; });
1165
1166 std::set<Event*> events_to_delete;
1167
1168 for (auto& [pid, dq] : m_PacketEventDeque)
1169 {
1170 if(m_PacketAlignmentProblem[pid])
1171 {
1172 continue;
1173 }
1174 Event* evt = dq.front();
1175 Packet* packet = evt->getPacket(pid);
1176
1177 int packet_id = packet->getIdentifier();
1178 if (packet_id != pid)
1179 {
1180 std::cout << Name() << ": packet id mismatch... Should never happen. Abort combining" << std::endl;
1181 EventAlignmentProblem(1);
1182 delete packet;
1183 return -1;
1184 }
1185
1186 CaloPacket *newhit = findNode::getClass<CaloPacket>(m_topNode, packet_id);
1187 newhit->Reset();
1188
1189 if (m_DitchPackets.count(packet_id) && m_DitchPackets[packet_id].count(0))
1190 {
1191 newhit->setStatus(OfflinePacket::PACKET_DROPPED);
1192 newhit->setIdentifier(packet_id);
1193 std::cout << "ditching packet " << packet_id << " from prdf event " << evt->getEvtSequence() << std::endl;
1194 delete packet;
1195 continue;
1196 }
1197
1198 newhit->setStatus(OfflinePacket::PACKET_OK);
1199 if (m_OverrideWithRepClock.count(packet_id))
1200 {
1201 newhit->setStatus(OfflinePacket::PACKET_CORRUPT);
1202 }
1203 newhit->setPacketEvtSequence(packet->iValue(0, "EVTNR"));
1204 int nr_modules = packet->iValue(0, "NRMODULES");
1205 int nr_channels = packet->iValue(0, "CHANNELS");
1206 int nr_samples = packet->iValue(0, "SAMPLES");
1207 newhit->setNrModules(nr_modules);
1208 newhit->setNrChannels(nr_channels);
1209 newhit->setNrSamples(nr_samples);
1210 newhit->setIdentifier(packet_id);
1211 if (m_packetclk_copy_runs && m_CorrectCopiedClockPackets.count(packet_id))
1212 {
1213 uint64_t prev_packet_clock = m_PreviousValidBCOMap[packet_id];
1214 newhit->setBCO(prev_packet_clock);
1215 m_PreviousValidBCOMap[packet_id] = GetClock(evt,packet_id);
1216 }
1217 else
1218 {
1219 newhit->setBCO(packet->lValue(0, "CLOCK"));
1220 }
1221
1222 for (int ifem = 0; ifem < nr_modules; ifem++)
1223 {
1224 newhit->setFemClock(ifem, packet->iValue(ifem, "FEMCLOCK"));
1225 newhit->setFemEvtSequence(ifem, packet->iValue(ifem, "FEMEVTNR"));
1226 newhit->setFemSlot(ifem, packet->iValue(ifem, "FEMSLOT"));
1227 newhit->setChecksumLsb(ifem, packet->iValue(ifem, "CHECKSUMLSB"));
1228 newhit->setChecksumMsb(ifem, packet->iValue(ifem, "CHECKSUMMSB"));
1229 newhit->setCalcChecksumLsb(ifem, packet->iValue(ifem, "CALCCHECKSUMLSB"));
1230 newhit->setCalcChecksumMsb(ifem, packet->iValue(ifem, "CALCCHECKSUMMSB"));
1231 newhit->setFemStatus(ifem, CaloPacket::FEM_OK);
1232 }
1233 for (int ipmt = 0; ipmt < nr_channels; ipmt++)
1234 {
1235 bool isSuppressed = packet->iValue(ipmt, "SUPPRESSED");
1236 newhit->setSuppressed(ipmt, isSuppressed);
1237 if (isSuppressed)
1238 {
1239 newhit->setPre(ipmt, packet->iValue(ipmt, "PRE"));
1240 newhit->setPost(ipmt, packet->iValue(ipmt, "POST"));
1241 }
1242 else
1243 {
1244 for (int isamp = 0; isamp < nr_samples; isamp++)
1245 {
1246 newhit->setSample(ipmt, isamp, packet->iValue(isamp, ipmt));
1247 }
1248 }
1249 }
1250 delete packet;
1251 int iret = FemEventNrClockCheck(newhit);
1252 if (iret < 0)
1253 {
1254 std::cout << Name() <<" : failed on FemEventNrClockCheck reset calo packet " << std::endl;
1255 newhit->Reset();
1256 }
1257
1258 if (all_packets_unshifted || m_PacketShiftOffset[pid] == 1)
1259 {
1260 events_to_delete.insert(evt);
1261 }
1262 }
1263
1264 for(Event *evtdelete : events_to_delete)
1265 {
1266 delete evtdelete;
1267 }
1268
1269 for (auto& [pid, idx_set] : m_DitchPackets)
1270 {
1271 std::set<int> new_set;
1272 for (int idx : idx_set)
1273 {
1274 if (idx > 0)
1275 {
1276 new_set.insert(idx - 1);
1277 }
1278 }
1279 idx_set = std::move(new_set);
1280 }
1281
1282 for (auto& [pid, dq] : m_PacketEventDeque)
1283 {
1284 if (!dq.empty())
1285 {
1286 dq.pop_front();
1287 }
1288 }
1289
1290 return Fun4AllReturnCodes::EVENT_OK;
1291 }
1292