Line data Source code
1 : /**
2 : * @file TAMakerADCSimpleWindowAlgorithm.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/ADCSimpleWindow/TAMakerADCSimpleWindowAlgorithm.hpp"
10 :
11 : #include "TRACE/trace.h"
12 : #define TRACE_NAME "TAMakerADCSimpleWindowAlgorithm"
13 :
14 : #include <vector>
15 :
16 :
17 :
18 :
19 : namespace triggeralgs {
20 :
21 : // using namespace triggeralgs;
22 : using Logging::TLVL_DEBUG_ALL;
23 : using Logging::TLVL_DEBUG_HIGH;
24 : using Logging::TLVL_DEBUG_LOW;
25 : using Logging::TLVL_IMPORTANT;
26 :
27 : void
28 0 : TAMakerADCSimpleWindowAlgorithm::Window::add(TriggerPrimitive const &input_tp){
29 : // Add the input TP's contribution to the total ADC and add it to
30 : // the TP list.
31 0 : adc_integral += input_tp.adc_integral;
32 0 : tp_list.push_back(input_tp);
33 0 : }
34 :
35 : void
36 0 : TAMakerADCSimpleWindowAlgorithm::Window::move(TriggerPrimitive const &input_tp, timestamp_t const &window_length){
37 : // Find all of the TPs in the window that need to be removed
38 : // if the input_tp is to be added and the size of the window
39 : // is to be conserved.
40 : // Substract those TPs' contribution from the total window ADC.
41 0 : uint32_t n_tps_to_erase = 0;
42 0 : for(auto tp : tp_list){
43 0 : if(input_tp.time_start-tp.time_start >= window_length){
44 0 : n_tps_to_erase++;
45 0 : adc_integral -= tp.adc_integral;
46 : } else {
47 : break;
48 : }
49 : }
50 : // Erase the TPs from the window.
51 0 : tp_list.erase(tp_list.begin(), tp_list.begin()+n_tps_to_erase);
52 :
53 : // Make the window start time the start time of what is now the
54 : // first TP.
55 0 : if(!tp_list.empty()){
56 0 : time_start = tp_list.front().time_start;
57 0 : add(input_tp);
58 : } else {
59 0 : reset(input_tp);
60 : }
61 0 : }
62 :
63 :
64 : void
65 0 : TAMakerADCSimpleWindowAlgorithm::Window::reset(TriggerPrimitive const &input_tp){
66 : // Empty the TP list.
67 0 : tp_list.clear();
68 : // Set the start time of the window to be the start time of the
69 : // input_tp.
70 0 : time_start = input_tp.time_start;
71 : // Start the total ADC integral.
72 0 : adc_integral = input_tp.adc_integral;
73 : // Add the input TP to the TP list.
74 0 : tp_list.push_back(input_tp);
75 0 : }
76 :
77 :
78 :
79 : std::ostream&
80 0 : operator<<(std::ostream& os, const TAMakerADCSimpleWindowAlgorithm::Window& window)
81 : {
82 0 : if (window.is_empty()) {
83 0 : os << "Window is empty!\n";
84 : } else {
85 0 : os << "Window start: " << window.time_start
86 0 : << ", end: " << window.tp_list.back().time_start
87 0 : << ". Total of: " << window.adc_integral
88 0 : << " ADC counts with " << window.tp_list.size()
89 0 : << " TPs.\n";
90 : }
91 0 : return os;
92 : }
93 :
94 : void
95 0 : TAMakerADCSimpleWindowAlgorithm::process(const TriggerPrimitive& input_tp, std::vector<TriggerActivity>& output_ta)
96 : {
97 :
98 : // The first time operator is called, reset
99 : // window object.
100 0 : if(m_current_window.is_empty()){
101 0 : m_current_window.reset(input_tp);
102 0 : m_primitive_count++;
103 0 : return;
104 : }
105 :
106 : // If the difference between the current TP's start time and the start of the window
107 : // is less than the specified window size, add the TP to the window.
108 0 : if((input_tp.time_start - m_current_window.time_start) < m_window_length){
109 0 : TLOG_DEBUG(TLVL_DEBUG_HIGH) << "[TAM:ADCSW] Window not yet complete, adding the input_tp to the window.";
110 0 : m_current_window.add(input_tp);
111 : }
112 : // If the addition of the current TP to the window would make it longer
113 : // than the specified window length, don't add it but check whether the sum of all adc in
114 : // the existing window is above the specified threshold. If it is, make a TA and start
115 : // a fresh window with the current TP.
116 0 : else if(m_current_window.adc_integral > m_adc_threshold){
117 0 : TLOG_DEBUG(TLVL_DEBUG_LOW) << "[TAM:ADCSW] ADC integral in window is greater than specified threshold.";
118 0 : output_ta.push_back(construct_ta());
119 0 : TLOG_DEBUG(TLVL_DEBUG_HIGH) << "[TAM:ADCSW] Resetting window with input_tp.";
120 0 : m_current_window.reset(input_tp);
121 : }
122 : // If it is not, move the window along.
123 : else{
124 0 : TLOG_DEBUG(TLVL_DEBUG_ALL) << "[TAM:ADCSW] Window is at required length but adc threshold not met, shifting window along.";
125 0 : m_current_window.move(input_tp, m_window_length);
126 : }
127 :
128 0 : TLOG_DEBUG(TLVL_DEBUG_ALL) << "[TAM:ADCSW] " << m_current_window;
129 :
130 0 : m_primitive_count++;
131 :
132 0 : return;
133 : }
134 :
135 : void
136 0 : TAMakerADCSimpleWindowAlgorithm::configure(const nlohmann::json& config)
137 : {
138 0 : TriggerActivityMaker::configure(config);
139 :
140 : //FIXME use some schema here
141 0 : if (config.is_object()){
142 0 : if (config.contains("window_length")) m_window_length = config["window_length"];
143 0 : if (config.contains("adc_threshold")) m_adc_threshold = config["adc_threshold"];
144 : }
145 : else{
146 0 : TLOG_DEBUG(TLVL_IMPORTANT) << "[TAM:ADCSW] The DEFAULT values of window_length and adc_threshold are being used.";
147 : }
148 0 : TLOG_DEBUG(TLVL_IMPORTANT) << "[TAM:ADCSW] If the total ADC of trigger primitives with times within a "
149 0 : << m_window_length << " tick time window is above " << m_adc_threshold << " counts, a trigger will be issued.";
150 0 : }
151 :
152 : TriggerActivity
153 0 : TAMakerADCSimpleWindowAlgorithm::construct_ta() const
154 : {
155 0 : TLOG_DEBUG(TLVL_DEBUG_LOW) << "[TAM:ADCSW] I am constructing a trigger activity!";
156 : //TLOG_DEBUG(TRACE_NAME) << m_current_window;
157 :
158 0 : const TriggerPrimitive& last_tp = m_current_window.tp_list.back();
159 0 : uint64_t ch_min{last_tp.channel}, ch_max{last_tp.channel};
160 0 : uint64_t time_min{last_tp.time_start}, time_max{last_tp.time_start + last_tp.samples_over_threshold * k_sample_to_dts_ticks};
161 :
162 0 : uint64_t adc_peak{last_tp.adc_peak};
163 0 : uint64_t ch_peak{last_tp.channel};
164 0 : timestamp_t time_peak{last_tp.time_start + last_tp.samples_to_peak * k_sample_to_dts_ticks};
165 :
166 :
167 0 : std::vector<TriggerPrimitive> tp_list;
168 0 : tp_list.reserve(m_current_window.tp_list.size());
169 :
170 :
171 : // Copy the queue into the vector
172 : // And compute TA parameters
173 0 : for( const auto& tp : m_current_window.tp_list ) {
174 :
175 0 : ch_min = std::min(ch_min, tp.channel);
176 0 : ch_max = std::max(ch_max, tp.channel);
177 0 : time_min = std::min(time_min, tp.time_start);
178 0 : time_max = std::max(time_max, tp.time_start + tp.samples_over_threshold * k_sample_to_dts_ticks); // FIXME: Replace the hard-coded SOT to TOT scaling.
179 0 : if (tp.adc_peak > adc_peak) {
180 0 : adc_peak = tp.adc_peak;
181 0 : ch_peak = tp.channel;
182 0 : time_peak = tp.time_start + tp.samples_to_peak * k_sample_to_dts_ticks; // FIXME: Replace the hard-coded STP to `time_peak` conversion.
183 : }
184 :
185 0 : tp_list.push_back(tp);
186 : }
187 :
188 0 : TriggerActivity ta;
189 :
190 0 : ta.time_start = time_min;
191 0 : ta.time_end = time_max;
192 0 : ta.time_peak = time_peak;
193 0 : ta.time_activity = time_peak;
194 0 : ta.channel_start = ch_min;
195 0 : ta.channel_end = ch_max;
196 0 : ta.channel_peak = ch_peak;
197 0 : ta.adc_integral = m_current_window.adc_integral;
198 0 : ta.adc_peak = adc_peak;
199 0 : ta.detid = last_tp.detid;
200 0 : ta.type = TriggerActivity::Type::kTPC;
201 0 : ta.algorithm = TriggerActivity::Algorithm::kADCSimpleWindow;
202 0 : ta.inputs.swap(tp_list);
203 0 : return ta;
204 0 : }
205 :
206 :
207 : // Register algo in TA Factory
208 12 : REGISTER_TRIGGER_ACTIVITY_MAKER(TRACE_NAME, TAMakerADCSimpleWindowAlgorithm)
209 :
210 : }
|