LCOV - code coverage report
Current view: top level - hdf5libs/src - HDF5FileLayout.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 42.5 % 146 62
Test Date: 2025-12-21 13:07:08 Functions: 47.6 % 21 10

            Line data    Source code
       1              : /**
       2              :  * This is part of the DUNE DAQ Application Framework, copyright 2020.
       3              :  * Licensing/copyright details are in the COPYING file that you should have
       4              :  * received with this code.
       5              :  *
       6              :  */
       7              : 
       8              : #include "hdf5libs/HDF5FileLayout.hpp"
       9              : 
      10              : #include <stdexcept>
      11              : #include <string>
      12              : #include <vector>
      13              : 
      14              : namespace dunedaq {
      15              : namespace hdf5libs {
      16              : 
      17           43 : HDF5FileLayout::HDF5FileLayout(HDF5FileLayoutParameters conf,
      18           43 :                                uint32_t version) // NOLINT(build/unsigned)
      19           43 :   : m_conf_params(conf)
      20           43 :   , m_version(version)
      21              : {
      22           43 :   if (m_version < 2)
      23            0 :     m_conf_params = get_v0_file_layout_params();
      24              : 
      25           43 :   fill_path_params_maps(m_conf_params);
      26              : 
      27           43 :   check_config();
      28           43 : }
      29              : 
      30              : void
      31           43 : HDF5FileLayout::check_config()
      32              : {
      33              :   // for now, don't do additional config checks for old versions
      34           43 :   if (m_version < 2)
      35              :     return;
      36              : 
      37           43 :   if (m_conf_params.record_name_prefix.compare("TriggerRecord") == 0) {
      38           31 :     if (m_conf_params.digits_for_sequence_number == 0) {
      39            0 :       ers::error(FileLayoutSequenceIDsCannotBeZero(ERS_HERE, 4));
      40            0 :       m_conf_params.digits_for_sequence_number = 4;
      41              :     }
      42           12 :   } else if (m_conf_params.record_name_prefix.compare("TimeSlice") == 0) {
      43           12 :     if (m_conf_params.digits_for_sequence_number != 0) {
      44            0 :       ers::warning(InvalidSequenceDigits(ERS_HERE, m_conf_params.record_name_prefix, 0));
      45            0 :       m_conf_params.digits_for_sequence_number = 0;
      46              :     }
      47              :   } else {
      48            0 :     throw InvalidRecordName(ERS_HERE, m_conf_params.record_name_prefix);
      49              :   }
      50              : }
      51              : 
      52              : HDF5PathParameters
      53            0 : HDF5FileLayout::get_path_params(daqdataformats::SourceID::Subsystem type) const
      54              : {
      55            0 :   try {
      56            0 :     return m_path_params_map.at(type);
      57            0 :   } catch (std::out_of_range&) {
      58            0 :     throw FileLayoutUnconfiguredSubsystem(ERS_HERE, type, daqdataformats::SourceID::subsystem_to_string(type));
      59            0 :   }
      60              : }
      61              : 
      62              : std::string
      63         1755 : HDF5FileLayout::get_record_number_string(uint64_t record_number, // NOLINT(build/unsigned)
      64              :                                          daqdataformats::sequence_number_t seq_num) const
      65              : {
      66         1755 :   std::ostringstream record_number_string;
      67              : 
      68         1755 :   int width = m_conf_params.digits_for_record_number;
      69         1755 :   record_number_string << m_conf_params.record_name_prefix << std::setw(width) << std::setfill('0') << record_number;
      70              : 
      71         1755 :   if (m_conf_params.digits_for_sequence_number > 0) {
      72              : 
      73         1435 :     width = m_conf_params.digits_for_sequence_number;
      74         1435 :     record_number_string << "." << std::setw(width) << std::setfill('0') << seq_num;
      75              :   }
      76              : 
      77         3510 :   return record_number_string.str();
      78         1755 : }
      79              : 
      80              : std::string
      81         1655 : HDF5FileLayout::get_trigger_number_string(daqdataformats::trigger_number_t trig_num,
      82              :                                           daqdataformats::sequence_number_t seq_num) const
      83              : {
      84         1655 :   return get_record_number_string(trig_num, seq_num);
      85              : }
      86              : 
      87              : std::string
      88           60 : HDF5FileLayout::get_timeslice_number_string(daqdataformats::timeslice_number_t ts_num) const
      89              : {
      90           60 :   return get_record_number_string(ts_num);
      91              : }
      92              : 
      93              : /**
      94              :  * @brief get the correct path for the TriggerRecordHeader
      95              :  */
      96              : std::vector<std::string>
      97           75 : HDF5FileLayout::get_path_elements(const daqdataformats::TriggerRecordHeader& trh) const
      98              : {
      99              : 
     100           75 :   std::vector<std::string> path_elements;
     101              : 
     102              :   // first the Trigger string
     103           75 :   path_elements.push_back(get_trigger_number_string(trh.get_trigger_number(), trh.get_sequence_number()));
     104              : 
     105              :   // then the RawData group name
     106           75 :   path_elements.push_back(m_conf_params.raw_data_group_name);
     107              : 
     108              :   // then the SourceID plus record header name
     109           75 :   path_elements.push_back(trh.get_header().element_id.to_string() + "_" +
     110           75 :                           m_conf_params.record_header_dataset_name);
     111              : 
     112           75 :   return path_elements;
     113            0 : }
     114              : 
     115              : /**
     116              :  * @brief get the correct path for the TimeSliceHeader
     117              :  */
     118              : std::vector<std::string>
     119           30 : HDF5FileLayout::get_path_elements(const daqdataformats::TimeSliceHeader& tsh) const
     120              : {
     121              : 
     122           30 :   std::vector<std::string> path_elements;
     123              : 
     124              :   // first the Trigger string
     125           30 :   path_elements.push_back(get_timeslice_number_string(tsh.timeslice_number));
     126              : 
     127              :   // then the RawData group name
     128           30 :   path_elements.push_back(m_conf_params.raw_data_group_name);
     129              : 
     130              :   // then the SourceID plus record header name
     131           30 :   path_elements.push_back(tsh.element_id.to_string() + "_" + m_conf_params.record_header_dataset_name);
     132              : 
     133           30 :   return path_elements;
     134            0 : }
     135              : 
     136              : /**
     137              :  * @brief get the correct path for the Fragment
     138              :  */
     139              : std::vector<std::string>
     140         1580 : HDF5FileLayout::get_path_elements(const daqdataformats::FragmentHeader& fh) const
     141              : {
     142              : 
     143         1580 :   std::vector<std::string> path_elements;
     144              : 
     145              :   // first the Trigger string
     146              :   // note, this still works for TimeSlices through enforced proper configuration of layout parameters
     147         1580 :   path_elements.push_back(get_trigger_number_string(fh.trigger_number, fh.sequence_number));
     148              : 
     149              :   // then the RawData group name
     150         1580 :   path_elements.push_back(m_conf_params.raw_data_group_name);
     151              : 
     152              :   // then the SourceID plus FragmentType
     153         1580 :   path_elements.push_back(
     154         3160 :     fh.element_id.to_string() + "_" +
     155         3160 :     daqdataformats::fragment_type_to_string(static_cast<daqdataformats::FragmentType>(fh.fragment_type)));
     156              : 
     157         1580 :   return path_elements;
     158            0 : }
     159              : 
     160              : /**
     161              :  * @brief get the path for the TimeSliceHeader as a single string
     162              :  */
     163              : std::string
     164           30 : HDF5FileLayout::get_path_string(const daqdataformats::TimeSliceHeader& tsh) const
     165              : {
     166           30 :   std::ostringstream path_string;
     167           30 :   path_string << "/" << get_timeslice_number_string(tsh.timeslice_number)
     168           30 :               << "/" << m_conf_params.raw_data_group_name
     169           60 :               << "/" << tsh.element_id.to_string() << "_" << m_conf_params.record_header_dataset_name;
     170           60 :   return path_string.str();
     171           30 : }
     172              : 
     173              : /**
     174              :  * @brief get the full path for a record header dataset based on trig/seq number
     175              :  */
     176              : std::string
     177            0 : HDF5FileLayout::get_record_header_path(uint64_t rec_num, // NOLINT (build/unsigned)
     178              :                                        daqdataformats::sequence_number_t seq_num) const
     179              : {
     180            0 :   return get_record_number_string(rec_num, seq_num) + "/" + m_conf_params.record_header_dataset_name;
     181              : }
     182              : 
     183              : /**
     184              :  * @brief get the full path for a TriggerRecordHeader dataset based on trig/seq number
     185              :  */
     186              : std::string
     187            0 : HDF5FileLayout::get_trigger_record_header_path(daqdataformats::trigger_number_t trig_num,
     188              :                                                daqdataformats::sequence_number_t seq_num) const
     189              : {
     190            0 :   return get_trigger_number_string(trig_num, seq_num) + "/" + m_conf_params.record_header_dataset_name;
     191              : }
     192              : 
     193              : /**
     194              :  * @brief get the full path for a TimeSliceHeader dataset based on ts number
     195              :  */
     196              : std::string
     197            0 : HDF5FileLayout::get_timeslice_header_path(daqdataformats::timeslice_number_t ts_num) const
     198              : {
     199            0 :   return get_timeslice_number_string(ts_num) + "/" + m_conf_params.record_header_dataset_name;
     200              : }
     201              : 
     202              : /**
     203              :  * @brief get the full path for a Fragment dataset based on trig/seq number and element ID
     204              :  */
     205              : std::string
     206            0 : HDF5FileLayout::get_fragment_path(uint64_t trig_num, // NOLINT(build/unsigned)
     207              :                                   daqdataformats::sequence_number_t seq_num,
     208              :                                   daqdataformats::SourceID element_id) const
     209              : {
     210              : 
     211            0 :   auto const& path_params = get_path_params(element_id.subsystem);
     212              : 
     213            0 :   std::ostringstream path_string;
     214            0 :   path_string << get_trigger_number_string(trig_num, seq_num) << "/" << path_params.detector_group_name << "/"
     215            0 :               << path_params.element_name_prefix << std::setw(path_params.digits_for_element_number)
     216            0 :               << std::setfill('0') << element_id.id;
     217            0 :   return path_string.str();
     218            0 : }
     219              : 
     220              : /**
     221              :  * @brief get the full path for a Fragment dataset based on trig/seq number, give element_id pieces
     222              :  */
     223              : std::string
     224            0 : HDF5FileLayout::get_fragment_path(uint64_t trig_num, // NOLINT(build/unsigned)
     225              :                                   daqdataformats::sequence_number_t seq_num,
     226              :                                   daqdataformats::SourceID::Subsystem type,
     227              :                                   uint32_t element_id) const // NOLINT(build/unsigned)
     228              : {
     229            0 :   daqdataformats::SourceID sid{ type, element_id };
     230            0 :   return get_fragment_path(trig_num, seq_num, sid);
     231              : }
     232              : 
     233              : /**
     234              :  * @brief get the full path for a Fragment dataset based on trig/seq number, give element_id pieces
     235              :  */
     236              : std::string
     237            0 : HDF5FileLayout::get_fragment_path(uint64_t trig_num, // NOLINT(build/unsigned)
     238              :                                   daqdataformats::sequence_number_t seq_num,
     239              :                                   const std::string& typestring,
     240              :                                   uint32_t element_id) const // NOLINT(build/unsigned)
     241              : {
     242            0 :   daqdataformats::SourceID sid{ daqdataformats::SourceID::string_to_subsystem(typestring), element_id };
     243            0 :   return get_fragment_path(trig_num, seq_num, sid);
     244              : }
     245              : 
     246              : /**
     247              :  * @brief get the path for a Fragment type group based on trig/seq number and type
     248              :  */
     249              : std::string
     250            0 : HDF5FileLayout::get_fragment_type_path(uint64_t trig_num, // NOLINT(build/unsigned)
     251              :                                        daqdataformats::sequence_number_t seq_num,
     252              :                                        daqdataformats::SourceID::Subsystem type) const
     253              : {
     254            0 :   auto const& path_params = get_path_params(type);
     255              : 
     256            0 :   std::ostringstream path_string;
     257            0 :   path_string << get_trigger_number_string(trig_num, seq_num) << "/" << path_params.detector_group_name;
     258            0 :   return path_string.str();
     259            0 : }
     260              : 
     261              : /**
     262              :  * @brief get the path for a Fragment type group based on trig/seq number and type
     263              :  */
     264              : std::string
     265            0 : HDF5FileLayout::get_fragment_type_path(uint64_t trig_num, // NOLINT(build/unsigned)
     266              :                                        daqdataformats::sequence_number_t seq_num,
     267              :                                        std::string typestring) const
     268              : {
     269            0 :   return get_fragment_type_path(trig_num, seq_num, daqdataformats::SourceID::string_to_subsystem(typestring));
     270              : }
     271              : 
     272              : daqdataformats::SourceID
     273            0 : HDF5FileLayout::get_source_id_from_path_elements(std::vector<std::string> const& path_elements) const
     274              : {
     275              :   // ignore first path element, which is for the record group
     276              :   // second path element is detector name.
     277            0 :   daqdataformats::SourceID::Subsystem systype = m_detector_group_name_to_type_map.at(path_elements[1]);
     278              : 
     279              :   // get back the path parameters for this system type from the file layout
     280            0 :   auto path_params = get_path_params(systype);
     281              : 
     282              :   // fourth path element is element. remove prefix and translate to numbers
     283            0 :   auto ele_id = std::stoi(path_elements[3].substr(path_params.element_name_prefix.size()));
     284              : 
     285            0 :   return daqdataformats::SourceID(systype, ele_id);
     286            0 : }
     287              : 
     288              : void
     289           43 : HDF5FileLayout::fill_path_params_maps(HDF5FileLayoutParameters const& flp)
     290              : {
     291           86 :   for (auto const& path_param : flp.path_params_list) {
     292           43 :     auto sys_type = daqdataformats::SourceID::string_to_subsystem(path_param.detector_group_type);
     293              : 
     294           43 :     if (sys_type == daqdataformats::SourceID::Subsystem::kUnknown)
     295            0 :       throw FileLayoutInvalidSubsystem(ERS_HERE, path_param.detector_group_type);
     296              : 
     297           43 :     m_path_params_map[sys_type] = path_param;
     298           43 :     m_detector_group_name_to_type_map[path_param.detector_group_name] = sys_type;
     299              :   }
     300           43 : }
     301              : 
     302              : /**
     303              :  * @brief Version0 FileLayout parameters, for backward compatibility
     304              :  */
     305              : HDF5FileLayoutParameters
     306            0 : HDF5FileLayout::get_v0_file_layout_params()
     307              : {
     308            0 :   HDF5FileLayoutParameters flp;
     309            0 :   flp.record_name_prefix = "TriggerRecord";
     310            0 :   flp.digits_for_record_number = 6;
     311            0 :   flp.digits_for_sequence_number = 0;
     312            0 :   flp.record_header_dataset_name = "TriggerRecordHeader";
     313              : 
     314            0 :   HDF5PathParameters pp;
     315              : 
     316            0 :   pp.detector_group_type = "TPC";
     317            0 :   pp.detector_group_name = "TPC";
     318            0 :   pp.element_name_prefix = "Link";
     319            0 :   pp.digits_for_element_number = 2;
     320            0 :   flp.path_params_list.push_back(pp);
     321              : 
     322            0 :   pp.detector_group_type = "PDS";
     323            0 :   pp.detector_group_name = "PDS";
     324            0 :   pp.element_name_prefix = "Element";
     325            0 :   pp.digits_for_element_number = 2;
     326            0 :   flp.path_params_list.push_back(pp);
     327              : 
     328            0 :   pp.detector_group_type = "NDLArTPC";
     329            0 :   pp.detector_group_name = "NDLArTPC";
     330            0 :   pp.element_name_prefix = "Element";
     331            0 :   pp.digits_for_element_number = 2;
     332            0 :   flp.path_params_list.push_back(pp);
     333              : 
     334            0 :   pp.detector_group_type = "NDLArPDS";
     335            0 :   pp.detector_group_name = "NDLArPDS";
     336            0 :   pp.element_name_prefix = "Element";
     337            0 :   pp.digits_for_element_number = 2;
     338            0 :   flp.path_params_list.push_back(pp);
     339              : 
     340            0 :   pp.detector_group_type = "DataSelection";
     341            0 :   pp.detector_group_name = "Trigger";
     342            0 :   pp.element_name_prefix = "Element";
     343            0 :   pp.digits_for_element_number = 2;
     344            0 :   flp.path_params_list.push_back(pp);
     345              : 
     346            0 :   return flp;
     347            0 : }
     348              : 
     349              : } // namespace hdf5libs
     350              : } // namespace dunedaq
        

Generated by: LCOV version 2.0-1