LCOV - code coverage report
Current view: top level - trgtools/apps - tapipe.cxx (source / functions) Coverage Total Hit
Test: code.result Lines: 0.0 % 95 0
Test Date: 2026-10-11 15:05:20 Functions: 0.0 % 7 0

            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 : }
        

Generated by: LCOV version 2.0-1