Skip to content
Snippets Groups Projects
Commit 416c22db authored by Volker Friese's avatar Volker Friese
Browse files

Implementation of a hit multiplicity trigger

parent 816cb880
No related branches found
No related tags found
No related merge requests found
Pipeline #29131 failed
......@@ -86,6 +86,7 @@ set(SRCS
evbuild/EventBuilderConfig.cxx
evbuild/EventbuildChain.cxx
trigger/DigiTriggerConfig.cxx
trigger/HitMultTrigger.cxx
trigger/TimeClusterTrigger.cxx
trigger/V0Trigger.cxx
trigger/V0TriggerConfig.cxx
......
......@@ -14,6 +14,7 @@ namespace cbm::algo::evbuild
// ----- Constructor from YAML --------------------------------------------
Config::Config(YAML::Node node)
: fDigiTrigger(node["trigger"])
, fHitMultTrigger(node["hit_mult_trigger"])
, fV0Trigger(node["v0trigger"])
, fBuilder(node["eventbuilder"])
, fSelector(node["selector"])
......@@ -27,7 +28,8 @@ namespace cbm::algo::evbuild
YAML::Node Config::ToYaml() const
{
YAML::Node result;
result["digitrigger"] = fDigiTrigger.ToYaml(); // Digi trigger config
result["trigger"] = fDigiTrigger.ToYaml(); // Digi trigger config
result["hit_mult_trigger"] = fHitMultTrigger.ToYaml(); // Hit multiplicity trigger config
result["v0trigger"] = fV0Trigger.ToYaml(); // V0 trigger config
result["eventbuilder"] = fBuilder.ToYaml(); // Event builder config
result["selector"] = fSelector.ToYaml(); // Event selector config
......
......@@ -31,6 +31,7 @@ namespace cbm::algo::evbuild
public: // data members
DigiTriggerConfig fDigiTrigger; ///< Digi trigger configuration
DigiTriggerConfig fHitMultTrigger; ///< Hit multiplicity trigger configuration
V0TriggerConfig fV0Trigger; ///< V0 trigger configuration
EventBuilderConfig fBuilder; ///< Event builder configuration
DigiEventSelectorConfig fSelector; ///< Event selector configuration
......
......@@ -20,7 +20,8 @@ using namespace cbm::algo::evbuild;
EventbuildChain::EventbuildChain(const Config& config, std::shared_ptr<HistogramSender> sender)
: fConfig(config)
, fTriggerDet(config.fDigiTrigger.Detector())
, fDigiTrigger(config.fDigiTrigger)
, fDigiMultTrigger(config.fDigiTrigger.Window(), config.fDigiTrigger.Threshold(), config.fDigiTrigger.DeadTime())
, fHitMultTrigger(config.fHitMultTrigger)
, fV0Trigger()
, fBuilder(config.fBuilder)
, fSelector(config.fSelector)
......@@ -66,7 +67,7 @@ EventbuildChain::~EventbuildChain() {}
typedef cbm::algo::ca::Vector<cbm::algo::ca::Track> TrackVector;
EventbuildChain::ResultType EventbuildChain::Run(const DigiData& digiData,
const cbm::algo::ca::Vector<cbm::algo::ca::Track>& tracks)
const RecoResults& recoData)
{
// --- Local variables
......@@ -75,17 +76,24 @@ EventbuildChain::ResultType EventbuildChain::Run(const DigiData& digiData,
// --- If V0Trigger is configured, use it
if (fConfig.fV0Trigger.IsSet()) {
auto [v0Triggers, v0TriggerMon] = fV0Trigger(tracks, fConfig.fV0Trigger);
auto [v0Triggers, v0TriggerMon] = fV0Trigger(recoData.tracks, fConfig.fV0Trigger);
triggers = std::move(v0Triggers);
result.second.v0Trigger = std::move(v0TriggerMon);
}
// --- Else, check the hit multiplicity trigger
if ( fConfig.fHitMultTrigger.IsSet()) {
auto [hitTriggers, digiTriggerMon] = fHitMultTrigger(recoData);
triggers = std::move(hitTriggers);
result.second.hitMultTrigger = std::move(digiTriggerMon);
}
// --- Else, use the digi multiplicity trigger
else if (fConfig.fDigiTrigger.IsSet()) {
std::vector<double> digiTimes = GetDigiTimes(digiData, fTriggerDet);
auto [digiTriggers, digiTriggerMon] = fDigiTrigger(digiTimes);
auto [digiTriggers, digiTriggerMon] = fDigiMultTrigger(digiTimes);
triggers = std::move(digiTriggers);
result.second.digiTrigger = std::move(digiTriggerMon);
result.second.digiMultTrigger = std::move(digiTriggerMon);
}
// --- Else, throw exception
......@@ -123,9 +131,11 @@ void EventbuildChain::Status() const
L_(info) << "=== Eventbuilder configuration ===================";
if (fConfig.fV0Trigger.IsSet())
L_(info) << fV0Trigger.ToString();
else if (fConfig.fHitMultTrigger.IsSet())
L_(info) << fHitMultTrigger.ToString();
else {
L_(info) << "--- Using digi multiplicity trigger with trigger detector " << ::ToString(fTriggerDet);
L_(info) << fDigiTrigger.ToString();
L_(info) << fDigiMultTrigger.ToString();
}
L_(info) << fBuilder.ToString();
L_(info) << fSelector.ToString();
......
......@@ -11,6 +11,7 @@
#include "DigiEventSelector.h"
#include "EventBuilder.h"
#include "HistogramSender.h"
#include "HitMultTrigger.h"
#include "RecoResults.h"
#include "SubChain.h"
#include "TimeClusterTrigger.h"
......@@ -28,7 +29,8 @@ namespace cbm::algo::evbuild
struct EventbuildChainMonitorData {
EventBuilderMonitorData evbuild;
TimeClusterTriggerMonitorData digiTrigger;
TimeClusterTriggerMonitorData digiMultTrigger;
TimeClusterTriggerMonitorData hitMultTrigger;
V0TriggerMoniData v0Trigger;
};
......@@ -54,7 +56,7 @@ namespace cbm::algo::evbuild
~EventbuildChain();
/** @brief Execution **/
ResultType Run(const DigiData&, const cbm::algo::ca::Vector<cbm::algo::ca::Track>&);
ResultType Run(const DigiData&, const RecoResults&);
/** @brief Status info to logger **/
void Status() const;
......@@ -65,7 +67,8 @@ namespace cbm::algo::evbuild
private: // members
Config fConfig; ///< Global configuration
ECbmModuleId fTriggerDet = ECbmModuleId::kNotExist; ///< Trigger detector
TimeClusterTrigger fDigiTrigger; ///< Digi multiplicity trigger algorithm
TimeClusterTrigger fDigiMultTrigger; ///< Digi multiplicity trigger algorithm
HitMultTrigger fHitMultTrigger; ///< Hit multiplicity trigger algorithm
V0Trigger fV0Trigger; ///< V0 trigger algorithm
EventBuilder fBuilder; ///< Event builder algorithm
DigiEventSelector fSelector; ///< Event selector algorithm
......
......@@ -211,7 +211,8 @@ RecoResults Reco::Run(const fles::Timeslice& ts)
ProcessingMonitor procMon;
RecoResults results;
RecoResults recoData; /// transient
RecoResults results; /// persistent (return object)
{
xpu::scoped_timer t_(fmt::format("TS {}", ts.index()), &procMon.time);
xpu::t_add_bytes(ts_utils::SizeBytes(ts));
......@@ -251,16 +252,16 @@ RecoResults Reco::Run(const fles::Timeslice& ts)
}
sts::HitfinderMon stsHitfinderMonitor;
PartitionedSpan<sts::Hit> stsHits;
PartitionedVector<sts::Cluster> stsClusters;
if (fStsHitFinder) {
bool storeClusters = Opts().HasOutput(RecoData::Cluster);
auto stsResults = (*fStsHitFinder)(digis.fSts, storeClusters);
stsHits = stsResults.hits;
stsClusters = std::move(stsResults.clusters);
stsHitfinderMonitor = std::move(stsResults.monitor);
recoData.stsHits = stsResults.hits;
;
recoData.stsClusters = std::move(stsResults.clusters);
QueueStsRecoMetrics(stsHitfinderMonitor);
}
L_(info) << "TS contains " << recoData.stsHits.NElements() << " STS Hits";
PartitionedVector<tof::Hit> tofHits;
if (Opts().Has(Step::LocalReco) && Opts().Has(fles::Subsystem::TOF)) {
......@@ -269,13 +270,12 @@ RecoResults Reco::Run(const fles::Timeslice& ts)
if (nUnknownRPC > 0) {
L_(error) << "TOF Digis with unknown RPCs: " << nUnknownRPC;
}
auto [hits, hitmonitor, digiindices] = (*fTofHitFinder)(caldigis);
tofHits = std::move(hits);
recoData.tofHits = std::move(hits);
QueueTofCalibMetrics(calmonitor);
QueueTofRecoMetrics(hitmonitor);
}
L_(info) << "TS contains " << tofHits.NElements() << " TOF Hits";
L_(info) << "TS contains " << recoData.tofHits.NElements() << " TOF Hits";
PartitionedVector<trd::Hit> trdHits;
......@@ -288,20 +288,21 @@ RecoResults Reco::Run(const fles::Timeslice& ts)
std::copy(digis1d.begin(), digis1d.end(), std::back_inserter(allDigis));
std::copy(digis2d.begin(), digis2d.end(), std::back_inserter(allDigis));
auto trdResults = (*fTrdHitfind)(allDigis);
trdHits = std::move(std::get<0>(trdResults));
recoData.trdHits = std::move(std::get<0>(trdResults));
QueueTrdRecoMetrics(std::get<1>(trdResults));
L_(info) << "TS has " << trdHits.NElements() << " TRD hits.";
L_(info) << "TS contains " << recoData.trdHits.NElements() << " TRD hits.";
}
// --- Tracking
TrackingChain::Output_t trackingOutput{};
if (Opts().Has(Step::Tracking)) {
TrackingChain::Input_t input{
.stsHits = stsHits,
.tofHits = tofHits,
.trdHits = trdHits,
.stsHits = recoData.stsHits,
.tofHits = recoData.tofHits,
.trdHits = recoData.trdHits,
};
trackingOutput = fTracking->Run(input);
recoData.tracks = std::move(trackingOutput.tracks);
QueueTrackingMetrics(trackingOutput.monitorData);
}
......@@ -309,13 +310,13 @@ RecoResults Reco::Run(const fles::Timeslice& ts)
std::vector<DigiEvent> events;
evbuild::EventbuildChainMonitorData evbuildMonitor;
if (Opts().Has(Step::DigiTrigger)) {
auto [ev, mon] = fEventBuild->Run(digis, trackingOutput.tracks);
auto [ev, mon] = fEventBuild->Run(digis, recoData);
events = std::move(ev);
evbuildMonitor = mon;
QueueEvbuildMetrics(evbuildMonitor);
}
// --- Filter data for output
if (Opts().HasOutput(RecoData::DigiTimeslice)) {
results.bmonDigis = std::move(digis.fBmon);
results.stsDigis = std::move(digis.fSts);
......@@ -326,16 +327,16 @@ RecoResults Reco::Run(const fles::Timeslice& ts)
results.richDigis = std::move(digis.fRich);
}
if (Opts().HasOutput(RecoData::Track)) {
results.tracks = std::move(trackingOutput.tracks);
results.tracks = std::move(recoData.tracks);
results.trackStsHitIndices = std::move(trackingOutput.stsHitIndices);
results.trackTofHitIndices = std::move(trackingOutput.tofHitIndices);
}
if (Opts().HasOutput(RecoData::DigiEvent)) results.events = std::move(events);
if (Opts().HasOutput(RecoData::Cluster)) results.stsClusters = std::move(stsClusters);
if (Opts().HasOutput(RecoData::Cluster)) results.stsClusters = std::move(recoData.stsClusters);
if (Opts().HasOutput(RecoData::Hit)) {
results.stsHits = std::move(stsHits);
results.tofHits = std::move(tofHits);
results.trdHits = std::move(trdHits);
results.stsHits = std::move(recoData.stsHits);
results.tofHits = std::move(recoData.tofHits);
results.trdHits = std::move(recoData.trdHits);
}
}
PrintTimings(procMon.time);
......@@ -506,8 +507,10 @@ void Reco::QueueEvbuildMetrics(const evbuild::EventbuildChainMonitorData& mon)
double totalSelectionRatio = nDigisTotal > 0 ? double(nDigisInEventsTotal) / nDigisTotal : 0;
GetMonitor().QueueMetric("cbmreco", tags,
{{"digiTriggerTimeTotal", mon.digiTrigger.time.wall()},
{"digiTriggerThroughput", mon.digiTrigger.time.throughput()},
{{"digiTriggerTimeTotal", mon.digiMultTrigger.time.wall()},
{"digiTriggerThroughput", mon.digiMultTrigger.time.throughput()},
{"hitTriggerTimeTotal", mon.hitMultTrigger.time.wall()},
{"hitTriggerThroughput", mon.hitMultTrigger.time.throughput()},
{"v0TriggerNumTrackPairs", mon.v0Trigger.numTrackPairs},
{"v0TriggerNumTrackPairsCoinc", mon.v0Trigger.numTrackPairsAfterTimeCut},
{"v0TriggerErrTracksUnsorted", mon.v0Trigger.errTracksUnsorted},
......@@ -515,7 +518,7 @@ void Reco::QueueEvbuildMetrics(const evbuild::EventbuildChainMonitorData& mon)
{"v0TriggerThroughput", mon.v0Trigger.time.throughput()},
{"eventbuildTimeTotal", mon.evbuild.time.wall()},
{"eventbuildThroughput", mon.evbuild.time.throughput()},
{"numTrigger", mon.digiTrigger.nTriggers},
{"numTrigger", mon.digiMultTrigger.nTriggers},
{"numEvents", mon.evbuild.nEvents},
{"totalEvSelectionRatio", totalSelectionRatio}});
}
......
......@@ -18,8 +18,7 @@ TEST(_GTestTimeClusterTrigger, CheckTriggerAlgorithmSimple)
const double windowSize = 1000.;
const uint nMinNumber = 100;
DigiTriggerConfig config = {ECbmModuleId::kSts, windowSize, nMinNumber, deadTime};
TimeClusterTrigger trigger(config);
TimeClusterTrigger trigger(windowSize, nMinNumber, deadTime);
std::vector<double> dataIn;
for (uint i = 0; i < nInput; i++) {
......
/* Copyright (C) 2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
SPDX-License-Identifier: GPL-3.0-only
Authors: Volker Friese [committer], Dominik Smith */
#include "HitMultTrigger.h"
#include "CbmStsHit.h"
#include "CbmTofHit.h"
#include "CbmTrdHit.h"
#include <iterator>
#include <sstream>
#include <xpu/host.h>
namespace cbm::algo::evbuild
{
// ----- Execution ------------------------------------------------------
HitMultTrigger::Result HitMultTrigger::operator()(const RecoResults& recoData) const
{
xpu::push_timer("HitMultTrigger");
xpu::t_add_bytes(1);
Result result;
auto hitTimes = GetHitTimes(recoData, fConfig.Detector());
auto [triggers, moniData] = fAlgo(hitTimes);
result.first = std::move(triggers);
result.second = std::move(moniData);
result.second.time = xpu::pop_timer();
L_(info) << "HitMultTrigger: hits " << hitTimes.size() << ", triggers " << result.first.size();
return result;
};
// --------------------------------------------------------------------------
// ----- Get hit times from reconstructed data --------------------------
std::vector<double> HitMultTrigger::GetHitTimes(const RecoResults& recoResults, ECbmModuleId system) const
{
std::vector<double> result;
switch (system) {
case ECbmModuleId::kSts: return GetTimeStamps<cbm::algo::sts::Hit>(recoResults.stsHits.Data()); break;
case ECbmModuleId::kTrd: return GetTimeStamps<cbm::algo::trd::Hit>(recoResults.trdHits.Data()); break;
case ECbmModuleId::kTof: return GetTimeStamps<cbm::algo::tof::Hit>(recoResults.tofHits.Data()); break;
default: {
L_(error) << "HitMultTrigger::GetHitTimes: Unknown system " << system;
break;
}
} //? system
return result;
}
// --------------------------------------------------------------------------
// ----- Info to string ---------------------------------------------------
std::string HitMultTrigger::ToString() const
{
std::stringstream out;
out << "--- Using Hit Multiplicity Trigger with trigger detector " << ::ToString(fConfig.Detector());
out << "\n" << fAlgo.ToString();
return out.str();
}
// --------------------------------------------------------------------------
} // namespace cbm::algo::evbuild
/* 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 "DigiTriggerConfig.h"
#include "RecoResults.h"
#include "TimeClusterTrigger.h"
#include <utility>
#include <vector>
#include <xpu/host.h>
namespace cbm::algo::evbuild
{
/** @class HitMultTrigger
** @brief Trigger class for finding time clusters of hit data
** @author Volker Friese <v.friese@gsi.de>
** @date 30 April 2024
**
** The class takes as input an array of detector hits. It finds clusters of hits in time, using the generic TimeClusterTrigger algorithm.
**/
class HitMultTrigger {
public:
typedef std::pair<std::vector<double>, TimeClusterTriggerMonitorData> Result;
/** @brief Constructor
** @param config Trigger configuration
**/
HitMultTrigger(const DigiTriggerConfig& config)
: fConfig(config)
, fAlgo(config.Window(), config.Threshold(), config.DeadTime()){};
/** @brief Execution
** @param recoData Container of reco data
** @return Vector of trigger times and monitoring data
**/
Result operator()(const RecoResults& recoData) const;
/** @brief Info to string **/
std::string ToString() const;
private: // methods
/** @brief Extract the hit time stamps for the selected trigger detector
** @param recoData Container of reco results
** @param system Trigger Detector
** @return Sorted vector of hit time stamps
**/
std::vector<double> GetHitTimes(const RecoResults& recoData, ECbmModuleId system) const;
/** @brief Get vector of time stamps from a data container [template]
** @param data Data container
** @return Sorted vector of time stamps
**/
template<class T>
std::vector<double> GetTimeStamps(const gsl::span<const T> data) const
{
std::vector<double> result;
result.resize(data.size());
std::transform(data.begin(), data.end(), result.begin(), [](const T& hit) { return hit.Time(); });
std::sort(result.begin(), result.end());
return result;
}
private: // members
DigiTriggerConfig fConfig; ///< Configuration
TimeClusterTrigger fAlgo; ///< Algorithm
};
} // namespace cbm::algo::evbuild
......@@ -27,11 +27,6 @@ namespace cbm::algo::evbuild
xpu::push_timer("TimeClusterTrigger");
xpu::t_add_bytes(dataVec.size() * sizeof(double));
// --- Parameters
double winSize = fConfig.Window();
int32_t minNumData = fConfig.Threshold();
double deadTime = fConfig.DeadTime();
// --- Output data
resultType result = {};
vector<double>& triggerVec = result.first;
......@@ -43,11 +38,11 @@ namespace cbm::algo::evbuild
while (current != dataVec.end()) {
// If window size is exceeded, adjust window start
while (*current - *winStart > winSize)
while (*current - *winStart > fWinSize)
winStart++;
// Create trigger if threshold is reached
if (std::distance(winStart, current) >= minNumData - 1) {
if (std::distance(winStart, current) >= fMinNumData - 1) {
triggerVec.push_back(0.5 * (*current + *winStart));
// Increment monitoring counter with number of digis used
......@@ -55,7 +50,7 @@ namespace cbm::algo::evbuild
// Start new window after dead time
winStart = current + 1;
while (winStart != dataVec.end() && *winStart - *current <= deadTime)
while (winStart != dataVec.end() && *winStart - *current <= fDeadTime)
winStart++;
current = winStart;
}
......@@ -77,9 +72,9 @@ namespace cbm::algo::evbuild
string TimeClusterTrigger::ToString() const
{
stringstream out;
out << "--- Using TimeClusterTrigger with trigger window " << fConfig.Window() << " ns";
out << ", threshold " << fConfig.Threshold();
out << ", dead time " << fConfig.DeadTime() << " ns";
out << "--- Using TimeClusterTrigger with trigger window " << fWinSize << " ns";
out << ", threshold " << fMinNumData;
out << ", dead time " << fDeadTime << " ns";
return out.str();
}
......
......@@ -5,6 +5,7 @@
#ifndef CBM_ALGO_TIMECLUSTERTRIGGER_H
#define CBM_ALGO_TIMECLUSTERTRIGGER_H 1
#include "Definitions.h"
#include "DigiTriggerConfig.h"
#include <cstddef>
......@@ -44,14 +45,20 @@ namespace cbm::algo::evbuild
public:
typedef std::pair<std::vector<double>, TimeClusterTriggerMonitorData> resultType;
/** @brief Constructor **/
TimeClusterTrigger(const DigiTriggerConfig& config) : fConfig(config) {}
/** @brief Execution
** @param dataVec Source data vector
/** @brief Constructor
** @param winSize Size of trigger window
** @param minNumData Threshold on number of data within the trigger window
** @param deadTime Minimum time between two triggers
**/
TimeClusterTrigger(double winSize, u32 minNumData, double deadTime)
: fWinSize(winSize)
, fMinNumData(minNumData)
, fDeadTime(deadTime)
{
}
/** @brief Execution
** @param dataVec Source data vector
** @return Vector of trigger times and monitoring data
**/
resultType operator()(const std::vector<double>& dataVec) const;
......@@ -61,7 +68,9 @@ namespace cbm::algo::evbuild
private:
DigiTriggerConfig fConfig;
double fWinSize = 0.;
int32_t fMinNumData = 0;
double fDeadTime = 0.;
};
......
......@@ -14,12 +14,11 @@
#include "CbmStsDigi.h"
#include "CbmTofDigi.h"
#include "CbmTrdDigi.h"
#include "TimeClusterTrigger.h"
#include <FairRootManager.h>
#include <Logger.h>
#include "TimeClusterTrigger.h"
#include <algorithm>
#include <cassert>
#include <iomanip>
......@@ -54,7 +53,9 @@ void CbmTaskTriggerDigi::Exec(Option_t*)
std::vector<double> systemDigiTimes = GetDigiTimes(system);
digiTimes.insert(digiTimes.end(), systemDigiTimes.begin(), systemDigiTimes.end());
}
if (fSystems.size() > 1) { std::sort(digiTimes.begin(), digiTimes.end()); }
if (fSystems.size() > 1) {
std::sort(digiTimes.begin(), digiTimes.end());
}
}
// --- Case: input digi branches
......@@ -98,7 +99,9 @@ void CbmTaskTriggerDigi::Exec(Option_t*)
}
digiTimes.insert(digiTimes.end(), locDigiTimes.begin(), locDigiTimes.end());
}
if (fSystems.size() > 1) { std::sort(digiTimes.begin(), digiTimes.end()); }
if (fSystems.size() > 1) {
std::sort(digiTimes.begin(), digiTimes.end());
}
}
// --- Call the trigger algorithm
......@@ -226,7 +229,9 @@ InitStatus CbmTaskTriggerDigi::Init()
// --- Check input data
// --- DigiTimeslice: Unpacked data from FLES
fTimeslice = ioman->InitObjectAs<const CbmDigiTimeslice*>("DigiTimeslice.");
if (fTimeslice) { LOG(info) << "--- Found branch DigiTimeslice."; }
if (fTimeslice) {
LOG(info) << "--- Found branch DigiTimeslice.";
}
// --- DigiManager: Simulated digi data
else {
fDigiMan = CbmDigiManager::Instance();
......@@ -254,7 +259,7 @@ InitStatus CbmTaskTriggerDigi::Init()
LOG(info) << "--- Registered branch Trigger";
// --- Configure algorithm
fAlgo.reset(new cbm::algo::evbuild::TimeClusterTrigger(*fConfig));
fAlgo.reset(new cbm::algo::evbuild::TimeClusterTrigger(fConfig->Window(), fConfig->Threshold(), fConfig->DeadTime()));
LOG(info) << "--- Using trigger detector " << ::ToString(fConfig->Detector());
LOG(info) << fAlgo->ToString();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment