Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-15 09:11:34

0001 // Author: Enrico Guiraud, Danilo Piparo CERN  02/2018
0002 
0003 /*************************************************************************
0004  * Copyright (C) 1995-2018, Rene Brun and Fons Rademakers.               *
0005  * All rights reserved.                                                  *
0006  *                                                                       *
0007  * For the licensing terms see $ROOTSYS/LICENSE.                         *
0008  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
0009  *************************************************************************/
0010 
0011 #ifndef ROOT_RLAZYDSIMPL
0012 #define ROOT_RLAZYDSIMPL
0013 
0014 #include "ROOT/RDataSource.hxx"
0015 #include "ROOT/RResultPtr.hxx"
0016 #include "ROOT/TSeq.hxx"
0017 
0018 #include <algorithm>
0019 #include <map>
0020 #include <memory>
0021 #include <tuple>
0022 #include <string>
0023 #include <typeinfo>
0024 #include <utility> // std::index_sequence
0025 #include <vector>
0026 
0027 namespace ROOT {
0028 
0029 namespace RDF {
0030 ////////////////////////////////////////////////////////////////////////////////////////////////
0031 /// \brief A RDataSource implementation which is built on top of result proxies
0032 ///
0033 /// This component allows to create a data source on a set of columns coming from
0034 /// one or multiple data frames. The processing of the parent data frames starts
0035 /// only when the event loop is triggered in the data frame initialized with a
0036 /// RLazyDS.
0037 ///
0038 /// The implementation takes care of matching compile time information with runtime
0039 /// information, e.g. expanding in a smart way the template parameters packs.
0040 template <typename... ColumnTypes>
0041 class RLazyDS final : public ROOT::RDF::RDataSource {
0042    using PointerHolderPtrs_t = std::vector<ROOT::Internal::TDS::TPointerHolder *>;
0043 
0044    std::tuple<RResultPtr<std::vector<ColumnTypes>>...> fColumns;
0045    const std::vector<std::string> fColNames;
0046    const std::map<std::string, std::string> fColTypesMap;
0047    // The role of the fPointerHoldersModels is to be initialized with the pack
0048    // of arguments in the constrcutor signature at construction time
0049    // Once the number of slots is known, the fPointerHolders are initialized
0050    // according to the models.
0051    const PointerHolderPtrs_t fPointerHoldersModels;
0052    std::vector<PointerHolderPtrs_t> fPointerHolders;
0053    std::vector<std::pair<ULong64_t, ULong64_t>> fEntryRanges{};
0054 
0055    Record_t GetColumnReadersImpl(std::string_view colName, const std::type_info &id) final
0056    {
0057       auto colNameStr = std::string(colName);
0058       // This could be optimised and done statically
0059       const auto idName = ROOT::Internal::RDF::TypeID2TypeName(id);
0060       auto it = fColTypesMap.find(colNameStr);
0061       if (fColTypesMap.end() == it) {
0062          std::string err = "The specified column name, \"" + colNameStr + "\" is not known to the data source.";
0063          throw std::runtime_error(err);
0064       }
0065 
0066       const auto colIdName = it->second;
0067       if (colIdName != idName) {
0068          std::string err = "Column " + colNameStr + " has type " + colIdName +
0069                            " while the id specified is associated to type " + idName;
0070          throw std::runtime_error(err);
0071       }
0072 
0073       const auto colBegin = fColNames.begin();
0074       const auto colEnd = fColNames.end();
0075       const auto namesIt = std::find(colBegin, colEnd, colName);
0076       const auto index = std::distance(colBegin, namesIt);
0077 
0078       Record_t ret(fNSlots);
0079       for (auto slot : ROOT::TSeqU(fNSlots)) {
0080          ret[slot] = fPointerHolders[index][slot]->GetPointerAddr();
0081       }
0082       return ret;
0083    }
0084 
0085    size_t GetEntriesNumber() { return std::get<0>(fColumns)->size(); }
0086    template <std::size_t... S>
0087    void SetEntryHelper(unsigned int slot, ULong64_t entry, std::index_sequence<S...>)
0088    {
0089       std::initializer_list<int> expander{
0090          (*static_cast<ColumnTypes *>(fPointerHolders[S][slot]->GetPointer()) = (*std::get<S>(fColumns))[entry], 0)...};
0091       (void)expander; // avoid unused variable warnings
0092    }
0093 
0094    template <std::size_t... S>
0095    void ColLengthChecker(std::index_sequence<S...>)
0096    {
0097       if (sizeof...(S) < 2)
0098          return;
0099 
0100       const std::vector<size_t> colLengths{std::get<S>(fColumns)->size()...};
0101       const auto expectedLen = colLengths[0];
0102       std::string err;
0103       for (auto i : TSeqI(1, colLengths.size())) {
0104          if (expectedLen != colLengths[i]) {
0105             err += "Column \"" + fColNames[i] + "\" and column \"" + fColNames[0] +
0106                    "\" have different lengths: " + std::to_string(expectedLen) + " and " +
0107                    std::to_string(colLengths[i]);
0108          }
0109       }
0110       if (!err.empty()) {
0111          throw std::runtime_error(err);
0112       }
0113    }
0114 
0115 protected:
0116    std::string AsString() final { return "lazy data source"; };
0117 
0118 public:
0119    RLazyDS(std::pair<std::string, RResultPtr<std::vector<ColumnTypes>>>... colsNameVals)
0120       : fColumns(std::tuple<RResultPtr<std::vector<ColumnTypes>>...>(colsNameVals.second...)),
0121         fColNames({colsNameVals.first...}),
0122         fColTypesMap({{colsNameVals.first, ROOT::Internal::RDF::TypeID2TypeName(typeid(ColumnTypes))}...}),
0123         fPointerHoldersModels({new ROOT::Internal::TDS::TTypedPointerHolder<ColumnTypes>(new ColumnTypes())...})
0124    {
0125    }
0126 
0127    // Rule of five
0128    RLazyDS(const RLazyDS &) = delete;
0129    RLazyDS &operator=(const RLazyDS &) = delete;
0130    RLazyDS(RLazyDS &&) = delete;
0131    RLazyDS &operator=(RLazyDS &&) = delete;
0132    ~RLazyDS() final
0133    {
0134       for (auto &&ptrHolderv : fPointerHolders) {
0135          for (auto &&ptrHolder : ptrHolderv) {
0136             delete ptrHolder;
0137          }
0138       }
0139    }
0140 
0141    const std::vector<std::string> &GetColumnNames() const final { return fColNames; }
0142 
0143    std::vector<std::pair<ULong64_t, ULong64_t>> GetEntryRanges() final
0144    {
0145       auto entryRanges(std::move(fEntryRanges)); // empty fEntryRanges
0146       return entryRanges;
0147    }
0148 
0149    std::string GetTypeName(std::string_view colName) const final
0150    {
0151       const auto key = std::string(colName);
0152       return fColTypesMap.at(key);
0153    }
0154 
0155    bool HasColumn(std::string_view colName) const final
0156    {
0157       const auto key = std::string(colName);
0158       const auto endIt = fColTypesMap.end();
0159       return endIt != fColTypesMap.find(key);
0160    }
0161 
0162    bool SetEntry(unsigned int slot, ULong64_t entry) final
0163    {
0164       SetEntryHelper(slot, entry, std::index_sequence_for<ColumnTypes...>());
0165       return true;
0166    }
0167 
0168    void SetNSlots(unsigned int nSlots) final
0169    {
0170       fNSlots = nSlots;
0171       const auto nCols = fColNames.size();
0172       fPointerHolders.resize(nCols); // now we need to fill it with the slots, all of the same type
0173       auto colIndex = 0U;
0174       for (auto &&ptrHolderv : fPointerHolders) {
0175          for (auto slot : ROOT::TSeqI(fNSlots)) {
0176             auto ptrHolder = fPointerHoldersModels[colIndex]->GetDeepCopy();
0177             ptrHolderv.emplace_back(ptrHolder);
0178             (void)slot;
0179          }
0180          colIndex++;
0181       }
0182       for (auto &&ptrHolder : fPointerHoldersModels)
0183          delete ptrHolder;
0184    }
0185 
0186    void Initialize() final
0187    {
0188       ColLengthChecker(std::index_sequence_for<ColumnTypes...>());
0189       const auto nEntries = GetEntriesNumber();
0190       const auto nEntriesInRange = nEntries / fNSlots; // between integers. Should make smaller?
0191       auto reminder = 1U == fNSlots ? 0 : nEntries % fNSlots;
0192       fEntryRanges.resize(fNSlots);
0193       auto init = 0ULL;
0194       auto end = 0ULL;
0195       for (auto &&range : fEntryRanges) {
0196          end = init + nEntriesInRange;
0197          if (0 != reminder) { // Distribute the reminder among the first chunks
0198             reminder--;
0199             end += 1;
0200          }
0201          range.first = init;
0202          range.second = end;
0203          init = end;
0204       }
0205    }
0206 
0207    std::string GetLabel() final { return "LazyDS"; }
0208 };
0209 
0210 } // ns RDF
0211 
0212 } // ns ROOT
0213 
0214 #endif