Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-06 08:17:25

0001 #include "SingleZdcTriggerInput.h"
0002 
0003 #include "Fun4AllPrdfInputTriggerManager.h"
0004 #include "InputManagerType.h"
0005 
0006 #include <ffarawobjects/CaloPacketContainerv1.h>
0007 #include <ffarawobjects/CaloPacketv1.h>
0008 
0009 #include <phool/PHCompositeNode.h>
0010 #include <phool/PHIODataNode.h>    // for PHIODataNode
0011 #include <phool/PHNode.h>          // for PHNode
0012 #include <phool/PHNodeIterator.h>  // for PHNodeIterator
0013 #include <phool/PHObject.h>        // for PHObject
0014 #include <phool/getClass.h>
0015 #include <phool/phool.h>
0016 
0017 #include <Event/Event.h>
0018 #include <Event/EventTypes.h>
0019 #include <Event/Eventiterator.h>
0020 #include <Event/packet.h>  // for Packet
0021 
0022 #include <TSystem.h>
0023 
0024 #include <cstdint>   // for uint64_t
0025 #include <iostream>  // for operator<<, basic_ostream<...
0026 #include <iterator>  // for reverse_iterator
0027 #include <limits>    // for numeric_limits
0028 #include <memory>
0029 #include <set>
0030 #include <utility>  // for pair
0031 
0032 SingleZdcTriggerInput::SingleZdcTriggerInput(const std::string &name)
0033   : SingleTriggerInput(name)
0034 {
0035   SubsystemEnum(InputManagerType::ZDC);
0036   LocalPoolDepth(3);
0037 }
0038 
0039 SingleZdcTriggerInput::~SingleZdcTriggerInput()
0040 {
0041   CleanupUsedLocalPackets(std::numeric_limits<int>::max());
0042   CleanupUsedPackets(std::numeric_limits<int>::max());
0043   // some events are already in the m_EventStack but they haven't been put
0044   // into the m_PacketMap
0045   while (m_EventStack.begin() != m_EventStack.end())
0046   {
0047     m_EventStack.erase(m_EventStack.begin());
0048   }
0049 }
0050 
0051 void SingleZdcTriggerInput::FillPool(const unsigned int keep)
0052 {
0053   if (AllDone())  // no more files and all events read
0054   {
0055     return;
0056   }
0057   while (GetEventiterator() == nullptr)  // at startup this is a null pointer
0058   {
0059     if (!OpenNextFile())
0060     {
0061       AllDone(1);
0062       return;
0063     }
0064   }
0065   while (GetSomeMoreEvents(keep))
0066   {
0067     std::unique_ptr<Event> evt(GetEventiterator()->getNextEvent());
0068     while (!evt)
0069     {
0070       fileclose();
0071       if (!OpenNextFile())
0072       {
0073         AllDone(1);
0074         return;
0075       }
0076       evt.reset(GetEventiterator()->getNextEvent());
0077     }
0078     if (Verbosity() > 2)
0079     {
0080       std::cout << PHWHERE << "Fetching next Event" << evt->getEvtSequence() << std::endl;
0081     }
0082     RunNumber(evt->getRunNumber());
0083     if (GetVerbosity() > 1)
0084     {
0085       evt->identify();
0086     }
0087     if (evt->getEvtType() != DATAEVENT)
0088     {
0089       m_NumSpecialEvents++;
0090       continue;
0091     }
0092     int EventSequence = evt->getEvtSequence();
0093     if (EventSequence < SkipToEvent())
0094     {
0095       continue;
0096     }
0097     std::vector<Packet *> pktvec = evt->getPacketVector();
0098     for (auto packet : pktvec)
0099     {
0100       int packet_id = packet->getIdentifier();
0101       // The call to  EventNumberOffset(identifier) will initialize it to our default if it wasn't set already
0102       // if we encounter a misalignemt, the Fun4AllPrdfInputTriggerManager will adjust this. But the event
0103       // number of the adjustment depends on its pooldepth. Events in its pools will be moved to the correct slots
0104       // and only when the pool gets refilled, this correction kicks in
0105       // SO DO NOT BE CONFUSED when printing this out - seeing different events where this kicks in
0106       int CorrectedEventSequence = EventSequence + EventNumberOffset(packet_id);
0107       if (Verbosity() > 2)
0108       {
0109         packet->identify();
0110       }
0111 
0112       CaloPacket *newhit = new CaloPacketv1();
0113       int nr_modules = packet->iValue(0, "NRMODULES");
0114       int nr_channels = packet->iValue(0, "CHANNELS");
0115       int nr_samples = packet->iValue(0, "SAMPLES");
0116       if (nr_modules > newhit->getMaxNumModules())
0117       {
0118         std::cout << PHWHERE << " too many modules " << nr_modules << ", max is "
0119                   << newhit->getMaxNumModules() << ", need to adjust arrays" << std::endl;
0120         gSystem->Exit(1);
0121       }
0122       if (nr_channels > newhit->getMaxNumChannels())
0123       {
0124         std::cout << PHWHERE << " too many channels " << nr_channels << ", max is "
0125                   << newhit->getMaxNumChannels() << ", need to adjust arrays" << std::endl;
0126         gSystem->Exit(1);
0127       }
0128       if (nr_samples > newhit->getMaxNumSamples())
0129       {
0130         std::cout << PHWHERE << " too many samples " << nr_samples << ", max is "
0131                   << newhit->getMaxNumSamples() << ", need to adjust arrays" << std::endl;
0132         gSystem->Exit(1);
0133       }
0134 
0135       uint64_t gtm_bco = packet->lValue(0, "CLOCK");
0136       newhit->setNrModules(nr_modules);
0137       newhit->setNrSamples(nr_samples);
0138       newhit->setNrChannels(nr_channels);
0139       newhit->setBCO(gtm_bco);
0140       newhit->setPacketEvtSequence(packet->iValue(0, "EVTNR"));
0141       newhit->setIdentifier(packet_id);
0142       newhit->setHitFormat(packet->getHitFormat());
0143       newhit->setEvtSequence(CorrectedEventSequence);
0144       newhit->setEvenChecksum(packet->iValue(0, "EVENCHECKSUM"));
0145       newhit->setCalcEvenChecksum(packet->iValue(0, "CALCEVENCHECKSUM"));
0146       newhit->setOddChecksum(packet->iValue(0, "ODDCHECKSUM"));
0147       newhit->setCalcOddChecksum(packet->iValue(0, "CALCODDCHECKSUM"));
0148       newhit->setModuleAddress(packet->iValue(0, "MODULEADDRESS"));
0149       newhit->setDetId(packet->iValue(0, "DETID"));
0150       for (int ifem = 0; ifem < nr_modules; ifem++)
0151       {
0152         newhit->setFemClock(ifem, packet->iValue(ifem, "FEMCLOCK"));
0153         newhit->setFemEvtSequence(ifem, packet->iValue(ifem, "FEMEVTNR"));
0154         newhit->setFemSlot(ifem, packet->iValue(ifem, "FEMSLOT"));
0155         newhit->setChecksumLsb(ifem, packet->iValue(ifem, "CHECKSUMLSB"));
0156         newhit->setChecksumMsb(ifem, packet->iValue(ifem, "CHECKSUMMSB"));
0157         newhit->setCalcChecksumLsb(ifem, packet->iValue(ifem, "CALCCHECKSUMLSB"));
0158         newhit->setCalcChecksumMsb(ifem, packet->iValue(ifem, "CALCCHECKSUMMSB"));
0159       }
0160       for (int ipmt = 0; ipmt < nr_channels; ipmt++)
0161       {
0162         // store pre/post only for suppressed channels, the array in the packet routines is not
0163         // initialized so reading pre/post for not zero suppressed channels returns garbage
0164         bool isSuppressed = packet->iValue(ipmt, "SUPPRESSED");
0165         newhit->setSuppressed(ipmt, isSuppressed);
0166         if (isSuppressed)
0167         {
0168           newhit->setPre(ipmt, packet->iValue(ipmt, "PRE"));
0169           newhit->setPost(ipmt, packet->iValue(ipmt, "POST"));
0170         }
0171         else
0172         {
0173           for (int isamp = 0; isamp < nr_samples; isamp++)
0174           {
0175             newhit->setSample(ipmt, isamp, packet->iValue(isamp, ipmt));
0176           }
0177         }
0178       }
0179       if (Verbosity() > 2)
0180       {
0181         std::cout << PHWHERE << "corrected evtno: " << CorrectedEventSequence
0182                   << ", original evtno: " << EventSequence
0183                   << ", bco: 0x" << std::hex << gtm_bco << std::dec
0184                   << std::endl;
0185       }
0186       if (packet_id == std::clamp(packet_id, 9000, 9999))
0187       {
0188         m_LocalPacketMap[CorrectedEventSequence].push_back(newhit);
0189       }
0190       else
0191       {
0192         m_LocalPacketMap_Unchecked[CorrectedEventSequence].push_back(newhit);
0193       }
0194       m_EventStack.insert(CorrectedEventSequence);
0195       if (ddump_enabled())
0196       {
0197         ddumppacket(packet);
0198       }
0199       delete packet;
0200     }
0201     if (m_LocalPacketMap.size() >= LocalPoolDepth())
0202     {
0203       CheckFEMEventNumber();
0204     }
0205     while (m_LocalPacketMap.size() > LocalPoolDepth())
0206     {
0207       std::set<int> events;
0208       auto nh = m_LocalPacketMap.begin()->second;
0209       //      std::cout << "Pushing event " << m_LocalPacketMap.begin()->first << " from local packet map to packet map" << std::endl;
0210       events.insert(m_LocalPacketMap.begin()->first);
0211       m_PacketMap[m_LocalPacketMap.begin()->first] = std::move(nh);
0212       m_LocalPacketMap.erase(m_LocalPacketMap.begin());
0213       // copy reference bco if we have a FEM problem
0214       if (FEMClockProblemFlag())
0215       {
0216         std::vector<OfflinePacket *> badpackets;
0217         uint64_t refbco = std::numeric_limits<uint64_t>::max();
0218         uint64_t fallbackrefbco = std::numeric_limits<uint64_t>::max();
0219         for (const auto &iter : m_PacketMap)
0220         {
0221           if (events.find(iter.first) == events.end())
0222           {
0223             //      std::cout << "event " << iter.first << " already bco treated" << std::endl;
0224             continue;
0225           }
0226           for (auto pktiter : iter.second)
0227           {
0228             if (pktiter->getIdentifier() == ClockReferencePacket())
0229             {
0230               refbco = pktiter->getBCO();
0231             }
0232             else if (m_BadBCOPacketSet.find(pktiter->getIdentifier()) == m_BadBCOPacketSet.end())
0233             {
0234               fallbackrefbco = pktiter->getBCO();  // all bcos are identical so we can pcik any for fallback
0235             }
0236             else
0237             {
0238               //          std::cout << "found bad packet " << pktiter->getIdentifier() << std::endl;
0239               badpackets.push_back(pktiter);
0240             }
0241           }
0242           if (refbco == std::numeric_limits<uint64_t>::max())
0243           {
0244             static int count = 0;
0245             if (count < 1000)
0246             {
0247               std::cout << PHWHERE << ": crap that didn't work, could not locate reference packet" << std::endl;
0248               count++;
0249             }
0250             refbco = fallbackrefbco;
0251           }
0252           for (auto pktiter : badpackets)
0253           {
0254             if (Verbosity() > 2)
0255             {
0256               std::cout << "event " << iter.first << " Setting packet " << pktiter->getIdentifier() << " to bco " << std::hex
0257                         << refbco << std::dec << std::endl;
0258             }
0259             pktiter->setBCO(refbco);
0260           }
0261         }
0262       }
0263     }
0264     while (m_LocalPacketMap_Unchecked.size() > LocalPoolDepth())
0265     {
0266       auto &pktmapiter = m_LocalPacketMap_Unchecked.begin()->second;
0267       for (auto packet : pktmapiter)
0268       {
0269         m_PacketMap[m_LocalPacketMap_Unchecked.begin()->first].push_back(packet);
0270       }
0271       pktmapiter.clear();
0272       m_LocalPacketMap_Unchecked.erase(m_LocalPacketMap_Unchecked.begin());
0273     }
0274     //    Print("PACKETMAP");
0275     if (TriggerInputManager())
0276     {
0277       for (const auto &evtiter : m_PacketMap)
0278       {
0279         for (auto pktiter : evtiter.second)
0280         {
0281           CaloPacket *calpacket = dynamic_cast<CaloPacket *>(pktiter);
0282           if (calpacket)
0283           {
0284             int packet_id = calpacket->getIdentifier();
0285             if (packet_id == std::clamp(packet_id, 9000, 9999))
0286             {
0287               TriggerInputManager()->AddSEpdPacket(evtiter.first, calpacket);
0288             }
0289             else
0290             {
0291               TriggerInputManager()->AddZdcPacket(evtiter.first, calpacket);
0292             }
0293           }
0294           else
0295           {
0296             static int count = 0;
0297             if (count < 1000)
0298             {
0299               std::cout << PHWHERE << " dynamic cast from offline to calo packet failed??? here is its identify():" << std::endl;
0300               count++;
0301             }
0302             pktiter->identify();
0303           }
0304         }
0305       }
0306     }
0307   }
0308 }
0309 
0310 void SingleZdcTriggerInput::Print(const std::string &what) const
0311 {
0312   if (what == "ALL" || what == "STORAGE")
0313   {
0314     for (const auto &bcliter : m_PacketMap)
0315     {
0316       std::cout << PHWHERE << "Event: " << bcliter.first << std::endl;
0317     }
0318   }
0319   if (what == "ALL" || what == "STACK")
0320   {
0321     for (auto iter : m_EventStack)
0322     {
0323       std::cout << PHWHERE << "stacked event: " << iter << std::endl;
0324     }
0325   }
0326   if (what == "LOCALMAP")
0327   {
0328     std::cout << "START OF LOCALMAP PRINTOUT" << std::endl;
0329     for (auto &iter : m_LocalPacketMap)
0330     {
0331       std::cout << "LocalMap Event " << iter.first << std::endl;
0332       for (auto pktiter : iter.second)
0333       {
0334         std::cout << "Packet " << pktiter->getIdentifier()
0335                   << ", BCO: " << std::hex << pktiter->getBCO() << std::dec
0336                   << ", FEM: " << std::hex << pktiter->iValue(0, "FEMCLOCK") << std::dec
0337                   << ", EVTNR: " << pktiter->iValue(0, "FEMEVTNR") << std::endl;
0338       }
0339       std::cout << "END OF LOCALMAP PRINTOUT" << std::endl;
0340     }
0341   }
0342   if (what == "PACKETMAP")
0343   {
0344     std::cout << "START OF PACKETMAP PRINTOUT" << std::endl;
0345     for (auto &iter : m_PacketMap)
0346     {
0347       std::cout << "PacketMap Event " << iter.first << std::endl;
0348       for (auto pktiter : iter.second)
0349       {
0350         std::cout << "Packet " << pktiter->getIdentifier()
0351                   << ", BCO: " << std::hex << pktiter->getBCO() << std::dec
0352                   << ", FEM: " << std::hex << pktiter->iValue(0, "FEMCLOCK") << std::dec
0353                   << ", EVTNR: " << pktiter->iValue(0, "FEMEVTNR") << std::endl;
0354       }
0355     }
0356     std::cout << "END OF PACKETMAP PRINTOUT" << std::endl;
0357   }
0358 }
0359 
0360 void SingleZdcTriggerInput::CleanupUsedLocalPackets(const int eventno)
0361 {
0362   std::vector<int> toclearevents;
0363   for (const auto &iter : m_LocalPacketMap)
0364   {
0365     if (iter.first <= eventno)
0366     {
0367       for (auto pktiter : iter.second)
0368       {
0369         delete pktiter;
0370       }
0371       toclearevents.push_back(iter.first);
0372     }
0373     else
0374     {
0375       break;
0376     }
0377   }
0378   for (auto iter : toclearevents)
0379   {
0380     // std::set::erase returns number of elements deleted if the key does not exist, it just returns 0
0381     m_EventStack.erase(iter);
0382     m_LocalPacketMap.erase(iter);
0383   }
0384   toclearevents.clear();
0385   for (const auto &iter : m_LocalPacketMap_Unchecked)
0386   {
0387     if (iter.first <= eventno)
0388     {
0389       for (auto pktiter : iter.second)
0390       {
0391         delete pktiter;
0392       }
0393       toclearevents.push_back(iter.first);
0394     }
0395     else
0396     {
0397       break;
0398     }
0399   }
0400   for (auto iter : toclearevents)
0401   {
0402     // std::set::erase returns number of elements deleted if the key does not exist, it just returns 0
0403     m_EventStack.erase(iter);
0404     m_LocalPacketMap_Unchecked.erase(iter);
0405   }
0406 }
0407 
0408 void SingleZdcTriggerInput::CleanupUsedPackets(const int eventno)
0409 {
0410   std::vector<int> toclearevents;
0411   for (const auto &iter : m_PacketMap)
0412   {
0413     if (iter.first <= eventno)
0414     {
0415       if (Verbosity() > 1)
0416       {
0417         std::cout << "Deleting event " << iter.first << " from zdc input mgr" << std::endl;
0418       }
0419       for (auto pktiter : iter.second)
0420       {
0421         if (Verbosity() > 1)
0422         {
0423           std::cout << "Deleting packet " << pktiter->getIdentifier() << std::endl;
0424         }
0425         delete pktiter;
0426       }
0427       toclearevents.push_back(iter.first);
0428     }
0429     else
0430     {
0431       break;
0432     }
0433   }
0434 
0435   for (auto iter : toclearevents)
0436   {
0437     // std::set::erase returns number of elements deleted if the key does not exist, it just returns 0
0438     m_EventStack.erase(iter);
0439     m_PacketMap.erase(iter);
0440   }
0441 }
0442 
0443 void SingleZdcTriggerInput::ClearCurrentEvent()
0444 {
0445   // called interactively, to get rid of the current event
0446   int currentevent = *m_EventStack.begin();
0447   //  std::cout << PHWHERE << "clearing bclk 0x" << std::hex << currentbclk << std::dec << std::endl;
0448   CleanupUsedPackets(currentevent);
0449   return;
0450 }
0451 
0452 void SingleZdcTriggerInput::CreateDSTNode(PHCompositeNode *topNode)
0453 {
0454   PHNodeIterator iter(topNode);
0455   PHCompositeNode *dstNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "DST"));
0456   if (!dstNode)
0457   {
0458     dstNode = new PHCompositeNode("DST");
0459     topNode->addNode(dstNode);
0460   }
0461   PHNodeIterator iterDst(dstNode);
0462   PHCompositeNode *detNode = dynamic_cast<PHCompositeNode *>(iterDst.findFirst("PHCompositeNode", "ZDC"));
0463   if (!detNode)
0464   {
0465     detNode = new PHCompositeNode("ZDC");
0466     dstNode->addNode(detNode);
0467   }
0468   CaloPacketContainer *zdcpacketcont = findNode::getClass<CaloPacketContainer>(detNode, "ZDCPackets");
0469   if (!zdcpacketcont)
0470   {
0471     zdcpacketcont = new CaloPacketContainerv1();
0472     PHIODataNode<PHObject> *newNode = new PHIODataNode<PHObject>(zdcpacketcont, "ZDCPackets", "PHObject");
0473     detNode->addNode(newNode);
0474   }
0475   detNode = dynamic_cast<PHCompositeNode *>(iterDst.findFirst("PHCompositeNode", "SEPD"));
0476   if (!detNode)
0477   {
0478     detNode = new PHCompositeNode("SEPD");
0479     dstNode->addNode(detNode);
0480   }
0481   CaloPacketContainer *sepdpacketcont = findNode::getClass<CaloPacketContainer>(detNode, "SEPDPackets");
0482   if (!sepdpacketcont)
0483   {
0484     sepdpacketcont = new CaloPacketContainerv1();
0485     PHIODataNode<PHObject> *newNode = new PHIODataNode<PHObject>(sepdpacketcont, "SEPDPackets", "PHObject");
0486     detNode->addNode(newNode);
0487   }
0488 }
0489 
0490 int SingleZdcTriggerInput::ShiftEvents(int pktid, int offset)
0491 {
0492   std::vector<int> eventnumbers;
0493   for (auto pktmapiter = m_LocalPacketMap.rbegin(); pktmapiter != m_LocalPacketMap.rend(); ++pktmapiter)
0494   {
0495     eventnumbers.push_back(pktmapiter->first);
0496   }
0497   for (auto evtnumiter : eventnumbers)
0498   {
0499     auto &pktmapiter = m_LocalPacketMap[evtnumiter];
0500 
0501     int newevent = evtnumiter + offset;
0502     for (unsigned int i = 0; i < pktmapiter.size(); ++i)
0503     {
0504       auto packet = pktmapiter[i];
0505       if (packet->getIdentifier() == pktid)
0506       {
0507         if (Verbosity() > 1)
0508         {
0509           std::cout << "moving packet " << packet->getIdentifier() << " from position " << i
0510                     << " from event " << evtnumiter << " to event " << newevent << std::endl;
0511         }
0512         auto bcotmpiter = m_EventRefBCO.find(newevent);
0513         if (bcotmpiter != m_EventRefBCO.end())
0514         {
0515           packet->setBCO(bcotmpiter->second);
0516         }
0517         else
0518         {
0519           packet->setBCO(std::numeric_limits<uint64_t>::max());
0520         }
0521 
0522         m_LocalPacketMap[newevent].push_back(packet);
0523         pktmapiter.erase(pktmapiter.begin() + i);
0524         break;
0525       }
0526     }
0527     if (Verbosity() > 1)
0528     {
0529       for (auto iter : m_LocalPacketMap[evtnumiter])
0530       {
0531         std::cout << "local packetmap after erase: " << iter->getIdentifier() << std::endl;
0532       }
0533     }
0534   }
0535   //  Print("LOCALMAP");
0536   return 0;
0537 }
0538 
0539 void SingleZdcTriggerInput::CheckFEMEventNumber()
0540 {
0541   // lets check in the first event if this is actually needed
0542   auto first_event = m_LocalPacketMap.begin();
0543   //    std::cout << "Event " << first_event->first << std::endl;
0544   std::map<int, std::set<int>> pktevtnummap;
0545   int ref_femevtnum = std::numeric_limits<int>::max();
0546   std::map<int, unsigned int> evtnumcount;
0547   for (auto pktiter : first_event->second)
0548   {
0549     //      std::cout << "packet id: " << pktiter->getIdentifier() << " size: " <<  first_event->second.size() << std::endl;
0550     std::set<int> femevtnumset;
0551     for (int i = 0; i < pktiter->iValue(0, "NRMODULES"); i++)
0552     {
0553       int femevtnum = pktiter->iValue(i, "FEMEVTNR");
0554       evtnumcount[femevtnum]++;
0555       if (Verbosity() > 21)
0556       {
0557         std::cout << "packet id: " << pktiter->getIdentifier() << " packet clock: 0x" << std::hex << pktiter->iValue(0, "CLOCK")
0558                   << " FEM EvtNo: " << std::dec << femevtnum << std::endl;
0559       }
0560       femevtnumset.insert(femevtnum);
0561       if (ref_femevtnum == std::numeric_limits<int>::max())
0562       {
0563         ref_femevtnum = femevtnum;
0564       }
0565       else
0566       {
0567         if (ref_femevtnum != femevtnum)
0568         {
0569           if (Verbosity() > 1)
0570           {
0571             std::cout << "Event " << first_event->first << " FEM Event Number mismatch for packet " << pktiter->getIdentifier() << std::endl;
0572             std::cout << "ref fem evt: " << ref_femevtnum << ", femevtnum: "
0573                       << femevtnum << std::endl;
0574           }
0575         }
0576       }
0577       if (femevtnumset.size() > 1)
0578       {
0579         static int count = 0;
0580         if (count < 1000)
0581         {
0582           std::cout << PHWHERE << " FEM Event Numbers differ for packet " << pktiter->getIdentifier()
0583                     << ", found " << femevtnumset.size() << " different ones" << std::endl;
0584           for (auto &iter : femevtnumset)
0585           {
0586             std::cout << iter << std::endl;
0587           }
0588           count++;
0589         }
0590       }
0591     }
0592     pktevtnummap[*femevtnumset.begin()].insert(pktiter->getIdentifier());
0593   }
0594   //    std::cout << "Map size " << evtnumcount.size() << std::endl;
0595   if (evtnumcount.size() < 2)
0596   {
0597     //      std::cout << "all good" << std::endl;
0598     return;
0599   }
0600   static int count = 0;
0601   if (count < 1000)
0602   {
0603     std::cout << PHWHERE << " FEM clocks are off, found " << evtnumcount.size() << " different ones, here we go ..." << std::endl;
0604     count++;
0605   }
0606   // set our FEM Clock Problem flag, since we need to copy clocks in the Fill loop
0607   SetFEMClockProblemFlag();
0608   // find good bco (which will give us the haystack) and bad packets
0609   if (Verbosity() > 1)
0610   {
0611     std::cout << "LocalPacketMap size: " << m_LocalPacketMap.size()
0612               << ", pool depth: " << LocalPoolDepth() << std::endl;
0613   }
0614   if (m_LocalPacketMap.size() < LocalPoolDepth())
0615   {
0616     // std::cout << "cache is not deep enough, this should never happen, size of local packet map: "
0617     //      << m_LocalPacketMap.size() << ", pool depth: " << LocalPoolDepth() << std::endl;
0618     return;
0619   }
0620   // first find the reference bco (majority of packets until I get the Master from JeaBeom
0621   int goodfemevtnum = std::numeric_limits<int>::max();
0622   unsigned int maxnumpackets = 0;
0623   for (auto bcoiter : evtnumcount)
0624   {
0625     if (bcoiter.second > maxnumpackets)
0626     {
0627       maxnumpackets = bcoiter.second;
0628       goodfemevtnum = bcoiter.first;
0629     }
0630     //  std::cout << "bco 0x" << std::hex << bcoiter.first << " shows up " << std::dec << bcoiter.second << std::endl;
0631   }
0632   int refpacketid = *pktevtnummap.find(goodfemevtnum)->second.begin();
0633   if (Verbosity() > 1)
0634   {
0635     std::cout << "Use packet " << refpacketid << " for reference bco 0x"
0636               << std::hex << goodfemevtnum << std::dec << std::endl;
0637   }
0638   SetClockReferencePacket(refpacketid);
0639   pktevtnummap.erase(goodfemevtnum);
0640   for (const auto &badpktmapiter : pktevtnummap)
0641   {
0642     for (auto badpktiter : badpktmapiter.second)
0643     {
0644       //       std::cout << "bad packet " << badpktiter << std::endl;
0645       if (TriggerInputManager())
0646       {
0647         TriggerInputManager()->AddFEMProblemPacket(badpktiter);
0648       }
0649       m_BadBCOPacketSet.insert(badpktiter);
0650     }
0651   }
0652   std::vector<int> HayStack;
0653   std::map<int, std::vector<int>> NeedleMap;
0654   m_EventRefBCO.clear();  // this is used if we need to reshuffle the BCO
0655   for (auto &iter : m_LocalPacketMap)
0656   {
0657     //    std::cout << "handling Event " << iter->first << std::endl;
0658     for (auto pktiter : iter.second)
0659     {
0660       if (pktiter->getIdentifier() == refpacketid)
0661       {
0662         // just pick the first one, we have already checked that they are identical
0663         int femevtnum = pktiter->iValue(0, "FEMEVTNR");
0664         HayStack.push_back(femevtnum);
0665         m_EventRefBCO[iter.first] = pktiter->getBCO();
0666       }
0667       else if (m_BadBCOPacketSet.find(pktiter->getIdentifier()) != m_BadBCOPacketSet.end())
0668       {
0669         int femevtnum = pktiter->iValue(0, "FEMEVTNR");
0670         NeedleMap[pktiter->getIdentifier()].push_back(femevtnum);
0671       }
0672     }
0673   }
0674   if (Verbosity() > 1)
0675   {
0676     for (auto evtno : HayStack)
0677     {
0678       std::cout << "Haystack : " << evtno << std::endl;
0679     }
0680   }
0681   for (const auto &needleiter : NeedleMap)
0682   {
0683     std::vector needle = needleiter.second;
0684     needle.pop_back();
0685     if (Verbosity() > 1)
0686     {
0687       std::cout << "Packet " << needleiter.first << std::endl;
0688       for (auto evtno : needle)
0689       {
0690         std::cout << "Needle: " << evtno << std::endl;
0691       }
0692     }
0693     auto it = std::search(HayStack.begin(), HayStack.end(), needle.begin(), needle.end());
0694     if (it != HayStack.end())  // found the needle in the haystack at offset position
0695     {
0696       int position = std::distance(HayStack.begin(), it);
0697       //     std::cout << "found needle at " << position << std::endl;
0698       AdjustEventNumberOffset(needleiter.first, position);
0699       ShiftEvents(needleiter.first, position);
0700     }
0701   }
0702   return;
0703 }