Back to home page

sPhenix code displayed by LXR

 
 

    


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

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