Process the event and put new data products into it.
85 {
86 ldmx_log(debug) << "ZCCMDecoder: produce() starts! Event number: "
87 << event.getEventHeader().getEventNumber();
88
89
90 int n_samp = n_samples_;
91 ldmx_log(debug) << "num samples = " << n_samp;
92
93 ldmx_log(debug) << "Looking up input collection " << input_collection_ << "_"
94 << input_pass_name_;
95 const auto event_output{
96 event.getCollection<uint8_t>(input_collection_, input_pass_name_)};
97 ldmx_log(debug) << "Got input collection " << input_collection_ << "_"
98 << input_pass_name_;
99
100
101 uint32_t time_stamp = 0;
102 for (int i_w = 0; i_w < ZCCMOutput::TIMESTAMP_LEN_BYTES; i_w++) {
104 uint8_t time_word = event_output.at(pos);
105 ldmx_log(debug) << "time stamp word at position " << pos
106 << " (with iW = " << i_w
107 << ") = " << std::bitset<8>(time_word);
108 time_stamp |= (time_word << i_w * 8);
109 }
110
111 event.getEventHeader().setIntParameter("TS Timestamp", time_stamp);
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128 std::map<int, std::vector<int>> adc_map;
129 std::map<int, std::vector<int>> tdc_map;
130 std::map<int, std::vector<int>> cid_map;
131 std::map<int, std::vector<int>> bc0_map;
132 std::map<int, std::vector<int>> ce_map;
133
134 std::vector<std::vector<trigscint::TrigScintQIEDigis>> out_digis;
135 std::size_t n_modules =
136 std::ranges::count_if(modules_used_, [](int x) { return x != 0; });
137
138 out_digis.resize(n_modules);
139
140
141
142 int word_length = ZCCMOutput::SAMPLE_WORD_LEN_BYTES;
143 int num_messages =
144 ((int)event_output.size() - ZCCMOutput::EVENTDATA_POS) / word_length;
145
146
147
148 int n_lanes = n_channels_ / ZCCMOutput::NUM_CHAN_PER_LANE;
149 int num_expected_messages = n_samp * n_lanes;
150 if (num_messages != num_expected_messages)
151 ldmx_log(warn) << "Unexpected stream length! Num messages is "
152 << num_messages << ", expect " << num_expected_messages;
153
154
155
156 int i_word = 0;
157 int start_lane = -1;
158 int sample_nb = -1;
159
160 while (i_word < num_messages) {
161 uint word_pos = ZCCMOutput::EVENTDATA_POS + i_word * word_length;
162
163 uint16_t empty =
164 event_output.at(word_pos + ZCCMOutput::EMPTY_WORD_SAMPLE_WORD_POS);
165 uint8_t lane = event_output.at(word_pos + ZCCMOutput::LANE_SAMPLE_WORD_POS);
166 uint8_t flag =
167 event_output.at(word_pos + ZCCMOutput::FLAGS_SAMPLE_WORD_POS);
168
169 ldmx_log(debug) << "Start of message " << i_word << ".\n\tEmpty word is "
170 << std::bitset<16>(empty) << ", read at position "
171 << word_pos + ZCCMOutput::EMPTY_WORD_SAMPLE_WORD_POS
172 << ". \n\tFlag word is " << std::bitset<8>(flag)
173 << ", read at position "
174 << word_pos + ZCCMOutput::FLAGS_SAMPLE_WORD_POS
175 << ". \n\tLane is " << std::bitset<8>(lane)
176 << ", read at position "
177 << word_pos + ZCCMOutput::LANE_SAMPLE_WORD_POS << ".";
178
179 if (start_lane == -1) {
180 start_lane = lane;
181 ldmx_log(debug) << "Set time sample start lane to " << start_lane;
182 }
183
184 int cid{(flag >> ZCCMOutput::CAPID_POS_IN_FLAG) &
186 ldmx_log(trace) << "Got Cap ID " << cid;
187 bool bc0{static_cast<bool>((flag >> ZCCMOutput::BC0_POS_IN_FLAG) &
189 ldmx_log(trace) << "Got BC0 flag " << bc0;
190 bool ce{static_cast<bool>((flag >> ZCCMOutput::CE_POS_IN_FLAG) &
192 ldmx_log(trace) << "Got CE flag " << ce;
193 int empty_bits{(flag >> ZCCMOutput::EMPTY_FLAG_WORD_POS_IN_FLAG) &
195 if (empty_bits)
196 ldmx_log(fatal) << "Empty bits of flag not empty: " << empty_bits;
197
198
199
200
201
202
203
204
205
206
207
208
209
210 if (lane == start_lane)
211 sample_nb++;
212
213 uint8_t cid_val = cid;
214
215
216 for (int i_c = 0; i_c < ZCCMOutput::NUM_CHAN_PER_LANE; i_c++) {
217 if (i_word >= num_expected_messages) {
218 ldmx_log(fatal)
219 << "More words than expected! Breaking event data loop in sample "
220 << sample_nb << " at lane = " << int(lane) << ", channel nb "
221 << i_c;
222 break;
223 }
224 uint8_t adc_val =
225 event_output.at(word_pos + ZCCMOutput::ADC_SAMPLE_WORD_POS + i_c);
226 uint8_t tdc_val =
227 event_output.at(word_pos + ZCCMOutput::TDC_SAMPLE_WORD_POS + i_c);
228
229
230 int module = module_map_[lane];
231 int elec_id = 100 * lane + 10 * module + i_c;
232
233 ldmx_log(trace) << "got ADC value " << (unsigned)adc_val
234 << " and TDC value " << (unsigned)tdc_val
235 << " at channel idx " << i_c << " with elec id "
236 << elec_id;
237 if (adc_map.find(elec_id) == adc_map.end()) {
238 std::vector<int> adcs(n_samp, 0);
239 adc_map.insert(std::pair<int, std::vector<int>>(elec_id, adcs));
240 }
241 adc_map[elec_id].at(sample_nb) = adc_val;
242
243
244 if (tdc_map.find(elec_id) == tdc_map.end()) {
245 std::vector<int> tdcs(n_samp, 0);
246 tdc_map.insert(std::pair<int, std::vector<int>>(elec_id, tdcs));
247 }
248 tdc_map[elec_id].at(sample_nb) = tdc_val;
249 if (cid_map.find(elec_id) == cid_map.end()) {
250 std::vector<int> cids(n_samp, 0);
251 cid_map.insert(std::pair<int, std::vector<int>>(elec_id, cids));
252 std::vector<int> bc0s(n_samp, 0);
253 bc0_map.insert(std::pair<int, std::vector<int>>(elec_id, bc0s));
254 std::vector<int> ces(n_samp, 0);
255 ce_map.insert(std::pair<int, std::vector<int>>(elec_id, ces));
256 }
257 cid_map[elec_id].at(sample_nb) = cid_val;
258 bc0_map[elec_id].at(sample_nb) = bc0;
259 ce_map[elec_id].at(sample_nb) = ce;
260 }
261 ldmx_log(debug) << "Done with lane " << int(lane) << " which we think is "
262 << i_word % n_lanes << " in sample " << sample_nb;
263
264 if (int(lane) != i_word % n_lanes)
265 ldmx_log(fatal) << "Lane ordering has been messed up! Expect lane "
266 << i_word % n_lanes << ", but we got lane " << int(lane)
267 << " in sample " << sample_nb;
268
269 i_word++;
270 }
271
272 ldmx_log(debug) << "Done reading in header, ADC and TDC for event "
273 << event.getEventNumber();
274
275
276
277 for (std::map<int, std::vector<int>>::iterator itr = adc_map.begin();
278 itr != adc_map.end(); ++itr) {
279 TrigScintQIEDigis digi;
280 digi.setADC(itr->second);
281 if (channel_map_.find(itr->first) == channel_map_.end()) {
282 ldmx_log(fatal)
283 << "Couldn't find the bar ID corresponding to electronics ID "
284 << itr->first << "!! Skipping.";
285 continue;
286 }
287 int bar = channel_map_[itr->first];
288 digi.setElecID(itr->first);
289 digi.setChanID(bar);
290 int module = itr->first / 10 % 10;
291 digi.setModuleID(module);
292 int lane = itr->first / 100;
293 digi.setLaneID(lane);
294 digi.setTDC(tdc_map[itr->first]);
295 digi.setCID(cid_map[itr->first]);
296 digi.setBC0(bc0_map[itr->first]);
297 digi.setCE(ce_map[itr->first]);
298 if (bar == 0)
299 ldmx_log(debug) << "for bar 0, got time since spill "
300 << digi.getTimeSinceSpill();
301 out_digis[module].push_back(digi);
302 ldmx_log(debug) << "Iterator points to key " << itr->first
303 << " and mapped channel supposedly is " << bar;
304 ldmx_log(debug) << "Made digi with elecID = " << digi.getElecID()
305 << ", barID = " << digi.getChanID() << ", third adc value "
306 << digi.getADC().at(2) << " and third tdc "
307 << digi.getTDC().at(2);
308 }
309
310
311 for (uint i = 0; i < n_modules; i++)
312 event.
add(output_collection_ + Form(
"%i", i + 1), out_digis[i]);
313}
void add(const std::string &collectionName, T &obj)
Adds an object to the event bus.
static const int TIMESTAMP_POS
for each time sample, every lane each sends a message: [ 1B ADC for 6 channels, 2B empty,...