Line data Source code
1 : /**
2 : * @file TCMakerPlaneCoincidenceAlgorithm.cpp
3 : *
4 : * This is part of the DUNE DAQ Application Framework, copyright 2021.
5 : * Licensing/copyright details are in the COPYING file that you should have
6 : * received with this code.
7 : */
8 :
9 : #include "triggeralgs/PlaneCoincidence/TCMakerPlaneCoincidenceAlgorithm.hpp"
10 :
11 : #include "TRACE/trace.h"
12 : #define TRACE_NAME "TCMakerPlaneCoincidenceAlgorithm"
13 :
14 : #include <vector>
15 :
16 : using namespace triggeralgs;
17 :
18 : using Logging::TLVL_DEBUG_HIGH;
19 : using Logging::TLVL_DEBUG_MEDIUM;
20 : using Logging::TLVL_DEBUG_LOW;
21 : using Logging::TLVL_DEBUG_INFO;
22 : using Logging::TLVL_VERY_IMPORTANT;
23 :
24 : void
25 0 : TCMakerPlaneCoincidenceAlgorithm::process(const TriggerActivity& activity,
26 : std::vector<TriggerCandidate>& output_tc)
27 : {
28 :
29 0 : std::vector<TriggerActivity::TriggerActivityData> ta_list = { static_cast<TriggerActivity::TriggerActivityData>(
30 0 : activity) };
31 :
32 : // The first time process is called, reset window object.
33 0 : if (m_current_window.is_empty()) {
34 0 : m_current_window.reset(activity);
35 0 : m_activity_count++;
36 : // Trivial TC Logic:
37 : // If the request has been made to not trigger on number of channels or
38 : // total adc, simply construct a trigger candidate from any single activity.
39 0 : if ((!m_trigger_on_adc) && (!m_trigger_on_n_channels)) {
40 :
41 : // add_window_to_record(m_current_window);
42 : // dump_window_record();
43 0 : TLOG_DEBUG(TLVL_DEBUG_LOW) << "[TCM:PC] Constructing TC.";
44 0 : TLOG_DEBUG(TLVL_DEBUG_HIGH) << "[TCM:PC] Activity count: " << m_activity_count;
45 0 : TriggerCandidate tc = construct_tc();
46 0 : output_tc.push_back(tc);
47 :
48 : // Clear the current window (only has a single TA in it)
49 0 : m_current_window.clear();
50 0 : }
51 0 : return;
52 : }
53 :
54 : // FIX ME: Only want to call this if running in debug mode.
55 : // add_window_to_record(m_current_window);
56 :
57 : // If the difference between the current TA's start time and the start of the window
58 : // is less than the specified window size, add the TA to the window.
59 0 : if ((activity.time_start - m_current_window.time_start) < m_window_length) {
60 0 : m_current_window.add(activity);
61 : }
62 : // If the addition of the current TA to the window would make it longer
63 : // than the specified window length, don't add it but check whether the sum of all adc in
64 : // the existing window is above the specified threshold. If it is, and we are triggering on ADC,
65 : // make a TA and start a fresh window with the current TP.
66 0 : else if (m_current_window.adc_integral > m_adc_threshold && m_trigger_on_adc) {
67 0 : TLOG_DEBUG(TLVL_DEBUG_MEDIUM) << "[TCM:PC] ADC integral in window is greater than specified threshold.";
68 0 : TriggerCandidate tc = construct_tc();
69 :
70 0 : output_tc.push_back(tc);
71 0 : TLOG_DEBUG(TLVL_DEBUG_HIGH) << "[TCM:PC] Resetting window with activity.";
72 0 : m_current_window.reset(activity);
73 0 : }
74 : // If the addition of the current TA to the window would make it longer
75 : // than the specified window length, don't add it but check whether the number of hit channels in
76 : // the existing window is above the specified threshold. If it is, and we are triggering on channels,
77 : // make a TC and start a fresh window with the current TA.
78 0 : else if (m_current_window.n_channels_hit() > m_n_channels_threshold && m_trigger_on_n_channels) {
79 : // TODO 04-2024: This case appears unsupported. Throwing error for now, but should this be removed?
80 0 : tc_number++;
81 : // output_tc.push_back(construct_tc());
82 0 : m_current_window.reset(activity);
83 0 : TLOG_DEBUG(TLVL_DEBUG_INFO) << "[TCM:PC] Should not see this!";
84 : }
85 : // If it is not, move the window along.
86 : else {
87 0 : TLOG_DEBUG(TLVL_DEBUG_HIGH) << "[TCM:PC] TAWindow is at required length but specified threshold not met, shifting window along.";
88 0 : m_current_window.move(activity, m_window_length);
89 : }
90 :
91 0 : m_activity_count++;
92 :
93 0 : return;
94 0 : }
95 :
96 : void
97 0 : TCMakerPlaneCoincidenceAlgorithm::configure(const nlohmann::json& config)
98 : {
99 0 : TriggerCandidateMaker::configure(config);
100 0 : if (config.is_object()) {
101 0 : if (config.contains("trigger_on_adc"))
102 0 : m_trigger_on_adc = config["trigger_on_adc"];
103 0 : if (config.contains("trigger_on_n_channels"))
104 0 : m_trigger_on_n_channels = config["trigger_on_n_channels"];
105 0 : if (config.contains("adc_threshold"))
106 0 : m_adc_threshold = config["adc_threshold"];
107 0 : if (config.contains("n_channels_threshold"))
108 0 : m_n_channels_threshold = config["n_channels_threshold"];
109 0 : if (config.contains("window_length"))
110 0 : m_window_length = config["window_length"];
111 : }
112 0 : if (m_trigger_on_n_channels) {
113 0 : TLOG_DEBUG(TLVL_VERY_IMPORTANT) << "[TCM:PC] Using trigger_on_n_channels is not supported.";
114 0 : throw BadConfiguration(ERS_HERE, TRACE_NAME);
115 : }
116 0 : if (!m_trigger_on_adc && !m_trigger_on_n_channels) {
117 0 : TLOG_DEBUG(TLVL_DEBUG_LOW) << "[TCM:PC] Both trigger flags are false. Passing TAs through 1:1.";
118 : }
119 :
120 0 : return;
121 : }
122 :
123 : TriggerCandidate
124 0 : TCMakerPlaneCoincidenceAlgorithm::construct_tc() const
125 : {
126 0 : TriggerActivity latest_ta_in_window = m_current_window.inputs.back();
127 :
128 0 : TriggerCandidate tc;
129 0 : tc.time_start = m_current_window.time_start;
130 0 : tc.time_end = latest_ta_in_window.time_end;
131 0 : tc.time_candidate = m_current_window.time_start;
132 0 : tc.detid = latest_ta_in_window.detid;
133 0 : tc.type = m_tc_type_out;
134 0 : tc.algorithm = TriggerCandidate::Algorithm::kPlaneCoincidence;
135 :
136 : // Take the list of triggeralgs::TriggerActivity in the current
137 : // window and convert them (implicitly) to detdataformats'
138 : // TriggerActivityData, which is the base class of TriggerActivity
139 0 : for (auto& ta : m_current_window.inputs) {
140 0 : tc.inputs.push_back(ta);
141 : }
142 :
143 0 : return tc;
144 0 : }
145 :
146 : bool
147 0 : TCMakerPlaneCoincidenceAlgorithm::check_adjacency() const
148 : {
149 : // FIX ME: An adjacency check on the channels which have hits.
150 0 : return true;
151 : }
152 :
153 : // Functions below this line are for debugging purposes.
154 : void
155 0 : TCMakerPlaneCoincidenceAlgorithm::add_window_to_record(TAWindow window)
156 : {
157 0 : m_window_record.push_back(window);
158 0 : return;
159 : }
160 :
161 : void
162 0 : TCMakerPlaneCoincidenceAlgorithm::dump_window_record()
163 : {
164 : // FIX ME: Need to index this outfile in the name by detid or something similar.
165 0 : std::ofstream outfile;
166 0 : outfile.open("window_record_tcm.csv", std::ios_base::app);
167 :
168 0 : for (auto window : m_window_record) {
169 0 : outfile << window.time_start << ",";
170 0 : outfile << window.inputs.back().time_start << ",";
171 0 : outfile << window.inputs.back().time_start - window.time_start << ",";
172 0 : outfile << window.adc_integral << ",";
173 0 : outfile << window.n_channels_hit() << ",";
174 0 : outfile << window.inputs.size() << std::endl;
175 0 : }
176 :
177 0 : outfile.close();
178 :
179 0 : m_window_record.clear();
180 :
181 0 : return;
182 0 : }
183 :
184 12 : REGISTER_TRIGGER_CANDIDATE_MAKER(TRACE_NAME, TCMakerPlaneCoincidenceAlgorithm)
|