Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-11-05 09:49:41

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