Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RTreeMapBase.cxx
Go to the documentation of this file.
1/// \file RTreeMapBase.cxx
2/// \author Patryk Tymoteusz Pilichowski <patryk.tymoteusz.pilichowski@cern.ch>
3/// \date 2025-08-21
4/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
5/// is welcome!
6
7/*************************************************************************
8 * Copyright (C) 1995-2025, Rene Brun and Fons Rademakers. *
9 * All rights reserved. *
10 * *
11 * For the licensing terms see $ROOTSYS/LICENSE. *
12 * For the list of contributors see $ROOTSYS/README/CREDITS. *
13 *************************************************************************/
14
15#include <ROOT/RTreeMapBase.hxx>
16
17#include <cmath>
18#include <iomanip>
19#include <sstream>
20#include <unordered_map>
21#include <algorithm>
22
23static constexpr float kIndentationOffset = 0.005f;
24static constexpr float kPadTextOffset = 0.004f;
25static constexpr float kTextSizeFactor = 0.009f;
26static constexpr const char *kUnits[] = {"B", "KB", "MB", "GB", "TB", "PB", "EB"};
27
28using namespace ROOT::Experimental;
29
30static uint64_t ComputeFnv(const std::string &str)
31{
32 uint64_t h = 14695981039346656037ULL;
33 for (char c : str)
34 h = (h ^ static_cast<uint8_t>(c)) * 1099511628211ULL;
35 return h;
36}
37
38static RTreeMapBase::RGBColor ComputeColor(const std::string &str)
39{
40 const uint64_t hash = ComputeFnv(str);
41 return RTreeMapBase::RGBColor((hash >> 16) & 0xFF, (hash >> 8) & 0xFF, hash & 0xFF);
42}
43
44static std::string GetFloatStr(const float &n, const uint8_t &precision)
45{
46 std::stringstream stream;
47 stream << std::fixed << std::setprecision(precision) << n;
48 return stream.str();
49}
50
51static std::string GetDataStr(uint64_t bytes)
52{
53 const uint64_t order = std::log10(bytes) / 3.0f;
54 const std::string unit = kUnits[order];
55 const float finalSize = static_cast<float>(bytes) / std::pow(1000, order);
56 return GetFloatStr(finalSize, 2) + unit;
57}
58
59static std::vector<std::pair<std::string, uint64_t>> GetDiskOccupation(const std::vector<RTreeMapBase::Node> &nodes)
60{
61 std::unordered_map<std::string, uint64_t> acc;
62 for (const auto &node : nodes) {
63 if (node.fNChildren > 0)
64 continue;
65 acc[node.fType] += node.fSize;
66 }
67
68 std::vector<std::pair<std::string, uint64_t>> vec;
69 vec.reserve(acc.size());
70 for (auto &p : acc)
71 vec.emplace_back(std::move(p.first), p.second);
72
73 std::sort(vec.begin(), vec.end(), [](const auto &a, const auto &b) { return a.second > b.second; });
74 return vec;
75}
76
77/* algorithm: https://vanwijk.win.tue.nl/stm.pdf */
78static float ComputeWorstRatio(const std::vector<RTreeMapBase::Node> &row, float width, float height,
79 uint64_t totalSize, bool horizontalRows)
80{
81 if (row.empty())
82 return 0.0f;
83 uint64_t sumRow = 0;
84 for (const auto &child : row)
85 sumRow += child.fSize;
86 if (sumRow == 0)
87 return 0.0f;
88 float worstRatio = 0.0f;
89 for (const auto &child : row) {
90 float ratio = horizontalRows ? static_cast<float>(child.fSize * width * totalSize) / (sumRow * sumRow * height)
91 : static_cast<float>(child.fSize * height * totalSize) / (sumRow * sumRow * width);
92 float aspectRatio = std::max(ratio, 1.0f / ratio);
95 }
96 return worstRatio;
97}
98
99static std::vector<std::pair<RTreeMapBase::Node, RTreeMapBase::Rect>>
100SquarifyChildren(const std::vector<RTreeMapBase::Node> &children, RTreeMapBase::Rect rect, bool horizontalRows,
101 uint64_t totalSize)
102{
103 float width = rect.fTopRight.x - rect.fBottomLeft.x;
104 float height = rect.fTopRight.y - rect.fBottomLeft.y;
105 std::vector<RTreeMapBase::Node> remainingChildren = children;
107 [](const RTreeMapBase::Node &a, const RTreeMapBase::Node &b) { return a.fSize > b.fSize; });
108 std::vector<std::pair<RTreeMapBase::Node, RTreeMapBase::Rect>> result;
110 while (!remainingChildren.empty()) {
111 std::vector<RTreeMapBase::Node> row;
112 float currentWorstRatio = std::numeric_limits<float>::max();
113 float remainingWidth = rect.fTopRight.x - remainingBegin.x;
114 float remainingHeight = rect.fTopRight.y - remainingBegin.y;
115 if (remainingWidth <= 0 || remainingHeight <= 0)
116 break;
117 while (!remainingChildren.empty()) {
118 row.push_back(remainingChildren.front());
122 remainingChildren.insert(remainingChildren.begin(), row.back());
123 row.pop_back();
124 break;
125 }
127 }
128 uint64_t sumRow = 0;
129 for (const auto &child : row)
130 sumRow += child.fSize;
131 if (sumRow == 0)
132 continue;
133 float dimension = horizontalRows ? (static_cast<float>(sumRow) / totalSize * height)
134 : (static_cast<float>(sumRow) / totalSize * width);
135 float position = 0.0f;
136 for (const auto &child : row) {
137 float childDimension = static_cast<float>(child.fSize) / sumRow * (horizontalRows ? width : height);
143 ? RTreeMapBase::Vec2{remainingBegin.x + position + childDimension, remainingBegin.y + dimension}
144 : RTreeMapBase::Vec2{remainingBegin.x + dimension, remainingBegin.y + position + childDimension};
145 result.push_back({child, {childBegin, childEnd}});
146 position += childDimension;
147 }
148 if (horizontalRows)
149 remainingBegin.y += dimension;
150 else
151 remainingBegin.x += dimension;
152 }
153 return result;
154}
156{
158
159 if (fNodes.empty())
160 return;
161 const uint64_t totalSize = fNodes[0].fSize;
162 if (totalSize == 0)
163 return;
164
165 uint8_t counter = 0;
166 for (const auto &entry : diskOccupation) {
167 const auto &typeName = entry.first;
168 const uint64_t entrySize = entry.second;
169 if (entrySize == 0)
170 continue;
171
172 const auto offset = 0.835f, factor = 0.05f;
173 const auto posY = offset - counter * factor;
174
175 AddBox(Rect(Vec2(offset, posY), Vec2(offset + factor, posY - factor)), ComputeColor(typeName));
176
177 const float percent = (entrySize / static_cast<float>(totalSize)) * 100.0f;
178 const auto content = "(" + GetDataStr(entrySize) + " / " + GetDataStr(totalSize) + ")";
179
180 float currOffset = 0.0125f;
181 for (const auto &currContent : {typeName, content, GetFloatStr(percent, 2) + "%"}) {
183 currOffset += 0.01f;
184 }
185
186 counter++;
187 }
188}
189
191{
193 RTreeMapBase::Vec2(rect.fTopRight.x, rect.fTopRight.y));
194 bool isLeaf = (element.fNChildren == 0);
196 AddBox(drawRect, boxColor, 0.15f);
197
198 const std::string label = element.fName + " (" + GetDataStr(element.fSize) + ")";
199 const Vec2 &labelPos = isLeaf ? Vec2((drawRect.fBottomLeft.x + drawRect.fTopRight.x) / 2.0f,
200 (drawRect.fBottomLeft.y + drawRect.fTopRight.y) / 2.0f)
201 : Vec2(drawRect.fBottomLeft.x + kPadTextOffset, drawRect.fTopRight.y - kPadTextOffset);
202
203 float rectWidth = rect.fTopRight.x - rect.fBottomLeft.x;
204 float rectHeight = rect.fTopRight.y - rect.fBottomLeft.y;
205 float textSize = std::min(std::min(rectWidth, rectHeight) * 0.1f, kTextSizeFactor);
206 AddText(labelPos, label, textSize, RTreeMapBase::RGBColor(255, 255, 255), isLeaf);
207
208 if (!isLeaf) {
211 RTreeMapBase::Rect(RTreeMapBase::Vec2(rect.fBottomLeft.x + indent, rect.fBottomLeft.y + indent),
212 RTreeMapBase::Vec2(rect.fTopRight.x - indent, rect.fTopRight.y - indent * 4.0f));
213 std::vector<RTreeMapBase::Node> children;
214 for (std::uint64_t i = 0; i < element.fNChildren; ++i)
215 children.push_back(fNodes[element.fChildrenIdx + i]);
216 uint64_t totalSize = 0;
217 for (const auto &child : children)
218 totalSize += child.fSize;
219 if (totalSize == 0)
220 return;
221 float width = innerRect.fTopRight.x - innerRect.fBottomLeft.x;
222 float height = innerRect.fTopRight.y - innerRect.fBottomLeft.y;
223 bool horizontalRows = width > height;
225 for (const auto &[child, childRect] : childRects)
227 }
228}
#define b(i)
Definition RSha256.hxx:100
#define c(i)
Definition RSha256.hxx:101
#define a(i)
Definition RSha256.hxx:99
#define h(i)
Definition RSha256.hxx:106
static std::vector< std::pair< RTreeMapBase::Node, RTreeMapBase::Rect > > SquarifyChildren(const std::vector< RTreeMapBase::Node > &children, RTreeMapBase::Rect rect, bool horizontalRows, uint64_t totalSize)
static float ComputeWorstRatio(const std::vector< RTreeMapBase::Node > &row, float width, float height, uint64_t totalSize, bool horizontalRows)
static constexpr float kTextSizeFactor
static std::string GetDataStr(uint64_t bytes)
static constexpr const char * kUnits[]
static constexpr float kIndentationOffset
static std::string GetFloatStr(const float &n, const uint8_t &precision)
static constexpr float kPadTextOffset
static RTreeMapBase::RGBColor ComputeColor(const std::string &str)
static std::vector< std::pair< std::string, uint64_t > > GetDiskOccupation(const std::vector< RTreeMapBase::Node > &nodes)
static uint64_t ComputeFnv(const std::string &str)
static void indent(ostringstream &buf, int indent_level)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t rect
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t child
Option_t Option_t width
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t bytes
Option_t Option_t TPoint TPoint percent
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t height
virtual void AddText(const Vec2 &pos, const std::string &content, float size, const RGBColor &color=RGBColor(0, 0, 0), bool alignCenter=false) const =0
Logic for drawing a text.
void DrawLegend() const
Logic for drawing the legend of leaf types.
virtual void AddBox(const Rect &rect, const RGBColor &color, float borderWidth=0.15f) const =0
Logic for drawing a box.
void DrawTreeMap(const Node &elem, Rect rect, int depth) const
Logic for drawing the entirety of the treemap.
const_iterator begin() const
const_iterator end() const
const Int_t n
Definition legend1.C:16
Namespace for ROOT features in testing.
Definition TROOT.h:100