LDMX Software
FiberTrackerRawDecoder.cxx
1
2#include <bitset>
3#include <iomanip>
4#include <optional>
5
7#include "Packing/Utility/Mask.h"
8#include "Packing/Utility/Reader.h"
9
10// un comment for FiberTrackerRawDecoder-specific debug printouts to std::cout
11// #define DEBUG
12
13namespace packing {
14
18double toDoubleFt(uint64_t i) {
19 static const unsigned int bits = 32;
20 static const unsigned int expbits = 8;
21 long double result;
22 long long shift;
23 unsigned bias;
24 unsigned significandbits = bits - expbits - 1; // -1 for sign bit
25
26 if (i == 0) return 0.0;
27
28 // pull the significand
29 result = (i & ((1LL << significandbits) - 1)); // mask
30 result /= (1LL << significandbits); // convert back to float
31 result += 1.0f; // add the one back on
32
33 // deal with the exponent
34 bias = (1 << (expbits - 1)) - 1;
35 shift = ((i >> significandbits) & ((1LL << expbits) - 1)) - bias;
36 while (shift > 0) {
37 result *= 2.0;
38 shift--;
39 }
40 while (shift < 0) {
41 result /= 2.0;
42 shift++;
43 }
44
45 // sign it
46 result *= (i >> (bits - 1)) & 1 ? -1.0 : 1.0;
47
48 return result;
49}
50
55 uint32_t field_header_;
56 std::vector<uint32_t> field_value_;
57
58 public:
64 uint32_t len;
65 r >> len >> field_header_;
66 r.read(field_value_, len - 1);
67 if (i_field != field_header_) {
68 EXCEPTION_RAISE("BadForm", "Field " + std::to_string(i_field) +
69 " has a mismatched header " +
70 std::to_string(field_header_));
71 }
72 }
73
77 int toInt(const std::size_t i = 0) const { return field_value_.at(i); }
78
82 std::string toString() const {
83 std::string str;
84 str.resize(field_value_.size());
85 for (int i{0}; i < str.size(); i++) {
86 str[i] = (char)field_value_[i];
87 }
88 return str;
89 }
90
96 long int toLong(const std::size_t i = 0) const {
97 return ((uint64_t)field_value_.at(i + 1) << 32) |
98 (uint64_t)field_value_.at(i);
99 }
100
104 double toDouble(const std::size_t i = 0) const {
105 return toDoubleFt(this->toLong(i));
106 }
107
111 const std::vector<uint32_t>& value() const { return field_value_; }
112};
113
136 int trigger_timestamp_lsb_, trigger_timestamp_msb_, event_timestamp_lsb_,
137 event_timestamp_msb_;
138 std::vector<uint32_t> channel_hits_;
139
140 FiberTrackerEvent() = default;
141
142 FiberTrackerEvent(const std::vector<uint32_t>& spill_data,
143 std::size_t i_word) {
144 trigger_timestamp_lsb_ = spill_data.at(i_word);
145 trigger_timestamp_msb_ = spill_data.at(i_word + 1);
146 event_timestamp_lsb_ = spill_data.at(i_word + 2);
147 event_timestamp_msb_ = spill_data.at(i_word + 3);
148 channel_hits_.clear();
149 channel_hits_.reserve(6);
150 for (std::size_t i{i_word + 4}; i < i_word + 10 and i < spill_data.size();
151 i++)
152 channel_hits_.push_back(spill_data.at(i));
153 }
154};
155
160 int acq_mode_;
161 long int acq_stamp_;
162 int acq_type_;
163 int acq_type_allowed_;
164 std::string coincidence_in_use_;
165 int counts_;
166 long int counts_records_;
167 long int counts_records_with_zero_events_;
168 long int counts_trigs_;
169 std::string cycle_name_;
170 long int cycle_stamp_;
171 std::string equipment_name_;
172 int event_selection_acq_;
176 std::vector<FiberTrackerEvent> events_data_;
178 int i_event_{0};
179
180 double mean_s_new_;
181 std::string message_;
182 std::vector<double> profile_;
183 std::vector<double> profile_stand_alone_;
184 std::string time_first_event_;
185 std::string time_first_trigger_;
186 std::string time_last_event_;
187 std::string time_last_trigger_;
188 int trigger_;
189 int trigger_offset_acq_;
190 int trigger_selection_acq_;
191
192 bool next(FiberTrackerEvent& e) {
193 i_event_++;
194 if (i_event_ < events_data_.size()) {
195 e = events_data_.at(i_event_);
196 return true;
197 }
198 return false;
199 }
200
205 int i_field{0};
206 acq_mode_ = FiberTrackerField(r, ++i_field).toInt();
207#ifdef DEBUG
208 std::cout << i_field << " " << "acqMode = " << acqMode << std::endl;
209#endif
210 acq_stamp_ = FiberTrackerField(r, ++i_field).toLong();
211#ifdef DEBUG
212 std::cout << i_field << " " << "acqStamp = " << acqStamp << std::endl;
213#endif
214 acq_type_ = FiberTrackerField(r, ++i_field).toInt();
215#ifdef DEBUG
216 std::cout << i_field << " " << "acqType = " << acqType << std::endl;
217#endif
218 acq_type_allowed_ = FiberTrackerField(r, ++i_field).toInt();
219#ifdef DEBUG
220 std::cout << i_field << " " << "acqTypeAllowed = " << acqTypeAllowed
221 << std::endl;
222#endif
223 coincidence_in_use_ = FiberTrackerField(r, ++i_field).toString();
224#ifdef DEBUG
225 std::cout << i_field << " " << "coincidenceInUse = " << coincidenceInUse
226 << std::endl;
227#endif
228 counts_ = FiberTrackerField(r, ++i_field).toInt();
229#ifdef DEBUG
230 std::cout << i_field << " " << "counts = " << counts << std::endl;
231#endif
232 counts_records_ = FiberTrackerField(r, ++i_field).toLong();
233#ifdef DEBUG
234 std::cout << i_field << " " << "countsRecords = " << countsRecords
235 << std::endl;
236#endif
237 counts_records_with_zero_events_ = FiberTrackerField(r, ++i_field).toLong();
238#ifdef DEBUG
239 std::cout << i_field << " "
240 << "countsRecordsWithZeroEvents = " << countsRecordsWithZeroEvents
241 << std::endl;
242#endif
243 counts_trigs_ = FiberTrackerField(r, ++i_field).toLong();
244#ifdef DEBUG
245 std::cout << i_field << " " << "countsTrigs = " << countsTrigs << std::endl;
246#endif
247 cycle_name_ = FiberTrackerField(r, ++i_field).toString();
248#ifdef DEBUG
249 std::cout << i_field << " " << "cycleName = " << cycleName << std::endl;
250#endif
251 cycle_stamp_ = FiberTrackerField(r, ++i_field).toLong();
252#ifdef DEBUG
253 std::cout << i_field << " " << "cycleStamp = " << cycleStamp << std::endl;
254#endif
255 equipment_name_ = FiberTrackerField(r, ++i_field).toString();
256#ifdef DEBUG
257 std::cout << i_field << " " << "equipmentName = " << equipmentName
258 << std::endl;
259#endif
260 event_selection_acq_ = FiberTrackerField(r, ++i_field).toInt();
261#ifdef DEBUG
262 std::cout << i_field << " " << "eventSelectionAcq = " << eventSelectionAcq
263 << std::endl;
264#endif
265 FiberTrackerField events_data_field(r, ++i_field);
266 i_event_ = -1;
267 events_data_.clear();
268 events_data_.reserve(events_data_field.value().size() / 10);
269 for (std::size_t i_word{0}; i_word < events_data_field.value().size();
270 i_word += 10) {
271 events_data_.emplace_back(events_data_field.value(), i_word);
272 }
273#ifdef DEBUG
274 std::cout << i_field << " " << "eventsData (size = " << eventsData.size()
275 << ")" << std::endl;
276#endif
277 mean_s_new_ = FiberTrackerField(r, ++i_field).toDouble();
278#ifdef DEBUG
279 std::cout << i_field << " " << "meanSNew = " << meanSNew << std::endl;
280#endif
281 message_ = FiberTrackerField(r, ++i_field).toString();
282#ifdef DEBUG
283 std::cout << i_field << " " << "message = " << message << std::endl;
284#endif
285 FiberTrackerField profile_field(r, ++i_field);
286 profile_.clear();
287 profile_.reserve(profile_field.value().size() / 2);
288 for (std::size_t i_word{0}; i_word < profile_field.value().size();
289 i_word += 2) {
290 profile_.push_back(profile_field.toDouble(i_word));
291 }
292#ifdef DEBUG
293 std::cout << i_field << " " << "profile size " << profile.size()
294 << std::endl;
295#endif
296 // fields 18 and 19 are skipped
297 i_field += 2;
298 FiberTrackerField profile_stand_alone_field(r, ++i_field);
299 profile_stand_alone_.clear();
300 profile_stand_alone_.reserve(profile_stand_alone_field.value().size() / 2);
301 for (std::size_t i_word{0};
302 i_word < profile_stand_alone_field.value().size(); i_word += 2) {
303 profile_stand_alone_.push_back(
304 profile_stand_alone_field.toDouble(i_word));
305 }
306#ifdef DEBUG
307 std::cout << i_field << " " << "profileStandAlone size "
308 << profileStandAlone.size() << std::endl;
309#endif
310 time_first_event_ = FiberTrackerField(r, ++i_field).toString();
311#ifdef DEBUG
312 std::cout << i_field << " " << "timeFirstEvent = " << timeFirstEvent
313 << std::endl;
314#endif
315 time_first_trigger_ = FiberTrackerField(r, ++i_field).toString();
316#ifdef DEBUG
317 std::cout << i_field << " " << "timeFirstTrigger = " << timeFirstTrigger
318 << std::endl;
319#endif
320 time_last_event_ = FiberTrackerField(r, ++i_field).toString();
321#ifdef DEBUG
322 std::cout << i_field << " " << "timeLastEvent = " << timeLastEvent
323 << std::endl;
324#endif
325 time_last_trigger_ = FiberTrackerField(r, ++i_field).toString();
326#ifdef DEBUG
327 std::cout << i_field << " " << "timeLastTrigger = " << timeLastTrigger
328 << std::endl;
329#endif
330 trigger_ = FiberTrackerField(r, ++i_field).toInt();
331#ifdef DEBUG
332 std::cout << i_field << " " << "trigger = " << trigger << std::endl;
333#endif
334 trigger_offset_acq_ = FiberTrackerField(r, ++i_field).toInt();
335#ifdef DEBUG
336 std::cout << i_field << " " << "triggerOffsetAcq = " << triggerOffsetAcq
337 << std::endl;
338#endif
339 trigger_selection_acq_ = FiberTrackerField(r, ++i_field).toInt();
340#ifdef DEBUG
341 std::cout << i_field << " "
342 << "triggerSelectionAcq = " << triggerSelectionAcq << std::endl;
343#endif
344 return r;
345 }
346};
347
348std::ostream& operator<<(std::ostream& os, const FiberTrackerBinaryPacket& p) {
349 return (os << "FiberTracker Packet {" << p.acq_stamp_ << "}");
350}
351
356 public:
357 FiberTrackerRawDecoder(const std::string& name, framework::Process& process)
358 : framework::Producer(name, process) {}
359 virtual ~FiberTrackerRawDecoder() = default;
360 virtual void configure(framework::config::Parameters&) final override;
361 virtual void onProcessStart() final override;
362 virtual void produce(framework::Event& event) final override;
363
364 private:
366 std::string input_file_;
368 std::string output_name_;
371
372 private:
380 TTree *tree_, *spill_tree_;
381};
382
384 input_file_ = ps.get<std::string>("input_file");
385 output_name_ = ps.get<std::string>("output_name");
386 ntuplize_ = ps.get<bool>("ntuplize");
387
389}
390
392 if (ntuplize_) {
394 tree_ = new TTree("raw", "Flattened and decoded raw FiberTracker data");
395 tree_->Branch("TriggerTSLSB", &ft_event_.trigger_timestamp_lsb_);
396 tree_->Branch("TriggerTSMSB", &ft_event_.trigger_timestamp_msb_);
397 tree_->Branch("EventTSLSB", &ft_event_.event_timestamp_lsb_);
398 tree_->Branch("EventTSMSB", &ft_event_.event_timestamp_msb_);
399 tree_->Branch("ChannelHits", &ft_event_.channel_hits_);
400
401 spill_tree_ = new TTree("spill", "Spill Meta-Data from FiberTrackerDAQ");
402 spill_tree_->Branch("acqMode", &spill_packet_.acq_mode_);
403 spill_tree_->Branch("acqStamp", &spill_packet_.acq_stamp_);
404 spill_tree_->Branch("acqType", &spill_packet_.acq_type_);
405 spill_tree_->Branch("acqTypeAllowed", &spill_packet_.acq_type_allowed_);
406 spill_tree_->Branch("counts", &spill_packet_.counts_);
407 spill_tree_->Branch("countsRecords", &spill_packet_.counts_records_);
408 spill_tree_->Branch("countsRecordsWithZeroEvents",
409 &spill_packet_.counts_records_with_zero_events_);
410 spill_tree_->Branch("countsTrigs", &spill_packet_.counts_trigs_);
411 spill_tree_->Branch("cycleStamp", &spill_packet_.cycle_stamp_);
412 spill_tree_->Branch("eventSelectionAcq",
413 &spill_packet_.event_selection_acq_);
414 spill_tree_->Branch("meanSNew", &spill_packet_.mean_s_new_);
415 spill_tree_->Branch("profile", &spill_packet_.profile_);
416 spill_tree_->Branch("profileStandAlone",
417 &spill_packet_.profile_stand_alone_);
418 spill_tree_->Branch("trigger", &spill_packet_.trigger_);
419 spill_tree_->Branch("triggerOffsetAcq", &spill_packet_.trigger_offset_acq_);
420 spill_tree_->Branch("triggerSelectionAcq",
421 &spill_packet_.trigger_selection_acq_);
422 }
423}
424
426 // only add and fill when file able to readout packet
427 if (not spill_packet_.next(ft_event_)) {
428 // no more events in this spill
430 spill_tree_->Fill();
431 // next spill loaded, pop its first event
433 } else {
434#ifdef DEBUG
435 std::cout << "no more events" << std::endl;
436#endif
437 return;
438 }
439 }
440 tree_->Fill();
441
442 event.add(output_name_ + "TriggerTSLSB", ft_event_.trigger_timestamp_lsb_);
443 event.add(output_name_ + "TriggerTSMSB", ft_event_.trigger_timestamp_msb_);
444 event.add(output_name_ + "EventTSLSB", ft_event_.event_timestamp_lsb_);
445 event.add(output_name_ + "EventTSMSB", ft_event_.event_timestamp_msb_);
446 event.add(output_name_ + "Hits", ft_event_.channel_hits_);
447 return;
448} // produce
449
450} // namespace packing
451
Base classes for all user event processing components to extend.
#define DECLARE_PRODUCER(CLASS)
Macro which allows the framework to construct a producer given its name during configuration.
TDirectory * getHistoDirectory()
Access/create a directory in the histogram file for this event processor to create histograms and ana...
Implements an event buffer system for storing event data.
Definition Event.h:42
Class which represents the process under execution.
Definition Process.h:36
Base class for a module which produces a data product.
virtual void process(Event &event) final
Processing an event for a Producer is calling produce.
Class encapsulating parameters for configuring a processor.
Definition Parameters.h:29
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:78
Each "field" of data in a FiberTracker packet.
const std::vector< uint32_t > & value() const
Get the field value.
long int toLong(const std::size_t i=0) const
long split across two ints
int toInt(const std::size_t i=0) const
conversion to a single int
double toDouble(const std::size_t i=0) const
convert two ints into a double
std::string toString() const
conversion from series of ints to string specific to FiberTrackerDAQ
FiberTrackerField(utility::Reader &r, int i_field)
r - reader i_field - field we are supposed to be reading from
std::string output_name_
output object to put onto event bus
virtual void produce(framework::Event &event) final override
Process the event and put new data products into it.
virtual void configure(framework::config::Parameters &) final override
Callback for the EventProcessor to configure itself from the given set of parameters.
FiberTrackerEvent ft_event_
Current Event.
FiberTrackerBinaryPacket spill_packet_
packet being used for decoding
virtual void onProcessStart() final override
Callback for the EventProcessor to take any necessary action when the processing of events starts,...
packing::utility::Reader file_reader_
the file reader (if we are doing that)
Reading a raw data file.
Definition Reader.h:19
void open(const std::string &file_name)
Open a file with this reader.
Definition Reader.h:35
Reader & read(WordType *w, std::size_t count)
Read the next 'count' words into the input handle.
Definition Reader.h:113
Each one of these packets represents an entire spill of data.
std::vector< FiberTrackerEvent > events_data_
This is the actual event data in which we are interested.
int i_event_
index_ of event we are on (for next)
utility::Reader & read(utility::Reader &r)
27 fields in order, all are present
A spill of events from a FiberTracker station.