Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-07-18 08:41:38

0001 #ifndef PODIO_ROOTREADER_H
0002 #define PODIO_ROOTREADER_H
0003 
0004 #include "podio/ROOTFrameData.h"
0005 #include "podio/podioVersion.h"
0006 #include "podio/utilities/DatamodelRegistryIOHelpers.h"
0007 #include "podio/utilities/ReaderUtils.h"
0008 #include "podio/utilities/RootHelpers.h"
0009 
0010 #include "TChain.h"
0011 
0012 #include <memory>
0013 #include <optional>
0014 #include <string>
0015 #include <string_view>
0016 #include <tuple>
0017 #include <utility>
0018 #include <vector>
0019 
0020 // forward declarations
0021 class TClass;
0022 class TFile;
0023 class TTree;
0024 
0025 namespace podio {
0026 
0027 namespace detail {
0028   // Information about the collection class type, whether it is a subset, the
0029   // schema version on file and the index in the collection branches cache
0030   // vector
0031   using CollectionInfo = std::tuple<std::string, bool, SchemaVersionT, size_t>;
0032 
0033   struct NamedCollInfo {
0034     std::string name{};
0035     CollectionInfo info{};
0036   };
0037 } // namespace detail
0038 
0039 class CollectionBase;
0040 class CollectionIDTable;
0041 class GenericParameters;
0042 struct CollectionReadBuffers;
0043 
0044 /// This class has the function to read available data from disk in ROOTs TTree
0045 /// format.
0046 ///
0047 /// The ROOTReader provides the data as ROOTFrameData from which a podio::Frame
0048 /// can be constructed. It can be used to read files written by the ROOTWriter.
0049 class ROOTReader {
0050 
0051 public:
0052   /// Create a ROOTReader
0053   ROOTReader() = default;
0054   /// Destructor
0055   ~ROOTReader() = default;
0056 
0057   /// The ROOTReader is not copy-able
0058   ROOTReader(const ROOTReader&) = delete;
0059   /// The ROOTReader is not copy-able
0060   ROOTReader& operator=(const ROOTReader&) = delete;
0061 
0062   /// Open a single file for reading.
0063   ///
0064   /// @param filename The name of the input file
0065   void openFile(const std::string& filename);
0066 
0067   /// Open multiple files for reading and then treat them as if they are one file
0068   ///
0069   /// @note All of the files are assumed to have the same structure. Specifically
0070   /// this means:
0071   /// - The same categories are available from all files
0072   /// - The collections that are contained in the individual categories are the
0073   ///   same across all files
0074   /// - This usually boils down to "the files have been written with the same
0075   ///   "settings", e.g. they are outputs of a batched process.
0076   ///
0077   /// @param filenames The filenames of all input files that should be read
0078   void openFiles(const std::vector<std::string>& filenames);
0079 
0080   /// Read the next data entry for a given category.
0081   ///
0082   /// @param name The category name for which to read the next entry
0083   /// @param collsToRead (optional) the collection names that should be read. If
0084   ///             not provided (or empty) all collections will be read
0085   ///
0086   /// @returns FrameData from which a podio::Frame can be constructed if the
0087   ///          category exists and if there are still entries left to read.
0088   ///          Otherwise a nullptr
0089   ///
0090   /// @throws std::invalid_argument in case collsToRead contains collection
0091   /// names that are not available
0092   std::unique_ptr<podio::ROOTFrameData> readNextEntry(const std::string& name,
0093                                                       const std::vector<std::string>& collsToRead = {});
0094 
0095   /// Read the desired data entry for a given category.
0096   ///
0097   /// @param name  The category name for which to read the next entry
0098   /// @param entry The entry number to read
0099   /// @param collsToRead (optional) the collection names that should be read. If
0100   ///              not provided (or empty) all collections will be read
0101   ///
0102   /// @returns FrameData from which a podio::Frame can be constructed if the
0103   ///          category and the desired entry exist. Otherwise a nullptr
0104   ///
0105   /// @throws std::invalid_argument in case collsToRead contains collection
0106   /// names that are not available
0107   std::unique_ptr<podio::ROOTFrameData> readEntry(const std::string& name, const unsigned entry,
0108                                                   const std::vector<std::string>& collsToRead = {});
0109 
0110   /// Get the number of entries for the given name
0111   ///
0112   /// @param name The name of the category
0113   ///
0114   /// @returns The number of entries that are available for the category
0115   unsigned getEntries(const std::string& name) const;
0116 
0117   /// Get the build version of podio that has been used to write the current
0118   /// file
0119   ///
0120   /// @returns The podio build version
0121   podio::version::Version currentFileVersion() const {
0122     return m_fileVersion;
0123   }
0124 
0125   /// Get the (build) version of a datamodel that has been used to write the
0126   /// current file
0127   ///
0128   /// @param name The name of the datamodel
0129   ///
0130   /// @returns The (build) version of the datamodel if available or an empty
0131   ///          optional
0132   std::optional<podio::version::Version> currentFileVersion(const std::string& name) const {
0133     return m_datamodelHolder.getDatamodelVersion(name);
0134   }
0135 
0136   /// Get the names of all the available Frame categories in the current file(s).
0137   ///
0138   /// @returns The names of the available categories from the file
0139   std::vector<std::string_view> getAvailableCategories() const;
0140 
0141   /// Get the datamodel definition for the given name
0142   ///
0143   /// @param name The name of the datamodel
0144   ///
0145   /// @returns The high level definition of the datamodel in JSON format
0146   const std::string_view getDatamodelDefinition(const std::string& name) const {
0147     return m_datamodelHolder.getDatamodelDefinition(name);
0148   }
0149 
0150   /// Get all names of the datamodels that are available from this reader
0151   ///
0152   /// @returns The names of the datamodels
0153   std::vector<std::string> getAvailableDatamodels() const {
0154     return m_datamodelHolder.getAvailableDatamodels();
0155   }
0156   std::optional<std::map<std::string, SizeStats>> getSizeStats(std::string_view category);
0157 
0158 private:
0159   /// Helper struct to group together all the necessary state to read / process
0160   /// a given category. A "category" in this case describes all frames with the
0161   /// same name which are constrained by the ROOT file structure that we use to
0162   /// have the same contents. It encapsulates all state that is necessary for
0163   /// reading from a TTree / TChain (i.e. collection infos, branches, ...)
0164   struct CategoryInfo {
0165     /// constructor from chain for more convenient map insertion
0166     CategoryInfo(std::unique_ptr<TChain>&& c) : chain(std::move(c)) {
0167     }
0168     std::unique_ptr<TChain> chain{nullptr};                 ///< The TChain with the data
0169     unsigned entry{0};                                      ///< The next entry to read
0170     std::vector<detail::NamedCollInfo> storedClasses{};     ///< The stored collections in this
0171                                                             ///< category
0172     std::vector<root_utils::CollectionBranches> branches{}; ///< The branches for this category
0173     std::shared_ptr<CollectionIDTable> table{nullptr};      ///< The collection ID table for this category
0174   };
0175 
0176   /// Initialize the passed CategoryInfo by setting up the necessary branches,
0177   /// collection infos and all necessary meta data to be able to read entries
0178   /// with this name
0179   void initCategory(CategoryInfo& catInfo, const std::string& name);
0180 
0181   /// Get the category information for the given name. In case there is no TTree
0182   /// with contents for the given name this will return a CategoryInfo with an
0183   /// uninitialized chain (nullptr) member
0184   CategoryInfo& getCategoryInfo(const std::string& name);
0185 
0186   /// Read the parameters for the entry specified in the passed CategoryInfo
0187   GenericParameters readEntryParameters(CategoryInfo& catInfo, bool reloadBranches, unsigned int localEntry);
0188 
0189   template <typename T>
0190   static void readParams(CategoryInfo& catInfo, podio::GenericParameters& params, bool reloadBranches,
0191                          unsigned int localEntry);
0192 
0193   /// Read the data entry specified in the passed CategoryInfo, and increase the
0194   /// counter afterwards. In case the requested entry is larger than the
0195   /// available number of entries, return a nullptr.
0196   std::unique_ptr<podio::ROOTFrameData> readEntry(ROOTReader::CategoryInfo& catInfo,
0197                                                   const std::vector<std::string>& collsToRead);
0198 
0199   /// Get / read the buffers at index iColl in the passed category information
0200   std::optional<podio::CollectionReadBuffers> getCollectionBuffers(CategoryInfo& catInfo, size_t iColl,
0201                                                                    bool reloadBranches, unsigned int localEntry);
0202 
0203   std::unique_ptr<TChain> m_metaChain{nullptr};                 ///< The metadata tree
0204   std::unordered_map<std::string, CategoryInfo> m_categories{}; ///< All categories
0205   std::vector<std::string> m_availCategories{};                 ///< All available categories from this file
0206 
0207   podio::version::Version m_fileVersion{0, 0, 0};
0208   DatamodelDefinitionHolder m_datamodelHolder{};
0209 };
0210 
0211 } // namespace podio
0212 
0213 #endif // PODIO_ROOTREADER_H