DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
emulate_from_tpstream.cxx File Reference
#include "trgtools/TCEmulationUnit.hpp"
#include "trgtools/TAEmulationWorker.hpp"
#include "CLI/App.hpp"
#include "CLI/Config.hpp"
#include "CLI/Formatter.hpp"
#include <fmt/core.h>
#include <fmt/format.h>
#include <fmt/chrono.h>
#include <filesystem>
#include <optional>
#include "hdf5libs/HDF5RawDataFile.hpp"
#include "hdf5libs/HDF5SourceIDHandler.hpp"
#include "triggeralgs/TriggerCandidateFactory.hpp"
Include dependency graph for emulate_from_tpstream.cxx:

Go to the source code of this file.

Classes

struct  Options
 Struct with available cli application options. More...

Functions

void save_fragments (const std::string &_outputfilename, const hdf5libs::HDF5SourceIDHandler::source_id_geo_id_map_t &_sourceid_geoid_map, std::map< uint64_t, std::vector< std::unique_ptr< daqdataformats::Fragment > > > _frags, bool _quiet)
 Saves fragments in timeslice format into output HDF5 file.
std::map< std::string, std::vector< std::shared_ptr< hdf5libs::HDF5RawDataFile > > > sort_files_per_writer (const std::vector< std::string > &_files)
 Group and order input TimeSlice files per TPStream writer application.
std::pair< uint64_t, uint64_t > get_available_slice_id_range (const std::map< std::string, std::vector< std::shared_ptr< hdf5libs::HDF5RawDataFile > > > &_files, bool _quiet)
 Compute the common SliceID interval shared by all writer groups.
void parse_app (CLI::App &_app, Options &_opts)
 Adds options to our CLI application.
int main (int argc, char const *argv[])

Function Documentation

◆ get_available_slice_id_range()

std::pair< uint64_t, uint64_t > get_available_slice_id_range ( const std::map< std::string, std::vector< std::shared_ptr< hdf5libs::HDF5RawDataFile > > > & _files,
bool _quiet )

Compute the common SliceID interval shared by all writer groups.

For each writer application, this function scans all of its files and finds the minimum and maximum available record IDs. It then computes the global intersection across applications:

  • global_start = max(all per-application starts)
  • global_end = min(all per-application ends)

The returned range is therefore the SliceID window for which data is expected to be available from every application.

Todo
: Rather than returning the SliceID range, should try to return a time range and have processors use that.
Parameters
_filesMap of writer application names to vectors of input HDF5 files.
_quietIf false, print per-application and global range diagnostics.
Returns
Inclusive pair {global_start, global_end} of overlapping SliceIDs.
Exceptions
std::runtime_errorIf _files is empty, if any file has no records, or if no overlapping SliceID interval exists.

Definition at line 168 of file emulate_from_tpstream.cxx.

◆ main()

int main ( int argc,
char const * argv[] )

Definition at line 282 of file emulate_from_tpstream.cxx.

◆ parse_app()

void parse_app ( CLI::App & _app,
Options & _opts )

Adds options to our CLI application.

Parameters
_appCLI application
_optsStruct with the available options

Definition at line 259 of file emulate_from_tpstream.cxx.

◆ save_fragments()

void save_fragments ( const std::string & _outputfilename,
const hdf5libs::HDF5SourceIDHandler::source_id_geo_id_map_t & _sourceid_geoid_map,
std::map< uint64_t, std::vector< std::unique_ptr< daqdataformats::Fragment > > > _frags,
bool _quiet )

Saves fragments in timeslice format into output HDF5 file.

Parameters
_outputfilenameName of the hdf5 file to save the output into
_sourceid_geoid_mapsourceid–geoid map required to create a HDF5 file
_fragsMap of fragments, with a vector of fragment pointers for each slice id
_quietDo we want to quiet down the cout?
Todo
Maybe in the future we will want to emulate PDS TPs.

Definition at line 32 of file emulate_from_tpstream.cxx.

50 params_trigger.detector_group_name = "TPC";
51 params_trigger.element_name_prefix = "Link";
52 params_trigger.digits_for_element_number = 5;
53
54 // Fill the HDF5 layout
55 std::vector<hdf5libs::HDF5PathParameters> params;
56 params.push_back(params_trigger);
57 layout_params.record_name_prefix = "TimeSlice";
58 layout_params.digits_for_record_number = 6;
59 layout_params.digits_for_sequence_number = 0;
60 layout_params.record_header_dataset_name = "TimeSliceHeader";
61 layout_params.raw_data_group_name = "RawData";
62 layout_params.view_group_name = "Views";
63 layout_params.path_params_list = {params};
64
65 // Create pointer to a new output HDF5 file
66 std::unique_ptr<hdf5libs::HDF5RawDataFile> output_file = std::make_unique<hdf5libs::HDF5RawDataFile>(
67 output_filename,
68 _frags.begin()->second[0]->get_run_number(),
69 0,
70 "emulate_from_tpstream",
71 layout_params,
72 _sourceid_geoid_map);
73
74 // Iterate over the time slices & save all the fragments
75 for (auto& [slice_id, vec_frags]: _frags) {
76 // Create a new timeslice header
77 daqdataformats::TimeSliceHeader tsh;
78 tsh.timeslice_number = slice_id;
79 tsh.run_number = vec_frags[0]->get_run_number();
81
82 // Create a new timeslice
84 if (!_quiet) {
85 std::cout << "Time slice number: " << slice_id << std::endl;
86 }
87 // Add the fragments to the timeslices
88 for (std::unique_ptr<daqdataformats::Fragment>& frag_ptr: vec_frags) {
89 if (!_quiet) {
90 std::cout << " Writing elementid: " << frag_ptr->get_element_id() << " trigger number: " << frag_ptr->get_trigger_number() << " trigger_timestamp: " << frag_ptr->get_trigger_timestamp() << " window_begin: " << frag_ptr->get_window_begin() << " sequence_no: " << frag_ptr->get_sequence_number() << std::endl;
91 }
92 ts.add_fragment(std::move(frag_ptr));
93 }
94
95 // Write the timeslice to output file
96 output_file->write(ts);
97 }
98}
C++ Representation of a DUNE TimeSlice, consisting of a TimeSliceHeader object and a vector of pointe...
Definition TimeSlice.hpp:27
SourceID is a generalized representation of the source of a piece of data in the DAQ....
Definition SourceID.hpp:32

◆ sort_files_per_writer()

std::map< std::string, std::vector< std::shared_ptr< hdf5libs::HDF5RawDataFile > > > sort_files_per_writer ( const std::vector< std::string > & _files)

Group and order input TimeSlice files per TPStream writer application.

Opens each input file, validates that it is of TimeSlice type, and groups files by their application_name attribute. Within each application group, files are sorted by their file_index attribute so consecutive segments from the same writer are processed in order.

Parameters
_filesVector of input HDF5 file paths.
Returns
Map keyed by application_name, each value a vector of file handles ordered by file_index.
Exceptions
std::runtime_errorIf any input file is not of type TimeSlice.

Definition at line 114 of file emulate_from_tpstream.cxx.

115{
116 std::map<std::string, std::vector<std::shared_ptr<hdf5libs::HDF5RawDataFile>>> files_sorted;
117
118 // Put files into per-writer app groups
119 for (const std::string& file : _files) {
120 std::shared_ptr<hdf5libs::HDF5RawDataFile> fl = std::make_shared<hdf5libs::HDF5RawDataFile>(file);
121 if (!fl->is_timeslice_type()) {
122 throw std::runtime_error(fmt::format("ERROR: input file '{}' not of type 'TimeSlice'", file));
123 }
124
125 std::string application_name = fl->get_attribute<std::string>("application_name");
126 files_sorted[application_name].push_back(fl);
127 }
128
129 // Sort files for each writer application individually
130 for (auto& [app_name, vec_files]: files_sorted) {
131 // Don't sort if we have 0 or 1 files in the application...
132 if (vec_files.size() <= 1) {
133 continue;
134 }
135
136 // Sort w.r.t. file index attribute
137 std::sort(vec_files.begin(), vec_files.end(),
138 [](const std::shared_ptr<hdf5libs::HDF5RawDataFile>& a, const std::shared_ptr<hdf5libs::HDF5RawDataFile>& b) {
139 return a->get_attribute<size_t>("file_index") <
140 b->get_attribute<size_t>("file_index");
141 });
142 }
143
144 return files_sorted;
145};