LDMX Software
trigscint::QIEDecoder Class Reference

Public Member Functions

 QIEDecoder (const std::string &name, framework::Process &process)
 
virtual ~QIEDecoder ()=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 input_collection_
 
std::string output_collection_
 
std::string input_pass_name_
 
int n_channels_ {50}
 
int n_samples_ {5}
 

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
 
NtupleManager & ntuple_ {NtupleManager::getInstance()}
 Manager for any ntuples.
 
logging::logger the_log_
 The logger for this EventProcessor.
 

Detailed Description

Definition at line 11 of file QIEDecoder.h.

Constructor & Destructor Documentation

◆ QIEDecoder()

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

Definition at line 13 of file QIEDecoder.h.

14 : 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::QIEDecoder::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 14 of file QIEDecoder.cxx.

14 {
15 // Configure this instance of the encoder
16 output_collection_ = ps.get<std::string>("output_collection");
17 input_collection_ = ps.get<std::string>("input_collection");
18 input_pass_name_ = ps.get<std::string>("input_pass_name");
19 channel_map_file_name_ = ps.get<std::string>("channel_map_file");
20 n_channels_ = ps.get<int>("number_channels");
21 n_samples_ = ps.get<int>("number_time_samples");
22
23 ldmx_log(debug) << "In configure, got parameters:" << "\noutput_collection = "
24 << output_collection_
25 << "\ninput_collection = " << input_collection_
26 << "\ninput_pass_name = " << input_pass_name_
27 << "\nchannel_map_file = " << channel_map_file_name_
28 << "\nnumber_channels = " << n_channels_
29 << "\nnumber_time_samples = " << n_samples_;
30
31 channel_map_file_.open(channel_map_file_name_, std::ios::in);
32 if (!channel_map_file_.is_open()) {
33 EXCEPTION_RAISE(
34 "BadMapFile",
35 "The channel mapping file cannot be opened."); // <-- appears this
36 // needs implementing
37 // first
38 ldmx_log(fatal) << "The channel mapping file cannot be opened.";
39 return;
40 }
41 int ch_id, el_id;
42 while (!channel_map_file_.eof()) {
43 channel_map_file_ >> el_id >> ch_id;
44 // make the map based on electronics ID, to look up channel ID.
45 // the reason is, we will only know the elecID from the position
46 // of the word in the stream. so these need to be strictly ordered.
47 // writing the right bar in the right position is easier if we can just
48 // read this map from beginning to end.
49 // barID can always be set, or looked up, as a property of the digi.
50
51 // here make the elecID the key (other way around when encoding)
52 channel_map_.insert(std::pair<int, int>(el_id, ch_id));
53 ldmx_log(debug) << el_id << " chID " << ch_id;
54 }
55 channel_map_file_.close();
56 if (el_id != n_channels_ - 1)
57 ldmx_log(fatal) << "The set number of channels " << n_channels_
58 << " seems not to match the number from the map (+1) :"
59 << el_id;
60 return;
61}
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:75
std::string channel_map_file_name_
the channel mapping
Definition QIEDecoder.h:35

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

◆ onProcessEnd()

void trigscint::QIEDecoder::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 300 of file QIEDecoder.cxx.

300 {
301 ldmx_log(debug) << "Process ends!";
302
303 return;
304}

◆ onProcessStart()

void trigscint::QIEDecoder::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 294 of file QIEDecoder.cxx.

294 {
295 ldmx_log(debug) << "Process starts!";
296
297 return;
298}

◆ produce()

void trigscint::QIEDecoder::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 63 of file QIEDecoder.cxx.

63 {
64 ldmx_log(debug) << "QIEDecoder: produce() starts! Event number: "
65 << event.getEventHeader().getEventNumber();
66
67 // turns out this need to be configurable for now, to read real data
68 int n_samp = n_samples_; // QIEStream::NUM_SAMPLES ;
69 ldmx_log(debug) << "num samples = " << n_samp;
70
71 ldmx_log(debug) << "Looking up input collection " << input_collection_ << "_"
72 << input_pass_name_;
73 const auto event_stream{
74 event.getCollection<uint8_t>(input_collection_, input_pass_name_)};
75 ldmx_log(debug) << "Got input collection" << input_collection_ << "_"
76 << input_pass_name_;
77
78 uint32_t time_epoch = 0;
79 // these don't have to be in any particular order, position is anyway looked
80 // up from definition in header
81 for (int i_w = 0; i_w < QIEStream::TIMESTAMP_LEN_BYTES; i_w++) {
82 int pos = QIEStream::TIMESTAMP_POS + i_w;
83 uint8_t time_word = event_stream.at(pos);
84 ldmx_log(debug) << "time stamp word at position " << pos
85 << " (with iW = " << i_w
86 << ") = " << std::bitset<8>(time_word);
87 time_epoch |= (time_word << i_w * 8); // shift by a byte at a time
88 }
89
90 uint32_t time_clock = 0;
91 for (int i_w = 0; i_w < QIEStream::TIMESTAMPCLOCK_LEN_BYTES; i_w++) {
92 int pos = QIEStream::TIMESTAMPCLOCK_POS + i_w;
93 uint8_t time_word = event_stream.at(pos);
94 ldmx_log(debug) << "time stamp ns word at position " << pos
95 << " (with iW = " << i_w
96 << ") = " << std::bitset<8>(time_word);
97 time_clock |= (time_word << i_w * 8); // shift by a byte at a time
98 }
99
100 uint32_t time_spill = 0;
101 ldmx_log(debug) << "Before starting, timeSpill = " << time_spill << " ("
102 << std::bitset<64>(time_spill) << ", or, " << std::hex
103 << time_spill << std::dec << ") counts since start of spill";
104
105 for (int i_w = 0; i_w < QIEStream::TIMESINCESPILL_LEN_BYTES; i_w++) {
106 int pos = QIEStream::TIMESINCESPILL_POS + i_w;
107 uint8_t time_word = event_stream.at(pos);
108 ldmx_log(debug) << "time since spill word at position " << pos
109 << " (with iW = " << i_w
110 << ") = " << std::bitset<8>(time_word);
111 time_spill |= (time_word << i_w * 8); // shift by a byte at a time
112 }
113 ldmx_log(debug) << "time stamp words are : " << time_epoch << " ("
114 << std::bitset<64>(time_epoch) << ") and " << time_clock
115 << " (" << std::bitset<64>(time_clock)
116 << ") clock ticks, and " << time_spill << " ("
117 << std::bitset<64>(time_spill) << ", or, " << std::hex
118 << time_spill << std::dec << ") counts since start of spill";
119
120 int sig_bits_skip = 6; // the first 6 bits are part of something else.
121 int divisor = TMath::Power(2, 32 - sig_bits_skip);
122 // remove them by taking remainder in division by
123 // the values of the last skipped bit
124 time_spill = time_spill % divisor;
125 ldmx_log(debug) << "After taking it mod 2^" << 32 - sig_bits_skip
126 << " (which is " << divisor << ", spill time is "
127 << time_spill;
128 event.getEventHeader().setIntParameter("timeSinceSpill", time_spill);
129
130 TTimeStamp* time_stamp = new TTimeStamp(time_epoch);
131 event.getEventHeader().setTimestamp(*time_stamp);
132
133 // trigger ID event number
134 uint32_t trigger_id = 0;
135
136 for (int i_w = 0; i_w < QIEStream::TRIGID_LEN_BYTES; i_w++) {
137 // assume the whole 3B are written as a single 24 bits word
138 int pos = QIEStream::TRIGID_POS + i_w;
139 uint8_t t_i_dword = event_stream.at(pos);
140 ldmx_log(debug) << "trigger word at position " << pos
141 << " (with iW = " << i_w
142 << ") = " << std::bitset<8>(t_i_dword);
143 trigger_id |= (t_i_dword << i_w * 8); // shift by a byte at a time
144 }
145
146 // ldmx_log(debug) << " got triggerID " << std::bitset<16>(triggerID) ;
147 ldmx_log(debug) << " got triggerID " << std::bitset<32>(trigger_id);
148
149 if (trigger_id != event.getEventHeader().getEventNumber()) {
150 // this probably only applies to digi emulation,
151 // unless an event number is explicitly set in unpacking
152 ldmx_log(fatal) << "Got event number mismatch: framework reports "
153 << event.getEventHeader().getEventNumber()
154 << ", stream says " << trigger_id;
155 }
156
157 // error word
158 /* the error word contains
159 - 4 trailing reserved 0's, for now
160 - isCIDunsync : if there is a mismatch between CID reported by channels
161 within the same time sample
162 - isCIDskipped : if there is a gap in the CID increment of a channel
163 beweeen samples
164 - isCRC0malformed : if there was an issue with CRC from fiber0
165 - isCRC1malformed : if there was an issue with CRC from fiber1
166 */
167 uint8_t flags = event_stream.at(QIEStream::ERROR_POS);
168
169 bool is_ci_dskipped{static_cast<bool>((flags >> QIEStream::CID_SKIP_POS) &
171 bool is_ci_dunsync{static_cast<bool>((flags >> QIEStream::CID_UNSYNC_POS) &
173 // These are unused, should they be? FIXME
174 // bool isCRC1malformed{static_cast<bool>((flags >> QIEStream::CRC1_ERR_POS) &
175 // Mask8<QIEStream::FLAG_SIZE_BITS>::m)};
176 // bool isCRC0malformed{static_cast<bool>((flags >> QIEStream::CRC0_ERR_POS) &
177 // Mask8<QIEStream::FLAG_SIZE_BITS>::m)};
178
179 // checksum
180 // really, this is just empty for now.
181 // TODO: implement a checksum set/get
182 uint8_t reference_checksum = 0;
183 int checksum{(flags >> QIEStream::CHECKSUM_POS) &
185 // eventStream.at(QIEStream::CRC0_ERR_POS)
186 // QIEStream::CHECKSUM_POS);
187 if (checksum != reference_checksum)
188 ldmx_log(fatal) << "Got checksum mismatch: expected "
189 << (int)reference_checksum << ", stream says " << checksum;
190 if (is_ci_dunsync) ldmx_log(debug) << "Found unsynced CIDs!";
191 if (is_ci_dskipped) ldmx_log(fatal) << "Found skipped CIDs!";
192
193 /* -- TS event header done; read the channel contents -- */
194 std::vector<trigscint::TrigScintQIEDigis> out_digis;
195 std::map<int, std::vector<int>> ad_cmap;
196 std::map<int, std::vector<int>> td_cmap;
197
198 // read in words from the stream. line them up per channel and time sample.
199 // channels are in the electronics ordering
200 int i_wstart =
201 std::max(std::max(QIEStream::ERROR_POS, QIEStream::CHECKSUM_POS),
202 QIEStream::TRIGID_POS + (QIEStream::TRIGID_LEN_BYTES)) +
203 1;
204 // make sure we're at end of header
205 int n_words = n_samp * n_channels_ * 2 + i_wstart;
206 // 1 ADC, 1 TDC per channel per sample,
207 // + the words in the header
208 int i_word = i_wstart;
209 ldmx_log(debug) << "Event parsing starts at vector idx " << i_wstart
210 << " and nWords = " << n_words;
211 // outer loop: over nSamples
212 // inner loop over nChannels to get ADCs, then repeat to get TDCs
213 for (int i_s = 0; i_s < n_samp; i_s++) {
214 for (int i_q = 0; i_q < n_channels_; i_q++) {
215 if (i_word >= n_words) {
216 ldmx_log(fatal)
217 << "More words than expected! Breaking ADC loop in sample " << i_s
218 << " at iQ = " << i_q;
219 break;
220 }
221 uint8_t val = event_stream.at(i_word);
222 if (val > 0) { // add only the digis with non-zero ADC value
223 ldmx_log(debug) << "got ADC value " << (unsigned)val
224 << " at channel (elec) idx " << i_q;
225 if (ad_cmap.find(i_q) == ad_cmap.end()) { // we have a new channel
226 std::vector<int> adcs(n_samp, 0);
227 ad_cmap.insert(std::pair<int, std::vector<int>>(i_q, adcs));
228 }
229 ad_cmap[i_q].at(i_s) = val;
230 }
231 i_word++;
232 }
233 for (int i_q = 0; i_q < n_channels_; i_q++) {
234 if (i_word >= n_words) {
235 ldmx_log(debug)
236 << "More words than expected! Breaking TDC loop in sample " << i_s
237 << " at iQ = " << i_q;
238 break;
239 }
240 uint8_t val = event_stream.at(i_word);
241 if (val > 0) { // TODO: check if this channel is also present in ADC map?
242 // in the end?
243 ldmx_log(debug) << "got TDC value " << (unsigned)val
244 << " at channel (elec) idx " << i_q;
245 ;
246 if (td_cmap.find(i_q) == td_cmap.end()) { // we have a new channel
247 std::vector<int> tdcs(n_samp, 0);
248 td_cmap.insert(std::pair<int, std::vector<int>>(i_q, tdcs));
249 }
250 // this is LETDC; only the two most significant bits included
251 // they are shipped as least significant bits --> shift them
252 // TDCmap[iQ].at(iS) = (val + 1) * 16; // want LE TDC = 3 to correspond
253 // to
254 // 64 > 49 (which is maxTDC in sim)
255 td_cmap[i_q].at(i_s) = val; // have full 6-bit TDC at SLAC
256 }
257 i_word++;
258 }
259 ldmx_log(debug) << "Done with sample " << i_s;
260 }
261
262 ldmx_log(debug) << "Done reading in header, ADC and TDC for event "
263 << trigger_id;
264 for (std::map<int, std::vector<int>>::iterator itr = ad_cmap.begin();
265 itr != ad_cmap.end(); ++itr) {
266 TrigScintQIEDigis digi;
267 digi.setADC(itr->second);
268 if (channel_map_.find(itr->first) == channel_map_.end()) {
269 ldmx_log(fatal)
270 << "Couldn't find the bar ID corresponding to electronics ID "
271 << itr->first << "!! Skipping.";
272 continue;
273 }
274 int bar = channel_map_[itr->first];
275 digi.setElecID(itr->first);
276 digi.setChanID(bar);
277 digi.setTDC(td_cmap[itr->first]);
278 digi.setTimeSinceSpill(time_spill);
279 if (bar == 0)
280 ldmx_log(debug) << "for bar 0, got time since spill "
281 << digi.getTimeSinceSpill();
282 out_digis.push_back(digi);
283 ldmx_log(debug) << "Iterator points to key " << itr->first
284 << " and mapped channel supposedly is " << bar;
285 ldmx_log(debug) << "Made digi with elecID = " << digi.getElecID()
286 << ", barID = " << digi.getChanID() << ", third adc value "
287 << digi.getADC().at(2) << " and third tdc "
288 << digi.getTDC().at(2);
289 }
290
291 event.add(output_collection_, out_digis);
292}
ldmx::EventHeader & getEventHeader()
Get the event header.
Definition Event.h:57
int getEventNumber() const
Return the event number.
Definition EventHeader.h:78

References trigscint::TrigScintQIEDigis::getADC(), trigscint::TrigScintQIEDigis::getChanID(), trigscint::TrigScintQIEDigis::getElecID(), framework::Event::getEventHeader(), ldmx::EventHeader::getEventNumber(), trigscint::TrigScintQIEDigis::getTDC(), trigscint::TrigScintQIEDigis::getTimeSinceSpill(), trigscint::TrigScintQIEDigis::setADC(), trigscint::TrigScintQIEDigis::setChanID(), trigscint::TrigScintQIEDigis::setElecID(), trigscint::TrigScintQIEDigis::setTDC(), and trigscint::TrigScintQIEDigis::setTimeSinceSpill().

Member Data Documentation

◆ channel_map_

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

Definition at line 37 of file QIEDecoder.h.

◆ channel_map_file_

std::ifstream trigscint::QIEDecoder::channel_map_file_
private

Definition at line 36 of file QIEDecoder.h.

◆ channel_map_file_name_

std::string trigscint::QIEDecoder::channel_map_file_name_
private

the channel mapping

Definition at line 35 of file QIEDecoder.h.

Referenced by configure().

◆ input_collection_

std::string trigscint::QIEDecoder::input_collection_
private

Definition at line 40 of file QIEDecoder.h.

◆ input_pass_name_

std::string trigscint::QIEDecoder::input_pass_name_
private

Definition at line 42 of file QIEDecoder.h.

◆ n_channels_

int trigscint::QIEDecoder::n_channels_ {50}
private

Definition at line 45 of file QIEDecoder.h.

45{50};

◆ n_samples_

int trigscint::QIEDecoder::n_samples_ {5}
private

Definition at line 47 of file QIEDecoder.h.

47{5};

◆ output_collection_

std::string trigscint::QIEDecoder::output_collection_
private

Definition at line 41 of file QIEDecoder.h.


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