LDMX Software
Public Member Functions | Private Attributes | List of all members
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 beforeNewRun (ldmx::RunHeader &header)
 Handle allowing producers to modify run headers before the run begins.
 
- Public Member Functions inherited from framework::EventProcessor
 EventProcessor (const std::string &name, Process &process)
 Class constructor.
 
virtual ~EventProcessor ()
 Class destructor.
 
virtual void onNewRun (const ldmx::RunHeader &runHeader)
 Callback for the EventProcessor to take any necessary action when the run being processed changes.
 
virtual void onFileOpen (EventFile &eventFile)
 Callback for the EventProcessor to take any necessary action when a new event input ROOT file is opened.
 
virtual void onFileClose (EventFile &eventFile)
 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 channelMapFileName_
 the channel mapping
 
std::ifstream channelMapFile_
 
std::map< int, int > channelMap_
 
std::string inputCollection_
 
std::string outputCollection_
 
std::string inputPassName_
 
bool verbose_ {false}
 
int nChannels_ {50}
 
int nSamples_ {5}
 
bool isRealData_ {false}
 

Additional Inherited Members

- Static Public Member Functions inherited from framework::EventProcessor
static void declare (const std::string &classname, int classtype, EventProcessorMaker *)
 Internal function which is part of the PluginFactory machinery.
 
- Static Public Attributes inherited from framework::Producer
static const int CLASSTYPE {1}
 Constant used to track EventProcessor types by the PluginFactory.
 
- Protected Member Functions inherited from framework::EventProcessor
void abortEvent ()
 Abort the event immediately.
 
- Protected Attributes inherited from framework::EventProcessor
HistogramHelper histograms_
 Interface class for making and filling histograms.
 
NtupleManagerntuple_ {NtupleManager::getInstance()}
 Manager for any ntuples.
 
logging::logger theLog_
 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.

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 outputCollection_ = ps.getParameter<std::string>("output_collection");
12 inputCollection_ = ps.getParameter<std::string>("input_collection");
13 inputPassName_ = ps.getParameter<std::string>("input_pass_name");
14 channelMapFileName_ = ps.getParameter<std::string>("channel_map_file");
15 nChannels_ = ps.getParameter<int>("number_channels");
16 nSamples_ = ps.getParameter<int>("number_time_samples");
17 isRealData_ = ps.getParameter<bool>("is_real_data");
18 verbose_ = ps.getParameter<bool>("verbose");
19
20 ldmx_log(debug) << "In configure, got parameters:"
21 << "\noutput_collection = " << outputCollection_
22 << "\ninput_collection = " << inputCollection_
23 << "\ninput_pass_name = " << inputPassName_
24 << "\nchannel_map_file = " << channelMapFileName_
25 << "\nnumber_channels = " << nChannels_
26 << "\nnumber_time_samples = " << nSamples_
27 << "\nis_real_data = " << isRealData_
28 << "\nverbose = " << verbose_;
29
30 channelMapFile_.open(channelMapFileName_, std::ios::in);
31 if (!channelMapFile_.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 chID, elID;
41 while (!channelMapFile_.eof()) {
42 channelMapFile_ >> elID >> chID;
43 // make the map based on electronics ID, to look up channel ID.
44 // the reason is, we will only know the elecID from the position
45 // of the word in the stream. so these need to be strictly ordered.
46 // writing the right bar in the right position is easier if we can just
47 // read this map from beginning to end.
48 // barID can always be set, or looked up, as a property of the digi.
49
50 // here make the elecID the key (other way around when encoding)
51 channelMap_.insert(std::pair<int, int>(elID, chID));
52 ldmx_log(debug) << elID << " chID " << chID;
53 }
54 channelMapFile_.close();
55 if (elID != nChannels_ - 1)
56 ldmx_log(fatal) << "The set number of channels " << nChannels_
57 << " seems not to match the number from the map (+1) :"
58 << elID;
59 return;
60}
T getParameter(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:89
std::string channelMapFileName_
the channel mapping
Definition QIEDecoder.h:40

References channelMapFileName_, and framework::config::Parameters::getParameter().

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

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

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

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

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

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

◆ channelMap_

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

Definition at line 42 of file QIEDecoder.h.

◆ channelMapFile_

std::ifstream trigscint::QIEDecoder::channelMapFile_
private

Definition at line 41 of file QIEDecoder.h.

◆ channelMapFileName_

std::string trigscint::QIEDecoder::channelMapFileName_
private

the channel mapping

Definition at line 40 of file QIEDecoder.h.

Referenced by configure().

◆ inputCollection_

std::string trigscint::QIEDecoder::inputCollection_
private

Definition at line 45 of file QIEDecoder.h.

◆ inputPassName_

std::string trigscint::QIEDecoder::inputPassName_
private

Definition at line 47 of file QIEDecoder.h.

◆ isRealData_

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

Definition at line 58 of file QIEDecoder.h.

58{false};

◆ nChannels_

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

Definition at line 54 of file QIEDecoder.h.

54{50};

◆ nSamples_

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

Definition at line 56 of file QIEDecoder.h.

56{5};

◆ outputCollection_

std::string trigscint::QIEDecoder::outputCollection_
private

Definition at line 46 of file QIEDecoder.h.

◆ verbose_

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

Definition at line 51 of file QIEDecoder.h.

51{false};

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