Line data Source code
1 : /**
2 : * @file tapipe.cxx
3 : *
4 : * Developer(s) of this DAQ application have yet to replace this line with a brief description of the application.
5 : *
6 : * This is part of the DUNE DAQ Application Framework, copyright 2020.
7 : * Licensing/copyright details are in the COPYING file that you should have
8 : * received with this code.
9 : */
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 :
18 : #include "hdf5libs/HDF5RawDataFile.hpp"
19 : #include "trgdataformats/TriggerPrimitive.hpp"
20 : #include "triggeralgs/HorizontalMuon/TAMakerHorizontalMuonAlgorithm.hpp"
21 : #include "triggeralgs/TriggerObjectOverlay.hpp"
22 :
23 : using namespace dunedaq;
24 :
25 : class HDF5FileReader
26 : {
27 : private:
28 : std::unique_ptr<hdf5libs::HDF5RawDataFile> m_file;
29 :
30 : public:
31 : HDF5FileReader(const std::string& path);
32 : ~HDF5FileReader();
33 : };
34 :
35 0 : HDF5FileReader::HDF5FileReader(const std::string& path)
36 : {
37 0 : m_file = std::make_unique<hdf5libs::HDF5RawDataFile>(path);
38 0 : }
39 :
40 0 : HDF5FileReader::~HDF5FileReader() {}
41 : //-----
42 :
43 : template<>
44 : struct 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 0 : 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 0 : return ctx.begin();
91 : }
92 :
93 : // Formats the point p using the parsed format specification (presentation)
94 : // stored in this formatter.
95 0 : auto format(const dunedaq::daqdataformats::SourceID& sid, format_context& ctx) const -> format_context::iterator
96 : {
97 0 : return fmt::format_to(
98 0 : ctx.out(), "({}, {})", dunedaq::daqdataformats::SourceID::subsystem_to_string(sid.subsystem), sid.id);
99 : }
100 : };
101 :
102 : template<>
103 : struct fmt::formatter<hdf5libs::HDF5RawDataFile::record_id_t>
104 : {
105 :
106 : // Parses format specifications of the form ['f' | 'e'].
107 0 : 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 0 : auto format(const hdf5libs::HDF5RawDataFile::record_id_t& rid, format_context& ctx) const -> format_context::iterator
112 : {
113 0 : return fmt::format_to(ctx.out(), "({}, {})", rid.first, rid.second);
114 : }
115 : };
116 : //-----
117 :
118 : int
119 0 : main(int argc, char* argv[])
120 : {
121 0 : std::string input_file;
122 0 : bool verbose = false;
123 0 : CLI::App app{ "tapipe" };
124 : // argv = app.ensure_utf8(argv);
125 :
126 0 : app.add_option("-i", input_file, "Input TPStream file path")->required();
127 0 : app.add_flag("-v", verbose);
128 0 : CLI11_PARSE(app, argc, argv);
129 :
130 0 : fmt::print("TPStream file: {}\n", input_file);
131 :
132 : // Pointer to DD hdf5 file
133 0 : std::unique_ptr<hdf5libs::HDF5RawDataFile> tpstream_file;
134 :
135 0 : try {
136 0 : tpstream_file = std::make_unique<hdf5libs::HDF5RawDataFile>(input_file);
137 0 : } catch (const hdf5libs::FileOpenFailed& e) {
138 0 : std::cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ERROR <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << std::endl;
139 0 : std::cerr << e.what() << '\n';
140 0 : exit(-1);
141 0 : }
142 :
143 0 : fmt::print("{} opened\n", input_file);
144 :
145 : // Check the record type
146 0 : fmt::print(" File type: {}\n", tpstream_file->get_record_type());
147 :
148 : // Extract the list of timeslices in the file
149 0 : auto records = tpstream_file->get_all_record_ids();
150 0 : std::set<daqdataformats::SourceID> source_ids;
151 : // Find what Source IDs are available in the file (all records)
152 0 : for (const auto& rid : records) {
153 0 : const auto& [id, slice] = rid;
154 0 : auto sids = tpstream_file->get_source_ids(rid);
155 0 : source_ids.merge(sids);
156 0 : if (verbose)
157 0 : fmt::print("TR {}:{} [{}]\n", id, slice, fmt::join(sids, ", "));
158 0 : }
159 0 : fmt::print("Source IDs [{}]\n", fmt::join(source_ids, ", "));
160 :
161 : // Map of source ids to trigger records
162 0 : std::map<daqdataformats::SourceID, hdf5libs::HDF5RawDataFile::record_id_set> m;
163 0 : for (const auto& sid : source_ids) {
164 0 : for (const auto& rid : records) {
165 0 : auto rec_sids = tpstream_file->get_source_ids(rid);
166 0 : if (rec_sids.find(sid) != rec_sids.end()) {
167 0 : m[sid].insert(rid);
168 : }
169 0 : }
170 0 : if (verbose)
171 0 : fmt::print("Record IDs for {} : [{}]\n", sid, fmt::join(m[sid], ", "));
172 : }
173 :
174 : // Print the number of timeslices in the files
175 0 : 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
179 0 : daqdataformats::SourceID tp_writer_sid{ daqdataformats::SourceID::Subsystem::kTrigger, 0 };
180 0 : auto tp_records = m[tp_writer_sid];
181 :
182 : // Prepare the TP buffer
183 0 : std::vector<trgdataformats::TriggerPrimitive> tp_buffer;
184 :
185 0 : auto a_slice_id = *tp_records.begin();
186 0 : fmt::print("Processing tp time slice {}\n", a_slice_id);
187 :
188 : // auto tsl_hdr = tsl.get_header();
189 0 : auto tsl_hdr = tpstream_file->get_tsh_ptr(a_slice_id);
190 :
191 : // Print header ingo
192 0 : fmt::print(" Run number: {}\n", tsl_hdr->run_number);
193 0 : fmt::print(" TSL number: {}\n", tsl_hdr->timeslice_number);
194 :
195 0 : auto frag = tpstream_file->get_frag_ptr(a_slice_id, tp_writer_sid);
196 :
197 0 : fmt::print(" Fragment id: {} [{}]\n",
198 0 : frag->get_element_id().to_string(),
199 0 : daqdataformats::fragment_type_to_string(frag->get_fragment_type()));
200 :
201 0 : size_t n_tps = frag->get_data_size() / sizeof(trgdataformats::TriggerPrimitive);
202 0 : fmt::print("TP fragment size: {}\n", frag->get_data_size());
203 0 : fmt::print("Num TPs: {}\n", n_tps);
204 :
205 0 : trgdataformats::TriggerPrimitive* tp_array = static_cast<trgdataformats::TriggerPrimitive*>(frag->get_data());
206 :
207 : // Prepare the TP buffer, checking for time ordering
208 0 : tp_buffer.resize(tp_buffer.size() + n_tps);
209 :
210 0 : uint64_t last_ts = 0;
211 0 : for (size_t i(0); i < n_tps; ++i) {
212 0 : auto& tp = tp_array[i];
213 0 : if (tp.time_start <= last_ts) {
214 0 : fmt::print("ERROR: {} {} ", +tp.time_start, last_ts);
215 : }
216 0 : tp_buffer.push_back(tp);
217 : }
218 :
219 : // Print some useful info
220 0 : uint64_t d_ts = tp_array[n_tps - 1].time_start - tp_array[0].time_start;
221 0 : 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!
225 0 : triggeralgs::TAMakerHorizontalMuonAlgorithm hmta;
226 :
227 : // Create output buffer
228 0 : std::vector<triggeralgs::TriggerActivity> ta_buffer;
229 :
230 : // We should config the algo, really
231 0 : const nlohmann::json config = {};
232 0 : hmta.configure(config);
233 :
234 : // Loop over TPs
235 0 : for (const auto& tp : tp_buffer) {
236 0 : hmta(tp, ta_buffer);
237 : }
238 :
239 : // Count number of TAs generated
240 0 : fmt::print("ta_buffer.size() = {}\n", ta_buffer.size());
241 :
242 0 : size_t payload_size(0);
243 0 : for (const auto& ta : ta_buffer) {
244 0 : payload_size += triggeralgs::get_overlay_nbytes(ta);
245 : }
246 :
247 : // Count number of TAs generated
248 0 : fmt::print("ta_buffer in bytes = {}\n", payload_size);
249 :
250 0 : char* payload = static_cast<char*>(malloc(payload_size));
251 :
252 0 : size_t offset(0);
253 0 : for (const auto& ta : ta_buffer) {
254 0 : triggeralgs::write_overlay(ta, static_cast<void*>(payload + offset));
255 0 : offset += triggeralgs::get_overlay_nbytes(ta);
256 : }
257 :
258 0 : daqdataformats::Fragment ta_frag(static_cast<void*>(payload), payload_size);
259 :
260 0 : free(static_cast<void*>(payload));
261 :
262 : // How to save to file?
263 0 : return 0;
264 0 : }
|