LDMX Software
trigscint::QIEEncoder Class Reference

Public Member Functions

 QIEEncoder (const std::string &name, framework::Process &process)
 
virtual ~QIEEncoder ()=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_
 
std::ifstream channel_map_file_
 
std::map< int, int > channel_map_
 
std::string input_collection_
 
std::string input_pass_name_
 
std::string output_collection_
 
bool verbose_ {false}
 
int n_channels_ {50}
 

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 12 of file QIEEncoder.h.

Constructor & Destructor Documentation

◆ QIEEncoder()

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

Definition at line 14 of file QIEEncoder.h.

15 : 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::QIEEncoder::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 12 of file QIEEncoder.cxx.

12 {
13 // Configure this instance of the encoder
14 output_collection_ = ps.get<std::string>("output_collection");
15 input_collection_ = ps.get<std::string>("input_collection");
16 input_pass_name_ = ps.get<std::string>("input_pass_name");
17 channel_map_file_name_ = ps.get<std::string>("channel_map_file");
18 n_channels_ = ps.get<int>("number_channels");
19 verbose_ = ps.get<bool>("verbose");
20
21 ldmx_log(debug) << "In configure, got parameters:" << "\noutput_collection = "
22 << output_collection_
23 << "\ninput_collection = " << input_collection_
24 << "\ninput_pass_name = " << input_pass_name_
25 << "\nchannel_map_file = " << channel_map_file_name_
26 << "\nnumber_channels = " << n_channels_
27 << "\nverbose = " << verbose_;
28
29 // set up channel mapping
30 channel_map_file_.open(channel_map_file_name_, std::ios::in);
31 if (!channel_map_file_.is_open()) {
32 EXCEPTION_RAISE(
33 "BadMapFile",
34 "The channel mapping file cannot be opened."); // <-- appears this
35 // needs implementing
36 // first
37 ldmx_log(fatal) << "The channel mapping file cannot be opened.";
38 return;
39 }
40 int ch_id, el_id;
41 while (!channel_map_file_.eof()) {
42 channel_map_file_ >> el_id >> ch_id;
43 // for test beam, we will only know the elecID from
44 // the position of the word in the stream.
45 // so these need to be strictly ordered in the map.
46 // barID can always be set, or looked up, as a property of the digi.
47
48 // make this based on channel ID. this is like looking up the position in a
49 // vector of a certain value. but it's fine
50 channel_map_.insert(std::pair<int, int>(ch_id, el_id));
51 ldmx_log(debug) << "elID " << el_id << " chID " << ch_id;
52 }
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 channel_map_file_.close();
58
59 return;
60}
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:75

References framework::config::Parameters::get().

◆ onProcessEnd()

void trigscint::QIEEncoder::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 240 of file QIEEncoder.cxx.

240 {
241 ldmx_log(debug) << "Process ends!";
242
243 return;
244}

◆ onProcessStart()

void trigscint::QIEEncoder::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 234 of file QIEEncoder.cxx.

234 {
235 ldmx_log(debug) << "Process starts!";
236
237 return;
238}

◆ produce()

void trigscint::QIEEncoder::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 62 of file QIEEncoder.cxx.

62 {
63 ldmx_log(debug) << "QIEEncoder: produce() starts! Event number: "
64 << event.getEventHeader().getEventNumber();
65
66 std::vector<trigscint::QIEStream> qie_outs;
67 int n_samp = QIEStream::NUM_SAMPLES;
68 std::vector<int> init_vec(n_samp, 0);
69 ldmx_log(debug) << "num samples = " << n_samp;
70
71 // we're keeping a list ordered in elec ID since this is the order we'll use
72 // to write them to stream
73 for (int i_q = 0; i_q < n_channels_; i_q++) {
74 QIEStream qie_out;
75 qie_out.setADC(init_vec);
76 qie_out.setTDC(init_vec);
77 qie_out.setCID(init_vec);
78 qie_out.setElectronicsID(i_q); // assume id is index
79
80 qie_outs.push_back(qie_out);
81 }
82
83 ldmx_log(debug) << "Looking up input collection " << input_collection_ << "_"
84 << input_pass_name_;
85 const auto digis{event.getCollection<trigscint::TrigScintQIEDigis>(
86 input_collection_, input_pass_name_)};
87 ldmx_log(debug) << "Got input collection" << input_collection_ << "_"
88 << input_pass_name_;
89
90 bool is_ci_dunsync = false; // mismatch between CID reported by channels
91 // within the same time sample
92 bool is_ci_dskipped = false; // a gap in the CID increment
93 bool is_cr_c0malformed = false; // an issue with CRC from fiber0
94 bool is_cr_c1malformed = false; // an issue with CRC from fiber1
95
96 int first_cid = -1;
97 ldmx_log(debug) << "entering loop over digis ";
98 for (auto& digi : digis) {
99 int bar = digi.getChanID();
100 auto itr = channel_map_.find(bar);
101 if (itr == channel_map_.end()) { // yikes! didn't find the bar in the map
102 ldmx_log(fatal) << "Couldn't find an entry for bar " << bar
103 << "; check the (choice of) channel map!. Exiting event "
104 << event.getEventHeader().getEventNumber();
105 return;
106 }
107 int idx = itr->second; // here we're just using the order. no actual elID
108 // is assumed.
109 qie_outs.at(idx).setChannelID(bar);
110 qie_outs.at(idx).setElectronicsID(idx);
111 ldmx_log(debug) << "Channel " << bar << " elec ID "
112 << qie_outs.at(idx).getElectronicsID();
113 std::vector<int> l_etdcs; // make the LE (Leading Edge) truncation explicit
114 std::vector<uint8_t> cids;
115 for (int i_s = 0; i_s < n_samp; i_s++) {
116 int tdc = digi.getTDC().at(i_s);
117 int cid = digi.getCID().at(i_s);
118 if (cids.size() > 0 && (cid % 4) != ((cids.back() + 1) % 4)) {
119 // by construction shouldn't happen in simulation. still, explicitly
120 // checking here, considering any future changes to our CID simulation.
121 is_ci_dskipped = true;
122 }
123 if (verbose_) { // all this is only useful for debugging
124 std::vector<uint8_t> adcs;
125 int adc = digi.getADC().at(i_s);
126 uint8_t mant = adc % 64;
127 uint8_t exp = adc / 64;
128 ldmx_log(debug) << "\tSample " << i_s << std::left << std::setw(6)
129 << " ADC " << adc << ",\texp " << unsigned(exp)
130 << " mant " << unsigned(mant) << ",\tTDC = " << tdc
131 << ", LE TDC = " << std::bitset<8>(tdc / 16)
132 << " and capID= " << cid;
133 adcs.push_back(64 * exp + mant);
134 ldmx_log(debug) << "Combined ADC: " << std::showbase
135 << std::bitset<8>(adcs.back()) << " and original adc "
136 << std::bitset<8>(adc) << std::dec;
137 } // if verbose
138
139 tdc /= 16; // do LE (leading edge) TDC
140 l_etdcs.push_back(tdc);
141 cids.push_back((uint8_t)cid);
142 } // over samples
143 if (first_cid == -1) {
144 // just store the 5th one, doesn't matter; if all channels
145 // are aligned then cids should match at any given time sample
146 first_cid = cids.back();
147 }
148 if (first_cid != cids.back()) {
149 is_ci_dunsync =
150 true; // any one channel not aligned is enough to set this bool
151 }
152 qie_outs.at(idx).setADC(digi.getADC());
153 qie_outs.at(idx).setTDC(l_etdcs);
154 } // over digis
155 if (is_ci_dunsync) ldmx_log(debug) << "Found unsynced CIDs!";
156 if (is_ci_dskipped) ldmx_log(info) << "Found skipped CIDs!";
157
158 // data format:
159 // RM ID: we don't set it for testbeam so skip for now.
160 // 16 bit trigger ID.
161 // 4 bits of flags, then 4 reserved 0 for now
162 // some 8-bit error word/checksum.
163 // all channel 8-bit ADCs.
164 // all channel TDCS.
165 // done.
166
167 uint16_t trigger_id = event.getEventHeader().getEventNumber();
168 uint8_t random_checksum =
169 30; // just some number for now. TODO implement a checksum
170 uint8_t flags = 0; // we use this to contain the four reserved 0's too
171 // put it all in, at the assigned position
172 flags |= (is_cr_c0malformed << QIEStream::CRC0_ERR_POS);
173 flags |= (is_cr_c1malformed << QIEStream::CRC1_ERR_POS);
174 flags |= (is_ci_dunsync << QIEStream::CID_UNSYNC_POS);
175 flags |= (is_ci_dskipped << QIEStream::CID_SKIP_POS);
176 ldmx_log(debug) << "FLAGS: " << std::bitset<8>(flags);
177
178 std::vector<uint8_t> out_word;
179 std::vector<uint8_t> trigger_i_dwords;
180 for (int i_w = QIEStream::TRIGID_LEN_BYTES - 1; i_w >= 0; i_w--) {
181 // assume the whole 2B are written as a single 16-bit word
182 uint8_t t_i_dword = trigger_id >> i_w * 8; // shift by a byte at a time
183 trigger_i_dwords.push_back(t_i_dword);
184 out_word.push_back(t_i_dword);
185 }
186
187 out_word.push_back(flags);
188 out_word.push_back(random_checksum);
189
190 if (verbose_) {
191 std::cout << "header word ";
192 for (auto word : out_word) std::cout << std::bitset<8>(word) << " ";
193 std::cout << std::endl;
194 }
195
196 // now write this in sequence: ADC of all channels, then TDC; repeat for all
197 // samples
198 for (int i_s = 0; i_s < n_samp; i_s++) {
199 for (int i_q = 0; i_q < n_channels_; i_q++) {
200 out_word.push_back(qie_outs.at(i_q).getADC().at(i_s));
201 } // over channels : ADC
202 for (int i_q = 0; i_q < n_channels_; i_q++) {
203 out_word.push_back(qie_outs.at(i_q).getTDC().at(i_s));
204 } // over channels: TDC
205 } // over time samples
206
207 // in verbose mode, print this all to screen
208 if (verbose_) {
209 std::cout << "total word ";
210 int widx = 0;
211 int i_wstart =
212 std::max(std::max(QIEStream::ERROR_POS, QIEStream::CHECKSUM_POS),
213 QIEStream::TRIGID_POS + (QIEStream::TRIGID_LEN_BYTES)) +
214 1; // probably overkill :D should be 4
215 for (auto word : out_word) {
216 if ((widx - i_wstart) % n_channels_ == 0) {
217 int sample = (widx - i_wstart) / n_channels_;
218 if (sample % 2 == 0)
219 std::cout << "\n sample " << sample / 2 << " | ";
220 else
221 std::cout << "\n TDC: ";
222 }
223 std::cout << (unsigned)word << " ";
224 // std::cout << std::bitset<8>(word) << " " ; //for binary output
225 // format
226 widx++;
227 }
228 std::cout << std::endl;
229 } // if verbose
230
231 event.add(output_collection_, out_word);
232}
class for storing QIE output

References trigscint::QIEStream::setADC(), trigscint::QIEStream::setCID(), trigscint::QIEStream::setElectronicsID(), and trigscint::QIEStream::setTDC().

Member Data Documentation

◆ channel_map_

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

Definition at line 38 of file QIEEncoder.h.

◆ channel_map_file_

std::ifstream trigscint::QIEEncoder::channel_map_file_
private

Definition at line 37 of file QIEEncoder.h.

◆ channel_map_file_name_

std::string trigscint::QIEEncoder::channel_map_file_name_
private

Definition at line 36 of file QIEEncoder.h.

◆ input_collection_

std::string trigscint::QIEEncoder::input_collection_
private

Definition at line 41 of file QIEEncoder.h.

◆ input_pass_name_

std::string trigscint::QIEEncoder::input_pass_name_
private

Definition at line 42 of file QIEEncoder.h.

◆ n_channels_

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

Definition at line 51 of file QIEEncoder.h.

51{50};

◆ output_collection_

std::string trigscint::QIEEncoder::output_collection_
private

Definition at line 44 of file QIEEncoder.h.

◆ verbose_

bool trigscint::QIEEncoder::verbose_ {false}
private

Definition at line 48 of file QIEEncoder.h.

48{false};

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