LDMX Software
trigscint::ZCCMDecoder Class Reference

Public Member Functions

 ZCCMDecoder (const std::string &name, framework::Process &process)
 
virtual ~ZCCMDecoder ()=default
 Default destructor, closes up boost archive and input stream.
 
void configure (framework::config::Parameters &ps) override
 Configure our converter based off the configuration parameters decoded from the passed python script.
 
void produce (framework::Event &event) override
 Process the event and put new data products into it.
 
void onProcessStart () override
 Callback for the EventProcessor to take any necessary action when the processing of events starts, such as creating histograms.
 
void onProcessEnd () override
 Callback for the EventProcessor to take any necessary action when the processing of events finishes, such as calculating job-summary quantities.
 
- Public Member Functions inherited from framework::Producer
 Producer (const std::string &name, Process &process)
 Class constructor.
 
virtual void process (Event &event) final
 Processing an event for a Producer is calling produce.
 
- Public Member Functions inherited from framework::EventProcessor
 DECLARE_FACTORY (EventProcessor, EventProcessor *, const std::string &, Process &)
 declare that we have a factory for this class
 
 EventProcessor (const std::string &name, Process &process)
 Class constructor.
 
virtual ~EventProcessor ()=default
 Class destructor.
 
virtual void beforeNewRun (ldmx::RunHeader &run_header)
 Callback for Producers to add parameters to the run header before conditions are initialized.
 
virtual void onNewRun (const ldmx::RunHeader &run_header)
 Callback for the EventProcessor to take any necessary action when the run being processed changes.
 
virtual void onFileOpen (EventFile &event_file)
 Callback for the EventProcessor to take any necessary action when a new event input ROOT file is opened.
 
virtual void onFileClose (EventFile &event_file)
 Callback for the EventProcessor to take any necessary action when a event input ROOT file is closed.
 
template<class T >
const T & getCondition (const std::string &condition_name)
 Access a conditions object for the current event.
 
TDirectory * getHistoDirectory ()
 Access/create a directory in the histogram file for this event processor to create histograms and analysis tuples.
 
void setStorageHint (framework::StorageControl::Hint hint)
 Mark the current event as having the given storage control hint from this module_.
 
void setStorageHint (framework::StorageControl::Hint hint, const std::string &purposeString)
 Mark the current event as having the given storage control hint from this module and the given purpose string.
 
int getLogFrequency () const
 Get the current logging frequency from the process.
 
int getRunNumber () const
 Get the run number from the process.
 
std::string getName () const
 Get the processor name.
 
void createHistograms (const std::vector< framework::config::Parameters > &histos)
 Internal function which is used to create histograms passed from the python configuration @parma histos vector of Parameters that configure histograms to create.
 

Private Attributes

std::string channel_map_file_name_
 the channel mapping
 
std::ifstream channel_map_file_
 
std::map< int, int > channel_map_
 
std::string module_map_file_name_
 the module mapping
 
std::ifstream module_map_file_
 
std::map< int, int > module_map_
 
std::string input_collection_
 
std::string output_collection_
 
std::string input_pass_name_
 
int number_of_lanes_ {14}
 
int n_channels_ {number_of_lanes_ * ZCCMOutput::NUM_CHAN_PER_LANE}
 
int n_samples_ {70}
 
bool is_real_data_ {true}
 
int modules_used_ [4] = {0}
 

Additional Inherited Members

- Protected Member Functions inherited from framework::EventProcessor
void abortEvent ()
 Abort the event immediately.
 
- Protected Attributes inherited from framework::EventProcessor
HistogramPool histograms_
 helper object for making and filling histograms
 
NtupleManagerntuple_ {NtupleManager::getInstance()}
 Manager for any ntuples.
 
logging::logger the_log_
 The logger for this EventProcessor.
 

Detailed Description

Definition at line 16 of file ZCCMDecoder.h.

Constructor & Destructor Documentation

◆ ZCCMDecoder()

trigscint::ZCCMDecoder::ZCCMDecoder ( const std::string & name,
framework::Process & process )
inline

Definition at line 18 of file ZCCMDecoder.h.

19 : Producer(name, process) {}
Producer(const std::string &name, Process &process)
Class constructor.
virtual void process(Event &event) final
Processing an event for a Producer is calling produce.

Member Function Documentation

◆ configure()

void trigscint::ZCCMDecoder::configure ( framework::config::Parameters & ps)
overridevirtual

Configure our converter based off the configuration parameters decoded from the passed python script.

Reimplemented from framework::EventProcessor.

Definition at line 9 of file ZCCMDecoder.cxx.

9 {
10 // Configure this instance of the encoder
11 output_collection_ = ps.get<std::string>("output_collection");
12 input_collection_ = ps.get<std::string>("input_collection");
13 input_pass_name_ = ps.get<std::string>("input_pass_name");
14 module_map_file_name_ = ps.get<std::string>("module_map_file");
15 channel_map_file_name_ = ps.get<std::string>("channel_map_file");
16 n_channels_ = ps.get<int>("number_channels");
17 n_samples_ = ps.get<int>("number_time_samples");
18 is_real_data_ = ps.get<bool>("is_real_data");
19 // daq_junk_words_len_bytes_ = ps.get<int>("daq_extra_header_bytes");
20 // daq_junk_tail_len_bits_ = ps.get<int>("daq_trailing_header_bits");
21
22 ldmx_log(debug) << "In configure, got parameters:" << "\noutput_collection = "
23 << output_collection_
24 << "\ninput_collection = " << input_collection_
25 << "\ninput_pass_name = " << input_pass_name_
26 << "\nmodule_map_file = " << module_map_file_name_
27 << "\nchannel_map_file = " << channel_map_file_name_
28 << "\nnumber_channels = " << n_channels_
29 << "\nnumber_time_samples = " << n_samples_
30 << "\nis_real_data = " << is_real_data_;
31
32 channel_map_file_.open(channel_map_file_name_, std::ios::in);
33 if (!channel_map_file_.is_open()) {
34 EXCEPTION_RAISE("BadMapFile", "The channel mapping file cannot be opened.");
35 return;
36 }
37 int n_chan_from_map = -1; // we will in effect count newlines
38 int ch_id, el_id;
39 while (!channel_map_file_.eof()) {
40 channel_map_file_ >> el_id >> ch_id;
41 // make the map based on electronics ID, to look up channel ID.
42 // the reason is, the elecID is given by the position of the word in
43 // the output. so these need to be strictly ordered.
44 // writing the right bar in the right position is easier if we can just
45 // read this map from beginning to end.
46 // barID can always be set, or looked up, as a property of the digi.
47
48 // here make the elecID the key (other way around when encoding)
49 channel_map_.insert(std::pair<int, int>(el_id, ch_id));
50 ldmx_log(debug) << el_id << " chID " << ch_id;
51 n_chan_from_map++; // will increment on last newline as well
52 }
53 channel_map_file_.close();
54 if (n_chan_from_map != n_channels_)
55 ldmx_log(fatal) << "The set number of channels: " << n_channels_
56 << " does not match the number obtained from the map :"
57 << n_chan_from_map;
58
59 // and similarly for the lane-->module mapping
60
61 module_map_file_.open(module_map_file_name_, std::ios::in);
62 if (!module_map_file_.is_open()) {
63 ldmx_log(fatal) << "The module mapping file cannot be opened.";
64 return;
65 }
66 int module_id, lane_id;
67 while (!module_map_file_.eof()) {
68 module_map_file_ >> lane_id >> module_id;
69 // make the map based on lane ID, to look up module ID.
70 // here make the lane the key (other way around when encoding)
71 module_map_.insert(std::pair<int, int>(lane_id, module_id));
72 ldmx_log(debug) << "lane " << lane_id << " --> module ID " << module_id;
73 modules_used_[module_id] = 1;
74 }
75 module_map_file_.close();
76 int n_lanes = n_channels_ / ZCCMOutput::NUM_CHAN_PER_LANE;
77 if (lane_id != n_lanes - 1)
78 ldmx_log(fatal) << "The set number of lanes " << n_lanes
79 << " seems not to match the number obtained from the map :"
80 << lane_id + 1;
81
82 return;
83}
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:78
std::string channel_map_file_name_
the channel mapping
Definition ZCCMDecoder.h:40
std::string module_map_file_name_
the module mapping
Definition ZCCMDecoder.h:44

References channel_map_file_name_, framework::config::Parameters::get(), and module_map_file_name_.

◆ onProcessEnd()

void trigscint::ZCCMDecoder::onProcessEnd ( )
overridevirtual

Callback for the EventProcessor to take any necessary action when the processing of events finishes, such as calculating job-summary quantities.

Reimplemented from framework::EventProcessor.

Definition at line 338 of file ZCCMDecoder.cxx.

338 {
339 ldmx_log(debug) << "Process ends!";
340
341 return;
342}

◆ onProcessStart()

void trigscint::ZCCMDecoder::onProcessStart ( )
overridevirtual

Callback for the EventProcessor to take any necessary action when the processing of events starts, such as creating histograms.

Reimplemented from framework::EventProcessor.

Definition at line 332 of file ZCCMDecoder.cxx.

332 {
333 ldmx_log(debug) << "Process starts!";
334
335 return;
336}

◆ produce()

void trigscint::ZCCMDecoder::produce ( framework::Event & event)
overridevirtual

Process the event and put new data products into it.

Parameters
eventThe Event to process.

Implements framework::Producer.

Definition at line 85 of file ZCCMDecoder.cxx.

85 {
86 ldmx_log(debug) << "ZCCMDecoder: produce() starts! Event number: "
87 << event.getEventHeader().getEventNumber();
88
89 // this has to be configurable for now, to read real data
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 /* -- PROCESS THE EVENT INFORMATION -- */
101
102 uint32_t time_stamp = 0;
103 for (int i_w = 0; i_w < ZCCMOutput::TIMESTAMP_LEN_BYTES; i_w++) {
104 int pos = ZCCMOutput::TIMESTAMP_POS + i_w;
105 uint8_t time_word = event_output.at(pos);
106 ldmx_log(debug) << "time stamp word at position " << pos
107 << " (with iW = " << i_w
108 << ") = " << std::bitset<8>(time_word);
109 time_stamp |= (time_word << i_w * 8); // shift by a byte at a time
110 }
111 // TODO: make actual use of the time stamp in the event header
112 /* the below is what was done before and does not apply for now,
113 what one could do is maybe compare to the previous
114 timestamp to make sure they are always incremented.
115
116 // ldmx_log(debug) << " got triggerID " << std::bitset<16>(triggerID) ;
117 ldmx_log(debug) << " got triggerID " << std::bitset<32>(trigger_id);
118
119 if (trigger_id != event.getEventHeader().getEventNumber()) {
120 // this probably only applies to digi emulation,
121 // unless an event number is explicitly set in unpacking
122 ldmx_log(fatal) << "Got event number mismatch: framework reports "
123 << event.getEventHeader().getEventNumber()
124 << ", output says " << trigger_id;
125 }
126 */
127 event.getEventHeader().setIntParameter("time_stamp_", time_stamp);
128 TTimeStamp *ttime_stamp = new TTimeStamp(time_stamp);
129 event.getEventHeader().setTimestamp(
130 *ttime_stamp); // still not sure this works
131
132 /* -- TS event header done; read the channel contents -- */
133
134 /*
135 in a loop over samples, loop over nlanes
136 get ADC, TDC, flags and lane nb
137 lane number uses a full byte
138 the flags word contains
139 - capID (2b)
140 - CE (1b, some channel alignment error flag)
141 - BC0 (most of the time 0, set to 1 with fixed frequency. if channels
142 are aligned, then BC0=1 should occur in the same time sample for all of
143 them)
144 - 4 trailing reserved 0's
145 */
146
147 std::map<int, std::vector<int>> adc_map;
148 std::map<int, std::vector<int>> tdc_map;
149 std::map<int, std::vector<int>> cid_map;
150 std::map<int, std::vector<int>> bc0_map;
151 std::map<int, std::vector<int>> ce_map;
152 // we need one output digi collection per pad
153 std::vector<std::vector<trigscint::TrigScintQIEDigis>> out_digis;
154 std::size_t n_modules =
155 std::ranges::count_if(modules_used_, [](int x) { return x != 0; });
156 // default construct (empty) vectors of digis separated into modules
157 out_digis.resize(n_modules);
158
159 // read in words from the output. line them up per channel and time sample.
160 // channels are in the electronics ordering
161 int word_length = ZCCMOutput::SAMPLE_WORD_LEN_BYTES;
162 int num_messages =
163 ((int)event_output.size() - ZCCMOutput::EVENTDATA_POS) / word_length;
164
165 // with one message per time sample per lane, we expect nSample*nLanes
166 // messages
167 int n_lanes = n_channels_ / ZCCMOutput::NUM_CHAN_PER_LANE;
168 int num_expected_messages = n_samp * n_lanes;
169 if (num_messages != num_expected_messages)
170 ldmx_log(warn) << "Unexpected stream length! Num messages is "
171 << num_messages << ", expect " << num_expected_messages;
172
173 // read in a lane stream at a time with a while loop
174 // operate on bytes, but i_word increments for each meassage i.e. each lane
175 int i_word = 0;
176 int start_lane = -1;
177 int sample_nb = -1;
178
179 while (i_word < num_messages) { // update the position to read the word from
180 uint word_pos = ZCCMOutput::EVENTDATA_POS + i_word * word_length;
181
182 uint16_t empty =
183 event_output.at(word_pos + ZCCMOutput::EMPTY_WORD_SAMPLE_WORD_POS);
184 uint8_t lane = event_output.at(word_pos + ZCCMOutput::LANE_SAMPLE_WORD_POS);
185 uint8_t flag =
186 event_output.at(word_pos + ZCCMOutput::FLAGS_SAMPLE_WORD_POS);
187
188 ldmx_log(debug) << "Start of message " << i_word << ".\n\tEmpty word is "
189 << std::bitset<16>(empty) << ", read at position "
190 << word_pos + ZCCMOutput::EMPTY_WORD_SAMPLE_WORD_POS
191 << ". \n\tFlag word is " << std::bitset<8>(flag)
192 << ", read at position "
193 << word_pos + ZCCMOutput::FLAGS_SAMPLE_WORD_POS
194 << ". \n\tLane is " << std::bitset<8>(lane)
195 << ", read at position "
196 << word_pos + ZCCMOutput::LANE_SAMPLE_WORD_POS << ".";
197
198 if (start_lane == -1) { // it is unset
199 start_lane = lane; // store the first one
200 ldmx_log(debug) << "Set time sample start lane to " << start_lane;
201 }
202 // extract the flag info
203 int cid{(flag >> ZCCMOutput::CAPID_POS_IN_FLAG) &
205 ldmx_log(trace) << "Got Cap ID " << cid;
206 bool bc0{static_cast<bool>((flag >> ZCCMOutput::BC0_POS_IN_FLAG) &
208 ldmx_log(trace) << "Got BC0 flag " << bc0;
209 bool ce{static_cast<bool>((flag >> ZCCMOutput::CE_POS_IN_FLAG) &
211 ldmx_log(trace) << "Got CE flag " << ce;
212 int empty_bits{(flag >> ZCCMOutput::EMPTY_FLAG_WORD_POS_IN_FLAG) &
214 if (empty_bits)
215 ldmx_log(fatal) << "Empty bits of flag not empty: " << empty_bits;
216
217 // TODO: check that BC0 bit is aligned across all lanes
218 // TODO: keep track of the CID cycling and flag when a CID is skipped
219 // bool is_cid_unsync{static_cast<bool>((flags >>
220 // ZCCMOutput::CID_UNSYNC_POS) &
221 // Mask8<ZCCMOutput::FLAG_SIZE_BITS>::M)};
222
223 // how do we know we're at the next time sample?
224 // 1. i_word has incremented by the number of lanes
225 // // i.e i_word % nLanes = 0
226 // 2. we're seeing the first lane again
227 // it is good, then, to check that these agree.
228
229 if (lane == start_lane) // we have cycled (or just started)
230 sample_nb++;
231
232 uint8_t cid_val = cid;
233
234 // get channel-by-channel info (ADC and TDC for this time sample)
235 for (int i_c = 0; i_c < ZCCMOutput::NUM_CHAN_PER_LANE; i_c++) {
236 if (i_word >= num_expected_messages) {
237 ldmx_log(fatal)
238 << "More words than expected! Breaking event data loop in sample "
239 << sample_nb << " at lane = " << lane << ", channel nb " << i_c;
240 break;
241 }
242 uint8_t adc_val =
243 event_output.at(word_pos + ZCCMOutput::ADC_SAMPLE_WORD_POS + i_c);
244 uint8_t tdc_val =
245 event_output.at(word_pos + ZCCMOutput::TDC_SAMPLE_WORD_POS + i_c);
246 // define a unique elecID for each channel in the readout, comprising of
247 // lane, module, channelNB then use that to look up bar ID in the the maps
248 int module = module_map_[lane];
249 int elec_id = 100 * lane + 10 * module + i_c; // numbering scheme: LLMC
250
251 ldmx_log(trace) << "got ADC value " << (unsigned)adc_val
252 << " and TDC value " << (unsigned)tdc_val
253 << " at channel idx " << i_c << " with elec id "
254 << elec_id;
255 if (adc_map.find(elec_id) == adc_map.end()) { // we have a new channel
256 std::vector<int> adcs(n_samp, 0);
257 adc_map.insert(std::pair<int, std::vector<int>>(elec_id, adcs));
258 }
259 adc_map[elec_id].at(sample_nb) = adc_val;
260 // perhaps overly prudent to check for TDC and CID as well, might tag them
261 // along on ADC
262 if (tdc_map.find(elec_id) == tdc_map.end()) { // we have a new channel
263 std::vector<int> tdcs(n_samp, 0);
264 tdc_map.insert(std::pair<int, std::vector<int>>(elec_id, tdcs));
265 }
266 tdc_map[elec_id].at(sample_nb) = tdc_val;
267 if (cid_map.find(elec_id) == cid_map.end()) { // we have a new channel
268 std::vector<int> cids(n_samp, 0);
269 cid_map.insert(std::pair<int, std::vector<int>>(elec_id, cids));
270 std::vector<int> bc0s(n_samp, 0);
271 bc0_map.insert(std::pair<int, std::vector<int>>(elec_id, bc0s));
272 std::vector<int> ces(n_samp, 0);
273 ce_map.insert(std::pair<int, std::vector<int>>(elec_id, ces));
274 }
275 cid_map[elec_id].at(sample_nb) = cid_val;
276 bc0_map[elec_id].at(sample_nb) = bc0;
277 ce_map[elec_id].at(sample_nb) = ce;
278 } // over channels
279 ldmx_log(debug) << "Done with lane " << int(lane) << " which we think is "
280 << i_word % n_lanes << " in sample " << sample_nb;
281
282 if (int(lane) != i_word % n_lanes)
283 ldmx_log(fatal) << "Lane ordering has been messed up! Expect lane "
284 << i_word % n_lanes << ", but we got lane " << int(lane);
285 // shift to next word
286 i_word++;
287 } // while event data words left in the stream
288
289 ldmx_log(debug) << "Done reading in header, ADC and TDC for event "
290 << event.getEventNumber();
291
292 // Reading step done.
293 /* -- make digis from all the info stored in maps -- */
294 for (std::map<int, std::vector<int>>::iterator itr = adc_map.begin();
295 itr != adc_map.end(); ++itr) {
296 TrigScintQIEDigis digi;
297 digi.setADC(itr->second);
298 if (channel_map_.find(itr->first) == channel_map_.end()) {
299 ldmx_log(fatal)
300 << "Couldn't find the bar ID corresponding to electronics ID "
301 << itr->first << "!! Skipping.";
302 continue;
303 }
304 int bar = channel_map_[itr->first];
305 digi.setElecID(itr->first);
306 digi.setChanID(bar);
307 int module = itr->first / 10 % 10;
308 digi.setModuleID(module);
309 int lane = itr->first / 100;
310 digi.setLaneID(lane);
311 digi.setTDC(tdc_map[itr->first]);
312 digi.setCID(cid_map[itr->first]);
313 digi.setBC0(bc0_map[itr->first]);
314 digi.setCE(ce_map[itr->first]);
315 if (bar == 0)
316 ldmx_log(debug) << "for bar 0, got time since spill "
317 << digi.getTimeSinceSpill();
318 out_digis[module].push_back(digi);
319 ldmx_log(debug) << "Iterator points to key " << itr->first
320 << " and mapped channel supposedly is " << bar;
321 ldmx_log(debug) << "Made digi with elecID = " << digi.getElecID()
322 << ", barID = " << digi.getChanID() << ", third adc value "
323 << digi.getADC().at(2) << " and third tdc "
324 << digi.getTDC().at(2);
325 }
326
327 // name them as ordered
328 for (uint i = 0; i < n_modules; i++)
329 event.add(output_collection_ + Form("%i", i + 1), out_digis[i]);
330}
void add(const std::string &collectionName, T &obj)
Adds an object to the event bus.
Definition Event.h:184

References framework::Event::add(), trigscint::TrigScintQIEDigis::getADC(), trigscint::TrigScintQIEDigis::getChanID(), trigscint::TrigScintQIEDigis::getElecID(), trigscint::TrigScintQIEDigis::getTDC(), trigscint::TrigScintQIEDigis::getTimeSinceSpill(), trigscint::TrigScintQIEDigis::setADC(), trigscint::TrigScintQIEDigis::setBC0(), trigscint::TrigScintQIEDigis::setCE(), trigscint::TrigScintQIEDigis::setChanID(), trigscint::TrigScintQIEDigis::setCID(), trigscint::TrigScintQIEDigis::setElecID(), trigscint::TrigScintQIEDigis::setLaneID(), trigscint::TrigScintQIEDigis::setModuleID(), and trigscint::TrigScintQIEDigis::setTDC().

Member Data Documentation

◆ channel_map_

std::map<int, int> trigscint::ZCCMDecoder::channel_map_
private

Definition at line 42 of file ZCCMDecoder.h.

◆ channel_map_file_

std::ifstream trigscint::ZCCMDecoder::channel_map_file_
private

Definition at line 41 of file ZCCMDecoder.h.

◆ channel_map_file_name_

std::string trigscint::ZCCMDecoder::channel_map_file_name_
private

the channel mapping

Definition at line 40 of file ZCCMDecoder.h.

Referenced by configure().

◆ input_collection_

std::string trigscint::ZCCMDecoder::input_collection_
private

Definition at line 49 of file ZCCMDecoder.h.

◆ input_pass_name_

std::string trigscint::ZCCMDecoder::input_pass_name_
private

Definition at line 51 of file ZCCMDecoder.h.

◆ is_real_data_

bool trigscint::ZCCMDecoder::is_real_data_ {true}
private

Definition at line 63 of file ZCCMDecoder.h.

63{true};

◆ module_map_

std::map<int, int> trigscint::ZCCMDecoder::module_map_
private

Definition at line 46 of file ZCCMDecoder.h.

◆ module_map_file_

std::ifstream trigscint::ZCCMDecoder::module_map_file_
private

Definition at line 45 of file ZCCMDecoder.h.

◆ module_map_file_name_

std::string trigscint::ZCCMDecoder::module_map_file_name_
private

the module mapping

Definition at line 44 of file ZCCMDecoder.h.

Referenced by configure().

◆ modules_used_

int trigscint::ZCCMDecoder::modules_used_[4] = {0}
private

Definition at line 65 of file ZCCMDecoder.h.

65{0};

◆ n_channels_

int trigscint::ZCCMDecoder::n_channels_ {number_of_lanes_ * ZCCMOutput::NUM_CHAN_PER_LANE}
private

Definition at line 59 of file ZCCMDecoder.h.

59{number_of_lanes_ * ZCCMOutput::NUM_CHAN_PER_LANE};

◆ n_samples_

int trigscint::ZCCMDecoder::n_samples_ {70}
private

Definition at line 61 of file ZCCMDecoder.h.

61{70};

◆ number_of_lanes_

int trigscint::ZCCMDecoder::number_of_lanes_ {14}
private

Definition at line 54 of file ZCCMDecoder.h.

54{14};

◆ output_collection_

std::string trigscint::ZCCMDecoder::output_collection_
private

Definition at line 50 of file ZCCMDecoder.h.


The documentation for this class was generated from the following files: