Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:16:15

0001 #include "SingleHcalTriggerInput.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 SingleHcalTriggerInput::SingleHcalTriggerInput(const std::string &name)
0033   : SingleTriggerInput(name)
0034 {
0035   SubsystemEnum(InputManagerType::HCAL);
0036   LocalPoolDepth(3);
0037 }
0038 
0039 SingleHcalTriggerInput::~SingleHcalTriggerInput()
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 SingleHcalTriggerInput::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 (zero) 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       // by default use previous bco clock for gtm bco
0113       CaloPacket *newhit = new CaloPacketv1();
0114       int nr_modules = packet->iValue(0, "NRMODULES");
0115       int nr_channels = packet->iValue(0, "CHANNELS");
0116       int nr_samples = packet->iValue(0, "SAMPLES");
0117       if (nr_modules > newhit->getMaxNumModules())
0118       {
0119         std::cout << PHWHERE << " too many modules " << nr_modules << ", max is "
0120                   << newhit->getMaxNumModules() << ", need to adjust arrays" << std::endl;
0121         gSystem->Exit(1);
0122       }
0123       if (nr_channels > newhit->getMaxNumChannels())
0124       {
0125         std::cout << PHWHERE << " too many channels " << nr_channels << ", max is "
0126                   << newhit->getMaxNumChannels() << ", need to adjust arrays" << std::endl;
0127         gSystem->Exit(1);
0128       }
0129       if (nr_samples > newhit->getMaxNumSamples())
0130       {
0131         std::cout << PHWHERE << " too many samples " << nr_samples << ", max is "
0132                   << newhit->getMaxNumSamples() << ", need to adjust arrays" << std::endl;
0133         gSystem->Exit(1);
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(EventSequence);
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       m_LocalPacketMap[CorrectedEventSequence].push_back(newhit);
0187       m_EventStack.insert(CorrectedEventSequence);
0188       if (ddump_enabled())
0189       {
0190         ddumppacket(packet);
0191       }
0192       delete packet;
0193     }
0194     if (m_LocalPacketMap.size() >= LocalPoolDepth())
0195     {
0196       CheckFEMEventNumber();
0197     }
0198     while (m_LocalPacketMap.size() > LocalPoolDepth())
0199     {
0200       std::set<int> events;
0201       auto nh = m_LocalPacketMap.begin()->second;
0202       //      std::cout << "Pushing event " << m_LocalPacketMap.begin()->first << " from local packet map to packet map" << std::endl;
0203       events.insert(m_LocalPacketMap.begin()->first);
0204       m_PacketMap[m_LocalPacketMap.begin()->first] = std::move(nh);
0205       m_LocalPacketMap.erase(m_LocalPacketMap.begin());
0206       // copy reference bco if we have a FEM problem
0207       if (FEMClockProblemFlag())
0208       {
0209         std::vector<OfflinePacket *> badpackets;
0210         uint64_t refbco = std::numeric_limits<uint64_t>::max();
0211         uint64_t fallbackrefbco = std::numeric_limits<uint64_t>::max();
0212         for (const auto &iter : m_PacketMap)
0213         {
0214           if (events.find(iter.first) == events.end())
0215           {
0216             //      std::cout << "event " << iter.first << " already bco treated" << std::endl;
0217             continue;
0218           }
0219           for (auto pktiter : iter.second)
0220           {
0221             if (pktiter->getIdentifier() == ClockReferencePacket())
0222             {
0223               refbco = pktiter->getBCO();
0224             }
0225             else if (m_BadBCOPacketSet.find(pktiter->getIdentifier()) == m_BadBCOPacketSet.end())
0226             {
0227               fallbackrefbco = pktiter->getBCO();  // all bcos are identical so we can pcik any for fallback
0228             }
0229             else
0230             {
0231               //          std::cout << "found bad packet " << pktiter->getIdentifier() << std::endl;
0232               badpackets.push_back(pktiter);
0233             }
0234           }
0235           if (refbco == std::numeric_limits<uint64_t>::max())
0236           {
0237             static int count = 0;
0238             if (count < 1000)
0239             {
0240               std::cout << PHWHERE << ": crap that didn't work, could not locate reference packet" << std::endl;
0241               count++;
0242             }
0243             refbco = fallbackrefbco;
0244           }
0245           for (auto pktiter : badpackets)
0246           {
0247             if (Verbosity() > 2)
0248             {
0249               std::cout << "event " << iter.first << " Setting packet " << pktiter->getIdentifier() << " to bco " << std::hex
0250                         << refbco << std::dec << std::endl;
0251             }
0252             pktiter->setBCO(refbco);
0253           }
0254         }
0255       }
0256     }
0257     //    Print("PACKETMAP");
0258     if (TriggerInputManager())
0259     {
0260       for (const auto &evtiter : m_PacketMap)
0261       {
0262         for (auto pktiter : evtiter.second)
0263         {
0264           CaloPacket *calpacket = dynamic_cast<CaloPacket *>(pktiter);
0265           if (calpacket)
0266           {
0267             //      std::cout << "pushing event " << evtiter.first << " to combiner" << std::endl;
0268             TriggerInputManager()->AddHcalPacket(evtiter.first, calpacket);
0269           }
0270           else
0271           {
0272             static int count = 0;
0273             if (count < 1000)
0274             {
0275               std::cout << PHWHERE << " dynamic cast from offline to calo packet failed??? here is its identify():" << std::endl;
0276               count++;
0277             }
0278             pktiter->identify();
0279           }
0280         }
0281       }
0282     }
0283   }
0284 }
0285 
0286 void SingleHcalTriggerInput::Print(const std::string &what) const
0287 {
0288   if (what == "ALL" || what == "STORAGE")
0289   {
0290     for (const auto &bcliter : m_PacketMap)
0291     {
0292       std::cout << PHWHERE << "Event: " << bcliter.first << std::endl;
0293     }
0294   }
0295   if (what == "ALL" || what == "STACK")
0296   {
0297     for (auto iter : m_EventStack)
0298     {
0299       std::cout << PHWHERE << "stacked event: " << iter << std::endl;
0300     }
0301   }
0302   if (what == "LOCALMAP")
0303   {
0304     for (auto &iter : m_LocalPacketMap)
0305     {
0306       std::cout << "LocalMap Event " << iter.first << std::endl;
0307       for (auto pktiter : iter.second)
0308       {
0309         std::cout << "Packet " << pktiter->getIdentifier()
0310                   << ", BCO: " << std::hex << pktiter->getBCO() << std::dec
0311                   << ", FEM: " << std::hex << pktiter->iValue(0, "FEMCLOCK") << std::dec << std::endl;
0312       }
0313     }
0314   }
0315   if (what == "PACKETMAP")
0316   {
0317     for (auto &iter : m_PacketMap)
0318     {
0319       std::cout << "PacketMap Event " << iter.first << std::endl;
0320       for (auto pktiter : iter.second)
0321       {
0322         std::cout << "Packet " << pktiter->getIdentifier()
0323                   << ", BCO: " << std::hex << pktiter->getBCO() << std::dec
0324                   << ", FEM: " << std::hex << pktiter->iValue(0, "FEMCLOCK") << std::dec << std::endl;
0325       }
0326     }
0327   }
0328 }
0329 
0330 void SingleHcalTriggerInput::CleanupUsedLocalPackets(const int eventno)
0331 {
0332   std::vector<int> toclearevents;
0333   for (const auto &iter : m_LocalPacketMap)
0334   {
0335     if (iter.first <= eventno)
0336     {
0337       for (auto pktiter : iter.second)
0338       {
0339         delete pktiter;
0340       }
0341       toclearevents.push_back(iter.first);
0342     }
0343     else
0344     {
0345       break;
0346     }
0347   }
0348   for (auto iter : toclearevents)
0349   {
0350     // std::set::erase returns number of elements deleted if the key does not exist, it just returns 0
0351     m_EventStack.erase(iter);
0352     m_LocalPacketMap.erase(iter);
0353   }
0354 }
0355 
0356 void SingleHcalTriggerInput::CleanupUsedPackets(const int eventno)
0357 {
0358   std::vector<int> toclearevents;
0359   for (const auto &iter : m_PacketMap)
0360   {
0361     if (iter.first <= eventno)
0362     {
0363       for (auto pktiter : iter.second)
0364       {
0365         delete pktiter;
0366       }
0367       toclearevents.push_back(iter.first);
0368     }
0369     else
0370     {
0371       break;
0372     }
0373   }
0374 
0375   for (auto iter : toclearevents)
0376   {
0377     // std::set::erase returns number of elements deleted if the key does not exist, it just returns 0
0378     m_EventStack.erase(iter);
0379     m_PacketMap.erase(iter);
0380   }
0381 }
0382 
0383 void SingleHcalTriggerInput::ClearCurrentEvent()
0384 {
0385   // called interactively, to get rid of the current event
0386   int currentevent = *m_EventStack.begin();
0387   //  std::cout << PHWHERE << "clearing bclk 0x" << std::hex << currentbclk << std::dec << std::endl;
0388   CleanupUsedPackets(currentevent);
0389   return;
0390 }
0391 
0392 void SingleHcalTriggerInput::CreateDSTNode(PHCompositeNode *topNode)
0393 {
0394   PHNodeIterator iter(topNode);
0395   PHCompositeNode *dstNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "DST"));
0396   if (!dstNode)
0397   {
0398     dstNode = new PHCompositeNode("DST");
0399     topNode->addNode(dstNode);
0400   }
0401   PHNodeIterator iterDst(dstNode);
0402   PHCompositeNode *detNode = dynamic_cast<PHCompositeNode *>(iterDst.findFirst("PHCompositeNode", "HCAL"));
0403   if (!detNode)
0404   {
0405     detNode = new PHCompositeNode("HCAL");
0406     dstNode->addNode(detNode);
0407   }
0408   CaloPacketContainer *hcalpacketcont = findNode::getClass<CaloPacketContainer>(detNode, "HCALPackets");
0409   if (!hcalpacketcont)
0410   {
0411     hcalpacketcont = new CaloPacketContainerv1();
0412     PHIODataNode<PHObject> *newNode = new PHIODataNode<PHObject>(hcalpacketcont, "HCALPackets", "PHObject");
0413     detNode->addNode(newNode);
0414   }
0415 }
0416 void SingleHcalTriggerInput::CheckFEMClock()
0417 {
0418   // lets check in the first event if this is actually needed
0419   auto first_event = m_LocalPacketMap.begin();
0420   //    std::cout << "Event " << first_event->first << std::endl;
0421   std::map<uint64_t, std::set<int>> pktbcomap;
0422   uint64_t ref_femclk = std::numeric_limits<uint64_t>::max();
0423   std::map<uint64_t, unsigned int> bcocount;
0424   for (auto pktiter : first_event->second)
0425   {
0426     //      std::cout << "packet id: " << pktiter->getIdentifier() << " size: " <<  first_event->second.size() << std::endl;
0427     std::set<uint64_t> femclockset;
0428     for (int i = 0; i < pktiter->iValue(0, "NRMODULES"); i++)
0429     {
0430       uint64_t femclk = pktiter->iValue(i, "FEMCLOCK");
0431       bcocount[femclk]++;
0432       if (Verbosity() > 21)
0433       {
0434         std::cout << "packet id: " << pktiter->getIdentifier() << " packet clock: 0x" << std::hex << pktiter->iValue(0, "CLOCK")
0435                   << " FEMClock: 0x" << femclk << std::dec << std::endl;
0436       }
0437       femclockset.insert(femclk);
0438       if (ref_femclk == std::numeric_limits<uint64_t>::max())
0439       {
0440         ref_femclk = femclk;
0441       }
0442       else
0443       {
0444         if (ref_femclk != femclk)
0445         {
0446           if (Verbosity() > 1)
0447           {
0448             std::cout << "Event " << first_event->first << " FEM Clock mismatch for packet " << pktiter->getIdentifier() << std::endl;
0449             std::cout << "ref fem clk: 0x" << std::hex << ref_femclk << ", femclk: 0x"
0450                       << femclk << std::dec << std::endl;
0451           }
0452         }
0453       }
0454       if (femclockset.size() > 1)
0455       {
0456         static int count = 0;
0457         if (count < 1000)
0458         {
0459           std::cout << PHWHERE << " FEM Clocks differ for packet " << pktiter->getIdentifier()
0460                     << ", found " << femclockset.size() << " different ones" << std::endl;
0461           for (auto &iter : femclockset)
0462           {
0463             std::cout << "0x" << std::hex << iter << std::dec << std::endl;
0464           }
0465           count++;
0466         }
0467       }
0468     }
0469     pktbcomap[*femclockset.begin()].insert(pktiter->getIdentifier());
0470   }
0471   //    std::cout << "Map size " << bcocount.size() << std::endl;
0472   if (bcocount.size() < 2)
0473   {
0474     //      std::cout << "all good" << std::endl;
0475     return;
0476   }
0477   static int count = 0;
0478   if (count < 1000)
0479   {
0480     std::cout << PHWHERE << " FEM clocks are off, found " << bcocount.size() << " different ones, here we go ..." << std::endl;
0481     count++;
0482   }
0483   // set our FEM Clock Problem flag, since we need to copy clocks in the Fill loop
0484   SetFEMClockProblemFlag();
0485   // find good bco (which will give us the haystack) and bad packets
0486   if (Verbosity() > 1)
0487   {
0488     std::cout << "LocalPacketMap size: " << m_LocalPacketMap.size()
0489               << ", pool depth: " << LocalPoolDepth() << std::endl;
0490   }
0491   if (m_LocalPacketMap.size() < LocalPoolDepth())
0492   {
0493     // std::cout << "cache is not deep enough, this should never happen, size of local packet map: "
0494     //      << m_LocalPacketMap.size() << ", pool depth: " << LocalPoolDepth() << std::endl;
0495     return;
0496   }
0497   // first find the reference bco (majority of packets until I get the Master from JeaBeom
0498   uint64_t goodfembco = std::numeric_limits<uint64_t>::max();
0499   unsigned int maxnumpackets = 0;
0500   for (auto bcoiter : bcocount)
0501   {
0502     if (bcoiter.second > maxnumpackets)
0503     {
0504       maxnumpackets = bcoiter.second;
0505       goodfembco = bcoiter.first;
0506     }
0507     //  std::cout << "bco 0x" << std::hex << bcoiter.first << " shows up " << std::dec << bcoiter.second << std::endl;
0508   }
0509   int refpacketid = *pktbcomap.find(goodfembco)->second.begin();
0510   if (Verbosity() > 1)
0511   {
0512     std::cout << "Use packet " << refpacketid << " for reference bco 0x"
0513               << std::hex << goodfembco << std::dec << std::endl;
0514   }
0515   SetClockReferencePacket(refpacketid);
0516   pktbcomap.erase(goodfembco);
0517   for (const auto &badpktmapiter : pktbcomap)
0518   {
0519     for (auto badpktiter : badpktmapiter.second)
0520     {
0521       //       std::cout << "bad packet " << badpktiter << std::endl;
0522       if (TriggerInputManager())
0523       {
0524         TriggerInputManager()->AddFEMProblemPacket(badpktiter);
0525       }
0526       m_BadBCOPacketSet.insert(badpktiter);
0527     }
0528   }
0529   std::vector<uint64_t> HayStack;
0530   std::map<int, std::vector<uint64_t>> NeedleMap;
0531   m_EventRefBCO.clear();  // this is used if we need to reshuffle the BCO
0532   for (auto &iter : m_LocalPacketMap)
0533   {
0534     //    std::cout << "handling Event " << iter->first << std::endl;
0535     for (auto pktiter : iter.second)
0536     {
0537       if (pktiter->getIdentifier() == refpacketid)
0538       {
0539         // just pick the first one, we have already checked that they are identical
0540         uint64_t femclk = pktiter->iValue(0, "FEMCLOCK");
0541         HayStack.push_back(femclk);
0542         m_EventRefBCO[iter.first] = pktiter->getBCO();
0543       }
0544       else if (m_BadBCOPacketSet.find(pktiter->getIdentifier()) != m_BadBCOPacketSet.end())
0545       {
0546         uint64_t femclk = pktiter->iValue(0, "FEMCLOCK");
0547         NeedleMap[pktiter->getIdentifier()].push_back(femclk);
0548       }
0549     }
0550   }
0551   if (Verbosity() > 1)
0552   {
0553     for (auto bco : HayStack)
0554     {
0555       std::cout << "Haystack : 0x" << std::hex << bco << std::dec << std::endl;
0556     }
0557   }
0558   for (const auto &needleiter : NeedleMap)
0559   {
0560     std::vector needle = needleiter.second;
0561     needle.pop_back();
0562     if (Verbosity() > 1)
0563     {
0564       std::cout << "Packet " << needleiter.first << std::endl;
0565       for (auto bco : needle)
0566       {
0567         std::cout << "Needle: 0x" << std::hex << bco << std::dec << std::endl;
0568       }
0569     }
0570     auto it = std::search(HayStack.begin(), HayStack.end(), needle.begin(), needle.end());
0571     if (it != HayStack.end())  // found the needle in the haystack at offset position
0572     {
0573       int position = std::distance(HayStack.begin(), it);
0574       //     std::cout << "found needle at " << position << std::endl;
0575       AdjustEventNumberOffset(needleiter.first, position);
0576       ShiftEvents(needleiter.first, position);
0577     }
0578   }
0579   return;
0580 }
0581 
0582 int SingleHcalTriggerInput::ShiftEvents(int pktid, int offset)
0583 {
0584   std::vector<int> eventnumbers;
0585   for (auto pktmapiter = m_LocalPacketMap.rbegin(); pktmapiter != m_LocalPacketMap.rend(); ++pktmapiter)
0586   {
0587     eventnumbers.push_back(pktmapiter->first);
0588   }
0589   for (auto evtnumiter : eventnumbers)
0590   {
0591     auto &pktmapiter = m_LocalPacketMap[evtnumiter];
0592 
0593     int newevent = evtnumiter + offset;
0594     for (unsigned int i = 0; i < pktmapiter.size(); ++i)
0595     {
0596       auto packet = pktmapiter[i];
0597       if (packet->getIdentifier() == pktid)
0598       {
0599         if (Verbosity() > 1)
0600         {
0601           std::cout << "moving packet " << packet->getIdentifier() << " from position " << i
0602                     << " from event " << evtnumiter << " to event " << newevent << std::endl;
0603         }
0604         auto bcotmpiter = m_EventRefBCO.find(newevent);
0605         if (bcotmpiter != m_EventRefBCO.end())
0606         {
0607           packet->setBCO(bcotmpiter->second);
0608         }
0609         else
0610         {
0611           packet->setBCO(std::numeric_limits<uint64_t>::max());
0612         }
0613 
0614         m_LocalPacketMap[newevent].push_back(packet);
0615         pktmapiter.erase(pktmapiter.begin() + i);
0616         break;
0617       }
0618     }
0619     if (Verbosity() > 1)
0620     {
0621       for (auto iter : m_LocalPacketMap[evtnumiter])
0622       {
0623         std::cout << "local packetmap after erase: " << iter->getIdentifier() << std::endl;
0624       }
0625     }
0626   }
0627   //  Print("LOCALMAP");
0628   return 0;
0629 }
0630 
0631 void SingleHcalTriggerInput::CheckFEMEventNumber()
0632 {
0633   // lets check in the first event if this is actually needed
0634   auto first_event = m_LocalPacketMap.begin();
0635   //    std::cout << "Event " << first_event->first << std::endl;
0636   std::map<int, std::set<int>> pktevtnummap;
0637   int ref_femevtnum = std::numeric_limits<int>::max();
0638   std::map<int, unsigned int> evtnumcount;
0639   for (auto pktiter : first_event->second)
0640   {
0641     //      std::cout << "packet id: " << pktiter->getIdentifier() << " size: " <<  first_event->second.size() << std::endl;
0642     std::set<int> femevtnumset;
0643     for (int i = 0; i < pktiter->iValue(0, "NRMODULES"); i++)
0644     {
0645       int femevtnum = pktiter->iValue(i, "FEMEVTNR");
0646       evtnumcount[femevtnum]++;
0647       if (Verbosity() > 21)
0648       {
0649         std::cout << "packet id: " << pktiter->getIdentifier() << " packet clock: 0x" << std::hex << pktiter->iValue(0, "CLOCK")
0650                   << " FEM EvtNo: " << std::dec << femevtnum << std::endl;
0651       }
0652       femevtnumset.insert(femevtnum);
0653       if (ref_femevtnum == std::numeric_limits<int>::max())
0654       {
0655         ref_femevtnum = femevtnum;
0656       }
0657       else
0658       {
0659         if (ref_femevtnum != femevtnum)
0660         {
0661           if (Verbosity() > 1)
0662           {
0663             std::cout << "Event " << first_event->first << " FEM Event Number  mismatch for packet " << pktiter->getIdentifier() << std::endl;
0664             std::cout << "ref fem evt: " << ref_femevtnum << ", femevtnum: "
0665                       << femevtnum << std::endl;
0666           }
0667         }
0668       }
0669       if (femevtnumset.size() > 1)
0670       {
0671         static int count = 0;
0672         if (count < 1000)
0673         {
0674           std::cout << PHWHERE << " FEM Event Numbers differ for packet " << pktiter->getIdentifier()
0675                     << ", found " << femevtnumset.size() << " different ones" << std::endl;
0676           for (auto &iter : femevtnumset)
0677           {
0678             std::cout << iter << std::endl;
0679           }
0680           count++;
0681         }
0682       }
0683     }
0684     pktevtnummap[*femevtnumset.begin()].insert(pktiter->getIdentifier());
0685   }
0686   //    std::cout << "Map size " << evtnumcount.size() << std::endl;
0687   if (evtnumcount.size() < 2)
0688   {
0689     //      std::cout << "all good" << std::endl;
0690     return;
0691   }
0692   static int count = 0;
0693   if (count < 1000)
0694   {
0695     std::cout << PHWHERE << " FEM clocks are off, found " << evtnumcount.size() << " different ones, here we go ..." << std::endl;
0696     count++;
0697   }
0698   // set our FEM Clock Problem flag, since we need to copy clocks in the Fill loop
0699   SetFEMClockProblemFlag();
0700   // find good bco (which will give us the haystack) and bad packets
0701   if (Verbosity() > 1)
0702   {
0703     std::cout << "LocalPacketMap size: " << m_LocalPacketMap.size()
0704               << ", pool depth: " << LocalPoolDepth() << std::endl;
0705   }
0706   if (m_LocalPacketMap.size() < LocalPoolDepth())
0707   {
0708     // std::cout << "cache is not deep enough, this should never happen, size of local packet map: "
0709     //      << m_LocalPacketMap.size() << ", pool depth: " << LocalPoolDepth() << std::endl;
0710     return;
0711   }
0712   // first find the reference bco (majority of packets until I get the Master from JeaBeom
0713   int goodfemevtnum = std::numeric_limits<int>::max();
0714   unsigned int maxnumpackets = 0;
0715   for (auto bcoiter : evtnumcount)
0716   {
0717     if (bcoiter.second > maxnumpackets)
0718     {
0719       maxnumpackets = bcoiter.second;
0720       goodfemevtnum = bcoiter.first;
0721     }
0722     //  std::cout << "bco 0x" << std::hex << bcoiter.first << " shows up " << std::dec << bcoiter.second << std::endl;
0723   }
0724   int refpacketid = *pktevtnummap.find(goodfemevtnum)->second.begin();
0725   if (Verbosity() > 1)
0726   {
0727     std::cout << "Use packet " << refpacketid << " for reference bco 0x"
0728               << std::hex << goodfemevtnum << std::dec << std::endl;
0729   }
0730   SetClockReferencePacket(refpacketid);
0731   pktevtnummap.erase(goodfemevtnum);
0732   for (const auto &badpktmapiter : pktevtnummap)
0733   {
0734     for (auto badpktiter : badpktmapiter.second)
0735     {
0736       //       std::cout << "bad packet " << badpktiter << std::endl;
0737       if (TriggerInputManager())
0738       {
0739         TriggerInputManager()->AddFEMProblemPacket(badpktiter);
0740       }
0741       m_BadBCOPacketSet.insert(badpktiter);
0742     }
0743   }
0744   std::vector<int> HayStack;
0745   std::map<int, std::vector<int>> NeedleMap;
0746   m_EventRefBCO.clear();  // this is used if we need to reshuffle the BCO
0747   for (auto &iter : m_LocalPacketMap)
0748   {
0749     //    std::cout << "handling Event " << iter->first << std::endl;
0750     for (auto pktiter : iter.second)
0751     {
0752       if (pktiter->getIdentifier() == refpacketid)
0753       {
0754         // just pick the first one, we have already checked that they are identical
0755         int femevtnum = pktiter->iValue(0, "FEMEVTNR");
0756         HayStack.push_back(femevtnum);
0757         m_EventRefBCO[iter.first] = pktiter->getBCO();
0758       }
0759       else if (m_BadBCOPacketSet.find(pktiter->getIdentifier()) != m_BadBCOPacketSet.end())
0760       {
0761         int femevtnum = pktiter->iValue(0, "FEMEVTNR");
0762         NeedleMap[pktiter->getIdentifier()].push_back(femevtnum);
0763       }
0764     }
0765   }
0766   if (Verbosity() > 1)
0767   {
0768     for (auto evtno : HayStack)
0769     {
0770       std::cout << "Haystack : " << evtno << std::endl;
0771     }
0772   }
0773   for (const auto &needleiter : NeedleMap)
0774   {
0775     std::vector needle = needleiter.second;
0776     needle.pop_back();
0777     if (Verbosity() > 1)
0778     {
0779       std::cout << "Packet " << needleiter.first << std::endl;
0780       for (auto evtno : needle)
0781       {
0782         std::cout << "Needle: " << evtno << std::endl;
0783       }
0784     }
0785     auto it = std::search(HayStack.begin(), HayStack.end(), needle.begin(), needle.end());
0786     if (it != HayStack.end())  // found the needle in the haystack at offset position
0787     {
0788       int position = std::distance(HayStack.begin(), it);
0789       //     std::cout << "found needle at " << position << std::endl;
0790       AdjustEventNumberOffset(needleiter.first, position);
0791       ShiftEvents(needleiter.first, position);
0792     }
0793   }
0794   return;
0795 }