diff --git a/offline/framework/fun4allraw/Fun4AllStreamingLumiCountingInputManager.cc b/offline/framework/fun4allraw/Fun4AllStreamingLumiCountingInputManager.cc new file mode 100644 index 0000000000..23b12b4947 --- /dev/null +++ b/offline/framework/fun4allraw/Fun4AllStreamingLumiCountingInputManager.cc @@ -0,0 +1,614 @@ +#include "Fun4AllStreamingLumiCountingInputManager.h" + +#include +#include "SingleStreamingInput.h" + +#include + +#include +#include // for Fun4AllInputManager +#include +#include +#include + +#include // for SyncObject +#include + +#include +#include +#include + +#include // for PHObject +#include +#include // for PHWHERE +#include + +#include +#include +#include +#include + +#include // for max +#include +#include // for uint64_t, uint16_t +#include +#include // for operator<<, basic_ostream, endl +#include // for pair + +Fun4AllStreamingLumiCountingInputManager::Fun4AllStreamingLumiCountingInputManager(const std::string &name, const std::string &dstnodename, const std::string &topnodename) + : Fun4AllInputManager(name, dstnodename, topnodename) + , m_SyncObject(new SyncObjectv1()) +{ + Fun4AllServer *se = Fun4AllServer::instance(); + m_topNode = se->topNode(TopNodeName()); + + createLuminosityHistos(); + return; +} + +Fun4AllStreamingLumiCountingInputManager::~Fun4AllStreamingLumiCountingInputManager() +{ + if (IsOpen()) + { + fileclose(); + } + // std::cout<<"----Write? files to output.root"<Write("", TObject::kOverwrite); + h_lumibco->Write("", TObject::kOverwrite); + h_bunchnumber->Write("", TObject::kOverwrite); + h_bunchnumber_occur->Write("", TObject::kOverwrite); + tfile->Close(); + delete tfile; + */ + return iret; +} + +void Fun4AllStreamingLumiCountingInputManager::SetOutputFileName(const std::string &fileName) +{ + m_outputFileName = fileName; // Update the filename +} + +int Fun4AllStreamingLumiCountingInputManager::fileclose() +{ + // std::cout<<"----fileclose()"<Name() << " reads run " + << iter->RunNumber() + << " from file " << iter->FileName() + << std::endl; + } + } + Fun4AllInputManager::Print(what); + return; +} + +int Fun4AllStreamingLumiCountingInputManager::ResetEvent() +{ + // zhiwan + // m_RefBCO = 0; + return 0; +} + +int Fun4AllStreamingLumiCountingInputManager::PushBackEvents(const int /*i*/) +{ + return 0; +} + +int Fun4AllStreamingLumiCountingInputManager::GetSyncObject(SyncObject **mastersync) +{ + // here we copy the sync object from the current file to the + // location pointed to by mastersync. If mastersync is a 0 pointer + // the syncobject is cloned. If mastersync allready exists the content + // of syncobject is copied + if (!(*mastersync)) + { + if (m_SyncObject) + { + *mastersync = dynamic_cast(m_SyncObject->CloneMe()); + assert(*mastersync); + } + } + else + { + *(*mastersync) = *m_SyncObject; // copy syncobject content + } + return Fun4AllReturnCodes::SYNC_OK; +} + +int Fun4AllStreamingLumiCountingInputManager::SyncIt(const SyncObject *mastersync) +{ + if (!mastersync) + { + std::cout << PHWHERE << Name() << " No MasterSync object, cannot perform synchronization" << std::endl; + std::cout << "Most likely your first file does not contain a SyncObject and the file" << std::endl; + std::cout << "opened by the Fun4AllDstInputManager with Name " << Name() << " has one" << std::endl; + std::cout << "Change your macro and use the file opened by this input manager as first input" << std::endl; + std::cout << "and you will be okay. Fun4All will not process the current configuration" << std::endl + << std::endl; + return Fun4AllReturnCodes::SYNC_FAIL; + } + int iret = m_SyncObject->Different(mastersync); + if (iret) + { + std::cout << "big problem" << std::endl; + exit(1); + } + return Fun4AllReturnCodes::SYNC_OK; +} + +/** + * @brief Lookup handler for named string properties; currently unimplemented and yields no value. + * + * Prints a diagnostic message indicating the requested key and returns an empty string. + * + * @param what Key or name of the requested string property (unused). + * @return std::string `""` (empty string). + */ +std::string Fun4AllStreamingLumiCountingInputManager::GetString(const std::string &what) const +{ + std::cout << PHWHERE << " called with " << what << " , returning empty string" << std::endl; + return ""; +} + +/** + * @brief Register a streaming input with the luminosity counting manager. + * + * Associates the provided streaming input with this manager, configures it for + * streaming operation, and registers it for the specified subsystem. For GL1 + * inputs the DST node is created only when not running in streaming-only mode; + * valid GL1 inputs are stored for later processing. + * + * @param evtin Pointer to the streaming input to register. + * @param system Subsystem identifier specifying how the input is handled (e.g., GL1). + * + * @note If an unsupported subsystem is provided, the function prints an error and terminates the process. + */ +void Fun4AllStreamingLumiCountingInputManager::registerStreamingInput(SingleStreamingInput *evtin, InputManagerType::enu_subsystem system) +{ + evtin->StreamingLumiInputManager(this); + // if the streaming flag is set, we only want the first event from the GL1 to + // get the starting BCO of that run which enables us to dump all the junk which + // is taken before the run starts in the streaming systems. But we don't want the + // GL1 in the output, so we do not create its dst node if running in streaming + if (system == InputManagerType::GL1) + { + if (!m_StreamingFlag) + { + evtin->CreateDSTNode(m_topNode); + } + } + else + { + evtin->CreateDSTNode(m_topNode); + } + evtin->ConfigureStreamingInputManager(); + if (system == InputManagerType::GL1) + { + m_gl1_registered_flag = true; + m_Gl1InputVector.push_back(evtin); + } + else + { + std::cout << "invalid subsystem flag " << system << std::endl; + gSystem->Exit(1); + exit(1); + } + if (Verbosity() > 3) + { + std::cout << "registering " << evtin->Name() + << " number of registered inputs: " + << m_Gl1InputVector.size() + << std::endl; + } + std::cout << m_Gl1InputVector.size() << std::endl; +} + +void Fun4AllStreamingLumiCountingInputManager::AddGl1RawHit(uint64_t bclk, Gl1Packet *hit) +{ + m_Gl1RawHitMap[bclk].Gl1RawHitVector.push_back(hit); +} + +void Fun4AllStreamingLumiCountingInputManager::AddGl1Window(uint64_t bco_trim, int negative_window, int positive_window) +{ + m_BCOWindows[bco_trim] = std::make_pair(bco_trim - negative_window, bco_trim + positive_window); +} + +void Fun4AllStreamingLumiCountingInputManager::AddGl1BunchNumber(uint64_t bco_trim, int bunch_number) +{ + m_BCOBunchNumber[bco_trim] = bunch_number; +} + +int Fun4AllStreamingLumiCountingInputManager::FillGl1() +{ + // unsigned int alldone = 0; + for (auto *iter : m_Gl1InputVector) + { + if (Verbosity() > 0) + { + std::cout << "Fun4AllStreamingLumiCountingInputManager::FillGl1 - fill pool for " << iter->Name() << std::endl; + std::cout << "Run number " << iter->RunNumber() << std::endl; + } + iter->FillPool(); + + if (m_RunNumber == 0) + { + m_RunNumber = iter->RunNumber(); + SetRunNumber(m_RunNumber); + } + else + { + if (m_RunNumber != iter->RunNumber()) + { + std::cout << PHWHERE << " Run Number mismatch, run is " + << m_RunNumber << ", " << iter->Name() << " reads " + << iter->RunNumber() << std::endl; + std::cout << "You are likely reading files from different runs, do not do that" << std::endl; + Print("INPUTFILES"); + gSystem->Exit(1); + exit(1); + } + } + } + + if (Verbosity() > 0) + { + std::cout << "Here BCO " << m_BCOWindows.begin()->first << " left " << m_BCOWindows.begin()->second.first << " right " << m_BCOWindows.begin()->second.second << std::endl; + } + /* + for (const auto &entry : m_BCOWindows) { + uint64_t key = entry.first; + uint64_t valueFirst = entry.second.first; + uint64_t valueSecond = entry.second.second; + std::cout << "Key: " << key + << ", Value First: " << valueFirst + << ", Value Second: " << valueSecond + << std::endl; + } + + for (const auto& [bco_trim, bunch_number] : m_BCOBunchNumber) { + std::cout << "Here BCO " << bco_trim << " Bunch Number " << bunch_number << std::endl; + } + */ + // std::cout << "Here BCO " <first < 1) + { + auto first_element = m_BCOWindows.begin(); + auto second_element = std::next(m_BCOWindows.begin()); + // std::cout<<"Key 1: "<first<<" Value ( "<second.first<<" , "<second.second<first<<" Value ( "<second.first<<" , "<second.second<first - first_element->first<<" compared with window "<< m_negative_bco_window+m_positive_bco_window < 1099511000000, then switch them + m_diffBCO = second_element->first - first_element->first; + + if (second_element->first - first_element->first > 1099510000000) + { + flat_overflow = true; + // int temp_m_diffBCO=first_element->first+1099511627775+1-second_element->first; + bco_temp = first_element->first; + m_BCOWindows.erase(m_BCOWindows.begin()); + bco_temp += 1099511627775 + 1; + m_BCOWindows[bco_temp] = std::make_pair(bco_temp - m_negative_bco_window, bco_temp + m_positive_bco_window); + first_element = m_BCOWindows.begin(); + second_element = std::next(m_BCOWindows.begin()); + m_diffBCO = second_element->first - first_element->first; + std::cout << "overflow new diff " << m_diffBCO << " new first element " << first_element->first << " new second element " << second_element->first << std::endl; + } + h_diffbco->Fill(m_diffBCO); + if (m_diffBCO < static_cast(m_negative_bco_window + m_positive_bco_window)) + { + m_BCOWindows.begin()->second.second = second_element->second.first; + std::cout << "*** new Key 1 BCO " << m_BCOWindows.begin()->first << " left " << m_BCOWindows.begin()->second.first << " right " << m_BCOWindows.begin()->second.second << std::endl; + } + } + + m_bco_trim = m_BCOWindows.begin()->first; + m_lower_bound = m_BCOWindows.begin()->second.first; + m_upper_bound = m_BCOWindows.begin()->second.second; + m_bunch_number = m_BCOBunchNumber[m_BCOWindows.begin()->first]; + // ttree->Fill(); + h_bunchnumber->Fill(m_BCOBunchNumber[m_BCOWindows.begin()->first]); + h_lumibco->Fill(m_BCOWindows.begin()->second.second - m_BCOWindows.begin()->second.first); + + int lower = -1 * static_cast(m_bco_trim - m_lower_bound); + int upper = (m_upper_bound > m_bco_trim) ? static_cast(m_upper_bound - m_bco_trim) : -1 * static_cast(m_bco_trim - m_upper_bound); // it is possible that upper is <0 + // std::cout<<"lower="<first); + // m_BCOBunchNumber.erase(m_BCOBunchNumber.begin()); + } + if (!m_BCOWindows.empty()) + { + m_BCOWindows.erase(m_BCOWindows.begin()); + } + if (flat_overflow) + { + m_BCOWindows.erase(m_BCOWindows.begin()); + bco_temp -= 1099511627775 + 1; + m_BCOWindows[bco_temp] = std::make_pair(bco_temp - m_negative_bco_window, bco_temp + m_positive_bco_window); + std::cout << " Change back, new bco window map " << m_BCOBunchNumber.begin()->first << std::endl; + flat_overflow = false; + } + + // mow use new + + Gl1Packet *gl1packet = findNode::getClass(m_topNode, "GL1RAWHIT"); + for (auto *gl1hititer : m_Gl1RawHitMap.begin()->second.Gl1RawHitVector) + { + if (!m_StreamingFlag) // if streaming flag is set, the gl1packet is a nullptr + { + gl1packet->FillFrom(gl1hititer); + MySyncManager()->CurrentEvent(gl1packet->getEvtSequence()); + } + } + + // add for mbd p_gl1 + Gl1Packet *p_gl1 = findNode::getClass(m_topNode, "GL1RAWHIT"); //"GL1Packet"); + if (!p_gl1) + { + std::cout << "CAN not find this Gl1Packet" << std::endl; + } + else + { + int bunchnumber = p_gl1->getBunchNumber(); + // uint64_t evtBCO_gl1 = p_gl1->getBCO() & 0xFFFFFFFFFFU; + // for (int i = 0; i <9;i++)// int(GL1PScaler_raw_vec.size()); i++) + // { + if (p_gl1->lValue(0, "GL1PRAW")) // 0-8, 0 is MBDSN + { + // GL1PScaler_raw_vec[i][bunchnumber] = p_gl1->lValue(i, "GL1PRAW"); + // std::cout<<"evtBCO: "<lValue(0, "GL1PRAW"); + m_bunchnumber_MBDNS_live[bunchnumber] = p_gl1->lValue(0, "GL1PLIVE"); + m_bunchnumber_MBDNS_scaled[bunchnumber] = p_gl1->lValue(0, "GL1PSCALED"); + m_bunchnumber_ZDCCoin_raw[bunchnumber] = p_gl1->lValue(5, "GL1PRAW"); // zdc coincidence + // h_gl1p_MBDSN_bunchid->Fill(bunchnumber, p_gl1->lValue(0, "GL1PRAW")); + // std::cout<<" bunchnumber ="<lValue(0, 0)) + { + // m_bunchnumber_rawgl1scaler[bunchnumber] = p_gl1->lValue(0, 0); + // std::cout<<" bunchnumber ="< 0) + { + if (m_alldone_flag) + { + std::cout << "all done is true" << std::endl; + } + } + + if (m_alldone_flag) + { + std::cout << m_event_number << " Events -- Storing files to output.root" << std::endl; + std::string updatedFileName = m_outputFileName + "_" + std::to_string(m_event_number) + ".root"; + if (TFile::Open(updatedFileName.c_str(), "READ")) + { + updatedFileName = m_outputFileName + "_" + std::to_string(m_event_number + 1) + ".root"; + } + tfile = TFile::Open(updatedFileName.c_str(), "RECREATE", ""); + ttree->Write("", TObject::kOverwrite); + h_lumibco->Write("", TObject::kOverwrite); + h_bunchnumber->Write("", TObject::kOverwrite); + h_bunchnumber_occur->Write("", TObject::kOverwrite); + h_diffbco->Write("", TObject::kOverwrite); + h_gl1p_MBDSN_bunchid_raw->Write("", TObject::kOverwrite); + h_gl1p_MBDSN_bunchid_live->Write("", TObject::kOverwrite); + h_gl1p_MBDSN_bunchid_scaled->Write("", TObject::kOverwrite); + h_gl1p_rawgl1scaler->Write("", TObject::kOverwrite); + h_gl1p_ZDCCoin_bunchid_raw->Write("", TObject::kOverwrite); + tfile->Close(); + delete tfile; + + ttree->Reset(); + h_lumibco->Reset(); + h_bunchnumber->Reset(); + h_bunchnumber_occur->Reset(); + h_diffbco->Reset(); + h_gl1p_MBDSN_bunchid_raw->Reset(); + h_gl1p_MBDSN_bunchid_live->Reset(); + h_gl1p_MBDSN_bunchid_scaled->Reset(); + h_gl1p_rawgl1scaler->Reset(); + h_gl1p_ZDCCoin_bunchid_raw->Reset(); + } + + return 0; +} + +void Fun4AllStreamingLumiCountingInputManager::SetNegativeWindow(const unsigned int i) +{ + m_negative_bco_window = std::max(i, m_negative_bco_window); +} + +void Fun4AllStreamingLumiCountingInputManager::SetPositiveWindow(const unsigned int i) +{ + m_positive_bco_window = std::max(i, m_positive_bco_window); +} + +void Fun4AllStreamingLumiCountingInputManager::createLuminosityHistos() +{ + auto *hm = QAHistManagerDef::getHistoManager(); + assert(hm); + // zhiwan + { + auto *tr = new TTree("BCOWindowTree", "BCO Window Data"); + tr->Branch("bco_trim", &m_bco_trim); + tr->Branch("lower_bound", &m_lower_bound); + tr->Branch("upper_bound", &m_upper_bound); + tr->Branch("bunch_number", &m_bunch_number); + // tr->Branch("rawgl1scaler", &m_rawgl1scaler); + tr->SetAutoFlush(100000); + hm->registerHisto(tr); + } + + { + auto *h = new TH1I("h_LumiBCO", "Lumi BCO", 500, 0, 500); + h->GetXaxis()->SetTitle(" Lumi BCO per event"); + h->SetTitle("Number of BCO matched"); + hm->registerHisto(h); + } + { + auto *h = new TH1I("h_BunchNumber", "Bunch Number Lumi BCO", 121, -0.5, 120.5); + h->GetXaxis()->SetTitle("Bunch Number per event"); + h->SetTitle("Number of crossing"); + hm->registerHisto(h); + } + { + auto *h = new TH1D("h_BunchNumberOccurance", "Bunch Number Lumi BCO", 120, -0.5, 119.5); + h->GetXaxis()->SetTitle("Bunch Number per time window"); + h->SetTitle("Number of crossing"); + hm->registerHisto(h); + } + { + auto *h = new TH1I("h_diffBCO", "gl1 bco 1-2", 3500, 0, 3500); + h->GetXaxis()->SetTitle("GL1 BCO difference"); + h->SetTitle("Number of crossing"); + hm->registerHisto(h); + } + { + auto *h = new TH1D("h_MBDSNraw_BunchID", "Bunch Number Lumi BCO", 121, -0.5, 120.5); + h->GetXaxis()->SetTitle("Bunch Number per event"); + h->SetTitle("MBDSN Number of crossing"); + hm->registerHisto(h); + } + { + auto *h = new TH1D("h_MBDSNlive_BunchID", "Bunch Number Lumi BCO", 121, -0.5, 120.5); + h->GetXaxis()->SetTitle("Bunch Number per event"); + h->SetTitle("MBDSN Number of crossing"); + hm->registerHisto(h); + } + { + auto *h = new TH1D("h_MBDSNscaled_BunchID", "Bunch Number Lumi BCO", 121, -0.5, 120.5); + h->GetXaxis()->SetTitle("Bunch Number per event"); + h->SetTitle("MBDSN Number of crossing"); + hm->registerHisto(h); + } + { + auto *h = new TH1D("h_rawgl1scalerBunchID", "Bunch Number Lumi BCO", 10, -0.5, 9.5); + h->GetXaxis()->SetTitle("Bunch Number per event"); + h->SetTitle("raw GL1 scaler"); + hm->registerHisto(h); + } + { + auto *h = new TH1D("h_gl1p_ZDCCoin_BunchID", "Bunch Number Lumi BCO", 121, -0.5, 120.5); + h->GetXaxis()->SetTitle("Bunch Number per event"); + h->SetTitle("raw GL1 scaler"); + hm->registerHisto(h); + } + // Get the global pointers + h_lumibco = dynamic_cast(hm->getHisto("h_LumiBCO")); + h_bunchnumber = dynamic_cast(hm->getHisto("h_BunchNumber")); + h_bunchnumber_occur = dynamic_cast(hm->getHisto("h_BunchNumberOccurance")); + ttree = dynamic_cast(hm->getHisto("BCOWindowTree")); + h_diffbco = dynamic_cast(hm->getHisto("h_diffBCO")); + h_gl1p_MBDSN_bunchid_raw = dynamic_cast(hm->getHisto("h_MBDSNraw_BunchID")); + h_gl1p_MBDSN_bunchid_live = dynamic_cast(hm->getHisto("h_MBDSNlive_BunchID")); + h_gl1p_MBDSN_bunchid_scaled = dynamic_cast(hm->getHisto("h_MBDSNscaled_BunchID")); + h_gl1p_rawgl1scaler = dynamic_cast(hm->getHisto("h_rawgl1scalerBunchID")); + h_gl1p_ZDCCoin_bunchid_raw = dynamic_cast(hm->getHisto("h_gl1p_ZDCCoin_BunchID")); +} \ No newline at end of file diff --git a/offline/framework/fun4allraw/Fun4AllStreamingLumiCountingInputManager.h b/offline/framework/fun4allraw/Fun4AllStreamingLumiCountingInputManager.h new file mode 100644 index 0000000000..b96021ea33 --- /dev/null +++ b/offline/framework/fun4allraw/Fun4AllStreamingLumiCountingInputManager.h @@ -0,0 +1,191 @@ +// Tell emacs that this is a C++ source +// -*- C++ -*-. +#ifndef RAWBCOLUMI_FUN4ALLSTREAMINGLUMICOUNTINGINPUTMANAGER_H +#define RAWBCOLUMI_FUN4ALLSTREAMINGLUMICOUNTINGINPUTMANAGER_H + +#include +// #include +#include + +#include +#include +#include +#include +class SingleStreamingInput; +class Gl1Packet; +class PHCompositeNode; +class SyncObject; +class TH1; +class TTree; +/** + * Construct a streaming luminosity-counting input manager. + * @param name Instance name used for identification. + * @param dstnodename Name of the DST node to which outputs attach. + * @param topnodename Name of the top-level node in the node tree. + */ + /** + * Clean up resources used by the input manager. + */ + /** + * Close any open input resources and release associated state. + * @returns `0` on success, non-zero on failure. + */ + /** + * Run processing loop for up to `nevents` events. + * @param nevents Maximum number of events to process; `0` means process until exhaustion or external stop. + * @returns Number of events actually processed, or a negative error code. + */ + /** + * Print internal status or diagnostics. + * @param what Selector controlling what to print (implementation-defined); defaults to "ALL". + */ + /** + * Reset the current event state so the manager is ready to read or process the next event. + * @returns `0` on success, non-zero on failure. + */ + /** + * Increase the number of events the manager should process or buffer. + * @param i Number of events to add to the internal backlog. + * @returns New total of backlog events on success, negative on failure. + */ + /** + * Provide the caller with the manager's synchronization object. + * @param mastersync Output pointer that will receive the manager's SyncObject. + * @returns `0` on success, non-zero on failure. + */ + /** + * Synchronize this input manager to the provided master synchronization object. + * @param mastersync The master SyncObject to synchronize against. + * @returns `0` on success, non-zero on failure. + */ + /** + * Retrieve a string value or property associated with this manager. + * @param what Key identifying the requested property or information. + * @returns The requested string value, or an empty string if not available. + */ + /** + * Register a streaming input source with this manager. + * @param evtin Pointer to the streaming input to register. + * @param enu_subsystem Enum value indicating the subsystem the input belongs to. + */ + /** + * Process accumulated GL1 raw hits and update internal luminosity/counting structures. + * @returns `0` on success, non-zero on failure. + */ + /** + * Add a raw GL1 hit associated with a BCLK value. + * @param bclk Bunch clock (BCO) or timestamp identifying the hit's bunch crossing. + * @param hit Pointer to the Gl1Packet representing the raw hit; ownership is not transferred by this call. + */ + /** + * Register a valid GL1 window around a trimmed BCO. + * @param bco_trim Trimmed BCO value used as the window center. + * @param negative_window Number of bunch crossings included before `bco_trim`. + * @param positive_window Number of bunch crossings included after `bco_trim`. + */ + /** + * Record the bunch number associated with a trimmed BCO. + * @param bco_trim Trimmed BCO value. + * @param bunch_number Bunch number to associate with `bco_trim`. + */ + /** + * Set the size of the negative-side BCO window used when matching hits. + * @param i Number of bunch crossings before the center to include. + */ + /** + * Set the size of the positive-side BCO window used when matching hits. + * @param i Number of bunch crossings after the center to include. + */ + /** + * Enable or disable streaming mode for this manager. + * @param b If `true`, enable streaming behaviour; if `false`, disable it. + */ + class Fun4AllStreamingLumiCountingInputManager : public Fun4AllInputManager +{ + public: + Fun4AllStreamingLumiCountingInputManager(const std::string &name = "DUMMY", const std::string &dstnodename = "DST", const std::string &topnodename = "TOP"); + ~Fun4AllStreamingLumiCountingInputManager() override; + int fileopen(const std::string & /*filenam*/) override { return 0; } + // cppcheck-suppress virtualCallInConstructor + int fileclose() override; + int run(const int nevents = 0) override; + + void Print(const std::string &what = "ALL") const override; + int ResetEvent() override; + int PushBackEvents(const int i) override; + int GetSyncObject(SyncObject **mastersync) override; + int SyncIt(const SyncObject *mastersync) override; + int HasSyncObject() const override { return 1; } + std::string GetString(const std::string &what) const override; + void registerStreamingInput(SingleStreamingInput *evtin, InputManagerType::enu_subsystem); + int FillGl1(); + void AddGl1RawHit(uint64_t bclk, Gl1Packet *hit); + void AddGl1Window(uint64_t bco_trim, int negative_window, int positive_window); + void AddGl1BunchNumber(uint64_t bco_trim, int bunch_number); + void SetNegativeWindow(const unsigned int i); + void SetPositiveWindow(const unsigned int i); + void Streaming(bool b = true) { m_StreamingFlag = b; } + void SetOutputFileName(const std::string &fileName); + void SetEndofEvent(bool flag = false, bool flag2 = false) + { + m_alldone_flag = flag; + m_lastevent_flag = flag2; + } + void SetEventNumber(int num) { m_event_number = num; } + + private: + struct Gl1RawHitInfo + { + std::vector Gl1RawHitVector; + unsigned int EventFoundCounter{0}; + }; + + void createLuminosityHistos(); + + SyncObject *m_SyncObject{nullptr}; + PHCompositeNode *m_topNode{nullptr}; + + int m_RunNumber{0}; + unsigned int m_negative_bco_window{0}; + unsigned int m_positive_bco_window{0}; + uint64_t m_rawgl1scaler{0}; + // std::string m_output_file="output.root"; + bool m_alldone_flag = {false}; + bool m_lastevent_flag = {false}; + int m_event_number{0}; + int m_diffBCO{0}; + bool m_gl1_registered_flag{false}; + bool m_StreamingFlag{false}; + bool flat_overflow{false}; + uint64_t bco_temp = 0; + + std::vector m_Gl1InputVector; + std::map m_Gl1RawHitMap; + std::map> m_BCOWindows; + std::map m_BCOBunchNumber; + std::map m_bunchnumber_MBDNS_raw; + std::map m_bunchnumber_MBDNS_live; + std::map m_bunchnumber_MBDNS_scaled; + std::map m_bunchnumber_ZDCCoin_raw; + // std::map m_bunchnumber_rawgl1scaler; + + // QA histos + TH1 *h_lumibco{nullptr}; + TH1 *h_bunchnumber{nullptr}; + TH1 *h_bunchnumber_occur{nullptr}; + TH1 *h_diffbco{nullptr}; + TH1 *h_gl1p_MBDSN_bunchid_raw{nullptr}; + TH1 *h_gl1p_MBDSN_bunchid_live{nullptr}; + TH1 *h_gl1p_MBDSN_bunchid_scaled{nullptr}; + TH1 *h_gl1p_rawgl1scaler{nullptr}; + TH1 *h_gl1p_ZDCCoin_bunchid_raw{nullptr}; + uint64_t m_bco_trim{}; + uint64_t m_lower_bound{}; + uint64_t m_upper_bound{}; + int m_bunch_number{}; + TTree *ttree = nullptr; + TFile *tfile = nullptr; + std::string m_outputFileName = "/sphenix/user/xuzhiwan/luminosity/streaming-macro/macro/output.root"; // Default value +}; + +#endif /* RAWBCOLUMI_FUN4ALLSTREAMINGLUMICOUNTINGINPUTMANAGER_H */ \ No newline at end of file diff --git a/offline/framework/fun4allraw/SingleGl1PoolInput.cc b/offline/framework/fun4allraw/SingleGl1PoolInput.cc index 814b47a7da..c877cd9683 100644 --- a/offline/framework/fun4allraw/SingleGl1PoolInput.cc +++ b/offline/framework/fun4allraw/SingleGl1PoolInput.cc @@ -1,12 +1,11 @@ #include "SingleGl1PoolInput.h" #include "Fun4AllStreamingInputManager.h" +#include "Fun4AllStreamingLumiCountingInputManager.h" #include "InputManagerType.h" #include -#include - #include #include // for PHIODataNode #include // for PHNode @@ -39,6 +38,19 @@ SingleGl1PoolInput::~SingleGl1PoolInput() CleanupUsedPackets(std::numeric_limits::max()); } +/** + * @brief Populate the internal GL1 event pool from input files. + * + * Reads events from the current input file(s) until the pool reaches the desired + * depth or no more events are available. For each DATAEVENT it extracts packet + * 14001, constructs a Gl1Packetv3 hit, updates BCO windowing and bunch-number + * maps, and stores the hit in the internal GL1 raw-hit map and beam-clock stack. + * Special and control events (e.g., end-of-run) are counted and cause appropriate + * end-of-event/end-of-run flags to be set; end conditions and per-event state + * (event number, end-of-event flags, window sizes, bunch numbers) are propagated + * to any attached StreamingInputManager and StreamingLumiInputManager. Packet + * objects consumed from events are deleted after their data are transferred. + */ void SingleGl1PoolInput::FillPool(const unsigned int /*nbclks*/) { if (AllDone()) // no more files and all events read @@ -47,7 +59,7 @@ void SingleGl1PoolInput::FillPool(const unsigned int /*nbclks*/) } while (GetEventiterator() == nullptr) // at startup this is a null pointer { - if (OpenNextFile() == InputFileHandlerReturnCodes::FAILURE) + if (!OpenNextFile()) { AllDone(1); return; @@ -60,7 +72,7 @@ void SingleGl1PoolInput::FillPool(const unsigned int /*nbclks*/) while (!evt) { fileclose(); - if (OpenNextFile() == InputFileHandlerReturnCodes::FAILURE) + if (!OpenNextFile()) { AllDone(1); return; @@ -71,6 +83,25 @@ void SingleGl1PoolInput::FillPool(const unsigned int /*nbclks*/) { std::cout << PHWHERE << "Fetching next Event" << evt->getEvtSequence() << std::endl; } + if ((m_total_event == 0 && evt->getEvtType() == ENDRUNEVENT) || + (m_total_event != 0 && evt->getEvtSequence() - 2 == m_total_event)) + { + m_alldone_flag = true; + m_lastevent_flag = true; + } + if (evt->getEvtSequence() % 5000 == 0) + { + m_alldone_flag = true; + m_lastevent_flag = true; + } + if (Verbosity() > 2) + { + if (m_alldone_flag) + { + std::cout << "gl1 all done is true" << std::endl; + } + // else{std::cout<<"gl1 all done is false"<getRunNumber()); if (GetVerbosity() > 1) { @@ -101,6 +132,15 @@ void SingleGl1PoolInput::FillPool(const unsigned int /*nbclks*/) { std::cout << PHWHERE << "Packet 14001 is null ptr" << std::endl; evt->identify(); + m_alldone_flag = true; + m_lastevent_flag = true; + if (StreamingLumiInputManager()) + { + StreamingLumiInputManager()->SetEndofEvent(m_alldone_flag, m_lastevent_flag); + StreamingLumiInputManager()->SetEventNumber(EventSequence); + } + m_alldone_flag = false; + m_lastevent_flag = false; continue; } if (Verbosity() > 1) @@ -110,6 +150,10 @@ void SingleGl1PoolInput::FillPool(const unsigned int /*nbclks*/) Gl1Packet *newhit = new Gl1Packetv3(); uint64_t gtm_bco = packet->lValue(0, "BCO"); + uint64_t bco_trim = gtm_bco & 0xFFFFFFFFFFU; + m_BCOWindows[bco_trim] = std::make_pair(bco_trim - m_negative_bco_window, bco_trim + m_positive_bco_window); + // std::cout<<"BCO "<< m_BCOWindows.begin()->first<<" left "<second.first<<" right "<< m_BCOWindows.begin()->second.second<lValue(0, "BunchNumber"); m_FEEBclkMap.insert(gtm_bco); newhit->setBCO(packet->lValue(0, "BCO")); newhit->setHitFormat(packet->getHitFormat()); @@ -158,6 +202,20 @@ void SingleGl1PoolInput::FillPool(const unsigned int /*nbclks*/) { StreamingInputManager()->AddGl1RawHit(gtm_bco, newhit); } + if (StreamingLumiInputManager()) + { + StreamingLumiInputManager()->AddGl1Window(bco_trim, m_negative_bco_window, m_positive_bco_window); + StreamingLumiInputManager()->AddGl1BunchNumber(bco_trim, m_BCOBunchNumber[bco_trim]); + StreamingLumiInputManager()->SetEndofEvent(m_alldone_flag, m_lastevent_flag); + StreamingLumiInputManager()->SetEventNumber(EventSequence); + StreamingLumiInputManager()->SetNegativeWindow(m_negative_bco_window); + StreamingLumiInputManager()->SetPositiveWindow(m_positive_bco_window); + } + if (evt->getEvtSequence() % 5000 == 0) + { + m_alldone_flag = false; + m_lastevent_flag = false; + } m_Gl1RawHitMap[gtm_bco].push_back(newhit); m_BclkStack.insert(gtm_bco); @@ -181,7 +239,7 @@ void SingleGl1PoolInput::Print(const std::string &what) const for (const auto &bcliter : m_Gl1RawHitMap) { std::cout << PHWHERE << "Beam clock 0x" << std::hex << bcliter.first << std::dec << std::endl; - for (auto *feeiter : bcliter.second) + for (auto feeiter : bcliter.second) { std::cout << PHWHERE << "fee: " << feeiter->getBCO() << " at " << std::hex << feeiter << std::dec << std::endl; @@ -197,6 +255,15 @@ void SingleGl1PoolInput::Print(const std::string &what) const } } +/** + * @brief Delete and remove stored GL1 packets and related state up to a given beam clock. + * + * Deletes all packet objects and erases entries whose BCLK key is less than or equal to the + * provided `bclk` from the internal storage maps and stack, and also removes corresponding + * BCO window and bunch-number entries using the trimmed BCLK key (lower 40 bits). + * + * @param bclk Upper bound beam clock (inclusive) indicating which stored entries to clear. + */ void SingleGl1PoolInput::CleanupUsedPackets(const uint64_t bclk) { std::vector toclearbclk; @@ -204,7 +271,7 @@ void SingleGl1PoolInput::CleanupUsedPackets(const uint64_t bclk) { if (iter.first <= bclk) { - for (auto *pktiter : iter.second) + for (auto pktiter : iter.second) { delete pktiter; } @@ -222,6 +289,9 @@ void SingleGl1PoolInput::CleanupUsedPackets(const uint64_t bclk) m_FEEBclkMap.erase(iter); m_BclkStack.erase(iter); m_Gl1RawHitMap.erase(iter); + auto trimbclk = iter & 0xFFFFFFFFFFU; + m_BCOWindows.erase(trimbclk); + m_BCOBunchNumber.erase(trimbclk); } } @@ -312,4 +382,4 @@ void SingleGl1PoolInput::CreateDSTNode(PHCompositeNode *topNode) PHIODataNode *newNode = new PHIODataNode(gl1hitcont, "GL1RAWHIT", "PHObject"); detNode->addNode(newNode); } -} +} \ No newline at end of file diff --git a/offline/framework/fun4allraw/SingleGl1PoolInput.h b/offline/framework/fun4allraw/SingleGl1PoolInput.h index 5d9d7acfab..b0d01ac35d 100644 --- a/offline/framework/fun4allraw/SingleGl1PoolInput.h +++ b/offline/framework/fun4allraw/SingleGl1PoolInput.h @@ -13,6 +13,57 @@ class Gl1Packet; class PHCompositeNode; +/** + * Construct a SingleGl1PoolInput with the given name. + * @param name Identifier used to name this input instance. + */ +/** + * Destroy the SingleGl1PoolInput and release associated resources. + */ +/** + * Populate the internal packet pool using up to the given number of items. + * @param count Maximum number of packets or items to attempt to add to the pool. + */ +/** + * Remove packets from internal structures that have been consumed up to the specified BCLK. + * @param bclk Boundary clock value; packets with timestamps <= bclk are eligible for cleanup. + */ +/** + * Verify whether the internal pool depth is sufficient relative to the specified BCLK. + * @param bclk Clock value used as the reference for pool depth checks. + * @returns `true` if the pool contains enough data for the provided BCLK, `false` otherwise. + */ +/** + * Reset state associated with the current event so the input can start a new event. + */ +/** + * Attempt to acquire additional events into the internal pool or event buffers. + * @returns `true` if one or more new events were obtained, `false` if no further events are available. + */ +/** + * Print status or diagnostic information. + * @param what Selector string indicating which information to print (default: "ALL"). + */ +/** + * Create and attach necessary DST nodes to the provided top-level node. + * @param topNode Parent node in the PHENIX node tree where new DST nodes will be created. + */ +/** + * Set the acceptable BCO range used by this input. + * @param i BCO range value to apply. + */ +/** + * Set the size of the negative BCO window (how far before a reference BCO to include). + * @param value Number of BCO units to include before the reference BCO. + */ +/** + * Set the size of the positive BCO window (how far after a reference BCO to include). + * @param value Number of BCO units to include after the reference BCO. + */ +/** + * Set the maximum number of events this input should produce. + * @param value Maximum total events to produce; use a large value to indicate no practical limit. + */ class SingleGl1PoolInput : public SingleStreamingInput { public: @@ -27,17 +78,25 @@ class SingleGl1PoolInput : public SingleStreamingInput void CreateDSTNode(PHCompositeNode *topNode) override; void SetBcoRange(const unsigned int i) { m_BcoRange = i; } // void ConfigureStreamingInputManager() override; - + void SetNegativeWindow(const unsigned int value) { m_negative_bco_window = value; } + void SetPositiveWindow(const unsigned int value) { m_positive_bco_window = value; } + void SetTotalEvent(const int value) { m_total_event = value; } private: unsigned int m_NumSpecialEvents{0}; unsigned int m_BcoRange{0}; - + unsigned int m_negative_bco_window = 20; + unsigned int m_positive_bco_window = 325; + int m_total_event = std::numeric_limits::max(); + bool m_alldone_flag = {false}; + bool m_lastevent_flag = {false}; //! map bco to packet std::map m_packet_bco; + std::map> m_BCOWindows; + std::map m_BCOBunchNumber; std::map> m_Gl1RawHitMap; std::set m_FEEBclkMap; std::set m_BclkStack; }; -#endif +#endif \ No newline at end of file diff --git a/offline/framework/fun4allraw/SingleStreamingInput.h b/offline/framework/fun4allraw/SingleStreamingInput.h index 082c1a079e..ab45ea4ed9 100644 --- a/offline/framework/fun4allraw/SingleStreamingInput.h +++ b/offline/framework/fun4allraw/SingleStreamingInput.h @@ -12,6 +12,7 @@ class Eventiterator; class Fun4AllEvtInputPoolManager; class Fun4AllStreamingInputManager; +class Fun4AllStreamingLumiCountingInputManager; class PHCompositeNode; class SingleStreamingInput : public Fun4AllBase, public InputFileHandler @@ -44,12 +45,53 @@ class SingleStreamingInput : public Fun4AllBase, public InputFileHandler virtual bool CheckPoolDepth(const uint64_t bclk); virtual void ClearCurrentEvent(); - virtual Eventiterator *GetEventiterator() const { return m_EventIterator; } - virtual Fun4AllStreamingInputManager *StreamingInputManager() { return m_StreamingInputMgr; } - virtual void StreamingInputManager(Fun4AllStreamingInputManager *in) { m_StreamingInputMgr = in; } - virtual void CreateDSTNode(PHCompositeNode *) { return; } - virtual void ConfigureStreamingInputManager() { return; } - virtual void SubsystemEnum(const int id) { m_SubsystemEnum = id; } + /** + * Access the current Eventiterator. + * @returns Pointer to the current Eventiterator, or `nullptr` if no iterator is set. + */ +virtual Eventiterator *GetEventiterator() const { return m_EventIterator; } + /** + * Get the current streaming input manager. + * + * @returns Pointer to the configured Fun4AllStreamingInputManager, or `nullptr` if no manager is set. + */ +virtual Fun4AllStreamingInputManager *StreamingInputManager() { return m_StreamingInputMgr; } + /** + * Assign the streaming input manager for this SingleStreamingInput instance. + * + * @param in Pointer to the Fun4AllStreamingInputManager to use; pass `nullptr` to clear the current manager. + */ +virtual void StreamingInputManager(Fun4AllStreamingInputManager *in) { m_StreamingInputMgr = in; } + /** + * Access the LumiCounting streaming input manager. + * + * @returns Pointer to the Fun4AllStreamingLumiCountingInputManager instance, or `nullptr` if no manager is set. + */ +virtual Fun4AllStreamingLumiCountingInputManager *StreamingLumiInputManager() { return m_StreamingLumiInputMgr; } + /** + * Set the streaming lumi counting input manager for this instance. + * @param in Fun4AllStreamingLumiCountingInputManager to associate with this input. + */ +virtual void StreamingLumiInputManager(Fun4AllStreamingLumiCountingInputManager *in) { m_StreamingLumiInputMgr = in; } + /** + * Create DST node(s) under the provided composite node. + * + * Default implementation does nothing; subclasses should override to attach + * DST-related nodes to the given top-level node when needed. + * @param topNode Top-level PHCompositeNode to which DST nodes will be added. + */ +virtual void CreateDSTNode(PHCompositeNode *) { return; } + /** + * Configure the associated streaming input manager. + * + * Hook for subclasses to perform any manager-specific initialization or configuration. + */ +virtual void ConfigureStreamingInputManager() { return; } + /** + * Set the subsystem enumeration identifier for this input. + * @param id Subsystem enumeration value identifying which subsystem this input corresponds to. + */ +virtual void SubsystemEnum(const int id) { m_SubsystemEnum = id; } virtual int SubsystemEnum() const { return m_SubsystemEnum; } void MaxBclkDiff(uint64_t ui) { m_MaxBclkSpread = ui; } uint64_t MaxBclkDiff() const { return m_MaxBclkSpread; } @@ -117,8 +159,20 @@ class SingleStreamingInput : public Fun4AllBase, public InputFileHandler Eventiterator *m_EventIterator{nullptr}; // Fun4AllEvtInputPoolManager *m_InputMgr {nullptr}; Fun4AllStreamingInputManager *m_StreamingInputMgr{nullptr}; + Fun4AllStreamingLumiCountingInputManager *m_StreamingLumiInputMgr{nullptr}; + uint64_t m_MaxBclkSpread{1000000}; - unsigned int m_EventNumberOffset{1}; // packet event counters start at 0 but we start with event number 1 + /** + * Offset added to event numbers when assigning or reporting event IDs. + * + * Set to 1 by default; the effective event ID is the original event index plus this offset. + */ +unsigned int m_EventNumberOffset{1}; /** + * Current run number for this input instance. + * + * A value of 0 indicates no run has been set. Packet event counters are zero-based, + * but event numbering used here starts at 1 relative to those packet counters. + */ int m_RunNumber{0}; int m_EventsThisFile{0}; int m_AllDone{0}; @@ -128,4 +182,4 @@ class SingleStreamingInput : public Fun4AllBase, public InputFileHandler std::set m_BclkStack; }; -#endif +#endif \ No newline at end of file