DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
tapipe.cxx
Go to the documentation of this file.
1
10
11#include "CLI/App.hpp"
12#include "CLI/Config.hpp"
13#include "CLI/Formatter.hpp"
14
15#include <fmt/core.h>
16#include <fmt/format.h>
17
22
23using namespace dunedaq;
24
26{
27private:
28 std::unique_ptr<hdf5libs::HDF5RawDataFile> m_file;
29
30public:
31 HDF5FileReader(const std::string& path);
33};
34
35HDF5FileReader::HDF5FileReader(const std::string& path)
36{
37 m_file = std::make_unique<hdf5libs::HDF5RawDataFile>(path);
38}
39
41//-----
42
43template<>
44struct fmt::formatter<dunedaq::daqdataformats::SourceID>
45{
46 // Presentation format: 'f' - fixed, 'e' - exponential.
47 // char presentation = 'f';
48
49 // // Parses format specifications of the form ['f' | 'e'].
50 // constexpr auto parse(format_parse_context& ctx) -> format_parse_context::iterator {
51 // // [ctx.begin(), ctx.end()) is a character range that contains a part of
52 // // the format string starting from the format specifications to be parsed,
53 // // e.g. in
54 // //
55 // // fmt::format("{:f} - point of interest", point{1, 2});
56 // //
57 // // the range will contain "f} - point of interest". The formatter should
58 // // parse specifiers until '}' or the end of the range. In this example
59 // // the formatter should parse the 'f' specifier and return an iterator
60 // // pointing to '}'.
61
62 // // Please also note that this character range may be empty, in case of
63 // // the "{}" format string, so therefore you should check ctx.begin()
64 // // for equality with ctx.end().
65
66 // // Parse the presentation format and store it in the formatter:
67 // auto it = ctx.begin(), end = ctx.end();
68 // if (it != end && (*it == 'f' || *it == 'e')) presentation = *it++;
69
70 // // Check if reached the end of the range:
71 // if (it != end && *it != '}') throw_format_error("invalid format");
72
73 // // Return an iterator past the end of the parsed range:
74 // return it;
75 // }
76
77 // Parses format specifications of the form ['f' | 'e'].
78 constexpr auto parse(format_parse_context& ctx) -> format_parse_context::iterator
79 {
80
81 // Parse the presentation format and store it in the formatter:
82 // auto it = ctx.begin(), end = ctx.end();
83 // if (it != end && (*it == 'f' || *it == 'e')) presentation = *it++;
84
85 // Check if reached the end of the range:
86 // if (it != end && *it != '}')
87 // fmt::detail::throw_format_error("invalid format");
88
89 // return it;
90 return ctx.begin();
91 }
92
93 // Formats the point p using the parsed format specification (presentation)
94 // stored in this formatter.
95 auto format(const dunedaq::daqdataformats::SourceID& sid, format_context& ctx) const -> format_context::iterator
96 {
97 return fmt::format_to(
98 ctx.out(), "({}, {})", dunedaq::daqdataformats::SourceID::subsystem_to_string(sid.subsystem), sid.id);
99 }
100};
101
102template<>
103struct fmt::formatter<hdf5libs::HDF5RawDataFile::record_id_t>
104{
105
106 // Parses format specifications of the form ['f' | 'e'].
107 constexpr auto parse(format_parse_context& ctx) -> format_parse_context::iterator { return ctx.begin(); }
108
109 // Formats the point p using the parsed format specification (presentation)
110 // stored in this formatter.
111 auto format(const hdf5libs::HDF5RawDataFile::record_id_t& rid, format_context& ctx) const -> format_context::iterator
112 {
113 return fmt::format_to(ctx.out(), "({}, {})", rid.first, rid.second);
114 }
115};
116//-----
117
118int
119main(int argc, char* argv[])
120{
121 std::string input_file;
122 bool verbose = false;
123 CLI::App app{ "tapipe" };
124 // argv = app.ensure_utf8(argv);
125
126 app.add_option("-i", input_file, "Input TPStream file path")->required();
127 app.add_flag("-v", verbose);
128 CLI11_PARSE(app, argc, argv);
129
130 fmt::print("TPStream file: {}\n", input_file);
131
132 // Pointer to DD hdf5 file
133 std::unique_ptr<hdf5libs::HDF5RawDataFile> tpstream_file;
134
135 try {
136 tpstream_file = std::make_unique<hdf5libs::HDF5RawDataFile>(input_file);
137 } catch (const hdf5libs::FileOpenFailed& e) {
138 std::cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ERROR <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << std::endl;
139 std::cerr << e.what() << '\n';
140 exit(-1);
141 }
142
143 fmt::print("{} opened\n", input_file);
144
145 // Check the record type
146 fmt::print(" File type: {}\n", tpstream_file->get_record_type());
147
148 // Extract the list of timeslices in the file
149 auto records = tpstream_file->get_all_record_ids();
150 std::set<daqdataformats::SourceID> source_ids;
151 // Find what Source IDs are available in the file (all records)
152 for (const auto& rid : records) {
153 const auto& [id, slice] = rid;
154 auto sids = tpstream_file->get_source_ids(rid);
155 source_ids.merge(sids);
156 if (verbose)
157 fmt::print("TR {}:{} [{}]\n", id, slice, fmt::join(sids, ", "));
158 }
159 fmt::print("Source IDs [{}]\n", fmt::join(source_ids, ", "));
160
161 // Map of source ids to trigger records
162 std::map<daqdataformats::SourceID, hdf5libs::HDF5RawDataFile::record_id_set> m;
163 for (const auto& sid : source_ids) {
164 for (const auto& rid : records) {
165 auto rec_sids = tpstream_file->get_source_ids(rid);
166 if (rec_sids.find(sid) != rec_sids.end()) {
167 m[sid].insert(rid);
168 }
169 }
170 if (verbose)
171 fmt::print("Record IDs for {} : [{}]\n", sid, fmt::join(m[sid], ", "));
172 }
173
174 // Print the number of timeslices in the files
175 fmt::print(" Number of time slices in file: {}\n", records.size());
176
177 // Get the list of records containing the tp writer source id
178 // I know the nuber by spying into the TP Stream File
180 auto tp_records = m[tp_writer_sid];
181
182 // Prepare the TP buffer
183 std::vector<trgdataformats::TriggerPrimitive> tp_buffer;
184
185 auto a_slice_id = *tp_records.begin();
186 fmt::print("Processing tp time slice {}\n", a_slice_id);
187
188 // auto tsl_hdr = tsl.get_header();
189 auto tsl_hdr = tpstream_file->get_tsh_ptr(a_slice_id);
190
191 // Print header ingo
192 fmt::print(" Run number: {}\n", tsl_hdr->run_number);
193 fmt::print(" TSL number: {}\n", tsl_hdr->timeslice_number);
194
195 auto frag = tpstream_file->get_frag_ptr(a_slice_id, tp_writer_sid);
196
197 fmt::print(" Fragment id: {} [{}]\n",
198 frag->get_element_id().to_string(),
199 daqdataformats::fragment_type_to_string(frag->get_fragment_type()));
200
201 size_t n_tps = frag->get_data_size() / sizeof(trgdataformats::TriggerPrimitive);
202 fmt::print("TP fragment size: {}\n", frag->get_data_size());
203 fmt::print("Num TPs: {}\n", n_tps);
204
205 trgdataformats::TriggerPrimitive* tp_array = static_cast<trgdataformats::TriggerPrimitive*>(frag->get_data());
206
207 // Prepare the TP buffer, checking for time ordering
208 tp_buffer.resize(tp_buffer.size() + n_tps);
209
210 uint64_t last_ts = 0;
211 for (size_t i(0); i < n_tps; ++i) {
212 auto& tp = tp_array[i];
213 if (tp.time_start <= last_ts) {
214 fmt::print("ERROR: {} {} ", +tp.time_start, last_ts);
215 }
216 tp_buffer.push_back(tp);
217 }
218
219 // Print some useful info
220 uint64_t d_ts = tp_array[n_tps - 1].time_start - tp_array[0].time_start;
221 fmt::print("TS gap: {} {} ms\n", d_ts, d_ts * 16.0 / 1'000'000);
222
223 // Finally create a TA maker
224 // Waiting for A.Oranday's factory!
226
227 // Create output buffer
228 std::vector<triggeralgs::TriggerActivity> ta_buffer;
229
230 // We should config the algo, really
231 const nlohmann::json config = {};
232 hmta.configure(config);
233
234 // Loop over TPs
235 for (const auto& tp : tp_buffer) {
236 hmta(tp, ta_buffer);
237 }
238
239 // Count number of TAs generated
240 fmt::print("ta_buffer.size() = {}\n", ta_buffer.size());
241
242 size_t payload_size(0);
243 for (const auto& ta : ta_buffer) {
244 payload_size += triggeralgs::get_overlay_nbytes(ta);
245 }
246
247 // Count number of TAs generated
248 fmt::print("ta_buffer in bytes = {}\n", payload_size);
249
250 char* payload = static_cast<char*>(malloc(payload_size));
251
252 size_t offset(0);
253 for (const auto& ta : ta_buffer) {
254 triggeralgs::write_overlay(ta, static_cast<void*>(payload + offset));
256 }
257
258 daqdataformats::Fragment ta_frag(static_cast<void*>(payload), payload_size);
259
260 free(static_cast<void*>(payload));
261
262 // How to save to file?
263 return 0;
264}
std::unique_ptr< hdf5libs::HDF5RawDataFile > m_file
Definition tapipe.cxx:28
HDF5FileReader(const std::string &path)
Definition tapipe.cxx:35
C++ Representation of a DUNE Fragment, wrapping the flat byte array that is the Fragment's "actual" f...
Definition Fragment.hpp:38
double offset
int main(int argc, char *argv[])
std::string fragment_type_to_string(const FragmentType &type)
The DUNE-DAQ namespace.
void write_overlay(const Object &object, void *buffer)
size_t get_overlay_nbytes(const Object &object)
SourceID is a generalized representation of the source of a piece of data in the DAQ....
Definition SourceID.hpp:32
static std::string subsystem_to_string(const Subsystem &type)
Definition SourceID.hxx:63
A single energy deposition on a TPC or PDS channel.
auto format(const dunedaq::daqdataformats::SourceID &sid, format_context &ctx) const -> format_context::iterator
Definition tapipe.cxx:95
constexpr auto parse(format_parse_context &ctx) -> format_parse_context::iterator
Definition tapipe.cxx:78
auto format(const hdf5libs::HDF5RawDataFile::record_id_t &rid, format_context &ctx) const -> format_context::iterator
Definition tapipe.cxx:111
constexpr auto parse(format_parse_context &ctx) -> format_parse_context::iterator
Definition tapipe.cxx:107