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

changes related to ROI random selection in MLT #242

Merged
merged 1 commit into from
Oct 16, 2023
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
206 changes: 196 additions & 10 deletions plugins/ModuleLevelTrigger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,18 @@ ModuleLevelTrigger::do_configure(const nlohmann::json& confobj)
{
auto params = confobj.get<moduleleveltrigger::ConfParams>();

m_links.clear();
for (auto const& link : params.links) {
m_links.push_back(
m_mandatory_links.clear();
for (auto const& link : params.mandatory_links) {
m_mandatory_links.push_back(
dfmessages::SourceID{ daqdataformats::SourceID::string_to_subsystem(link.subsystem), link.element });
}
m_group_links.clear();
m_group_links_data = params.groups_links;
parse_group_links(m_group_links_data);
print_group_links();
m_total_group_links = m_group_links.size();
TLOG_DEBUG(3) << "Total group links: " << m_total_group_links;

// m_trigger_decision_connection = params.dfo_connection;
// m_inhibit_connection = params.dfo_busy_connection;
m_hsi_passthrough = params.hsi_trigger_type_passthrough;
Expand All @@ -117,11 +124,20 @@ ModuleLevelTrigger::do_configure(const nlohmann::json& confobj)
m_td_readout_limit = params.td_readout_limit;
m_ignoring_tc_types = (m_ignored_tc_types.size() > 0) ? true : false;
m_use_readout_map = params.use_readout_map;
m_use_roi_readout = params.use_roi_readout;
m_use_bitwords = params.use_bitwords;
TLOG_DEBUG(3) << "Allow merging: " << m_tc_merging;
TLOG_DEBUG(3) << "Buffer timeout: " << m_buffer_timeout;
TLOG_DEBUG(3) << "Should send timed out TDs: " << m_send_timed_out_tds;
TLOG_DEBUG(3) << "TD readout limit: " << m_td_readout_limit;
TLOG_DEBUG(3) << "Use ROI readout?: " << m_use_roi_readout;

// ROI map
if (m_use_roi_readout) {
m_roi_conf_data = params.roi_conf;
parse_roi_conf(m_roi_conf_data);
print_roi_conf(m_roi_conf);
}

// Custom readout map
TLOG_DEBUG(3) << "Use readout map: " << m_use_readout_map;
Expand Down Expand Up @@ -228,7 +244,8 @@ ModuleLevelTrigger::do_resume(const nlohmann::json& /*resumeobj*/)
void
ModuleLevelTrigger::do_scrap(const nlohmann::json& /*scrapobj*/)
{
m_links.clear();
m_mandatory_links.clear();
m_group_links.clear();
m_configured_flag.store(false);
}

Expand Down Expand Up @@ -268,13 +285,18 @@ ModuleLevelTrigger::create_decision(const ModuleLevelTrigger::PendingTD& pending
<< ", request window begin: " << pending_td.readout_start
<< ", request window end: " << pending_td.readout_end;

for (auto link : m_links) {
dfmessages::ComponentRequest request;
request.component = link;
request.window_begin = pending_td.readout_start;
request.window_end = pending_td.readout_end;
std::vector<dfmessages::ComponentRequest> requests =
create_all_decision_requests(m_mandatory_links, pending_td.readout_start, pending_td.readout_end);
add_requests_to_decision(decision, requests);

decision.components.push_back(request);
if (!m_use_roi_readout) {
for (const auto& [key, value] : m_group_links) {
std::vector<dfmessages::ComponentRequest> group_requests =
create_all_decision_requests(value, pending_td.readout_start, pending_td.readout_end);
add_requests_to_decision(decision, group_requests);
}
} else { // using ROI readout
roi_readout_make_requests(decision);
}

return decision;
Expand Down Expand Up @@ -783,6 +805,170 @@ ModuleLevelTrigger::print_readout_map(std::map<trgdataformats::TriggerCandidateD
return;
}

void
ModuleLevelTrigger::parse_group_links(const nlohmann::json& data)
{
for (auto group : data) {
const nlohmann::json& temp_links_data = group["links"];
std::vector<dfmessages::SourceID> temp_links;
for (auto link : temp_links_data) {
temp_links.push_back(
dfmessages::SourceID{ daqdataformats::SourceID::string_to_subsystem(link["subsystem"]), link["element"] });
}
m_group_links.insert({ group["group"], temp_links });
}
return;
}

void
ModuleLevelTrigger::print_group_links()
{
TLOG_DEBUG(3) << "MLT Group Links:";
for (auto const& [key, val] : m_group_links) {
TLOG_DEBUG(3) << "Group: " << key;
for (auto const& link : val) {
TLOG_DEBUG(3) << link;
}
}
TLOG_DEBUG(3) << " ";
return;
}

dfmessages::ComponentRequest
ModuleLevelTrigger::create_request_for_link(dfmessages::SourceID link,
triggeralgs::timestamp_t start,
triggeralgs::timestamp_t end)
{
dfmessages::ComponentRequest request;
request.component = link;
request.window_begin = start;
request.window_end = end;

return request;
}

std::vector<dfmessages::ComponentRequest>
ModuleLevelTrigger::create_all_decision_requests(std::vector<dfmessages::SourceID> links,
triggeralgs::timestamp_t start,
triggeralgs::timestamp_t end)
{
std::vector<dfmessages::ComponentRequest> requests;
for (auto link : links) {
requests.push_back(create_request_for_link(link, start, end));
}
return requests;
}

void
ModuleLevelTrigger::add_requests_to_decision(dfmessages::TriggerDecision& decision,
std::vector<dfmessages::ComponentRequest> requests)
{
for (auto request : requests) {
decision.components.push_back(request);
}
}

void
ModuleLevelTrigger::parse_roi_conf(const nlohmann::json& data)
{
int counter = 0;
float run_sum = 0;
for (auto group : data) {
roi_group temp_roi_group;
temp_roi_group.n_links = group["number_of_link_groups"];
temp_roi_group.prob = group["probability"];
temp_roi_group.time_window = group["time_window"];
temp_roi_group.mode = group["groups_selection_mode"];
m_roi_conf.insert({ counter, temp_roi_group });
m_roi_conf_ids.push_back(counter);
m_roi_conf_probs.push_back(group["probability"]);
run_sum += static_cast<float>(group["probability"]);
m_roi_conf_probs_c.push_back(run_sum);
counter++;
}
return;
}

void
ModuleLevelTrigger::print_roi_conf(std::map<int, roi_group> roi_conf)
{
TLOG_DEBUG(3) << "ROI CONF";
for (const auto& [key, value] : roi_conf) {
TLOG_DEBUG(3) << "ID: " << key;
TLOG_DEBUG(3) << "n links: " << value.n_links;
TLOG_DEBUG(3) << "prob: " << value.prob;
TLOG_DEBUG(3) << "time: " << value.time_window;
TLOG_DEBUG(3) << "mode: " << value.mode;
}
TLOG_DEBUG(3) << " ";
return;
}

float
ModuleLevelTrigger::get_random_num_float(float limit)
{
float rnd = (double)rand() / RAND_MAX;
return rnd * (limit);
}

int
ModuleLevelTrigger::pick_roi_group_conf()
{
float rnd_num = get_random_num_float(m_roi_conf_probs_c.back());
for (int i = 0; i < static_cast<int>(m_roi_conf_probs_c.size()); i++) {
if (rnd_num < m_roi_conf_probs_c[i]) {
return i;
}
}
return -1;
}

int
ModuleLevelTrigger::get_random_num_int()
{
int range = m_total_group_links;
int rnd = rand() % range;
return rnd;
}

void
ModuleLevelTrigger::roi_readout_make_requests(dfmessages::TriggerDecision& decision)
{
// Get configuration at random (weighted)
int group_pick = pick_roi_group_conf();
if (group_pick != -1) {
roi_group this_group = m_roi_conf[m_roi_conf_ids[group_pick]];
std::vector<dfmessages::SourceID> links;

// If mode is random, pick groups to request at random
if (this_group.mode == "kRandom") {
TLOG_DEBUG(3) << "RAND";
std::set<int> groups;
while (static_cast<int>(groups.size()) < this_group.n_links) {
groups.insert(get_random_num_int());
}
for (auto r_id : groups) {
links.insert(links.end(), m_group_links[r_id].begin(), m_group_links[r_id].end());
}
// Otherwise, read sequntially by IDs, starting at 0
} else {
TLOG_DEBUG(3) << "SEQ";
int r_id = 0;
while (r_id < this_group.n_links) {
links.insert(links.end(), m_group_links[r_id].begin(), m_group_links[r_id].end());
r_id++;
}
}

// Once the components are prepared, create requests and append them to decision
std::vector<dfmessages::ComponentRequest> requests =
create_all_decision_requests(links, this_group.time_window, this_group.time_window);
add_requests_to_decision(decision, requests);
links.clear();
}
return;
}

} // namespace trigger
} // namespace dunedaq

Expand Down
37 changes: 36 additions & 1 deletion plugins/ModuleLevelTrigger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,42 @@ class ModuleLevelTrigger : public dunedaq::appfwk::DAQModule
std::shared_ptr<iomanager::ReceiverConcept<dfmessages::TriggerInhibit>> m_inhibit_input;
std::string m_td_output_connection;

std::vector<dfmessages::SourceID> m_links;
// TD requests
std::vector<dfmessages::SourceID> m_mandatory_links;
std::map<int, std::vector<dfmessages::SourceID>> m_group_links;
nlohmann::json m_group_links_data;
int m_total_group_links;
void parse_group_links(const nlohmann::json& data);
void print_group_links();
dfmessages::ComponentRequest create_request_for_link(dfmessages::SourceID link,
triggeralgs::timestamp_t start,
triggeralgs::timestamp_t end);
std::vector<dfmessages::ComponentRequest> create_all_decision_requests(std::vector<dfmessages::SourceID> links,
triggeralgs::timestamp_t start,
triggeralgs::timestamp_t end);
void add_requests_to_decision(dfmessages::TriggerDecision& decision,
std::vector<dfmessages::ComponentRequest> requests);

// ROI
bool m_use_roi_readout;
struct roi_group
{
int n_links;
float prob;
triggeralgs::timestamp_t time_window;
std::string mode;
};
std::map<int, roi_group> m_roi_conf;
nlohmann::json m_roi_conf_data;
void parse_roi_conf(const nlohmann::json& data);
void print_roi_conf(std::map<int, roi_group> roi_conf);
std::vector<int> m_roi_conf_ids;
std::vector<float> m_roi_conf_probs;
std::vector<float> m_roi_conf_probs_c;
float get_random_num_float(float limit);
int get_random_num_int();
int pick_roi_group_conf();
void roi_readout_make_requests(dfmessages::TriggerDecision& decision);

int m_repeat_trigger_count{ 1 };

Expand Down
27 changes: 24 additions & 3 deletions schema/trigger/moduleleveltrigger.jsonnet
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
local moo = import "moo.jsonnet";
local ns = "dunedaq.trigger.moduleleveltrigger";
local s = moo.oschema.schema(ns);
local nc = moo.oschema.numeric_constraints;

local types = {
group_id: s.number("group_id", "i4"),
element_id : s.number("element_id_t", "u4"),
subsystem : s.string("subsystem_t"),
flag : s.boolean("Boolean", doc="Option for flags, true/false"),
Expand All @@ -14,6 +16,9 @@ local types = {
bitword: s.number( "Bitword", "i4", doc="An integer representing the TC type, to be set in the trigger bitword."),
bitword_list: s.sequence( "BitwordList", self.bitword, doc="A sequence of bitword (bits) forming a bitword."),
bitwords: s.sequence( "Bitwords", self.bitword_list, doc="List of bitwords to use when forming trigger decisions in MLT" ),
number_of_groups: s.number( "Ngroups", "i4", nc(minimum=0, maximum=150), doc="Number of groups of detector links to readout, for ROI config"),
probability: s.number( "Prob", "f4", nc(minimum=0.0, maximum=1.0), doc="Probability to read out a group of links, for ROI config"),
group_selection: s.enum( "GroupSelection", ["kRandom", "kSequential"]),

tc_readout: s.record("tc_readout", [
s.field("candidate_type", self.tc_type, default=0, doc="The TC type"),
Expand Down Expand Up @@ -91,10 +96,24 @@ local types = {
]),

linkvec : s.sequence("link_vec", self.sourceid),

grouplink: s.record("group_link", [
s.field("group", self.group_id, doc="ID / group"),
s.field("links", self.linkvec, doc="List of associated elements"),
]),
grouplinks: s.sequence("group_links", self.grouplink),

roi_group_conf: s.record("roi_group_conf", [
s.field("number_of_link_groups", self.number_of_groups, default=1, doc="Number of groups of links to readout"),
s.field("probability", self.probability, default=0.1, doc="Probability to select this configuration [0 to 1]"),
s.field("time_window", self.readout_time, default=1000, doc="Time window to read out pre/post decision, [clock ticks]"),
s.field("groups_selection_mode", self.group_selection, default="kRandom", doc="Whether to read out random groups or in sequence"),
]),

roi_conf_map: s.sequence("roi_conf_map", self.roi_group_conf),

conf : s.record("ConfParams", [
s.field("links", self.linkvec,
doc="List of link identifiers that may be included into trigger decision"),
s.field("mandatory_links", self.linkvec, doc="List of link identifiers that will be included in trigger decision"),
s.field("groups_links", self.grouplinks, doc="List of link identifiers that may be included in trigger decision"),
s.field("hsi_trigger_type_passthrough", self.flag, default=false, doc="Option to override the trigger type inside MLT"),
s.field("merge_overlapping_tcs", self.flag, default=true, doc="Flag to allow(true)/disable(false) merging of overlapping TCs when forming TD"),
s.field("td_out_of_timeout", self.flag, default=true, doc="Option to send TD if TC comes out of timeout window (late, overlapping already sent TD"),
Expand All @@ -103,6 +122,8 @@ local types = {
s.field("ignore_tc", self.tc_types, [], doc="List of TC types to be ignored"),
s.field("use_bitwords", self.flag, default=false, doc="Option to use bitwords (ie trigger types, coincidences) when forming trigger decisions"),
s.field("trigger_bitwords", self.bitwords, [], doc="Optional dictionary of bitwords to use when forming trigger decisions"),
s.field("use_roi_readout", self.flag, default=false, doc="Option to use ROI readout in MLT: only readout selection of fragment producers"),
s.field("roi_conf", self.roi_conf_map, default=[self.roi_group_conf], doc="The configuration (table) for ROI readout"),
s.field("use_readout_map", self.flag, default=false, doc="Option to use defalt readout windows (tc.time_start and tc.time_end) or a custom readout map from daqconf"),
s.field("td_readout_map", self.tc_readout_map, self.tc_readout_map, doc="A map holding readout pre/post depending on TC type"),
], doc="ModuleLevelTrigger configuration parameters"),
Expand Down