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