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

Detailed Description

Definition at line 15 of file QIEEncoder.h.

Constructor & Destructor Documentation

◆ QIEEncoder()

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

Definition at line 17 of file QIEEncoder.h.

18 : 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 8 of file QIEEncoder.cxx.

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

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 236 of file QIEEncoder.cxx.

236 {
237 ldmx_log(debug) << "Process ends!";
238
239 return;
240}

◆ 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 230 of file QIEEncoder.cxx.

230 {
231 ldmx_log(debug) << "Process starts!";
232
233 return;
234}

◆ 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 58 of file QIEEncoder.cxx.

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

◆ channel_map_file_

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

Definition at line 40 of file QIEEncoder.h.

◆ channel_map_file_name_

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

Definition at line 39 of file QIEEncoder.h.

◆ input_collection_

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

Definition at line 44 of file QIEEncoder.h.

◆ input_pass_name_

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

Definition at line 45 of file QIEEncoder.h.

◆ n_channels_

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

Definition at line 54 of file QIEEncoder.h.

54{50};

◆ output_collection_

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

Definition at line 47 of file QIEEncoder.h.

◆ verbose_

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

Definition at line 51 of file QIEEncoder.h.

51{false};

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