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}
 
bool is_real_data_ {false}
 

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 QIEDecoder.h.

Constructor & Destructor Documentation

◆ QIEDecoder()

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

Definition at line 18 of file QIEDecoder.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::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 9 of file QIEDecoder.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 channel_map_file_name_ = ps.get<std::string>("channel_map_file");
15 n_channels_ = ps.get<int>("number_channels");
16 n_samples_ = ps.get<int>("number_time_samples");
17 is_real_data_ = ps.get<bool>("is_real_data");
18
19 ldmx_log(debug) << "In configure, got parameters:" << "\noutput_collection = "
20 << output_collection_
21 << "\ninput_collection = " << input_collection_
22 << "\ninput_pass_name = " << input_pass_name_
23 << "\nchannel_map_file = " << channel_map_file_name_
24 << "\nnumber_channels = " << n_channels_
25 << "\nnumber_time_samples = " << n_samples_
26 << "\nis_real_data = " << is_real_data_;
27
28 channel_map_file_.open(channel_map_file_name_, std::ios::in);
29 if (!channel_map_file_.is_open()) {
30 EXCEPTION_RAISE(
31 "BadMapFile",
32 "The channel mapping file cannot be opened."); // <-- appears this
33 // needs implementing
34 // first
35 ldmx_log(fatal) << "The channel mapping file cannot be opened.";
36 return;
37 }
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, we will only know the elecID from the position
43 // of the word in the stream. 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 }
52 channel_map_file_.close();
53 if (el_id != n_channels_ - 1)
54 ldmx_log(fatal) << "The set number of channels " << n_channels_
55 << " seems not to match the number from the map (+1) :"
56 << el_id;
57 return;
58}
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 QIEDecoder.h:40

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

297 {
298 ldmx_log(debug) << "Process ends!";
299
300 return;
301}

◆ 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 291 of file QIEDecoder.cxx.

291 {
292 ldmx_log(debug) << "Process starts!";
293
294 return;
295}

◆ 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 60 of file QIEDecoder.cxx.

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

◆ channel_map_file_

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

Definition at line 41 of file QIEDecoder.h.

◆ channel_map_file_name_

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

the channel mapping

Definition at line 40 of file QIEDecoder.h.

Referenced by configure().

◆ input_collection_

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

Definition at line 45 of file QIEDecoder.h.

◆ input_pass_name_

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

Definition at line 47 of file QIEDecoder.h.

◆ is_real_data_

bool trigscint::QIEDecoder::is_real_data_ {false}
private

Definition at line 54 of file QIEDecoder.h.

54{false};

◆ n_channels_

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

Definition at line 50 of file QIEDecoder.h.

50{50};

◆ n_samples_

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

Definition at line 52 of file QIEDecoder.h.

52{5};

◆ output_collection_

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

Definition at line 46 of file QIEDecoder.h.


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