diff --git a/core/data/CMakeLists.txt b/core/data/CMakeLists.txt index 57cfea793442d17eadea422c85e72a681a2ca140..b5b59dd07855d9e7f8fb17bbd151c570757e7563 100644 --- a/core/data/CMakeLists.txt +++ b/core/data/CMakeLists.txt @@ -23,6 +23,7 @@ set(SRCS CbmAddress.cxx CbmTimeSlice.cxx CbmEvent.cxx + CbmEventTriggers.cxx CbmEventStore.cxx CbmHit.cxx CbmPixelHit.cxx diff --git a/core/data/CbmDataLinkDef.h b/core/data/CbmDataLinkDef.h index 1a110af4802ca2f8190424bac2b0e5b3eca21a55..b418995a9fd6172f5b98464b855627f419d9dd94 100644 --- a/core/data/CbmDataLinkDef.h +++ b/core/data/CbmDataLinkDef.h @@ -12,6 +12,7 @@ #pragma link C++ class CbmTimeSlice; #pragma link C++ class CbmDigiBranchBase + ; #pragma link C++ class CbmEvent + ; +#pragma link C++ class CbmEventTriggers + ; #pragma link C++ class CbmEventStore + ; #pragma link C++ class CbmHit + ; #pragma link C++ class CbmMCTrack + ; @@ -28,6 +29,8 @@ #pragma link C++ class CbmErrorMessage + ; #pragma link C++ class CbmTsEventHeader + ; #pragma link C++ class std::vector < CbmErrorMessage> + ; +#pragma link C++ class std::vector < CbmEventTriggers> + ; +#pragma link C++ enum CbmEventTriggers::ETrigger; // ---In base #pragma link C++ class CbmDigiBranchBase + ; diff --git a/core/data/CbmEventTriggers.cxx b/core/data/CbmEventTriggers.cxx new file mode 100644 index 0000000000000000000000000000000000000000..d6e52d96d7e8fd943cd46c075b37a516ff6ae8b5 --- /dev/null +++ b/core/data/CbmEventTriggers.cxx @@ -0,0 +1,25 @@ +/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file CbmEventTriggers.h +/// \brief A structure to store different triggers in parallel to the CbmEvent (implementation) +/// \since 25.01.2025 +/// \author Sergei Zharko <s.zharko@gsi.de> + +#include "CbmEventTriggers.h" + +#include <sstream> + +// --------------------------------------------------------------------------------------------------------------------- +// +std::string CbmEventTriggers::ToString() const +{ + std::stringstream msg; + msg << "CbmEventTriggers: Lambda " << Test(ETrigger::Lambda) << ", Ks " << Test(ETrigger::Ks); + return msg.str(); +} + +#ifndef NO_ROOT +ClassImp(CbmEventTriggers) +#endif diff --git a/core/data/CbmEventTriggers.h b/core/data/CbmEventTriggers.h new file mode 100644 index 0000000000000000000000000000000000000000..ce1b8de535825650cfb3e6cbf77661bbf44c36c5 --- /dev/null +++ b/core/data/CbmEventTriggers.h @@ -0,0 +1,78 @@ +/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file CbmEventTriggers.h +/// \brief A structure to store different triggers in parallel to the CbmEvent +/// \since 25.01.2025 +/// \author Sergei Zharko <s.zharko@gsi.de> + +#pragma once + +#if !defined(NO_ROOT) && !XPU_IS_HIP_CUDA +#include <Rtypes.h> // for ClassDef +#endif + +/// \class CbmEventTriggers +/// \brief Class to store different triggers for a given event +class CbmEventTriggers { + public: + /// \enum ETrigger + /// \brief Defines a trigger address + enum class ETrigger : uint8_t + { + Lambda = 0b00000001, ///< Lambda-trigger + Ks = 0b00000010 ///< Ks-trigger + }; + + //using Trigger_t = std::underlying_type_t<ETrigger>; + using Trigger_t = uint8_t; + + /// \brief Default constructor + CbmEventTriggers() = default; + + /// \brief Copy constructor + CbmEventTriggers(const CbmEventTriggers&) = default; + + /// \brief Move constructor + CbmEventTriggers(CbmEventTriggers&&) = default; + + /// \brief Destructor + ~CbmEventTriggers() = default; + + /// \brief Copy assignment operator + CbmEventTriggers& operator=(const CbmEventTriggers&) = default; + + /// \brief Move assignment operator + CbmEventTriggers& operator=(CbmEventTriggers&&) = default; + + /// \brief Sets a trigger + /// \param key Trigger key + void Set(ETrigger key) { fTriggers |= static_cast<Trigger_t>(key); } + + /// \brief Resets a trigger + /// \param key Trigger key + void Reset(ETrigger key) { fTriggers &= ~static_cast<Trigger_t>(key); } + + /// \brief Tests a particular single trigger + /// \param key Trigger key + bool Test(ETrigger key) const { return static_cast<bool>(fTriggers & static_cast<Trigger_t>(key)); } + + /// \brief Tests, if ALL the triggers in the mask are on + /// \param mask Trigger mask + bool TestAll(Trigger_t mask) const { return mask == (fTriggers & mask); } + + /// \brief Tests, if ANY of the triggers in the mask are on + /// \param mask Trigger mask + bool TestAny(Trigger_t mask) const { return static_cast<bool>(fTriggers | mask); } + + /// \brief String representation of the class content + std::string ToString() const; + + private: + Trigger_t fTriggers; + +#if !defined(NO_ROOT) && !XPU_IS_HIP_CUDA + ClassDefNV(CbmEventTriggers, 1); +#endif +}; diff --git a/macro/beamtime/mcbm2024/reco_mcbm.sh b/macro/beamtime/mcbm2024/reco_mcbm.sh index bda9fb5f80d37654110cbfccc7388e6c7046381c..c3053f4cd7c8036431ab4398337a166f76bc2682 100755 --- a/macro/beamtime/mcbm2024/reco_mcbm.sh +++ b/macro/beamtime/mcbm2024/reco_mcbm.sh @@ -262,26 +262,15 @@ else DIR_KFPF=$(realpath -m ${DIR_KFPF}) fi -printf "\n" -printf "\n" -printf "\t********************************************************************************************\n" -printf "\t*** ***\n" -printf "\t*** --- The Compressed Baryonic Matter Experiment: Data Reconstruction Routine --- ***\n" -printf "\t*** ***\n" -printf "\t********************************************************************************************\n\n\n" - +# ----- Check the environment +# +if [[ -z "${VMCWORKDIR}" ]]; then + printf "E- CBM environment is not defined (VMCWORKDIR is not found). Please, configure your CbmRoot\n" + exit 1 +fi -printf "***\n" -printf "*** Data directories:\n" -printf "***\n\n" -printf "\tSetup: ${DIR_SETUP}\n" -printf "\tUnpacking output: ${DIR_UNPACK}\n" -printf "\tReconstruction output: ${DIR_RECO}\n" -printf "\tQA output: ${DIR_QA}\n" -printf "\tKFPF output: ${DIR_KFPF}\n\n\n" - -# ----- Redifine the TSA input, if the TSA index and job were provided +# ----- Redefine the TSA input, if the TSA index and job were provided # # TODO: Add check on the integer for JOB_ID if [[ ${TSA_INDEX} != 0 && ! -z ${TSA_INDEX} ]]; then @@ -290,23 +279,6 @@ if [[ ${TSA_INDEX} != 0 && ! -z ${TSA_INDEX} ]]; then fi TSA=$(sed -n "${JOB_ID}p" "${TSA_INDEX}") fi -printf "***\n" -printf "*** Input:\n" -printf "***\n\n" -printf "\tTSA: ${TSA}\n" -printf "\tJOB: ${JOB_ID}\n" -printf "\tROUTINE STEPS: ${STEPS_TO_PRINT}\n" -printf "\n\n" - - - - -# ----- Check the environment -# -if [[ -z "${VMCWORKDIR}" ]]; then - printf "E- CBM environment is not defined (VMCWORKDIR is not found). Please, configure your CbmRoot\n" - exit 1 -fi # ----- Select the reconstruction binary ONLINE_BINARY="${VMCWORKDIR}/../../bin/cbmreco" @@ -328,6 +300,13 @@ fi # The run_info must be in the same directory as the cbmreco RUN_INFO=${ONLINE_BINARY%/*}/run_info +if [[ ! -x ${RUN_INFO} ]]; then + printf "E- the run_info binary was not found. It must be in the same bin directory, as the cbmreco binary. " + printf "At this point such an error might not happen, but never the less it did, so please provide the " + printf "path to the run_info binary in PATH manually.\n" + exit 2 +fi + printf "I- Online binary path: %s, with parameters: %s\n" ${ONLINE_BINARY} ${ONLINE_PAR} @@ -382,7 +361,7 @@ MACRO_QA_MODULE="${VMCWORKDIR}/macro/qa/run_recoQa.C" MACRO_KFPF="${VMCWORKDIR}/macro/mcbm/mcbm_hadron_kfp_ana.C" SETUP_NAME=$(${RUN_INFO} --run ${RUN} --geotag) -# ----- !!! Setting selections vs. run number +# ----- Setting selections vs. run number # if [[ ${RUN} -ge 2350 && ${RUN} -le 2610 ]]; then MACRO_RECO="${VMCWORKDIR}/macro/beamtime/mcbm2022/mcbm_event_reco_L1.C" @@ -419,6 +398,29 @@ RECO_QA_LOG="run_mcbm_reco_qa.log" QA_LOG="run_mcbm_qa.log" KFPF_LOG="run_mcbm_kfpf.log" + +printf "\n" +printf "\n" +printf "\t********************************************************************************************\n" +printf "\t*** ***\n" +printf "\t*** --- The Compressed Baryonic Matter Experiment: Data Reconstruction Routine --- ***\n" +printf "\t*** ***\n" +printf "\t********************************************************************************************\n\n\n" + +printf "\tSetup: ${DIR_SETUP}\n" +printf "\tUnpacking output: ${DIR_UNPACK}\n" +printf "\tReconstruction output: ${DIR_RECO}\n" +printf "\tQA output: ${DIR_QA}\n" +printf "\tKFPF output: ${DIR_KFPF}\n\n\n" +printf "\n" +printf "\tTSA: ${TSA}\n" +printf "\tJOB: ${JOB_ID}\n" +printf "\tROUTINE STEPS: ${STEPS_TO_PRINT}\n" +printf "\n" +printf "\tGEOMETRY FILE: ${SETUP_GEO_FILE}\n" + + + # ********************* # ** Steps execution ** # ********************* @@ -568,7 +570,7 @@ if [[ ${DO_LAMBDA} -eq 1 ]]; then LAMBDA_IN_REC=${RECO_FILE} LAMBDA_IN_TRA="\"\",\"\",\"\"" # Empty for real data LAMBDA_OUT="${DIR_KFPF}/${FILE_LABEL}.kfp.ana.root" - LAMBDA_IN_GEO=${SETUP_QA_LOG} + LAMBDA_IN_GEO=${SETUP_GEO_FILE} LAMBDA_IN_PAR=${RECO_PAR_FILE} LAMBDA_USE_MC="false" PARS="${RUN},${LAMBDA_FST_TS},${LAMBDA_LST_TS},\"${LAMBDA_IN_REC}\",${LAMBDA_IN_TRA},\"${LAMBDA_OUT}\",\"${LAMBDA_IN_GEO}\"" diff --git a/reco/KF/CbmKFV0FinderTask.cxx b/reco/KF/CbmKFV0FinderTask.cxx index e29f13b209a93097ff275ef9de6e904af38f9141..bb4d223a111923a020f7d9beb866ebb2d957a8bc 100644 --- a/reco/KF/CbmKFV0FinderTask.cxx +++ b/reco/KF/CbmKFV0FinderTask.cxx @@ -10,6 +10,7 @@ #include "CbmKFV0FinderTask.h" #include "CbmEvent.h" +#include "CbmEventTriggers.h" #include "CbmGlobalTrack.h" #include "CbmKfTarget.h" #include "CbmStsHit.h" @@ -192,6 +193,8 @@ bool V0FinderTask::ProcessEvent(const CbmEvent* pEvent) } fCounters[ECounter::KfpLambdaCandidates] += nLambda; if (nLambda > 0) { + auto& triggers = (*fpBrEventTriggers)[pEvent ? pEvent->GetNumber() : 0]; + triggers.Set(CbmEventTriggers::ETrigger::Lambda); ++fCounters[ECounter::KfpEventsLambdaCand]; } @@ -320,11 +323,16 @@ void V0FinderTask::Exec(Option_t*) // ----- Process timeslice if (EProcessingMode::EventBased == fProcessingMode) { ++fCounters[ECounter::EventsTotal]; + fpBrEventTriggers->clear(); + fpBrEventTriggers->resize(1); ProcessEvent</*UseEvent = */ false>(nullptr); } else { const int nEvents{fpBrRecoEvents->GetEntriesFast()}; + fCounters[ECounter::EventsTotal] += nEvents; + fpBrEventTriggers->clear(); + fpBrEventTriggers->resize(nEvents); for (int iEvent = 0; iEvent < nEvents; ++iEvent) { const auto* pEvent = static_cast<CbmEvent*>(fpBrRecoEvents->At(iEvent)); ProcessEvent</*UseEvent = */ true>(pEvent); @@ -458,6 +466,15 @@ InitStatus V0FinderTask::Init() return kERROR; } + // ----- Output branches initialization + fpBrEventTriggers = new std::vector<CbmEventTriggers>(); + if (pFairManager->GetObject("CbmEventTriggers")) { + LOG(error) << "Branch \"CbmEventTriggers\" already exists!"; + return kFATAL; + } + pFairManager->RegisterAny("CbmEventTriggers", fpBrEventTriggers, true); + LOG_(info, 1) << "registering branch \"CbmEventTriggers\""; + // ----- Topology reconstructor initialization fpTopoReconstructorRun->SetTarget({float(pTarget->GetX()), float(pTarget->GetY()), float(pTarget->GetZ())}); fpTopoReconstructorEvent->SetTarget(fpTopoReconstructorRun->GetTargetPosition()); diff --git a/reco/KF/CbmKFV0FinderTask.h b/reco/KF/CbmKFV0FinderTask.h index 6fb0bbf3683a55efe454a2c901b1e4259c547312..caf2a237933cdcecdddd4cabda4189f571928d00 100644 --- a/reco/KF/CbmKFV0FinderTask.h +++ b/reco/KF/CbmKFV0FinderTask.h @@ -30,6 +30,7 @@ class FairTrackParam; class KFPTrackVector; class KFVertex; class KFParticleFinder; +class CbmEventTriggers; namespace cbm::kfp { @@ -144,6 +145,14 @@ namespace cbm::kfp /// \brief Gets DCA to origin const auto& GetTrackDcaToOrigin() const { return fvTrackDca; } + /// \brief Accessor to the topology reconstructor + const std::shared_ptr<const KFParticleTopoReconstructor> GetTopoReconstructor() const + { + return fpTopoReconstructorRun; + } + + /// \brief Accessor to the track DCA + //const //* Task logic and preliminary selection cut setters @@ -418,7 +427,7 @@ namespace cbm::kfp double fQpAssignedUncertainty{0.1}; ///< Assigned relative uncertainty for q/p estimation int fPrimaryAssignedPdg{321}; ///< Assigned PDG hypothesis for primary particles - //* Input data + //* Input data branches TClonesArray* fpBrRecoEvents{nullptr}; TClonesArray* fpBrGlobalTracks{nullptr}; TClonesArray* fpBrStsTracks{nullptr}; @@ -429,6 +438,10 @@ namespace cbm::kfp TClonesArray* fpBrTofHits{nullptr}; CbmVertex* fpBrPrimaryVertex{nullptr}; + //* Output data branches + std::vector<CbmEventTriggers>* fpBrEventTriggers{nullptr}; //< Branch for event triggers + // TODO: in principle one can store the found KF particles and vertices as well + //* Temporary data and auxilary variables (per FairTask::Exec() call) std::vector<DcaVector> fvTrackDca; ///< Track DCA vector [n selected tracks] std::unique_ptr<CbmVertex> fpOrigin{ @@ -437,8 +450,8 @@ namespace cbm::kfp //* KFParticleFinder utilities /// \brief Main topology reconstructor // Main topology reconstructor - std::unique_ptr<KFParticleTopoReconstructor> fpTopoReconstructorRun{ - std::make_unique<KFParticleTopoReconstructor>()}; + std::shared_ptr<KFParticleTopoReconstructor> fpTopoReconstructorRun{ + std::make_shared<KFParticleTopoReconstructor>()}; std::unique_ptr<KFParticleTopoReconstructor> fpTopoReconstructorEvent{ std::make_unique<KFParticleTopoReconstructor>()}; diff --git a/reco/KF/KFParticleInterfaceLinkDef.h b/reco/KF/KFParticleInterfaceLinkDef.h index f04b91c6bfabbb23d96543641e92d98deabe5291..03efa8422dc4382c6997032def48243802aa8423 100644 --- a/reco/KF/KFParticleInterfaceLinkDef.h +++ b/reco/KF/KFParticleInterfaceLinkDef.h @@ -14,5 +14,6 @@ #pragma link C++ class CbmKFParticleInterface + ; #pragma link C++ class cbm::kfp::V0FinderTask + ; #pragma link C++ class cbm::kfp::V0FinderQa + ; +#pragma link C++ class std::vector < KFParticle> + ; #endif