diff --git a/tree/ntupleutil/inc/ROOT/RNTupleInspector.hxx b/tree/ntupleutil/inc/ROOT/RNTupleInspector.hxx index 957b1550b9c88..407c58c408bfa 100644 --- a/tree/ntupleutil/inc/ROOT/RNTupleInspector.hxx +++ b/tree/ntupleutil/inc/ROOT/RNTupleInspector.hxx @@ -105,7 +105,9 @@ public: : fColumnDescriptor(colDesc), fCompressedPageSizes(compressedPageSizes), fElementSize(elemSize), - fNElements(nElems){}; + fNElements(nElems) + { + } ~RColumnInspector() = default; const ROOT::RColumnDescriptor &GetDescriptor() const { return fColumnDescriptor; } @@ -136,7 +138,9 @@ public: public: RFieldTreeInspector(const ROOT::RFieldDescriptor &fieldDesc, std::uint64_t onDiskSize, std::uint64_t inMemSize) - : fRootFieldDescriptor(fieldDesc), fCompressedSize(onDiskSize), fUncompressedSize(inMemSize){}; + : fRootFieldDescriptor(fieldDesc), fCompressedSize(onDiskSize), fUncompressedSize(inMemSize) + { + } ~RFieldTreeInspector() = default; const ROOT::RFieldDescriptor &GetDescriptor() const { return fRootFieldDescriptor; } @@ -426,6 +430,10 @@ public: std::string histName = "", std::string histTitle = "", size_t nBins = 64); + std::unique_ptr GetPagesPerClusterDistribution(std::initializer_list colTypes = {}, + std::string_view histName = "", + std::string_view histTitle = "", size_t nBins = 32); + ///////////////////////////////////////////////////////////////////////////// /// \brief Get storage information for a given (sub)field by ID. /// diff --git a/tree/ntupleutil/src/RNTupleInspector.cxx b/tree/ntupleutil/src/RNTupleInspector.cxx index a3287a1d4d2ff..941f2aeb82855 100644 --- a/tree/ntupleutil/src/RNTupleInspector.cxx +++ b/tree/ntupleutil/src/RNTupleInspector.cxx @@ -455,6 +455,66 @@ ROOT::Experimental::RNTupleInspector::GetPageSizeDistribution(std::initializer_l return stackedHist; } +std::unique_ptr ROOT::Experimental::RNTupleInspector::GetPagesPerClusterDistribution( + std::initializer_list colTypes, std::string_view histName, std::string_view histTitle, + size_t nBins) +{ + if (histName.empty()) + histName = "pagesPerClusterHist"; + if (histTitle.empty()) + histTitle = "#pages per cluster"; + + auto stackedHist = std::make_unique(std::string(histName).c_str(), std::string(histTitle).c_str()); + // Each element of the vector contains the sum of all pages of all columns of each type. + std::vector> pagesPerClusterPerColumnType; + + std::vector colTypeVec = colTypes; + if (std::empty(colTypes)) { + colTypeVec = GetColumnTypes(); + } + + for (const auto &clDesc : fDescriptor.GetClusterIterable()) { + auto &pagesPerColumnTypeInThisCluster = pagesPerClusterPerColumnType.emplace_back(); + for (const auto &colRange : clDesc.GetColumnRangeIterable()) { + const auto colId = colRange.GetPhysicalColumnId(); + const auto &colDesc = fDescriptor.GetColumnDescriptor(colId); + const auto nPages = clDesc.GetPageRange(colId).GetPageInfos().size(); + auto &nPagesForThisType = pagesPerColumnTypeInThisCluster[colDesc.GetType()]; + nPagesForThisType += nPages; + } + } + + double histMin = std::numeric_limits::max(); + double histMax = 0; + for (const auto &pagesPerType : pagesPerClusterPerColumnType) { + auto [min, max] = std::minmax_element(pagesPerType.begin(), pagesPerType.end(), + [](const auto &a, const auto &b) { return a.second < b.second; }); + histMin = std::min(histMin, min->second); + histMax = std::max(histMax, max->second); + } + + std::array, static_cast(ENTupleColumnType::kMax)> histsPerType = {}; + for (const auto &pagesPerType : pagesPerClusterPerColumnType) { + for (const auto &[colType, nPages] : pagesPerType) { + auto &hist = histsPerType[static_cast(colType)]; + if (!hist) { + hist = std::make_unique(ROOT::Internal::RColumnElementBase::GetColumnTypeName(colType), + ROOT::Internal::RColumnElementBase::GetColumnTypeName(colType), nBins, + histMin, histMax + ((histMax - histMin) / static_cast(nBins))); + } + hist->Fill(nPages); + } + } + + for (auto &hist : histsPerType) { + if (hist) { + stackedHist->Add(hist.release()); + } + } + + return stackedHist; +} + //------------------------------------------------------------------------------ const ROOT::Experimental::RNTupleInspector::RFieldTreeInspector &