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