LDMX Software
eventbuilder::EventBuilder Class Reference

Public Member Functions

 EventBuilder (const std::string &name, framework::Process &proc)
 
 enableLogging ("EventBuilder") virtual ~EventBuilder()=default
 
void configure (framework::config::Parameters &ps) override
 Callback for the EventProcessor to configure itself from the given set of parameters.
 
void produce (framework::Event &event) override
 Process the event and put new data products into it.
 
- 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.
 
virtual void onProcessStart ()
 Callback for the EventProcessor to take any necessary action when the processing of events starts, such as creating histograms.
 
virtual void onProcessEnd ()
 Callback for the EventProcessor to take any necessary action when the processing of events finishes, such as calculating job-summary quantities.
 
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 Member Functions

PhysicsEventData assemble_payload (const std::vector< DataFragment > &fragments)
 
void write_event_binary (const PhysicsEventData &ev, const std::string &path="events.bin")
 

Private Attributes

bool m_verbose_parse
 
unsigned int m_event_id
 
FragmentBuffer m_event_buffer
 
std::string m_input_file
 
packing::utility::Reader m_reader
 
std::string m_output_name {"BuilderOutput"}
 
long long m_coherence_window_ns {5000000}
 
int m_min_subsystems {2}
 
std::chrono::steady_clock::time_point m_start_time
 
std::chrono::steady_clock::time_point m_event_start_time
 
uint64_t m_total_bytes_read {0}
 
uint64_t m_total_events_built {0}
 
unsigned long m_events_since_last_report {0}
 
std::chrono::steady_clock::time_point m_window_start_time
 
uint64_t m_window_events_count {0}
 
uint64_t m_window_bytes_read {0}
 

Static Private Attributes

static constexpr unsigned int WINDOW_SIZE = 100
 

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 13 of file EventBuilder.h.

Constructor & Destructor Documentation

◆ EventBuilder()

eventbuilder::EventBuilder::EventBuilder ( const std::string & name,
framework::Process & proc )
inline

Definition at line 16 of file EventBuilder.h.

17 : framework::Producer(name, proc), m_verbose_parse(false), m_event_id(0) {}
Base class for a module which produces a data product.

Member Function Documentation

◆ assemble_payload()

PhysicsEventData EventBuilder::assemble_payload ( const std::vector< DataFragment > & fragments)
private

Definition at line 439 of file EventBuilder.cxx.

439 {
440 PhysicsEventData event_data;
441 if (fragments.empty()) return event_data;
442 event_data.event_id = m_event_id;
443 event_data.timestamp = fragments.front().header.timestamp;
444 for (const auto &fragment : fragments) {
446 g.subsystem_id = fragment.header.subsystem_id;
447 g.timestamp_ns = fragment.header.timestamp;
448 g.data = fragment.payload;
449 if (fragment.trailer.checksum != 0) g.checksum = fragment.trailer.checksum;
450 else g.checksum = crc32(fragment.payload);
451 event_data.blocks.push_back(std::move(g));
452 event_data.systems_readout.push_back(fragment.header.subsystem_id);
453 }
454 return event_data;
455}

◆ configure()

void EventBuilder::configure ( framework::config::Parameters & parameters)
overridevirtual

Callback for the EventProcessor to configure itself from the given set of parameters.

The parameters a processor has access to are the member variables of the python class in the sequence that has class_name equal to the EventProcessor class name.

For an example, look at MyProcessor.

Parameters
parametersParameters for configuration.

Reimplemented from framework::EventProcessor.

Definition at line 61 of file EventBuilder.cxx.

61 {
62 if (ps.exists("verbose_parse")) {
63 m_verbose_parse = ps.get<bool>("verbose_parse");
64 }
65 if (ps.exists("dat_file")) {
66 m_input_file = ps.get<std::string>("dat_file");
67 } else {
68 const char* env_input = std::getenv("EVENTBUILDER_INPUT");
69 if (env_input) m_input_file = env_input;
70 }
71 if (ps.exists("output_name")) m_output_name = ps.get<std::string>("output_name");
72 if (ps.exists("coherence_window_ns")) {
73 m_coherence_window_ns = ps.get<double>("coherence_window_ns");
74 }
75 if (ps.exists("min_subsystems")) {
76 m_min_subsystems = ps.get<int>("min_subsystems");
77 }
78
79 ldmx_log(info) << "configure(): dat_file='" << m_input_file << "' output_name='" << m_output_name
80 << "' verbose_parse=" << (m_verbose_parse?"true":"false")
81 << " coherence_window_ns=" << m_coherence_window_ns
82 << " min_subsystems=" << m_min_subsystems;
83
84 if (!m_input_file.empty()) {
85 ldmx_log(info) << "configure(): opening file '" << m_input_file << "'";
86 m_reader.open(m_input_file);
87 if (!m_reader) {
88 ldmx_log(error) << "failed to open input file: '" << m_input_file << "'";
89 } else {
90 ldmx_log(info) << "configure(): file opened successfully";
91 }
92 } else {
93 ldmx_log(error) << "no input file specified";
94 }
95
96 // Initialize performance tracking
97 m_start_time = std::chrono::steady_clock::now();
98 m_total_bytes_read = 0;
99 m_total_events_built = 0;
100 m_events_since_last_report = 0;
101
102 // Initialize windowed metrics for real-time DAQ monitoring
103 m_window_start_time = m_start_time;
104 m_window_events_count = 0;
105 m_window_bytes_read = 0;
106}
void open(const std::string &file_name)
Open a file with this reader.
Definition Reader.h:36

References framework::config::Parameters::exists(), framework::config::Parameters::get(), and packing::utility::Reader::open().

◆ produce()

void EventBuilder::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 108 of file EventBuilder.cxx.

108 {
109 static int produce_call_count = 0;
110 produce_call_count++;
111 ldmx_log(debug) << "produce() called, count=" << produce_call_count;
112 ldmx_log(debug) << "verbose_parse=" << (m_verbose_parse ? "true" : "false");
113 if (m_verbose_parse || produce_call_count <= 3) {
114 ldmx_log(info) << "produce() call #" << produce_call_count;
115 }
116
117 // Start timing for this event
118 m_event_start_time = std::chrono::steady_clock::now();
119
120 // Track errors encountered during event assembly
121 uint32_t current_event_errors = 0;
122
123 while (m_reader && !m_reader.eof()) {
124 // Try to read a RogueFrameHeader
125 packing::RogueFrameHeader frame_header;
126 frame_header.read(m_reader);
127
128 // Store location of end-of-frame for potential recovery
129 const long long frame_end =
130 static_cast<long long>(m_reader.tell()) + frame_header.size();
131
132 // Check if this is a data frame (channel 0) and not YAML
133 if (frame_header.channel() != 0 || frame_header.probablyYaml()) {
134 // Skip this frame
135 if (m_verbose_parse) ldmx_log(debug) << "skipping non-data frame (channel=" << frame_header.channel() << ")";
136 m_reader.seek(frame_end);
137 continue;
138 }
139
140 // We have a valid data frame - try to parse it
141 DataFragment fragment{{}, {}, {.checksum = 0}};
142 bool parsed_ok = false;
143
144 // Try RoR format first
145 packing::LDMXRoRHeader ror_header;
146 int pos_before_ror = m_reader.tell();
147
148 // Attempt to read as RoR header
149 try {
150 ror_header.read(m_reader);
151 // Successfully parsed RoR header
152 fragment.header.subsystem_id = static_cast<uint64_t>(ror_header.subsystem());
153 fragment.header.contributor_id = static_cast<uint64_t>(ror_header.contributor());
154 fragment.header.timestamp = ror_header.timestamp();
155
156 if (m_verbose_parse) {
157 ldmx_log(debug) << "parsed RoR header subsys=" << (int)ror_header.subsystem()
158 << " contrib=" << (int)ror_header.contributor()
159 << " ts=" << ror_header.timestamp();
160 }
161
162 // Read remaining frame payload after RoR header
163 std::vector<uint8_t> payload_data;
164 long long payload_size = frame_end - m_reader.tell();
165 if (payload_size > 0) {
166 payload_data.resize(payload_size);
167 m_reader.read(reinterpret_cast<char*>(payload_data.data()), payload_size);
168 }
169 fragment.payload = std::move(payload_data);
170 parsed_ok = true;
171 } catch (...) {
172 // RoR parse failed, try packing subsystem format
173 if (m_verbose_parse) ldmx_log(debug) << "RoR header parse failed, trying packing subsystem format";
174 current_event_errors |= ldmx::EventSummary::ERROR_PARSE_FAILURE;
175 m_reader.seek(pos_before_ror);
176 }
177
178 if (!parsed_ok) {
179 // Try packing subsystem format
181 try {
182 pkt.read(m_reader);
183 fragment.header.subsystem_id = static_cast<uint64_t>(pkt.id());
184 fragment.header.contributor_id = 0; // Not available in packing subsystem format
185 fragment.header.timestamp = static_cast<uint64_t>(pkt.header()[1]) * 1000000000ULL; // event number to ns
186
187 // Convert packet data to payload bytes
188 const auto& data = pkt.data();
189 fragment.payload.resize(data.size() * 4);
190 std::memcpy(fragment.payload.data(), reinterpret_cast<const char*>(data.data()), data.size() * 4);
191
192 if (m_verbose_parse) {
193 ldmx_log(debug) << "parsed packing subsystem pkt subsys=" << pkt.id()
194 << " data_size=" << data.size();
195 }
196 parsed_ok = true;
197 } catch (...) {
198 // Both parse attempts failed, skip this frame
199 if (m_verbose_parse) ldmx_log(debug) << "failed to parse as either format, skipping frame";
200 current_event_errors |= ldmx::EventSummary::ERROR_PARSE_FAILURE;
201 m_reader.seek(frame_end);
202 continue;
203 }
204 }
205
206 if (!parsed_ok) {
207 m_reader.seek(frame_end);
208 continue;
209 }
210
211 if (m_verbose_parse) ldmx_log(debug) << "adding fragment subsys=" << fragment.header.subsystem_id
212 << " ts=" << fragment.header.timestamp << " bytes=" << fragment.payload.size();
213
214 // Check if this fragment is outside the coherence window of the current event batch
215 // If so, it means we should finalize the previous event before adding this one
216 long long fragment_ts = fragment.header.timestamp;
217 long long buffer_ref_time = m_event_buffer.get_reference_time();
218
219 if (buffer_ref_time > 0 && (fragment_ts < buffer_ref_time - m_coherence_window_ns ||
220 fragment_ts > buffer_ref_time + m_coherence_window_ns)) {
221 // This fragment is outside the current window - try to build the previous event
222 std::vector<DataFragment> assembled_event_fragments;
223 if (m_event_buffer.try_build_event(m_coherence_window_ns, m_min_subsystems, assembled_event_fragments) &&
224 !assembled_event_fragments.empty()) {
225 // Output the complete event and return
226 ++m_event_id;
227 // Add each subsystem's raw data as vector<uint8_t> directly
228 uint64_t event_timestamp = 0;
229 for (const auto &frag : assembled_event_fragments) {
230 std::string subsys_name = packing::LDMXRoRHeader::getSubsystemName(
231 static_cast<uint8_t>(frag.header.subsystem_id),
232 static_cast<uint8_t>(frag.header.contributor_id));
233 std::vector<uint8_t> payload_bytes(frag.payload.begin(), frag.payload.end());
234 event.add(subsys_name, payload_bytes);
235 if (event_timestamp == 0) {
236 event_timestamp = frag.header.timestamp;
237 }
238 }
239 event.getEventHeader().setIntParameter("RoR Timestamp", static_cast<long long>(event_timestamp));
240 // Still create PhysicsEventData for binary output file
241 PhysicsEventData final_event = assemble_payload(assembled_event_fragments);
242 write_event_binary(final_event, "events.bin");
243 ldmx_log(info) << "assembled event id=" << m_event_id << " timestamp=" << final_event.timestamp
244 << " fragments=" << assembled_event_fragments.size() << " systems=" << final_event.systems_readout.size();
245
246 ldmx::EventSummary summary;
247 summary.setEventNumber(m_event_id);
248 summary.setTimestampNs(static_cast<uint64_t>(final_event.timestamp));
249 std::set<uint64_t> unique_sys;
250 uint64_t total_payload = 0;
251 for (const auto &f : assembled_event_fragments) {
252 unique_sys.insert(f.header.subsystem_id);
253 total_payload += f.payload.size();
254 }
255 // Check for duplicate subsystems
256 if (unique_sys.size() != assembled_event_fragments.size()) {
257 current_event_errors |= ldmx::EventSummary::ERROR_DUPLICATE_SUBSYSTEM;
258 }
259 summary.setNSystems(static_cast<uint32_t>(unique_sys.size()));
260 summary.setSystemIds(std::vector<uint64_t>(unique_sys.begin(), unique_sys.end()));
261 summary.setPayloadSize(total_payload);
262 summary.setErrorFlags(current_event_errors);
263 event.add("EventSummary", summary);
264
265 // Update performance metrics
266 m_total_bytes_read += total_payload;
267 m_total_events_built++;
268 m_events_since_last_report++;
269 std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
270 std::chrono::milliseconds event_build_time_ms = std::chrono::duration_cast<std::chrono::milliseconds>(now - m_event_start_time);
271 std::chrono::seconds total_elapsed_s = std::chrono::duration_cast<std::chrono::seconds>(now - m_start_time);
272
273 double events_per_sec = (total_elapsed_s.count() > 0) ? static_cast<double>(m_total_events_built) / total_elapsed_s.count() : 0.0;
274 double mb_per_sec = (total_elapsed_s.count() > 0) ? static_cast<double>(m_total_bytes_read) / (1024.0 * 1024.0) / total_elapsed_s.count() : 0.0;
275
276 // Update windowed metrics
277 m_window_events_count++;
278 m_window_bytes_read += total_payload;
279 std::chrono::seconds window_elapsed_s = std::chrono::duration_cast<std::chrono::seconds>(now - m_window_start_time);
280
281 // Reset window if we've processed WINDOW_SIZE events
282 double window_events_per_sec = 0.0;
283 double window_mb_per_sec = 0.0;
284 if (m_window_events_count >= WINDOW_SIZE) {
285 double window_time_sec = std::max(1.0, static_cast<double>(window_elapsed_s.count()));
286 window_events_per_sec = static_cast<double>(m_window_events_count) / window_time_sec;
287 window_mb_per_sec = static_cast<double>(m_window_bytes_read) / (1024.0 * 1024.0) / window_time_sec;
288
289 // Reset window
290 m_window_start_time = now;
291 m_window_events_count = 0;
292 m_window_bytes_read = 0;
293 }
294
295 // Write performance metrics to CSV
296 long long event_build_time_ms_val = event_build_time_ms.count();
297 write_performance_metric(m_event_id, static_cast<double>(event_build_time_ms_val),
298 events_per_sec, mb_per_sec,
299 window_events_per_sec, window_mb_per_sec,
300 m_total_events_built, m_total_bytes_read);
301
302 if (m_verbose_parse || m_events_since_last_report % 100 == 0) {
303 ldmx_log(info) << "Performance: "
304 << "total_events=" << m_total_events_built << ", "
305 << "events_per_sec=" << std::fixed << std::setprecision(2) << events_per_sec << ", "
306 << "mb_per_sec=" << std::fixed << std::setprecision(3) << mb_per_sec;
307 }
308
309 current_event_errors = 0; // Reset for next event
310 // The fragment that tripped the window-close belongs to the NEXT
311 // event, not the one we just emitted. Buffer it here (the buffer is
312 // empty post-build, so this also resets the reference time) instead
313 // of dropping it -- otherwise every event after the first loses its
314 // triggering subsystem.
315 m_event_buffer.add_fragment(std::move(fragment));
316 return; // Return the event to framework
317 }
318 }
319
320 // Add fragment to buffer (may start a new event batch if buffer was empty)
321 m_event_buffer.add_fragment(std::move(fragment));
322
323 if (m_verbose_parse) ldmx_log(debug) << "frame added to buffer, searching for more frames...";
324 }
325
326 // Reached EOF - flush any remaining events in the buffer
327 if (m_verbose_parse) ldmx_log(debug) << "reached EOF, flushing remaining events";
328
329 std::vector<DataFragment> assembled_event_fragments;
330 while (m_event_buffer.try_build_event(m_coherence_window_ns, m_min_subsystems, assembled_event_fragments)) {
331 if (assembled_event_fragments.empty()) break;
332
333 // Mark truncated events (those flushed at EOF)
334 current_event_errors |= ldmx::EventSummary::ERROR_TRUNCATED_EVENT;
335
336 ++m_event_id;
337 // Add each subsystem's raw data as vector<uint8_t> directly
338 uint64_t event_timestamp = 0;
339 for (const auto &frag : assembled_event_fragments) {
340 std::string subsys_name = packing::LDMXRoRHeader::getSubsystemName(
341 static_cast<uint8_t>(frag.header.subsystem_id),
342 static_cast<uint8_t>(frag.header.contributor_id));
343 std::vector<uint8_t> payload_bytes(frag.payload.begin(), frag.payload.end());
344 event.add(subsys_name, payload_bytes);
345 if (event_timestamp == 0) {
346 event_timestamp = frag.header.timestamp;
347 }
348 }
349 event.getEventHeader().setIntParameter("RoR Timestamp", static_cast<long long>(event_timestamp));
350 // Still create PhysicsEventData for binary output file
351 PhysicsEventData final_event = assemble_payload(assembled_event_fragments);
352 write_event_binary(final_event, "events.bin");
353 ldmx_log(info) << "assembled event id=" << m_event_id << " timestamp=" << final_event.timestamp
354 << " fragments=" << assembled_event_fragments.size() << " systems=" << final_event.systems_readout.size();
355
356 ldmx::EventSummary summary;
357 summary.setEventNumber(m_event_id);
358 summary.setTimestampNs(static_cast<uint64_t>(final_event.timestamp));
359 std::set<uint64_t> unique_sys;
360 uint64_t total_payload = 0;
361 for (const auto &f : assembled_event_fragments) {
362 unique_sys.insert(f.header.subsystem_id);
363 total_payload += f.payload.size();
364 }
365 // Check for duplicate subsystems
366 if (unique_sys.size() != assembled_event_fragments.size()) {
367 current_event_errors |= ldmx::EventSummary::ERROR_DUPLICATE_SUBSYSTEM;
368 }
369 summary.setNSystems(static_cast<uint32_t>(unique_sys.size()));
370 summary.setSystemIds(std::vector<uint64_t>(unique_sys.begin(), unique_sys.end()));
371 summary.setPayloadSize(total_payload);
372 summary.setErrorFlags(current_event_errors);
373 event.add("EventSummary", summary);
374
375 // Update performance metrics
376 m_total_bytes_read += total_payload;
377 m_total_events_built++;
378 m_events_since_last_report++;
379 std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
380 std::chrono::milliseconds event_build_time_ms = std::chrono::duration_cast<std::chrono::milliseconds>(now - m_event_start_time);
381 std::chrono::seconds total_elapsed_s = std::chrono::duration_cast<std::chrono::seconds>(now - m_start_time);
382
383 double events_per_sec = (total_elapsed_s.count() > 0) ? static_cast<double>(m_total_events_built) / total_elapsed_s.count() : 0.0;
384 double mb_per_sec = (total_elapsed_s.count() > 0) ? static_cast<double>(m_total_bytes_read) / (1024.0 * 1024.0) / total_elapsed_s.count() : 0.0;
385
386 // Update windowed metrics
387 m_window_events_count++;
388 m_window_bytes_read += total_payload;
389 std::chrono::seconds window_elapsed_s = std::chrono::duration_cast<std::chrono::seconds>(now - m_window_start_time);
390
391 // Calculate window metrics (for final event, may not have full window)
392 double window_events_per_sec = 0.0;
393 double window_mb_per_sec = 0.0;
394 if (m_window_events_count >= WINDOW_SIZE || window_elapsed_s.count() > 0) {
395 double window_time_sec = std::max(1.0, static_cast<double>(window_elapsed_s.count()));
396 window_events_per_sec = static_cast<double>(m_window_events_count) / window_time_sec;
397 window_mb_per_sec = static_cast<double>(m_window_bytes_read) / (1024.0 * 1024.0) / window_time_sec;
398 }
399
400 // Write performance metrics to CSV
401 long long event_build_time_ms_val = event_build_time_ms.count();
402 write_performance_metric(m_event_id, static_cast<double>(event_build_time_ms_val),
403 events_per_sec, mb_per_sec,
404 window_events_per_sec, window_mb_per_sec,
405 m_total_events_built, m_total_bytes_read);
406
407 if (m_verbose_parse || m_events_since_last_report % 100 == 0) {
408 ldmx_log(info) << "Performance: "
409 << "total_events=" << m_total_events_built << ", "
410 << "events_per_sec=" << std::fixed << std::setprecision(2) << events_per_sec << ", "
411 << "mb_per_sec=" << std::fixed << std::setprecision(3) << mb_per_sec;
412 }
413
414 current_event_errors = 0; // Reset for next event
415
416 assembled_event_fragments.clear();
417 return;
418 }
419
420 // No more events - print final summary statistics
421 std::chrono::steady_clock::time_point final_time = std::chrono::steady_clock::now();
422 std::chrono::seconds total_time_s = std::chrono::duration_cast<std::chrono::seconds>(final_time - m_start_time);
423 double final_events_per_sec = (total_time_s.count() > 0) ? static_cast<double>(m_total_events_built) / total_time_s.count() : 0.0;
424 double final_mb_per_sec = (total_time_s.count() > 0) ? static_cast<double>(m_total_bytes_read) / (1024.0 * 1024.0) / total_time_s.count() : 0.0;
425
426 ldmx_log(info) << "\n===== FINAL STATISTICS =====";
427 ldmx_log(info) << "Total events built: " << m_total_events_built;
428 ldmx_log(info) << "Total bytes read: " << m_total_bytes_read / (1024.0 * 1024.0) << " MB";
429 ldmx_log(info) << "Total time: " << total_time_s.count() << " seconds";
430 ldmx_log(info) << "Average throughput: "
431 << "events_per_sec=" << std::fixed << std::setprecision(2) << final_events_per_sec << ", "
432 << "mb_per_sec=" << std::fixed << std::setprecision(3) << final_mb_per_sec;
433 ldmx_log(info) << "=============================\n";
434 ldmx_log(info) << "Event building complete";
435
436 abortEvent();
437}
void abortEvent()
Abort the event immediately.
Provides summary information about an assembled event, including error flags for data quality assessm...
void setSystemIds(const std::vector< uint64_t > &ids)
Set the system IDs.
void setNSystems(uint32_t ns)
Set the number of systems in this event.
void setPayloadSize(uint64_t size)
Set the total payload size.
void setTimestampNs(uint64_t ts)
Set the timestamp in nanoseconds.
void setEventNumber(uint64_t num)
Set the event number.
void setErrorFlags(uint32_t flags)
Set the error flags.
@ ERROR_PARSE_FAILURE
Frame parsing error.
@ ERROR_DUPLICATE_SUBSYSTEM
Duplicate subsystem in single event.
@ ERROR_TRUNCATED_EVENT
Event was truncated (EOF reached)
the header that the LDMX DAQ Firmware block includes in the output data stream at the beginning of ea...
static std::tuple< int, int > subsystem(const std::string &name)
Get the (subsystem, contributor) pair for the input subsystem name.
uint8_t contributor() const
ID number for contributor within subsystem (configured into firmware)
static std::string getSubsystemName(uint8_t subsystem_id, uint8_t contributor_id)
Get the subsystem name from subsystem and contributor IDs.
uint64_t timestamp() const
get timestamp of this RoR
utility::Reader & read(utility::Reader &r)
read the next LDMX RoR header into memory
the header that the Rogue StreamWriter puts includes at the beginning of each frame.
unsigned int size() const
get the size of the frame not including this header
bool probablyYaml() const
check if this frame is probably a yaml dump
int channel() const
get the channel this data was written to
utility::Reader & read(utility::Reader &r)
read the next rogue frame header into memory
std::vector< uint32_t > & data()
Get data.
utility::Reader & read(utility::Reader &r)
read the subsystem packet from the input reader
std::vector< uint32_t > header() const
get the header words
std::streampos tell()
Tell us where the reader is.
Definition Reader.h:88
bool eof()
check if file is done
Definition Reader.h:217
void seek(std::streampos off, std::ios_base::seekdir dir=std::ios::beg)
Go ("seek") a specific position in the file.
Definition Reader.h:62
Reader & read(WordType *w, std::size_t count)
Read the next 'count' words into the input handle.
Definition Reader.h:114

References framework::EventProcessor::abortEvent(), packing::RogueFrameHeader::channel(), packing::LDMXRoRHeader::contributor(), packing::rawdatafile::SubsystemPacket::data(), packing::utility::Reader::eof(), ldmx::EventSummary::ERROR_DUPLICATE_SUBSYSTEM, ldmx::EventSummary::ERROR_PARSE_FAILURE, ldmx::EventSummary::ERROR_TRUNCATED_EVENT, packing::LDMXRoRHeader::getSubsystemName(), packing::rawdatafile::SubsystemPacket::header(), packing::RogueFrameHeader::probablyYaml(), packing::LDMXRoRHeader::read(), packing::rawdatafile::SubsystemPacket::read(), packing::RogueFrameHeader::read(), packing::utility::Reader::read(), packing::utility::Reader::seek(), ldmx::EventSummary::setErrorFlags(), ldmx::EventSummary::setEventNumber(), ldmx::EventSummary::setNSystems(), ldmx::EventSummary::setPayloadSize(), ldmx::EventSummary::setSystemIds(), ldmx::EventSummary::setTimestampNs(), packing::RogueFrameHeader::size(), packing::LDMXRoRHeader::subsystem(), packing::utility::Reader::tell(), and packing::LDMXRoRHeader::timestamp().

◆ write_event_binary()

void EventBuilder::write_event_binary ( const PhysicsEventData & ev,
const std::string & path = "events.bin" )
private

Definition at line 457 of file EventBuilder.cxx.

457 {
458 static std::mutex g_out_mutex;
459 std::lock_guard<std::mutex> lg(g_out_mutex);
460 std::ofstream ofs(path, std::ios::binary | std::ios::app);
461 if (!ofs) return;
462 uint64_t event_id_u = static_cast<uint64_t>(ev.event_id);
463 uint64_t ts = static_cast<uint64_t>(ev.timestamp);
464 uint32_t nblocks = static_cast<uint32_t>(ev.blocks.size());
465 ofs.write(reinterpret_cast<const char*>(&event_id_u), sizeof(event_id_u));
466 ofs.write(reinterpret_cast<const char*>(&ts), sizeof(ts));
467 ofs.write(reinterpret_cast<const char*>(&nblocks), sizeof(nblocks));
468 for (const auto &b : ev.blocks) {
469 uint64_t sid = b.subsystem_id;
470 uint64_t bts = b.timestamp_ns;
471 uint32_t psz = static_cast<uint32_t>(b.data.size());
472 uint32_t csum = b.checksum;
473 ofs.write(reinterpret_cast<const char*>(&sid), sizeof(sid));
474 ofs.write(reinterpret_cast<const char*>(&bts), sizeof(bts));
475 ofs.write(reinterpret_cast<const char*>(&psz), sizeof(psz));
476 ofs.write(reinterpret_cast<const char*>(&csum), sizeof(csum));
477 if (psz) ofs.write(reinterpret_cast<const char*>(b.data.data()), static_cast<std::streamsize>(psz));
478 }
479 ofs.flush();
480}

Member Data Documentation

◆ m_coherence_window_ns

long long eventbuilder::EventBuilder::m_coherence_window_ns {5000000}
private

Definition at line 38 of file EventBuilder.h.

38{5000000}; // 5 ms window for collecting fragments

◆ m_event_buffer

FragmentBuffer eventbuilder::EventBuilder::m_event_buffer
private

Definition at line 34 of file EventBuilder.h.

◆ m_event_id

unsigned int eventbuilder::EventBuilder::m_event_id
private

Definition at line 33 of file EventBuilder.h.

◆ m_event_start_time

std::chrono::steady_clock::time_point eventbuilder::EventBuilder::m_event_start_time
private

Definition at line 45 of file EventBuilder.h.

◆ m_events_since_last_report

unsigned long eventbuilder::EventBuilder::m_events_since_last_report {0}
private

Definition at line 48 of file EventBuilder.h.

48{0};

◆ m_input_file

std::string eventbuilder::EventBuilder::m_input_file
private

Definition at line 35 of file EventBuilder.h.

◆ m_min_subsystems

int eventbuilder::EventBuilder::m_min_subsystems {2}
private

Definition at line 41 of file EventBuilder.h.

41{2};

◆ m_output_name

std::string eventbuilder::EventBuilder::m_output_name {"BuilderOutput"}
private

Definition at line 37 of file EventBuilder.h.

37{"BuilderOutput"};

◆ m_reader

packing::utility::Reader eventbuilder::EventBuilder::m_reader
private

Definition at line 36 of file EventBuilder.h.

◆ m_start_time

std::chrono::steady_clock::time_point eventbuilder::EventBuilder::m_start_time
private

Definition at line 44 of file EventBuilder.h.

◆ m_total_bytes_read

uint64_t eventbuilder::EventBuilder::m_total_bytes_read {0}
private

Definition at line 46 of file EventBuilder.h.

46{0};

◆ m_total_events_built

uint64_t eventbuilder::EventBuilder::m_total_events_built {0}
private

Definition at line 47 of file EventBuilder.h.

47{0};

◆ m_verbose_parse

bool eventbuilder::EventBuilder::m_verbose_parse
private

Definition at line 32 of file EventBuilder.h.

◆ m_window_bytes_read

uint64_t eventbuilder::EventBuilder::m_window_bytes_read {0}
private

Definition at line 54 of file EventBuilder.h.

54{0};

◆ m_window_events_count

uint64_t eventbuilder::EventBuilder::m_window_events_count {0}
private

Definition at line 53 of file EventBuilder.h.

53{0};

◆ m_window_start_time

std::chrono::steady_clock::time_point eventbuilder::EventBuilder::m_window_start_time
private

Definition at line 52 of file EventBuilder.h.

◆ WINDOW_SIZE

unsigned int eventbuilder::EventBuilder::WINDOW_SIZE = 100
staticconstexprprivate

Definition at line 51 of file EventBuilder.h.


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