Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for CIB #295

Merged
merged 4 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ daq_codegen(
tpsetbuffercreator.jsonnet
tasetsink.jsonnet
tpchannelfilter.jsonnet
cibtriggercandidatemaker.jsonnet
TEMPLATES Structs.hpp.j2 Nljs.hpp.j2 )

daq_codegen(
Expand All @@ -71,6 +72,7 @@ daq_codegen( *info.jsonnet DEP_PKGS opmonlib TEMPLATES opmonlib/InfoStructs.hpp.

daq_add_plugin(TimingTriggerCandidateMaker duneDAQModule SCHEMA LINK_LIBRARIES trigger)
daq_add_plugin(CTBTriggerCandidateMaker duneDAQModule SCHEMA LINK_LIBRARIES trigger)
daq_add_plugin(CIBTriggerCandidateMaker duneDAQModule SCHEMA LINK_LIBRARIES trigger)
daq_add_plugin(TriggerPrimitiveMaker duneDAQModule LINK_LIBRARIES trigger)
daq_add_plugin(TriggerActivityMaker duneDAQModule LINK_LIBRARIES trigger)
daq_add_plugin(TriggerCandidateMaker duneDAQModule LINK_LIBRARIES trigger)
Expand Down
10 changes: 10 additions & 0 deletions include/trigger/Issues.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,16 @@ ERS_DECLARE_ISSUE_BASE(trigger,
((std::bitset<32>)bits)
((size_t)map_size))

ERS_DECLARE_ISSUE_BASE(trigger,
InvalidCIBSignal,
appfwk::GeneralDAQModuleIssue,
"An invalid CIB signal was received, signal: " << signal << ", bits: " << bits
<< ", configured CIB bits: " << map_size,
((std::string)name),
((uint32_t)signal)
((std::bitset<32>)bits)
((size_t)map_size))

ERS_DECLARE_ISSUE(trigger,
MissingFactoryItemError,
"Factory could not find requested item " << item << ".",
Expand Down
204 changes: 204 additions & 0 deletions plugins/CIBTriggerCandidateMaker.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
/**
* @file CIBTriggerCandidateMaker.cpp
*
* This is part of the DUNE DAQ Application Framework, copyright 2020.
* Licensing/copyright details are in the COPYING file that you should have
* received with this code.
*/

#include "CIBTriggerCandidateMaker.hpp"
#include "trigger/Logging.hpp"

#include "appfwk/DAQModuleHelper.hpp"
#include "iomanager/IOManager.hpp"
#include "rcif/cmd/Nljs.hpp"
#include "trgdataformats/Types.hpp"
#include "trigger/TriggerCandidate_serialization.hpp"

#include <bitset>
#include <regex>
#include <string>

using dunedaq::trigger::logging::TLVL_DEBUG_ALL;
using dunedaq::trigger::logging::TLVL_DEBUG_HIGH;
using dunedaq::trigger::logging::TLVL_DEBUG_MEDIUM;
using dunedaq::trigger::logging::TLVL_GENERAL;
using dunedaq::trigger::logging::TLVL_VERY_IMPORTANT;

namespace dunedaq {
namespace trigger {

CIBTriggerCandidateMaker::CIBTriggerCandidateMaker(const std::string& name)
: DAQModule(name)
, m_output_queue(nullptr)
, m_queue_timeout(100)
{

register_command("conf", &CIBTriggerCandidateMaker::do_conf);
register_command("start", &CIBTriggerCandidateMaker::do_start);
register_command("stop", &CIBTriggerCandidateMaker::do_stop);
register_command("scrap", &CIBTriggerCandidateMaker::do_scrap);
}

std::vector<triggeralgs::TriggerCandidate>
CIBTriggerCandidateMaker::HSIEventToTriggerCandidate(const dfmessages::HSIEvent& data)
{
TLOG_DEBUG(TLVL_DEBUG_MEDIUM) << "[CIB] Converting HSI event, signal: " << data.signal_map;

std::vector<triggeralgs::TriggerCandidate> candidates;
std::bitset<32> bits(data.signal_map);
TLOG_DEBUG(TLVL_DEBUG_HIGH) << "[CIB] BITS: " << bits;

for (size_t i = 0; i < bits.size(); ++i) {
if (bits.test(i)) {

TLOG_DEBUG(TLVL_DEBUG_ALL) << "[CIB] this bit: " << i;

if (m_CIB_TC_map.count(i)) {
TLOG_DEBUG(TLVL_DEBUG_ALL) << "[CIB] TC type: " << static_cast<int>(m_CIB_TC_map[i]);

triggeralgs::TriggerCandidate candidate;
candidate.time_candidate = data.timestamp;
candidate.time_start = data.timestamp - m_time_before;
candidate.time_end = data.timestamp + m_time_after;
// candidate.detid = 1;
candidate.detid = data.header;
candidate.type = m_CIB_TC_map[i];
candidate.algorithm = triggeralgs::TriggerCandidate::Algorithm::kHSIEventToTriggerCandidate;
candidate.inputs = {};

candidates.push_back(candidate);
} else {
ers::error(
dunedaq::trigger::InvalidCIBSignal(ERS_HERE, get_name(), data.signal_map, bits, m_CIB_TC_map.size()));
}
}
}

return candidates;
}

void
CIBTriggerCandidateMaker::do_conf(const nlohmann::json& config)
{
auto params = config.get<dunedaq::trigger::cibtriggercandidatemaker::Conf>();
m_time_before = params.time_before;
m_time_after = params.time_after;
m_prescale = params.prescale;
m_prescale_flag = (m_prescale > 1) ? true : false;
TLOG_DEBUG(TLVL_GENERAL) << "[CIB] " << get_name() + " configured.";
TLOG_DEBUG(TLVL_VERY_IMPORTANT) << "[CIB] Time before: " << m_time_before;
TLOG_DEBUG(TLVL_VERY_IMPORTANT) << "[CIB] Time after: " << m_time_after;
if (m_prescale_flag) {
TLOG_DEBUG(TLVL_VERY_IMPORTANT) << "[CIB] Running with prescale at: " << m_prescale;
}
}

void
CIBTriggerCandidateMaker::init(const nlohmann::json& iniobj)
{
try {
auto ci = appfwk::connection_index(iniobj, { "output", "hsi_input" });
m_output_queue = get_iom_sender<triggeralgs::TriggerCandidate>(ci["output"]);
m_hsievent_input = get_iom_receiver<dfmessages::HSIEvent>(ci["hsi_input"]);
} catch (const ers::Issue& excpt) {
throw dunedaq::trigger::InvalidQueueFatalError(ERS_HERE, get_name(), "input/output", excpt);
}
}

void
CIBTriggerCandidateMaker::do_start(const nlohmann::json& startobj)
{
// OpMon.
m_tsd_received_count.store(0);
m_tc_sent_count.store(0);
m_tc_sig_type_err_count.store(0);
m_tc_total_count.store(0);

auto start_params = startobj.get<rcif::cmd::StartParams>();
m_run_number.store(start_params.run);

m_hsievent_input->add_callback(std::bind(&CIBTriggerCandidateMaker::receive_hsievent, this, std::placeholders::_1));

TLOG_DEBUG(TLVL_GENERAL) << "[CIB] " << get_name() + " successfully started.";
}

void
CIBTriggerCandidateMaker::do_stop(const nlohmann::json&)
{
m_hsievent_input->remove_callback();

TLOG() << "[CIB] Received " << m_tsd_received_count << " HSIEvent messages. Successfully sent " << m_tc_sent_count
<< " TriggerCandidates";
TLOG_DEBUG(TLVL_GENERAL) << "[CIB] " << get_name() + " successfully stopped.";
}

void
CIBTriggerCandidateMaker::receive_hsievent(dfmessages::HSIEvent& data)
{
TLOG_DEBUG(TLVL_DEBUG_MEDIUM) << "[CIB] Activity received with timestamp " << data.timestamp << ", sequence_counter "
<< data.sequence_counter << ", and run_number " << data.run_number;

if (data.run_number != m_run_number) {
ers::error(dunedaq::trigger::InvalidHSIEventRunNumber(
ERS_HERE, get_name(), data.run_number, m_run_number, data.timestamp, data.sequence_counter));
return;
}

++m_tsd_received_count;

if (m_prescale_flag) {
if (m_tsd_received_count % m_prescale != 0) {
return;
}
}

std::vector<triggeralgs::TriggerCandidate> candidates;
try {
candidates = HSIEventToTriggerCandidate(data);
} catch (SignalTypeError& e) {
m_tc_sig_type_err_count++;
ers::error(e);
return;
}

for (const auto& candidate : candidates) {
bool successfullyWasSent = false;
while (!successfullyWasSent) {
try {
triggeralgs::TriggerCandidate candidate_copy(candidate);
m_output_queue->send(std::move(candidate_copy), m_queue_timeout);
successfullyWasSent = true;
++m_tc_sent_count;
} catch (const dunedaq::iomanager::TimeoutExpired& excpt) {
std::ostringstream oss_warn;
oss_warn << "push to output queue \"" << m_output_queue->get_name() << "\"";
ers::warning(dunedaq::iomanager::TimeoutExpired(ERS_HERE, get_name(), oss_warn.str(), m_queue_timeout.count()));
}
}
m_tc_total_count++;
}
}

void
CIBTriggerCandidateMaker::do_scrap(const nlohmann::json&)
{
}

void
CIBTriggerCandidateMaker::get_info(opmonlib::InfoCollector& ci, int /*level*/)
{
cibtriggercandidatemakerinfo::Info i;

i.tsd_received_count = m_tsd_received_count.load();
i.tc_sent_count = m_tc_sent_count.load();
i.tc_sig_type_err_count = m_tc_sig_type_err_count.load();
i.tc_total_count = m_tc_total_count.load();

ci.add(i);
}

} // namespace trigger
} // namespace dunedaq

DEFINE_DUNE_DAQ_MODULE(dunedaq::trigger::CIBTriggerCandidateMaker)
91 changes: 91 additions & 0 deletions plugins/CIBTriggerCandidateMaker.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/**
* @file CIBTriggerCandidateMaker.cpp
*
* This is part of the DUNE DAQ Application Framework, copyright 2020.
* Licensing/copyright details are in the COPYING file that you should have
* received with this code.
*/

#ifndef TRIGGER_PLUGINS_CIBTRIGGERCANDIDATEMAKER_HPP_
#define TRIGGER_PLUGINS_CIBTRIGGERCANDIDATEMAKER_HPP_

#include "trigger/Issues.hpp"
#include "trigger/cibtriggercandidatemaker/Nljs.hpp"
#include "trigger/cibtriggercandidatemakerinfo/InfoNljs.hpp"

#include "appfwk/DAQModule.hpp"
#include "daqdataformats/Types.hpp"
#include "dfmessages/HSIEvent.hpp"
#include "iomanager/Receiver.hpp"
#include "iomanager/Sender.hpp"
#include "triggeralgs/TriggerActivity.hpp"
#include "triggeralgs/TriggerCandidate.hpp"
#include "utilities/WorkerThread.hpp"

#include <chrono>
#include <map>
#include <memory>
#include <string>
#include <utility>

namespace dunedaq {
namespace trigger {
class CIBTriggerCandidateMaker : public dunedaq::appfwk::DAQModule
{
public:
explicit CIBTriggerCandidateMaker(const std::string& name);

CIBTriggerCandidateMaker(const CIBTriggerCandidateMaker&) = delete;
CIBTriggerCandidateMaker& operator=(const CIBTriggerCandidateMaker&) = delete;
CIBTriggerCandidateMaker(CIBTriggerCandidateMaker&&) = delete;
CIBTriggerCandidateMaker& operator=(CIBTriggerCandidateMaker&&) = delete;

void init(const nlohmann::json& iniobj) override;
void get_info(opmonlib::InfoCollector& ci, int level) override;

private:
void do_conf(const nlohmann::json& config);
void do_start(const nlohmann::json& obj);
void do_stop(const nlohmann::json& obj);
void do_scrap(const nlohmann::json& obj);

std::string m_hsievent_receive_connection;

// Prescale functionality
bool m_prescale_flag;
int m_prescale;

// Config
int m_time_before;
int m_time_after;

std::vector<triggeralgs::TriggerCandidate> HSIEventToTriggerCandidate(const dfmessages::HSIEvent& data);
void receive_hsievent(dfmessages::HSIEvent& data);

using sink_t = dunedaq::iomanager::SenderConcept<triggeralgs::TriggerCandidate>;
std::shared_ptr<sink_t> m_output_queue;
std::shared_ptr<iomanager::ReceiverConcept<dfmessages::HSIEvent>> m_hsievent_input;

std::chrono::milliseconds m_queue_timeout;

// HLT to TC type map
std::map<int, trgdataformats::TriggerCandidateData::Type> m_CIB_TC_map = {
{ 0, trgdataformats::TriggerCandidateData::Type::kCIBFakeTrigger },
{ 1, trgdataformats::TriggerCandidateData::Type::kCIBLaserTriggerP1 },
{ 2, trgdataformats::TriggerCandidateData::Type::kCIBLaserTriggerP2 },
{ 3, trgdataformats::TriggerCandidateData::Type::kCIBLaserTriggerP3 },
};

// Opmon variables
using metric_counter_type = decltype(cibtriggercandidatemakerinfo::Info::tsd_received_count);
std::atomic<metric_counter_type> m_tsd_received_count{ 0 };
std::atomic<metric_counter_type> m_tc_sent_count{ 0 };
std::atomic<metric_counter_type> m_tc_sig_type_err_count{ 0 };
std::atomic<metric_counter_type> m_tc_total_count{ 0 };

std::atomic<daqdataformats::run_number_t> m_run_number;
};
} // namespace trigger
} // namespace dunedaq

#endif // TRIGGER_PLUGINS_CIBTRIGGERCANDIDATEMAKER_HPP_
17 changes: 17 additions & 0 deletions schema/trigger/cibtriggercandidatemaker.jsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
local moo = import "moo.jsonnet";
local ns = "dunedaq.trigger.cibtriggercandidatemaker";
local s = moo.oschema.schema(ns);
local nc = moo.oschema.numeric_constraints;

local types = {
count_t : s.number("count_t", "i8", nc(minimum=1), doc="Counter"),
time_t : s.number("time_t", "i8", doc="Time"),
conf: s.record("Conf", [
s.field("prescale", self.count_t, default=1, doc="Option to prescale TTCM TCs"),
s.field("time_before", self.time_t, 1000, doc="Readout time before time stamp"),
s.field("time_after", self.time_t, 1000, doc="Readout time after time stamp")
], doc="CIB configuration block"),

};

moo.oschema.sort_select(types, ns)
20 changes: 20 additions & 0 deletions schema/trigger/cibtriggercandidatemakerinfo.jsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// This is the application info schema used by the cib trigger candidate maker module.
// It describes the information object structure passed by the application
// for operational monitoring

local moo = import "moo.jsonnet";
local s = moo.oschema.schema("dunedaq.trigger.cibtriggercandidatemakerinfo");

local info = {
uint8 : s.number("uint8", "u8",
doc="An unsigned of 8 bytes"),

info: s.record("Info", [
s.field("tsd_received_count", self.uint8, 0, doc="Number of HSIEvent messages received."),
s.field("tc_sent_count", self.uint8, 0, doc="Number of trigger candidates added to queue."),
s.field("tc_sig_type_err_count", self.uint8, 0, doc="Number of trigger candidates not added to queue due to a signal type error."),
s.field("tc_total_count", self.uint8, 0, doc="Total number of trigger candidates created."),
], doc="CIB trigger candidate maker information.")
};

moo.oschema.sort_select(info)
Loading