Line data Source code
1 : /**
2 : * @file generate_tpset_from_hdf5.cxx Read TP fragments from file and generate a TPSet vector.
3 : * Matches code within TPReplayModule.
4 : *
5 : * This is part of the DUNE DAQ Application Framework, copyright 2020.
6 : * Licensing/copyright details are in the COPYING file that you should have
7 : * received with this code.
8 : */
9 : #include "CLI/CLI.hpp"
10 :
11 : #include "../../plugins/TPReplayModule.hpp"
12 : #include "trgdataformats/TriggerPrimitive.hpp"
13 :
14 : #include "daqdataformats/Fragment.hpp"
15 : #include "daqdataformats/FragmentHeader.hpp"
16 : #include "daqdataformats/SourceID.hpp"
17 : #include "daqdataformats/TriggerRecordHeader.hpp"
18 : #include "daqdataformats/Types.hpp"
19 : #include "hdf5libs/HDF5RawDataFile.hpp"
20 :
21 : #include <iostream>
22 :
23 : int
24 0 : main(int argc, char** argv)
25 : {
26 0 : CLI::App app{ "App description" };
27 :
28 0 : std::string filename;
29 0 : app.add_option("-f,--file", filename, "Input HDF5 file");
30 :
31 0 : CLI11_PARSE(app, argc, argv);
32 :
33 0 : dunedaq::trigger::TPSet tpset;
34 0 : std::vector<dunedaq::trigger::TPSet> tpsets;
35 :
36 0 : uint64_t prev_tpset_number = 0; // NOLINT(build/unsigned)
37 0 : uint32_t seqno = 0; // NOLINT(build/unsigned)
38 0 : uint64_t old_time_start = 0; // NOLINT(build/unsigned)
39 0 : uint32_t tpset_time_width = 10; // Arbitrary
40 0 : uint32_t tpset_time_offset = 5; // Arbitrary
41 0 : uint16_t element = 0; // Arbitrary
42 0 : uint32_t total_tps = 0;
43 :
44 : // Prepare input file
45 0 : std::unique_ptr<dunedaq::hdf5libs::HDF5RawDataFile> input_file =
46 0 : std::make_unique<dunedaq::hdf5libs::HDF5RawDataFile>(filename);
47 :
48 : // Check that the file is a TimeSlice type
49 0 : if (!input_file->is_timeslice_type()) {
50 0 : std::cout << "Not a timeslice type.\n";
51 : return 1;
52 : }
53 :
54 0 : std::vector<std::string> fragment_paths = input_file->get_all_fragment_dataset_paths();
55 :
56 : // Read in the file and place the TPs in TPSets. TPSets have time
57 : // boundaries ( n*tpset_time_width + tpset_time_offset ), and TPs are placed
58 : // in TPSets based on the TP start time
59 : //
60 : // This loop assumes the input file is sorted by TP start time
61 0 : for (std::string& fragment_path : fragment_paths) {
62 0 : std::unique_ptr<dunedaq::daqdataformats::Fragment> frag = input_file->get_frag_ptr(fragment_path);
63 : // Make sure this fragment is a TriggerPrimitive
64 0 : if (frag->get_fragment_type() != dunedaq::daqdataformats::FragmentType::kTriggerPrimitive)
65 0 : continue;
66 0 : if (frag->get_element_id().subsystem != dunedaq::daqdataformats::SourceID::Subsystem::kTrigger)
67 0 : continue;
68 :
69 : // Prepare TP buffer
70 0 : size_t num_tps = frag->get_data_size() / sizeof(dunedaq::trgdataformats::TriggerPrimitive);
71 0 : total_tps += num_tps;
72 :
73 0 : dunedaq::trgdataformats::TriggerPrimitive* tp_array =
74 0 : static_cast<dunedaq::trgdataformats::TriggerPrimitive*>(frag->get_data());
75 :
76 0 : for (size_t i(0); i < num_tps; i++) {
77 0 : auto& tp = tp_array[i];
78 0 : if (tp.time_start < old_time_start) {
79 0 : std::cout << "TPs are unsorted.\n";
80 0 : return 1;
81 : }
82 : // NOLINTNEXTLINE(build/unsigned)
83 0 : uint64_t current_tpset_number = (tp.time_start + tpset_time_offset) / tpset_time_width;
84 0 : old_time_start = tp.time_start;
85 :
86 : // If we crossed a time boundary, push the current TPSet and reset it
87 0 : if (current_tpset_number > prev_tpset_number) {
88 0 : tpset.start_time = prev_tpset_number * tpset_time_width + tpset_time_offset;
89 0 : tpset.end_time = tpset.start_time + tpset_time_width;
90 0 : tpset.seqno = seqno;
91 0 : ++seqno;
92 :
93 : // 12-Jul-2021, KAB: setting origin fields from configuration
94 0 : tpset.origin.id = element;
95 :
96 0 : tpset.type = dunedaq::trigger::TPSet::Type::kPayload;
97 :
98 0 : if (!tpset.objects.empty()) {
99 : // We don't send empty TPSets, so there's no point creating them
100 0 : tpsets.push_back(tpset);
101 : }
102 0 : prev_tpset_number = current_tpset_number;
103 :
104 0 : tpset.objects.clear();
105 : }
106 0 : tpset.objects.push_back(tp);
107 : }
108 0 : }
109 0 : if (!tpset.objects.empty()) {
110 : // We don't send empty TPSets, so there's no point creating them
111 0 : tpsets.push_back(tpset);
112 : }
113 0 : std::cout << "Read " << total_tps << " TPs into " << tpsets.size() << " TPSets, from file " << filename << std::endl;
114 :
115 : return 0;
116 0 : }
|