diff --git a/macro/run/run_inspect_digievents.C b/macro/run/run_inspect_digievents.C new file mode 100644 index 0000000000000000000000000000000000000000..d5164a7fb3ac57f5f3371fdb4e8d044b4fe65603 --- /dev/null +++ b/macro/run/run_inspect_digievents.C @@ -0,0 +1,119 @@ +/* Copyright (C) 2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Volker Friese [committer] */ + +/** @file run_inspect_digievents.C + ** @author Volker Friese <v.friese@gsi.de> + ** @since 19 March 2024 + **/ + + +// --- Includes needed for IDE +#include <RtypesCore.h> +#if !defined(__CLING__) +#include "CbmSourceDigiEvents.h" +#include "CbmTaskInspectDigiEvents.h" + +#include <FairRunAna.h> +#include <FairSystemInfo.h> + +#include <TStopwatch.h> +#endif + + +/** @brief Macro for simple inspection of DigiEvents + ** @author Volker Friese <v.friese@gsi.de> + ** @since 219 March 2024 + ** @param input Name of input file + ** @param nTimeSlices Number of time-slices to process + ** + ** This macro performs a simple inspection of DigiEvents produced an archived by online data processing. + ** It prints statistics of events on the console. The purpose is to test CbmSourceDigiEvents and to + ** demonstrate the event loop within a timeslice and the access to digi data in the event. + **/ +void run_inspect_digievents(TString inputFileName, TString outputFileName, size_t numTimeslices = -1) +{ + + // ======================================================================== + // Adjust this part according to your requirements + + // --- Logger settings ---------------------------------------------------- + TString logLevel = "INFO"; + TString logVerbosity = "LOW"; + // ------------------------------------------------------------------------ + + // ----- Environment -------------------------------------------------- + TString myName = "run_inspect_digievents"; // this macro's name for screen output + TString srcDir = gSystem->Getenv("VMCWORKDIR"); // top source directory + // ------------------------------------------------------------------------ + + + // ----- Timer -------------------------------------------------------- + TStopwatch timer; + timer.Start(); + // ------------------------------------------------------------------------ + + + // ----- FairRunAna --------------------------------------------------- + FairRunAna* run = new FairRunAna(); + FairSource* source = new CbmSourceDigiEvents(inputFileName); + run->SetSource(source); + run->SetOutputFile(outputFileName); + run->SetGenerateRunInfo(kTRUE); + // ------------------------------------------------------------------------ + + + // ----- Logger settings ---------------------------------------------- + FairLogger::GetLogger()->SetLogScreenLevel(logLevel.Data()); + FairLogger::GetLogger()->SetLogVerbosityLevel(logVerbosity.Data()); + // ------------------------------------------------------------------------ + + + // ----- Event inspection --------------------------------------------- + //std::unique_ptr<CbmTaskInspectDigiEvents> inspect = std::make_unique<CbmTaskInspectDigiEvents>; + //LOG(info) << "-I- " << myName << ": Adding task " << inspect->GetName(); + //run->AddTask(inspect.release()); + FairTask* inspect = new CbmTaskInspectDigiEvents(); + LOG(info) << "-I- " << myName << ": Adding task " << inspect->GetName(); + run->AddTask(inspect); + // ------------------------------------------------------------------------ + + + // ----- Run initialisation ------------------------------------------- + std::cout << std::endl; + std::cout << "-I- " << myName << ": Initialise run" << std::endl; + run->Init(); + // ------------------------------------------------------------------------ + + + // ----- Start run ---------------------------------------------------- + std::cout << std::endl << std::endl; + std::cout << "-I- " << myName << ": Starting run" << std::endl; + if (numTimeslices == -1) + run->Run(); + else + run->Run(0, numTimeslices); + // ------------------------------------------------------------------------ + + + // ----- Finish ------------------------------------------------------- + timer.Stop(); + FairMonitor::GetMonitor()->Print(); + Double_t rtime = timer.RealTime(); + Double_t ctime = timer.CpuTime(); + std::cout << std::endl << std::endl; + std::cout << "Macro finished successfully." << std::endl; + std::cout << "Real time " << rtime << " s, CPU time " << ctime << " s" << std::endl; + FairSystemInfo sysInfo; + Float_t maxMemory = sysInfo.GetMaxMemory(); + std::cout << "<DartMeasurement name=\"MaxMemory\" type=\"numeric/double\">"; + std::cout << maxMemory; + std::cout << "</DartMeasurement>" << std::endl; + Float_t cpuUsage = ctime / rtime; + std::cout << "<DartMeasurement name=\"CpuLoad\" type=\"numeric/double\">"; + std::cout << cpuUsage; + std::cout << "</DartMeasurement>" << std::endl; + // ------------------------------------------------------------------------ + + +} // End of main macro function diff --git a/reco/steer/CMakeLists.txt b/reco/steer/CMakeLists.txt index b8f3b7bd122c0f59cdc24989a059913ecdb357b2..b74ba5e638c965f5c98d0448d152660c1bc7f315 100644 --- a/reco/steer/CMakeLists.txt +++ b/reco/steer/CMakeLists.txt @@ -8,6 +8,7 @@ set(INCLUDE_DIRECTORIES set(SRCS CbmRecoUnpack.cxx + CbmSourceDigiEvents.cxx CbmSourceTsArchive.cxx ) diff --git a/reco/steer/CbmRecoSteerLinkDef.h b/reco/steer/CbmRecoSteerLinkDef.h index f584bd911e23ace644d928a4326b5d05713da6b4..f28876be61e15834239ddc1e5d8c6c5fb456742c 100644 --- a/reco/steer/CbmRecoSteerLinkDef.h +++ b/reco/steer/CbmRecoSteerLinkDef.h @@ -10,6 +10,7 @@ // --- Classes #pragma link C++ class CbmRecoUnpack + ; +#pragma link C++ class CbmSourceDigiEvents + ; #pragma link C++ class CbmSourceTsArchive + ; #endif /* __CINT__ */ diff --git a/reco/steer/CbmSourceDigiEvents.cxx b/reco/steer/CbmSourceDigiEvents.cxx new file mode 100644 index 0000000000000000000000000000000000000000..1bbb43f0b9bebb8c44bf723f48bb04a852ec434a --- /dev/null +++ b/reco/steer/CbmSourceDigiEvents.cxx @@ -0,0 +1,89 @@ +/* Copyright (C) 2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Volker Friese[committer] */ + +#include "CbmSourceDigiEvents.h" + +#include <FairRootManager.h> +#include <Logger.h> + +#include <utility> + + +// ----- Constructor ------------------------------------------------------ +CbmSourceDigiEvents::CbmSourceDigiEvents(const char* fileName) : fInputFileName(fileName) {} +// ---------------------------------------------------------------------------- + + +// ----- Close ------------------------------------------------------------ +void CbmSourceDigiEvents::Close() +{ + LOG(info) << "Source: Closing after " << fNumTs << "timeslices with " << fNumEvents << "events."; +} +// ---------------------------------------------------------------------------- + + +// ----- Initialisation --------------------------------------------------- +Bool_t CbmSourceDigiEvents::Init() +{ + + // Create input archive + fArchive = std::make_unique<cbm::algo::RecoResultsInputArchive>(fInputFileName); + LOG(info) << "Source: Reading from input archive " << fInputFileName; + auto desc = fArchive->descriptor(); + LOG(info) << " - Time created: " << desc.time_created(); + LOG(info) << " - Host name : " << desc.hostname(); + LOG(info) << " - User name : " << desc.username(); + + // Create and register the DigiEvent tree branch + FairRootManager* ioman = FairRootManager::Instance(); + assert(ioman); + if (ioman->GetObject("DigiEvent")) { + LOG(fatal) << "Source: Branch DigiEvent already exists!"; + return kFALSE; + } + fEvents = new std::vector<CbmDigiEvent>(); + ioman->RegisterAny("DigiEvent", fEvents, true); + LOG(info) << "Source: Registered branch DigiEvent"; + + return kTRUE; +} +// ---------------------------------------------------------------------------- + + +// ----- Read one time slice from archive --------------------------------- +Int_t CbmSourceDigiEvents::ReadEvent(UInt_t) +{ + + // Clear output event vector + fEvents->clear(); + + // Get next timeslice data from archive. Stop run if end of archive is reached. + auto results = fArchive->get(); + if (fArchive->eos()) { + LOG(info) << "Source: End of input archive; terminating run"; + return 1; + } + + // Move event data from input archive to ROOT tree + if (results == nullptr) { + LOG(error) << "Source: Failed to read RecoResults from archive"; + return 1; + } + size_t numEvents = results->DigiEvents().size(); + LOG(info); + LOG(info) << "Source: Reading TS " << fNumTs << ", index " << results->TsIndex() << ", start " + << results->TsStartTime() << ", events " << numEvents; + std::move(results->DigiEvents().begin(), results->DigiEvents().end(), std::back_inserter(*fEvents)); + assert(fEvents->size() == numEvents); + + // Update counters + fNumTs++; + fNumEvents += numEvents; + + return 0; +} +// ---------------------------------------------------------------------------- + + +ClassImp(CbmSourceDigiEvents) diff --git a/reco/steer/CbmSourceDigiEvents.h b/reco/steer/CbmSourceDigiEvents.h new file mode 100644 index 0000000000000000000000000000000000000000..c11954d2d38019ab450e4b9f807d67c403546e76 --- /dev/null +++ b/reco/steer/CbmSourceDigiEvents.h @@ -0,0 +1,103 @@ +/* Copyright (C) 2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Volker Friese[committer] */ + +#pragma once // include this header only once per compilation unit + +#include "CbmDigiEvent.h" +#include "DigiData.h" +#include "RecoResultsInputArchive.h" + +#include <FairSource.h> + +#include <cstdint> +#include <memory> +#include <string> +#include <vector> + + +/** @class CbmSourceDigiEvents + ** @brief Source class for reading from files resulting from online processing (containing DigiEvents) + ** @author Volker Friese + ** @since 18 March 2024 + ** + ** The online process creates a std::vector of DigiEvents per timeslice. These are saved to file using the BOOST streamer. + ** This class allows to read such files and get the DigiEvents into the ROOT tree for offline analysis. It creates a + ** branch DigiEvents containing the DigiEvent vector; one tree entry corresponds to one timelice. + **/ +class CbmSourceDigiEvents : public FairSource { + + public: + /** @brief Constructor + ** @param fileName Name of (single) input file. + ** + ** More input files can be added by the method AddInputFile. + */ + CbmSourceDigiEvents(const char* fileName = ""); + + /** @brief Copy constructor - not implemented **/ + CbmSourceDigiEvents(const CbmSourceDigiEvents&) = delete; + + /** @brief Assignment operator - not implemented **/ + CbmSourceDigiEvents& operator=(const CbmSourceDigiEvents&) = delete; + + /** @brief Destructor **/ + virtual ~CbmSourceDigiEvents() {} + + /** @brief Close source after end of run **/ + virtual void Close(); + + /** @brief Source type + ** @return FairSource::Source_Type + **/ + virtual Source_Type GetSourceType() { return fSourceType; } + + /** @brief Initialisation **/ + virtual Bool_t Init(); + + /** @brief Initialise unpackers (forced by base class, not relevant here) **/ + virtual Bool_t InitUnpackers() { return kTRUE; } + + /** @brief Read one time slice from file **/ + Int_t ReadEvent(UInt_t = 0); + + /** @brief Re-Initialise unpackers (forced by base class, not relevant here) **/ + virtual Bool_t ReInitUnpackers() { return kTRUE; } + + /** @brief Reset (forced by base class, not relevant here) **/ + virtual void Reset() {} + + /** @brief Set unpacker parameters (forced by base class, not relevant here) **/ + virtual void SetParUnpackers() {} + + /** @brief Set the Source Type + ** @param type Source type + **/ + void SetSourceType(Source_Type type) { fSourceType = type; } + + /** @brief Set Run ID (forced by base class, not relevant here) **/ + Bool_t SpecifyRunId() { return kTRUE; } + + + private: + /** Input file name **/ + std::string fInputFileName = {}; + + /** Input archive **/ + std::unique_ptr<cbm::algo::RecoResultsInputArchive> fArchive = nullptr; + + /** Branch vector of DigiEvents **/ + std::vector<CbmDigiEvent>* fEvents = nullptr; + + /** @brief type of source that is currently used @remark currently we use kONLINE as default, since, kFILE skipps the first TS probably due to obsolete reasons (to be checked PR072021) */ + Source_Type fSourceType = Source_Type::kONLINE; + + /** Time-slice counter **/ + size_t fNumTs = 0; + + /** Event counter **/ + size_t fNumEvents = 0; + + + ClassDef(CbmSourceDigiEvents, 1) +}; diff --git a/reco/tasks/CMakeLists.txt b/reco/tasks/CMakeLists.txt index 76d5677cc0654c8261dbc79e77c4ee7b95898241..533e37764febb7d697035ab3b30035cee8752008 100644 --- a/reco/tasks/CMakeLists.txt +++ b/reco/tasks/CMakeLists.txt @@ -12,6 +12,7 @@ set(SRCS CbmTaskBuildEvents.cxx CbmTaskDigiEventQa.cxx CbmTaskEventsCloneInToOut.cxx + CbmTaskInspectDigiEvents.cxx CbmTaskMakeRecoEvents.cxx CbmTaskTriggerDigi.cxx CbmTaskTofHitFinder.cxx diff --git a/reco/tasks/CbmRecoTasksLinkDef.h b/reco/tasks/CbmRecoTasksLinkDef.h index 8f829d3dfc1396d159981bfab070b6d89b98fd3a..fbff7c46c36c14ace228780e38de5b92792da259 100644 --- a/reco/tasks/CbmRecoTasksLinkDef.h +++ b/reco/tasks/CbmRecoTasksLinkDef.h @@ -16,6 +16,7 @@ #pragma link C++ class CbmTaskBuildEvents + ; #pragma link C++ class CbmTaskDigiEventQa + ; #pragma link C++ class CbmTaskEventsCloneInToOut + ; +#pragma link C++ class CbmTaskInspectDigiEvents + ; #pragma link C++ class CbmTaskMakeRecoEvents + ; #pragma link C++ class CbmTaskTofHitFinder + ; #pragma link C++ class CbmTaskTofClusterizer + ; diff --git a/reco/tasks/CbmTaskInspectDigiEvents.cxx b/reco/tasks/CbmTaskInspectDigiEvents.cxx new file mode 100644 index 0000000000000000000000000000000000000000..d04483d0fb0c4a29219aa58c8bd68f65d35f87e3 --- /dev/null +++ b/reco/tasks/CbmTaskInspectDigiEvents.cxx @@ -0,0 +1,88 @@ +/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Volker Friese [committer] */ + +#include "CbmTaskInspectDigiEvents.h" + +#include <FairRootManager.h> +#include <Logger.h> + + +// ----- Constructor ----------------------------------------------------- +CbmTaskInspectDigiEvents::CbmTaskInspectDigiEvents() : FairTask("InspectDigiEvents") {} +// --------------------------------------------------------------------------- + + +// ----- Destructor ------------------------------------------------------ +CbmTaskInspectDigiEvents::~CbmTaskInspectDigiEvents() {} +// --------------------------------------------------------------------------- + + +// ----- Execution ------------------------------------------------------- +void CbmTaskInspectDigiEvents::Exec(Option_t*) +{ + + // --- Inspect event vector + LOG(info) << GetName() << ": timeslice " << fNumTs << " with " << fEvents->size() << " events" + << (fEvents->size() > 10 ? " (showing the first 10 only)" : ""); + size_t numEventsInTs = 0; + for (auto& event : *fEvents) { + size_t numBmon = event.fData.fBmon.Size(); + size_t numSts = event.fData.fSts.Size(); + size_t numMuch = event.fData.fMuch.Size(); + size_t numRich = event.fData.fRich.Size(); + size_t numTrd1d = event.fData.fTrd.Size(); + size_t numTrd2d = event.fData.fTrd2d.Size(); + size_t numTof = event.fData.fTof.Size(); + size_t numFsd = event.fData.fFsd.Size(); + LOG(info) << " Event " << event.fNumber << ", time " << event.fTime << ", digis: bmon " << numBmon << " sts " + << numSts << " much " << numMuch << " rich " << numRich << " trd1d " << numTrd1d << " trd2d " + << numTrd2d << " tof " << numTof << " fsd " << numFsd; + numEventsInTs++; + if (numEventsInTs > 9) break; + } + + // --- Run statistics + fNumTs++; + fNumEvents += fEvents->size(); +} +// ---------------------------------------------------------------------------- + + +// ----- End-of-run action ------------------------------------------------ +void CbmTaskInspectDigiEvents::Finish() +{ + LOG(info) << "====================================="; + LOG(info) << GetName() << ": Run summary"; + LOG(info) << "Timeslices : " << fNumTs; + LOG(info) << "Events : " << fNumEvents; + LOG(info) << "====================================="; +} +// ---------------------------------------------------------------------------- + + +// ----- Initialisation --------------------------------------------------- +InitStatus CbmTaskInspectDigiEvents::Init() +{ + // --- Get FairRootManager instance + FairRootManager* ioman = FairRootManager::Instance(); + assert(ioman); + + LOG(info) << "=================================================="; + LOG(info) << GetName() << ": Initialising..."; + + // --- Input data + fEvents = ioman->InitObjectAs<const std::vector<CbmDigiEvent>*>("DigiEvent"); + if (!fEvents) { + LOG(error) << GetName() << ": No input branch DigiEvent!"; + return kFATAL; + } + LOG(info) << "--- Found branch DigiEvent"; + + LOG(info) << "=================================================="; + return kSUCCESS; +} +// ---------------------------------------------------------------------------- + + +ClassImp(CbmTaskInspectDigiEvents) diff --git a/reco/tasks/CbmTaskInspectDigiEvents.h b/reco/tasks/CbmTaskInspectDigiEvents.h new file mode 100644 index 0000000000000000000000000000000000000000..680786bbf5beb0405d667eac77b7359f3df48e6f --- /dev/null +++ b/reco/tasks/CbmTaskInspectDigiEvents.h @@ -0,0 +1,62 @@ +/* Copyright (C) 2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Volker Friese [committer] */ + +#pragma once + + +#include "CbmDefs.h" +#include "CbmDigiEvent.h" + +#include <FairTask.h> + +#include <vector> + + +/** @class CbmTaskInspectDigiEvents + ** @brief Demonstrator class to look at digi events in the ROOT tree + ** @author Volker Friese <v.friese@gsi.de> + ** @since 19.03.2024 + ** + ** This is just a demonstrator how to look at DigiEvents in the ROOT tree. It logs some information to the console. + **/ +class CbmTaskInspectDigiEvents : public FairTask { + + public: + /** @brief Constructor **/ + CbmTaskInspectDigiEvents(); + + + /** @brief Copy constructor (disabled) **/ + CbmTaskInspectDigiEvents(const CbmTaskInspectDigiEvents&) = delete; + + + /** @brief Destructor **/ + virtual ~CbmTaskInspectDigiEvents(); + + + /** @brief Task execution **/ + virtual void Exec(Option_t* opt); + + + /** @brief Finish timeslice **/ + virtual void Finish(); + + + /** @brief Assignment operator (disabled) **/ + CbmTaskInspectDigiEvents& operator=(const CbmTaskInspectDigiEvents&) = delete; + + + private: // methods + /** @brief Task initialisation **/ + virtual InitStatus Init(); + + + private: // members + const std::vector<CbmDigiEvent>* fEvents = nullptr; //! Input data (events) + size_t fNumTs = 0; ///< Number of processed timeslices + size_t fNumEvents = 0; ///< Number of analysed events + + + ClassDef(CbmTaskInspectDigiEvents, 1); +};